@pixerate/editor 0.134.0 → 0.136.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 (113) hide show
  1. package/dist/animation-editor/index.cjs +58 -55
  2. package/dist/animation-editor/index.cjs.map +1 -1
  3. package/dist/animation-editor/index.d.cts +8 -5
  4. package/dist/animation-editor/index.d.ts +8 -5
  5. package/dist/animation-editor/index.js +5 -2
  6. package/dist/animation-editor/index.js.map +1 -1
  7. package/dist/{bezier-J8i4uqSH.d.cts → bezier-CdccFsF8.d.cts} +1 -1
  8. package/dist/{bezier-lNEOp0Jx.d.ts → bezier-DG9qNZQV.d.ts} +1 -1
  9. package/dist/canvas/index.d.cts +10 -7
  10. package/dist/canvas/index.d.ts +10 -7
  11. package/dist/{chunk-Z2H7KECK.cjs → chunk-2R3UW57U.cjs} +13 -2
  12. package/dist/chunk-2R3UW57U.cjs.map +1 -0
  13. package/dist/{chunk-ESIWZMMK.js → chunk-6QQR4LKE.js} +2 -2
  14. package/dist/chunk-A3BVTI3G.js +150 -0
  15. package/dist/chunk-A3BVTI3G.js.map +1 -0
  16. package/dist/{chunk-T6TV6HY6.cjs → chunk-B2CUCM7Y.cjs} +36 -36
  17. package/dist/{chunk-T6TV6HY6.cjs.map → chunk-B2CUCM7Y.cjs.map} +1 -1
  18. package/dist/chunk-ECCXGELC.cjs +727 -0
  19. package/dist/chunk-ECCXGELC.cjs.map +1 -0
  20. package/dist/{chunk-OXSV64JX.js → chunk-G6IKY6PL.js} +4 -4
  21. package/dist/chunk-I52DRGGJ.js +727 -0
  22. package/dist/chunk-I52DRGGJ.js.map +1 -0
  23. package/dist/{chunk-6CTZAGZ2.js → chunk-ILYFOJUN.js} +56 -1
  24. package/dist/chunk-ILYFOJUN.js.map +1 -0
  25. package/dist/{chunk-YAFS2QFZ.cjs → chunk-JLGNZMUV.cjs} +82 -82
  26. package/dist/{chunk-YAFS2QFZ.cjs.map → chunk-JLGNZMUV.cjs.map} +1 -1
  27. package/dist/{chunk-7RJ6P7MI.js → chunk-KZXLZCQ7.js} +2 -2
  28. package/dist/{chunk-HHTCDFZC.js → chunk-MAHQC3SK.js} +13 -2
  29. package/dist/chunk-MAHQC3SK.js.map +1 -0
  30. package/dist/{chunk-FWEO3HSL.js → chunk-PQQF5KOW.js} +8 -8
  31. package/dist/chunk-Q6OUXEK3.cjs +150 -0
  32. package/dist/chunk-Q6OUXEK3.cjs.map +1 -0
  33. package/dist/{chunk-P3RQ5UJE.cjs → chunk-UTQKC66X.cjs} +4 -4
  34. package/dist/{chunk-P3RQ5UJE.cjs.map → chunk-UTQKC66X.cjs.map} +1 -1
  35. package/dist/{chunk-J3B45HTA.cjs → chunk-XB25WOC2.cjs} +6 -6
  36. package/dist/{chunk-J3B45HTA.cjs.map → chunk-XB25WOC2.cjs.map} +1 -1
  37. package/dist/{chunk-NVTHUPJ6.cjs → chunk-YT3JL7YM.cjs} +71 -16
  38. package/dist/chunk-YT3JL7YM.cjs.map +1 -0
  39. package/dist/effects/index.d.cts +7 -4
  40. package/dist/effects/index.d.ts +7 -4
  41. package/dist/{export-BGdT02aL.d.cts → export-BOheWw2R.d.cts} +13 -5
  42. package/dist/{export-Dng22YB8.d.ts → export-ByKKIA2S.d.ts} +13 -5
  43. package/dist/{export-KzubBKo7.d.cts → export-CEYeRQXH.d.cts} +1 -1
  44. package/dist/{export-DMeG6E06.d.ts → export-Ds7zgGD8.d.ts} +1 -1
  45. package/dist/extensions/index.cjs +3 -3
  46. package/dist/extensions/index.cjs.map +1 -1
  47. package/dist/extensions/index.js +2 -2
  48. package/dist/generation/index.cjs +150 -945
  49. package/dist/generation/index.cjs.map +1 -1
  50. package/dist/generation/index.d.cts +3 -423
  51. package/dist/generation/index.d.ts +3 -423
  52. package/dist/generation/index.js +59 -854
  53. package/dist/generation/index.js.map +1 -1
  54. package/dist/grammar/index.cjs +3 -3
  55. package/dist/grammar/index.cjs.map +1 -1
  56. package/dist/grammar/index.js +2 -2
  57. package/dist/{helpers-Coa4e2j_.d.ts → helpers--ns3W2D7.d.ts} +7 -1
  58. package/dist/{helpers-DHl28yLO.d.cts → helpers-BVkU4oUi.d.cts} +7 -1
  59. package/dist/image-editor/index.cjs +742 -647
  60. package/dist/image-editor/index.cjs.map +1 -1
  61. package/dist/image-editor/index.d.cts +29 -11
  62. package/dist/image-editor/index.d.ts +29 -11
  63. package/dist/image-editor/index.js +107 -12
  64. package/dist/image-editor/index.js.map +1 -1
  65. package/dist/index.cjs +28 -28
  66. package/dist/index.cjs.map +1 -1
  67. package/dist/index.js +36 -36
  68. package/dist/{opentype-Dfcx6wFx.d.ts → opentype-DfoVYgmG.d.ts} +1 -1
  69. package/dist/{opentype-BWR7Qv8W.d.cts → opentype-yi-Kz4ND.d.cts} +1 -1
  70. package/dist/paint/index.cjs +10 -2
  71. package/dist/paint/index.cjs.map +1 -1
  72. package/dist/paint/index.d.cts +2 -2
  73. package/dist/paint/index.d.ts +2 -2
  74. package/dist/paint/index.js +9 -1
  75. package/dist/paint-editor/index.cjs +10 -7
  76. package/dist/paint-editor/index.cjs.map +1 -1
  77. package/dist/paint-editor/index.d.cts +10 -7
  78. package/dist/paint-editor/index.d.ts +10 -7
  79. package/dist/paint-editor/index.js +5 -2
  80. package/dist/paint-editor/index.js.map +1 -1
  81. package/dist/{pathfinder-D8KQ6blQ.d.cts → pathfinder-7JkMwYvC.d.cts} +1 -1
  82. package/dist/{pathfinder-Celbi3e6.d.ts → pathfinder-GM3UWdBZ.d.ts} +1 -1
  83. package/dist/{pool-BfuxBKTd.d.cts → pool-04qp8iW4.d.cts} +1 -1
  84. package/dist/{pool-8JZGWHvR.d.ts → pool-CkTxlLMC.d.ts} +1 -1
  85. package/dist/provenance-DmlcgdzT.d.cts +426 -0
  86. package/dist/provenance-uh5r2TQ8.d.ts +426 -0
  87. package/dist/{rand-BaqEOs1Y.d.ts → rand-BszBST4s.d.ts} +31 -1
  88. package/dist/{rand-DdpFzCo6.d.cts → rand-DOH_aMvm.d.cts} +31 -1
  89. package/dist/{svg-pwXWq6s2.d.cts → svg-BDDKvWWY.d.cts} +2 -2
  90. package/dist/{svg-CxxqG3_W.d.ts → svg-rV6_HPmn.d.ts} +2 -2
  91. package/dist/{tools-3EBjR91b.d.cts → tools-BAjSbTdY.d.cts} +1 -1
  92. package/dist/{tools-y1M6O3UT.d.ts → tools-DPYerqeR.d.ts} +1 -1
  93. package/dist/vector/index.cjs +2684 -1860
  94. package/dist/vector/index.cjs.map +1 -1
  95. package/dist/vector/index.d.cts +313 -71
  96. package/dist/vector/index.d.ts +313 -71
  97. package/dist/vector/index.js +4700 -3876
  98. package/dist/vector/index.js.map +1 -1
  99. package/dist/video-editor/index.d.cts +7 -4
  100. package/dist/video-editor/index.d.ts +7 -4
  101. package/dist/{warp-Ceqdz7kj.d.cts → warp-DQh9R7Ie.d.cts} +1 -1
  102. package/dist/{warp-C1gwu2G_.d.ts → warp-XVL6SpSh.d.ts} +1 -1
  103. package/package.json +1 -1
  104. package/skills/pixerate-image-editor/SKILL.md +4 -4
  105. package/skills/pixerate-vector/SKILL.md +20 -1
  106. package/dist/chunk-6CTZAGZ2.js.map +0 -1
  107. package/dist/chunk-HHTCDFZC.js.map +0 -1
  108. package/dist/chunk-NVTHUPJ6.cjs.map +0 -1
  109. package/dist/chunk-Z2H7KECK.cjs.map +0 -1
  110. /package/dist/{chunk-ESIWZMMK.js.map → chunk-6QQR4LKE.js.map} +0 -0
  111. /package/dist/{chunk-OXSV64JX.js.map → chunk-G6IKY6PL.js.map} +0 -0
  112. /package/dist/{chunk-7RJ6P7MI.js.map → chunk-KZXLZCQ7.js.map} +0 -0
  113. /package/dist/{chunk-FWEO3HSL.js.map → chunk-PQQF5KOW.js.map} +0 -0
