@pixerate/editor 0.96.0 → 0.98.0

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.
Files changed (52) hide show
  1. package/THIRD_PARTY_NOTICES.md +4 -2
  2. package/dist/animation-editor/index.cjs +55 -53
  3. package/dist/animation-editor/index.cjs.map +1 -1
  4. package/dist/animation-editor/index.d.cts +3 -2
  5. package/dist/animation-editor/index.d.ts +3 -2
  6. package/dist/animation-editor/index.js +11 -9
  7. package/dist/animation-editor/index.js.map +1 -1
  8. package/dist/chunk-DWGZUSES.cjs +694 -0
  9. package/dist/chunk-DWGZUSES.cjs.map +1 -0
  10. package/dist/chunk-GX332W2C.js +181 -0
  11. package/dist/chunk-GX332W2C.js.map +1 -0
  12. package/dist/{chunk-7MD7C6XQ.cjs → chunk-JF5PXN7W.cjs} +96 -744
  13. package/dist/chunk-JF5PXN7W.cjs.map +1 -0
  14. package/dist/chunk-KKREERP2.js +694 -0
  15. package/dist/chunk-KKREERP2.js.map +1 -0
  16. package/dist/chunk-MUUXNRU4.cjs +181 -0
  17. package/dist/chunk-MUUXNRU4.cjs.map +1 -0
  18. package/dist/{chunk-KFTQ2PKP.js → chunk-WIR377F6.js} +1001 -61
  19. package/dist/chunk-WIR377F6.js.map +1 -0
  20. package/dist/{chunk-T422YCHR.cjs → chunk-WT6ZAWJP.cjs} +1023 -83
  21. package/dist/chunk-WT6ZAWJP.cjs.map +1 -0
  22. package/dist/{chunk-4JLB2USO.js → chunk-YGZNGDIT.js} +45 -693
  23. package/dist/chunk-YGZNGDIT.js.map +1 -0
  24. package/dist/image-editor/index.cjs +1519 -360
  25. package/dist/image-editor/index.cjs.map +1 -1
  26. package/dist/image-editor/index.d.cts +378 -5
  27. package/dist/image-editor/index.d.ts +378 -5
  28. package/dist/image-editor/index.js +1244 -85
  29. package/dist/image-editor/index.js.map +1 -1
  30. package/dist/raster/index.cjs +25 -2
  31. package/dist/raster/index.cjs.map +1 -1
  32. package/dist/raster/index.d.cts +143 -4
  33. package/dist/raster/index.d.ts +143 -4
  34. package/dist/raster/index.js +25 -2
  35. package/dist/{svg-ymShkNtu.d.cts → svg-C9r284x8.d.cts} +6 -9
  36. package/dist/{svg-Dh17jCyA.d.ts → svg-MVKBqwD4.d.ts} +6 -9
  37. package/dist/types-CwMPoRMU.d.cts +40 -0
  38. package/dist/types-CwMPoRMU.d.ts +40 -0
  39. package/dist/vector/index.cjs +490 -554
  40. package/dist/vector/index.cjs.map +1 -1
  41. package/dist/vector/index.d.cts +154 -292
  42. package/dist/vector/index.d.ts +154 -292
  43. package/dist/vector/index.js +91 -155
  44. package/dist/vector/index.js.map +1 -1
  45. package/dist/warp-B8rAguzs.d.ts +165 -0
  46. package/dist/warp-nYs2DPrx.d.cts +165 -0
  47. package/package.json +1 -1
  48. package/skills/pixerate-image-editor/SKILL.md +49 -3
  49. package/dist/chunk-4JLB2USO.js.map +0 -1
  50. package/dist/chunk-7MD7C6XQ.cjs.map +0 -1
  51. package/dist/chunk-KFTQ2PKP.js.map +0 -1
  52. package/dist/chunk-T422YCHR.cjs.map +0 -1
@@ -7,6 +7,21 @@
7
7
 
8
8
 
9
9
 
10
+ var _chunkMUUXNRU4cjs = require('./chunk-MUUXNRU4.cjs');
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
10
25
 
11
26
 
12
27
 
@@ -644,14 +659,14 @@ var PatternTile = class {
644
659
  let b = 0;
645
660
  let a = 0;
646
661
  for (let dy = 0; dy < 2; dy++) {
647
- const wy = dy ? fy : 1 - fy;
648
- if (wy === 0) continue;
662
+ const wy2 = dy ? fy : 1 - fy;
663
+ if (wy2 === 0) continue;
649
664
  const yi = ((y0 + dy) % this.h + this.h) % this.h;
650
665
  for (let dx = 0; dx < 2; dx++) {
651
- const wx = dx ? fx : 1 - fx;
652
- if (wx === 0) continue;
666
+ const wx2 = dx ? fx : 1 - fx;
667
+ if (wx2 === 0) continue;
653
668
  const xi = ((x0 + dx) % this.w + this.w) % this.w;
654
- const k = wx * wy;
669
+ const k = wx2 * wy2;
655
670
  const i = (yi * this.w + xi) * 4;
656
671
  r += this.px[i] * k;
657
672
  g += this.px[i + 1] * k;
@@ -1080,11 +1095,18 @@ function boxLine(src, x0, dst, bw) {
1080
1095
  }
1081
1096
  }
1082
1097
  var BLUR_EPS = 1e-7;
1098
+ var BLUR_FIX = 2 ** 32;
1083
1099
  function tentLine(src, dst, bw, mid) {
1084
1100
  const [r] = boxGeom(bw);
1085
- boxLine(src, -r, mid.subarray(0, src.length + 2 * r), bw);
1086
- boxLine(mid.subarray(0, src.length + 2 * r), r, dst, bw);
1087
- for (let i = 0; i < dst.length; i++) if (Math.abs(dst[i]) < BLUR_EPS) dst[i] = 0;
1101
+ const m = mid.subarray(0, src.length + 2 * r);
1102
+ for (let i = 0; i < src.length; i++) src[i] = Math.round(src[i] * BLUR_FIX);
1103
+ boxLine(src, -r, m, bw);
1104
+ for (let i = 0; i < m.length; i++) m[i] = Math.round(m[i]);
1105
+ boxLine(m, r, dst, bw);
1106
+ for (let i = 0; i < dst.length; i++) {
1107
+ const v = dst[i] / BLUR_FIX;
1108
+ dst[i] = Math.abs(v) < BLUR_EPS ? 0 : v;
1109
+ }
1088
1110
  }
1089
1111
  function tent(m, w) {
1090
1112
  if (!Number.isFinite(w) || m.v.length === 0) return;
@@ -1386,25 +1408,41 @@ function effectsAreLocal(items) {
1386
1408
  }
1387
1409
  });
1388
1410
  }
