@pixerate/editor 0.267.0 → 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 (80) hide show
  1. package/dist/animation-editor/index.cjs +62 -62
  2. package/dist/animation-editor/index.js +6 -6
  3. package/dist/brushes/index.cjs +198 -72
  4. package/dist/brushes/index.d.cts +4 -3
  5. package/dist/brushes/index.d.ts +4 -3
  6. package/dist/brushes/index.js +136 -10
  7. package/dist/brushes/library.d.cts +27 -1
  8. package/dist/brushes/library.d.ts +27 -1
  9. package/dist/brushes/profiles.d.cts +4 -0
  10. package/dist/brushes/profiles.d.ts +4 -0
  11. package/dist/brushes/schema.d.cts +4 -0
  12. package/dist/brushes/schema.d.ts +4 -0
  13. package/dist/brushes/sources.d.cts +114 -0
  14. package/dist/brushes/sources.d.ts +114 -0
  15. package/dist/brushes/types.d.cts +37 -5
  16. package/dist/brushes/types.d.ts +37 -5
  17. package/dist/brushes/ui.d.cts +40 -4
  18. package/dist/brushes/ui.d.ts +40 -4
  19. package/dist/{brushstrokeRender-NLFPEBGI.js → brushstrokeRender-A727TTNQ.js} +6 -6
  20. package/dist/{brushstrokeRender-L7JYRR2R.cjs → brushstrokeRender-WR2N5HHY.cjs} +22 -22
  21. package/dist/canvas/index.cjs +13 -13
  22. package/dist/canvas/index.js +1 -1
  23. package/dist/{chunk-J2TNIZ55.cjs → chunk-2WOGXEDX.cjs} +1 -1
  24. package/dist/{chunk-JGWVZPT6.js → chunk-3XDSNIGF.js} +72 -5
  25. package/dist/{chunk-EXB2EGBE.cjs → chunk-62MFUHSI.cjs} +16 -16
  26. package/dist/{chunk-FGJHJIMN.js → chunk-74ODPZLX.js} +10 -10
  27. package/dist/{chunk-GCVFEPJG.js → chunk-ACTHSQOI.js} +182 -0
  28. package/dist/{chunk-LHPEG5AU.cjs → chunk-B3G7BKUV.cjs} +90 -90
  29. package/dist/{chunk-EF7LZAXQ.js → chunk-BAZMCFVL.js} +1 -1
  30. package/dist/{chunk-HIO6E7LC.cjs → chunk-BPJSI4NT.cjs} +2 -2
  31. package/dist/{chunk-XVOP3CGQ.cjs → chunk-EU2ZZA6L.cjs} +393 -62
  32. package/dist/{chunk-YIC6MAJ2.js → chunk-HFY5LG5J.js} +1 -1
  33. package/dist/{chunk-7UKFXXWL.js → chunk-HVO6XCI4.js} +1 -1
  34. package/dist/{chunk-OKHKA43L.cjs → chunk-JBB3GDBB.cjs} +330 -216
  35. package/dist/{chunk-AGNUD5BI.js → chunk-KZI3YWKW.js} +351 -20
  36. package/dist/{chunk-EYSHTYLG.js → chunk-LETF75CA.js} +1 -1
  37. package/dist/{chunk-FQPUF2W2.cjs → chunk-NIBFKXMD.cjs} +217 -35
  38. package/dist/{chunk-G7NHE2VD.cjs → chunk-NPWWSCWT.cjs} +35 -35
  39. package/dist/{chunk-OSEXT7JL.js → chunk-QNY7BDFP.js} +1 -1
  40. package/dist/{chunk-PXDIAYB6.cjs → chunk-STLTOISW.cjs} +34 -214
  41. package/dist/{chunk-4IDUYB45.js → chunk-UVTO3D4E.js} +130 -16
  42. package/dist/{chunk-TXFWZ5ZJ.js → chunk-W6JDUXP3.js} +4 -184
  43. package/dist/{chunk-LA5Y4ETA.cjs → chunk-YOVXQHA3.cjs} +23 -23
  44. package/dist/{chunk-DT4YQUGT.cjs → chunk-YXP6X3SY.cjs} +101 -34
  45. package/dist/image-editor/index.cjs +851 -851
  46. package/dist/image-editor/index.js +23 -23
  47. package/dist/paint/index.cjs +5 -5
  48. package/dist/paint/index.js +11 -11
  49. package/dist/paint-editor/brush-library-tools.d.cts +12 -2
  50. package/dist/paint-editor/brush-library-tools.d.ts +12 -2
  51. package/dist/paint-editor/brush-model.d.cts +29 -1
  52. package/dist/paint-editor/brush-model.d.ts +29 -1
  53. package/dist/paint-editor/brush-source-art.d.cts +32 -0
  54. package/dist/paint-editor/brush-source-art.d.ts +32 -0
  55. package/dist/paint-editor/controller.d.cts +6 -1
  56. package/dist/paint-editor/controller.d.ts +6 -1
  57. package/dist/paint-editor/dab-stroke.d.cts +2 -0
  58. package/dist/paint-editor/dab-stroke.d.ts +2 -0
  59. package/dist/paint-editor/engine.d.cts +11 -2
  60. package/dist/paint-editor/engine.d.ts +11 -2
  61. package/dist/paint-editor/index.cjs +576 -481
  62. package/dist/paint-editor/index.d.cts +3 -1
  63. package/dist/paint-editor/index.d.ts +3 -1
  64. package/dist/paint-editor/index.js +127 -32
  65. package/dist/paint-editor/stamp-tip.d.cts +8 -5
  66. package/dist/paint-editor/stamp-tip.d.ts +8 -5
  67. package/dist/paint-editor/thumbnails.d.cts +6 -0
  68. package/dist/paint-editor/thumbnails.d.ts +6 -0
  69. package/dist/paint-editor/tip-grain.d.cts +34 -0
  70. package/dist/paint-editor/tip-grain.d.ts +34 -0
  71. package/dist/raster/index.cjs +2 -2
  72. package/dist/raster/index.js +9 -9
  73. package/dist/vector/index.cjs +1002 -1002
  74. package/dist/vector/index.js +7 -7
  75. package/package.json +1 -1
  76. package/skills/pixerate-brushes/SKILL.md +35 -8
  77. package/skills/pixerate-brushes-design/SKILL.md +8 -1
  78. package/skills/pixerate-paint-editor/SKILL.md +6 -0
  79. package/skills/pixerate-paint-editor/references/brush-facets.md +3 -1
  80. package/skills/pixerate-paint-sketch-to-finish/SKILL.md +1 -0
@@ -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,