@pixerate/editor 0.249.0 → 0.251.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 (158) hide show
  1. package/dist/agent/index.cjs +40 -41
  2. package/dist/agent/index.js +9 -10
  3. package/dist/animation/index.cjs +6 -7
  4. package/dist/animation/index.js +5 -6
  5. package/dist/animation-editor/index.cjs +124 -123
  6. package/dist/animation-editor/index.js +15 -14
  7. package/dist/brushes/index.cjs +1406 -0
  8. package/dist/brushes/index.d.cts +12 -0
  9. package/dist/brushes/index.d.ts +12 -0
  10. package/dist/brushes/index.js +1406 -0
  11. package/dist/brushes/migrate.d.cts +17 -0
  12. package/dist/brushes/migrate.d.ts +17 -0
  13. package/dist/brushes/normalize.d.cts +15 -0
  14. package/dist/brushes/normalize.d.ts +15 -0
  15. package/dist/brushes/presets.d.cts +12 -0
  16. package/dist/brushes/presets.d.ts +12 -0
  17. package/dist/brushes/resolve.d.cts +56 -0
  18. package/dist/brushes/resolve.d.ts +56 -0
  19. package/dist/brushes/schema.d.cts +29 -0
  20. package/dist/brushes/schema.d.ts +29 -0
  21. package/dist/brushes/types.d.cts +323 -0
  22. package/dist/brushes/types.d.ts +323 -0
  23. package/dist/{brushstrokeRender-T3JZST44.js → brushstrokeRender-5PYSKZIJ.js} +9 -8
  24. package/dist/{brushstrokeRender-GCKK7V2I.cjs → brushstrokeRender-7FLLSQEC.cjs} +15 -14
  25. package/dist/canvas/index.cjs +120 -65
  26. package/dist/canvas/index.d.cts +1 -0
  27. package/dist/canvas/index.d.ts +1 -0
  28. package/dist/canvas/index.js +88 -33
  29. package/dist/canvas/stickers.d.cts +35 -0
  30. package/dist/canvas/stickers.d.ts +35 -0
  31. package/dist/chart/index.cjs +159 -160
  32. package/dist/chart/index.js +9 -10
  33. package/dist/{chunk-RXZL4NG5.js → chunk-226QDRO3.js} +1 -1
  34. package/dist/{chunk-DOIU7VJG.js → chunk-2ZJ4DT3M.js} +1 -1
  35. package/dist/{chunk-XZNU4DUX.cjs → chunk-3NS5C7FB.cjs} +76 -76
  36. package/dist/{chunk-UTI5IITZ.cjs → chunk-4ZC5QJE2.cjs} +3 -3
  37. package/dist/{chunk-L3JFOTBQ.js → chunk-5E2Q7ZHI.js} +1 -1
  38. package/dist/{chunk-6BIDVPED.js → chunk-5JNA6LLY.js} +1 -1
  39. package/dist/{chunk-RD7RX52G.cjs → chunk-5UEFBM2M.cjs} +207 -18
  40. package/dist/{chunk-WA44NKPF.js → chunk-62Z5WLRA.js} +1 -1
  41. package/dist/{chunk-BVRRIW7F.js → chunk-6GRUVGKU.js} +3 -3
  42. package/dist/{chunk-QARCM66V.js → chunk-6ZZKRH7R.js} +3 -3
  43. package/dist/{chunk-BP6KSGVD.js → chunk-7272D3K2.js} +4 -6
  44. package/dist/{chunk-O75V4ZS3.js → chunk-7P6VF3FG.js} +2 -2
  45. package/dist/{chunk-AU6MWQKZ.js → chunk-ABL7IWFZ.js} +1 -1
  46. package/dist/{chunk-5RH3VXAK.js → chunk-APX63ILU.js} +4 -100
  47. package/dist/{chunk-W7L4HUT2.cjs → chunk-CJ6TBL2N.cjs} +16 -16
  48. package/dist/{chunk-7PT4RJL5.cjs → chunk-EUIDTZNQ.cjs} +111 -113
  49. package/dist/{chunk-CXXXAZ7H.js → chunk-F6R67I3A.js} +1 -1
  50. package/dist/{chunk-I7NJPHWV.cjs → chunk-FQPUF2W2.cjs} +35 -606
  51. package/dist/{chunk-D5KGAO4Z.js → chunk-GCVFEPJG.js} +2 -573
  52. package/dist/{chunk-LEQKZGQI.js → chunk-GOBOCZZI.js} +1 -1
  53. package/dist/{chunk-PZP2SZIZ.js → chunk-GYMMNCFT.js} +3 -3
  54. package/dist/{chunk-NUTMINJZ.cjs → chunk-H7ET2ISK.cjs} +52 -52
  55. package/dist/chunk-HS6QDWDF.cjs +1029 -0
  56. package/dist/{chunk-T7KQEMAE.cjs → chunk-HUAISCUX.cjs} +18 -18
  57. package/dist/{chunk-YGQVCQTG.js → chunk-ILP77UD6.js} +1 -1
  58. package/dist/{chunk-GHCSC2WP.cjs → chunk-ISIO63Q5.cjs} +21 -15
  59. package/dist/{chunk-S6OT6CTS.cjs → chunk-IWEVV63O.cjs} +31 -33
  60. package/dist/{chunk-OFH6Q67U.js → chunk-JA57JIT5.js} +9 -3
  61. package/dist/{chunk-LP2MCSBE.cjs → chunk-JFHBXNR2.cjs} +88 -88
  62. package/dist/{chunk-IOFVM3L3.cjs → chunk-JPEHXIB5.cjs} +10 -10
  63. package/dist/chunk-JSDND7DF.cjs +173 -0
  64. package/dist/{chunk-36ZTV7WO.js → chunk-L6Y7TSQ4.js} +1 -1
  65. package/dist/{chunk-KYX7NZ5V.cjs → chunk-LFMKWGFL.cjs} +1 -1
  66. package/dist/{chunk-V6DT2CDH.js → chunk-M2TPMYJE.js} +1 -1
  67. package/dist/{chunk-LJZRHVZV.cjs → chunk-M5GLQQWG.cjs} +2 -2
  68. package/dist/{chunk-JEGJP4OW.js → chunk-MHLU6GRJ.js} +196 -7
  69. package/dist/{chunk-KMPM5JM5.js → chunk-MONXNVZK.js} +4 -6
  70. package/dist/chunk-MTKY6K3Q.js +1029 -0
  71. package/dist/{chunk-MOW3JMNG.cjs → chunk-N76AMOKE.cjs} +42 -42
  72. package/dist/{chunk-75K3W4D6.cjs → chunk-NKGB64CW.cjs} +16 -16
  73. package/dist/{chunk-SGPIVHJB.js → chunk-P3K2JCJA.js} +3 -3
  74. package/dist/chunk-PXDIAYB6.cjs +594 -0
  75. package/dist/{chunk-UBRJOIR5.js → chunk-QC3OXRE4.js} +9 -9
  76. package/dist/{chunk-QOBCBGGI.cjs → chunk-QKXO6JPP.cjs} +14 -14
  77. package/dist/{chunk-WLJZZHUZ.cjs → chunk-QLSGTCYT.cjs} +23 -23
  78. package/dist/{chunk-7YW7T5TJ.js → chunk-RHPSE2YR.js} +2 -2
  79. package/dist/{chunk-44BMJJVA.cjs → chunk-RUONPPMC.cjs} +8 -8
  80. package/dist/{chunk-LJRCU3BJ.cjs → chunk-SABJMH6M.cjs} +150 -15
  81. package/dist/{chunk-XWOLPNBW.cjs → chunk-SOSBOS5T.cjs} +22 -22
  82. package/dist/chunk-SZTI6EER.js +13 -0
  83. package/dist/{chunk-PPFJHTW5.cjs → chunk-TFF2GTGN.cjs} +22 -24
  84. package/dist/{chunk-2SMMZDMG.cjs → chunk-TLOGFIIV.cjs} +37 -37
  85. package/dist/chunk-TXFWZ5ZJ.js +594 -0
  86. package/dist/chunk-U67EN7GG.cjs +13 -0
  87. package/dist/{chunk-GXAK6Q5J.js → chunk-UFEDHACQ.js} +2 -2
  88. package/dist/{chunk-GA4EU4P3.cjs → chunk-UXETV2NC.cjs} +4 -4
  89. package/dist/{chunk-N4DFDI73.js → chunk-WKMUBATU.js} +1 -1
  90. package/dist/{chunk-3R5P3DVY.cjs → chunk-WRZ6C4TU.cjs} +6 -6
  91. package/dist/{chunk-EJLRBS5Q.js → chunk-WZOGDKCQ.js} +137 -2
  92. package/dist/{chunk-6ADHGQ73.js → chunk-YBAPT7NL.js} +2 -4
  93. package/dist/{chunk-K5DS2JTA.cjs → chunk-Z3BRH4JK.cjs} +6 -6
  94. package/dist/{chunk-XNZFVYC2.cjs → chunk-ZBCT5MEA.cjs} +7 -7
  95. package/dist/color/index.cjs +4 -6
  96. package/dist/color/index.js +7 -9
  97. package/dist/effects/helpers.d.cts +6 -0
  98. package/dist/effects/helpers.d.ts +6 -0
  99. package/dist/effects/index.cjs +62 -60
  100. package/dist/effects/index.js +5 -3
  101. package/dist/effects/tools.d.cts +6 -0
  102. package/dist/effects/tools.d.ts +6 -0
  103. package/dist/export/index.cjs +7 -8
  104. package/dist/export/index.js +6 -7
  105. package/dist/extensions/index.cjs +10 -11
  106. package/dist/extensions/index.js +9 -10
  107. package/dist/gradient/index.cjs +33 -34
  108. package/dist/gradient/index.js +4 -5
  109. package/dist/image-editor/effects.d.cts +1 -1
  110. package/dist/image-editor/effects.d.ts +1 -1
  111. package/dist/image-editor/index.cjs +887 -863
  112. package/dist/image-editor/index.d.cts +1 -0
  113. package/dist/image-editor/index.d.ts +1 -0
  114. package/dist/image-editor/index.js +69 -45
  115. package/dist/image-editor/stickers.d.cts +9 -0
  116. package/dist/image-editor/stickers.d.ts +9 -0
  117. package/dist/index.cjs +16 -17
  118. package/dist/index.js +10 -11
  119. package/dist/paint/index.cjs +6 -4
  120. package/dist/paint/index.js +21 -19
  121. package/dist/paint-editor/brushes.d.cts +1 -2
  122. package/dist/paint-editor/brushes.d.ts +1 -2
  123. package/dist/paint-editor/index.cjs +2199 -699
  124. package/dist/paint-editor/index.js +1577 -77
  125. package/dist/paint-editor/mark-settings.d.cts +104 -0
  126. package/dist/paint-editor/mark-settings.d.ts +104 -0
  127. package/dist/paint-editor/procedural.d.cts +2 -75
  128. package/dist/paint-editor/procedural.d.ts +2 -75
  129. package/dist/paint-editor/stickers.d.cts +1 -22
  130. package/dist/paint-editor/stickers.d.ts +1 -22
  131. package/dist/raster/index.cjs +2 -2
  132. package/dist/raster/index.js +9 -9
  133. package/dist/stickers/index.cjs +22 -16
  134. package/dist/stickers/index.d.cts +1 -1
  135. package/dist/stickers/index.d.ts +1 -1
  136. package/dist/stickers/index.js +14 -8
  137. package/dist/stickers/tools.d.cts +57 -1
  138. package/dist/stickers/tools.d.ts +57 -1
  139. package/dist/tokens/index.cjs +3 -4
  140. package/dist/tokens/index.js +2 -3
  141. package/dist/typography/index.cjs +7 -8
  142. package/dist/typography/index.js +2 -3
  143. package/dist/vector/index.cjs +1011 -977
  144. package/dist/vector/index.d.cts +1 -0
  145. package/dist/vector/index.d.ts +1 -0
  146. package/dist/vector/index.js +47 -13
  147. package/dist/vector/stickers.d.cts +11 -0
  148. package/dist/vector/stickers.d.ts +11 -0
  149. package/dist/video-editor/index.cjs +349 -350
  150. package/dist/video-editor/index.js +9 -10
  151. package/package.json +11 -1
  152. package/skills/pixerate-image-editor/SKILL.md +1 -1
  153. package/skills/pixerate-stickers/SKILL.md +13 -1
  154. package/dist/chunk-7AHBW2CQ.cjs +0 -200
  155. package/dist/chunk-F67XMVDI.js +0 -200
  156. package/dist/chunk-H4AOUUBE.cjs +0 -2635
  157. package/dist/chunk-J7T5QZ45.js +0 -2635
  158. package/dist/chunk-ZEYMKDYS.cjs +0 -269
