@pixerate/editor 0.136.0 → 0.137.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.
- package/dist/animation-editor/index.cjs +60 -55
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +4 -4
- package/dist/animation-editor/index.d.ts +4 -4
- package/dist/animation-editor/index.js +7 -2
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/{bezier-CdccFsF8.d.cts → bezier-CZ2AhjID.d.cts} +1 -1
- package/dist/{bezier-DG9qNZQV.d.ts → bezier-Dywv3Bw8.d.ts} +1 -1
- package/dist/blending-D7jCmjO6.d.cts +1026 -0
- package/dist/blending-NgF3qo3d.d.ts +1026 -0
- package/dist/brushes-CnvZSYYU.d.cts +744 -0
- package/dist/brushes-DJmUbIgz.d.ts +744 -0
- package/dist/{brushstrokeRender-SII6MG4R.js → brushstrokeRender-2FAXA3XC.js} +13 -16
- package/dist/{brushstrokeRender-SII6MG4R.js.map → brushstrokeRender-2FAXA3XC.js.map} +1 -1
- package/dist/{brushstrokeRender-JNHVEUFG.cjs → brushstrokeRender-IMFY3FF6.cjs} +16 -19
- package/dist/brushstrokeRender-IMFY3FF6.cjs.map +1 -0
- package/dist/canvas/index.cjs +10 -10
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +7 -7
- package/dist/canvas/index.d.ts +7 -7
- package/dist/canvas/index.js +4 -4
- package/dist/{chunk-W4LNKTHT.cjs → chunk-2XS6LTUP.cjs} +63 -63
- package/dist/{chunk-W4LNKTHT.cjs.map → chunk-2XS6LTUP.cjs.map} +1 -1
- package/dist/{chunk-MAHQC3SK.js → chunk-3D77LOBM.js} +222 -135
- package/dist/chunk-3D77LOBM.js.map +1 -0
- package/dist/{chunk-BR7EKQUP.js → chunk-3G6J7UFV.js} +322 -2
- package/dist/chunk-3G6J7UFV.js.map +1 -0
- package/dist/{chunk-62XUO5LB.js → chunk-3X6IAJUQ.js} +2 -2
- package/dist/{chunk-EM3FMJWE.js → chunk-5FSRTP6E.js} +320 -3
- package/dist/chunk-5FSRTP6E.js.map +1 -0
- package/dist/{chunk-2R3UW57U.cjs → chunk-5OOIUXNJ.cjs} +333 -246
- package/dist/chunk-5OOIUXNJ.cjs.map +1 -0
- package/dist/{chunk-KZXLZCQ7.js → chunk-6S6362D2.js} +2 -2
- package/dist/{chunk-24ATT2PE.cjs → chunk-AEAAN4AD.cjs} +120 -120
- package/dist/{chunk-24ATT2PE.cjs.map → chunk-AEAAN4AD.cjs.map} +1 -1
- package/dist/{chunk-SVYE5HIM.js → chunk-EQQMGO42.js} +2 -2
- package/dist/{chunk-FHPVDTI2.cjs → chunk-F2Y4E4GU.cjs} +22 -22
- package/dist/{chunk-FHPVDTI2.cjs.map → chunk-F2Y4E4GU.cjs.map} +1 -1
- package/dist/{chunk-UYQUPUR6.js → chunk-HUO3TI4C.js} +3 -3
- package/dist/{chunk-DDSO4HS7.cjs → chunk-KEENUAFN.cjs} +2 -2
- package/dist/{chunk-DDSO4HS7.cjs.map → chunk-KEENUAFN.cjs.map} +1 -1
- package/dist/{chunk-2HC4DRF4.js → chunk-LLFHCSU2.js} +2 -2
- package/dist/{chunk-J5BA3BQ6.cjs → chunk-O7LUD7MH.cjs} +323 -3
- package/dist/chunk-O7LUD7MH.cjs.map +1 -0
- package/dist/{chunk-ILYFOJUN.js → chunk-OIBIRXRG.js} +3 -3
- package/dist/{chunk-B2CUCM7Y.cjs → chunk-PRSRYHQD.cjs} +36 -36
- package/dist/{chunk-B2CUCM7Y.cjs.map → chunk-PRSRYHQD.cjs.map} +1 -1
- package/dist/{chunk-6GFRKLLS.cjs → chunk-QBWEH3IM.cjs} +429 -112
- package/dist/chunk-QBWEH3IM.cjs.map +1 -0
- package/dist/{chunk-6QQR4LKE.js → chunk-SYT2TLQF.js} +35 -37
- package/dist/{chunk-6QQR4LKE.js.map → chunk-SYT2TLQF.js.map} +1 -1
- package/dist/{chunk-YT3JL7YM.cjs → chunk-TLCTTQFF.cjs} +53 -53
- package/dist/{chunk-YT3JL7YM.cjs.map → chunk-TLCTTQFF.cjs.map} +1 -1
- package/dist/{chunk-JLGNZMUV.cjs → chunk-XN2NBLV5.cjs} +313 -315
- package/dist/chunk-XN2NBLV5.cjs.map +1 -0
- package/dist/effects/index.d.cts +4 -4
- package/dist/effects/index.d.ts +4 -4
- package/dist/{export-Ds7zgGD8.d.ts → export-41rL6Cne.d.ts} +1 -1
- package/dist/{export-BOheWw2R.d.cts → export-CyJdfP_Z.d.cts} +5 -4
- package/dist/{export-CEYeRQXH.d.cts → export-D9mXp05Q.d.cts} +1 -1
- package/dist/{export-ByKKIA2S.d.ts → export-DwnZ_hvQ.d.ts} +5 -4
- package/dist/{helpers--ns3W2D7.d.ts → helpers-C-RgeyvH.d.ts} +18 -7
- package/dist/{helpers-BVkU4oUi.d.cts → helpers-v6GMazzg.d.cts} +18 -7
- package/dist/image-editor/index.cjs +984 -987
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +12 -11
- package/dist/image-editor/index.d.ts +12 -11
- package/dist/image-editor/index.js +92 -95
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{opentype-yi-Kz4ND.d.cts → opentype-KR_jj6b_.d.cts} +1 -1
- package/dist/{opentype-DfoVYgmG.d.ts → opentype-a1KAW-qs.d.ts} +1 -1
- package/dist/paint/index.cjs +5 -8
- package/dist/paint/index.cjs.map +1 -1
- package/dist/paint/index.d.cts +4 -2
- package/dist/paint/index.d.ts +4 -2
- package/dist/paint/index.js +15 -18
- package/dist/paint-editor/index.cjs +403 -404
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +12 -748
- package/dist/paint-editor/index.d.ts +12 -748
- package/dist/paint-editor/index.js +77 -78
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/{pathfinder-7JkMwYvC.d.cts → pathfinder-BHS4vQNm.d.cts} +1 -1
- package/dist/{pathfinder-GM3UWdBZ.d.ts → pathfinder-BVvTIBMo.d.ts} +1 -1
- package/dist/{pool-CkTxlLMC.d.ts → pool-CZQOrSXZ.d.ts} +1 -1
- package/dist/{pool-04qp8iW4.d.cts → pool-FjZZmZ80.d.cts} +1 -1
- package/dist/rand-8xbUb6ur.d.ts +1118 -0
- package/dist/rand-Cw9VLrVC.d.cts +1118 -0
- package/dist/raster/index.cjs +17 -19
- package/dist/raster/index.cjs.map +1 -1
- package/dist/raster/index.js +9 -11
- package/dist/raster/index.js.map +1 -1
- package/dist/{svg-rV6_HPmn.d.ts → svg-CSz3mzkw.d.ts} +2 -2
- package/dist/{svg-BDDKvWWY.d.cts → svg-DTb40ICU.d.cts} +2 -2
- package/dist/{tools-DPYerqeR.d.ts → tools-B0wXP5cF.d.ts} +1 -1
- package/dist/{tools-BAjSbTdY.d.cts → tools-Ca0kI1qo.d.cts} +1 -1
- package/dist/vector/index.cjs +1459 -1259
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +87 -11
- package/dist/vector/index.d.ts +87 -11
- package/dist/vector/index.js +213 -13
- package/dist/vector/index.js.map +1 -1
- package/dist/video-editor/index.d.cts +4 -4
- package/dist/video-editor/index.d.ts +4 -4
- package/dist/{warp-DQh9R7Ie.d.cts → warp-DTOp0lON.d.cts} +1 -1
- package/dist/{warp-XVL6SpSh.d.ts → warp-pd7hrH4T.d.ts} +1 -1
- package/package.json +1 -1
- package/skills/pixerate-vector/SKILL.md +8 -0
- package/dist/brushstrokeRender-JNHVEUFG.cjs.map +0 -1
- package/dist/chunk-2R3UW57U.cjs.map +0 -1
- package/dist/chunk-64PYNEHJ.js +0 -340
- package/dist/chunk-64PYNEHJ.js.map +0 -1
- package/dist/chunk-6GFRKLLS.cjs.map +0 -1
- package/dist/chunk-7QN76ESJ.js +0 -323
- package/dist/chunk-7QN76ESJ.js.map +0 -1
- package/dist/chunk-BR7EKQUP.js.map +0 -1
- package/dist/chunk-DCLJNVZS.cjs +0 -323
- package/dist/chunk-DCLJNVZS.cjs.map +0 -1
- package/dist/chunk-EM3FMJWE.js.map +0 -1
- package/dist/chunk-J5BA3BQ6.cjs.map +0 -1
- package/dist/chunk-JLGNZMUV.cjs.map +0 -1
- package/dist/chunk-MAHQC3SK.js.map +0 -1
- package/dist/chunk-Z6OUCS2K.cjs +0 -340
- package/dist/chunk-Z6OUCS2K.cjs.map +0 -1
- package/dist/rand-BszBST4s.d.ts +0 -2140
- package/dist/rand-DOH_aMvm.d.cts +0 -2140
- /package/dist/{chunk-62XUO5LB.js.map → chunk-3X6IAJUQ.js.map} +0 -0
- /package/dist/{chunk-KZXLZCQ7.js.map → chunk-6S6362D2.js.map} +0 -0
- /package/dist/{chunk-SVYE5HIM.js.map → chunk-EQQMGO42.js.map} +0 -0
- /package/dist/{chunk-UYQUPUR6.js.map → chunk-HUO3TI4C.js.map} +0 -0
- /package/dist/{chunk-2HC4DRF4.js.map → chunk-LLFHCSU2.js.map} +0 -0
- /package/dist/{chunk-ILYFOJUN.js.map → chunk-OIBIRXRG.js.map} +0 -0
package/dist/vector/index.js
CHANGED
|
@@ -20,15 +20,6 @@ import {
|
|
|
20
20
|
orderQuad,
|
|
21
21
|
solve8
|
|
22
22
|
} from "../chunk-GX332W2C.js";
|
|
23
|
-
import {
|
|
24
|
-
bytesToBase64,
|
|
25
|
-
decodePng,
|
|
26
|
-
isPng,
|
|
27
|
-
parseDataUrl
|
|
28
|
-
} from "../chunk-7QN76ESJ.js";
|
|
29
|
-
import {
|
|
30
|
-
deflate
|
|
31
|
-
} from "../chunk-6FCKOS2B.js";
|
|
32
23
|
import {
|
|
33
24
|
correspondMorphContours,
|
|
34
25
|
createVectorMorph,
|
|
@@ -47,7 +38,7 @@ import {
|
|
|
47
38
|
reverseMorphContour,
|
|
48
39
|
subpathToMorphContour,
|
|
49
40
|
turnMorphContour
|
|
50
|
-
} from "../chunk-
|
|
41
|
+
} from "../chunk-6S6362D2.js";
|
|
51
42
|
import {
|
|
52
43
|
DEFAULT_VECTOR_FONT,
|
|
53
44
|
IDENTITY_MATRIX,
|
|
@@ -56,6 +47,7 @@ import {
|
|
|
56
47
|
VECTOR_BLEND_MODES,
|
|
57
48
|
VECTOR_BLEND_MODE_LABELS,
|
|
58
49
|
VECTOR_BLEND_SPACINGS,
|
|
50
|
+
VECTOR_BRUSHSTROKE_SCALE,
|
|
59
51
|
VECTOR_CHARACTER_STYLE_KEYS,
|
|
60
52
|
VECTOR_CONNECTOR_ROUTES,
|
|
61
53
|
VECTOR_CONNECTOR_ROUTE_LABELS,
|
|
@@ -202,6 +194,7 @@ import {
|
|
|
202
194
|
isUniformWidthProfile,
|
|
203
195
|
isValidWarpMesh,
|
|
204
196
|
isVectorBlendMode,
|
|
197
|
+
isVectorBrushstrokeLayer,
|
|
205
198
|
isVectorConnector,
|
|
206
199
|
isVectorFilterType,
|
|
207
200
|
isVectorFrame,
|
|
@@ -292,6 +285,7 @@ import {
|
|
|
292
285
|
sampleVectorGradient,
|
|
293
286
|
sampleVectorGradientAt,
|
|
294
287
|
sampleVectorPaintDefAt,
|
|
288
|
+
sanitizeVectorBrushstroke,
|
|
295
289
|
sanitizeVectorConnector,
|
|
296
290
|
sanitizeVectorEffects,
|
|
297
291
|
sanitizeVectorFills,
|
|
@@ -360,6 +354,10 @@ import {
|
|
|
360
354
|
vectorBlendModeFromCss,
|
|
361
355
|
vectorBoundsInside,
|
|
362
356
|
vectorBoxMatrix,
|
|
357
|
+
vectorBrushstrokeBrush,
|
|
358
|
+
vectorBrushstrokeBrushes,
|
|
359
|
+
vectorBrushstrokeImages,
|
|
360
|
+
vectorBrushstrokeReach,
|
|
363
361
|
vectorChildAppearanceShapes,
|
|
364
362
|
vectorConnectionSites,
|
|
365
363
|
vectorConnectorTargetAt,
|
|
@@ -505,7 +503,8 @@ import {
|
|
|
505
503
|
withVectorStrokes,
|
|
506
504
|
withVectorTargetPaint,
|
|
507
505
|
zigzagPaths
|
|
508
|
-
} from "../chunk-
|
|
506
|
+
} from "../chunk-3D77LOBM.js";
|
|
507
|
+
import "../chunk-HUO3TI4C.js";
|
|
509
508
|
import {
|
|
510
509
|
createProvenance
|
|
511
510
|
} from "../chunk-A3BVTI3G.js";
|
|
@@ -540,6 +539,17 @@ import {
|
|
|
540
539
|
resolveEffectValues
|
|
541
540
|
} from "../chunk-QFSTQHZY.js";
|
|
542
541
|
import "../chunk-4FX5ACVG.js";
|
|
542
|
+
import "../chunk-5FSRTP6E.js";
|
|
543
|
+
import "../chunk-63AZAUSN.js";
|
|
544
|
+
import {
|
|
545
|
+
bytesToBase64,
|
|
546
|
+
decodePng,
|
|
547
|
+
isPng,
|
|
548
|
+
parseDataUrl
|
|
549
|
+
} from "../chunk-3G6J7UFV.js";
|
|
550
|
+
import {
|
|
551
|
+
deflate
|
|
552
|
+
} from "../chunk-6FCKOS2B.js";
|
|
543
553
|
import "../chunk-FPENXAEJ.js";
|
|
544
554
|
import "../chunk-P6ODPZ4W.js";
|
|
545
555
|
import {
|
|
@@ -2895,6 +2905,12 @@ function lineStyle(node) {
|
|
|
2895
2905
|
function renderLayers(node, defs, idPrefix) {
|
|
2896
2906
|
const out = [];
|
|
2897
2907
|
for (const l of vectorPaintLayerNodes(node)) {
|
|
2908
|
+
if (l.kind === "stroke" && isVectorBrushstrokeLayer(l.layer) && l.layer.visible !== false && (l.layer.opacity ?? 1) > 0) {
|
|
2909
|
+
const images = vectorBrushstrokeImages(node, l.layer);
|
|
2910
|
+
const blend2 = vectorBlendModeCss(l.layer.blendMode);
|
|
2911
|
+
if (images.length) out.push({ kind: "brushstroke", index: l.index, fill: "none", stroke: "none", strokeWidth: 0, opacity: l.layer.opacity ?? 1, ...blend2 ? { blendMode: blend2 } : {}, images });
|
|
2912
|
+
continue;
|
|
2913
|
+
}
|
|
2898
2914
|
if (!l.drawn) continue;
|
|
2899
2915
|
const role = l.kind;
|
|
2900
2916
|
const paint = vectorPaintToSvg(l.layer.paint, `${idPrefix}${role}-${node.id}-${l.index}`, { node: l.node, ...role === "stroke" ? { role } : {} });
|
|
@@ -3919,7 +3935,11 @@ function getVectorAppearancePanel(state) {
|
|
|
3919
3935
|
blendMode: l.blendMode ?? "normal",
|
|
3920
3936
|
visible: l.visible !== false,
|
|
3921
3937
|
...kind === "stroke" ? { strokeWidth: l.strokeWidth ?? 1, strokeAlign: l.strokeAlign ?? "center" } : {},
|
|
3922
|
-
...(l
|
|
3938
|
+
...isVectorBrushstrokeLayer(l) ? (() => {
|
|
3939
|
+
const b = l.brush;
|
|
3940
|
+
const preset = vectorBrushstrokeBrush(b.brushId);
|
|
3941
|
+
return { brushstroke: { brushId: b.brushId, name: preset.name, size: b.size ?? preset.tip.size } };
|
|
3942
|
+
})() : (l.kind ?? "paint") !== "paint" ? { unknownKind: String(l.kind) } : {},
|
|
3923
3943
|
editing: edit.target === kind && (edit.layer === null ? index === count - 1 : edit.layer === index)
|
|
3924
3944
|
});
|
|
3925
3945
|
const fills = first ? vectorFills(first) : [];
|
|
@@ -4072,6 +4092,7 @@ var Page = class {
|
|
|
4072
4092
|
content = [];
|
|
4073
4093
|
states = /* @__PURE__ */ new Map();
|
|
4074
4094
|
shadings = /* @__PURE__ */ new Map();
|
|
4095
|
+
images = /* @__PURE__ */ new Map();
|
|
4075
4096
|
/** A graphics state with this fill / stroke alpha and blend mode, by name. */
|
|
4076
4097
|
gs(alpha, strokeAlpha, blend) {
|
|
4077
4098
|
const bm = blend ? BLEND[blend] : void 0;
|
|
@@ -4085,6 +4106,36 @@ var Page = class {
|
|
|
4085
4106
|
}
|
|
4086
4107
|
return name;
|
|
4087
4108
|
}
|
|
4109
|
+
/** An image (a PNG data URL) as an XObject with its alpha as a soft mask, by name; null when unreadable. */
|
|
4110
|
+
image(href) {
|
|
4111
|
+
const hit = this.images.get(href);
|
|
4112
|
+
if (hit) return hit;
|
|
4113
|
+
const parsed = parseDataUrl(href);
|
|
4114
|
+
if (!parsed || !isPng(parsed.bytes)) return null;
|
|
4115
|
+
let img;
|
|
4116
|
+
try {
|
|
4117
|
+
img = decodePng(parsed.bytes);
|
|
4118
|
+
} catch {
|
|
4119
|
+
return null;
|
|
4120
|
+
}
|
|
4121
|
+
const px = img.width * img.height;
|
|
4122
|
+
const rgb = new Uint8Array(px * 3);
|
|
4123
|
+
const alpha = new Uint8Array(px);
|
|
4124
|
+
for (let i = 0; i < px; i++) {
|
|
4125
|
+
rgb[i * 3] = img.data[i * 4];
|
|
4126
|
+
rgb[i * 3 + 1] = img.data[i * 4 + 1];
|
|
4127
|
+
rgb[i * 3 + 2] = img.data[i * 4 + 2];
|
|
4128
|
+
alpha[i] = img.data[i * 4 + 3];
|
|
4129
|
+
}
|
|
4130
|
+
const w = this.writer;
|
|
4131
|
+
const dims = `/Type /XObject /Subtype /Image /Width ${img.width} /Height ${img.height} /BitsPerComponent 8`;
|
|
4132
|
+
const mask = w.add(w.stream(`${dims} /ColorSpace /DeviceGray`, alpha, true));
|
|
4133
|
+
const id = w.add(w.stream(`${dims} /ColorSpace /DeviceRGB /SMask ${mask} 0 R`, rgb, true));
|
|
4134
|
+
const name = `Im${this.images.size + 1}`;
|
|
4135
|
+
this.images.set(href, name);
|
|
4136
|
+
w.imageIds.set(`${w.pageIndex}:${name}`, id);
|
|
4137
|
+
return name;
|
|
4138
|
+
}
|
|
4088
4139
|
/** Sets the fill colour (or prepares a paint server) for `paint`: returns its alpha, or a def to fill with by clipping. */
|
|
4089
4140
|
paint(paint, stroking) {
|
|
4090
4141
|
if (!paint || paint === "none") return null;
|
|
@@ -4230,6 +4281,14 @@ var Page = class {
|
|
|
4230
4281
|
for (const l of layers) {
|
|
4231
4282
|
const a = alpha * l.opacity;
|
|
4232
4283
|
const blend = l.blendMode ?? p.blendMode;
|
|
4284
|
+
if (l.kind === "brushstroke") {
|
|
4285
|
+
for (const im of l.images ?? []) {
|
|
4286
|
+
const name = this.image(im.href);
|
|
4287
|
+
if (!name) continue;
|
|
4288
|
+
this.content.push("q", `/${this.gs(a, a, blend)} gs`, `${n(im.width)} 0 0 ${n(-im.height)} ${n(im.x)} ${n(im.y + im.height)} cm`, `/${name} Do`, "Q");
|
|
4289
|
+
}
|
|
4290
|
+
continue;
|
|
4291
|
+
}
|
|
4233
4292
|
if (l.kind === "fill") {
|
|
4234
4293
|
if (l.fill !== "none") this.fill(p.d, l.fill, a, evenodd, blend);
|
|
4235
4294
|
} else if (l.stroke !== "none" && l.strokeWidth > 0) {
|
|
@@ -4247,6 +4306,7 @@ var PdfWriter = class {
|
|
|
4247
4306
|
objects = [];
|
|
4248
4307
|
gsDicts = /* @__PURE__ */ new Map();
|
|
4249
4308
|
shadingDicts = /* @__PURE__ */ new Map();
|
|
4309
|
+
imageIds = /* @__PURE__ */ new Map();
|
|
4250
4310
|
pageIndex = 0;
|
|
4251
4311
|
add(body) {
|
|
4252
4312
|
this.objects.push(body);
|
|
@@ -4332,7 +4392,8 @@ function vectorDocumentToPdf(doc, options = {}) {
|
|
|
4332
4392
|
const content = w.add(w.stream("", new TextEncoder().encode(page.content.join("\n")), compress));
|
|
4333
4393
|
const gsEntries = [...page.states.values()].map((name) => `/${name} ${w.add(w.gsDicts.get(`${k}:${name}`))} 0 R`);
|
|
4334
4394
|
const shEntries = [...page.shadings.values()].map((name) => `/${name} ${w.add(w.shadingDicts.get(`${k}:${name}`))} 0 R`);
|
|
4335
|
-
const
|
|
4395
|
+
const imEntries = [...page.images.values()].map((name) => `/${name} ${w.imageIds.get(`${k}:${name}`)} 0 R`);
|
|
4396
|
+
const resources = `<< ${gsEntries.length ? `/ExtGState << ${gsEntries.join(" ")} >> ` : ""}${shEntries.length ? `/Shading << ${shEntries.join(" ")} >> ` : ""}${imEntries.length ? `/XObject << ${imEntries.join(" ")} >>` : ""} >>`;
|
|
4336
4397
|
pageIds.push(w.add(`<< /Type /Page /Parent ${pagesId} 0 R /MediaBox [0 0 ${n(W)} ${n(H)}] /Resources ${resources} /Contents ${content} 0 R >>`));
|
|
4337
4398
|
});
|
|
4338
4399
|
w.set(catalog, `<< /Type /Catalog /Pages ${pagesId} 0 R >>`);
|
|
@@ -4517,6 +4578,7 @@ function pathItems(node, notes) {
|
|
|
4517
4578
|
function nodeGroup(node, notes) {
|
|
4518
4579
|
if (node.visible === false) return null;
|
|
4519
4580
|
if (node.filters?.length) notes.push(`${label(node)}: filters (shadows, glows, blurs) are not part of Lottie (left out).`);
|
|
4581
|
+
if (node.type === "path" && node.strokes?.some((l) => l.kind === "brushstroke" && l.visible !== false)) notes.push(`${label(node)}: brushstrokes are raster images, not part of Lottie (left out).`);
|
|
4520
4582
|
const m = nodeMatrix(node);
|
|
4521
4583
|
let items = [];
|
|
4522
4584
|
const live = (node.effects ?? []).some((e) => e.enabled !== false && (e.type === "wiggle" || e.type === "envelope" || e.type === "contour" || e.type === "blockShadow" || e.type === "extrude" || e.type === "bevel"));
|
|
@@ -8726,6 +8788,57 @@ var VectorEditorController = class _VectorEditorController {
|
|
|
8726
8788
|
merge
|
|
8727
8789
|
);
|
|
8728
8790
|
}
|
|
8791
|
+
/**
|
|
8792
|
+
* Adds a brushstroke to the selected (or given) paths: a stroke layer that paints the path with
|
|
8793
|
+
* brush `brushId` from the paint editor's library (`vectorBrushstrokeBrushes`), `size` document
|
|
8794
|
+
* units across (default the brush's own), an optional `pressure` profile along the length, in
|
|
8795
|
+
* `color` (default the top stroke's paint, else black) at `opacity`. At the top of the stroke
|
|
8796
|
+
* stack or at `index`. One undo step.
|
|
8797
|
+
*/
|
|
8798
|
+
addBrushstroke(brush, options = {}) {
|
|
8799
|
+
const clean = sanitizeVectorBrushstroke(brush);
|
|
8800
|
+
if (!clean) return { ok: false, message: `Unknown brush "${brush?.brushId}": use one of ${vectorBrushstrokeBrushes().map((b) => b.id).join(", ")}.` };
|
|
8801
|
+
if (brush.size !== void 0 && !(brush.size > 0 && brush.size <= 500)) return { ok: false, message: "size must be above 0 and at most 500 (document units)." };
|
|
8802
|
+
if (options.color !== void 0 && !parseVectorColor(options.color)) return { ok: false, message: `"${options.color}" is not a colour.` };
|
|
8803
|
+
if (options.opacity !== void 0 && !(options.opacity >= 0 && options.opacity <= 1)) return { ok: false, message: "opacity must be from 0 to 1." };
|
|
8804
|
+
return this.editStacks("stroke", options.ids, "Add Brushstroke", (stack, path) => {
|
|
8805
|
+
const top = [...stack].reverse().find((l) => (l.kind ?? "paint") === "paint");
|
|
8806
|
+
const paint = options.color ?? (typeof top?.paint === "string" && top.paint !== "none" ? top.paint : typeof path.stroke === "string" && path.stroke !== "none" ? path.stroke : "#000000");
|
|
8807
|
+
const layer = { kind: "brushstroke", paint, brush: clean, ...options.opacity !== void 0 && options.opacity < 1 ? { opacity: options.opacity } : {} };
|
|
8808
|
+
const at = options.index === void 0 ? stack.length : Math.min(stack.length, Math.max(0, Math.round(options.index)));
|
|
8809
|
+
return [...stack.slice(0, at), layer, ...stack.slice(at)];
|
|
8810
|
+
});
|
|
8811
|
+
}
|
|
8812
|
+
/**
|
|
8813
|
+
* Changes brushstroke layer `index` (in the stroke stack, 0 is the bottom) of the selected (or
|
|
8814
|
+
* given) paths: another brush, size, pressure profile (null removes it), colour or opacity.
|
|
8815
|
+
* Fails, changing nothing, when that layer is not a brushstroke. With `merge`, consecutive edits
|
|
8816
|
+
* fold into one undo step.
|
|
8817
|
+
*/
|
|
8818
|
+
setBrushstroke(index, patch, options = {}) {
|
|
8819
|
+
if (patch.brushId !== void 0 && !vectorBrushstrokeBrush(patch.brushId)) return { ok: false, message: `Unknown brush "${patch.brushId}": use one of ${vectorBrushstrokeBrushes().map((b) => b.id).join(", ")}.` };
|
|
8820
|
+
if (patch.size !== void 0 && patch.size !== null && !(patch.size > 0 && patch.size <= 500)) return { ok: false, message: "size must be above 0 and at most 500 (document units)." };
|
|
8821
|
+
if (patch.color !== void 0 && !parseVectorColor(patch.color)) return { ok: false, message: `"${patch.color}" is not a colour.` };
|
|
8822
|
+
if (patch.opacity !== void 0 && !(patch.opacity >= 0 && patch.opacity <= 1)) return { ok: false, message: "opacity must be from 0 to 1." };
|
|
8823
|
+
const merge = options.merge === true ? `brushstroke:${index}` : options.merge || void 0;
|
|
8824
|
+
return this.editStacks(
|
|
8825
|
+
"stroke",
|
|
8826
|
+
options.ids,
|
|
8827
|
+
"Edit Brushstroke",
|
|
8828
|
+
(stack, path) => {
|
|
8829
|
+
const layer = stack[index];
|
|
8830
|
+
if (!layer || layer.kind !== "brushstroke" || !layer.brush) return `Path "${path.id}" has no brushstroke at stroke ${index} (vector.getAppearance lists its strokes; 0 is the bottom).`;
|
|
8831
|
+
const brush = { ...layer.brush, ...patch.brushId ? { brushId: patch.brushId } : {} };
|
|
8832
|
+
if (patch.size === null) delete brush.size;
|
|
8833
|
+
else if (patch.size !== void 0) brush.size = patch.size;
|
|
8834
|
+
if (patch.pressure === null) delete brush.pressure;
|
|
8835
|
+
else if (patch.pressure !== void 0) brush.pressure = patch.pressure;
|
|
8836
|
+
const next = { ...layer, brush: sanitizeVectorBrushstroke(brush) ?? layer.brush, ...patch.color ? { paint: patch.color } : {}, ...patch.opacity !== void 0 ? { opacity: patch.opacity } : {} };
|
|
8837
|
+
return stack.map((l, i) => i === index ? next : l);
|
|
8838
|
+
},
|
|
8839
|
+
merge
|
|
8840
|
+
);
|
|
8841
|
+
}
|
|
8729
8842
|
/** Removes layer `index` of the fill or stroke stack of the selected (or given) paths. */
|
|
8730
8843
|
removePaintLayer(kind, index, options = {}) {
|
|
8731
8844
|
return this.editStacks(
|
|
@@ -16166,6 +16279,85 @@ function createVectorCommands(controller, options = {}) {
|
|
|
16166
16279
|
}
|
|
16167
16280
|
}
|
|
16168
16281
|
];
|
|
16282
|
+
const brushstrokeCommands = () => [
|
|
16283
|
+
{
|
|
16284
|
+
...base,
|
|
16285
|
+
id: `${prefix}listBrushes`,
|
|
16286
|
+
label: "Brushstroke Brushes",
|
|
16287
|
+
readOnly: true,
|
|
16288
|
+
keywords: ["brush", "brushstroke", "pencil", "pastel", "charcoal", "ink", "marker", "natural media"],
|
|
16289
|
+
description: "Lists the brushes a brushstroke can use (the paint editor's dry brushes): { brushes: [{ id, name, category, size }] } (size: the brush's own diameter in document units).",
|
|
16290
|
+
params: { type: "object", properties: {}, additionalProperties: false },
|
|
16291
|
+
run: () => ({ brushes: vectorBrushstrokeBrushes().map((b) => ({ id: b.id, name: b.name, category: b.category, size: b.tip.size })) })
|
|
16292
|
+
},
|
|
16293
|
+
{
|
|
16294
|
+
...base,
|
|
16295
|
+
id: `${prefix}addBrushstroke`,
|
|
16296
|
+
label: "Add Brushstroke\u2026",
|
|
16297
|
+
keywords: ["brushstroke", "brush", "natural media", "pencil line", "chalk", "sketchy", "hand-drawn", "ink stroke"],
|
|
16298
|
+
description: "Paints paths (`ids`, default the selection; groups: every path inside) with a natural-media brush along their outline, as a stroke layer of kind brushstroke: `brushId` from vector.listBrushes, `size` (document units), an optional `pressure` profile (0\u20131 values spread from start to end, e.g. [0.2, 1, 0.2] for a tapered stroke), `color` and `opacity`. The path stays editable; the strokes follow it. One undo step. Returns { paths: [{ id, strokes }] } (the brushstroke is a stroke layer; change it with vector.setBrushstroke, remove it with vector.removeStroke).",
|
|
16299
|
+
params: {
|
|
16300
|
+
type: "object",
|
|
16301
|
+
properties: {
|
|
16302
|
+
ids: { ...IDS, description: "Paths or groups (default: the selection)." },
|
|
16303
|
+
brushId: { type: "string", description: 'Brush id from vector.listBrushes, e.g. "pencil-hb".' },
|
|
16304
|
+
size: { type: "number", exclusiveMinimum: 0, maximum: 500, description: "Brush diameter in document units (default: the brush's own)." },
|
|
16305
|
+
pressure: { type: "array", items: { type: "number", minimum: 0, maximum: 1 }, minItems: 1, maxItems: 64, description: "Pressure 0\u20131 along the length, spread evenly from start to end (default: full pressure)." },
|
|
16306
|
+
color: { type: "string", description: "CSS colour (default: the path's stroke colour, else black)." },
|
|
16307
|
+
opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0\u20131 (default 1)." },
|
|
16308
|
+
index: { type: "integer", minimum: 0, description: "Position in the stroke stack, 0 the bottom (default: on top)." }
|
|
16309
|
+
},
|
|
16310
|
+
required: ["brushId"],
|
|
16311
|
+
additionalProperties: false
|
|
16312
|
+
},
|
|
16313
|
+
undoable: true,
|
|
16314
|
+
enabled: enabledFor,
|
|
16315
|
+
run: (_ctx, params) => {
|
|
16316
|
+
const targets = params.ids ?? controller.getState().selection;
|
|
16317
|
+
check2(
|
|
16318
|
+
controller.addBrushstroke(
|
|
16319
|
+
{ brushId: params.brushId, ...params.size !== void 0 ? { size: params.size } : {}, ...params.pressure ? { pressure: params.pressure } : {} },
|
|
16320
|
+
{ ...params.ids ? { ids: params.ids } : {}, ...params.index !== void 0 ? { index: params.index } : {}, ...params.color ? { color: params.color } : {}, ...params.opacity !== void 0 ? { opacity: params.opacity } : {} }
|
|
16321
|
+
)
|
|
16322
|
+
);
|
|
16323
|
+
const paths = [];
|
|
16324
|
+
for (const id of targets) {
|
|
16325
|
+
const n2 = controller.getNode(id);
|
|
16326
|
+
if (n2?.type === "path") paths.push(stackResult(id, "stroke"));
|
|
16327
|
+
}
|
|
16328
|
+
return { paths };
|
|
16329
|
+
}
|
|
16330
|
+
},
|
|
16331
|
+
{
|
|
16332
|
+
...base,
|
|
16333
|
+
id: `${prefix}setBrushstroke`,
|
|
16334
|
+
label: "Edit Brushstroke\u2026",
|
|
16335
|
+
keywords: ["brushstroke", "brush", "size", "pressure", "taper"],
|
|
16336
|
+
description: "Changes the brushstroke at stroke layer `index` of path `id` (vector.getAppearance lists strokes; 0 is the bottom): `brushId`, `size` (null: the brush's own), `pressure` (null: full pressure), `color`, `opacity`. Pass at least one. One undo step. Returns { id, strokes }.",
|
|
16337
|
+
params: {
|
|
16338
|
+
type: "object",
|
|
16339
|
+
properties: {
|
|
16340
|
+
id: { type: "string", description: "The path." },
|
|
16341
|
+
index: { type: "integer", minimum: 0, description: "Stroke layer index of the brushstroke." },
|
|
16342
|
+
brushId: { type: "string", description: "Another brush from vector.listBrushes." },
|
|
16343
|
+
size: { type: ["number", "null"], description: "Diameter in document units, or null for the brush's own." },
|
|
16344
|
+
pressure: { type: ["array", "null"], items: { type: "number", minimum: 0, maximum: 1 }, description: "Pressure profile 0\u20131 from start to end, or null for full pressure." },
|
|
16345
|
+
color: { type: "string", description: "CSS colour." },
|
|
16346
|
+
opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0\u20131." }
|
|
16347
|
+
},
|
|
16348
|
+
required: ["id", "index"],
|
|
16349
|
+
additionalProperties: false
|
|
16350
|
+
},
|
|
16351
|
+
undoable: true,
|
|
16352
|
+
run: (_ctx, params) => {
|
|
16353
|
+
const { id, index, ...patch } = params;
|
|
16354
|
+
if (!Object.keys(patch).length) fail("Pass at least one of brushId, size, pressure, color, opacity.");
|
|
16355
|
+
layerIndex(id, "stroke", index);
|
|
16356
|
+
check2(controller.setBrushstroke(index, patch, { ids: [id] }));
|
|
16357
|
+
return stackResult(id, "stroke");
|
|
16358
|
+
}
|
|
16359
|
+
}
|
|
16360
|
+
];
|
|
16169
16361
|
const pdfCommands = () => [
|
|
16170
16362
|
{
|
|
16171
16363
|
...base,
|
|
@@ -17170,6 +17362,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
17170
17362
|
...lottieCommands(),
|
|
17171
17363
|
...pdfCommands(),
|
|
17172
17364
|
...symmetryCommands(),
|
|
17365
|
+
...brushstrokeCommands(),
|
|
17173
17366
|
...stylizeCommands(),
|
|
17174
17367
|
...perspectiveCommands(),
|
|
17175
17368
|
...lensCommands(),
|
|
@@ -18378,6 +18571,7 @@ export {
|
|
|
18378
18571
|
VECTOR_BLEND_MODE_MENU,
|
|
18379
18572
|
VECTOR_BLEND_SPACINGS,
|
|
18380
18573
|
VECTOR_BLEND_SPACING_LABELS,
|
|
18574
|
+
VECTOR_BRUSHSTROKE_SCALE,
|
|
18381
18575
|
VECTOR_BUILDER_HATCH_GAP,
|
|
18382
18576
|
VECTOR_CHARACTER_STYLE_KEYS,
|
|
18383
18577
|
VECTOR_CLIPBOARD_TYPE,
|
|
@@ -18635,6 +18829,7 @@ export {
|
|
|
18635
18829
|
isValidVectorParameterName,
|
|
18636
18830
|
isVectorBlendGroup,
|
|
18637
18831
|
isVectorBlendMode,
|
|
18832
|
+
isVectorBrushstrokeLayer,
|
|
18638
18833
|
isVectorConnector,
|
|
18639
18834
|
isVectorFilterType,
|
|
18640
18835
|
isVectorFrame,
|
|
@@ -18750,6 +18945,7 @@ export {
|
|
|
18750
18945
|
sampleVectorGradient,
|
|
18751
18946
|
sampleVectorGradientAt,
|
|
18752
18947
|
sampleVectorPaintDefAt,
|
|
18948
|
+
sanitizeVectorBrushstroke,
|
|
18753
18949
|
sanitizeVectorConnector,
|
|
18754
18950
|
sanitizeVectorEffects,
|
|
18755
18951
|
sanitizeVectorFills,
|
|
@@ -18843,6 +19039,10 @@ export {
|
|
|
18843
19039
|
vectorBoundsInside,
|
|
18844
19040
|
vectorBoxCorners,
|
|
18845
19041
|
vectorBoxMatrix,
|
|
19042
|
+
vectorBrushstrokeBrush,
|
|
19043
|
+
vectorBrushstrokeBrushes,
|
|
19044
|
+
vectorBrushstrokeImages,
|
|
19045
|
+
vectorBrushstrokeReach,
|
|
18846
19046
|
vectorBuilderErasedEdges,
|
|
18847
19047
|
vectorChildAppearanceShapes,
|
|
18848
19048
|
vectorConnectionSites,
|