1411
+ function shapeBounds(shape, rect) {
1412
+ const { width: w, height: h } = rect;
1413
+ const rowHit = (y) => {
1414
+ for (let x = 0, i = y * w; x < w; x++, i++) if (shape[i] > INSIDE_EPS) return true;
1415
+ return false;
1416
+ };
1417
+ let y0 = 0;
1418
+ while (y0 < h && !rowHit(y0)) y0++;
1419
+ if (y0 === h) return null;
1420
+ let y1 = h - 1;
1421
+ while (!rowHit(y1)) y1--;
1422
+ let x0 = w;
1423
+ let x1 = -1;
1424
+ for (let y = y0; y <= y1; y++) {
1425
+ const o = y * w;
1426
+ for (let x = 0; x < x0; x++) {
1427
+ if (shape[o + x] > INSIDE_EPS) {
1428
+ x0 = x;
1429
+ break;
1430
+ }
1431
+ }
1432
+ for (let x = w - 1; x > x1; x--) {
1433
+ if (shape[o + x] > INSIDE_EPS) {
1434
+ x1 = x;
1435
+ break;
1436
+ }
1437
+ }
1438
+ }
1439
+ return { x: rect.x + x0, y: rect.y + y0, width: x1 - x0 + 1, height: y1 - y0 + 1 };
1440
+ }
1389
1441
  function buildEffectMaps(items, shape, rect, ctx) {
1390
1442
  const w = rect.width;
1391
1443
  const h = rect.height;
1392
1444
  const s = { w, h, v: shape };
1393
- let x0 = Infinity;
1394
- let y0 = Infinity;
1395
- let x1 = -Infinity;
1396
- let y1 = -Infinity;
1397
- for (let y = 0; y < h; y++) {
1398
- for (let x = 0; x < w; x++) {
1399
- if (shape[y * w + x] > INSIDE_EPS) {
1400
- if (x < x0) x0 = x;
1401
- if (x > x1) x1 = x;
1402
- if (y < y0) y0 = y;
1403
- if (y > y1) y1 = y;
1404
- }
1405
- }
1406
- }
1407
- const bounds = x0 === Infinity ? null : { x: rect.x + x0, y: rect.y + y0, width: x1 - x0 + 1, height: y1 - y0 + 1 };
1445
+ const bounds = shapeBounds(shape, rect);
1408
1446
  const anchor = bounds ? { x: bounds.x, y: bounds.y } : { x: rect.x, y: rect.y };
1409
1447
  const per = [];
1410
1448
  const bevelPaint = [];
@@ -1452,6 +1490,81 @@ function buildEffectMaps(items, shape, rect, ctx) {
1452
1490
  for (const d of [din, dout, doutExact]) if (d) bytes += d.byteLength;
1453
1491
  return { rect, items, bounds, shape, per, bevelPaint, din, dout, doutExact, frames, bytes };
1454
1492
  }
1493
+ var rectArea = (r) => r.width * r.height;
1494
+ function clipRect(a, b) {
1495
+ const x0 = Math.max(a.x, b.x);
1496
+ const y0 = Math.max(a.y, b.y);
1497
+ const x1 = Math.min(a.x + a.width, b.x + b.width);
1498
+ const y1 = Math.min(a.y + a.height, b.y + b.height);
1499
+ return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
1500
+ }
1501
+ var growRect = (r, m) => ({ x: r.x - m, y: r.y - m, width: r.width + 2 * m, height: r.height + 2 * m });
1502
+ function unionRect(a, b) {
1503
+ const x0 = Math.min(a.x, b.x);
1504
+ const y0 = Math.min(a.y, b.y);
1505
+ return { x: x0, y: y0, width: Math.max(a.x + a.width, b.x + b.width) - x0, height: Math.max(a.y + a.height, b.y + b.height) - y0 };
1506
+ }
1507
+ function rectMinus(r, cut) {
1508
+ const i = clipRect(r, cut);
1509
+ if (!i) return [r];
1510
+ const parts = [
1511
+ { x: r.x, y: r.y, width: r.width, height: i.y - r.y },
1512
+ { x: r.x, y: i.y + i.height, width: r.width, height: r.y + r.height - (i.y + i.height) },
1513
+ { x: r.x, y: i.y, width: i.x - r.x, height: i.height },
1514
+ { x: i.x + i.width, y: i.y, width: r.x + r.width - (i.x + i.width), height: i.height }
1515
+ ];
1516
+ return parts.filter((p) => p.width > 0 && p.height > 0);
1517
+ }
1518
+ function pasteMap(dst, to, src, from, a) {
1519
+ for (let y = a.y; y < a.y + a.height; y++) {
1520
+ const s = (y - from.y) * from.width + (a.x - from.x);
1521
+ dst.set(src.subarray(s, s + a.width), (y - to.y) * to.width + (a.x - to.x));
1522
+ }
1523
+ }
1524
+ function patchEffectMaps(prev, items, rect, changed, margin, shapeOver, ctx) {
1525
+ if (!effectsAreLocal(items) || rectArea(rect) <= 0) return null;
1526
+ let areas = [];
1527
+ for (const c of changed) {
1528
+ const a = clipRect(growRect(c, margin), rect);
1529
+ if (a) areas.push(a);
1530
+ }
1531
+ areas.push(...rectMinus(rect, prev.rect));
1532
+ for (let merged = true; merged; ) {
1533
+ merged = false;
1534
+ for (let i = 0; i < areas.length && !merged; i++) {
1535
+ for (let j = i + 1; j < areas.length; j++) {
1536
+ if (clipRect(growRect(areas[i], 2 * margin), areas[j])) {
1537
+ areas[i] = unionRect(areas[i], areas[j]);
1538
+ areas.splice(j, 1);
1539
+ merged = true;
1540
+ break;
1541
+ }
1542
+ }
1543
+ }
1544
+ }
1545
+ const windows = areas.map((a) => clipRect(growRect(a, margin), rect));
1546
+ if (windows.reduce((n, w) => n + rectArea(w), 0) > rectArea(rect) / 2) return null;
1547
+ const same = rect.x === prev.rect.x && rect.y === prev.rect.y && rect.width === prev.rect.width && rect.height === prev.rect.height;
1548
+ const take = (v) => same ? v : crop(v, prev.rect, rect, 0);
1549
+ const shape = take(prev.shape);
1550
+ const per = prev.per.map((maps) => maps.map(take));
1551
+ const din = prev.din && take(prev.din);
1552
+ const dout = prev.dout && take(prev.dout);
1553
+ const doutExact = prev.doutExact && take(prev.doutExact);
1554
+ areas.forEach((a, k) => {
1555
+ const w = windows[k];
1556
+ const part = buildEffectMaps(items, shapeOver(w), w, ctx);
1557
+ pasteMap(shape, rect, part.shape, w, a);
1558
+ per.forEach((maps, i) => maps.forEach((m, j) => pasteMap(m, rect, part.per[i][j], w, a)));
1559
+ if (din) pasteMap(din, rect, part.din, w, a);
1560
+ if (dout) pasteMap(dout, rect, part.dout, w, a);
1561
+ if (doutExact) pasteMap(doutExact, rect, part.doutExact, w, a);
1562
+ });
1563
+ let bytes = shape.byteLength;
1564
+ for (const maps of per) for (const m of maps) bytes += m.byteLength;
1565
+ for (const d of [din, dout, doutExact]) if (d) bytes += d.byteLength;
1566
+ return { rect, items, bounds: shapeBounds(shape, rect), shape, per, bevelPaint: prev.bevelPaint, din, dout, doutExact, frames: /* @__PURE__ */ new Map(), bytes };
1567
+ }
1455
1568
  var rgbScratchB = [0, 0, 0];
1456
1569
  var rgbScratchS = [0, 0, 0];
1457
1570
  var rgbScratchM = [0, 0, 0];
@@ -1650,15 +1763,15 @@ function gradientLayout(style, angle, scale, offset, frame) {
1650
1763
  const half = chordOf(a) * Math.max(scale, 1e-3) / 2;
1651
1764
  const dx = Math.cos(a) * half;
1652
1765
  const dy = -Math.sin(a) * half;
1653
- const snap = (v2) => Math.floor(v2 + 1e-4);
1654
- const end = [snap(cx + dx), snap(cy + dy)];
1766
+ const snap2 = (v2) => Math.floor(v2 + 1e-4);
1767
+ const end = [snap2(cx + dx), snap2(cy + dy)];
1655
1768
  let start;
1656
1769
  let mid;
1657
1770
  if (style === "reflected") {
1658
1771
  start = [cx, cy];
1659
1772
  mid = [cx, cy];
1660
1773
  } else {
1661
- start = [snap(cx - dx), snap(cy - dy)];
1774
+ start = [snap2(cx - dx), snap2(cy - dy)];
1662
1775
  mid = [(start[0] + end[0]) / 2, (start[1] + end[1]) / 2];
1663
1776
  }
1664
1777
  const v = [end[0] - start[0], end[1] - start[1]];
@@ -2059,7 +2172,7 @@ var ZERO_TILE = new Uint8ClampedArray(TILE_BYTES);
2059
2172
  var isGroup = (l) => l.type === "group";
2060
2173
  var isPixel = (l) => l.type === "pixel";
2061
2174
  var RasterCompositor = (_class = class {
2062
- constructor(profile = {}, options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);_class.prototype.__init13.call(this);_class.prototype.__init14.call(this);_class.prototype.__init15.call(this);_class.prototype.__init16.call(this);_class.prototype.__init17.call(this);_class.prototype.__init18.call(this);_class.prototype.__init19.call(this);
2175
+ constructor(profile = {}, options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);_class.prototype.__init13.call(this);_class.prototype.__init14.call(this);_class.prototype.__init15.call(this);_class.prototype.__init16.call(this);_class.prototype.__init17.call(this);_class.prototype.__init18.call(this);_class.prototype.__init19.call(this);_class.prototype.__init20.call(this);_class.prototype.__init21.call(this);
2063
2176
  this.profile = profile;
2064
2177
  this.maxCacheBytes = _nullishCoalesce(options.maxCacheBytes, () => ( 256 * 1024 * 1024));
2065
2178
  }
@@ -2084,8 +2197,11 @@ var RasterCompositor = (_class = class {
2084
2197
  __init15() {this.patternTiles = /* @__PURE__ */ new WeakMap()}
2085
2198
  __init16() {this.reachCache = /* @__PURE__ */ new WeakMap()}
2086
2199
  __init17() {this.fxContext = null}
2087
- __init18() {this.lastStats = { tiles: 0, cached: 0, stepsRun: 0 }}
2200
+ __init18() {this.lastStats = { tiles: 0, cached: 0, stepsRun: 0, effectsBuilt: 0, effectsPatched: 0 }}
2088
2201
  __init19() {this.hint = -1}
2202
+ /** The `dirty` rectangles of the current call, as passed. */
2203
+ __init20() {this.callDirty = null}
2204
+ __init21() {this.callStats = this.lastStats}
2089
2205
  /** Drops every cached tile and plane. */
2090
2206
  clear() {
2091
2207
  this.tiles.clear();
@@ -2133,7 +2249,9 @@ var RasterCompositor = (_class = class {
2133
2249
  const steps = this.buildSteps(layers);
2134
2250
  this.hint = options.checkpointLayerId ? this.stepIndexOf(steps, options.checkpointLayerId) : -1;
2135
2251
  this.stamp++;
2136
- const stats = { tiles: 0, cached: 0, stepsRun: 0 };
2252
+ this.callDirty = _nullishCoalesce(options.dirty, () => ( null));
2253
+ const stats = { tiles: 0, cached: 0, stepsRun: 0, effectsBuilt: 0, effectsPatched: 0 };
2254
+ this.callStats = stats;
2137
2255
  const grow = options.dirty ? this.effectsReach(layers) : 0;
2138
2256
  const dirty = grow > 0 ? options.dirty.map((d) => inflateRect(d, grow)) : options.dirty;
2139
2257
  for (const { tx, ty } of _chunkCRMAXIUVcjs.tilesInRect.call(void 0, rect)) {
@@ -2149,8 +2267,10 @@ var RasterCompositor = (_class = class {
2149
2267
  tile(layers, tx, ty, sources) {
2150
2268
  this.setSources(sources);
2151
2269
  this.stamp++;
2152
- const stats = { tiles: 1, cached: 0, stepsRun: 0 };
2270
+ const stats = { tiles: 1, cached: 0, stepsRun: 0, effectsBuilt: 0, effectsPatched: 0 };
2271
+ this.callStats = stats;
2153
2272
  this.hint = -1;
2273
+ this.callDirty = null;
2154
2274
  const data = this.compositeTile(layers, this.buildSteps(layers), tx, ty, stats);
2155
2275
  this.lastStats = stats;
2156
2276
  this.evict();
@@ -2220,7 +2340,8 @@ var RasterCompositor = (_class = class {
2220
2340
  let first = 0;
2221
2341
  if (entry) {
2222
2342
  while (first < sigs.length && first < entry.sigs.length && sameSig(entry.sigs[first], sigs[first])) first++;
2223
- if (first === sigs.length && first === entry.sigs.length) {
2343
+ if (first === sigs.length && first === entry.sigs.length || this.changedOnlyNearby(steps, sigs, entry, dirty)) {
2344
+ entry.sigs = sigs;
2224
2345
  entry.stamp = this.stamp;
2225
2346
  stats.cached++;
2226
2347
  return entry.result;
@@ -2285,6 +2406,20 @@ var RasterCompositor = (_class = class {
2285
2406
  this.cacheBytes += this.entryBytes(next) - prevBytes;
2286
2407
  return result;
2287
2408
  }
2409
+ /**
2410
+ * Whether a tile with no part in this call's (grown) `dirty` rectangles changed only in what local
2411
+ * effects read beyond it: every changed step is a pixel layer with local effects whose changes stay
2412
+ * inside `dirty` (and so are farther than its margin), which leaves the tile's pixels as they were.
2413
+ */
2414
+ changedOnlyNearby(steps, sigs, entry, dirty) {
2415
+ if (this.callDirty === null || dirty || entry.stamp !== this.stamp - 1 || sigs.length !== entry.sigs.length) return false;
2416
+ return steps.every((step, i) => {
2417
+ if (sameSig(entry.sigs[i], sigs[i])) return true;
2418
+ if (step.kind !== "content" || entry.sigs[i].key !== sigs[i].key) return false;
2419
+ const { layer, clipped } = step;
2420
+ return this.hasEffects(layer) && effectsAreLocal(activeEffectItems(layer.effects)) && this.dirtyCoversShape(layer) && clipped.every((c) => this.dirtyCoversShape(c));
2421
+ });
2422
+ }
2288
2423
  entryBytes(e) {
2289
2424
  let n = e.result === ZERO_TILE ? 0 : TILE_BYTES;
2290
2425
  for (const cp of e.checkpoints.values()) n += cp.data.byteLength;
@@ -2415,14 +2550,20 @@ var RasterCompositor = (_class = class {
2415
2550
  if (!b) return { x: 0, y: 0, width: 0, height: 0 };
2416
2551
  return intersectRect({ x: b.x + dx - m, y: b.y + dy - m, width: b.width + 2 * m, height: b.height + 2 * m }, canvas);
2417
2552
  }
2553
+ /** The signature of a layer's shape (its surface tiles and mask refs) per tile of `region`. */
2554
+ shapeSigs(layer, region) {
2555
+ const sigs = /* @__PURE__ */ new Map();
2556
+ if (region.width <= 0 || region.height <= 0) return sigs;
2557
+ const steps = isGroup(layer) ? this.buildSteps(_nullishCoalesce(layer.children, () => ( []))) : null;
2558
+ for (const t of _chunkCRMAXIUVcjs.tilesInRect.call(void 0, region)) {
2559
+ sigs.set(_chunkCRMAXIUVcjs.tileKey.call(void 0, t.tx, t.ty), steps ? this.plainGroupSig(layer, steps, t.tx, t.ty) : this.plainContentSig(layer, t.tx, t.ty));
2560
+ }
2561
+ return sigs;
2562
+ }
2418
2563
  /** The surface tiles (and mask refs) a layer's shape reads over `region`. */
2419
2564
  shapeRefs(layer, region) {
2420
2565
  const refs = [];
2421
- if (region.width <= 0 || region.height <= 0) return refs;
2422
- for (const t of _chunkCRMAXIUVcjs.tilesInRect.call(void 0, region)) {
2423
- const sig = isGroup(layer) ? this.plainGroupSig(layer, this.buildSteps(_nullishCoalesce(layer.children, () => ( []))), t.tx, t.ty) : this.plainContentSig(layer, t.tx, t.ty);
2424
- for (const r of sig.refs) refs.push(r);
2425
- }
2566
+ for (const sig of this.shapeSigs(layer, region).values()) for (const r of sig.refs) refs.push(r);
2426
2567
  return refs;
2427
2568
  }
2428
2569
  lightKey() {
@@ -2448,18 +2589,28 @@ var RasterCompositor = (_class = class {
2448
2589
  const memo = this.effectMemo.get(layer);
2449
2590
  if (memo && memo.stamp === this.stamp) return memo.maps;
2450
2591
  const region = this.effectRegion(layer);
2451
- const key = `${this.propsKey(layer)}${this.lightKey()}|${region.x},${region.y},${region.width},${region.height}`;
2452
- const refs = this.shapeRefs(layer, region);
2592
+ const key = this.propsKey(layer) + this.lightKey();
2593
+ const tiles = this.shapeSigs(layer, region);
2453
2594
  const hit = this.effectCache.get(layer.id);
2454
- let maps;
2455
- if (hit && hit.key === key && sameSig({ key, refs: hit.refs }, { key, refs })) {
2456
- this.effectCache.delete(layer.id);
2457
- this.effectCache.set(layer.id, hit);
2458
- maps = hit.maps;
2595
+ this.effectCache.delete(layer.id);
2596
+ let entry;
2597
+ if (hit && hit.key === key && sameRect(hit.region, region) && [...tiles].every(([k, sig]) => sameSig(hit.tiles.get(k), sig))) {
2598
+ entry = hit;
2459
2599
  } else {
2460
- maps = buildEffectMaps(activeEffectItems(layer.effects), this.layerShape(layer, region), region, this.effectContext());
2461
- this.effectCache.delete(layer.id);
2462
- this.effectCache.set(layer.id, { key, refs, maps });
2600
+ const items = activeEffectItems(layer.effects);
2601
+ const ctx = this.effectContext();
2602
+ let maps = null;
2603
+ if (hit && hit.key === key && items.every((e) => effectReach(e) <= MAX_EFFECT_REACH)) {
2604
+ const changed = this.shapeChanges(layer, hit, tiles, region);
2605
+ maps = patchEffectMaps(hit.maps, items, region, changed, effectsMargin(layer.effects), (r) => this.layerShape(layer, r), ctx);
2606
+ }
2607
+ if (maps) this.callStats.effectsPatched++;
2608
+ else this.callStats.effectsBuilt++;
2609
+ entry = { key, region, tiles, maps: _nullishCoalesce(maps, () => ( buildEffectMaps(items, this.layerShape(layer, region), region, ctx))), stamp: 0 };
2610
+ }
2611
+ entry.stamp = this.stamp;
2612
+ this.effectCache.set(layer.id, entry);
2613
+ if (entry !== hit) {
2463
2614
  let bytes = 0;
2464
2615
  for (const e of this.effectCache.values()) bytes += e.maps.bytes;
2465
2616
  while (this.effectCache.size > 1 && (this.effectCache.size > 32 || bytes > this.maxCacheBytes / 2)) {
@@ -2468,8 +2619,42 @@ var RasterCompositor = (_class = class {
2468
2619
  this.effectCache.delete(oldest);
2469
2620
  }
2470
2621
  }
2471
- this.effectMemo.set(layer, { stamp: this.stamp, maps });
2472
- return maps;
2622
+ this.effectMemo.set(layer, { stamp: this.stamp, maps: entry.maps });
2623
+ return entry.maps;
2624
+ }
2625
+ /**
2626
+ * Where a layer's shape may differ from the one `prev` was built from: the tiles whose signature
2627
+ * changed (a tile new to the region that reads nothing did not), narrowed to this call's `dirty`
2628
+ * rectangles when `prev` is from the previous call and they cover every change of the shape.
2629
+ */
2630
+ shapeChanges(layer, prev, tiles, region) {
2631
+ const out = [];
2632
+ for (const { tx, ty } of _chunkCRMAXIUVcjs.tilesInRect.call(void 0, region)) {
2633
+ const sig = tiles.get(_chunkCRMAXIUVcjs.tileKey.call(void 0, tx, ty));
2634
+ const old = prev.tiles.get(_chunkCRMAXIUVcjs.tileKey.call(void 0, tx, ty));
2635
+ if (old ? sameSig(old, sig) : sig.refs.every((r2) => r2 === null || r2 === 0)) continue;
2636
+ const r = intersectRect({ x: tx * _chunkCRMAXIUVcjs.TILE, y: ty * _chunkCRMAXIUVcjs.TILE, width: _chunkCRMAXIUVcjs.TILE, height: _chunkCRMAXIUVcjs.TILE }, region);
2637
+ if (r.width > 0 && r.height > 0) out.push(r);
2638
+ }
2639
+ const dirty = this.callDirty;
2640
+ if (!dirty || prev.stamp !== this.stamp - 1 || !this.dirtyCoversShape(layer)) return out;
2641
+ const narrowed = [];
2642
+ for (const r of out) {
2643
+ for (const d of dirty) {
2644
+ const a = intersectRect(r, { x: Math.floor(d.x), y: Math.floor(d.y), width: Math.ceil(d.x + d.width) - Math.floor(d.x), height: Math.ceil(d.y + d.height) - Math.floor(d.y) });
2645
+ if (a.width > 0 && a.height > 0) narrowed.push(a);
2646
+ }
2647
+ }
2648
+ return narrowed;
2649
+ }
2650
+ /**
2651
+ * Whether a change to a layer stays inside the `dirty` rectangles that name it: a pixel layer
2652
+ * without filters or a feathered or parametric mask (those spread a change beyond it).
2653
+ */
2654
+ dirtyCoversShape(layer) {
2655
+ if (!isPixel(layer) || _optionalChain([this, 'access', _26 => _26.profile, 'access', _27 => _27.pixelFilters, 'optionalCall', _28 => _28(layer)])) return false;
2656
+ const mask = layer.mask;
2657
+ return !mask || mask.enabled === false || !mask.source && !((_nullishCoalesce(mask.feather, () => ( 0))) > 0);
2473
2658
  }
2474
2659
  /** A layer's alpha over `r` after its mask (0..1, quantised to bytes as tiles see it). */
2475
2660
  layerShape(layer, r) {
@@ -2555,10 +2740,10 @@ var RasterCompositor = (_class = class {
2555
2740
  */
2556
2741
  layerPixels(layer) {
2557
2742
  const raw = this.sources.surfaceOf ? this.sources.surfaceOf(layer) : layer.surface;
2558
- const ox = _nullishCoalesce(_optionalChain([layer, 'access', _26 => _26.offset, 'optionalAccess', _27 => _27.x]), () => ( 0));
2559
- const oy = _nullishCoalesce(_optionalChain([layer, 'access', _28 => _28.offset, 'optionalAccess', _29 => _29.y]), () => ( 0));
2560
- const filters = _nullishCoalesce(_optionalChain([this, 'access', _30 => _30.profile, 'access', _31 => _31.pixelFilters, 'optionalCall', _32 => _32(layer)]), () => ( null));
2561
- if (!_optionalChain([filters, 'optionalAccess', _33 => _33.spatial])) return { surface: raw, dx: ox, dy: oy, perPixel: filters };
2743
+ const ox = _nullishCoalesce(_optionalChain([layer, 'access', _29 => _29.offset, 'optionalAccess', _30 => _30.x]), () => ( 0));
2744
+ const oy = _nullishCoalesce(_optionalChain([layer, 'access', _31 => _31.offset, 'optionalAccess', _32 => _32.y]), () => ( 0));
2745
+ const filters = _nullishCoalesce(_optionalChain([this, 'access', _33 => _33.profile, 'access', _34 => _34.pixelFilters, 'optionalCall', _35 => _35(layer)]), () => ( null));
2746
+ if (!_optionalChain([filters, 'optionalAccess', _36 => _36.spatial])) return { surface: raw, dx: ox, dy: oy, perPixel: filters };
2562
2747
  const fkey = `${ox},${oy}:${filters.key}`;
2563
2748
  let byKey = this.filteredCache.get(raw);
2564
2749
  if (!byKey) {
@@ -2575,7 +2760,7 @@ var RasterCompositor = (_class = class {
2575
2760
  }
2576
2761
  /** RGBA of a content layer over `r` (document space, inside one tile), or `null` when it has nothing there. */
2577
2762
  contentTile(layer, r) {
2578
- if (!isPixel(layer)) return _nullishCoalesce(_optionalChain([this, 'access', _34 => _34.profile, 'access', _35 => _35.contentTile, 'optionalCall', _36 => _36(layer, r, this.sources)]), () => ( null));
2763
+ if (!isPixel(layer)) return _nullishCoalesce(_optionalChain([this, 'access', _37 => _37.profile, 'access', _38 => _38.contentTile, 'optionalCall', _39 => _39(layer, r, this.sources)]), () => ( null));
2579
2764
  const { surface, dx, dy, perPixel } = this.layerPixels(layer);
2580
2765
  const src = { x: r.x - dx, y: r.y - dy, width: r.width, height: r.height };
2581
2766
  const covered = _chunkCRMAXIUVcjs.tilesInRect.call(void 0, src).map((t) => surface.getTile(t.tx, t.ty));
@@ -2590,7 +2775,7 @@ var RasterCompositor = (_class = class {
2590
2775
  let byKey = this.contentCache.get(anchor);
2591
2776
  const refsKey = `${r.x},${r.y}:${fkey}`;
2592
2777
  if (aligned) {
2593
- const hit = _optionalChain([byKey, 'optionalAccess', _37 => _37.get, 'call', _38 => _38(refsKey)]);
2778
+ const hit = _optionalChain([byKey, 'optionalAccess', _40 => _40.get, 'call', _41 => _41(refsKey)]);
2594
2779
  if (hit) return hit;
2595
2780
  }
2596
2781
  const data = _chunkCRMAXIUVcjs.readRegion.call(void 0, surface, src);
@@ -2628,7 +2813,7 @@ var RasterCompositor = (_class = class {
2628
2813
  const H = this.sources.height;
2629
2814
  let v = new Float32Array(W * H);
2630
2815
  if (mask.source) {
2631
- const generated = _nullishCoalesce(_optionalChain([this, 'access', _39 => _39.profile, 'access', _40 => _40.maskSourcePlane, 'optionalCall', _41 => _41(mask.source, W, H, this.sources)]), () => ( null));
2816
+ const generated = _nullishCoalesce(_optionalChain([this, 'access', _42 => _42.profile, 'access', _43 => _43.maskSourcePlane, 'optionalCall', _44 => _44(mask.source, W, H, this.sources)]), () => ( null));
2632
2817
  if (!generated || generated.length !== W * H) v.fill(1);
2633
2818
  else v.set(generated);
2634
2819
  } else {
@@ -2647,8 +2832,8 @@ var RasterCompositor = (_class = class {
2647
2832
  maskTile(layer, r) {
2648
2833
  const mask = layer.mask;
2649
2834
  if (!mask || mask.enabled === false) return null;
2650
- const ox = isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _42 => _42.offset, 'optionalAccess', _43 => _43.x]), () => ( 0)) : 0;
2651
- const oy = isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _44 => _44.offset, 'optionalAccess', _45 => _45.y]), () => ( 0)) : 0;
2835
+ const ox = isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _45 => _45.offset, 'optionalAccess', _46 => _46.x]), () => ( 0)) : 0;
2836
+ const oy = isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _47 => _47.offset, 'optionalAccess', _48 => _48.y]), () => ( 0)) : 0;
2652
2837
  const n = r.width * r.height;
2653
2838
  const out = new Float32Array(n);
2654
2839
  const density = _nullishCoalesce(mask.density, () => ( 1));
@@ -2722,7 +2907,7 @@ var RasterCompositor = (_class = class {
2722
2907
  return empty;
2723
2908
  }
2724
2909
  contentBlend(layer) {
2725
- return _nullishCoalesce(_optionalChain([this, 'access', _46 => _46.profile, 'access', _47 => _47.contentBlend, 'optionalCall', _48 => _48(layer)]), () => ( layer.blend));
2910
+ return _nullishCoalesce(_optionalChain([this, 'access', _49 => _49.profile, 'access', _50 => _50.contentBlend, 'optionalCall', _51 => _51(layer)]), () => ( layer.blend));
2726
2911
  }
2727
2912
  blendOnto(acc, src, empty, mode, alpha, coverage) {
2728
2913
  if (!(alpha > 0)) return empty;
@@ -2776,7 +2961,7 @@ var RasterCompositor = (_class = class {
2776
2961
  }
2777
2962
  visible.push(node);
2778
2963
  }
2779
- if (visible.length) _optionalChain([this, 'access', _49 => _49.profile, 'access', _50 => _50.applyFilterRun, 'optionalCall', _51 => _51(visible, acc, r, masks, this.sources)]);
2964
+ if (visible.length) _optionalChain([this, 'access', _52 => _52.profile, 'access', _53 => _53.applyFilterRun, 'optionalCall', _54 => _54(visible, acc, r, masks, this.sources)]);
2780
2965
  }
2781
2966
  }, _class);
2782
2967
  function filterOverCanvas(surface, ox, oy, filters, width, height) {
@@ -2796,6 +2981,9 @@ function copyRect(data, r, a) {
2796
2981
  function pasteRect(data, r, part, a) {
2797
2982
  for (let y = 0; y < a.height; y++) data.set(part.subarray(y * a.width * 4, (y + 1) * a.width * 4), ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4);
2798
2983
  }
2984
+ function sameRect(a, b) {
2985
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
2986
+ }
2799
2987
  function inflateRect(r, m) {
2800
2988
  return { x: r.x - m, y: r.y - m, width: r.width + 2 * m, height: r.height + 2 * m };
2801
2989
  }
@@ -2813,6 +3001,747 @@ function changedTiles(a, b) {
2813
3001
  return out;
2814
3002
  }
2815
3003
 
3004
+ // src/raster/transform.ts
3005
+ var INTERPOLATIONS = ["nearest", "bilinear", "bicubic"];
3006
+ function isInterpolation(value) {
3007
+ return typeof value === "string" && INTERPOLATIONS.includes(value);
3008
+ }
3009
+ var MAX_TRANSFORM_PIXELS = 1 << 27;
3010
+ var TransformTooLargeError = class extends Error {
3011
+ constructor(message) {
3012
+ super(message);
3013
+ this.name = "TransformTooLargeError";
3014
+ }
3015
+ };
3016
+ var KEYS_A = -0.75;
3017
+ function keysWeight(x) {
3018
+ x = Math.abs(x);
3019
+ if (x < 1) return ((KEYS_A + 2) * x - (KEYS_A + 3)) * x * x + 1;
3020
+ if (x < 2) return KEYS_A * (((x - 5) * x + 8) * x - 4);
3021
+ return 0;
3022
+ }
3023
+ var snap = (t) => Math.abs(t - Math.round(t)) < 1e-7 ? Math.round(t) : t;
3024
+ var MAX_TAPS = 20;
3025
+ var tapI0 = 0;
3026
+ var tapN = 0;
3027
+ function cubicTaps(u, s, w) {
3028
+ if (s <= 1.0001) {
3029
+ const f = Math.floor(u);
3030
+ const t = u - f;
3031
+ w[0] = keysWeight(1 + t);
3032
+ w[1] = keysWeight(t);
3033
+ w[2] = keysWeight(1 - t);
3034
+ w[3] = keysWeight(2 - t);
3035
+ tapI0 = f - 1;
3036
+ tapN = 4;
3037
+ return;
3038
+ }
3039
+ const r = 2 * s;
3040
+ const i0 = Math.ceil(u - r);
3041
+ const n = Math.min(MAX_TAPS, Math.floor(u + r) - i0 + 1);
3042
+ let sum = 0;
3043
+ for (let k = 0; k < n; k++) {
3044
+ const v = keysWeight((i0 + k - u) / s);
3045
+ w[k] = v;
3046
+ sum += v;
3047
+ }
3048
+ if (sum !== 0) for (let k = 0; k < n; k++) w[k] /= sum;
3049
+ tapI0 = i0;
3050
+ tapN = n;
3051
+ }
3052
+ function intersect(a, b) {
3053
+ const x = Math.max(a.x, b.x);
3054
+ const y = Math.max(a.y, b.y);
3055
+ const x1 = Math.min(a.x + a.width, b.x + b.width);
3056
+ const y1 = Math.min(a.y + a.height, b.y + b.height);
3057
+ return x1 > x && y1 > y ? { x, y, width: x1 - x, height: y1 - y } : null;
3058
+ }
3059
+ function hasTilesIn(src, r) {
3060
+ for (const { tx, ty } of _chunkCRMAXIUVcjs.tilesInRect.call(void 0, r)) if (src.getTile(tx, ty)) return true;
3061
+ return false;
3062
+ }
3063
+ function readWindow(src, srcRect, rect) {
3064
+ const n = src.channels === 4 ? 4 : 2;
3065
+ const data = new Float32Array(rect.width * rect.height * n);
3066
+ const win = { x: rect.x, y: rect.y, w: rect.width, h: rect.height, n, data };
3067
+ const r = intersect(rect, srcRect);
3068
+ if (!r) return win;
3069
+ const px = _chunkCRMAXIUVcjs.readRegion.call(void 0, src, r);
3070
+ for (let y = 0; y < r.height; y++) {
3071
+ let s = y * r.width * src.channels;
3072
+ let d = ((r.y - rect.y + y) * rect.width + (r.x - rect.x)) * n;
3073
+ if (n === 4) {
3074
+ for (let x = 0; x < r.width; x++, s += 4, d += 4) {
3075
+ const a = px[s + 3] / 255;
3076
+ data[d] = px[s] * a;
3077
+ data[d + 1] = px[s + 1] * a;
3078
+ data[d + 2] = px[s + 2] * a;
3079
+ data[d + 3] = a;
3080
+ }
3081
+ } else {
3082
+ for (let x = 0; x < r.width; x++, s++, d += 2) {
3083
+ data[d] = px[s];
3084
+ data[d + 1] = 1;
3085
+ }
3086
+ }
3087
+ }
3088
+ return win;
3089
+ }
3090
+ var scratch = new Uint8ClampedArray(4);
3091
+ var scratchWord = new Uint32Array(scratch.buffer);
3092
+ var wx = new Float64Array(MAX_TAPS);
3093
+ var wy = new Float64Array(MAX_TAPS);
3094
+ function sample(win, interp, u, v, su, sv, acc) {
3095
+ const n = win.n;
3096
+ const d = win.data;
3097
+ for (let c = 0; c < n; c++) acc[c] = 0;
3098
+ if (interp === "nearest") {
3099
+ const ix = Math.floor(u + 0.5) - win.x;
3100
+ const iy = Math.floor(v + 0.5) - win.y;
3101
+ if (ix < 0 || iy < 0 || ix >= win.w || iy >= win.h) return;
3102
+ const o = (iy * win.w + ix) * n;
3103
+ for (let c = 0; c < n; c++) acc[c] = d[o + c];
3104
+ return;
3105
+ }
3106
+ if (interp === "bilinear") {
3107
+ const fx = Math.floor(u);
3108
+ const fy = Math.floor(v);
3109
+ const tx = u - fx;
3110
+ const ty = v - fy;
3111
+ for (let j = 0; j < 2; j++) {
3112
+ const iy = fy + j - win.y;
3113
+ if (iy < 0 || iy >= win.h) continue;
3114
+ const kyw = j ? ty : 1 - ty;
3115
+ if (!kyw) continue;
3116
+ for (let i = 0; i < 2; i++) {
3117
+ const ix = fx + i - win.x;
3118
+ if (ix < 0 || ix >= win.w) continue;
3119
+ const k = (i ? tx : 1 - tx) * kyw;
3120
+ if (!k) continue;
3121
+ const o = (iy * win.w + ix) * n;
3122
+ for (let c = 0; c < n; c++) acc[c] += d[o + c] * k;
3123
+ }
3124
+ }
3125
+ return;
3126
+ }
3127
+ u = snap(u);
3128
+ v = snap(v);
3129
+ cubicTaps(u, su, wx);
3130
+ const x0 = tapI0 - win.x;
3131
+ const nu = tapN;
3132
+ cubicTaps(v, sv, wy);
3133
+ const y0 = tapI0 - win.y;
3134
+ const nv = tapN;
3135
+ const W = win.w;
3136
+ if (n === 4 && nu === 4 && nv === 4 && x0 >= 0 && y0 >= 0 && x0 + 4 <= W && y0 + 4 <= win.h) {
3137
+ let r = 0;
3138
+ let g = 0;
3139
+ let b = 0;
3140
+ let a = 0;
3141
+ const w0 = wx[0];
3142
+ const w1 = wx[1];
3143
+ const w2 = wx[2];
3144
+ const w3 = wx[3];
3145
+ for (let j = 0; j < 4; j++) {
3146
+ const kyw = wy[j];
3147
+ if (kyw === 0) continue;
3148
+ let o = ((y0 + j) * W + x0) * 4;
3149
+ const r0 = d[o] * w0 + d[o + 4] * w1 + d[o + 8] * w2 + d[o + 12] * w3;
3150
+ const g0 = d[o + 1] * w0 + d[o + 5] * w1 + d[o + 9] * w2 + d[o + 13] * w3;
3151
+ const b0 = d[o + 2] * w0 + d[o + 6] * w1 + d[o + 10] * w2 + d[o + 14] * w3;
3152
+ const a0 = d[o + 3] * w0 + d[o + 7] * w1 + d[o + 11] * w2 + d[o + 15] * w3;
3153
+ r += r0 * kyw;
3154
+ g += g0 * kyw;
3155
+ b += b0 * kyw;
3156
+ a += a0 * kyw;
3157
+ }
3158
+ acc[0] = r;
3159
+ acc[1] = g;
3160
+ acc[2] = b;
3161
+ acc[3] = a;
3162
+ return;
3163
+ }
3164
+ for (let j = 0; j < nv; j++) {
3165
+ const kyw = wy[j];
3166
+ if (kyw === 0) continue;
3167
+ const iy = y0 + j;
3168
+ if (iy < 0 || iy >= win.h) continue;
3169
+ const row = iy * W;
3170
+ for (let i = 0; i < nu; i++) {
3171
+ const k = wx[i] * kyw;
3172
+ if (k === 0) continue;
3173
+ const ix = x0 + i;
3174
+ if (ix < 0 || ix >= W) continue;
3175
+ const o = (row + ix) * n;
3176
+ if (n === 4) {
3177
+ acc[0] += d[o] * k;
3178
+ acc[1] += d[o + 1] * k;
3179
+ acc[2] += d[o + 2] * k;
3180
+ acc[3] += d[o + 3] * k;
3181
+ } else {
3182
+ acc[0] += d[o] * k;
3183
+ acc[1] += d[o + 1] * k;
3184
+ }
3185
+ }
3186
+ }
3187
+ }
3188
+ function store(out, o, acc, ch, def) {
3189
+ if (ch === 4) {
3190
+ const al = acc[3] > 1 ? 1 : acc[3];
3191
+ if (!(al > 1e-6)) return false;
3192
+ out[o] = acc[0] / al;
3193
+ out[o + 1] = acc[1] / al;
3194
+ out[o + 2] = acc[2] / al;
3195
+ out[o + 3] = al * 255;
3196
+ return true;
3197
+ }
3198
+ const inside = acc[1] > 1 ? 1 : acc[1];
3199
+ if (!(inside > 1e-6)) return false;
3200
+ out[o] = acc[0] + def * (1 - inside);
3201
+ return true;
3202
+ }
3203
+ function boxReduce(src, srcRect, kx, ky) {
3204
+ const ch = src.channels;
3205
+ const rx0 = Math.floor(srcRect.x / kx);
3206
+ const ry0 = Math.floor(srcRect.y / ky);
3207
+ const rx1 = Math.ceil((srcRect.x + srcRect.width) / kx);
3208
+ const ry1 = Math.ceil((srcRect.y + srcRect.height) / ky);
3209
+ const rw = rx1 - rx0;
3210
+ const rect = { x: rx0, y: ry0, width: rw, height: ry1 - ry0 };
3211
+ let out = _chunkCRMAXIUVcjs.emptySurface.call(void 0, ch, src.defaultValue);
3212
+ const rowsPer = Math.max(1, Math.floor(_chunkCRMAXIUVcjs.TILE / ky));
3213
+ const area = kx * ky;
3214
+ for (let ry = ry0; ry < ry1; ry += rowsPer) {
3215
+ const rows = Math.min(rowsPer, ry1 - ry);
3216
+ const strip = { x: rx0 * kx, y: ry * ky, width: rw * kx, height: rows * ky };
3217
+ const px = _chunkCRMAXIUVcjs.readRegion.call(void 0, src, strip);
3218
+ const red = new Uint8ClampedArray(rw * rows * ch);
3219
+ for (let j = 0; j < rows; j++) {
3220
+ for (let i = 0; i < rw; i++) {
3221
+ if (ch === 4) {
3222
+ let a = 0;
3223
+ let r = 0;
3224
+ let g = 0;
3225
+ let b = 0;
3226
+ for (let y = 0; y < ky; y++) {
3227
+ let s = ((j * ky + y) * strip.width + i * kx) * 4;
3228
+ for (let x = 0; x < kx; x++, s += 4) {
3229
+ const al = px[s + 3];
3230
+ a += al;
3231
+ r += px[s] * al;
3232
+ g += px[s + 1] * al;
3233
+ b += px[s + 2] * al;
3234
+ }
3235
+ }
3236
+ const o = (j * rw + i) * 4;
3237
+ if (a > 0) {
3238
+ red[o] = r / a;
3239
+ red[o + 1] = g / a;
3240
+ red[o + 2] = b / a;
3241
+ red[o + 3] = a / area;
3242
+ }
3243
+ } else {
3244
+ let v = 0;
3245
+ for (let y = 0; y < ky; y++) {
3246
+ const s = (j * ky + y) * strip.width + i * kx;
3247
+ for (let x = 0; x < kx; x++) v += px[s + x];
3248
+ }
3249
+ red[j * rw + i] = v / area;
3250
+ }
3251
+ }
3252
+ }
3253
+ out = _chunkCRMAXIUVcjs.writeRegion.call(void 0, out, { x: rx0, y: ry, width: rw, height: rows }, red);
3254
+ }
3255
+ return { surface: out, rect };
3256
+ }
3257
+ function reduceSurface(src, factor) {
3258
+ const k = Math.max(1, Math.floor(factor));
3259
+ const b = _chunkCRMAXIUVcjs.contentBounds.call(void 0, src);
3260
+ if (k === 1 || !b) return src;
3261
+ return boxReduce(src, b, k, k).surface;
3262
+ }
3263
+ function inverseStretch(inv, X, Y) {
3264
+ const w = inv[6] * X + inv[7] * Y + inv[8];
3265
+ if (!(Math.abs(w) > 1e-12)) return [1, 1];
3266
+ const U = (inv[0] * X + inv[1] * Y + inv[2]) / w;
3267
+ const V = (inv[3] * X + inv[4] * Y + inv[5]) / w;
3268
+ const ux = (inv[0] - U * inv[6]) / w;
3269
+ const uy = (inv[1] - U * inv[7]) / w;
3270
+ const vx = (inv[3] - V * inv[6]) / w;
3271
+ const vy = (inv[4] - V * inv[7]) / w;
3272
+ return [Math.hypot(ux, uy), Math.hypot(vx, vy)];
3273
+ }
3274
+ var reduction = (s) => s >= 2 && Number.isFinite(s) ? Math.min(64, 2 ** Math.floor(Math.log2(s))) : 1;
3275
+ function normalizeStep(step) {
3276
+ if (!step || !(step > 1)) return 1;
3277
+ return Math.min(64, 2 ** Math.floor(Math.log2(step)));
3278
+ }
3279
+ function checkBudget(dst, what = "result") {
3280
+ if (dst.width * dst.height > MAX_TRANSFORM_PIXELS) {
3281
+ throw new TransformTooLargeError(
3282
+ `The transformed ${what} would be ${dst.width} \xD7 ${dst.height} px, more than the ${MAX_TRANSFORM_PIXELS} px limit; use a smaller scale.`
3283
+ );
3284
+ }
3285
+ }
3286
+ function assemble(src, tiles) {
3287
+ return new (0, _chunkCRMAXIUVcjs.TiledSurface)(src.channels, tiles, src.defaultValue);
3288
+ }
3289
+ function transformedBounds(source, h) {
3290
+ if (!(source.width > 0 && source.height > 0) || !_chunkMUUXNRU4cjs.invertHomography.call(void 0, h)) return null;
3291
+ const pts = _chunkMUUXNRU4cjs.boxQuad.call(void 0, source).map((p) => _chunkMUUXNRU4cjs.applyHomography.call(void 0, h, p));
3292
+ if (pts.some((p) => !p)) return null;
3293
+ return _chunkMUUXNRU4cjs.cornerBounds.call(void 0, pts);
3294
+ }
3295
+ function transformSurface(src, h, options = {}) {
3296
+ const interp = _nullishCoalesce(options.interpolation, () => ( "bicubic"));
3297
+ const ch = src.channels;
3298
+ const def = src.defaultValue;
3299
+ const empty = _chunkCRMAXIUVcjs.emptySurface.call(void 0, ch, def);
3300
+ const given = options.source;
3301
+ const step = normalizeStep(options.step);
3302
+ if (_chunkMUUXNRU4cjs.isIdentityHomography.call(void 0, h, 1e-12) && !given && !options.clip) return src;
3303
+ const dx = h[2] / h[8];
3304
+ const dy = h[5] / h[8];
3305
+ if (!given && !options.clip && _chunkMUUXNRU4cjs.isIdentityHomography.call(void 0, [h[0], h[1], 0, h[3], h[4], 0, h[6], h[7], h[8]], 1e-12) && Math.abs(dx - Math.round(dx)) < 1e-9 && Math.abs(dy - Math.round(dy)) < 1e-9) {
3306
+ return _chunkCRMAXIUVcjs.translateSurface.call(void 0, src, Math.round(dx), Math.round(dy));
3307
+ }
3308
+ let srcRect = given ? intersect(given, given) : _chunkCRMAXIUVcjs.contentBounds.call(void 0, src);
3309
+ if (!srcRect) return empty;
3310
+ let H = h;
3311
+ let S = src;
3312
+ if (interp === "bicubic") {
3313
+ const inv0 = _chunkMUUXNRU4cjs.invertHomography.call(void 0, H);
3314
+ const c = _chunkMUUXNRU4cjs.applyHomography.call(void 0, H, { x: srcRect.x + srcRect.width / 2, y: srcRect.y + srcRect.height / 2 });
3315
+ if (inv0 && c) {
3316
+ const [su, sv] = inverseStretch(inv0, c.x, c.y);
3317
+ const kx = reduction(su);
3318
+ const ky = reduction(sv);
3319
+ if (kx > 1 || ky > 1) {
3320
+ const red = boxReduce(src, srcRect, kx, ky);
3321
+ S = red.surface;
3322
+ srcRect = red.rect;
3323
+ H = _chunkMUUXNRU4cjs.multiplyHomographies.call(void 0, [kx, 0, 0, 0, ky, 0, 0, 0, 1], H);
3324
+ }
3325
+ }
3326
+ }
3327
+ const inv = _chunkMUUXNRU4cjs.invertHomography.call(void 0, H);
3328
+ if (!inv) return empty;
3329
+ const sr = srcRect;
3330
+ const fwd = [
3331
+ { x: sr.x - 1, y: sr.y - 1 },
3332
+ { x: sr.x + sr.width + 1, y: sr.y - 1 },
3333
+ { x: sr.x + sr.width + 1, y: sr.y + sr.height + 1 },
3334
+ { x: sr.x - 1, y: sr.y + sr.height + 1 }
3335
+ ].map((p) => _chunkMUUXNRU4cjs.homographyW.call(void 0, H, p));
3336
+ const side = fwd.every((w) => w > 0) ? 1 : fwd.every((w) => w < 0) ? -1 : 0;
3337
+ const wLo = 1 / fwd.reduce((m, w) => Math.max(m, Math.abs(w)), 0);
3338
+ const front = side === 0 ? _chunkMUUXNRU4cjs.homographyFrontSide.call(void 0, H, sr) : 0;
3339
+ const corners = _chunkMUUXNRU4cjs.boxQuad.call(void 0, sr).map((p) => _chunkMUUXNRU4cjs.applyHomography.call(void 0, H, p));
3340
+ const bounds = corners.every(Boolean) ? _chunkMUUXNRU4cjs.cornerBounds.call(void 0, corners) : null;
3341
+ let dst;
3342
+ if (options.clip && bounds && side !== 0) dst = intersect(bounds, options.clip);
3343
+ else dst = _nullishCoalesce(options.clip, () => ( bounds));
3344
+ if (!dst) return empty;
3345
+ if (!options.clip) checkBudget(dst);
3346
+ const affine = Math.abs(inv[6]) < 1e-15 && Math.abs(inv[7]) < 1e-15;
3347
+ const [su0, sv0] = inverseStretch(inv, dst.x + dst.width / 2, dst.y + dst.height / 2);
3348
+ const widen = (s) => interp === "bicubic" ? Math.min(4, Math.max(1, s)) : 1;
3349
+ const maxWiden = interp === "bicubic" ? 4 : 1;
3350
+ const pad = 3 + Math.ceil(2 * maxWiden);
3351
+ const margin = interp === "bicubic" ? Math.max(1, widen(su0), widen(sv0)) : 1;
3352
+ const tiles = /* @__PURE__ */ new Map();
3353
+ const acc = new Float64Array(4);
3354
+ const sx0 = sr.x;
3355
+ const sy0 = sr.y;
3356
+ const sx1 = sr.x + sr.width - 1;
3357
+ const sy1 = sr.y + sr.height - 1;
3358
+ for (const { tx, ty } of _chunkCRMAXIUVcjs.tilesInRect.call(void 0, dst)) {
3359
+ const t = intersect({ x: tx * _chunkCRMAXIUVcjs.TILE, y: ty * _chunkCRMAXIUVcjs.TILE, width: _chunkCRMAXIUVcjs.TILE, height: _chunkCRMAXIUVcjs.TILE }, dst);
3360
+ if (!t) continue;
3361
+ const tc = [
3362
+ { x: t.x, y: t.y },
3363
+ { x: t.x + t.width, y: t.y },
3364
+ { x: t.x + t.width, y: t.y + t.height },
3365
+ { x: t.x, y: t.y + t.height }
3366
+ ];
3367
+ const wc = tc.map((p) => _chunkMUUXNRU4cjs.homographyW.call(void 0, inv, p));
3368
+ let poly = tc;
3369
+ if (side !== 0) {
3370
+ const dd = wc.map((w) => side * w - wLo);
3371
+ poly = [];
3372
+ for (let i = 0; i < 4; i++) {
3373
+ const p = tc[i];
3374
+ const q = tc[(i + 1) % 4];
3375
+ const dp = dd[i];
3376
+ const dq = dd[(i + 1) % 4];
3377
+ if (dp >= 0) poly.push(p);
3378
+ if (dp >= 0 !== dq >= 0) {
3379
+ const k = dp / (dp - dq);
3380
+ poly.push({ x: p.x + (q.x - p.x) * k, y: p.y + (q.y - p.y) * k });
3381
+ }
3382
+ }
3383
+ }
3384
+ if (!poly.length) continue;
3385
+ const straddles = side === 0 && wc.some((w) => w <= 0) && wc.some((w) => w >= 0);
3386
+ let foot;
3387
+ if (straddles) foot = sr;
3388
+ else {
3389
+ const fp = poly.map((p) => _chunkMUUXNRU4cjs.applyHomography.call(void 0, inv, p));
3390
+ if (fp.some((p) => !p)) foot = sr;
3391
+ else {
3392
+ const xs = fp.map((p) => p.x);
3393
+ const ys = fp.map((p) => p.y);
3394
+ const fx0 = Math.floor(Math.min(...xs)) - pad;
3395
+ const fy0 = Math.floor(Math.min(...ys)) - pad;
3396
+ const fx1 = Math.ceil(Math.max(...xs)) + pad;
3397
+ const fy1 = Math.ceil(Math.max(...ys)) + pad;
3398
+ foot = intersect({ x: fx0, y: fy0, width: fx1 - fx0, height: fy1 - fy0 }, { x: sr.x - pad, y: sr.y - pad, width: sr.width + 2 * pad, height: sr.height + 2 * pad });
3399
+ }
3400
+ }
3401
+ if (!foot) continue;
3402
+ const readable = intersect(foot, sr);
3403
+ if (!readable || !hasTilesIn(S, readable)) continue;
3404
+ const win = readWindow(S, sr, foot);
3405
+ const out = new Uint8ClampedArray(_chunkCRMAXIUVcjs.TILE * _chunkCRMAXIUVcjs.TILE * ch);
3406
+ if (def) out.fill(def);
3407
+ let any = false;
3408
+ const ox = tx * _chunkCRMAXIUVcjs.TILE;
3409
+ const oy = ty * _chunkCRMAXIUVcjs.TILE;
3410
+ let su = widen(su0);
3411
+ let sv = widen(sv0);
3412
+ const ystart = t.y - ((t.y - oy) % step + step) % step;
3413
+ const xstart = t.x - ((t.x - ox) % step + step) % step;
3414
+ const blocks = Math.ceil((t.x + t.width - xstart) / step);
3415
+ const words = ch === 4 ? new Uint32Array(out.buffer) : null;
3416
+ const rowVals = new Float64Array(blocks);
3417
+ const rowSet = new Uint8Array(blocks);
3418
+ for (let y = ystart; y < t.y + t.height; y += step) {
3419
+ const Y = y + step / 2;
3420
+ let anyInRow = false;
3421
+ for (let bi = 0, x = xstart; bi < blocks; bi++, x += step) {
3422
+ rowSet[bi] = 0;
3423
+ const X = x + step / 2;
3424
+ const w = inv[6] * X + inv[7] * Y + inv[8];
3425
+ if (front !== 0 && front * w <= 0) continue;
3426
+ const u = (inv[0] * X + inv[1] * Y + inv[2]) / w - 0.5;
3427
+ const v = (inv[3] * X + inv[4] * Y + inv[5]) / w - 0.5;
3428
+ if (!(u >= sx0 - margin && v >= sy0 - margin && u <= sx1 + margin && v <= sy1 + margin)) continue;
3429
+ if (!affine && interp === "bicubic") {
3430
+ const s = inverseStretch(inv, X, Y);
3431
+ su = widen(s[0]);
3432
+ sv = widen(s[1]);
3433
+ }
3434
+ sample(win, interp, u, v, su, sv, acc);
3435
+ if (!store(scratch, 0, acc, ch, def)) continue;
3436
+ rowSet[bi] = 1;
3437
+ rowVals[bi] = ch === 4 ? scratchWord[0] : scratch[0];
3438
+ anyInRow = true;
3439
+ }
3440
+ if (!anyInRow) continue;
3441
+ any = true;
3442
+ const y0 = Math.max(y, t.y);
3443
+ const y1 = Math.min(y + step, t.y + t.height);
3444
+ for (let yy = y0; yy < y1; yy++) {
3445
+ const row = (yy - oy) * _chunkCRMAXIUVcjs.TILE - ox;
3446
+ for (let bi = 0, x = xstart; bi < blocks; bi++, x += step) {
3447
+ if (!rowSet[bi]) continue;
3448
+ const x0 = Math.max(x, t.x);
3449
+ const x1 = Math.min(x + step, t.x + t.width);
3450
+ const val = rowVals[bi];
3451
+ if (words) for (let xx = x0; xx < x1; xx++) words[row + xx] = val;
3452
+ else for (let xx = x0; xx < x1; xx++) out[row + xx] = val;
3453
+ }
3454
+ }
3455
+ }
3456
+ if (!any) continue;
3457
+ const tile = _chunkCRMAXIUVcjs.finishTile.call(void 0, out, ch, def);
3458
+ if (tile) tiles.set(_chunkCRMAXIUVcjs.tileKey.call(void 0, tx, ty), tile);
3459
+ }
3460
+ return assemble(src, tiles);
3461
+ }
3462
+ var CELL = 4;
3463
+ var MAX_CELLS = 512;
3464
+ var MAX_SS = 8;
3465
+ function warpSurface(src, f, options = {}) {
3466
+ const interp = _nullishCoalesce(options.interpolation, () => ( "bicubic"));
3467
+ const ch = src.channels;
3468
+ const def = src.defaultValue;
3469
+ const empty = _chunkCRMAXIUVcjs.emptySurface.call(void 0, ch, def);
3470
+ const sr = options.source ? intersect(options.source, options.source) : _chunkCRMAXIUVcjs.contentBounds.call(void 0, src);
3471
+ if (!sr) return empty;
3472
+ const step = normalizeStep(options.step);
3473
+ const nx = Math.min(MAX_CELLS, Math.max(1, Math.ceil(sr.width / CELL)));
3474
+ const ny = Math.min(MAX_CELLS, Math.max(1, Math.ceil(sr.height / CELL)));
3475
+ const w1 = nx + 1;
3476
+ const dvx = new Float64Array(w1 * (ny + 1));
3477
+ const dvy = new Float64Array(w1 * (ny + 1));
3478
+ const svx = new Float64Array(w1 * (ny + 1));
3479
+ const svy = new Float64Array(w1 * (ny + 1));
3480
+ let x0 = Infinity;
3481
+ let y0 = Infinity;
3482
+ let x1 = -Infinity;
3483
+ let y1 = -Infinity;
3484
+ for (let j = 0; j <= ny; j++) {
3485
+ for (let i = 0; i <= nx; i++) {
3486
+ const k = j * w1 + i;
3487
+ const sx = sr.x + sr.width * i / nx;
3488
+ const sy = sr.y + sr.height * j / ny;
3489
+ const d = f({ x: sx, y: sy });
3490
+ if (!d || !Number.isFinite(d.x) || !Number.isFinite(d.y)) return empty;
3491
+ dvx[k] = d.x;
3492
+ dvy[k] = d.y;
3493
+ svx[k] = sx;
3494
+ svy[k] = sy;
3495
+ if (d.x < x0) x0 = d.x;
3496
+ if (d.y < y0) y0 = d.y;
3497
+ if (d.x > x1) x1 = d.x;
3498
+ if (d.y > y1) y1 = d.y;
3499
+ }
3500
+ }
3501
+ const lim = 1 << 20;
3502
+ const bx0 = Math.floor(Math.max(-lim, x0)) - 1;
3503
+ const by0 = Math.floor(Math.max(-lim, y0)) - 1;
3504
+ const full = { x: bx0, y: by0, width: Math.ceil(Math.min(lim, x1)) + 1 - bx0, height: Math.ceil(Math.min(lim, y1)) + 1 - by0 };
3505
+ const dst = options.clip ? intersect(full, options.clip) : full;
3506
+ if (!dst) return empty;
3507
+ if (!options.clip) checkBudget(dst);
3508
+ const triCount = nx * ny * 2;
3509
+ const tris = new Int32Array(triCount * 3);
3510
+ for (let j = 0, t = 0; j < ny; j++) {
3511
+ for (let i = 0; i < nx; i++) {
3512
+ const a = j * w1 + i;
3513
+ tris[t++] = a;
3514
+ tris[t++] = a + 1;
3515
+ tris[t++] = a + w1 + 1;
3516
+ tris[t++] = a;
3517
+ tris[t++] = a + w1 + 1;
3518
+ tris[t++] = a + w1;
3519
+ }
3520
+ }
3521
+ const tx0 = Math.floor(dst.x / _chunkCRMAXIUVcjs.TILE);
3522
+ const ty0 = Math.floor(dst.y / _chunkCRMAXIUVcjs.TILE);
3523
+ const cols = Math.floor((dst.x + dst.width - 1) / _chunkCRMAXIUVcjs.TILE) - tx0 + 1;
3524
+ const rows = Math.floor((dst.y + dst.height - 1) / _chunkCRMAXIUVcjs.TILE) - ty0 + 1;
3525
+ const bins = Array.from({ length: cols * rows }, () => []);
3526
+ for (let k = 0; k < triCount; k++) {
3527
+ const a = tris[3 * k];
3528
+ const b = tris[3 * k + 1];
3529
+ const c = tris[3 * k + 2];
3530
+ const tminx = Math.floor(Math.min(dvx[a], dvx[b], dvx[c]));
3531
+ const tminy = Math.floor(Math.min(dvy[a], dvy[b], dvy[c]));
3532
+ const tmaxx = Math.ceil(Math.max(dvx[a], dvx[b], dvx[c]));
3533
+ const tmaxy = Math.ceil(Math.max(dvy[a], dvy[b], dvy[c]));
3534
+ const cx0 = Math.max(0, Math.floor(Math.max(tminx, dst.x) / _chunkCRMAXIUVcjs.TILE) - tx0);
3535
+ const cy0 = Math.max(0, Math.floor(Math.max(tminy, dst.y) / _chunkCRMAXIUVcjs.TILE) - ty0);
3536
+ const cx1 = Math.min(cols - 1, Math.floor(Math.min(tmaxx, dst.x + dst.width - 1) / _chunkCRMAXIUVcjs.TILE) - tx0);
3537
+ const cy1 = Math.min(rows - 1, Math.floor(Math.min(tmaxy, dst.y + dst.height - 1) / _chunkCRMAXIUVcjs.TILE) - ty0);
3538
+ for (let cy = cy0; cy <= cy1; cy++) for (let cx = cx0; cx <= cx1; cx++) bins[cy * cols + cx].push(k);
3539
+ }
3540
+ const tiles = /* @__PURE__ */ new Map();
3541
+ const acc = new Float64Array(4);
3542
+ const one = new Float64Array(4);
3543
+ const n = ch === 4 ? 4 : 2;
3544
+ const count = (jx, jy) => interp === "nearest" ? 1 : Math.min(MAX_SS, Math.max(1, Math.round(Math.hypot(jx, jy))));
3545
+ for (let cy = 0; cy < rows; cy++) {
3546
+ for (let cx = 0; cx < cols; cx++) {
3547
+ const list = bins[cy * cols + cx];
3548
+ if (!list.length) continue;
3549
+ const ttx = tx0 + cx;
3550
+ const tty = ty0 + cy;
3551
+ const t = intersect({ x: ttx * _chunkCRMAXIUVcjs.TILE, y: tty * _chunkCRMAXIUVcjs.TILE, width: _chunkCRMAXIUVcjs.TILE, height: _chunkCRMAXIUVcjs.TILE }, dst);
3552
+ if (!t) continue;
3553
+ const tw = t.width;
3554
+ const th = t.height;
3555
+ const us = new Float64Array(tw * th).fill(NaN);
3556
+ const vs = new Float64Array(tw * th);
3557
+ const owner = new Int32Array(tw * th);
3558
+ const jac = new Float64Array(list.length * 4);
3559
+ const ssx = new Int32Array(list.length);
3560
+ const ssy = new Int32Array(list.length);
3561
+ for (let li = 0; li < list.length; li++) {
3562
+ const k = list[li];
3563
+ const a = tris[3 * k];
3564
+ const b = tris[3 * k + 1];
3565
+ const c = tris[3 * k + 2];
3566
+ const p0x = dvx[a];
3567
+ const p0y = dvy[a];
3568
+ const p1x = dvx[b];
3569
+ const p1y = dvy[b];
3570
+ const p2x = dvx[c];
3571
+ const p2y = dvy[c];
3572
+ const det = (p1x - p0x) * (p2y - p0y) - (p2x - p0x) * (p1y - p0y);
3573
+ ssx[li] = 1;
3574
+ ssy[li] = 1;
3575
+ if (Math.abs(det) < 1e-12) continue;
3576
+ const d1x = svx[b] - svx[a];
3577
+ const d1y = svy[b] - svy[a];
3578
+ const d2x = svx[c] - svx[a];
3579
+ const d2y = svy[c] - svy[a];
3580
+ const l1x = (p2y - p0y) / det;
3581
+ const l1y = (p0x - p2x) / det;
3582
+ const l2x = (p0y - p1y) / det;
3583
+ const l2y = (p1x - p0x) / det;
3584
+ const cap = (vx, vy) => {
3585
+ const l = Math.hypot(vx, vy);
3586
+ return l > MAX_SS ? [vx * MAX_SS / l, vy * MAX_SS / l] : [vx, vy];
3587
+ };
3588
+ const jx = cap(l1x * d1x + l2x * d2x, l1x * d1y + l2x * d2y);
3589
+ const jy = cap(l1y * d1x + l2y * d2x, l1y * d1y + l2y * d2y);
3590
+ const cnx = count(jx[0], jx[1]);
3591
+ const cny = count(jy[0], jy[1]);
3592
+ if (cnx * cny > 1) {
3593
+ jac[li * 4] = jx[0];
3594
+ jac[li * 4 + 1] = jx[1];
3595
+ jac[li * 4 + 2] = jy[0];
3596
+ jac[li * 4 + 3] = jy[1];
3597
+ ssx[li] = cnx;
3598
+ ssy[li] = cny;
3599
+ }
3600
+ const rx0 = Math.max(t.x, Math.floor(Math.min(p0x, p1x, p2x) - 0.5));
3601
+ const ry0 = Math.max(t.y, Math.floor(Math.min(p0y, p1y, p2y) - 0.5));
3602
+ const rx1 = Math.min(t.x + tw, Math.ceil(Math.max(p0x, p1x, p2x) + 0.5));
3603
+ const ry1 = Math.min(t.y + th, Math.ceil(Math.max(p0y, p1y, p2y) + 0.5));
3604
+ const eps = -1e-9;
3605
+ const ay0 = step === 1 ? ry0 : ry0 + ((t.y - ry0) % step + step) % step;
3606
+ const ax0 = step === 1 ? rx0 : rx0 + ((t.x - rx0) % step + step) % step;
3607
+ for (let y = ay0; y < ry1; y += step) {
3608
+ const py = y + 0.5;
3609
+ for (let x = ax0; x < rx1; x += step) {
3610
+ const px = x + 0.5;
3611
+ const l1 = ((px - p0x) * (p2y - p0y) - (p2x - p0x) * (py - p0y)) / det;
3612
+ const l2 = ((p1x - p0x) * (py - p0y) - (px - p0x) * (p1y - p0y)) / det;
3613
+ const l0 = 1 - l1 - l2;
3614
+ if (l0 < eps || l1 < eps || l2 < eps) continue;
3615
+ const o = (y - t.y) * tw + (x - t.x);
3616
+ us[o] = l0 * svx[a] + l1 * svx[b] + l2 * svx[c];
3617
+ vs[o] = l0 * svy[a] + l1 * svy[b] + l2 * svy[c];
3618
+ owner[o] = li;
3619
+ }
3620
+ }
3621
+ }
3622
+ let fx0 = Infinity;
3623
+ let fy0 = Infinity;
3624
+ let fx1 = -Infinity;
3625
+ let fy1 = -Infinity;
3626
+ for (let o = 0; o < us.length; o++) {
3627
+ const u = us[o];
3628
+ if (Number.isNaN(u)) continue;
3629
+ const li = owner[o];
3630
+ const ex = 0.5 * (Math.abs(jac[li * 4]) + Math.abs(jac[li * 4 + 2]));
3631
+ const ey = 0.5 * (Math.abs(jac[li * 4 + 1]) + Math.abs(jac[li * 4 + 3]));
3632
+ if (u - ex < fx0) fx0 = u - ex;
3633
+ if (vs[o] - ey < fy0) fy0 = vs[o] - ey;
3634
+ if (u + ex > fx1) fx1 = u + ex;
3635
+ if (vs[o] + ey > fy1) fy1 = vs[o] + ey;
3636
+ }
3637
+ if (fx0 > fx1) continue;
3638
+ const foot = intersect({ x: Math.floor(fx0) - 3, y: Math.floor(fy0) - 3, width: Math.ceil(fx1) - Math.floor(fx0) + 6, height: Math.ceil(fy1) - Math.floor(fy0) + 6 }, sr);
3639
+ if (!foot || !hasTilesIn(src, foot)) continue;
3640
+ const win = readWindow(src, sr, foot);
3641
+ const out = new Uint8ClampedArray(_chunkCRMAXIUVcjs.TILE * _chunkCRMAXIUVcjs.TILE * ch);
3642
+ if (def) out.fill(def);
3643
+ let any = false;
3644
+ const ox = ttx * _chunkCRMAXIUVcjs.TILE;
3645
+ const oy = tty * _chunkCRMAXIUVcjs.TILE;
3646
+ const pointAt = (o, into) => {
3647
+ const li = owner[o];
3648
+ const cnx = ssx[li];
3649
+ const cny = ssy[li];
3650
+ if (cnx * cny === 1) {
3651
+ sample(win, interp, us[o] - 0.5, vs[o] - 0.5, 1, 1, into);
3652
+ return;
3653
+ }
3654
+ for (let c = 0; c < n; c++) into[c] = 0;
3655
+ const j0 = jac[li * 4];
3656
+ const j1 = jac[li * 4 + 1];
3657
+ const j2 = jac[li * 4 + 2];
3658
+ const j3 = jac[li * 4 + 3];
3659
+ for (let sy = 0; sy < cny; sy++) {
3660
+ const tt = (sy + 0.5) / cny - 0.5;
3661
+ for (let sx = 0; sx < cnx; sx++) {
3662
+ const s = (sx + 0.5) / cnx - 0.5;
3663
+ sample(win, "bilinear", us[o] + s * j0 + tt * j2 - 0.5, vs[o] + s * j1 + tt * j3 - 0.5, 1, 1, one);
3664
+ for (let c = 0; c < n; c++) into[c] += one[c];
3665
+ }
3666
+ }
3667
+ const k = 1 / (cnx * cny);
3668
+ for (let c = 0; c < n; c++) into[c] *= k;
3669
+ };
3670
+ if (step === 1) {
3671
+ for (let o = 0; o < us.length; o++) {
3672
+ if (Number.isNaN(us[o])) continue;
3673
+ pointAt(o, acc);
3674
+ const x = t.x + o % tw;
3675
+ const y = t.y + Math.floor(o / tw);
3676
+ if (store(out, ((y - oy) * _chunkCRMAXIUVcjs.TILE + (x - ox)) * ch, acc, ch, def)) any = true;
3677
+ }
3678
+ } else {
3679
+ for (let by = 0; by < th; by += step) {
3680
+ for (let bx = 0; bx < tw; bx += step) {
3681
+ const o = by * tw + bx;
3682
+ if (Number.isNaN(us[o])) continue;
3683
+ pointAt(o, acc);
3684
+ const first = ((t.y + by - oy) * _chunkCRMAXIUVcjs.TILE + (t.x + bx - ox)) * ch;
3685
+ if (!store(out, first, acc, ch, def)) continue;
3686
+ any = true;
3687
+ for (let yy = by; yy < Math.min(th, by + step); yy++) {
3688
+ const row = ((t.y + yy - oy) * _chunkCRMAXIUVcjs.TILE + (t.x - ox)) * ch;
3689
+ for (let xx = bx; xx < Math.min(tw, bx + step); xx++) for (let c = 0; c < ch; c++) out[row + xx * ch + c] = out[first + c];
3690
+ }
3691
+ }
3692
+ }
3693
+ }
3694
+ if (!any) continue;
3695
+ const tile = _chunkCRMAXIUVcjs.finishTile.call(void 0, out, ch, def);
3696
+ if (tile) tiles.set(_chunkCRMAXIUVcjs.tileKey.call(void 0, ttx, tty), tile);
3697
+ }
3698
+ }
3699
+ return assemble(src, tiles);
3700
+ }
3701
+ function compositeSurfaceOver(base, top) {
3702
+ if (top.channels !== 4) throw new Error("compositeSurfaceOver: top must be RGBA");
3703
+ if (!top.tiles.size) return base;
3704
+ const ch = base.channels;
3705
+ const tiles = new Map(base.tiles);
3706
+ for (const [key, t] of top.tiles) {
3707
+ const under = base.tiles.get(key);
3708
+ if (!under && ch === 4) {
3709
+ tiles.set(key, t);
3710
+ continue;
3711
+ }
3712
+ const d = new Uint8ClampedArray(_chunkCRMAXIUVcjs.TILE * _chunkCRMAXIUVcjs.TILE * ch);
3713
+ if (under) d.set(under.data);
3714
+ else if (base.defaultValue) d.fill(base.defaultValue);
3715
+ const s = t.data;
3716
+ if (ch === 4) {
3717
+ for (let i = 0; i < d.length; i += 4) {
3718
+ const ta = s[i + 3] / 255;
3719
+ if (ta <= 0) continue;
3720
+ if (ta >= 1) {
3721
+ d[i] = s[i];
3722
+ d[i + 1] = s[i + 1];
3723
+ d[i + 2] = s[i + 2];
3724
+ d[i + 3] = 255;
3725
+ continue;
3726
+ }
3727
+ const da = d[i + 3] / 255;
3728
+ const oa = ta + da * (1 - ta);
3729
+ for (let c = 0; c < 3; c++) d[i + c] = (s[i + c] * ta + d[i + c] * da * (1 - ta)) / oa;
3730
+ d[i + 3] = oa * 255;
3731
+ }
3732
+ } else {
3733
+ for (let p = 0, i = 0; p < d.length; p++, i += 4) {
3734
+ const ta = s[i + 3] / 255;
3735
+ if (ta > 0) d[p] = s[i] * ta + d[p] * (1 - ta);
3736
+ }
3737
+ }
3738
+ const tile = _chunkCRMAXIUVcjs.finishTile.call(void 0, d, ch, base.defaultValue);
3739
+ if (tile) tiles.set(key, tile);
3740
+ else tiles.delete(key);
3741
+ }
3742
+ return new (0, _chunkCRMAXIUVcjs.TiledSurface)(ch, tiles, base.defaultValue);
3743
+ }
3744
+
2816
3745
  // src/raster/zlib.ts
2817
3746
  var LENGTH_BASE = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258];
2818
3747
  var LENGTH_EXTRA = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];
@@ -2851,13 +3780,13 @@ function fixedTables() {
2851
3780
  return [fixedLit, fixedDist];
2852
3781
  }
2853
3782
  var BitReader = (_class2 = class {
2854
- constructor(data) {;_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);
3783
+ constructor(data) {;_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);
2855
3784
  this.data = data;
2856
3785
  }
2857
3786
 
2858
- __init20() {this.pos = 0}
2859
- __init21() {this.bit = 0}
2860
- __init22() {this.bits = 0}
3787
+ __init22() {this.pos = 0}
3788
+ __init23() {this.bit = 0}
3789
+ __init24() {this.bits = 0}
2861
3790
  need(n) {
2862
3791
  while (this.bits < n) {
2863
3792
  if (this.pos >= this.data.length) throw new ZlibError("Unexpected end of compressed data");
@@ -2890,13 +3819,13 @@ var BitReader = (_class2 = class {
2890
3819
  }
2891
3820
  }, _class2);
2892
3821
  var Output = (_class3 = class {
2893
- constructor(hint, max) {;_class3.prototype.__init23.call(this);
3822
+ constructor(hint, max) {;_class3.prototype.__init25.call(this);
2894
3823
  this.max = max;
2895
3824
  this.buf = new Uint8Array(Math.max(1024, Math.min(hint, max)));
2896
3825
  }
2897
3826
 
2898
3827
 
2899
- __init23() {this.len = 0}
3828
+ __init25() {this.len = 0}
2900
3829
  ensure(n) {
2901
3830
  if (this.len + n > this.max) throw new ZlibError(`Decompressed data exceeds ${this.max} bytes`);
2902
3831
  if (this.len + n <= this.buf.length) return;
@@ -3016,10 +3945,10 @@ function inflate(data, options = {}) {
3016
3945
  }
3017
3946
  var BitWriter = (_class4 = class {
3018
3947
 
3019
- __init24() {this.len = 0}
3020
- __init25() {this.bit = 0}
3021
- __init26() {this.bits = 0}
3022
- constructor(hint) {;_class4.prototype.__init24.call(this);_class4.prototype.__init25.call(this);_class4.prototype.__init26.call(this);
3948
+ __init26() {this.len = 0}
3949
+ __init27() {this.bit = 0}
3950
+ __init28() {this.bits = 0}
3951
+ constructor(hint) {;_class4.prototype.__init26.call(this);_class4.prototype.__init27.call(this);_class4.prototype.__init28.call(this);
3023
3952
  this.buf = new Uint8Array(Math.max(1024, hint));
3024
3953
  }
3025
3954
  grow() {
@@ -3525,7 +4454,7 @@ function decodePng(bytes, options = {}) {
3525
4454
  lines[dst + x] = r & 255;
3526
4455
  }
3527
4456
  }
3528
- const sample = (y, i) => {
4457
+ const sample2 = (y, i) => {
3529
4458
  const row = y * stride;
3530
4459
  if (depth === 8) return lines[row + i];
3531
4460
  if (depth === 16) return lines[row + i * 2];
@@ -3544,36 +4473,36 @@ function decodePng(bytes, options = {}) {
3544
4473
  for (let x = 0; x < width; x++) {
3545
4474
  const d = (y * width + x) * channels;
3546
4475
  if (type === 0) {
3547
- const v = sample(y, x);
4476
+ const v = sample2(y, x);
3548
4477
  if (gray) out[d] = v;
3549
4478
  else {
3550
4479
  out[d] = out[d + 1] = out[d + 2] = v;
3551
4480
  out[d + 3] = v === trnsGray && trns ? 0 : 255;
3552
4481
  }
3553
4482
  } else if (type === 2) {
3554
- const r = sample(y, x * 3);
3555
- const g = sample(y, x * 3 + 1);
3556
- const b = sample(y, x * 3 + 2);
4483
+ const r = sample2(y, x * 3);
4484
+ const g = sample2(y, x * 3 + 1);
4485
+ const b = sample2(y, x * 3 + 2);
3557
4486
  out[d] = r;
3558
4487
  out[d + 1] = g;
3559
4488
  out[d + 2] = b;
3560
4489
  out[d + 3] = trnsRgb && r === trnsRgb[0] && g === trnsRgb[1] && b === trnsRgb[2] ? 0 : 255;
3561
4490
  } else if (type === 3) {
3562
- const i = sample(y, x);
4491
+ const i = sample2(y, x);
3563
4492
  if (!palette || i * 3 + 2 >= palette.length) throw new Error("PNG palette index out of range.");
3564
4493
  out[d] = palette[i * 3];
3565
4494
  out[d + 1] = palette[i * 3 + 1];
3566
4495
  out[d + 2] = palette[i * 3 + 2];
3567
4496
  out[d + 3] = trns && i < trns.length ? trns[i] : 255;
3568
4497
  } else if (type === 4) {
3569
- const v = sample(y, x * 2);
4498
+ const v = sample2(y, x * 2);
3570
4499
  out[d] = out[d + 1] = out[d + 2] = v;
3571
- out[d + 3] = sample(y, x * 2 + 1);
4500
+ out[d + 3] = sample2(y, x * 2 + 1);
3572
4501
  } else {
3573
- out[d] = sample(y, x * 4);
3574
- out[d + 1] = sample(y, x * 4 + 1);
3575
- out[d + 2] = sample(y, x * 4 + 2);
3576
- out[d + 3] = sample(y, x * 4 + 3);
4502
+ out[d] = sample2(y, x * 4);
4503
+ out[d + 1] = sample2(y, x * 4 + 1);
4504
+ out[d + 2] = sample2(y, x * 4 + 2);
4505
+ out[d + 3] = sample2(y, x * 4 + 3);
3577
4506
  }
3578
4507
  }
3579
4508
  }
@@ -3708,5 +4637,16 @@ function pngDataUrl(width, height, data, channels = 4) {
3708
4637
 
3709
4638
 
3710
4639
 
3711
- exports.DIRECT_GAUSSIAN_MAX_SIGMA = DIRECT_GAUSSIAN_MAX_SIGMA; exports.gaussianBlur = gaussianBlur; exports.flattenLayers = flattenLayers; exports.findLayer = findLayer; exports.mapLayer = mapLayer; exports.insertLayer = insertLayer; exports.isLayerLocked = isLayerLocked; exports.DEFAULT_GLOBAL_LIGHT = DEFAULT_GLOBAL_LIGHT; exports.LAYER_EFFECT_KINDS = LAYER_EFFECT_KINDS; exports.layerEffectLabel = layerEffectLabel; exports.isLayerEffectKind = isLayerEffectKind; exports.defaultEffectGradient = defaultEffectGradient; exports.newEffectId = newEffectId; exports.defaultLayerEffect = defaultLayerEffect; exports.hasActiveEffects = hasActiveEffects; exports.MAX_EFFECT_REACH = MAX_EFFECT_REACH; exports.effectReach = effectReach; exports.effectsMargin = effectsMargin; exports.effectsScale = effectsScale; exports.scaleLayerEffect = scaleLayerEffect; exports.parseEffectColor = parseEffectColor; exports.effectColorHex = effectColorHex; exports.LayerEffectError = LayerEffectError; exports.validateEffectGradient = validateEffectGradient; exports.layerEffectFields = layerEffectFields; exports.validateLayerEffect = validateLayerEffect; exports.mergeLayerEffect = mergeLayerEffect; exports.validateLayerEffects = validateLayerEffects; exports.normalizeLayerEffects = normalizeLayerEffects; exports.effectsFingerprint = effectsFingerprint; exports.PatternTile = PatternTile; exports.PatternPlacement = PatternPlacement; exports.builtinPatternIds = builtinPatternIds; exports.builtinPattern = builtinPattern; exports.hashNoise = hashNoise; exports.CURVE_LUT_SIZE = CURVE_LUT_SIZE; exports.curveLut = curveLut; exports.STROKE_CHAMFER_MAX = STROKE_CHAMFER_MAX; exports.contourLut = contourLut; exports.activeEffectItems = activeEffectItems; exports.effectsAreLocal = effectsAreLocal; exports.buildEffectMaps = buildEffectMaps; exports.gradientT = gradientT; exports.compositeLayerEffects = compositeLayerEffects; exports.renderLayerEffects = renderLayerEffects; exports.blendTile = blendTile; exports.RasterCompositor = RasterCompositor; exports.changedTiles = changedTiles; exports.ZlibError = ZlibError; exports.inflateRaw = inflateRaw; exports.adler32 = adler32; exports.inflate = inflate; exports.deflateRaw = deflateRaw; exports.deflate = deflate; exports.encodePng = encodePng; exports.isPng = isPng; exports.decodePng = decodePng; exports.bytesToBase64 = bytesToBase64; exports.base64ToBytes = base64ToBytes; exports.parseDataUrl = parseDataUrl; exports.pngDataUrl = pngDataUrl;
3712
- //# sourceMappingURL=chunk-T422YCHR.cjs.map
4640
+
4641
+
4642
+
4643
+
4644
+
4645
+
4646
+
4647
+
4648
+
4649
+
4650
+
4651
+ exports.DIRECT_GAUSSIAN_MAX_SIGMA = DIRECT_GAUSSIAN_MAX_SIGMA; exports.gaussianBlur = gaussianBlur; exports.flattenLayers = flattenLayers; exports.findLayer = findLayer; exports.mapLayer = mapLayer; exports.insertLayer = insertLayer; exports.isLayerLocked = isLayerLocked; exports.DEFAULT_GLOBAL_LIGHT = DEFAULT_GLOBAL_LIGHT; exports.LAYER_EFFECT_KINDS = LAYER_EFFECT_KINDS; exports.layerEffectLabel = layerEffectLabel; exports.isLayerEffectKind = isLayerEffectKind; exports.defaultEffectGradient = defaultEffectGradient; exports.newEffectId = newEffectId; exports.defaultLayerEffect = defaultLayerEffect; exports.hasActiveEffects = hasActiveEffects; exports.MAX_EFFECT_REACH = MAX_EFFECT_REACH; exports.effectReach = effectReach; exports.effectsMargin = effectsMargin; exports.effectsScale = effectsScale; exports.scaleLayerEffect = scaleLayerEffect; exports.parseEffectColor = parseEffectColor; exports.effectColorHex = effectColorHex; exports.LayerEffectError = LayerEffectError; exports.validateEffectGradient = validateEffectGradient; exports.layerEffectFields = layerEffectFields; exports.validateLayerEffect = validateLayerEffect; exports.mergeLayerEffect = mergeLayerEffect; exports.validateLayerEffects = validateLayerEffects; exports.normalizeLayerEffects = normalizeLayerEffects; exports.effectsFingerprint = effectsFingerprint; exports.PatternTile = PatternTile; exports.PatternPlacement = PatternPlacement; exports.builtinPatternIds = builtinPatternIds; exports.builtinPattern = builtinPattern; exports.hashNoise = hashNoise; exports.CURVE_LUT_SIZE = CURVE_LUT_SIZE; exports.curveLut = curveLut; exports.STROKE_CHAMFER_MAX = STROKE_CHAMFER_MAX; exports.contourLut = contourLut; exports.activeEffectItems = activeEffectItems; exports.effectsAreLocal = effectsAreLocal; exports.buildEffectMaps = buildEffectMaps; exports.patchEffectMaps = patchEffectMaps; exports.gradientT = gradientT; exports.compositeLayerEffects = compositeLayerEffects; exports.renderLayerEffects = renderLayerEffects; exports.blendTile = blendTile; exports.RasterCompositor = RasterCompositor; exports.changedTiles = changedTiles; exports.INTERPOLATIONS = INTERPOLATIONS; exports.isInterpolation = isInterpolation; exports.MAX_TRANSFORM_PIXELS = MAX_TRANSFORM_PIXELS; exports.TransformTooLargeError = TransformTooLargeError; exports.keysWeight = keysWeight; exports.reduceSurface = reduceSurface; exports.transformedBounds = transformedBounds; exports.transformSurface = transformSurface; exports.warpSurface = warpSurface; exports.compositeSurfaceOver = compositeSurfaceOver; exports.ZlibError = ZlibError; exports.inflateRaw = inflateRaw; exports.adler32 = adler32; exports.inflate = inflate; exports.deflateRaw = deflateRaw; exports.deflate = deflate; exports.encodePng = encodePng; exports.isPng = isPng; exports.decodePng = decodePng; exports.bytesToBase64 = bytesToBase64; exports.base64ToBytes = base64ToBytes; exports.parseDataUrl = parseDataUrl; exports.pngDataUrl = pngDataUrl;
4652
+ //# sourceMappingURL=chunk-WT6ZAWJP.cjs.map