@@ -1,16 +1,9 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9;
2
-
3
-
4
-
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7;
5
2
 
6
3
  var _chunk3K6HWEXZcjs = require('./chunk-3K6HWEXZ.cjs');
7
4
 
8
5
 
9
6
 
10
- var _chunkYQGCPL5Xcjs = require('./chunk-YQGCPL5X.cjs');
11
-
12
-
13
-
14
7
 
15
8
 
16
9
 
@@ -22,14 +15,6 @@ var _chunkYQGCPL5Xcjs = require('./chunk-YQGCPL5X.cjs');
22
15
  var _chunk2VX55NFMcjs = require('./chunk-2VX55NFM.cjs');
23
16
 
24
17
 
25
- var _chunkW5M3J7PVcjs = require('./chunk-W5M3J7PV.cjs');
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
18
 
34
19
 
35
20
  var _chunk474IQG74cjs = require('./chunk-474IQG74.cjs');
@@ -1093,545 +1078,6 @@ function coverageTileCoord(key) {
1093
1078
  return _chunk474IQG74cjs.tileCoord.call(void 0, key);
1094
1079
  }
1095
1080
 
1096
- // src/paint/grain.ts
1097
- var GRAIN_PATTERNS = ["smooth", "cold-pressed", "hot-pressed", "rough", "vellum", "laid", "ingres", "sanded", "canvas", "linen", "gesso"];
1098
- var GRAIN_TILE = 256;
1099
- var clamp01 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
1100
- function patternHeights(pattern, n, seed) {
1101
- const out = new Float32Array(n * n);
1102
- const salt = Math.imul(seed | 0, 2654435761) + 17;
1103
- if (pattern === "smooth") return out.fill(1);
1104
- const noise = (cx, cy, oct, s = 0) => new (0, _chunk3K6HWEXZcjs.TileableNoise)(n, cx, cy, oct, salt + s);
1105
- const k = n / GRAIN_TILE;
1106
- switch (pattern) {
1107
- case "cold-pressed": {
1108
- const base = noise(20 * k, 20 * k, 4);
1109
- const fine = noise(64 * k, 64 * k, 2, 3);
1110
- for (let y = 0; y < n; y++)
1111
- for (let x = 0; x < n; x++) out[y * n + x] = clamp01((base.at(x, y) - 0.5) * 1.8 + 0.5 + (fine.at(x, y) - 0.5) * 0.5 + (_chunk3K6HWEXZcjs.hash2.call(void 0, x, y, salt) - 0.5) * 0.12);
1112
- break;
1113
- }
1114
- case "hot-pressed": {
1115
- const base = noise(40 * k, 40 * k, 3);
1116
- for (let y = 0; y < n; y++) for (let x = 0; x < n; x++) out[y * n + x] = clamp01((base.at(x, y) - 0.5) * 1.1 + 0.6 + (_chunk3K6HWEXZcjs.hash2.call(void 0, x, y, salt) - 0.5) * 0.08);
1117
- break;
1118
- }
1119
- case "rough": {
1120
- const base = noise(10 * k, 10 * k, 5);
1121
- const blot = noise(28 * k, 28 * k, 2, 5);
1122
- for (let y = 0; y < n; y++)
1123
- for (let x = 0; x < n; x++) out[y * n + x] = clamp01((base.at(x, y) - 0.5) * 2.4 + 0.5 + (blot.at(x, y) - 0.5) * 0.7 + (_chunk3K6HWEXZcjs.hash2.call(void 0, x, y, salt) - 0.5) * 0.15);
1124
- break;
1125
- }
1126
- case "vellum": {
1127
- const base = noise(40 * k, 40 * k, 3);
1128
- for (let y = 0; y < n; y++) for (let x = 0; x < n; x++) out[y * n + x] = clamp01((base.at(x, y) - 0.5) * 1.6 + 0.55 + (_chunk3K6HWEXZcjs.hash2.call(void 0, x, y, salt) - 0.5) * 0.2);
1129
- break;
1130
- }
1131
- case "laid": {
1132
- const pulp = noise(32 * k, 32 * k, 3);
1133
- const chain = n / 8;
1134
- for (let y = 0; y < n; y++) {
1135
- const laid = 0.5 + 0.5 * Math.cos(2 * Math.PI * y / 4);
1136
- for (let x = 0; x < n; x++) {
1137
- const c = Math.abs((x + 0.5) % chain - chain / 2) / (chain / 2);
1138
- const chainLine = c > 0.94 ? -0.35 : 0;
1139
- out[y * n + x] = clamp01(0.3 + 0.5 * laid + chainLine + (pulp.at(x, y) - 0.5) * 0.6);
1140
- }
1141
- }
1142
- break;
1143
- }
1144
- case "ingres": {
1145
- const fibres = noise(64 * k, 12 * k, 3);
1146
- const base = noise(16 * k, 16 * k, 3, 7);
1147
- for (let y = 0; y < n; y++)
1148
- for (let x = 0; x < n; x++) {
1149
- const g = _chunk3K6HWEXZcjs.hash2.call(void 0, x, y, salt ^ 85);
1150
- out[y * n + x] = clamp01((fibres.at(x, y) - 0.5) * 1.5 + (base.at(x, y) - 0.5) * 0.7 + 0.55 + (g < 0.1 ? -0.3 : 0));
1151
- }
1152
- break;
1153
- }
1154
- case "sanded": {
1155
- const grit = noise(96 * k, 96 * k, 2);
1156
- for (let y = 0; y < n; y++)
1157
- for (let x = 0; x < n; x++) {
1158
- const h = _chunk3K6HWEXZcjs.hash2.call(void 0, x, y, salt);
1159
- out[y * n + x] = clamp01((grit.at(x, y) - 0.5) * 2.4 + 0.5 + (h - 0.5) * 0.7);
1160
- }
1161
- break;
1162
- }
1163
- case "canvas":
1164
- case "linen": {
1165
- const period = (pattern === "canvas" ? 8 : 5) * k;
1166
- const threads = Math.max(2, 2 * Math.round(n / period / 2));
1167
- const p = n / threads;
1168
- const slub = noise(threads, threads, 2, 11);
1169
- for (let y = 0; y < n; y++)
1170
- for (let x = 0; x < n; x++) {
1171
- const fx = (x + 0.5) / p;
1172
- const fy = (y + 0.5) / p;
1173
- const cx = Math.floor(fx);
1174
- const cy = Math.floor(fy);
1175
- const warp = Math.sin(Math.PI * (fx - cx));
1176
- const weft = Math.sin(Math.PI * (fy - cy));
1177
- const top = (cx + cy) % 2 === 0 ? warp : weft;
1178
- const irregular = pattern === "linen" ? (slub.at(x, y) - 0.5) * 0.5 : 0;
1179
- out[y * n + x] = clamp01(0.2 + 0.7 * top + irregular + (_chunk3K6HWEXZcjs.hash2.call(void 0, x, y, salt) - 0.5) * 0.15);
1180
- }
1181
- break;
1182
- }
1183
- case "gesso": {
1184
- const streaks = noise(2 * k, 28 * k, 3);
1185
- const tooth = noise(64 * k, 64 * k, 2, 13);
1186
- for (let y = 0; y < n; y++)
1187
- for (let x = 0; x < n; x++) out[y * n + x] = clamp01((streaks.at(x, y) - 0.5) * 1.8 + (tooth.at(x, y) - 0.5) * 0.9 + 0.55);
1188
- break;
1189
- }
1190
- }
1191
- return out;
1192
- }
1193
- var rawCache = /* @__PURE__ */ new Map();
1194
- function grainHeights(pattern, seed, size = GRAIN_TILE) {
1195
- const key = `${pattern}:${seed}:${size}`;
1196
- let h = rawCache.get(key);
1197
- if (!h) {
1198
- h = patternHeights(pattern, size, seed);
1199
- if (rawCache.size > 32) rawCache.delete(rawCache.keys().next().value);
1200
- rawCache.set(key, h);
1201
- }
1202
- return h;
1203
- }
1204
- var PaperGrain = (_class4 = class {
1205
- __init21() {this.size = GRAIN_TILE}
1206
-
1207
-
1208
-
1209
-
1210
-
1211
-
1212
- constructor(paper, media = "dry") {;_class4.prototype.__init21.call(this);
1213
- const raw = grainHeights(paper.pattern, paper.seed);
1214
- const t = paper[media];
1215
- this.flat = paper.pattern === "smooth";
1216
- if (t.contrast === 1 && !t.invert) this.heights = raw;
1217
- else {
1218
- const out = new Float32Array(raw.length);
1219
- for (let i = 0; i < raw.length; i++) {
1220
- const v = clamp01((raw[i] - 0.5) * t.contrast + 0.5);
1221
- out[i] = t.invert ? 1 - v : v;
1222
- }
1223
- this.heights = out;
1224
- }
1225
- this.scale = paper.scale;
1226
- this.mirror = paper.tiling === "mirror";
1227
- this.ox = _nullishCoalesce(_optionalChain([paper, 'access', _5 => _5.offset, 'optionalAccess', _6 => _6.x]), () => ( 0));
1228
- this.oy = _nullishCoalesce(_optionalChain([paper, 'access', _7 => _7.offset, 'optionalAccess', _8 => _8.y]), () => ( 0));
1229
- }
1230
- /** Tile cell index for a coordinate in grain pixels (mirrored on odd tiles when mirroring). */
1231
- wrap(v) {
1232
- const n = this.size;
1233
- if (!this.mirror) return (v % n + n) % n;
1234
- const p = (v % (2 * n) + 2 * n) % (2 * n);
1235
- return p < n ? p : 2 * n - 1 - p;
1236
- }
1237
- /** Height 0..1 at document position (x, y). */
1238
- at(x, y) {
1239
- const u = (x - this.ox) / this.scale - 0.5;
1240
- const v = (y - this.oy) / this.scale - 0.5;
1241
- const x0 = Math.floor(u);
1242
- const y0 = Math.floor(v);
1243
- const fx = u - x0;
1244
- const fy = v - y0;
1245
- const n = this.size;
1246
- const h = this.heights;
1247
- const a = this.wrap(x0);
1248
- const b = this.wrap(x0 + 1);
1249
- const c = this.wrap(y0) * n;
1250
- const d = this.wrap(y0 + 1) * n;
1251
- const top = h[c + a] + (h[c + b] - h[c + a]) * fx;
1252
- const bot = h[d + a] + (h[d + b] - h[d + a]) * fx;
1253
- return top + (bot - top) * fy;
1254
- }
1255
- }, _class4);
1256
- function grainCatch(h, depth, pressure) {
1257
- if (depth <= 0) return 1;
1258
- const t = depth * (0.75 - 0.65 * Math.min(1, Math.max(0, pressure)));
1259
- const u = clamp01((h - t + 0.18) / 0.36);
1260
- return 1 - depth + depth * u * u * (3 - 2 * u);
1261
- }
1262
- function strokeGrainCatch(h, depth, pressure) {
1263
- if (depth <= 0) return 1;
1264
- const p = Math.min(1, Math.max(0, pressure));
1265
- const amount = Math.min(1, depth * (1.4 - 0.6 * p));
1266
- const u = clamp01((h - 0.2 - 0.25 * (1 - p)) / 0.5);
1267
- return 1 - amount + amount * u * u * (3 - 2 * u);
1268
- }
1269
-
1270
- // src/paint/path-stroke.ts
1271
- var JITTER_SIZE = 1;
1272
- var JITTER_ANGLE = 2;
1273
- var JITTER_OPACITY = 3;
1274
- var JITTER_SCATTER = 4;
1275
- function lean(s) {
1276
- if (typeof s.altitude === "number" && Number.isFinite(s.altitude)) {
1277
- return { amount: 1 - Math.min(1, Math.max(0, s.altitude / (Math.PI / 2))), azimuth: _nullishCoalesce(s.azimuth, () => ( 0)) };
1278
- }
1279
- if (typeof s.tiltX === "number" || typeof s.tiltY === "number") {
1280
- const tx = (_nullishCoalesce(s.tiltX, () => ( 0))) * Math.PI / 180;
1281
- const ty = (_nullishCoalesce(s.tiltY, () => ( 0))) * Math.PI / 180;
1282
- if (tx === 0 && ty === 0) return { amount: 0, azimuth: 0 };
1283
- const az = Math.atan2(Math.tan(ty), Math.tan(tx));
1284
- const alt = Math.atan(1 / Math.hypot(Math.tan(tx), Math.tan(ty)));
1285
- return { amount: 1 - alt / (Math.PI / 2), azimuth: az };
1286
- }
1287
- return null;
1288
- }
1289
- function pathStrokeDabs(samples, options) {
1290
- const brush = normalizeBrush(options.brush);
1291
- const pts = options.closed && samples.length > 2 ? [...samples, samples[0]] : [...samples];
1292
- if (!pts.length) return [];
1293
- const tilt = _nullishCoalesce(options.tilt, () => ( {}));
1294
- const minSize = Math.min(1, Math.max(0, _nullishCoalesce(options.minSize, () => ( 0))));
1295
- let index = 0;
1296
- const t0 = _nullishCoalesce(_optionalChain([pts, 'access', _9 => _9.find, 'call', _10 => _10((s) => typeof s.t === "number" && Number.isFinite(s.t)), 'optionalAccess', _11 => _11.t]), () => ( null));
1297
- const dab = (x, y, p, l, dir, travel = 0, time = null, speed = null) => {
1298
- const pr = Math.min(1, Math.max(0, p));
1299
- const lean0 = _nullishCoalesce(_optionalChain([l, 'optionalAccess', _12 => _12.amount]), () => ( 0));
1300
- const size = brush.size * (brush.pressureSize ? minSize + (1 - minSize) * pr : 1) * (1 + 1.5 * (_nullishCoalesce(tilt.size, () => ( 0))) * lean0);
1301
- let angle = brush.angle * Math.PI / 180;
1302
- if (options.followPath) angle += dir;
1303
- if (tilt.followAzimuth && l) angle = -l.azimuth;
1304
- const roundness = Math.max(0.05, brush.roundness * (1 - 0.85 * (_nullishCoalesce(tilt.roundness, () => ( 0))) * lean0));
1305
- const op = brush.pressureOpacity ? pr : 1;
1306
- const i = index++;
1307
- const params = { travel, index: i, pressure: pr, lean: lean0, speed, direction: dir, time: time === null || t0 === null ? null : time - t0 };
1308
- let diameter = size;
1309
- let opacity = brush.opacity * op;
1310
- const j = options.jitter;
1311
- if (j) {
1312
- if (j.size) diameter *= Math.max(0.05, 1 + j.size * _chunk3K6HWEXZcjs.randSigned.call(void 0, j.seed, i, JITTER_SIZE));
1313
- if (j.angle) angle += j.angle * Math.PI * _chunk3K6HWEXZcjs.randSigned.call(void 0, j.seed, i, JITTER_ANGLE);
1314
- if (j.opacity) opacity *= 1 - j.opacity * (_chunk3K6HWEXZcjs.randSigned.call(void 0, j.seed, i, JITTER_OPACITY) * 0.5 + 0.5);
1315
- if (j.scatter) {
1316
- const off = j.scatter * diameter * _chunk3K6HWEXZcjs.randSigned.call(void 0, j.seed, i, JITTER_SCATTER);
1317
- x += Math.sin(dir) * off;
1318
- y += Math.cos(dir) * off;
1319
- }
1320
- }
1321
- return { x, y, radius: Math.max(0.5, diameter / 2), alpha: brush.flow, opacity, angle, roundness, params };
1322
- };
1323
- const out = [];
1324
- const pressure = (s) => typeof s.pressure === "number" && Number.isFinite(s.pressure) ? s.pressure : 1;
1325
- if (pts.length === 1) {
1326
- out.push(dab(pts[0].x, pts[0].y, pressure(pts[0]), lean(pts[0]), 0));
1327
- return out;
1328
- }
1329
- let carry = 0;
1330
- let along = 0;
1331
- const timeOf = (s) => typeof s.t === "number" && Number.isFinite(s.t) ? s.t : null;
1332
- out.push(dab(pts[0].x, pts[0].y, pressure(pts[0]), lean(pts[0]), Math.atan2(-(pts[1].y - pts[0].y), pts[1].x - pts[0].x), 0, timeOf(pts[0])));
1333
- for (let i = 0; i + 1 < pts.length; i++) {
1334
- const a = pts[i];
1335
- const b = pts[i + 1];
1336
- const dx = b.x - a.x;
1337
- const dy = b.y - a.y;
1338
- const len = Math.hypot(dx, dy);
1339
- if (len === 0) continue;
1340
- const dir = Math.atan2(-dy, dx);
1341
- const la = lean(a);
1342
- const lb = lean(b);
1343
- const ta = timeOf(a);
1344
- const tb = timeOf(b);
1345
- const speed = ta !== null && tb !== null && tb > ta ? len / (tb - ta) : null;
1346
- let t = carry;
1347
- for (; ; ) {
1348
- const f = t / len;
1349
- if (f > 1) break;
1350
- const p = pressure(a) + (pressure(b) - pressure(a)) * f;
1351
- const l = la && lb ? { amount: la.amount + (lb.amount - la.amount) * f, azimuth: la.azimuth + (lb.azimuth - la.azimuth) * f } : _nullishCoalesce(la, () => ( lb));
1352
- const size = brush.size * (brush.pressureSize ? minSize + (1 - minSize) * p : 1);
1353
- const step = Math.max(0.5, size * brush.spacing);
1354
- if (t > 0 || i > 0) out.push(dab(a.x + dx * f, a.y + dy * f, p, l, dir, along + t, ta !== null && tb !== null ? ta + (tb - ta) * f : null, speed));
1355
- t += step;
1356
- }
1357
- carry = t - len;
1358
- along += len;
1359
- }
1360
- return out;
1361
- }
1362
- function pathStrokeCoverage(samples, options) {
1363
- const brush = normalizeBrush(options.brush);
1364
- const coverage = new CoverageMap();
1365
- const dabs = pathStrokeDabs(samples, options);
1366
- const g = _optionalChain([options, 'access', _13 => _13.gradient, 'optionalAccess', _14 => _14.paint, 'access', _15 => _15.type]) === "gradient" ? options.gradient : null;
1367
- const sampler = g ? new PaintGradientSampler(resolvePaintGradient(g.paint, _nullishCoalesce(g.colors, () => ( { paint: "#000000", secondary: "#ffffff" }))), _nullishCoalesce(g.seed, () => ( 0))) : null;
1368
- const tipTable = _optionalChain([sampler, 'optionalAccess', _16 => _16.acrossTip]) ? sampler.tipTable(TIP_GRADIENT_STEPS) : null;
1369
- const scratch = { field: new Float32Array(0), sample: { rgb: [0, 0, 0], alpha: 1 } };
1370
- let buf = new Float32Array(0);
1371
- let bounds = null;
1372
- for (const d of dabs) {
1373
- const rect = dabRect(d, brush.hardness);
1374
- const n = rect.width * rect.height;
1375
- if (n <= 0) continue;
1376
- if (buf.length < n) buf = new Float32Array(n);
1377
- const vals = buf.subarray(0, n);
1378
- rasterizeDab(d, brush.hardness, rect, vals);
1379
- if (sampler) {
1380
- const { color, field } = gradientDabColor(sampler, tipTable, d, d.params, rect, vals, scratch);
1381
- coverage.accumulate(rect, vals, d.opacity, color, field);
1382
- } else coverage.accumulate(rect, vals, d.opacity);
1383
- if (!bounds) bounds = { ...rect };
1384
- else {
1385
- const x = Math.min(bounds.x, rect.x);
1386
- const y = Math.min(bounds.y, rect.y);
1387
- bounds = { x, y, width: Math.max(bounds.x + bounds.width, rect.x + rect.width) - x, height: Math.max(bounds.y + bounds.height, rect.y + rect.height) - y };
1388
- }
1389
- }
1390
- const grain = options.grain;
1391
- if (grain && grain.depth > 0 && dabs.length) {
1392
- const pressure = dabs.reduce((sum, d) => sum + (_nullishCoalesce(_optionalChain([d, 'access', _17 => _17.params, 'optionalAccess', _18 => _18.pressure]), () => ( 1))), 0) / dabs.length;
1393
- for (const [key, t] of coverage.tiles) {
1394
- const { tx, ty } = _chunk474IQG74cjs.tileCoord.call(void 0, key);
1395
- for (let y = 0, k = 0; y < _chunk474IQG74cjs.TILE; y++) {
1396
- const gy = ty * _chunk474IQG74cjs.TILE + y + 0.5;
1397
- for (let x = 0; x < _chunk474IQG74cjs.TILE; x++, k++) if (t[k] > 0) t[k] *= strokeGrainCatch(grain.at(tx * _chunk474IQG74cjs.TILE + x + 0.5, gy), grain.depth, pressure);
1398
- }
1399
- }
1400
- }
1401
- return { coverage, bounds, dabs: dabs.length };
1402
- }
1403
- function paintPathStroke(surface, samples, options) {
1404
- if (surface.channels !== 4) throw new Error("paintPathStroke paints RGBA surfaces (4 channels).");
1405
- const brush = normalizeBrush(options.brush);
1406
- const hex = (c) => "#" + [0, 1, 2].map((i) => Math.round(Math.min(255, Math.max(0, c[i]))).toString(16).padStart(2, "0")).join("");
1407
- let color = options.color;
1408
- if (_optionalChain([options, 'access', _19 => _19.paint, 'optionalAccess', _20 => _20.paint, 'access', _21 => _21.type]) === "color") {
1409
- const rgb = hexToPaintRgb(options.paint.paint.color).map((v) => Math.round(v * 255));
1410
- color = [rgb[0], rgb[1], rgb[2], color[3]];
1411
- }
1412
- const gradient = _optionalChain([options, 'access', _22 => _22.paint, 'optionalAccess', _23 => _23.paint, 'access', _24 => _24.type]) === "gradient" ? { ...options.paint, colors: _nullishCoalesce(options.paint.colors, () => ( { paint: hex(color), secondary: "#ffffff" })) } : null;
1413
- const { coverage, bounds, dabs } = pathStrokeCoverage(samples, { ...options, gradient });
1414
- if (!bounds) return { surface, bounds: null, dabs };
1415
- const offset = _nullishCoalesce(options.offset, () => ( { x: 0, y: 0 }));
1416
- const apply = {
1417
- mode: _nullishCoalesce(options.mode, () => ( "paint")),
1418
- color,
1419
- background: [0, 0, 0, 0],
1420
- opacity: brush.opacity,
1421
- blend: _nullishCoalesce(options.blend, () => ( brush.blend)),
1422
- lockTransparency: _nullishCoalesce(options.lockTransparency, () => ( false)),
1423
- selection: _nullishCoalesce(options.selection, () => ( null)),
1424
- offset
1425
- };
1426
- const tiles = new Map(surface.tiles);
1427
- for (const { tx, ty } of _chunk474IQG74cjs.tilesInRect.call(void 0, { x: bounds.x - offset.x, y: bounds.y - offset.y, width: bounds.width, height: bounds.height })) {
1428
- const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
1429
- const src = _optionalChain([surface, 'access', _25 => _25.tiles, 'access', _26 => _26.get, 'call', _27 => _27(key), 'optionalAccess', _28 => _28.data]);
1430
- const base = src && src.length === _chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4 ? src : new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4);
1431
- const t = _chunk474IQG74cjs.finishTile.call(void 0, applyStrokeToTile(coverage, base, 4, tx, ty, apply), 4, surface.defaultValue);
1432
- if (t) tiles.set(key, t);
1433
- else tiles.delete(key);
1434
- }
1435
- return { surface: new (0, _chunk474IQG74cjs.TiledSurface)(4, tiles, surface.defaultValue), bounds, dabs };
1436
- }
1437
-
1438
- // src/paint/brushstroke.ts
1439
- var DEFAULT_MAX_PIXELS = 4096 * 4096;
1440
- var isProfilePath = (input) => !Array.isArray(input) && typeof input === "object" && input !== null && "points" in input;
1441
- function profileAt(profile, f) {
1442
- if (!profile || !profile.length) return void 0;
1443
- if (profile.length === 1) return profile[0];
1444
- const u = Math.min(1, Math.max(0, f)) * (profile.length - 1);
1445
- const i = Math.min(profile.length - 2, Math.floor(u));
1446
- return profile[i] + (profile[i + 1] - profile[i]) * (u - i);
1447
- }
1448
- function brushstrokeSamples(input) {
1449
- if (!isProfilePath(input)) return input.map((s) => ({ ...s }));
1450
- const pts = input.points;
1451
- const lengths = [0];
1452
- for (let i = 1; i < pts.length; i++) lengths.push(lengths[i - 1] + Math.hypot(pts[i].x - pts[i - 1].x, pts[i].y - pts[i - 1].y));
1453
- const total = _nullishCoalesce(lengths.at(-1), () => ( 0));
1454
- return pts.map((p, i) => {
1455
- const f = total > 0 ? lengths[i] / total : pts.length > 1 ? i / (pts.length - 1) : 0;
1456
- const s = { x: p.x, y: p.y };
1457
- const pressure = profileAt(input.pressure, f);
1458
- const tiltX = profileAt(input.tiltX, f);
1459
- const tiltY = profileAt(input.tiltY, f);
1460
- if (pressure !== void 0) s.pressure = pressure;
1461
- if (tiltX !== void 0) s.tiltX = tiltX;
1462
- if (tiltY !== void 0) s.tiltY = tiltY;
1463
- return s;
1464
- });
1465
- }
1466
- var REFUSED_ENGINES = {
1467
- wet: "is a wet brush, and wet paint needs an area to flow in (paint it on a wet layer in the paint editor)",
1468
- mixer: "is a Mixer Brush, which picks up paint from under the tip and has none on a standalone stroke",
1469
- blender: "is a blender, which only moves paint that is already there",
1470
- smudge: "is a smudge brush, which only moves paint that is already there",
1471
- eraser: "is an eraser, which has nothing to remove on a standalone stroke"
1472
- };
1473
- function brushstrokeStrokeOptions(brush) {
1474
- if (!brush || typeof brush !== "object") throw new Error("A brushstroke needs a brush: tip settings ({ size, hardness, \u2026 }) or a paint brush preset.");
1475
- if (!("tip" in brush) || !brush.tip) return { brush: normalizeBrush(brush) };
1476
- const engine = _nullishCoalesce(brush.engine, () => ( "dab"));
1477
- if (engine !== "dab") {
1478
- const label = _nullishCoalesce(_nullishCoalesce(brush.name, () => ( brush.id)), () => ( "This brush"));
1479
- const why = _nullishCoalesce(REFUSED_ENGINES[engine], () => ( `uses the '${engine}' engine, which renderBrushstroke does not draw`));
1480
- throw new Error(`Brushstrokes render dry media only: '${label}' ${why}. Pick a dry brush (a dab-engine preset such as a pencil, pastel, charcoal, marker, ink or airbrush) or plain tip settings.`);
1481
- }
1482
- const d = _nullishCoalesce(brush.dynamics, () => ( {}));
1483
- const tilt = { size: _nullishCoalesce(d.tiltSize, () => ( 0)), roundness: _nullishCoalesce(d.tiltRoundness, () => ( 0)) };
1484
- return {
1485
- brush: normalizeBrush(brush.tip),
1486
- followPath: brush.rotation === "stroke",
1487
- minSize: _nullishCoalesce(d.minSize, () => ( 0)),
1488
- ...tilt.size || tilt.roundness ? { tilt } : {}
1489
- };
1490
- }
1491
- function isBrushstrokeBrush(brush) {
1492
- return !("tip" in brush) || !brush.tip || (_nullishCoalesce(brush.engine, () => ( "dab"))) === "dab";
1493
- }
1494
- var finite2 = (v) => typeof v === "number" && Number.isFinite(v);
1495
- function brushCharacterOf(brush) {
1496
- if (!("tip" in brush) || !brush.tip) return { grain: 0, size: 0, angle: 0, opacity: 0, scatter: 0 };
1497
- const d = _nullishCoalesce(brush.dynamics, () => ( {}));
1498
- const u = (v, hi = 1) => finite2(v) ? Math.min(hi, Math.max(0, v)) : 0;
1499
- return { grain: u(brush.grain), size: u(d.sizeJitter), angle: u(d.angleJitter), opacity: u(d.opacityJitter), scatter: u(d.scatter, 4) };
1500
- }
1501
- var papers = /* @__PURE__ */ new Map();
1502
- function paperGrain(paper) {
1503
- const pattern = _nullishCoalesce(paper.pattern, () => ( "sanded"));
1504
- const seed = finite2(paper.seed) ? Math.round(Math.abs(paper.seed)) : 1;
1505
- const scale = finite2(paper.scale) && paper.scale > 0 ? Math.min(8, Math.max(0.25, paper.scale)) : 1;
1506
- const key = `${pattern}:${seed}:${scale}`;
1507
- let g = papers.get(key);
1508
- if (!g) {
1509
- g = new PaperGrain({ pattern, seed, scale, tiling: "mirror", dry: { contrast: 1, invert: false }, wet: { contrast: 1, invert: false } });
1510
- if (papers.size > 16) papers.delete(papers.keys().next().value);
1511
- papers.set(key, g);
1512
- }
1513
- return g;
1514
- }
1515
- function renderBrushstroke(input, brush, options = {}) {
1516
- const strokeOptions = brushstrokeStrokeOptions(brush);
1517
- const samples = brushstrokeSamples(input);
1518
- for (const s of samples) if (!finite2(s.x) || !finite2(s.y)) throw new Error("Brushstroke samples need finite x and y.");
1519
- const solid = options.paint && !("type" in options.paint) ? options.paint.color : null;
1520
- const source = options.paint && "type" in options.paint ? options.paint : null;
1521
- const color = _nullishCoalesce(_nullishCoalesce(solid, () => ( options.color)), () => ( [0, 0, 0, 255]));
1522
- let scale = finite2(options.scale) && options.scale > 0 ? Math.min(_chunkYQGCPL5Xcjs.BRUSHSTROKE_MAX_SCALE, Math.max(_chunkYQGCPL5Xcjs.BRUSHSTROKE_MIN_SCALE, options.scale)) : 1;
1523
- if (!samples.length) return { image: { width: 0, height: 0, data: new Uint8ClampedArray(0) }, bounds: null, scale, dabs: 0 };
1524
- const tip = strokeOptions.brush;
1525
- const reach = tip.size * (1 + 1.5 * (_nullishCoalesce(_optionalChain([strokeOptions, 'access', _29 => _29.tilt, 'optionalAccess', _30 => _30.size]), () => ( 0)))) + 4;
1526
- let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
1527
- for (const s of samples) {
1528
- x0 = Math.min(x0, s.x);
1529
- y0 = Math.min(y0, s.y);
1530
- x1 = Math.max(x1, s.x);
1531
- y1 = Math.max(y1, s.y);
1532
- }
1533
- const maxPixels = finite2(options.maxPixels) && options.maxPixels > 0 ? options.maxPixels : DEFAULT_MAX_PIXELS;
1534
- const area = (x1 - x0 + reach) * (y1 - y0 + reach);
1535
- if (area * scale * scale > maxPixels) scale = Math.max(_chunkYQGCPL5Xcjs.BRUSHSTROKE_MIN_SCALE, Math.sqrt(maxPixels / area));
1536
- const scaled = samples.map((s) => ({ ...s, x: s.x * scale, y: s.y * scale }));
1537
- let character = {};
1538
- if (options.character) {
1539
- const c = brushCharacterOf(brush);
1540
- const ch = options.character;
1541
- const seed = finite2(ch.seed) ? ch.seed | 0 : hashString(JSON.stringify(input));
1542
- const jitter = c.size || c.angle || c.opacity || c.scatter ? { seed, size: c.size, angle: c.angle, opacity: c.opacity, scatter: c.scatter } : void 0;
1543
- const paper = ch.paper === null ? null : _nullishCoalesce(ch.paper, () => ( {}));
1544
- const depth = paper ? Math.min(1, Math.max(0, (finite2(paper.depth) ? paper.depth : 0.5) * c.grain)) : 0;
1545
- let grain;
1546
- if (paper && depth > 0) {
1547
- const g = paperGrain(paper);
1548
- const ox = _nullishCoalesce(_optionalChain([ch, 'access', _31 => _31.origin, 'optionalAccess', _32 => _32.x]), () => ( 0));
1549
- const oy = _nullishCoalesce(_optionalChain([ch, 'access', _33 => _33.origin, 'optionalAccess', _34 => _34.y]), () => ( 0));
1550
- const k = (finite2(ch.unit) && ch.unit > 0 ? ch.unit : 1) / scale;
1551
- grain = { depth, at: (x, y) => g.at(ox + x * k, oy + y * k) };
1552
- }
1553
- character = { ...jitter ? { jitter } : {}, ...grain ? { grain } : {} };
1554
- }
1555
- const { surface, bounds, dabs } = paintPathStroke(_chunk474IQG74cjs.emptySurface.call(void 0, 4), scaled, {
1556
- ...strokeOptions,
1557
- ...character,
1558
- brush: { ...tip, size: tip.size * scale },
1559
- closed: _nullishCoalesce(options.closed, () => ( strokeOptions.closed)),
1560
- color,
1561
- // Gradient lengths are in path units: scale them with the image.
1562
- ...source ? { paint: { paint: source.type === "gradient" ? scalePaintGradient(source, scale) : source, seed: _nullishCoalesce(options.seed, () => ( 0)) } } : {}
1563
- });
1564
- if (!bounds) return { image: { width: 0, height: 0, data: new Uint8ClampedArray(0) }, bounds: null, scale, dabs };
1565
- const rect = bounds;
1566
- const data = _chunk474IQG74cjs.readRegion.call(void 0, surface, rect);
1567
- return {
1568
- image: { width: rect.width, height: rect.height, data },
1569
- bounds: { x: rect.x / scale, y: rect.y / scale, width: rect.width / scale, height: rect.height / scale },
1570
- scale,
1571
- dabs
1572
- };
1573
- }
1574
- function brushstrokeDataUrl(stroke) {
1575
- const { width, height, data } = stroke.image;
1576
- return width && height ? _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, width, height, data) : "";
1577
- }
1578
- function brushstrokeToCanvas(stroke, createCanvas) {
1579
- const { width, height, data } = stroke.image;
1580
- if (!width || !height) return null;
1581
- const canvas = createCanvas(width, height);
1582
- const ctx = canvas.getContext("2d");
1583
- if (!ctx) return null;
1584
- const img = ctx.createImageData(width, height);
1585
- img.data.set(data);
1586
- ctx.putImageData(img, 0, 0);
1587
- return canvas;
1588
- }
1589
- function hashString(s, h = 2166136261) {
1590
- for (let i = 0; i < s.length; i++) {
1591
- h ^= s.charCodeAt(i);
1592
- h = Math.imul(h, 16777619) >>> 0;
1593
- }
1594
- return h;
1595
- }
1596
- function brushstrokeKey(input, brush, options = {}) {
1597
- const path = JSON.stringify(input);
1598
- const { brush: tip, ...rest } = brushstrokeStrokeOptions(brush);
1599
- const character = options.character ? [options.character, brushCharacterOf(brush)] : null;
1600
- const rest2 = JSON.stringify([tip, rest, _nullishCoalesce(_nullishCoalesce(options.paint, () => ( options.color)), () => ( null)), _nullishCoalesce(options.seed, () => ( 0)), _nullishCoalesce(options.closed, () => ( false)), _nullishCoalesce(options.maxPixels, () => ( null)), ...character ? [character] : []]);
1601
- const scale = finite2(options.scale) ? options.scale : 1;
1602
- return `${hashString(path).toString(16)}:${path.length}:${hashString(rest2).toString(16)}:${scale}`;
1603
- }
1604
- var BrushstrokeCache = (_class5 = class {
1605
- constructor(capacity = 64) {;_class5.prototype.__init22.call(this);_class5.prototype.__init23.call(this);
1606
- this.capacity = capacity;
1607
- }
1608
-
1609
- __init22() {this.entries = /* @__PURE__ */ new Map()}
1610
- /** Renders that missed the cache (for tests and stats). */
1611
- __init23() {this.misses = 0}
1612
- get size() {
1613
- return this.entries.size;
1614
- }
1615
- /** The cached stroke for these arguments, rendering (and caching) it on a miss. */
1616
- render(input, brush, options = {}) {
1617
- const key = brushstrokeKey(input, brush, options);
1618
- const hit = this.entries.get(key);
1619
- if (hit) {
1620
- this.entries.delete(key);
1621
- this.entries.set(key, hit);
1622
- return hit;
1623
- }
1624
- this.misses++;
1625
- const out = renderBrushstroke(input, brush, options);
1626
- this.entries.set(key, out);
1627
- while (this.entries.size > Math.max(1, this.capacity)) this.entries.delete(this.entries.keys().next().value);
1628
- return out;
1629
- }
1630
- clear() {
1631
- this.entries.clear();
1632
- }
1633
- }, _class5);
1634
-
1635
1081
  // src/paint/exchange.ts
