@pixerate/editor 0.266.2 → 0.268.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 (149) hide show
  1. package/dist/agent/index.cjs +2 -2
  2. package/dist/agent/index.js +1 -1
  3. package/dist/animation-editor/controller.d.cts +8 -0
  4. package/dist/animation-editor/controller.d.ts +8 -0
  5. package/dist/animation-editor/effect-tools.d.cts +1 -1
  6. package/dist/animation-editor/effect-tools.d.ts +1 -1
  7. package/dist/animation-editor/index.cjs +175 -108
  8. package/dist/animation-editor/index.js +94 -27
  9. package/dist/brushes/index.cjs +201 -75
  10. package/dist/brushes/index.d.cts +4 -3
  11. package/dist/brushes/index.d.ts +4 -3
  12. package/dist/brushes/index.js +138 -12
  13. package/dist/brushes/library.d.cts +27 -1
  14. package/dist/brushes/library.d.ts +27 -1
  15. package/dist/brushes/profiles.d.cts +10 -1
  16. package/dist/brushes/profiles.d.ts +10 -1
  17. package/dist/brushes/schema.d.cts +4 -0
  18. package/dist/brushes/schema.d.ts +4 -0
  19. package/dist/brushes/sources.d.cts +114 -0
  20. package/dist/brushes/sources.d.ts +114 -0
  21. package/dist/brushes/types.d.cts +37 -5
  22. package/dist/brushes/types.d.ts +37 -5
  23. package/dist/brushes/ui.d.cts +40 -4
  24. package/dist/brushes/ui.d.ts +40 -4
  25. package/dist/{brushstrokeRender-KD453OBX.js → brushstrokeRender-A727TTNQ.js} +7 -7
  26. package/dist/{brushstrokeRender-FSUWXUZY.cjs → brushstrokeRender-WR2N5HHY.cjs} +23 -23
  27. package/dist/canvas/brushTypes.d.cts +12 -0
  28. package/dist/canvas/brushTypes.d.ts +12 -0
  29. package/dist/canvas/brushstroke.d.cts +1 -1
  30. package/dist/canvas/brushstroke.d.ts +1 -1
  31. package/dist/canvas/drawController.d.cts +19 -4
  32. package/dist/canvas/drawController.d.ts +19 -4
  33. package/dist/canvas/index.cjs +144 -105
  34. package/dist/canvas/index.js +46 -7
  35. package/dist/{chunk-TOID45I2.cjs → chunk-2WOGXEDX.cjs} +1 -1
  36. package/dist/{chunk-XORJ7UZO.cjs → chunk-3VHH6V67.cjs} +13 -12
  37. package/dist/{chunk-3C33YTNN.js → chunk-3XDSNIGF.js} +73 -6
  38. package/dist/chunk-62MFUHSI.cjs +802 -0
  39. package/dist/{chunk-R44Y3EFS.js → chunk-74ODPZLX.js} +17 -345
  40. package/dist/{chunk-GCVFEPJG.js → chunk-ACTHSQOI.js} +182 -0
  41. package/dist/chunk-ADMRNWR7.js +340 -0
  42. package/dist/{chunk-MVUQSK5J.cjs → chunk-B3G7BKUV.cjs} +111 -439
  43. package/dist/{chunk-DXYHQ2VN.js → chunk-BAZMCFVL.js} +1 -1
  44. package/dist/{chunk-VRK322ZC.cjs → chunk-BPJSI4NT.cjs} +2 -2
  45. package/dist/{chunk-RFJZGTHA.cjs → chunk-EU2ZZA6L.cjs} +400 -69
  46. package/dist/{chunk-XC6DPRYI.js → chunk-GSTSZPSR.js} +154 -949
  47. package/dist/{chunk-EZOJBP4D.js → chunk-HFY5LG5J.js} +1 -1
  48. package/dist/chunk-HVO6XCI4.js +802 -0
  49. package/dist/{chunk-YHDHFJUC.cjs → chunk-J5VQYK7T.cjs} +217 -1012
  50. package/dist/{chunk-XRXFVRGY.cjs → chunk-JBB3GDBB.cjs} +2483 -208
  51. package/dist/{chunk-ACFSFUQH.js → chunk-JL6YH5WD.js} +4 -0
  52. package/dist/{chunk-CIJBSUM5.js → chunk-KZI3YWKW.js} +353 -22
  53. package/dist/{chunk-4ODRXQRW.js → chunk-LETF75CA.js} +1 -1
  54. package/dist/{chunk-FQPUF2W2.cjs → chunk-NIBFKXMD.cjs} +217 -35
  55. package/dist/{chunk-AQZQWXEU.cjs → chunk-NPWWSCWT.cjs} +35 -35
  56. package/dist/{chunk-DOZ6F2K2.js → chunk-NSETJI74.js} +3 -2
  57. package/dist/{chunk-PE6YJMQT.cjs → chunk-PFHJS4HE.cjs} +20 -19
  58. package/dist/{chunk-7KNW3WXZ.cjs → chunk-QEVLRLUN.cjs} +63 -0
  59. package/dist/{chunk-LK4SXL3V.js → chunk-QNY7BDFP.js} +1 -1
  60. package/dist/{chunk-OTN6VB5S.cjs → chunk-RDFHWAHL.cjs} +5 -1
  61. package/dist/{chunk-PXDIAYB6.cjs → chunk-STLTOISW.cjs} +34 -214
  62. package/dist/{chunk-T2LDTEXK.js → chunk-UVTO3D4E.js} +2333 -58
  63. package/dist/{chunk-6JL2D5SG.js → chunk-VE6UKYQ2.js} +3 -2
  64. package/dist/{chunk-TXFWZ5ZJ.js → chunk-W6JDUXP3.js} +4 -184
  65. package/dist/{chunk-3SBLVGOM.cjs → chunk-YOVXQHA3.cjs} +23 -23
  66. package/dist/{chunk-WLUVZKVD.cjs → chunk-YXP6X3SY.cjs} +103 -36
  67. package/dist/chunk-YZWM6ZIP.cjs +340 -0
  68. package/dist/{chunk-472INMWH.js → chunk-ZA7L5YJB.js} +63 -0
  69. package/dist/commands/builtins.d.cts +12 -1
  70. package/dist/commands/builtins.d.ts +12 -1
  71. package/dist/commands/index.cjs +2 -2
  72. package/dist/commands/index.js +1 -1
  73. package/dist/image-editor/controller.d.cts +1 -1
  74. package/dist/image-editor/controller.d.ts +1 -1
  75. package/dist/image-editor/index.cjs +868 -864
  76. package/dist/image-editor/index.js +123 -119
  77. package/dist/paint/index.cjs +8 -6
  78. package/dist/paint/index.js +56 -54
  79. package/dist/paint-editor/brush-library-tools.d.cts +12 -2
  80. package/dist/paint-editor/brush-library-tools.d.ts +12 -2
  81. package/dist/paint-editor/brush-model.d.cts +29 -1
  82. package/dist/paint-editor/brush-model.d.ts +29 -1
  83. package/dist/paint-editor/brush-source-art.d.cts +32 -0
  84. package/dist/paint-editor/brush-source-art.d.ts +32 -0
  85. package/dist/paint-editor/controller.d.cts +11 -4
  86. package/dist/paint-editor/controller.d.ts +11 -4
  87. package/dist/paint-editor/dab-stroke.d.cts +2 -0
  88. package/dist/paint-editor/dab-stroke.d.ts +2 -0
  89. package/dist/paint-editor/engine.d.cts +11 -2
  90. package/dist/paint-editor/engine.d.ts +11 -2
  91. package/dist/paint-editor/index.cjs +967 -2335
  92. package/dist/paint-editor/index.d.cts +3 -1
  93. package/dist/paint-editor/index.d.ts +3 -1
  94. package/dist/paint-editor/index.js +394 -1762
  95. package/dist/paint-editor/path-samples.d.cts +2 -0
  96. package/dist/paint-editor/path-samples.d.ts +2 -0
  97. package/dist/paint-editor/presence.d.cts +20 -1
  98. package/dist/paint-editor/presence.d.ts +20 -1
  99. package/dist/paint-editor/stamp-tip.d.cts +8 -5
  100. package/dist/paint-editor/stamp-tip.d.ts +8 -5
  101. package/dist/paint-editor/thumbnails.d.cts +6 -0
  102. package/dist/paint-editor/thumbnails.d.ts +6 -0
  103. package/dist/paint-editor/tip-grain.d.cts +34 -0
  104. package/dist/paint-editor/tip-grain.d.ts +34 -0
  105. package/dist/raster/index.cjs +2 -2
  106. package/dist/raster/index.js +9 -9
  107. package/dist/stickers/helpers.d.cts +2 -0
  108. package/dist/stickers/helpers.d.ts +2 -0
  109. package/dist/stickers/index.cjs +41 -35
  110. package/dist/stickers/index.js +22 -16
  111. package/dist/stickers/types.d.cts +4 -2
  112. package/dist/stickers/types.d.ts +4 -2
  113. package/dist/vector/backdrop.d.cts +13 -0
  114. package/dist/vector/backdrop.d.ts +13 -0
  115. package/dist/vector/brushstroke.d.cts +54 -7
  116. package/dist/vector/brushstroke.d.ts +54 -7
  117. package/dist/vector/brushstrokeMedia.d.cts +96 -0
  118. package/dist/vector/brushstrokeMedia.d.ts +96 -0
  119. package/dist/vector/controller.d.cts +17 -3
  120. package/dist/vector/controller.d.ts +17 -3
  121. package/dist/vector/index.cjs +1850 -1390
  122. package/dist/vector/index.d.cts +2 -0
  123. package/dist/vector/index.d.ts +2 -0
  124. package/dist/vector/index.js +520 -60
  125. package/dist/vector/render.d.cts +6 -0
  126. package/dist/vector/render.d.ts +6 -0
  127. package/dist/vector/types.d.cts +14 -0
  128. package/dist/vector/types.d.ts +14 -0
  129. package/package.json +1 -1
  130. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  131. package/skills/pixerate-brushes/SKILL.md +37 -10
  132. package/skills/pixerate-brushes-design/SKILL.md +15 -5
  133. package/skills/pixerate-brushes-design/evals/port-to-vector.json +8 -8
  134. package/skills/pixerate-canvas/SKILL.md +11 -1
  135. package/skills/pixerate-image-editor/SKILL.md +19 -64
  136. package/skills/pixerate-image-editor/references/color-management.md +2 -1
  137. package/skills/pixerate-image-editor/references/free-transform.md +12 -0
  138. package/skills/pixerate-image-editor/references/layer-effects.md +10 -0
  139. package/skills/pixerate-image-editor/references/painting.md +17 -0
  140. package/skills/pixerate-image-editor/references/photoshop-files.md +1 -1
  141. package/skills/pixerate-image-editor/references/shapes-and-type.md +14 -0
  142. package/skills/pixerate-image-editor/references/smart-objects.md +10 -0
  143. package/skills/pixerate-paint-editor/SKILL.md +14 -4
  144. package/skills/pixerate-paint-editor/references/brush-facets.md +3 -1
  145. package/skills/pixerate-paint-editor/references/wet-media.md +9 -0
  146. package/skills/pixerate-paint-sketch-to-finish/SKILL.md +1 -0
  147. package/skills/pixerate-vector/SKILL.md +16 -6
  148. package/skills/pixerate-vector/references/best-practices.md +1 -0
  149. package/skills/pixerate-vector/references/commands.md +19 -0