@@ -363,7 +363,7 @@ import {
363
363
  writePsd,
364
364
  xyToTempTint,
365
365
  xyToUv
366
- } from "../chunk-ESIWZMMK.js";
366
+ } from "../chunk-6QQR4LKE.js";
367
367
  import {
368
368
  parseCssColor
369
369
  } from "../chunk-CTTF4KYV.js";
@@ -439,21 +439,25 @@ import {
439
439
  } from "../chunk-GX332W2C.js";
440
440
  import {
441
441
  DEFAULT_RETOUCH,
442
+ IDENTITY_CLONE_TRANSFORM,
442
443
  RETOUCH_SAMPLES,
443
444
  RegionPixelSource,
444
445
  RetouchDabStroke,
445
446
  SPOT_HEAL_TYPES,
446
447
  TONE_RANGES,
447
448
  TilePixelSource,
449
+ TransformedPixelSource,
448
450
  applyRetouchToTile,
449
451
  applyToneToDeepTile,
450
452
  bestOffset,
451
453
  boxBlurPixels,
454
+ cloneSamplePoint,
452
455
  contentAwareFill,
453
456
  dilateMask,
454
457
  dodgeBurn,
455
458
  dodgeBurnCurve,
456
459
  healPixels,
460
+ isIdentityCloneTransform,
457
461
  luma,
458
462
  maskBounds,
459
463
  membraneFill,
@@ -471,7 +475,7 @@ import {
471
475
  spotHealPixels,
472
476
  spotHealWindow,
473
477
  toneOf
474
- } from "../chunk-6CTZAGZ2.js";
478
+ } from "../chunk-ILYFOJUN.js";
475
479
  import {
476
480
  BrushstrokeCache,
477
481
  brushstrokeDataUrl,
@@ -806,7 +810,8 @@ import {
806
810
  warpMeshParamAt,
807
811
  warpMeshRows,
808
812
  warpPresetMesh
809
- } from "../chunk-HHTCDFZC.js";
813
+ } from "../chunk-MAHQC3SK.js";
814
+ import "../chunk-A3BVTI3G.js";
810
815
  import "../chunk-YGJIER2R.js";