1636
1082
  var MIXING_MODELS = ["rgb", "pigment"];
1637
1083
  var EMPTY_MIXER_LOAD = { reservoir: null, amount: 0, pickup: null };
@@ -1640,8 +1086,8 @@ var MIXER_DRAIN = 0.08;
1640
1086
  function exchangeRates(pickup, mix, load, mixing) {
1641
1087
  return { pickup: MIXER_PICKUP_RATE * pickup, mix: mix * pickup, drain: MIXER_DRAIN * (1 - load), mixing };
1642
1088
  }
1643
- var PaintExchange = (_class6 = class {
1644
- constructor(rates, load) {;_class6.prototype.__init24.call(this);
1089
+ var PaintExchange = (_class4 = class {
1090
+ constructor(rates, load) {;_class4.prototype.__init21.call(this);
1645
1091
  this.rates = rates;
1646
1092
  this.reservoir = load.reservoir ? [load.reservoir[0], load.reservoir[1], load.reservoir[2]] : null;
1647
1093
  this.amount = this.reservoir ? Math.min(1, Math.max(0, load.amount)) : 0;
@@ -1653,7 +1099,7 @@ var PaintExchange = (_class6 = class {
1653
1099
 
1654
1100
 
1655
1101
 
1656
- __init24() {this.out = [0, 0, 0]}
1102
+ __init21() {this.out = [0, 0, 0]}
1657
1103
  /** What the brush carries now. */
1658
1104
  get load() {
1659
1105
  return { reservoir: this.reservoir ? [...this.reservoir] : null, amount: this.amount, pickup: this.well ? [...this.well] : null };
@@ -1664,7 +1110,7 @@ var PaintExchange = (_class6 = class {
1664
1110
  }
1665
1111
  /** The prepared pigment of the last `paint` colour (pigment mixing only), for `deposit`. */
1666
1112
  get paintPigment() {
1667
- return _nullishCoalesce(_optionalChain([this, 'access', _35 => _35.pig, 'optionalAccess', _36 => _36.paint]), () => ( null));
1113
+ return _nullishCoalesce(_optionalChain([this, 'access', _5 => _5.pig, 'optionalAccess', _6 => _6.paint]), () => ( null));
1668
1114
  }
1669
1115
  /** Recolours the reservoir without refilling it (a multi-coloured brush, per dab). */
1670
1116
  setReservoirColor(r, g, b) {
@@ -1701,7 +1147,7 @@ var PaintExchange = (_class6 = class {
1701
1147
  if (!this.well) this.well = [sample.rgb[0], sample.rgb[1], sample.rgb[2]];
1702
1148
  else {
1703
1149
  if (pig) _chunk2VX55NFMcjs.setPigmentColor.call(void 0, pig.canvas, sample.rgb[0], sample.rgb[1], sample.rgb[2]);
1704
- const o = this.mix(this.well, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _37 => _37.well]), () => ( null)), sample.rgb, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _38 => _38.canvas]), () => ( null)), this.rates.pickup * sample.contact);
1150
+ const o = this.mix(this.well, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _7 => _7.well]), () => ( null)), sample.rgb, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _8 => _8.canvas]), () => ( null)), this.rates.pickup * sample.contact);
1705
1151
  this.well = [o[0], o[1], o[2]];
1706
1152
  }
1707
1153
  if (pig) _chunk2VX55NFMcjs.setPigmentColor.call(void 0, pig.well, this.well[0], this.well[1], this.well[2]);
@@ -1719,7 +1165,7 @@ var PaintExchange = (_class6 = class {
1719
1165
  if (!(total > 1e-6)) return 0;
1720
1166
  const pig = this.pig;
1721
1167
  if (res && this.well) {
1722
- const m = this.mix(res, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _39 => _39.res]), () => ( null)), this.well, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _40 => _40.well]), () => ( null)), wp / total);
1168
+ const m = this.mix(res, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _9 => _9.res]), () => ( null)), this.well, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _10 => _10.well]), () => ( null)), wp / total);
1723
1169
  out[0] = m[0];