@@ -1,3 +1,10 @@
1
+ import {
2
+ combineCoverage,
3
+ flatBounds,
4
+ flattenPath,
5
+ rasterizeCoverage,
6
+ rasterizeCoverageSampled
7
+ } from "./chunk-ADMRNWR7.js";
1
8
  import {
2
9
  boxMean,
3
10
  combineSelections,
@@ -108,7 +115,7 @@ import {
108
115
  transformTextRect,
109
116
  translateMatrix,
110
117
  warpPresetMesh
111
- } from "./chunk-T2LDTEXK.js";
118
+ } from "./chunk-UVTO3D4E.js";
112
119
  import {
113
120
  bezierPathBounds,
114
121
  outlineStroke,
@@ -122,15 +129,7 @@ import {
122
129
  } from "./chunk-DVPQFMH6.js";
123
130
  import {
124
131
  MAX_BRUSH_SIZE
125
- } from "./chunk-GCVFEPJG.js";
126
- import {
127
- base64ToBytes,
128
- bytesToBase64,
129
- decodePng,
130
- encodePng,
131
- parseDataUrl,
132
- pngDataUrl
133
- } from "./chunk-OTTT5N3K.js";
132
+ } from "./chunk-ACTHSQOI.js";
134
133
  import {
135
134
  BLEND_MODES,
136
135
  blendRgb,
@@ -143,6 +142,14 @@ import {
143
142
  surfaceFromDeepPixels,
144
143
  writeDeepRegion
145
144
  } from "./chunk-IRSTHLQQ.js";
145
+ import {
146
+ base64ToBytes,
147
+ bytesToBase64,
148
+ decodePng,
149
+ encodePng,
150
+ parseDataUrl,
151
+ pngDataUrl
152
+ } from "./chunk-OTTT5N3K.js";
146
153
  import {
147
154
  TILE,
148
155
  TiledSurface,
@@ -1912,339 +1919,6 @@ function removeAlpha(imageData) {
1912
1919
  }
1913
1920
  }
1914
1921
 
1915
- // src/image-editor/layers/vector-raster.ts
1916
- var FLATNESS = 0.01;
1917
- function flattenPath(path, tolerance = FLATNESS) {
1918
- const out = [];
1919
- let pts = [];
1920
- let cx = 0;
1921
- let cy = 0;
1922
- let sx = 0;
1923
- let sy = 0;
1924
- const flush = () => {
1925
- if (pts.length >= 6) out.push(Float64Array.from(pts));
1926
- pts = [];
1927
- };
1928
- const steps = (dd, degree) => Math.max(1, Math.min(1024, Math.ceil(Math.sqrt(degree * (degree - 1) * dd / (8 * tolerance)))));
1929
- for (const c of path) {
1930
- switch (c.type) {
1931
- case "M":
1932
- flush();
1933
- cx = sx = c.x;
1934
- cy = sy = c.y;
1935
- pts.push(cx, cy);
1936
- break;
1937
- case "L":
1938
- if (!pts.length) pts.push(cx, cy);
1939
- cx = c.x;
1940
- cy = c.y;
1941
- pts.push(cx, cy);
1942
- break;
1943
- case "Q": {
1944
- if (!pts.length) pts.push(cx, cy);
1945
- const n = steps(Math.hypot(cx - 2 * c.x1 + c.x, cy - 2 * c.y1 + c.y), 2);
1946
- for (let k = 1; k <= n; k++) {
1947
- const t = k / n;
1948
- const u = 1 - t;
1949
- pts.push(u * u * cx + 2 * u * t * c.x1 + t * t * c.x, u * u * cy + 2 * u * t * c.y1 + t * t * c.y);
1950
- }
1951
- cx = c.x;
1952
- cy = c.y;
1953
- break;
1954
- }
1955
- case "C": {
1956
- if (!pts.length) pts.push(cx, cy);
1957
- const dd = Math.max(Math.hypot(cx - 2 * c.x1 + c.x2, cy - 2 * c.y1 + c.y2), Math.hypot(c.x1 - 2 * c.x2 + c.x, c.y1 - 2 * c.y2 + c.y));
1958
- const n = steps(dd, 3);
1959
- for (let k = 1; k <= n; k++) {
1960
- const t = k / n;
1961
- const u = 1 - t;
1962
- const a = u * u * u;
1963
- const b = 3 * u * u * t;
1964
- const d = 3 * u * t * t;
1965
- const e = t * t * t;
1966
- pts.push(a * cx + b * c.x1 + d * c.x2 + e * c.x, a * cy + b * c.y1 + d * c.y2 + e * c.y);
1967
- }
1968
- cx = c.x;
1969
- cy = c.y;
1970
- break;
1971
- }
1972
- case "Z":
1973
- flush();
1974
- cx = sx;
1975
- cy = sy;
1976
- break;
1977
- }
1978
- }
1979
- flush();
1980
- return out.filter((p) => p.every(Number.isFinite));
1981
- }
1982
- function flatBounds(flat) {
1983
- let x0 = Infinity;
1984
- let y0 = Infinity;
1985
- let x1 = -Infinity;
1986
- let y1 = -Infinity;
1987
- for (const p of flat) {
1988
- for (let i = 0; i < p.length; i += 2) {
1989
- if (p[i] < x0) x0 = p[i];
1990
- if (p[i] > x1) x1 = p[i];
1991
- if (p[i + 1] < y0) y0 = p[i + 1];
1992
- if (p[i + 1] > y1) y1 = p[i + 1];
1993
- }
1994
- }
1995
- if (x0 === Infinity) return null;
1996
- const x = Math.floor(x0);
1997
- const y = Math.floor(y0);
1998
- return { x, y, width: Math.ceil(x1) - x, height: Math.ceil(y1) - y };
1999
- }
2000
- function drawLine(a, w, h, x0, y0, x1, y1) {
2001
- if (y0 === y1) return;
2002
- let dir = 1;
2003
- if (y0 > y1) {
2004
- dir = -1;
2005
- let t = x0;
2006
- x0 = x1;
2007
- x1 = t;
2008
- t = y0;
2009
- y0 = y1;
2010
- y1 = t;
2011
- }
2012
- if (y1 <= 0 || y0 >= h) return;
2013
- const dxdy = (x1 - x0) / (y1 - y0);
2014
- let x = x0;
2015
- if (y0 < 0) x -= y0 * dxdy;
2016
- const rowStart = Math.max(0, Math.floor(y0));
2017
- const rowEnd = Math.min(h, Math.ceil(y1));
2018
- for (let y = rowStart; y < rowEnd; y++) {
2019
- const line = y * w;
2020
- const dy = Math.min(y + 1, y1) - Math.max(y, y0);
2021
- const xnext = x + dxdy * dy;
2022
- const d = dy * dir;
2023
- const xa = x < xnext ? x : xnext;
2024
- const xb = x < xnext ? xnext : x;
2025
- const xaFloor = Math.floor(xa);
2026
- const xai = xaFloor;
2027
- const xbCeil = Math.ceil(xb);
2028
- const xbi = xbCeil;
2029
- if (xbi <= xai + 1) {
2030
- const xmf = 0.5 * (x + xnext) - xaFloor;
2031
- a[line + xai] += d - d * xmf;
2032
- a[line + xai + 1] += d * xmf;
2033
- } else {
2034
- const s = 1 / (xb - xa);
2035
- const xaf = xa - xaFloor;
2036
- const a0 = 0.5 * s * (1 - xaf) * (1 - xaf);
2037
- const xbf = xb - xbCeil + 1;
2038
- const am = 0.5 * s * xbf * xbf;
2039
- a[line + xai] += d * a0;
2040
- if (xbi === xai + 2) a[line + xai + 1] += d * (1 - a0 - am);
2041
- else {
2042
- const a1 = s * (1.5 - xaf);
2043
- a[line + xai + 1] += d * (a1 - a0);
2044
- for (let xi = xai + 2; xi < xbi - 1; xi++) a[line + xi] += d * s;
2045
- const a2 = a1 + (xbi - xai - 3) * s;
2046
- a[line + xbi - 1] += d * (1 - a2 - am);
2047
- }
2048
- a[line + xbi] += d * am;
2049
- }
2050
- x = xnext;
2051
- }
2052
- }
2053
- function drawClippedLine(a, w, h, x0, y0, x1, y1) {
2054
- if (y0 === y1) return;
2055
- if (y0 <= 0 && y1 <= 0 || y0 >= h && y1 >= h) return;
2056
- if (x0 >= 0 && x0 <= w && x1 >= 0 && x1 <= w) return drawLine(a, w, h, x0, y0, x1, y1);
2057
- const ts = [0, 1];
2058
- const dx = x1 - x0;
2059
- if (dx !== 0) {
2060
- for (const edge of [0, w]) {
2061
- const t = (edge - x0) / dx;
2062
- if (t > 0 && t < 1) ts.push(t);
2063
- }
2064
- }
2065
- ts.sort((p, q2) => p - q2);
2066
- const clamp4 = (v) => v < 0 ? 0 : v > w ? w : v;
2067
- for (let i = 0; i + 1 < ts.length; i++) {
2068
- const ta = ts[i];
2069
- const tb = ts[i + 1];
2070
- drawLine(a, w, h, clamp4(x0 + dx * ta), y0 + (y1 - y0) * ta, clamp4(x0 + dx * tb), y0 + (y1 - y0) * tb);
2071
- }
2072
- }
2073
- function ruleCoverage(v, rule) {
2074
- const m = v < 0 ? -v : v;
2075
- if (rule === "nonzero") return m >= 1 ? 1 : m;
2076
- const f = m % 2;
2077
- return f > 1 ? 2 - f : f;
2078
- }
2079
- function rasterizeCoverage(flat, rect, rule = "nonzero") {
2080
- const w = rect.width;
2081
- const h = rect.height;
2082
- if (w <= 0 || h <= 0 || !flat.length) return null;
2083
- const a = new Float64Array(w * h + w + 4);
2084
- const ox = rect.x;
2085
- const oy = rect.y;
2086
- let touched = false;
2087
- for (const p of flat) {
2088
- const n = p.length;
2089
- for (let i = 0; i < n; i += 2) {
2090
- const j = i + 2 < n ? i + 2 : 0;
2091
- const ya = p[i + 1] - oy;
2092
- const yb = p[j + 1] - oy;
2093
- if (ya <= 0 && yb <= 0 || ya >= h && yb >= h || ya === yb) continue;
2094
- drawClippedLine(a, w, h, p[i] - ox, ya, p[j] - ox, yb);
2095
- touched = true;
2096
- }
2097
- }
2098
- if (!touched) return null;
2099
- const out = new Float32Array(w * h);
2100
- let acc = 0;
2101
- let any = false;
2102
- for (let i = 0; i < out.length; i++) {
2103
- acc += a[i];
2104
- const c = ruleCoverage(acc, rule);
2105
- if (c > 1e-6) {
2106
- out[i] = c;
2107
- any = true;
2108
- }
2109
- }
2110
- return any ? out : null;
2111
- }
2112
- var SUB_ROWS = 16;
2113
- function rasterizeCoverageSampled(flat, rect, rule = "nonzero") {
2114
- const w = rect.width;
2115
- const h = rect.height;
2116
- if (w <= 0 || h <= 0 || !flat.length) return null;
2117
- let n = 0;
2118
- for (const p of flat) n += p.length >> 1;
2119
- const ey0 = new Float64Array(n);
2120
- const ey1 = new Float64Array(n);
2121
- const ex0 = new Float64Array(n);
2122
- const eslope = new Float64Array(n);
2123
- const edir = new Int8Array(n);
2124
- let count = 0;
2125
- for (const p of flat) {
2126
- const len = p.length;
2127
- for (let i = 0; i < len; i += 2) {
2128
- const j = i + 2 < len ? i + 2 : 0;
2129
- let xa = p[i] - rect.x;
2130
- let ya = p[i + 1] - rect.y;
2131
- let xb = p[j] - rect.x;
2132
- let yb = p[j + 1] - rect.y;
2133
- if (ya === yb) continue;
2134
- let dir = 1;
2135
- if (ya > yb) {
2136
- dir = -1;
2137
- let t = xa;
2138
- xa = xb;
2139
- xb = t;
2140
- t = ya;
2141
- ya = yb;
2142
- yb = t;
2143
- }
2144
- if (yb <= 0 || ya >= h) continue;
2145
- ey0[count] = ya;
2146
- ey1[count] = yb;
2147
- ex0[count] = xa;
2148
- eslope[count] = (xb - xa) / (yb - ya);
2149
- edir[count] = dir;
2150
- count++;
2151
- }
2152
- }
2153
- if (!count) return null;
2154
- const order = Array.from({ length: count }, (_, i) => i).sort((a, b) => ey0[a] - ey0[b]);
2155
- const out = new Float32Array(w * h);
2156
- const diff = new Float32Array(w + 1);
2157
- let active = [];
2158
- let next = 0;
2159
- const xs = [];
2160
- const ds = [];
2161
- const idx = [];
2162
- const f = 1 / SUB_ROWS;
2163
- let any = false;
2164
- const firstRow = Math.max(0, Math.floor(ey0[order[0]]));
2165
- for (let y = firstRow; y < h; y++) {
2166
- if (next >= count && !active.length) break;
2167
- const row = y * w;
2168
- let rowTouched = false;
2169
- for (let s = 0; s < SUB_ROWS; s++) {
2170
- const sy = y + (s + 0.5) * f;
2171
- while (next < count && ey0[order[next]] <= sy) active.push(order[next++]);
2172
- if (!active.length) continue;
2173
- active = active.filter((e) => ey1[e] > sy);
2174
- xs.length = 0;
2175
- ds.length = 0;
2176
- idx.length = 0;
2177
- for (const e of active) {
2178
- if (ey0[e] > sy) continue;
2179
- idx.push(xs.length);
2180
- xs.push(ex0[e] + (sy - ey0[e]) * eslope[e]);
2181
- ds.push(edir[e]);
2182
- }
2183
- if (xs.length < 2) continue;
2184
- idx.sort((a, b) => xs[a] - xs[b]);
2185
- let wind = 0;
2186
- for (let k = 0; k + 1 < idx.length; k++) {
2187
- wind += ds[idx[k]];
2188
- const inside = rule === "nonzero" ? wind !== 0 : (wind & 1) !== 0;
2189
- if (!inside) continue;
2190
- let xa = xs[idx[k]];
2191
- let xb = xs[idx[k + 1]];
2192
- if (xb <= 0 || xa >= w || xb <= xa) continue;
2193
- if (xa < 0) xa = 0;
2194
- if (xb > w) xb = w;
2195
- const ia = Math.floor(xa);
2196
- const ib = Math.floor(xb);
2197
- rowTouched = true;
2198
- if (ia === ib) {
2199
- out[row + ia] += (xb - xa) * f;
2200
- continue;
2201
- }
2202
- out[row + ia] += (ia + 1 - xa) * f;
2203
- diff[ia + 1] += f;
2204
- diff[ib] -= f;
2205
- if (ib < w) out[row + ib] += (xb - ib) * f;
2206
- }
2207
- }
2208
- if (!rowTouched) continue;
2209
- let run = 0;
2210
- for (let x = 0; x < w; x++) {
2211
- run += diff[x];
2212
- diff[x] = 0;
2213
- const v = out[row + x] + run;
2214
- out[row + x] = v > 1 ? 1 : v < 1e-6 ? 0 : v;
2215
- if (out[row + x] > 0) any = true;
2216
- }
2217
- diff[w] = 0;
2218
- }
2219
- return any ? out : null;
2220
- }
2221
- function combineCoverage(a, b, op, n) {
2222
- if (op === "combine") {
2223
- if (!a) return b;
2224
- if (!b) return a;
2225
- const out2 = new Float32Array(n);
2226
- for (let i = 0; i < n; i++) out2[i] = a[i] + b[i] - a[i] * b[i];
2227
- return out2;
2228
- }
2229
- if (op === "subtract") {
2230
- if (!a || !b) return a;
2231
- const out2 = new Float32Array(n);
2232
- for (let i = 0; i < n; i++) out2[i] = a[i] * (1 - b[i]);
2233
- return out2;
2234
- }
2235
- if (op === "intersect") {
2236
- if (!a || !b) return null;
2237
- const out2 = new Float32Array(n);
2238
- for (let i = 0; i < n; i++) out2[i] = a[i] * b[i];
2239
- return out2;
2240
- }
2241
- if (!a) return b;
2242
- if (!b) return a;
2243
- const out = new Float32Array(n);
2244
- for (let i = 0; i < n; i++) out[i] = a[i] + b[i] - 2 * a[i] * b[i];
2245
- return out;
2246
- }
2247
-
2248
1922
  // src/text/types.ts
2249
1923
  var TEXT_ORIENTATIONS = ["horizontal", "vertical"];
2250
1924
  var TEXT_ALIGNS = ["left", "center", "right", "justify"];
@@ -13322,8 +12996,6 @@ export {
13322
12996
  applyBoxBlur,
13323
12997
  applyDepthMask,
13324
12998
  removeAlpha,
13325
- flattenPath,
13326
- rasterizeCoverage,
13327
12999
  TEXT_ORIENTATIONS,
13328
13000
  TEXT_ALIGNS,
13329
13001
  MAX_EFFECT_ANIMATION_MS,
@@ -1,4 +1,6 @@
1
1
  import {
2
+ TileableNoise,
3
+ hash2,
2
4
  rand01
3
5
  } from "./chunk-4D6KP5BV.js";
4
6
  import {
@@ -1078,6 +1080,180 @@ function coverageTileCoord(key) {
1078
1080
  return tileCoord(key);
1079
1081
  }
1080
1082
 
1083
+ // src/paint/grain.ts
1084
+ var GRAIN_PATTERNS = ["smooth", "cold-pressed", "hot-pressed", "rough", "vellum", "laid", "ingres", "sanded", "canvas", "linen", "gesso"];
1085
+ var GRAIN_TILE = 256;
1086
+ var clamp01 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
1087
+ function patternHeights(pattern, n, seed) {
1088
+ const out = new Float32Array(n * n);
1089
+ const salt = Math.imul(seed | 0, 2654435761) + 17;
1090
+ if (pattern === "smooth") return out.fill(1);
1091
+ const noise = (cx, cy, oct, s = 0) => new TileableNoise(n, cx, cy, oct, salt + s);
1092
+ const k = n / GRAIN_TILE;
1093
+ switch (pattern) {
1094
+ case "cold-pressed": {
1095
+ const base = noise(20 * k, 20 * k, 4);
1096
+ const fine = noise(64 * k, 64 * k, 2, 3);
1097
+ for (let y = 0; y < n; y++)
1098
+ 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 + (hash2(x, y, salt) - 0.5) * 0.12);
1099
+ break;
1100
+ }
1101
+ case "hot-pressed": {
1102
+ const base = noise(40 * k, 40 * k, 3);
1103
+ 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 + (hash2(x, y, salt) - 0.5) * 0.08);
1104
+ break;
1105
+ }
1106
+ case "rough": {
1107
+ const base = noise(10 * k, 10 * k, 5);
1108
+ const blot = noise(28 * k, 28 * k, 2, 5);
1109
+ for (let y = 0; y < n; y++)
1110
+ 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 + (hash2(x, y, salt) - 0.5) * 0.15);
1111
+ break;
1112
+ }
1113
+ case "vellum": {
1114
+ const base = noise(40 * k, 40 * k, 3);
1115
+ 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 + (hash2(x, y, salt) - 0.5) * 0.2);
1116
+ break;
1117
+ }
1118
+ case "laid": {
1119
+ const pulp = noise(32 * k, 32 * k, 3);
1120
+ const chain = n / 8;
1121
+ for (let y = 0; y < n; y++) {
1122
+ const laid = 0.5 + 0.5 * Math.cos(2 * Math.PI * y / 4);
1123
+ for (let x = 0; x < n; x++) {
1124
+ const c = Math.abs((x + 0.5) % chain - chain / 2) / (chain / 2);
1125
+ const chainLine = c > 0.94 ? -0.35 : 0;
1126
+ out[y * n + x] = clamp01(0.3 + 0.5 * laid + chainLine + (pulp.at(x, y) - 0.5) * 0.6);
1127
+ }
1128
+ }
1129
+ break;
1130
+ }
1131
+ case "ingres": {
1132
+ const fibres = noise(64 * k, 12 * k, 3);
1133
+ const base = noise(16 * k, 16 * k, 3, 7);
1134
+ for (let y = 0; y < n; y++)
1135
+ for (let x = 0; x < n; x++) {
1136
+ const g = hash2(x, y, salt ^ 85);
1137
+ 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));
1138
+ }
1139
+ break;
1140
+ }
1141
+ case "sanded": {
1142
+ const grit = noise(96 * k, 96 * k, 2);
1143
+ for (let y = 0; y < n; y++)
1144
+ for (let x = 0; x < n; x++) {
1145
+ const h = hash2(x, y, salt);
1146
+ out[y * n + x] = clamp01((grit.at(x, y) - 0.5) * 2.4 + 0.5 + (h - 0.5) * 0.7);
1147
+ }
1148
+ break;
1149
+ }
1150
+ case "canvas":
1151
+ case "linen": {
1152
+ const period = (pattern === "canvas" ? 8 : 5) * k;
1153
+ const threads = Math.max(2, 2 * Math.round(n / period / 2));
1154
+ const p = n / threads;
1155
+ const slub = noise(threads, threads, 2, 11);
1156
+ for (let y = 0; y < n; y++)
1157
+ for (let x = 0; x < n; x++) {
1158
+ const fx = (x + 0.5) / p;
1159
+ const fy = (y + 0.5) / p;
1160
+ const cx = Math.floor(fx);
1161
+ const cy = Math.floor(fy);
1162
+ const warp = Math.sin(Math.PI * (fx - cx));
1163
+ const weft = Math.sin(Math.PI * (fy - cy));
1164
+ const top = (cx + cy) % 2 === 0 ? warp : weft;
1165
+ const irregular = pattern === "linen" ? (slub.at(x, y) - 0.5) * 0.5 : 0;
1166
+ out[y * n + x] = clamp01(0.2 + 0.7 * top + irregular + (hash2(x, y, salt) - 0.5) * 0.15);
1167
+ }
1168
+ break;
1169
+ }
1170
+ case "gesso": {
1171
+ const streaks = noise(2 * k, 28 * k, 3);
1172
+ const tooth = noise(64 * k, 64 * k, 2, 13);
1173
+ for (let y = 0; y < n; y++)
1174
+ 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);
1175
+ break;
1176
+ }
1177
+ }
1178
+ return out;
1179
+ }
1180
+ var rawCache = /* @__PURE__ */ new Map();
1181
+ function grainHeights(pattern, seed, size = GRAIN_TILE) {
1182
+ const key = `${pattern}:${seed}:${size}`;
1183
+ let h = rawCache.get(key);
1184
+ if (!h) {
1185
+ h = patternHeights(pattern, size, seed);
1186
+ if (rawCache.size > 32) rawCache.delete(rawCache.keys().next().value);
1187
+ rawCache.set(key, h);
1188
+ }
1189
+ return h;
1190
+ }
1191
+ var PaperGrain = class {
1192
+ size = GRAIN_TILE;
1193
+ heights;
1194
+ scale;
1195
+ mirror;
1196
+ ox;
1197
+ oy;
1198
+ flat;
1199
+ constructor(paper, media = "dry") {
1200
+ const raw = grainHeights(paper.pattern, paper.seed);
1201
+ const t = paper[media];
1202
+ this.flat = paper.pattern === "smooth";
1203
+ if (t.contrast === 1 && !t.invert) this.heights = raw;
1204
+ else {
1205
+ const out = new Float32Array(raw.length);
1206
+ for (let i = 0; i < raw.length; i++) {
1207
+ const v = clamp01((raw[i] - 0.5) * t.contrast + 0.5);
1208
+ out[i] = t.invert ? 1 - v : v;
1209
+ }
1210
+ this.heights = out;
1211
+ }
1212
+ this.scale = paper.scale;
1213
+ this.mirror = paper.tiling === "mirror";
1214
+ this.ox = paper.offset?.x ?? 0;
1215
+ this.oy = paper.offset?.y ?? 0;
1216
+ }
1217
+ /** Tile cell index for a coordinate in grain pixels (mirrored on odd tiles when mirroring). */
1218
+ wrap(v) {
1219
+ const n = this.size;
1220
+ if (!this.mirror) return (v % n + n) % n;
1221
+ const p = (v % (2 * n) + 2 * n) % (2 * n);
1222
+ return p < n ? p : 2 * n - 1 - p;
1223
+ }
1224
+ /** Height 0..1 at document position (x, y). */
1225
+ at(x, y) {
1226
+ const u = (x - this.ox) / this.scale - 0.5;
1227
+ const v = (y - this.oy) / this.scale - 0.5;
1228
+ const x0 = Math.floor(u);
1229
+ const y0 = Math.floor(v);
1230
+ const fx = u - x0;
1231
+ const fy = v - y0;
1232
+ const n = this.size;
1233
+ const h = this.heights;
1234
+ const a = this.wrap(x0);
1235
+ const b = this.wrap(x0 + 1);
1236
+ const c = this.wrap(y0) * n;
1237
+ const d = this.wrap(y0 + 1) * n;
1238
+ const top = h[c + a] + (h[c + b] - h[c + a]) * fx;
1239
+ const bot = h[d + a] + (h[d + b] - h[d + a]) * fx;
1240
+ return top + (bot - top) * fy;
1241
+ }
1242
+ };
1243
+ function grainCatch(h, depth, pressure) {
1244
+ if (depth <= 0) return 1;
1245
+ const t = depth * (0.75 - 0.65 * Math.min(1, Math.max(0, pressure)));
1246
+ const u = clamp01((h - t + 0.18) / 0.36);
1247
+ return 1 - depth + depth * u * u * (3 - 2 * u);
1248
+ }
1249
+ function strokeGrainCatch(h, depth, pressure) {
1250
+ if (depth <= 0) return 1;
1251
+ const p = Math.min(1, Math.max(0, pressure));
1252
+ const amount = Math.min(1, depth * (1.4 - 0.6 * p));
1253
+ const u = clamp01((h - 0.2 - 0.25 * (1 - p)) / 0.5);
1254
+ return 1 - amount + amount * u * u * (3 - 2 * u);
1255
+ }
1256
+
1081
1257
  // src/paint/exchange.ts
1082
1258
  var MIXING_MODELS = ["rgb", "pigment"];
1083
1259
  var EMPTY_MIXER_LOAD = { reservoir: null, amount: 0, pickup: null };
@@ -1741,6 +1917,12 @@ export {
1741
1917
  applyStrokeToTile,
1742
1918
  applyStrokeToDeepTile,
1743
1919
  coverageTileCoord,
1920
+ GRAIN_PATTERNS,
1921
+ GRAIN_TILE,
1922
+ grainHeights,
1923
+ PaperGrain,
1924
+ grainCatch,
1925
+ strokeGrainCatch,
1744
1926
  MIXING_MODELS,
1745
1927
  EMPTY_MIXER_LOAD,
1746
1928
  MIXER_PICKUP_RATE,