811
816
  import "../chunk-KHNZ6MOU.js";
812
817
  import {
@@ -818,6 +823,8 @@ import {
818
823
  resolveEffectValues
819
824
  } from "../chunk-QFSTQHZY.js";
820
825
  import "../chunk-4FX5ACVG.js";
826
+ import "../chunk-FPENXAEJ.js";
827
+ import "../chunk-P6ODPZ4W.js";
821
828
  import "../chunk-ZRJMJIQU.js";
822
829
  import "../chunk-TGD52FEZ.js";
823
830
 
@@ -4180,7 +4187,7 @@ var ImageEditorController = class {
4180
4187
  activeLayerId: null,
4181
4188
  activeTarget: "pixels",
4182
4189
  outputOpacity: 1,
4183
- paint: { brush: { ...DEFAULT_BRUSH }, foreground: "#000000", background: "#ffffff", paint: { type: "color", color: "#000000" }, mixer: { ...DEFAULT_MIXER }, mixerLoad: EMPTY_MIXER_LOAD, retouch: { ...DEFAULT_RETOUCH }, cloneSource: null },
4190
+ paint: { brush: { ...DEFAULT_BRUSH }, foreground: "#000000", background: "#ffffff", paint: { type: "color", color: "#000000" }, mixer: { ...DEFAULT_MIXER }, mixerLoad: EMPTY_MIXER_LOAD, retouch: { ...DEFAULT_RETOUCH }, cloneSource: null, cloneTransform: { ...IDENTITY_CLONE_TRANSFORM } },
4184
4191
  fit: options.fit ?? "margin"
4185
4192
  };
4186
4193
  if (options.image instanceof Object && "width" in options.image) {
@@ -6038,7 +6045,8 @@ var ImageEditorController = class {
6038
6045
  mixer: options.mixer ? normalizeMixer({ ...cur.mixer, ...options.mixer }) : cur.mixer,
6039
6046
  mixerLoad: cur.mixerLoad,
6040
6047
  retouch,
6041
- cloneSource
6048
+ cloneSource,
6049
+ cloneTransform: cur.cloneTransform
6042
6050
  };
6043
6051
  this.state.paint = next;
6044
6052
  this.notify();
@@ -6079,6 +6087,24 @@ var ImageEditorController = class {
6079
6087
  this.notify();
6080
6088
  return source;
6081
6089
  }
6090
+ /**
6091
+ * The Clone Source panel's transform for the Clone Stamp and Healing Brush: `scaleX` / `scaleY`
6092
+ * (factors, 0.01..10 in size; negative flips) and `rotate` (degrees, clockwise), merged into the
6093
+ * current one; `null` resets it. View state, no undo. Returns the transform.
6094
+ */
6095
+ setCloneTransform(t) {
6096
+ const cur = this.state.paint.cloneTransform;
6097
+ const next = t ? { ...cur, ...t } : { ...IDENTITY_CLONE_TRANSFORM };
6098
+ for (const k of ["scaleX", "scaleY"]) {
6099
+ const v = next[k];
6100
+ if (!Number.isFinite(v) || Math.abs(v) < 0.01 || Math.abs(v) > 10) throw new LayerOperationError(`${k} must be a scale factor between 0.01 and 10 in size (negative flips), not ${String(v)}.`);
6101
+ }
6102
+ if (!Number.isFinite(next.rotate)) throw new LayerOperationError("rotate must be a number of degrees.");
6103
+ next.rotate = ((next.rotate + 180) % 360 + 360) % 360 - 180;
6104
+ this.state.paint = { ...this.state.paint, cloneTransform: next };
6105
+ this.notify();
6106
+ return next;
6107
+ }
6082
6108
  /** D: black foreground, white background. */
6083
6109
  resetPaintColors() {
6084
6110
  this.setPaintOptions({ foreground: "#000000", background: "#ffffff" });
@@ -6261,7 +6287,9 @@ var ImageEditorController = class {
6261
6287
  if (!cs) throw new LayerOperationError(`The ${tool === "clone" ? "Clone Stamp" : "Healing Brush"} needs a source point; Alt-click the canvas, call set_clone_source, or pass source { x, y }.`);
6262
6288
  let offset = { x: 0, y: 0 };
6263
6289
  let first = { x: 0, y: 0 };
6264
- const paint = () => ({ kind: "source", source, dx: offset.x, dy: offset.y });
6290
+ const xf = this.state.paint.cloneTransform;
6291
+ const transformed = isIdentityCloneTransform(xf) ? null : new TransformedPixelSource(source, (x, y) => cloneSamplePoint(xf, cs, { x: cs.x - offset.x, y: cs.y - offset.y }, x, y));
6292
+ const paint = () => transformed ? { kind: "source", source: transformed, dx: 0, dy: 0 } : { kind: "source", source, dx: offset.x, dy: offset.y };
6265
6293
  return {
6266
6294
  kind: "coverage",
6267
6295
  coverage,
@@ -6275,7 +6303,7 @@ var ImageEditorController = class {
6275
6303
  finalPaint: tool === "heal" ? (cov) => {
6276
6304
  if (!cov.bounds) return null;
6277
6305
  const g = pad(cov.bounds, 2);
6278
- const src = readSourceRegion(source, g, offset.x, offset.y);
6306
+ const src = transformed ? readSourceRegion(transformed, g) : readSourceRegion(source, g, offset.x, offset.y);
6279
6307
  const dst = readSourceRegion(source, g);
6280
6308
  return { kind: "source", source: new RegionPixelSource(g, healPixels(g.width, g.height, src, dst, covered(cov, g))), dx: 0, dy: 0 };
6281
6309
  } : void 0,
@@ -7088,7 +7116,10 @@ var ImageEditorController = class {
7088
7116
  if (s.activeTool !== "clone" && s.activeTool !== "heal") return null;
7089
7117
  const cs = s.paint.cloneSource;
7090
7118
  if (!cs) return null;
7091
- if (cursor && cs.offset && s.paint.retouch.aligned) return { x: cursor.x + cs.offset.x, y: cursor.y + cs.offset.y };
7119
+ if (cursor && cs.offset && s.paint.retouch.aligned) {
7120
+ const [x, y] = cloneSamplePoint(s.paint.cloneTransform, cs, { x: cs.x - cs.offset.x, y: cs.y - cs.offset.y }, cursor.x, cursor.y);
7121
+ return { x, y };
7122
+ }
7092
7123
  return { x: cs.x, y: cs.y };
7093
7124
  }
7094
7125
  async render(targetCanvas, options) {
@@ -10719,6 +10750,30 @@ var RETOUCH_OPTION_CONTROLS = [
10719
10750
  { id: "strength", label: "Strength", section: "layer", min: 0, max: 1, step: 0.01, default: 0.5, decimals: 0, track: plain2, displayScale: 100, unit: "%", tools: ["smudge", "blur", "sharpen"] },
10720
10751
  { id: "historySteps", label: "Steps back", section: "layer", min: 0, max: 50, step: 1, default: 0, decimals: 0, track: plain2, unit: "", tools: ["history"] }
10721
10752
  ];
10753
+ var CLONE_TRANSFORM_CONTROLS = [
10754
+ { id: "width", label: "Source W", section: "layer", min: 1, max: 400, step: 1, default: 100, decimals: 0, track: plain2, unit: "%" },
10755
+ { id: "height", label: "Source H", section: "layer", min: 1, max: 400, step: 1, default: 100, decimals: 0, track: plain2, unit: "%" },
10756
+ { id: "angle", label: "Source angle", section: "layer", min: -180, max: 180, step: 1, default: 0, decimals: 0, track: plain2, unit: "\xB0" }
10757
+ ];
10758
+ function cloneTransformView(controller) {
10759
+ const t = controller.getState().paint.cloneTransform;
10760
+ return {
10761
+ width: Math.round(Math.abs(t.scaleX) * 100),
10762
+ height: Math.round(Math.abs(t.scaleY) * 100),
10763
+ angle: t.rotate,
10764
+ flipH: t.scaleX < 0,
10765
+ flipV: t.scaleY < 0,
10766
+ identity: t.scaleX === 1 && t.scaleY === 1 && t.rotate === 0
10767
+ };
10768
+ }
10769
+ function setCloneTransformValue(controller, id, value) {
10770
+ const t = controller.getState().paint.cloneTransform;
10771
+ if (id === "width") controller.setCloneTransform({ scaleX: Math.sign(t.scaleX) * (value ?? 100) / 100 });
10772
+ else if (id === "height") controller.setCloneTransform({ scaleY: Math.sign(t.scaleY) * (value ?? 100) / 100 });
10773
+ else if (id === "angle") controller.setCloneTransform({ rotate: value ?? 0 });
10774
+ else if (id === "flipH") controller.setCloneTransform({ scaleX: -t.scaleX });
10775
+ else controller.setCloneTransform({ scaleY: -t.scaleY });
10776
+ }
10722
10777
  var RETOUCH_CHOICES = [
10723
10778
  {
10724
10779
  id: "sample",
@@ -11526,12 +11581,12 @@ function createImageRetouchTools(controller) {
11526
11581
  const getOptions = {
11527
11582
  name: "get_retouch_options",
11528
11583
  title: "Get retouch options",
11529
- description: "Reads the retouching tools' options (aligned, sample, spotType, range, exposure, protectTones, spongeMode, vibrance, strength, historySteps) and the clone source ({x, y, offset} or null; offset is the aligned offset the last clone or heal stroke fixed: an aligned stroke samples at the brush plus offset, which the editors show as a crosshair). Call it before clone_stamp or heal_brush without a source to see where they will sample.",
11584
+ description: "Reads the retouching tools' options (aligned, sample, spotType, range, exposure, protectTones, spongeMode, vibrance, strength, historySteps), the Clone Source transform ({scaleX, scaleY, rotate}) and the clone source ({x, y, offset} or null; offset is the aligned offset the last clone or heal stroke fixed: an aligned stroke samples at the brush plus offset, which the editors show as a crosshair). Call it before clone_stamp or heal_brush without a source to see where they will sample.",
11530
11585
  inputSchema: { type: "object", properties: {}, additionalProperties: false },
11531
11586
  annotations: { title: "Get retouch options", ...READ6 },
11532
11587
  handler: () => {
11533
- const { retouch, cloneSource } = controller.getState().paint;
11534
- return { options: { ...retouch }, cloneSource: cloneSource ? { ...cloneSource } : null };
11588
+ const { retouch, cloneSource, cloneTransform } = controller.getState().paint;
11589
+ return { options: { ...retouch }, cloneSource: cloneSource ? { ...cloneSource } : null, cloneTransform: { ...cloneTransform } };
11535
11590
  }
11536
11591
  };
11537
11592
  const setOptions = {
@@ -11580,7 +11635,40 @@ function createImageRetouchTools(controller) {
11580
11635
  return controller.setCloneSource(checkSource(controller, { x: args.x, y: args.y }));
11581
11636
  }
11582
11637
  };
11583
- return [cloneStamp, healBrush, spotHeal, smudge, dodge, burn, spongeTool, blurTool, sharpenTool, historyBrush, getOptions, setOptions, setSource];
11638
+ const setTransform = {
11639
+ name: "set_clone_transform",
11640
+ title: "Transform the clone source",
11641
+ description: "Photoshop's Clone Source panel: the Clone Stamp and Healing Brush lay the source scaled by `scaleX` / `scaleY` (percent, default 100; negative or the flip flags mirror it) and rotated by `rotate` degrees clockwise about the stroke's start. Merged into the current transform; reset true goes back to 100 %, 0\xB0. Use it to clone a reflection, a smaller copy or a tilted patch. View state, not an undo step. Returns the transform ({scaleX, scaleY, rotate} as factors and degrees).",
11642
+ inputSchema: {
11643
+ type: "object",
11644
+ properties: {
11645
+ scaleX: { type: "number", description: "Width in percent of the source (1..1000; negative flips horizontally)." },
11646
+ scaleY: { type: "number", description: "Height in percent of the source (1..1000; negative flips vertically)." },
11647
+ rotate: { type: "number", description: "Rotation in degrees, clockwise (-180..180)." },
11648
+ flipHorizontal: { type: "boolean", description: "Mirror the source left to right (negates the width scale; default false)." },
11649
+ flipVertical: { type: "boolean", description: "Mirror the source top to bottom (negates the height scale; default false)." },
11650
+ reset: { type: "boolean", description: "Back to 100 %, no flip, 0\xB0 (default false); other arguments are not allowed with it." }
11651
+ },
11652
+ additionalProperties: false
11653
+ },
11654
+ annotations: { title: "Transform the clone source", ...WRITE5, idempotentHint: false },
11655
+ handler: (args) => {
11656
+ if (args.reset === true) {
11657
+ if (Object.keys(args).some((k) => k !== "reset")) throw new LayerOperationError("Give either reset true or transform values, not both.");
11658
+ return controller.setCloneTransform(null);
11659
+ }
11660
+ const cur = controller.getState().paint.cloneTransform;
11661
+ const next = {};
11662
+ if (args.scaleX !== void 0) next.scaleX = args.scaleX / 100;
11663
+ if (args.scaleY !== void 0) next.scaleY = args.scaleY / 100;
11664
+ if (args.rotate !== void 0) next.rotate = args.rotate;
11665
+ if (args.flipHorizontal === true) next.scaleX = -(next.scaleX ?? cur.scaleX);
11666
+ if (args.flipVertical === true) next.scaleY = -(next.scaleY ?? cur.scaleY);
11667
+ if (!Object.keys(next).length) throw new LayerOperationError("Pass scaleX, scaleY, rotate, flipHorizontal or flipVertical, or reset true.");
11668
+ return controller.setCloneTransform(next);
11669
+ }
11670
+ };
11671
+ return [cloneStamp, healBrush, spotHeal, smudge, dodge, burn, spongeTool, blurTool, sharpenTool, historyBrush, getOptions, setOptions, setSource, setTransform];
11584
11672
  }
11585
11673
  function pick(args, keys) {
11586
11674
  const out = {};
@@ -15003,6 +15091,7 @@ export {
15003
15091
  BRUSH_OPTION_CONTROLS,
15004
15092
  BUILTIN_PROFILES,
15005
15093
  BrushstrokeCache,
15094
+ CLONE_TRANSFORM_CONTROLS,
15006
15095
  COLOR_MODE_OPTIONS,
15007
15096
  CoverageMap,
15008
15097
  D50,
@@ -15056,6 +15145,7 @@ export {
15056
15145
  HIDE,
15057
15146
  HISTOGRAM_BINS,
15058
15147
  HUE_RANGE_LABELS,
15148
+ IDENTITY_CLONE_TRANSFORM,
15059
15149
  IDENTITY_MATRIX3,
15060
15150
  IMAGE_ADJUSTMENT_CONTROLS,
15061
15151
  IMAGE_CROP_PRESETS,
@@ -15190,6 +15280,7 @@ export {
15190
15280
  TilePixelSource,
15191
15281
  TiledSurface,
15192
15282
  TransformTooLargeError,
15283
+ TransformedPixelSource,
15193
15284
  TypeToolGesture,
15194
15285
  U_MAX,
15195
15286
  VIBRANCE_GREY,
@@ -15297,7 +15388,9 @@ export {
15297
15388
  clampControlValue,
15298
15389
  clampCropToImage,
15299
15390
  cleanMixer,
15391
+ cloneSamplePoint,
15300
15392
  cloneSourceLabel,
15393
+ cloneTransformView,
15301
15394
  collectTiles,
15302
15395
  colorBalanceChannel,
15303
15396
  colorModePlanes,
@@ -15516,6 +15609,7 @@ export {
15516
15609
  isContentsDecoded,
15517
15610
  isDefaultDepthMask,
15518
15611
  isGradientPaint,
15612
+ isIdentityCloneTransform,
15519
15613
  isIdentityTransform,
15520
15614
  isInterpolation,
15521
15615
  isLayerEffectKind,
@@ -15785,6 +15879,7 @@ export {
15785
15879
  serializeLayersExternal,
15786
15880
  serializePatterns,
15787
15881
  serializeSelection,
15882
+ setCloneTransformValue,
15788
15883
  setControlPath,
15789
15884
  setLayerEffects,
15790
15885
  setLayerEffectsEnabled,