1724
1170
  out[1] = m[1];
1725
1171
  out[2] = m[2];
@@ -1736,29 +1182,29 @@ var PaintExchange = (_class6 = class {
1736
1182
  drain() {
1737
1183
  this.amount *= 1 - this.rates.drain;
1738
1184
  }
1739
- }, _class6);
1185
+ }, _class4);
1740
1186
  function put255(px, i, v) {
1741
1187
  if (px instanceof Float32Array) px[i] = v > 0 ? v * 255 : 0;
1742
1188
  else px[i] = Math.round(v * 255);
1743
1189
  }
1744
- var TileMedium = (_class7 = class {
1745
- constructor(target, options = {}) {;_class7.prototype.__init25.call(this);_class7.prototype.__init26.call(this);_class7.prototype.__init27.call(this);_class7.prototype.__init28.call(this);_class7.prototype.__init29.call(this);_class7.prototype.__init30.call(this);_class7.prototype.__init31.call(this);_class7.prototype.__init32.call(this);_class7.prototype.__init33.call(this);_class7.prototype.__init34.call(this);
1190
+ var TileMedium = (_class5 = class {
1191
+ constructor(target, options = {}) {;_class5.prototype.__init22.call(this);_class5.prototype.__init23.call(this);_class5.prototype.__init24.call(this);_class5.prototype.__init25.call(this);_class5.prototype.__init26.call(this);_class5.prototype.__init27.call(this);_class5.prototype.__init28.call(this);_class5.prototype.__init29.call(this);_class5.prototype.__init30.call(this);_class5.prototype.__init31.call(this);
1746
1192
  this.target = target;
1747
1193
  this.options = options;
1748
1194
  }
1749
1195
 
1750
1196
 
1751
1197
  // The tile last looked up by `locate` (and whether it came from `writeTile`).
1752
- __init25() {this.tx = NaN}
1753
- __init26() {this.ty = NaN}
1754
- __init27() {this.tile = null}
1755
- __init28() {this.writable = false}
1756
- __init29() {this.canvasPig = _chunk2VX55NFMcjs.createPigment.call(void 0, [0, 0, 0])}
1757
- __init30() {this.paintPig = _chunk2VX55NFMcjs.createPigment.call(void 0, [0, 0, 0])}
1758
- __init31() {this.paintKey = -1}
1759
- __init32() {this.cb = [0, 0, 0, 0]}
1760
- __init33() {this.src = [0, 0, 0, 1]}
1761
- __init34() {this.o = [0, 0, 0]}
1198
+ __init22() {this.tx = NaN}
1199
+ __init23() {this.ty = NaN}
1200
+ __init24() {this.tile = null}
1201
+ __init25() {this.writable = false}
1202
+ __init26() {this.canvasPig = _chunk2VX55NFMcjs.createPigment.call(void 0, [0, 0, 0])}
1203
+ __init27() {this.paintPig = _chunk2VX55NFMcjs.createPigment.call(void 0, [0, 0, 0])}
1204
+ __init28() {this.paintKey = -1}
1205
+ __init29() {this.cb = [0, 0, 0, 0]}
1206
+ __init30() {this.src = [0, 0, 0, 1]}
1207
+ __init31() {this.o = [0, 0, 0]}
1762
1208
  /** Forgets the cached tile (call when another writer may have replaced tiles). */
1763
1209
  reset() {
1764
1210
  this.tx = NaN;
@@ -1903,7 +1349,7 @@ var TileMedium = (_class7 = class {
1903
1349
  }
1904
1350
  }
1905
1351
  }
1906
- }, _class7);
1352
+ }, _class5);
1907
1353
 
1908
1354
  // src/paint/blending.ts
1909
1355
  var DEFAULT_BLENDER = { strength: 0.5, distance: 0.35, mixing: "pigment" };
@@ -2019,8 +1465,8 @@ function blenderDab(medium, rect, cov, opacity, radius, settings, scratch) {
2019
1465
  }
2020
1466
  }
