emf-converter 4.8.0 → 4.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -16403,8 +16403,8 @@ function midtoneGamma(t) {
16403
16403
  low = high;
16404
16404
  high = (high + 100) / 2;
16405
16405
  }
16406
- gamma = Math.abs(t) === 100 ? 10 : Math.min(10, gamma + (Math.abs(t) - low) / (high - low));
16407
- return Math.fround(t < 0 ? gamma : 1 / gamma);
16406
+ gamma = Math.abs(t) === 100 ? 10 : Math.min(10, truncF32(gamma + truncF32(truncF32(Math.abs(t) - low) / truncF32(high - low))));
16407
+ return t < 0 ? truncF32(gamma) : truncF32(1 / truncF32(gamma));
16408
16408
  }
16409
16409
  function brightnessContrastLut(brightness, contrast) {
16410
16410
  const gain = contrast >= 100 ? 1e6 : contrast >= 0 ? 100 / (100 - contrast) : (100 + contrast) / 100;
@@ -16421,6 +16421,23 @@ function curveAdjustmentLut(adjustment, intensity) {
16421
16421
  return nativeCurveLookup(adjustment, clamp(Math.trunc(intensity), min, max)).slice();
16422
16422
  }
16423
16423
  function levelsLut(highlight, midtone, shadow) {
16424
+ if (highlight !== shadow) {
16425
+ const forward = highlight > shadow;
16426
+ const lo = truncF32((forward ? shadow : highlight) * 255 / 100);
16427
+ const hi = truncF32((forward ? highlight : shadow) * 255 / 100);
16428
+ const scale = truncF32(1 / truncF32(hi - lo));
16429
+ const exponent2 = midtoneGamma(midtone);
16430
+ const lut = new Uint8Array(256);
16431
+ for (let v = 0; v < 256; v++) {
16432
+ let level = clamp(truncF32(truncF32(v - lo) * scale), 0, 1);
16433
+ if (midtone !== 0) {
16434
+ level = truncF32(level ** exponent2);
16435
+ }
16436
+ const out = forward ? truncF32(255 * level) : truncF32(255 - truncF32(255 * level));
16437
+ lut[v] = clamp(Math.floor(out + 0.5), 0, 255);
16438
+ }
16439
+ return lut;
16440
+ }
16424
16441
  const base = shadow * 255 / 100 - (highlight === shadow && shadow < 50 ? 1 : 0);
16425
16442
  const span = highlight === shadow ? 1 : (highlight - shadow) * 255 / 100;
16426
16443
  const exponent = midtoneGamma(midtone);
@@ -16453,14 +16470,6 @@ function applyColorMatrix(src, m) {
16453
16470
  }
16454
16471
  return out;
16455
16472
  }
16456
- function hslToRgb(h, s, l) {
16457
- const c = (1 - Math.abs(2 * l - 1)) * s;
16458
- const hp = (h % 360 + 360) % 360 / 60;
16459
- const x = c * (1 - Math.abs(hp % 2 - 1));
16460
- const m = l - c / 2;
16461
- const [r, g, b] = hp < 1 ? [c, x, 0] : hp < 2 ? [x, c, 0] : hp < 3 ? [0, c, x] : hp < 4 ? [0, x, c] : hp < 5 ? [x, 0, c] : [c, 0, x];
16462
- return [r + m, g + m, b + m];
16463
- }
16464
16473
  var HUE_SEXTANT = 43;
16465
16474
  var HUE_CIRCLE = 255;
16466
16475
  function gdipHue(r, g, b) {
@@ -16483,29 +16492,30 @@ function gdipHue(r, g, b) {
16483
16492
  function applyHueSaturationLightness(src, hue, saturation, lightness) {
16484
16493
  const out = new Uint8ClampedArray(src);
16485
16494
  const shift = Math.round(hue * HUE_CIRCLE / 360);
16486
- const sMul = 1 + saturation / 100;
16495
+ const satScale = 65536 + Math.floor(saturation * 65536 / 100);
16496
+ const lightOffset = Math.round(255 * Math.floor(lightness * 65536 / 100) / 65536);
16487
16497
  for (let i = 0; i < src.length; i += 4) {
16488
16498
  const r = src[i];
16489
16499
  const g = src[i + 1];
16490
16500
  const b = src[i + 2];
16491
16501
  const max = Math.max(r, g, b);
16492
16502
  const min = Math.min(r, g, b);
16493
- const l = clamp(Math.round(((max + min >> 1) * 100 + 255 * lightness) / 100), 0, 255);
16503
+ const l = clamp((max + min >> 1) + lightOffset, 0, 255);
16494
16504
  if (max === min) {
16495
16505
  out[i] = out[i + 1] = out[i + 2] = l;
16496
16506
  continue;
16497
16507
  }
16498
16508
  const sum = max + min;
16499
- const s = Math.fround(clamp((max - min) / (sum <= 255 ? sum : 510 - sum) * sMul, 0, 1));
16500
- const hi = l <= 127 ? l * (1 + s) : l + s * (255 - l);
16501
- const m1 = l <= 127 ? 2 * l - Math.trunc(hi) : Math.round(2 * l - hi);
16502
- const m2 = 2 * l - m1;
16509
+ const sat2 = clamp(Math.round(Math.floor((max - min) * 255 / (sum <= 255 ? sum : 510 - sum)) * satScale / 65536), 0, 255);
16510
+ const hi = l <= 127 ? Math.floor(l * (255 + sat2) / 255) : l + sat2 - Math.floor(l * sat2 / 255);
16511
+ const m1 = 2 * l - hi;
16512
+ const m2 = hi;
16503
16513
  const index = ((gdipHue(r, g, b) + shift) % HUE_CIRCLE + HUE_CIRCLE) % HUE_CIRCLE;
16504
16514
  const q = index + Math.floor((index + 41) / 85);
16505
16515
  const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16506
- const f = (q - sextant * HUE_SEXTANT) / HUE_SEXTANT;
16507
- const up = Math.trunc(m1 + (m2 - m1) * f);
16508
- const down = Math.trunc(m1 + (m2 - m1) * (1 - f));
16516
+ const position = q - sextant * HUE_SEXTANT;
16517
+ const up = m1 + Math.floor((m2 - m1) * position / HUE_SEXTANT);
16518
+ const down = m1 + Math.floor((m2 - m1) * (HUE_SEXTANT - position) / HUE_SEXTANT);
16509
16519
  const [nr, ng, nb] = [
16510
16520
  [m2, up, m1],
16511
16521
  [down, m2, m1],
@@ -16520,28 +16530,40 @@ function applyHueSaturationLightness(src, hue, saturation, lightness) {
16520
16530
  }
16521
16531
  return out;
16522
16532
  }
16523
- var LUMA_709 = [0.2126, 0.7152, 0.0722];
16524
- var TINT_CHROMA_SCALE = 0.985;
16525
16533
  function applyTint(src, hue, amount) {
16526
16534
  const index = (Math.round(hue * 255 / 360) + 256) % 256;
16527
16535
  const q = (index + Math.floor((index + 41) / 85)) % 258;
16528
- const tint = hslToRgb(q * 60 / 43, 1, 0.5);
16529
- const ty = tint[0] * LUMA_709[0] + tint[1] * LUMA_709[1] + tint[2] * LUMA_709[2];
16530
- const chroma = tint.map((c) => (c - ty) * TINT_CHROMA_SCALE);
16531
- const a = amount / 100;
16536
+ const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16537
+ const position = q - sextant * HUE_SEXTANT;
16538
+ const up = Math.floor(TINT_FULL * position / HUE_SEXTANT);
16539
+ const down = Math.floor(TINT_FULL * (HUE_SEXTANT - position) / HUE_SEXTANT);
16540
+ const [tr, tg, tb] = [
16541
+ [TINT_FULL, up, 0],
16542
+ [down, TINT_FULL, 0],
16543
+ [0, TINT_FULL, up],
16544
+ [0, down, TINT_FULL],
16545
+ [up, 0, TINT_FULL],
16546
+ [TINT_FULL, 0, down]
16547
+ ][sextant];
16548
+ const weight = Math.sign(amount) * Math.floor((255 * Math.abs(amount) + 49) / 100);
16549
+ const original = 255 - weight;
16532
16550
  const out = new Uint8ClampedArray(src);
16533
16551
  for (let i = 0; i < src.length; i += 4) {
16534
16552
  const r = src[i];
16535
16553
  const g = src[i + 1];
16536
16554
  const b = src[i + 2];
16537
- const y = r * LUMA_709[0] + g * LUMA_709[1] + b * LUMA_709[2];
16538
- const v = Math.max(r, g, b);
16539
- out[i] = Math.round((1 - a) * r + a * (y + v * chroma[0]));
16540
- out[i + 1] = Math.round((1 - a) * g + a * (y + v * chroma[1]));
16541
- out[i + 2] = Math.round((1 - a) * b + a * (y + v * chroma[2]));
16555
+ const u = weight * Math.max(r, g, b) >> 8;
16556
+ const x0 = original * r + tr * u;
16557
+ const x1 = original * g + tg * u;
16558
+ const x2 = original * b + tb * u;
16559
+ const base = 54 * r + 183 * g + 19 * b - (54 * (x0 >> 8) + 183 * (x1 >> 8) + 19 * (x2 >> 8));
16560
+ out[i] = base + x0 >> 8;
16561
+ out[i + 1] = base + x1 >> 8;
16562
+ out[i + 2] = base + x2 >> 8;
16542
16563
  }
16543
16564
  return out;
16544
16565
  }
16566
+ var TINT_FULL = 254;
16545
16567
  function applyRedEyeCorrection(src, width, height, areas) {
16546
16568
  const out = new Uint8ClampedArray(src);
16547
16569
  for (const a of areas) {
@@ -20541,8 +20563,7 @@ function resampleImage(rgba, width, height, spec, surface) {
20541
20563
  const axisAligned = m[1] === 0 && m[2] === 0;
20542
20564
  if (hq && axisAligned) {
20543
20565
  const ox = m[0] * spec.srcX + m[4];
20544
- const oy = m[3] * spec.srcY + m[5];
20545
- m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5] + mirroredOrigin(oy) - oy];
20566
+ m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5]];
20546
20567
  }
20547
20568
  const inv2 = invert2(m);
20548
20569
  if (!inv2) {
@@ -23355,6 +23376,21 @@ var nestedReplayer = null;
23355
23376
  function registerNestedMetafileReplayer(fn) {
23356
23377
  nestedReplayer = fn;
23357
23378
  }
23379
+ function inclusiveNestedMapping(toDevice, srcX, srcY, srcW, srcH) {
23380
+ const [a, b, c, d, e, f] = toDevice;
23381
+ const lengthU = Math.hypot(a, b) * srcW;
23382
+ const lengthV = Math.hypot(c, d) * srcH;
23383
+ if (!(srcW > 1 && srcH > 1 && lengthU > 1 && lengthV > 1)) {
23384
+ return toDevice;
23385
+ }
23386
+ const ku = (lengthU - 1) / lengthU * (srcW / (srcW - 1));
23387
+ const kv = (lengthV - 1) / lengthV * (srcH / (srcH - 1));
23388
+ const na = a * ku;
23389
+ const nb = b * ku;
23390
+ const nc = c * kv;
23391
+ const nd = d * kv;
23392
+ return [na, nb, nc, nd, e + (a - na) * srcX + (c - nc) * srcY, f + (b - nb) * srcX + (d - nd) * srcY];
23393
+ }
23358
23394
  function drawNestedMetafile(rCtx, img, cached, source) {
23359
23395
  const depth = rCtx.nestingDepth ?? 0;
23360
23396
  if (!nestedReplayer || !source || !img.data || source.unit !== UNIT_PIXEL || depth >= MAX_NESTED_METAFILE_DEPTH) {
@@ -23368,9 +23404,12 @@ function drawNestedMetafile(rCtx, img, cached, source) {
23368
23404
  if (!size) {
23369
23405
  return false;
23370
23406
  }
23371
- const toCanvas = mulMatrix(
23372
- [1, 0, 0, 1, -0.5, -0.5],
23373
- mulMatrix(mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)), [1, 0, 0, 1, 0.5, 0.5])
23407
+ const toCanvas = inclusiveNestedMapping(
23408
+ mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)),
23409
+ srcX,
23410
+ srcY,
23411
+ srcW,
23412
+ srcH
23374
23413
  );
23375
23414
  const bytes = img.data.slice(0);
23376
23415
  const caches = cached && cached.kind === "metafile" ? cached.caches : void 0;
package/dist/browser.mjs CHANGED
@@ -16401,8 +16401,8 @@ function midtoneGamma(t) {
16401
16401
  low = high;
16402
16402
  high = (high + 100) / 2;
16403
16403
  }
16404
- gamma = Math.abs(t) === 100 ? 10 : Math.min(10, gamma + (Math.abs(t) - low) / (high - low));
16405
- return Math.fround(t < 0 ? gamma : 1 / gamma);
16404
+ gamma = Math.abs(t) === 100 ? 10 : Math.min(10, truncF32(gamma + truncF32(truncF32(Math.abs(t) - low) / truncF32(high - low))));
16405
+ return t < 0 ? truncF32(gamma) : truncF32(1 / truncF32(gamma));
16406
16406
  }
16407
16407
  function brightnessContrastLut(brightness, contrast) {
16408
16408
  const gain = contrast >= 100 ? 1e6 : contrast >= 0 ? 100 / (100 - contrast) : (100 + contrast) / 100;
@@ -16419,6 +16419,23 @@ function curveAdjustmentLut(adjustment, intensity) {
16419
16419
  return nativeCurveLookup(adjustment, clamp(Math.trunc(intensity), min, max)).slice();
16420
16420
  }
16421
16421
  function levelsLut(highlight, midtone, shadow) {
16422
+ if (highlight !== shadow) {
16423
+ const forward = highlight > shadow;
16424
+ const lo = truncF32((forward ? shadow : highlight) * 255 / 100);
16425
+ const hi = truncF32((forward ? highlight : shadow) * 255 / 100);
16426
+ const scale = truncF32(1 / truncF32(hi - lo));
16427
+ const exponent2 = midtoneGamma(midtone);
16428
+ const lut = new Uint8Array(256);
16429
+ for (let v = 0; v < 256; v++) {
16430
+ let level = clamp(truncF32(truncF32(v - lo) * scale), 0, 1);
16431
+ if (midtone !== 0) {
16432
+ level = truncF32(level ** exponent2);
16433
+ }
16434
+ const out = forward ? truncF32(255 * level) : truncF32(255 - truncF32(255 * level));
16435
+ lut[v] = clamp(Math.floor(out + 0.5), 0, 255);
16436
+ }
16437
+ return lut;
16438
+ }
16422
16439
  const base = shadow * 255 / 100 - (highlight === shadow && shadow < 50 ? 1 : 0);
16423
16440
  const span = highlight === shadow ? 1 : (highlight - shadow) * 255 / 100;
16424
16441
  const exponent = midtoneGamma(midtone);
@@ -16451,14 +16468,6 @@ function applyColorMatrix(src, m) {
16451
16468
  }
16452
16469
  return out;
16453
16470
  }
16454
- function hslToRgb(h, s, l) {
16455
- const c = (1 - Math.abs(2 * l - 1)) * s;
16456
- const hp = (h % 360 + 360) % 360 / 60;
16457
- const x = c * (1 - Math.abs(hp % 2 - 1));
16458
- const m = l - c / 2;
16459
- const [r, g, b] = hp < 1 ? [c, x, 0] : hp < 2 ? [x, c, 0] : hp < 3 ? [0, c, x] : hp < 4 ? [0, x, c] : hp < 5 ? [x, 0, c] : [c, 0, x];
16460
- return [r + m, g + m, b + m];
16461
- }
16462
16471
  var HUE_SEXTANT = 43;
16463
16472
  var HUE_CIRCLE = 255;
16464
16473
  function gdipHue(r, g, b) {
@@ -16481,29 +16490,30 @@ function gdipHue(r, g, b) {
16481
16490
  function applyHueSaturationLightness(src, hue, saturation, lightness) {
16482
16491
  const out = new Uint8ClampedArray(src);
16483
16492
  const shift = Math.round(hue * HUE_CIRCLE / 360);
16484
- const sMul = 1 + saturation / 100;
16493
+ const satScale = 65536 + Math.floor(saturation * 65536 / 100);
16494
+ const lightOffset = Math.round(255 * Math.floor(lightness * 65536 / 100) / 65536);
16485
16495
  for (let i = 0; i < src.length; i += 4) {
16486
16496
  const r = src[i];
16487
16497
  const g = src[i + 1];
16488
16498
  const b = src[i + 2];
16489
16499
  const max = Math.max(r, g, b);
16490
16500
  const min = Math.min(r, g, b);
16491
- const l = clamp(Math.round(((max + min >> 1) * 100 + 255 * lightness) / 100), 0, 255);
16501
+ const l = clamp((max + min >> 1) + lightOffset, 0, 255);
16492
16502
  if (max === min) {
16493
16503
  out[i] = out[i + 1] = out[i + 2] = l;
16494
16504
  continue;
16495
16505
  }
16496
16506
  const sum = max + min;
16497
- const s = Math.fround(clamp((max - min) / (sum <= 255 ? sum : 510 - sum) * sMul, 0, 1));
16498
- const hi = l <= 127 ? l * (1 + s) : l + s * (255 - l);
16499
- const m1 = l <= 127 ? 2 * l - Math.trunc(hi) : Math.round(2 * l - hi);
16500
- const m2 = 2 * l - m1;
16507
+ const sat2 = clamp(Math.round(Math.floor((max - min) * 255 / (sum <= 255 ? sum : 510 - sum)) * satScale / 65536), 0, 255);
16508
+ const hi = l <= 127 ? Math.floor(l * (255 + sat2) / 255) : l + sat2 - Math.floor(l * sat2 / 255);
16509
+ const m1 = 2 * l - hi;
16510
+ const m2 = hi;
16501
16511
  const index = ((gdipHue(r, g, b) + shift) % HUE_CIRCLE + HUE_CIRCLE) % HUE_CIRCLE;
16502
16512
  const q = index + Math.floor((index + 41) / 85);
16503
16513
  const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16504
- const f = (q - sextant * HUE_SEXTANT) / HUE_SEXTANT;
16505
- const up = Math.trunc(m1 + (m2 - m1) * f);
16506
- const down = Math.trunc(m1 + (m2 - m1) * (1 - f));
16514
+ const position = q - sextant * HUE_SEXTANT;
16515
+ const up = m1 + Math.floor((m2 - m1) * position / HUE_SEXTANT);
16516
+ const down = m1 + Math.floor((m2 - m1) * (HUE_SEXTANT - position) / HUE_SEXTANT);
16507
16517
  const [nr, ng, nb] = [
16508
16518
  [m2, up, m1],
16509
16519
  [down, m2, m1],
@@ -16518,28 +16528,40 @@ function applyHueSaturationLightness(src, hue, saturation, lightness) {
16518
16528
  }
16519
16529
  return out;
16520
16530
  }
16521
- var LUMA_709 = [0.2126, 0.7152, 0.0722];
16522
- var TINT_CHROMA_SCALE = 0.985;
16523
16531
  function applyTint(src, hue, amount) {
16524
16532
  const index = (Math.round(hue * 255 / 360) + 256) % 256;
16525
16533
  const q = (index + Math.floor((index + 41) / 85)) % 258;
16526
- const tint = hslToRgb(q * 60 / 43, 1, 0.5);
16527
- const ty = tint[0] * LUMA_709[0] + tint[1] * LUMA_709[1] + tint[2] * LUMA_709[2];
16528
- const chroma = tint.map((c) => (c - ty) * TINT_CHROMA_SCALE);
16529
- const a = amount / 100;
16534
+ const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16535
+ const position = q - sextant * HUE_SEXTANT;
16536
+ const up = Math.floor(TINT_FULL * position / HUE_SEXTANT);
16537
+ const down = Math.floor(TINT_FULL * (HUE_SEXTANT - position) / HUE_SEXTANT);
16538
+ const [tr, tg, tb] = [
16539
+ [TINT_FULL, up, 0],
16540
+ [down, TINT_FULL, 0],
16541
+ [0, TINT_FULL, up],
16542
+ [0, down, TINT_FULL],
16543
+ [up, 0, TINT_FULL],
16544
+ [TINT_FULL, 0, down]
16545
+ ][sextant];
16546
+ const weight = Math.sign(amount) * Math.floor((255 * Math.abs(amount) + 49) / 100);
16547
+ const original = 255 - weight;
16530
16548
  const out = new Uint8ClampedArray(src);
16531
16549
  for (let i = 0; i < src.length; i += 4) {
16532
16550
  const r = src[i];
16533
16551
  const g = src[i + 1];
16534
16552
  const b = src[i + 2];
16535
- const y = r * LUMA_709[0] + g * LUMA_709[1] + b * LUMA_709[2];
16536
- const v = Math.max(r, g, b);
16537
- out[i] = Math.round((1 - a) * r + a * (y + v * chroma[0]));
16538
- out[i + 1] = Math.round((1 - a) * g + a * (y + v * chroma[1]));
16539
- out[i + 2] = Math.round((1 - a) * b + a * (y + v * chroma[2]));
16553
+ const u = weight * Math.max(r, g, b) >> 8;
16554
+ const x0 = original * r + tr * u;
16555
+ const x1 = original * g + tg * u;
16556
+ const x2 = original * b + tb * u;
16557
+ const base = 54 * r + 183 * g + 19 * b - (54 * (x0 >> 8) + 183 * (x1 >> 8) + 19 * (x2 >> 8));
16558
+ out[i] = base + x0 >> 8;
16559
+ out[i + 1] = base + x1 >> 8;
16560
+ out[i + 2] = base + x2 >> 8;
16540
16561
  }
16541
16562
  return out;
16542
16563
  }
16564
+ var TINT_FULL = 254;
16543
16565
  function applyRedEyeCorrection(src, width, height, areas) {
16544
16566
  const out = new Uint8ClampedArray(src);
16545
16567
  for (const a of areas) {
@@ -20539,8 +20561,7 @@ function resampleImage(rgba, width, height, spec, surface) {
20539
20561
  const axisAligned = m[1] === 0 && m[2] === 0;
20540
20562
  if (hq && axisAligned) {
20541
20563
  const ox = m[0] * spec.srcX + m[4];
20542
- const oy = m[3] * spec.srcY + m[5];
20543
- m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5] + mirroredOrigin(oy) - oy];
20564
+ m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5]];
20544
20565
  }
20545
20566
  const inv2 = invert2(m);
20546
20567
  if (!inv2) {
@@ -23353,6 +23374,21 @@ var nestedReplayer = null;
23353
23374
  function registerNestedMetafileReplayer(fn) {
23354
23375
  nestedReplayer = fn;
23355
23376
  }
23377
+ function inclusiveNestedMapping(toDevice, srcX, srcY, srcW, srcH) {
23378
+ const [a, b, c, d, e, f] = toDevice;
23379
+ const lengthU = Math.hypot(a, b) * srcW;
23380
+ const lengthV = Math.hypot(c, d) * srcH;
23381
+ if (!(srcW > 1 && srcH > 1 && lengthU > 1 && lengthV > 1)) {
23382
+ return toDevice;
23383
+ }
23384
+ const ku = (lengthU - 1) / lengthU * (srcW / (srcW - 1));
23385
+ const kv = (lengthV - 1) / lengthV * (srcH / (srcH - 1));
23386
+ const na = a * ku;
23387
+ const nb = b * ku;
23388
+ const nc = c * kv;
23389
+ const nd = d * kv;
23390
+ return [na, nb, nc, nd, e + (a - na) * srcX + (c - nc) * srcY, f + (b - nb) * srcX + (d - nd) * srcY];
23391
+ }
23356
23392
  function drawNestedMetafile(rCtx, img, cached, source) {
23357
23393
  const depth = rCtx.nestingDepth ?? 0;
23358
23394
  if (!nestedReplayer || !source || !img.data || source.unit !== UNIT_PIXEL || depth >= MAX_NESTED_METAFILE_DEPTH) {
@@ -23366,9 +23402,12 @@ function drawNestedMetafile(rCtx, img, cached, source) {
23366
23402
  if (!size) {
23367
23403
  return false;
23368
23404
  }
23369
- const toCanvas = mulMatrix(
23370
- [1, 0, 0, 1, -0.5, -0.5],
23371
- mulMatrix(mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)), [1, 0, 0, 1, 0.5, 0.5])
23405
+ const toCanvas = inclusiveNestedMapping(
23406
+ mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)),
23407
+ srcX,
23408
+ srcY,
23409
+ srcW,
23410
+ srcH
23372
23411
  );
23373
23412
  const bytes = img.data.slice(0);
23374
23413
  const caches = cached && cached.kind === "metafile" ? cached.caches : void 0;
package/dist/index.js CHANGED
@@ -16404,8 +16404,8 @@ function midtoneGamma(t) {
16404
16404
  low = high;
16405
16405
  high = (high + 100) / 2;
16406
16406
  }
16407
- gamma = Math.abs(t) === 100 ? 10 : Math.min(10, gamma + (Math.abs(t) - low) / (high - low));
16408
- return Math.fround(t < 0 ? gamma : 1 / gamma);
16407
+ gamma = Math.abs(t) === 100 ? 10 : Math.min(10, truncF32(gamma + truncF32(truncF32(Math.abs(t) - low) / truncF32(high - low))));
16408
+ return t < 0 ? truncF32(gamma) : truncF32(1 / truncF32(gamma));
16409
16409
  }
16410
16410
  function brightnessContrastLut(brightness, contrast) {
16411
16411
  const gain = contrast >= 100 ? 1e6 : contrast >= 0 ? 100 / (100 - contrast) : (100 + contrast) / 100;
@@ -16422,6 +16422,23 @@ function curveAdjustmentLut(adjustment, intensity) {
16422
16422
  return nativeCurveLookup(adjustment, clamp(Math.trunc(intensity), min, max)).slice();
16423
16423
  }
16424
16424
  function levelsLut(highlight, midtone, shadow) {
16425
+ if (highlight !== shadow) {
16426
+ const forward = highlight > shadow;
16427
+ const lo = truncF32((forward ? shadow : highlight) * 255 / 100);
16428
+ const hi = truncF32((forward ? highlight : shadow) * 255 / 100);
16429
+ const scale = truncF32(1 / truncF32(hi - lo));
16430
+ const exponent2 = midtoneGamma(midtone);
16431
+ const lut = new Uint8Array(256);
16432
+ for (let v = 0; v < 256; v++) {
16433
+ let level = clamp(truncF32(truncF32(v - lo) * scale), 0, 1);
16434
+ if (midtone !== 0) {
16435
+ level = truncF32(level ** exponent2);
16436
+ }
16437
+ const out = forward ? truncF32(255 * level) : truncF32(255 - truncF32(255 * level));
16438
+ lut[v] = clamp(Math.floor(out + 0.5), 0, 255);
16439
+ }
16440
+ return lut;
16441
+ }
16425
16442
  const base = shadow * 255 / 100 - (highlight === shadow && shadow < 50 ? 1 : 0);
16426
16443
  const span = highlight === shadow ? 1 : (highlight - shadow) * 255 / 100;
16427
16444
  const exponent = midtoneGamma(midtone);
@@ -16454,14 +16471,6 @@ function applyColorMatrix(src, m) {
16454
16471
  }
16455
16472
  return out;
16456
16473
  }
16457
- function hslToRgb(h, s, l) {
16458
- const c = (1 - Math.abs(2 * l - 1)) * s;
16459
- const hp = (h % 360 + 360) % 360 / 60;
16460
- const x = c * (1 - Math.abs(hp % 2 - 1));
16461
- const m = l - c / 2;
16462
- const [r, g, b] = hp < 1 ? [c, x, 0] : hp < 2 ? [x, c, 0] : hp < 3 ? [0, c, x] : hp < 4 ? [0, x, c] : hp < 5 ? [x, 0, c] : [c, 0, x];
16463
- return [r + m, g + m, b + m];
16464
- }
16465
16474
  var HUE_SEXTANT = 43;
16466
16475
  var HUE_CIRCLE = 255;
16467
16476
  function gdipHue(r, g, b) {
@@ -16484,29 +16493,30 @@ function gdipHue(r, g, b) {
16484
16493
  function applyHueSaturationLightness(src, hue, saturation, lightness) {
16485
16494
  const out = new Uint8ClampedArray(src);
16486
16495
  const shift = Math.round(hue * HUE_CIRCLE / 360);
16487
- const sMul = 1 + saturation / 100;
16496
+ const satScale = 65536 + Math.floor(saturation * 65536 / 100);
16497
+ const lightOffset = Math.round(255 * Math.floor(lightness * 65536 / 100) / 65536);
16488
16498
  for (let i = 0; i < src.length; i += 4) {
16489
16499
  const r = src[i];
16490
16500
  const g = src[i + 1];
16491
16501
  const b = src[i + 2];
16492
16502
  const max = Math.max(r, g, b);
16493
16503
  const min = Math.min(r, g, b);
16494
- const l = clamp(Math.round(((max + min >> 1) * 100 + 255 * lightness) / 100), 0, 255);
16504
+ const l = clamp((max + min >> 1) + lightOffset, 0, 255);
16495
16505
  if (max === min) {
16496
16506
  out[i] = out[i + 1] = out[i + 2] = l;
16497
16507
  continue;
16498
16508
  }
16499
16509
  const sum = max + min;
16500
- const s = Math.fround(clamp((max - min) / (sum <= 255 ? sum : 510 - sum) * sMul, 0, 1));
16501
- const hi = l <= 127 ? l * (1 + s) : l + s * (255 - l);
16502
- const m1 = l <= 127 ? 2 * l - Math.trunc(hi) : Math.round(2 * l - hi);
16503
- const m2 = 2 * l - m1;
16510
+ const sat2 = clamp(Math.round(Math.floor((max - min) * 255 / (sum <= 255 ? sum : 510 - sum)) * satScale / 65536), 0, 255);
16511
+ const hi = l <= 127 ? Math.floor(l * (255 + sat2) / 255) : l + sat2 - Math.floor(l * sat2 / 255);
16512
+ const m1 = 2 * l - hi;
16513
+ const m2 = hi;
16504
16514
  const index = ((gdipHue(r, g, b) + shift) % HUE_CIRCLE + HUE_CIRCLE) % HUE_CIRCLE;
16505
16515
  const q = index + Math.floor((index + 41) / 85);
16506
16516
  const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16507
- const f = (q - sextant * HUE_SEXTANT) / HUE_SEXTANT;
16508
- const up = Math.trunc(m1 + (m2 - m1) * f);
16509
- const down = Math.trunc(m1 + (m2 - m1) * (1 - f));
16517
+ const position = q - sextant * HUE_SEXTANT;
16518
+ const up = m1 + Math.floor((m2 - m1) * position / HUE_SEXTANT);
16519
+ const down = m1 + Math.floor((m2 - m1) * (HUE_SEXTANT - position) / HUE_SEXTANT);
16510
16520
  const [nr, ng, nb] = [
16511
16521
  [m2, up, m1],
16512
16522
  [down, m2, m1],
@@ -16521,28 +16531,40 @@ function applyHueSaturationLightness(src, hue, saturation, lightness) {
16521
16531
  }
16522
16532
  return out;
16523
16533
  }
16524
- var LUMA_709 = [0.2126, 0.7152, 0.0722];
16525
- var TINT_CHROMA_SCALE = 0.985;
16526
16534
  function applyTint(src, hue, amount) {
16527
16535
  const index = (Math.round(hue * 255 / 360) + 256) % 256;
16528
16536
  const q = (index + Math.floor((index + 41) / 85)) % 258;
16529
- const tint = hslToRgb(q * 60 / 43, 1, 0.5);
16530
- const ty = tint[0] * LUMA_709[0] + tint[1] * LUMA_709[1] + tint[2] * LUMA_709[2];
16531
- const chroma = tint.map((c) => (c - ty) * TINT_CHROMA_SCALE);
16532
- const a = amount / 100;
16537
+ const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16538
+ const position = q - sextant * HUE_SEXTANT;
16539
+ const up = Math.floor(TINT_FULL * position / HUE_SEXTANT);
16540
+ const down = Math.floor(TINT_FULL * (HUE_SEXTANT - position) / HUE_SEXTANT);
16541
+ const [tr, tg, tb] = [
16542
+ [TINT_FULL, up, 0],
16543
+ [down, TINT_FULL, 0],
16544
+ [0, TINT_FULL, up],
16545
+ [0, down, TINT_FULL],
16546
+ [up, 0, TINT_FULL],
16547
+ [TINT_FULL, 0, down]
16548
+ ][sextant];
16549
+ const weight = Math.sign(amount) * Math.floor((255 * Math.abs(amount) + 49) / 100);
16550
+ const original = 255 - weight;
16533
16551
  const out = new Uint8ClampedArray(src);
16534
16552
  for (let i = 0; i < src.length; i += 4) {
16535
16553
  const r = src[i];
16536
16554
  const g = src[i + 1];
16537
16555
  const b = src[i + 2];
16538
- const y = r * LUMA_709[0] + g * LUMA_709[1] + b * LUMA_709[2];
16539
- const v = Math.max(r, g, b);
16540
- out[i] = Math.round((1 - a) * r + a * (y + v * chroma[0]));
16541
- out[i + 1] = Math.round((1 - a) * g + a * (y + v * chroma[1]));
16542
- out[i + 2] = Math.round((1 - a) * b + a * (y + v * chroma[2]));
16556
+ const u = weight * Math.max(r, g, b) >> 8;
16557
+ const x0 = original * r + tr * u;
16558
+ const x1 = original * g + tg * u;
16559
+ const x2 = original * b + tb * u;
16560
+ const base = 54 * r + 183 * g + 19 * b - (54 * (x0 >> 8) + 183 * (x1 >> 8) + 19 * (x2 >> 8));
16561
+ out[i] = base + x0 >> 8;
16562
+ out[i + 1] = base + x1 >> 8;
16563
+ out[i + 2] = base + x2 >> 8;
16543
16564
  }
16544
16565
  return out;
16545
16566
  }
16567
+ var TINT_FULL = 254;
16546
16568
  function applyRedEyeCorrection(src, width, height, areas) {
16547
16569
  const out = new Uint8ClampedArray(src);
16548
16570
  for (const a of areas) {
@@ -20542,8 +20564,7 @@ function resampleImage(rgba, width, height, spec, surface) {
20542
20564
  const axisAligned = m[1] === 0 && m[2] === 0;
20543
20565
  if (hq && axisAligned) {
20544
20566
  const ox = m[0] * spec.srcX + m[4];
20545
- const oy = m[3] * spec.srcY + m[5];
20546
- m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5] + mirroredOrigin(oy) - oy];
20567
+ m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5]];
20547
20568
  }
20548
20569
  const inv2 = invert2(m);
20549
20570
  if (!inv2) {
@@ -23356,6 +23377,21 @@ var nestedReplayer = null;
23356
23377
  function registerNestedMetafileReplayer(fn) {
23357
23378
  nestedReplayer = fn;
23358
23379
  }
23380
+ function inclusiveNestedMapping(toDevice, srcX, srcY, srcW, srcH) {
23381
+ const [a, b, c, d, e, f] = toDevice;
23382
+ const lengthU = Math.hypot(a, b) * srcW;
23383
+ const lengthV = Math.hypot(c, d) * srcH;
23384
+ if (!(srcW > 1 && srcH > 1 && lengthU > 1 && lengthV > 1)) {
23385
+ return toDevice;
23386
+ }
23387
+ const ku = (lengthU - 1) / lengthU * (srcW / (srcW - 1));
23388
+ const kv = (lengthV - 1) / lengthV * (srcH / (srcH - 1));
23389
+ const na = a * ku;
23390
+ const nb = b * ku;
23391
+ const nc = c * kv;
23392
+ const nd = d * kv;
23393
+ return [na, nb, nc, nd, e + (a - na) * srcX + (c - nc) * srcY, f + (b - nb) * srcX + (d - nd) * srcY];
23394
+ }
23359
23395
  function drawNestedMetafile(rCtx, img, cached, source) {
23360
23396
  const depth = rCtx.nestingDepth ?? 0;
23361
23397
  if (!nestedReplayer || !source || !img.data || source.unit !== UNIT_PIXEL || depth >= MAX_NESTED_METAFILE_DEPTH) {
@@ -23369,9 +23405,12 @@ function drawNestedMetafile(rCtx, img, cached, source) {
23369
23405
  if (!size) {
23370
23406
  return false;
23371
23407
  }
23372
- const toCanvas = mulMatrix(
23373
- [1, 0, 0, 1, -0.5, -0.5],
23374
- mulMatrix(mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)), [1, 0, 0, 1, 0.5, 0.5])
23408
+ const toCanvas = inclusiveNestedMapping(
23409
+ mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)),
23410
+ srcX,
23411
+ srcY,
23412
+ srcW,
23413
+ srcH
23375
23414
  );
23376
23415
  const bytes = img.data.slice(0);
23377
23416
  const caches = cached && cached.kind === "metafile" ? cached.caches : void 0;
package/dist/index.mjs CHANGED
@@ -16402,8 +16402,8 @@ function midtoneGamma(t) {
16402
16402
  low = high;
16403
16403
  high = (high + 100) / 2;
16404
16404
  }
16405
- gamma = Math.abs(t) === 100 ? 10 : Math.min(10, gamma + (Math.abs(t) - low) / (high - low));
16406
- return Math.fround(t < 0 ? gamma : 1 / gamma);
16405
+ gamma = Math.abs(t) === 100 ? 10 : Math.min(10, truncF32(gamma + truncF32(truncF32(Math.abs(t) - low) / truncF32(high - low))));
16406
+ return t < 0 ? truncF32(gamma) : truncF32(1 / truncF32(gamma));
16407
16407
  }
16408
16408
  function brightnessContrastLut(brightness, contrast) {
16409
16409
  const gain = contrast >= 100 ? 1e6 : contrast >= 0 ? 100 / (100 - contrast) : (100 + contrast) / 100;
@@ -16420,6 +16420,23 @@ function curveAdjustmentLut(adjustment, intensity) {
16420
16420
  return nativeCurveLookup(adjustment, clamp(Math.trunc(intensity), min, max)).slice();
16421
16421
  }
16422
16422
  function levelsLut(highlight, midtone, shadow) {
16423
+ if (highlight !== shadow) {
16424
+ const forward = highlight > shadow;
16425
+ const lo = truncF32((forward ? shadow : highlight) * 255 / 100);
16426
+ const hi = truncF32((forward ? highlight : shadow) * 255 / 100);
16427
+ const scale = truncF32(1 / truncF32(hi - lo));
16428
+ const exponent2 = midtoneGamma(midtone);
16429
+ const lut = new Uint8Array(256);
16430
+ for (let v = 0; v < 256; v++) {
16431
+ let level = clamp(truncF32(truncF32(v - lo) * scale), 0, 1);
16432
+ if (midtone !== 0) {
16433
+ level = truncF32(level ** exponent2);
16434
+ }
16435
+ const out = forward ? truncF32(255 * level) : truncF32(255 - truncF32(255 * level));
16436
+ lut[v] = clamp(Math.floor(out + 0.5), 0, 255);
16437
+ }
16438
+ return lut;
16439
+ }
16423
16440
  const base = shadow * 255 / 100 - (highlight === shadow && shadow < 50 ? 1 : 0);
16424
16441
  const span = highlight === shadow ? 1 : (highlight - shadow) * 255 / 100;
16425
16442
  const exponent = midtoneGamma(midtone);
@@ -16452,14 +16469,6 @@ function applyColorMatrix(src, m) {
16452
16469
  }
16453
16470
  return out;
16454
16471
  }
16455
- function hslToRgb(h, s, l) {
16456
- const c = (1 - Math.abs(2 * l - 1)) * s;
16457
- const hp = (h % 360 + 360) % 360 / 60;
16458
- const x = c * (1 - Math.abs(hp % 2 - 1));
16459
- const m = l - c / 2;
16460
- const [r, g, b] = hp < 1 ? [c, x, 0] : hp < 2 ? [x, c, 0] : hp < 3 ? [0, c, x] : hp < 4 ? [0, x, c] : hp < 5 ? [x, 0, c] : [c, 0, x];
16461
- return [r + m, g + m, b + m];
16462
- }
16463
16472
  var HUE_SEXTANT = 43;
16464
16473
  var HUE_CIRCLE = 255;
16465
16474
  function gdipHue(r, g, b) {
@@ -16482,29 +16491,30 @@ function gdipHue(r, g, b) {
16482
16491
  function applyHueSaturationLightness(src, hue, saturation, lightness) {
16483
16492
  const out = new Uint8ClampedArray(src);
16484
16493
  const shift = Math.round(hue * HUE_CIRCLE / 360);
16485
- const sMul = 1 + saturation / 100;
16494
+ const satScale = 65536 + Math.floor(saturation * 65536 / 100);
16495
+ const lightOffset = Math.round(255 * Math.floor(lightness * 65536 / 100) / 65536);
16486
16496
  for (let i = 0; i < src.length; i += 4) {
16487
16497
  const r = src[i];
16488
16498
  const g = src[i + 1];
16489
16499
  const b = src[i + 2];
16490
16500
  const max = Math.max(r, g, b);
16491
16501
  const min = Math.min(r, g, b);
16492
- const l = clamp(Math.round(((max + min >> 1) * 100 + 255 * lightness) / 100), 0, 255);
16502
+ const l = clamp((max + min >> 1) + lightOffset, 0, 255);
16493
16503
  if (max === min) {
16494
16504
  out[i] = out[i + 1] = out[i + 2] = l;
16495
16505
  continue;
16496
16506
  }
16497
16507
  const sum = max + min;
16498
- const s = Math.fround(clamp((max - min) / (sum <= 255 ? sum : 510 - sum) * sMul, 0, 1));
16499
- const hi = l <= 127 ? l * (1 + s) : l + s * (255 - l);
16500
- const m1 = l <= 127 ? 2 * l - Math.trunc(hi) : Math.round(2 * l - hi);
16501
- const m2 = 2 * l - m1;
16508
+ const sat2 = clamp(Math.round(Math.floor((max - min) * 255 / (sum <= 255 ? sum : 510 - sum)) * satScale / 65536), 0, 255);
16509
+ const hi = l <= 127 ? Math.floor(l * (255 + sat2) / 255) : l + sat2 - Math.floor(l * sat2 / 255);
16510
+ const m1 = 2 * l - hi;
16511
+ const m2 = hi;
16502
16512
  const index = ((gdipHue(r, g, b) + shift) % HUE_CIRCLE + HUE_CIRCLE) % HUE_CIRCLE;
16503
16513
  const q = index + Math.floor((index + 41) / 85);
16504
16514
  const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16505
- const f = (q - sextant * HUE_SEXTANT) / HUE_SEXTANT;
16506
- const up = Math.trunc(m1 + (m2 - m1) * f);
16507
- const down = Math.trunc(m1 + (m2 - m1) * (1 - f));
16515
+ const position = q - sextant * HUE_SEXTANT;
16516
+ const up = m1 + Math.floor((m2 - m1) * position / HUE_SEXTANT);
16517
+ const down = m1 + Math.floor((m2 - m1) * (HUE_SEXTANT - position) / HUE_SEXTANT);
16508
16518
  const [nr, ng, nb] = [
16509
16519
  [m2, up, m1],
16510
16520
  [down, m2, m1],
@@ -16519,28 +16529,40 @@ function applyHueSaturationLightness(src, hue, saturation, lightness) {
16519
16529
  }
16520
16530
  return out;
16521
16531
  }
16522
- var LUMA_709 = [0.2126, 0.7152, 0.0722];
16523
- var TINT_CHROMA_SCALE = 0.985;
16524
16532
  function applyTint(src, hue, amount) {
16525
16533
  const index = (Math.round(hue * 255 / 360) + 256) % 256;
16526
16534
  const q = (index + Math.floor((index + 41) / 85)) % 258;
16527
- const tint = hslToRgb(q * 60 / 43, 1, 0.5);
16528
- const ty = tint[0] * LUMA_709[0] + tint[1] * LUMA_709[1] + tint[2] * LUMA_709[2];
16529
- const chroma = tint.map((c) => (c - ty) * TINT_CHROMA_SCALE);
16530
- const a = amount / 100;
16535
+ const sextant = Math.min(5, Math.floor(q / HUE_SEXTANT));
16536
+ const position = q - sextant * HUE_SEXTANT;
16537
+ const up = Math.floor(TINT_FULL * position / HUE_SEXTANT);
16538
+ const down = Math.floor(TINT_FULL * (HUE_SEXTANT - position) / HUE_SEXTANT);
16539
+ const [tr, tg, tb] = [
16540
+ [TINT_FULL, up, 0],
16541
+ [down, TINT_FULL, 0],
16542
+ [0, TINT_FULL, up],
16543
+ [0, down, TINT_FULL],
16544
+ [up, 0, TINT_FULL],
16545
+ [TINT_FULL, 0, down]
16546
+ ][sextant];
16547
+ const weight = Math.sign(amount) * Math.floor((255 * Math.abs(amount) + 49) / 100);
16548
+ const original = 255 - weight;
16531
16549
  const out = new Uint8ClampedArray(src);
16532
16550
  for (let i = 0; i < src.length; i += 4) {
16533
16551
  const r = src[i];
16534
16552
  const g = src[i + 1];
16535
16553
  const b = src[i + 2];
16536
- const y = r * LUMA_709[0] + g * LUMA_709[1] + b * LUMA_709[2];
16537
- const v = Math.max(r, g, b);
16538
- out[i] = Math.round((1 - a) * r + a * (y + v * chroma[0]));
16539
- out[i + 1] = Math.round((1 - a) * g + a * (y + v * chroma[1]));
16540
- out[i + 2] = Math.round((1 - a) * b + a * (y + v * chroma[2]));
16554
+ const u = weight * Math.max(r, g, b) >> 8;
16555
+ const x0 = original * r + tr * u;
16556
+ const x1 = original * g + tg * u;
16557
+ const x2 = original * b + tb * u;
16558
+ const base = 54 * r + 183 * g + 19 * b - (54 * (x0 >> 8) + 183 * (x1 >> 8) + 19 * (x2 >> 8));
16559
+ out[i] = base + x0 >> 8;
16560
+ out[i + 1] = base + x1 >> 8;
16561
+ out[i + 2] = base + x2 >> 8;
16541
16562
  }
16542
16563
  return out;
16543
16564
  }
16565
+ var TINT_FULL = 254;
16544
16566
  function applyRedEyeCorrection(src, width, height, areas) {
16545
16567
  const out = new Uint8ClampedArray(src);
16546
16568
  for (const a of areas) {
@@ -20540,8 +20562,7 @@ function resampleImage(rgba, width, height, spec, surface) {
20540
20562
  const axisAligned = m[1] === 0 && m[2] === 0;
20541
20563
  if (hq && axisAligned) {
20542
20564
  const ox = m[0] * spec.srcX + m[4];
20543
- const oy = m[3] * spec.srcY + m[5];
20544
- m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5] + mirroredOrigin(oy) - oy];
20565
+ m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5]];
20545
20566
  }
20546
20567
  const inv2 = invert2(m);
20547
20568
  if (!inv2) {
@@ -23354,6 +23375,21 @@ var nestedReplayer = null;
23354
23375
  function registerNestedMetafileReplayer(fn) {
23355
23376
  nestedReplayer = fn;
23356
23377
  }
23378
+ function inclusiveNestedMapping(toDevice, srcX, srcY, srcW, srcH) {
23379
+ const [a, b, c, d, e, f] = toDevice;
23380
+ const lengthU = Math.hypot(a, b) * srcW;
23381
+ const lengthV = Math.hypot(c, d) * srcH;
23382
+ if (!(srcW > 1 && srcH > 1 && lengthU > 1 && lengthV > 1)) {
23383
+ return toDevice;
23384
+ }
23385
+ const ku = (lengthU - 1) / lengthU * (srcW / (srcW - 1));
23386
+ const kv = (lengthV - 1) / lengthV * (srcH / (srcH - 1));
23387
+ const na = a * ku;
23388
+ const nb = b * ku;
23389
+ const nc = c * kv;
23390
+ const nd = d * kv;
23391
+ return [na, nb, nc, nd, e + (a - na) * srcX + (c - nc) * srcY, f + (b - nb) * srcX + (d - nd) * srcY];
23392
+ }
23357
23393
  function drawNestedMetafile(rCtx, img, cached, source) {
23358
23394
  const depth = rCtx.nestingDepth ?? 0;
23359
23395
  if (!nestedReplayer || !source || !img.data || source.unit !== UNIT_PIXEL || depth >= MAX_NESTED_METAFILE_DEPTH) {
@@ -23367,9 +23403,12 @@ function drawNestedMetafile(rCtx, img, cached, source) {
23367
23403
  if (!size) {
23368
23404
  return false;
23369
23405
  }
23370
- const toCanvas = mulMatrix(
23371
- [1, 0, 0, 1, -0.5, -0.5],
23372
- mulMatrix(mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)), [1, 0, 0, 1, 0.5, 0.5])
23406
+ const toCanvas = inclusiveNestedMapping(
23407
+ mulMatrix(plusWorldMatrix(rCtx), source.toWorld(srcX, srcY, srcW, srcH)),
23408
+ srcX,
23409
+ srcY,
23410
+ srcW,
23411
+ srcH
23373
23412
  );
23374
23413
  const bytes = img.data.slice(0);
23375
23414
  const caches = cached && cached.kind === "metafile" ? cached.caches : void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emf-converter",
3
- "version": "4.8.0",
3
+ "version": "4.8.1",
4
4
  "description": "Convert EMF/WMF metafile binaries to PNG data URLs or SVG (markup, data URL, React/JSX)",
5
5
  "keywords": [
6
6
  "canvas",