2021
1467
  }
2022
- var SmudgeTip = (_class8 = class {
2023
- constructor(settings, diameter) {;_class8.prototype.__init35.call(this);_class8.prototype.__init36.call(this);
1468
+ var SmudgeTip = (_class6 = class {
1469
+ constructor(settings, diameter) {;_class6.prototype.__init32.call(this);_class6.prototype.__init33.call(this);
2024
1470
  this.settings = settings;
2025
1471
  this.size = Math.max(2, Math.min(512, Math.ceil(diameter)));
2026
1472
  this.patch = new Float32Array(this.size * this.size * 4);
@@ -2028,8 +1474,8 @@ var SmudgeTip = (_class8 = class {
2028
1474
 
2029
1475
 
2030
1476
 
2031
- __init35() {this.loaded = false}
2032
- __init36() {this.out = [0, 0, 0]}
1477
+ __init32() {this.loaded = false}
1478
+ __init33() {this.out = [0, 0, 0]}
2033
1479
  cell(d, px, py) {
2034
1480
  const s = this.size;
2035
1481
  const r = Math.max(0.5, d.radius);
@@ -2140,7 +1586,7 @@ var SmudgeTip = (_class8 = class {
2140
1586
  }
2141
1587
  }
2142
1588
  }
2143
- }, _class8);
1589
+ }, _class6);
2144
1590
 
2145
1591
  // src/paint/mixer.ts
2146
1592
  var DEFAULT_MIXER = {
@@ -2173,22 +1619,22 @@ function loadMixer(load, color) {
2173
1619
  function cleanMixer(load) {
2174
1620
  return { reservoir: load.reservoir, amount: load.amount, pickup: null };
2175
1621
  }
2176
- var MixerStroke = (_class9 = class {
2177
- constructor(brush, settings, load, target) {;_class9.prototype.__init37.call(this);_class9.prototype.__init38.call(this);_class9.prototype.__init39.call(this);_class9.prototype.__init40.call(this);_class9.prototype.__init41.call(this);
1622
+ var MixerStroke = (_class7 = class {
1623
+ constructor(brush, settings, load, target) {;_class7.prototype.__init34.call(this);_class7.prototype.__init35.call(this);_class7.prototype.__init36.call(this);_class7.prototype.__init37.call(this);_class7.prototype.__init38.call(this);
2178
1624
  this.brush = brush;
2179
1625
  this.walker = new DabWalker(brush);
2180
1626
  this.exchange = new PaintExchange(mixerRates(normalizeMixer(settings)), load);
2181
1627
  this.medium = new TileMedium(target);
2182
1628
  }
2183
1629
 
2184
- __init37() {this.dabCount = 0}
2185
- __init38() {this.bounds = null}
1630
+ __init34() {this.dabCount = 0}
1631
+ __init35() {this.bounds = null}
2186
1632
 
2187
- __init39() {this.smoothPos = null}
2188
- __init40() {this.buf = new Float32Array(0)}
1633
+ __init36() {this.smoothPos = null}
1634
+ __init37() {this.buf = new Float32Array(0)}
2189
1635
 
2190
1636
 
2191
- __init41() {this.paintColor = [0, 0, 0]}
1637
+ __init38() {this.paintColor = [0, 0, 0]}
2192
1638
  /** The brush load after the dabs so far. */
2193
1639
  get load() {
2194
1640
  return this.exchange.load;
@@ -2236,7 +1682,7 @@ var MixerStroke = (_class9 = class {
2236
1682
  }
2237
1683
  ex.drain();
2238
1684
  }
2239
- }, _class9);
1685
+ }, _class7);
2240
1686
  function union(a, b) {
2241
1687
  if (!a) return { ...b };
2242
1688
  const x = Math.min(a.x, b.x);
@@ -2317,21 +1763,4 @@ function union(a, b) {
2317
1763
 
2318
1764
 
2319
1765
 
2320
-
2321
-
2322
-
2323
-
2324
-
2325
-
2326
-
2327
-
2328
-
2329
-
2330
-
2331
-
2332
-
2333
-
2334
-
2335
-
2336
-
2337
- exports.PAINT_GRADIENT_SPACES = PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_REPEATS = PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_MAPPINGS = PAINT_GRADIENT_MAPPINGS; exports.DEFAULT_PAINT_GRADIENT_MAPPING = DEFAULT_PAINT_GRADIENT_MAPPING; exports.PAINT_GRADIENT_FULL_SPEED = PAINT_GRADIENT_FULL_SPEED; exports.PaintSourceError = PaintSourceError; exports.normalizeHexColor = normalizeHexColor; exports.hexToPaintRgb = hexToPaintRgb; exports.parsePaintSource = parsePaintSource; exports.readPaintSource = readPaintSource; exports.resolvePaintGradient = resolvePaintGradient; exports.scalePaintGradient = scalePaintGradient; exports.solidPaint = solidPaint; exports.isGradientPaint = isGradientPaint; exports.paintSourceColor = paintSourceColor; exports.paintSourceCss = paintSourceCss; exports.PaintGradientSampler = PaintGradientSampler; exports.PAINT_GRADIENT_JSON_SCHEMA = PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_COLOR_JSON_SCHEMA = PAINT_COLOR_JSON_SCHEMA; exports.PAINT_SOURCE_JSON_SCHEMA = PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_GRADIENT_MAPPING_LABELS = PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_SPACE_LABELS = PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_GRADIENT_REPEAT_LABELS = PAINT_GRADIENT_REPEAT_LABELS; exports.DEFAULT_PAINT_GRADIENT = DEFAULT_PAINT_GRADIENT; exports.PAINT_GRADIENT_PRESETS = PAINT_GRADIENT_PRESETS; exports.addPaintGradientStop = addPaintGradientStop; exports.removePaintGradientStop = removePaintGradientStop; exports.updatePaintGradientStop = updatePaintGradientStop; exports.reversePaintGradient = reversePaintGradient; exports.paintGradientMappingFor = paintGradientMappingFor; exports.PAINT_GRADIENT_KIT = PAINT_GRADIENT_KIT; exports.DEFAULT_BRUSH = DEFAULT_BRUSH; exports.MAX_BRUSH_SIZE = MAX_BRUSH_SIZE; exports.normalizeBrush = normalizeBrush; exports.tipShape = tipShape; exports.tipFalloff = tipFalloff; exports.tipReach = tipReach; exports.dabCoverage = dabCoverage; exports.smoothPoints = smoothPoints; exports.DabWalker = DabWalker; exports.walkDabs = walkDabs; exports.dabRect = dabRect; exports.rasterizeDab = rasterizeDab; exports.CoverageMap = CoverageMap; exports.StrokeCoverage = StrokeCoverage; exports.TIP_GRADIENT_STEPS = TIP_GRADIENT_STEPS; exports.gradientDabColor = gradientDabColor; exports.applyStrokeToTile = applyStrokeToTile; exports.applyStrokeToDeepTile = applyStrokeToDeepTile; exports.coverageTileCoord = coverageTileCoord; exports.GRAIN_PATTERNS = GRAIN_PATTERNS; exports.GRAIN_TILE = GRAIN_TILE; exports.grainHeights = grainHeights; exports.PaperGrain = PaperGrain; exports.grainCatch = grainCatch; exports.strokeGrainCatch = strokeGrainCatch; exports.pathStrokeDabs = pathStrokeDabs; exports.pathStrokeCoverage = pathStrokeCoverage; exports.paintPathStroke = paintPathStroke; exports.brushstrokeSamples = brushstrokeSamples; exports.brushstrokeStrokeOptions = brushstrokeStrokeOptions; exports.isBrushstrokeBrush = isBrushstrokeBrush; exports.renderBrushstroke = renderBrushstroke; exports.brushstrokeDataUrl = brushstrokeDataUrl; exports.brushstrokeToCanvas = brushstrokeToCanvas; exports.brushstrokeKey = brushstrokeKey; exports.BrushstrokeCache = BrushstrokeCache; exports.MIXING_MODELS = MIXING_MODELS; exports.EMPTY_MIXER_LOAD = EMPTY_MIXER_LOAD; exports.MIXER_PICKUP_RATE = MIXER_PICKUP_RATE; exports.MIXER_DRAIN = MIXER_DRAIN; exports.exchangeRates = exchangeRates; exports.PaintExchange = PaintExchange; exports.put255 = put255; exports.TileMedium = TileMedium; exports.DEFAULT_BLENDER = DEFAULT_BLENDER; exports.DEFAULT_SMUDGE = DEFAULT_SMUDGE; exports.normalizeBlender = normalizeBlender; exports.normalizeSmudge = normalizeSmudge; exports.blendRadius = blendRadius; exports.createBlenderScratch = createBlenderScratch; exports.blenderDab = blenderDab; exports.SmudgeTip = SmudgeTip; exports.DEFAULT_MIXER = DEFAULT_MIXER; exports.normalizeMixer = normalizeMixer; exports.mixerRates = mixerRates; exports.loadMixer = loadMixer; exports.cleanMixer = cleanMixer; exports.MixerStroke = MixerStroke;
1766
+ exports.PAINT_GRADIENT_SPACES = PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_REPEATS = PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_MAPPINGS = PAINT_GRADIENT_MAPPINGS; exports.DEFAULT_PAINT_GRADIENT_MAPPING = DEFAULT_PAINT_GRADIENT_MAPPING; exports.PAINT_GRADIENT_FULL_SPEED = PAINT_GRADIENT_FULL_SPEED; exports.PaintSourceError = PaintSourceError; exports.normalizeHexColor = normalizeHexColor; exports.hexToPaintRgb = hexToPaintRgb; exports.parsePaintSource = parsePaintSource; exports.readPaintSource = readPaintSource; exports.resolvePaintGradient = resolvePaintGradient; exports.scalePaintGradient = scalePaintGradient; exports.solidPaint = solidPaint; exports.isGradientPaint = isGradientPaint; exports.paintSourceColor = paintSourceColor; exports.paintSourceCss = paintSourceCss; exports.PaintGradientSampler = PaintGradientSampler; exports.PAINT_GRADIENT_JSON_SCHEMA = PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_COLOR_JSON_SCHEMA = PAINT_COLOR_JSON_SCHEMA; exports.PAINT_SOURCE_JSON_SCHEMA = PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_GRADIENT_MAPPING_LABELS = PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_SPACE_LABELS = PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_GRADIENT_REPEAT_LABELS = PAINT_GRADIENT_REPEAT_LABELS; exports.DEFAULT_PAINT_GRADIENT = DEFAULT_PAINT_GRADIENT; exports.PAINT_GRADIENT_PRESETS = PAINT_GRADIENT_PRESETS; exports.addPaintGradientStop = addPaintGradientStop; exports.removePaintGradientStop = removePaintGradientStop; exports.updatePaintGradientStop = updatePaintGradientStop; exports.reversePaintGradient = reversePaintGradient; exports.paintGradientMappingFor = paintGradientMappingFor; exports.PAINT_GRADIENT_KIT = PAINT_GRADIENT_KIT; exports.DEFAULT_BRUSH = DEFAULT_BRUSH; exports.MAX_BRUSH_SIZE = MAX_BRUSH_SIZE; exports.normalizeBrush = normalizeBrush; exports.tipShape = tipShape; exports.tipFalloff = tipFalloff; exports.tipReach = tipReach; exports.dabCoverage = dabCoverage; exports.smoothPoints = smoothPoints; exports.DabWalker = DabWalker; exports.walkDabs = walkDabs; exports.dabRect = dabRect; exports.rasterizeDab = rasterizeDab; exports.CoverageMap = CoverageMap; exports.StrokeCoverage = StrokeCoverage; exports.TIP_GRADIENT_STEPS = TIP_GRADIENT_STEPS; exports.gradientDabColor = gradientDabColor; exports.applyStrokeToTile = applyStrokeToTile; exports.applyStrokeToDeepTile = applyStrokeToDeepTile; exports.coverageTileCoord = coverageTileCoord; exports.MIXING_MODELS = MIXING_MODELS; exports.EMPTY_MIXER_LOAD = EMPTY_MIXER_LOAD; exports.MIXER_PICKUP_RATE = MIXER_PICKUP_RATE; exports.MIXER_DRAIN = MIXER_DRAIN; exports.exchangeRates = exchangeRates; exports.PaintExchange = PaintExchange; exports.put255 = put255; exports.TileMedium = TileMedium; exports.DEFAULT_BLENDER = DEFAULT_BLENDER; exports.DEFAULT_SMUDGE = DEFAULT_SMUDGE; exports.normalizeBlender = normalizeBlender; exports.normalizeSmudge = normalizeSmudge; exports.blendRadius = blendRadius; exports.createBlenderScratch = createBlenderScratch; exports.blenderDab = blenderDab; exports.SmudgeTip = SmudgeTip; exports.DEFAULT_MIXER = DEFAULT_MIXER; exports.normalizeMixer = normalizeMixer; exports.mixerRates = mixerRates; exports.loadMixer = loadMixer; exports.cleanMixer = cleanMixer; exports.MixerStroke = MixerStroke;