@pixerate/editor 0.37.0 → 0.39.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/THIRD_PARTY_NOTICES.md +7 -0
- package/dist/canvas/index.cjs +43 -25
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +16 -3
- package/dist/canvas/index.d.ts +16 -3
- package/dist/canvas/index.js +19 -1
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-HPEKB352.js → chunk-3LHWTGHW.js} +803 -23
- package/dist/chunk-3LHWTGHW.js.map +1 -0
- package/dist/{chunk-GVB7ZPLZ.cjs → chunk-VNYRI265.cjs} +806 -26
- package/dist/chunk-VNYRI265.cjs.map +1 -0
- package/dist/{stroke-ysgaPpAo.d.ts → pathfinder-D98S2lV5.d.ts} +252 -1
- package/dist/{stroke-CWjFKal4.d.cts → pathfinder-DKRcXiLS.d.cts} +252 -1
- package/dist/vector/index.cjs +867 -220
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +285 -3
- package/dist/vector/index.d.ts +285 -3
- package/dist/vector/index.js +672 -25
- package/dist/vector/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-GVB7ZPLZ.cjs.map +0 -1
- package/dist/chunk-HPEKB352.js.map +0 -1
package/dist/vector/index.cjs
CHANGED
|
@@ -34,13 +34,34 @@ var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
var _chunkVNYRI265cjs = require('../chunk-VNYRI265.cjs');
|
|
38
42
|
|
|
39
43
|
// src/vector/types.ts
|
|
40
44
|
var VECTOR_CORNER_KINDS = ["round", "inverted", "chamfer"];
|
|
41
45
|
var VECTOR_ARROWHEADS = ["triangle", "arrow", "open", "circle", "square", "bar"];
|
|
42
|
-
var VECTOR_TOOLS = [
|
|
46
|
+
var VECTOR_TOOLS = [
|
|
47
|
+
"select",
|
|
48
|
+
"direct",
|
|
49
|
+
"pen",
|
|
50
|
+
"pencil",
|
|
51
|
+
"rect",
|
|
52
|
+
"ellipse",
|
|
53
|
+
"polygon",
|
|
54
|
+
"star",
|
|
55
|
+
"line",
|
|
56
|
+
"scissors",
|
|
57
|
+
"knife",
|
|
58
|
+
"eraser",
|
|
59
|
+
"width",
|
|
60
|
+
"shapeBuilder",
|
|
61
|
+
"paintBucket"
|
|
62
|
+
];
|
|
43
63
|
var VECTOR_TRANSFORM_HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w", "rotate"];
|
|
64
|
+
var VECTOR_PATHFINDER_OPERATIONS = ["divide", "trim", "merge", "crop", "outline", "minusBack"];
|
|
44
65
|
|
|
45
66
|
// src/vector/corners.ts
|
|
46
67
|
var EPS = 1e-9;
|
|
@@ -61,7 +82,7 @@ var Side = class {
|
|
|
61
82
|
constructor(a, h1, h2, b) {
|
|
62
83
|
this.straight = onAnchor(a, h1) && onAnchor(b, h2);
|
|
63
84
|
this.curve = this.straight ? [pt(a), pt(b)] : [pt(a), pt(_nullishCoalesce(h1, () => ( a))), pt(_nullishCoalesce(h2, () => ( b))), pt(b)];
|
|
64
|
-
this.length = this.straight ? Math.hypot(b.x - a.x, b.y - a.y) :
|
|
85
|
+
this.length = this.straight ? Math.hypot(b.x - a.x, b.y - a.y) : _chunkVNYRI265cjs.segmentLength.call(void 0, this.curve);
|
|
65
86
|
}
|
|
66
87
|
/** Unit direction the side leaves the corner in (towards its first control point off the corner). */
|
|
67
88
|
direction() {
|
|
@@ -79,10 +100,10 @@ var Side = class {
|
|
|
79
100
|
const t2 = this.length > EPS ? Math.min(1, Math.max(0, s / this.length)) : 0;
|
|
80
101
|
return { t: t2, p: add(vec(this.curve[0]), mul(u, s)), dir: u };
|
|
81
102
|
}
|
|
82
|
-
const t =
|
|
83
|
-
const d = vec(
|
|
103
|
+
const t = _chunkVNYRI265cjs.segmentParamAtLength.call(void 0, this.curve, s, this.length);
|
|
104
|
+
const d = vec(_chunkVNYRI265cjs.segmentDerivative.call(void 0, this.curve, t));
|
|
84
105
|
const l = len(d);
|
|
85
|
-
return { t, p: vec(
|
|
106
|
+
return { t, p: vec(_chunkVNYRI265cjs.segmentPoint.call(void 0, this.curve, t)), dir: l > EPS ? mul(d, 1 / l) : u };
|
|
86
107
|
}
|
|
87
108
|
};
|
|
88
109
|
function cornerOf(sp, s, i) {
|
|
@@ -183,7 +204,7 @@ function expandVectorCornersOf(sp, subpath = 0) {
|
|
|
183
204
|
const s0 = from ? from.tv : 0;
|
|
184
205
|
const s1 = to ? 1 - to.tu : 1;
|
|
185
206
|
const seg = [pt(a), pt(_nullishCoalesce(a.out, () => ( a))), pt(_nullishCoalesce(b.in, () => ( b))), pt(b)];
|
|
186
|
-
const part =
|
|
207
|
+
const part = _chunkVNYRI265cjs.subSegment.call(void 0, seg, s0, Math.max(s0, s1));
|
|
187
208
|
return { out: vec(part[1]), in: vec(part[2]) };
|
|
188
209
|
});
|
|
189
210
|
const anchors = [];
|
|
@@ -344,14 +365,14 @@ function mirrorWidthProfile(points) {
|
|
|
344
365
|
function editable(points) {
|
|
345
366
|
return _optionalChain([points, 'optionalAccess', _13 => _13.length]) ? points.map((p) => ({ ...p })) : [sym(0, 1), sym(1, 1)];
|
|
346
367
|
}
|
|
347
|
-
function insertWidthPoint(points, t,
|
|
368
|
+
function insertWidthPoint(points, t, sides2 = {}, options = {}) {
|
|
348
369
|
const pts = editable(points);
|
|
349
370
|
const tt = Math.min(Math.max(Number.isFinite(t) ? t : 0, 0), 1);
|
|
350
371
|
const here = widthProfileAt(_optionalChain([points, 'optionalAccess', _14 => _14.length]) ? points : null, tt);
|
|
351
372
|
const p = {
|
|
352
373
|
t: tt,
|
|
353
|
-
left: _nullishCoalesce(clean(
|
|
354
|
-
right: _nullishCoalesce(clean(
|
|
374
|
+
left: _nullishCoalesce(clean(sides2.left, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.left)),
|
|
375
|
+
right: _nullishCoalesce(clean(sides2.right, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.right))
|
|
355
376
|
};
|
|
356
377
|
const same = pts.findIndex((q) => Math.abs(q.t - tt) <= VECTOR_WIDTH_SAME_T);
|
|
357
378
|
if (same >= 0 && !options.step) {
|
|
@@ -486,7 +507,7 @@ function flatten(segments, closed, tol) {
|
|
|
486
507
|
corner.push(isCorner);
|
|
487
508
|
};
|
|
488
509
|
for (const seg of segments) {
|
|
489
|
-
const flat =
|
|
510
|
+
const flat = _chunkVNYRI265cjs.flattenChain.call(void 0, [seg], tol);
|
|
490
511
|
if (dist(seg[0], seg[seg.length - 1]) <= 1e-12 && flat.length > 1) flat.push(seg[seg.length - 1]);
|
|
491
512
|
flat.forEach((p, i) => push(p, i === 0 || i === flat.length - 1));
|
|
492
513
|
}
|
|
@@ -576,12 +597,12 @@ function variableStrokeRings(path, options) {
|
|
|
576
597
|
const last = out[out.length - 1];
|
|
577
598
|
if (!last || dist(last, p) > 1e-12) out.push(p);
|
|
578
599
|
};
|
|
579
|
-
for (const contour of
|
|
600
|
+
for (const contour of _chunkVNYRI265cjs.pathToContours.call(void 0, path)) {
|
|
580
601
|
if (!contour.segments.length) continue;
|
|
581
602
|
const poly = flatten(contour.segments, contour.closed, Math.min(tol, half) / 4);
|
|
582
603
|
if (!poly) continue;
|
|
583
604
|
const len2 = poly.s[poly.s.length - 1];
|
|
584
|
-
const
|
|
605
|
+
const sides2 = (s) => {
|
|
585
606
|
const w = widthProfileAt(options.profile, s / len2);
|
|
586
607
|
return [w.left * half, w.right * half];
|
|
587
608
|
};
|
|
@@ -595,7 +616,7 @@ function variableStrokeRings(path, options) {
|
|
|
595
616
|
pts.push({ p: pb, s: b, corner: false });
|
|
596
617
|
const run = pts.filter((q, i) => i === 0 || dist(q.p, pts[i - 1].p) > 1e-9);
|
|
597
618
|
if (run.length < 2) {
|
|
598
|
-
const [l, r] =
|
|
619
|
+
const [l, r] = sides2(a);
|
|
599
620
|
const w2 = (l + r) / 2;
|
|
600
621
|
if (cap === "round" && w2 > 0) rings.push([[pa[0] + w2, pa[1]], ...arcPoints(pa, 0, 2 * Math.PI, w2, w2, tol)]);
|
|
601
622
|
continue;
|
|
@@ -605,7 +626,7 @@ function variableStrokeRings(path, options) {
|
|
|
605
626
|
const dirs = [];
|
|
606
627
|
for (let i = 0; i < m; i++) dirs.push(unitOf(sub2(run[i + 1].p, run[i].p)));
|
|
607
628
|
const normals = dirs.map(leftNormal);
|
|
608
|
-
const w = run.map((q) =>
|
|
629
|
+
const w = run.map((q) => sides2(q.s));
|
|
609
630
|
const side = (sigma) => {
|
|
610
631
|
const k = sigma > 0 ? 0 : 1;
|
|
611
632
|
const S = (i) => along(run[i].p, normals[i], sigma * w[i][k]);
|
|
@@ -702,7 +723,7 @@ function variableStrokeOutline(path, options) {
|
|
|
702
723
|
const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : 0.05;
|
|
703
724
|
let polygons;
|
|
704
725
|
try {
|
|
705
|
-
polygons =
|
|
726
|
+
polygons = _chunkVNYRI265cjs.polygonBoolean.call(void 0, "union", [{ rings: pieces, fillRule: "nonzero" }]);
|
|
706
727
|
} catch (e2) {
|
|
707
728
|
return [];
|
|
708
729
|
}
|
|
@@ -710,11 +731,11 @@ function variableStrokeOutline(path, options) {
|
|
|
710
731
|
for (const polygon2 of polygons) {
|
|
711
732
|
for (const ring of polygon2) {
|
|
712
733
|
if (ring.length < 3) continue;
|
|
713
|
-
const cubics =
|
|
734
|
+
const cubics = _chunkVNYRI265cjs.fitCubics.call(void 0, ring, tol, { closed: true, cornerAngleDeg: 25 });
|
|
714
735
|
if (!cubics.length) continue;
|
|
715
736
|
out.push({ type: "M", x: cubics[0].p0[0], y: cubics[0].p0[1] });
|
|
716
737
|
cubics.forEach((c, i) => {
|
|
717
|
-
if (
|
|
738
|
+
if (_chunkVNYRI265cjs.isStraightCubic.call(void 0, c, tol * 0.02)) {
|
|
718
739
|
if (i < cubics.length - 1) out.push({ type: "L", x: c.p3[0], y: c.p3[1] });
|
|
719
740
|
} else out.push({ type: "C", x1: c.p1[0], y1: c.p1[1], x2: c.p2[0], y2: c.p2[1], x: c.p3[0], y: c.p3[1] });
|
|
720
741
|
});
|
|
@@ -725,17 +746,17 @@ function variableStrokeOutline(path, options) {
|
|
|
725
746
|
}
|
|
726
747
|
function nearestStrokePosition(path, p, only) {
|
|
727
748
|
let best = null;
|
|
728
|
-
|
|
749
|
+
_chunkVNYRI265cjs.pathToContours.call(void 0, path).forEach((c, ci) => {
|
|
729
750
|
if (!c.segments.length || only !== void 0 && ci !== only) return;
|
|
730
|
-
const lengths = c.segments.map((s) =>
|
|
751
|
+
const lengths = c.segments.map((s) => _chunkVNYRI265cjs.segmentLength.call(void 0, s));
|
|
731
752
|
const total = lengths.reduce((a, b) => a + b, 0);
|
|
732
753
|
if (!(total > 0)) return;
|
|
733
754
|
let acc = 0;
|
|
734
755
|
c.segments.forEach((seg, si) => {
|
|
735
|
-
const near2 =
|
|
756
|
+
const near2 = _chunkVNYRI265cjs.segmentNearest.call(void 0, seg, p);
|
|
736
757
|
if (!best || near2.distance < best.distance) {
|
|
737
|
-
const s = acc +
|
|
738
|
-
const tan =
|
|
758
|
+
const s = acc + _chunkVNYRI265cjs.segmentLength.call(void 0, seg, 0, near2.t);
|
|
759
|
+
const tan = _chunkVNYRI265cjs.segmentTangent.call(void 0, seg, near2.t);
|
|
739
760
|
const pt2 = seg.length === 2 ? lerp(seg[0], seg[1], near2.t) : evalSeg(seg, near2.t);
|
|
740
761
|
const n = leftNormal([tan[0], tan[1]]);
|
|
741
762
|
const side = (p[0] - pt2[0]) * n[0] + (p[1] - pt2[1]) * n[1] >= 0 ? "left" : "right";
|
|
@@ -752,9 +773,9 @@ function evalSeg(seg, t) {
|
|
|
752
773
|
return pts[0];
|
|
753
774
|
}
|
|
754
775
|
function strokePositionPoint(path, index, t) {
|
|
755
|
-
const c =
|
|
776
|
+
const c = _chunkVNYRI265cjs.pathToContours.call(void 0, path)[index];
|
|
756
777
|
if (!_optionalChain([c, 'optionalAccess', _22 => _22.segments, 'access', _23 => _23.length])) return null;
|
|
757
|
-
const lengths = c.segments.map((s) =>
|
|
778
|
+
const lengths = c.segments.map((s) => _chunkVNYRI265cjs.segmentLength.call(void 0, s));
|
|
758
779
|
const total = lengths.reduce((a, b) => a + b, 0);
|
|
759
780
|
let want = Math.min(Math.max(t, 0), 1) * total;
|
|
760
781
|
for (let i = 0; i < c.segments.length; i++) {
|
|
@@ -765,11 +786,11 @@ function strokePositionPoint(path, index, t) {
|
|
|
765
786
|
const target = Math.min(want, lengths[i]);
|
|
766
787
|
for (let k = 0; k < 40; k++) {
|
|
767
788
|
const mid = (lo + hi) / 2;
|
|
768
|
-
if (
|
|
789
|
+
if (_chunkVNYRI265cjs.segmentLength.call(void 0, seg, 0, mid) < target) lo = mid;
|
|
769
790
|
else hi = mid;
|
|
770
791
|
}
|
|
771
792
|
const u = (lo + hi) / 2;
|
|
772
|
-
const tan =
|
|
793
|
+
const tan = _chunkVNYRI265cjs.segmentTangent.call(void 0, seg, u);
|
|
773
794
|
return { point: evalSeg(seg, u), tangent: [tan[0], tan[1]] };
|
|
774
795
|
}
|
|
775
796
|
want -= lengths[i];
|
|
@@ -781,7 +802,7 @@ function strokePositionPoint(path, index, t) {
|
|
|
781
802
|
var KAPPA = 0.5522847498307936;
|
|
782
803
|
var NOTCH = 0.7;
|
|
783
804
|
function isClosedBezierShape(path) {
|
|
784
|
-
const contours =
|
|
805
|
+
const contours = _chunkVNYRI265cjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
|
|
785
806
|
return contours.length > 0 && contours.every((c) => c.closed);
|
|
786
807
|
}
|
|
787
808
|
function effectiveStrokeAlign(style, closedShape) {
|
|
@@ -802,7 +823,7 @@ function vectorStrokeLineArea(parts, style, tolerance) {
|
|
|
802
823
|
const join = _nullishCoalesce(style.strokeLinejoin, () => ( "miter"));
|
|
803
824
|
const cap = _nullishCoalesce(style.strokeLinecap, () => ( "butt"));
|
|
804
825
|
if (profile) return variableStrokeOutline(parts.line, { width: parts.drawWidth, profile, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
|
|
805
|
-
return
|
|
826
|
+
return _chunkVNYRI265cjs.outlineStroke.call(void 0, parts.line, { width: parts.drawWidth, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
|
|
806
827
|
}
|
|
807
828
|
var capExtent = (style, width) => style.strokeLinecap === "round" || style.strokeLinecap === "square" ? width / 2 : 0;
|
|
808
829
|
function arrowheadWeight(style, end) {
|
|
@@ -879,16 +900,16 @@ function arrowheadPath(kind, tip, dir, hw) {
|
|
|
879
900
|
}
|
|
880
901
|
}
|
|
881
902
|
var toVec = (p) => ({ x: p[0], y: p[1] });
|
|
882
|
-
var segLen = (s) =>
|
|
903
|
+
var segLen = (s) => _chunkVNYRI265cjs.segmentLength.call(void 0, s);
|
|
883
904
|
function endOf(segs, atStart) {
|
|
884
905
|
const long = (s2) => segLen(s2) > 1e-9;
|
|
885
906
|
if (atStart) {
|
|
886
907
|
const s2 = _nullishCoalesce(segs.find(long), () => ( segs[0]));
|
|
887
|
-
const t2 =
|
|
908
|
+
const t2 = _chunkVNYRI265cjs.segmentTangent.call(void 0, s2, 0);
|
|
888
909
|
return { p: toVec(segs[0][0]), out: v(-t2[0], -t2[1]) };
|
|
889
910
|
}
|
|
890
911
|
const s = _nullishCoalesce([...segs].reverse().find(long), () => ( segs[segs.length - 1]));
|
|
891
|
-
const t =
|
|
912
|
+
const t = _chunkVNYRI265cjs.segmentTangent.call(void 0, s, 1);
|
|
892
913
|
const last = segs[segs.length - 1];
|
|
893
914
|
return { p: toVec(last[last.length - 1]), out: v(t[0], t[1]) };
|
|
894
915
|
}
|
|
@@ -899,7 +920,7 @@ function pointAlong(segs, fromStart, dist4) {
|
|
|
899
920
|
const l = segLen(s);
|
|
900
921
|
if (acc + l >= dist4) {
|
|
901
922
|
const want = fromStart ? dist4 - acc : l - (dist4 - acc);
|
|
902
|
-
const pts =
|
|
923
|
+
const pts = _chunkVNYRI265cjs.trimSegments.call(void 0, [s], 0, want);
|
|
903
924
|
const p = pts.length ? pts[0][pts[0].length - 1] : s[0];
|
|
904
925
|
return toVec(p);
|
|
905
926
|
}
|
|
@@ -909,7 +930,7 @@ function pointAlong(segs, fromStart, dist4) {
|
|
|
909
930
|
}
|
|
910
931
|
function vectorStrokeParts(path, style) {
|
|
911
932
|
const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
|
|
912
|
-
const contours =
|
|
933
|
+
const contours = _chunkVNYRI265cjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
|
|
913
934
|
const closedShape = contours.length > 0 && contours.every((c) => c.closed);
|
|
914
935
|
const align = effectiveStrokeAlign(style, closedShape);
|
|
915
936
|
const drawWidth = align === "center" ? width : width * 2;
|
|
@@ -949,26 +970,26 @@ function vectorStrokeParts(path, style) {
|
|
|
949
970
|
if (!s0 && !s1) return c;
|
|
950
971
|
const lengths = c.segments.map(segLen);
|
|
951
972
|
const total = lengths.reduce((a, b) => a + b, 0);
|
|
952
|
-
return { closed: false, segments: total - s1 > s0 ?
|
|
973
|
+
return { closed: false, segments: total - s1 > s0 ? _chunkVNYRI265cjs.trimSegments.call(void 0, c.segments, s0, total - s1, lengths) : [] };
|
|
953
974
|
});
|
|
954
|
-
return { align, line:
|
|
975
|
+
return { align, line: _chunkVNYRI265cjs.contoursToPath.call(void 0, trimmed), drawWidth, heads };
|
|
955
976
|
}
|
|
956
977
|
function vectorStrokeOutlinePath(path, style) {
|
|
957
978
|
const parts = vectorStrokeParts(path, style);
|
|
958
979
|
const stroke = vectorStrokeLineArea(parts, style);
|
|
959
980
|
const fill = { path, fillRule: _nullishCoalesce(style.fillRule, () => ( "nonzero")) };
|
|
960
981
|
let area = stroke;
|
|
961
|
-
if (parts.align === "inside") area =
|
|
962
|
-
else if (parts.align === "outside") area =
|
|
982
|
+
if (parts.align === "inside") area = _chunkVNYRI265cjs.pathBoolean.call(void 0, "intersection", [stroke, fill]).path;
|
|
983
|
+
else if (parts.align === "outside") area = _chunkVNYRI265cjs.pathBoolean.call(void 0, "difference", [stroke, fill]).path;
|
|
963
984
|
if (!parts.heads.length) return area;
|
|
964
|
-
return
|
|
985
|
+
return _chunkVNYRI265cjs.pathBoolean.call(void 0, "union", [area, ...parts.heads.map((h) => h.path)]).path;
|
|
965
986
|
}
|
|
966
987
|
function hitTestVectorStroke(path, p, style, tolerance = 0) {
|
|
967
988
|
const parts = vectorStrokeParts(path, style);
|
|
968
989
|
const point = [p.x, p.y];
|
|
969
990
|
const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
|
|
970
991
|
for (const h of parts.heads) {
|
|
971
|
-
if (
|
|
992
|
+
if (_chunkVNYRI265cjs.pointInBezierPath.call(void 0, h.path, point) || tolerance > 0 && _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, h.path, point) <= tolerance) return true;
|
|
972
993
|
}
|
|
973
994
|
if (!parts.line.length) return false;
|
|
974
995
|
const profile = strokeWidthProfileOf(style);
|
|
@@ -986,13 +1007,13 @@ function hitTestVectorStroke(path, p, style, tolerance = 0) {
|
|
|
986
1007
|
reach = Math.max(reach, width / 2 * (w.left + w.right) / 2);
|
|
987
1008
|
}
|
|
988
1009
|
} else {
|
|
989
|
-
d =
|
|
1010
|
+
d = _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, parts.line, point);
|
|
990
1011
|
if (parts.align !== "center") reach = width;
|
|
991
1012
|
}
|
|
992
1013
|
if (parts.align === "center") return d <= reach + tolerance;
|
|
993
1014
|
if (d > reach + tolerance) return false;
|
|
994
1015
|
if (d <= tolerance) return true;
|
|
995
|
-
const inside =
|
|
1016
|
+
const inside = _chunkVNYRI265cjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(style.fillRule, () => ( "nonzero")));
|
|
996
1017
|
return parts.align === "inside" ? inside : !inside;
|
|
997
1018
|
}
|
|
998
1019
|
function vectorStrokeReach(style) {
|
|
@@ -1068,7 +1089,7 @@ function vectorNodeToBezier(node) {
|
|
|
1068
1089
|
}
|
|
1069
1090
|
function vectorPathData(input, precision = 3) {
|
|
1070
1091
|
const subpaths = Array.isArray(input) ? input : input.subpaths;
|
|
1071
|
-
return
|
|
1092
|
+
return _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, subpathsToBezier(subpaths), { precision });
|
|
1072
1093
|
}
|
|
1073
1094
|
function inferAnchorType(a) {
|
|
1074
1095
|
if (isOnAnchor(a, a.in) || isOnAnchor(a, a.out)) return "corner";
|
|
@@ -1084,7 +1105,7 @@ function inferAnchorType(a) {
|
|
|
1084
1105
|
return Math.abs(li - lo) <= 1e-3 * Math.max(li, lo) ? "symmetric" : "smooth";
|
|
1085
1106
|
}
|
|
1086
1107
|
function bezierToSubpaths(input) {
|
|
1087
|
-
const path =
|
|
1108
|
+
const path = _chunkVNYRI265cjs.toBezierPath.call(void 0, input);
|
|
1088
1109
|
const out = [];
|
|
1089
1110
|
let current = null;
|
|
1090
1111
|
const last = () => current.anchors[current.anchors.length - 1];
|
|
@@ -1181,14 +1202,14 @@ function nodeMatrix(node) {
|
|
|
1181
1202
|
function vectorPathWorldBezier(node, parent = IDENTITY_MATRIX) {
|
|
1182
1203
|
const m = multiplyMatrices(nodeMatrix(node), parent);
|
|
1183
1204
|
const path = subpathsToBezier(node.subpaths);
|
|
1184
|
-
return isIdentityMatrix(m) ? path :
|
|
1205
|
+
return isIdentityMatrix(m) ? path : _chunkVNYRI265cjs.transformBezierPath.call(void 0, path, m);
|
|
1185
1206
|
}
|
|
1186
1207
|
function vectorNodeBounds(node, parent = IDENTITY_MATRIX) {
|
|
1187
1208
|
if (node.type === "group") {
|
|
1188
1209
|
const m = multiplyMatrices(nodeMatrix(node), parent);
|
|
1189
1210
|
return unionBounds(node.children.map((c) => vectorNodeBounds(c, m)));
|
|
1190
1211
|
}
|
|
1191
|
-
const b =
|
|
1212
|
+
const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, vectorPathWorldBezier(node, parent));
|
|
1192
1213
|
if (!b) return null;
|
|
1193
1214
|
return { x: b.minX, y: b.minY, width: b.maxX - b.minX, height: b.maxY - b.minY };
|
|
1194
1215
|
}
|
|
@@ -1222,9 +1243,9 @@ function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX) {
|
|
|
1222
1243
|
const path = vectorPathWorldBezier(node, parent);
|
|
1223
1244
|
if (path.length === 0) return false;
|
|
1224
1245
|
const point = [p.x, p.y];
|
|
1225
|
-
if (hasPaint(node.fill) &&
|
|
1246
|
+
if (hasPaint(node.fill) && _chunkVNYRI265cjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(node.fillRule, () => ( "nonzero")))) return true;
|
|
1226
1247
|
if (hasPaint(node.stroke)) return hitTestVectorStroke(path, p, node, tolerance);
|
|
1227
|
-
return
|
|
1248
|
+
return _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, path, point) <= tolerance;
|
|
1228
1249
|
}
|
|
1229
1250
|
function vectorStrokeOutline(node, parent = IDENTITY_MATRIX) {
|
|
1230
1251
|
if (!hasPaint(node.stroke) || !((_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0)) return [];
|
|
@@ -1244,9 +1265,9 @@ function nearestSegment(node, p) {
|
|
|
1244
1265
|
const count = subpathSegmentCount(sp);
|
|
1245
1266
|
for (let i = 0; i < count; i++) {
|
|
1246
1267
|
const seg = subpathSegment(sp, i);
|
|
1247
|
-
const hit =
|
|
1268
|
+
const hit = _chunkVNYRI265cjs.segmentNearest.call(void 0, seg, [p.x, p.y]);
|
|
1248
1269
|
if (!best || hit.distance < best.distance) {
|
|
1249
|
-
const pt2 =
|
|
1270
|
+
const pt2 = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, hit.t);
|
|
1250
1271
|
best = { subpath: s, segment: i, t: hit.t, point: { x: pt2[0], y: pt2[1] }, distance: hit.distance };
|
|
1251
1272
|
}
|
|
1252
1273
|
}
|
|
@@ -1420,7 +1441,7 @@ function insertAnchor(sp, segment, t) {
|
|
|
1420
1441
|
const ia = segment;
|
|
1421
1442
|
const ib = (segment + 1) % n;
|
|
1422
1443
|
const seg = subpathSegment(sp, segment);
|
|
1423
|
-
const [left, right] =
|
|
1444
|
+
const [left, right] = _chunkVNYRI265cjs.splitSegment.call(void 0, seg, t);
|
|
1424
1445
|
const mid = left[left.length - 1];
|
|
1425
1446
|
const anchor = { x: mid[0], y: mid[1] };
|
|
1426
1447
|
if (seg.length === 4) {
|
|
@@ -1474,8 +1495,8 @@ function ellipseSubpath(b) {
|
|
|
1474
1495
|
]
|
|
1475
1496
|
};
|
|
1476
1497
|
}
|
|
1477
|
-
function polygonSubpath(b,
|
|
1478
|
-
const n = Math.max(3, Math.round(
|
|
1498
|
+
function polygonSubpath(b, sides2 = 6) {
|
|
1499
|
+
const n = Math.max(3, Math.round(sides2));
|
|
1479
1500
|
const cx = b.x + b.width / 2;
|
|
1480
1501
|
const cy = b.y + b.height / 2;
|
|
1481
1502
|
const anchors = [];
|
|
@@ -1516,7 +1537,7 @@ function vectorCornersAttribute(subpaths, precision = 3) {
|
|
|
1516
1537
|
subpaths.forEach(
|
|
1517
1538
|
(sp, s) => sp.anchors.forEach((a, i) => {
|
|
1518
1539
|
if (!a.corner || !(a.corner.radius > 0)) return;
|
|
1519
|
-
out.push(`${s}.${i}:${
|
|
1540
|
+
out.push(`${s}.${i}:${_chunkVNYRI265cjs.formatNumber.call(void 0, a.corner.radius, precision)}${a.corner.kind && a.corner.kind !== "round" ? `:${a.corner.kind}` : ""}`);
|
|
1520
1541
|
})
|
|
1521
1542
|
);
|
|
1522
1543
|
return out.join(" ");
|
|
@@ -1537,7 +1558,7 @@ var escapeAttr = (value) => value.replace(/&/g, "&").replace(/"/g, """)
|
|
|
1537
1558
|
function vectorPaintToSvg(paint, gradientId) {
|
|
1538
1559
|
if (!hasPaint(paint)) return { value: "none", gradient: null };
|
|
1539
1560
|
if (typeof paint === "string") return { value: paint, gradient: null };
|
|
1540
|
-
return { value: `url(#${gradientId})`, gradient:
|
|
1561
|
+
return { value: `url(#${gradientId})`, gradient: _chunkVNYRI265cjs.gradientToSvgDef.call(void 0, paint, gradientId) };
|
|
1541
1562
|
}
|
|
1542
1563
|
var partsCache = /* @__PURE__ */ new WeakMap();
|
|
1543
1564
|
function vectorStrokeSvgParts(node, clipId, precision = 3) {
|
|
@@ -1555,22 +1576,22 @@ function computeStrokeSvgParts(node, clipId, precision) {
|
|
|
1555
1576
|
if (parts.align === "center" && !parts.heads.length && !profiled) return void 0;
|
|
1556
1577
|
let clip = null;
|
|
1557
1578
|
if (parts.align !== "center") {
|
|
1558
|
-
const b =
|
|
1579
|
+
const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, path);
|
|
1559
1580
|
const pad = vectorStrokeReach(node) + 1;
|
|
1560
1581
|
const bounds = b ? { x: round2(b.minX - pad), y: round2(b.minY - pad), width: round2(b.maxX - b.minX + 2 * pad), height: round2(b.maxY - b.minY + 2 * pad) } : { x: 0, y: 0, width: 0, height: 0 };
|
|
1561
1582
|
clip = { kind: parts.align === "inside" ? "clip" : "mask", id: clipId, bounds };
|
|
1562
1583
|
}
|
|
1563
1584
|
return {
|
|
1564
1585
|
align: parts.align,
|
|
1565
|
-
d:
|
|
1586
|
+
d: _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, parts.line, { precision }),
|
|
1566
1587
|
width: parts.drawWidth,
|
|
1567
|
-
...profiled && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0 ? { outline:
|
|
1588
|
+
...profiled && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0 ? { outline: _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, vectorStrokeLineArea(parts, node), { precision }) } : {},
|
|
1568
1589
|
clip,
|
|
1569
|
-
heads: parts.heads.map((h) =>
|
|
1590
|
+
heads: parts.heads.map((h) => _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, h.path, { precision }))
|
|
1570
1591
|
};
|
|
1571
1592
|
}
|
|
1572
1593
|
function widthProfileToAttribute(points, precision = 4) {
|
|
1573
|
-
return points.map((p) => [p.t, p.left, p.right].map((n) =>
|
|
1594
|
+
return points.map((p) => [p.t, p.left, p.right].map((n) => _chunkVNYRI265cjs.formatNumber.call(void 0, n, precision)).join(",")).join(";");
|
|
1574
1595
|
}
|
|
1575
1596
|
function widthProfileFromAttribute(value) {
|
|
1576
1597
|
if (!value) return [];
|
|
@@ -1594,11 +1615,11 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
1594
1615
|
const pretty = options.pretty !== false;
|
|
1595
1616
|
const defs = [];
|
|
1596
1617
|
const lines = [];
|
|
1597
|
-
const num = (n) =>
|
|
1618
|
+
const num = (n) => _chunkVNYRI265cjs.formatNumber.call(void 0, n, precision);
|
|
1598
1619
|
const indent = (depth) => pretty ? " ".repeat(depth) : "";
|
|
1599
1620
|
const common = (node) => {
|
|
1600
1621
|
let out2 = ` id="${escapeAttr(node.id)}"`;
|
|
1601
|
-
if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) =>
|
|
1622
|
+
if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) => _chunkVNYRI265cjs.formatNumber.call(void 0, n, 6)).join(" ")})"`;
|
|
1602
1623
|
if (node.opacity !== void 0 && node.opacity < 1) out2 += ` opacity="${num(node.opacity)}"`;
|
|
1603
1624
|
if (node.visible === false) out2 += ` display="none"`;
|
|
1604
1625
|
return out2;
|
|
@@ -1617,7 +1638,7 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
1617
1638
|
if (stroke.gradient) defs.push(gradientMarkup(stroke.gradient));
|
|
1618
1639
|
const d = vectorPathData(node, precision);
|
|
1619
1640
|
const corners2 = vectorCornersAttribute(node.subpaths, precision);
|
|
1620
|
-
const live = corners2 ? ` data-vector-d="${
|
|
1641
|
+
const live = corners2 ? ` data-vector-d="${_chunkVNYRI265cjs.bezierPathToSvg.call(void 0, subpathsToBezier(node.subpaths, { corners: false }), { precision })}" data-vector-corners="${corners2}"` : "";
|
|
1621
1642
|
const fillAttrs = ` fill="${escapeAttr(fill.value)}"${node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : ""}`;
|
|
1622
1643
|
const lineAttrs = (width) => {
|
|
1623
1644
|
let out2 = ` stroke="${escapeAttr(stroke.value)}" stroke-width="${num(width)}"`;
|
|
@@ -1648,7 +1669,7 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
1648
1669
|
lines.push(`${indent(depth)}<g${common(node)}${data}>`);
|
|
1649
1670
|
lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
|
|
1650
1671
|
if (options.strokes === "outline") {
|
|
1651
|
-
const area =
|
|
1672
|
+
const area = _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
|
|
1652
1673
|
lines.push(`${indent(depth + 1)}<path data-vector-part="stroke-outline" d="${area}" fill="${escapeAttr(stroke.value)}"/>`);
|
|
1653
1674
|
} else {
|
|
1654
1675
|
let clip = "";
|
|
@@ -2373,13 +2394,13 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
2373
2394
|
const pt2 = toPoint(p);
|
|
2374
2395
|
for (const s of this.segments) {
|
|
2375
2396
|
if (p.x < s.minX - tol || p.x > s.maxX + tol || p.y < s.minY - tol || p.y > s.maxY + tol) continue;
|
|
2376
|
-
const hit =
|
|
2397
|
+
const hit = _chunkVNYRI265cjs.segmentNearest.call(void 0, s.seg, pt2);
|
|
2377
2398
|
if (hit.distance <= tol) out.push({ seg: s.seg, t: hit.t, distance: hit.distance });
|
|
2378
2399
|
}
|
|
2379
2400
|
return out.sort((a, b) => a.distance - b.distance);
|
|
2380
2401
|
}
|
|
2381
2402
|
onSegment(near2) {
|
|
2382
|
-
return near2.length ? toVec2(
|
|
2403
|
+
return near2.length ? toVec2(_chunkVNYRI265cjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
|
|
2383
2404
|
}
|
|
2384
2405
|
/** Where two of the target segments near `p` cross, the crossing nearest `p` within `tol`. */
|
|
2385
2406
|
crossing(near2, p, tol) {
|
|
@@ -2388,7 +2409,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
2388
2409
|
let bestD = Infinity;
|
|
2389
2410
|
for (let i = 0; i < list.length; i++) {
|
|
2390
2411
|
for (let j = i + 1; j < list.length; j++) {
|
|
2391
|
-
for (const hit of
|
|
2412
|
+
for (const hit of _chunkVNYRI265cjs.segmentIntersections.call(void 0, list[i].seg, list[j].seg)) {
|
|
2392
2413
|
const q = toVec2(hit.point);
|
|
2393
2414
|
const d = distance(q, p);
|
|
2394
2415
|
if (d <= tol && d < bestD) {
|
|
@@ -2710,15 +2731,15 @@ var crossCondition = (r, d) => r[0] * d[1] - r[1] * d[0];
|
|
|
2710
2731
|
function solveOnSegment(seg, base, cond) {
|
|
2711
2732
|
const b = [base.x, base.y];
|
|
2712
2733
|
const g = (t) => {
|
|
2713
|
-
const p =
|
|
2714
|
-
return cond([p[0] - b[0], p[1] - b[1]],
|
|
2734
|
+
const p = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
|
|
2735
|
+
return cond([p[0] - b[0], p[1] - b[1]], _chunkVNYRI265cjs.segmentDerivative.call(void 0, seg, t));
|
|
2715
2736
|
};
|
|
2716
2737
|
const vals = [];
|
|
2717
2738
|
let scale = 0;
|
|
2718
2739
|
for (let i = 0; i <= CURVE_SAMPLES; i++) {
|
|
2719
2740
|
const t = i / CURVE_SAMPLES;
|
|
2720
|
-
const p =
|
|
2721
|
-
const d =
|
|
2741
|
+
const p = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
|
|
2742
|
+
const d = _chunkVNYRI265cjs.segmentDerivative.call(void 0, seg, t);
|
|
2722
2743
|
const r = [p[0] - b[0], p[1] - b[1]];
|
|
2723
2744
|
vals.push(cond(r, d));
|
|
2724
2745
|
scale = Math.max(scale, Math.hypot(r[0], r[1]) * Math.hypot(d[0], d[1]));
|
|
@@ -2745,8 +2766,8 @@ function solveOnSegment(seg, base, cond) {
|
|
|
2745
2766
|
} else hi = m;
|
|
2746
2767
|
}
|
|
2747
2768
|
const t = (lo + hi) / 2;
|
|
2748
|
-
const p =
|
|
2749
|
-
const dv =
|
|
2769
|
+
const p = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
|
|
2770
|
+
const dv = _chunkVNYRI265cjs.segmentDerivative.call(void 0, seg, t);
|
|
2750
2771
|
const r = Math.hypot(p[0] - b[0], p[1] - b[1]);
|
|
2751
2772
|
const dl = Math.hypot(dv[0], dv[1]);
|
|
2752
2773
|
if (!(r > 1e-9 && dl > 0) || Math.abs(cond([p[0] - b[0], p[1] - b[1]], dv)) > 1e-6 * r * dl) continue;
|
|
@@ -2783,7 +2804,7 @@ function endTangent(c) {
|
|
|
2783
2804
|
return [1, 0];
|
|
2784
2805
|
}
|
|
2785
2806
|
function sample(c, n, out, withStart) {
|
|
2786
|
-
for (let i = withStart ? 0 : 1; i <= n; i++) out.push(
|
|
2807
|
+
for (let i = withStart ? 0 : 1; i <= n; i++) out.push(_chunkVNYRI265cjs.segmentPoint.call(void 0, c, i / n));
|
|
2787
2808
|
}
|
|
2788
2809
|
var onAnchor2 = (a, h) => !h || Math.abs(h.x - a.x) < EPS3 && Math.abs(h.y - a.y) < EPS3;
|
|
2789
2810
|
function tidy(a, keepType = true) {
|
|
@@ -2829,7 +2850,7 @@ function fitAcross(pts, N, t0, t1) {
|
|
|
2829
2850
|
const u = [];
|
|
2830
2851
|
for (let i = 0; i <= N; i++) u.push(k * i / N);
|
|
2831
2852
|
for (let i = 1; i <= N; i++) u.push(k + (1 - k) * i / N);
|
|
2832
|
-
return
|
|
2853
|
+
return _chunkVNYRI265cjs.fitCubicWithTangents.call(void 0, pts, u, t0, t1);
|
|
2833
2854
|
};
|
|
2834
2855
|
return goldenMin(fit, 0, 1);
|
|
2835
2856
|
}
|
|
@@ -2889,7 +2910,7 @@ function bendSegment(sp, segment, t, p) {
|
|
|
2889
2910
|
return { anchors, closed: sp.closed };
|
|
2890
2911
|
}
|
|
2891
2912
|
function subpathPointAt(sp, segment, t) {
|
|
2892
|
-
const [x, y] =
|
|
2913
|
+
const [x, y] = _chunkVNYRI265cjs.segmentPoint.call(void 0, subpathSegment(sp, segment), t);
|
|
2893
2914
|
return { x, y };
|
|
2894
2915
|
}
|
|
2895
2916
|
function curvatureMoveAnchor(sp, index, q) {
|
|
@@ -3150,20 +3171,20 @@ function removeRedundantPoints(sp, tolerance) {
|
|
|
3150
3171
|
}
|
|
3151
3172
|
|
|
3152
3173
|
// src/vector/pathCut.ts
|
|
3153
|
-
var loopArea = (l) =>
|
|
3174
|
+
var loopArea = (l) => _chunkVNYRI265cjs.contourSignedArea.call(void 0, l.segs);
|
|
3154
3175
|
function loopSample(l) {
|
|
3155
3176
|
const k = l.chord.findIndex((c) => !c);
|
|
3156
|
-
return
|
|
3177
|
+
return _chunkVNYRI265cjs.segmentPoint.call(void 0, l.segs[k >= 0 ? k : 0], 0.5);
|
|
3157
3178
|
}
|
|
3158
|
-
var contains2 = (l, p) =>
|
|
3179
|
+
var contains2 = (l, p) => _chunkVNYRI265cjs.windingNumber.call(void 0, [l.segs], p) !== 0;
|
|
3159
3180
|
function groupFaces(loops) {
|
|
3160
|
-
const
|
|
3161
|
-
if (!
|
|
3162
|
-
const largest =
|
|
3181
|
+
const usable2 = loops.filter((l) => l.segs.length && Math.abs(loopArea(l)) > 1e-12);
|
|
3182
|
+
if (!usable2.length) return [];
|
|
3183
|
+
const largest = usable2.reduce((a, b) => Math.abs(loopArea(b)) > Math.abs(loopArea(a)) ? b : a);
|
|
3163
3184
|
const sign = Math.sign(loopArea(largest));
|
|
3164
|
-
const outers =
|
|
3185
|
+
const outers = usable2.filter((l) => Math.sign(loopArea(l)) === sign).sort((a, b) => Math.abs(loopArea(a)) - Math.abs(loopArea(b)));
|
|
3165
3186
|
const faces = new Map(outers.map((o) => [o, { loops: [o] }]));
|
|
3166
|
-
for (const hole of
|
|
3187
|
+
for (const hole of usable2.filter((l) => Math.sign(loopArea(l)) !== sign)) {
|
|
3167
3188
|
const p = loopSample(hole);
|
|
3168
3189
|
const parent = outers.find((o) => Math.abs(loopArea(o)) > Math.abs(loopArea(hole)) && contains2(o, p));
|
|
3169
3190
|
if (parent) faces.get(parent).loops.push(hole);
|
|
@@ -3171,12 +3192,12 @@ function groupFaces(loops) {
|
|
|
3171
3192
|
return outers.reverse().map((o) => faces.get(o));
|
|
3172
3193
|
}
|
|
3173
3194
|
function faceToPath(face) {
|
|
3174
|
-
return
|
|
3195
|
+
return _chunkVNYRI265cjs.contoursToPath.call(void 0, face.loops.map((l) => ({ segments: l.segs, closed: true })));
|
|
3175
3196
|
}
|
|
3176
3197
|
function facesOf(path, fillRule) {
|
|
3177
|
-
const normalized =
|
|
3178
|
-
const loops =
|
|
3179
|
-
const segs =
|
|
3198
|
+
const normalized = _chunkVNYRI265cjs.normalizeBezierPath.call(void 0, path, fillRule);
|
|
3199
|
+
const loops = _chunkVNYRI265cjs.pathToContours.call(void 0, normalized).map((c) => {
|
|
3200
|
+
const segs = _chunkVNYRI265cjs.closeContour.call(void 0, c, true).map((s) => s.slice());
|
|
3180
3201
|
return { segs, chord: segs.map(() => false) };
|
|
3181
3202
|
});
|
|
3182
3203
|
return groupFaces(loops);
|
|
@@ -3246,7 +3267,7 @@ function lineHits(p, q, seg) {
|
|
|
3246
3267
|
const scale = Math.sqrt(len2) * Math.max(1, ...seg.map((pt2) => Math.abs(pt2[0]) + Math.abs(pt2[1])));
|
|
3247
3268
|
const out = [];
|
|
3248
3269
|
for (const t of rootsInUnit(...coeffs, scale)) {
|
|
3249
|
-
const point =
|
|
3270
|
+
const point = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
|
|
3250
3271
|
const s = ((point[0] - p[0]) * dx + (point[1] - p[1]) * dy) / len2;
|
|
3251
3272
|
if (s >= -1e-9 && s <= 1 + 1e-9) out.push({ s: Math.min(1, Math.max(0, s)), t, point });
|
|
3252
3273
|
}
|
|
@@ -3259,7 +3280,7 @@ function arc(l, a, b, eps) {
|
|
|
3259
3280
|
const segs = [];
|
|
3260
3281
|
const chord = [];
|
|
3261
3282
|
const push = (k, t0, t1) => {
|
|
3262
|
-
const piece = t0 <= 0 && t1 >= 1 ? l.segs[k].slice() :
|
|
3283
|
+
const piece = t0 <= 0 && t1 >= 1 ? l.segs[k].slice() : _chunkVNYRI265cjs.subSegment.call(void 0, l.segs[k], t0, t1);
|
|
3263
3284
|
if (!degenerate(piece, eps)) {
|
|
3264
3285
|
segs.push(piece);
|
|
3265
3286
|
chord.push(l.chord[k]);
|
|
@@ -3284,7 +3305,7 @@ function knifePath(path, fillRule, knife) {
|
|
|
3284
3305
|
if (pts.length < 2) return null;
|
|
3285
3306
|
let faces = facesOf(path, fillRule);
|
|
3286
3307
|
if (!faces.length) return null;
|
|
3287
|
-
const b =
|
|
3308
|
+
const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, path);
|
|
3288
3309
|
const size = b ? Math.max(b.maxX - b.minX, b.maxY - b.minY, 1) : 1;
|
|
3289
3310
|
const eps = size * 1e-9;
|
|
3290
3311
|
let cursor = -Infinity;
|
|
@@ -3298,7 +3319,7 @@ function knifePath(path, fillRule, knife) {
|
|
|
3298
3319
|
const kb = { minX: Math.min(pts[m][0], pts[m + 1][0]), maxX: Math.max(pts[m][0], pts[m + 1][0]), minY: Math.min(pts[m][1], pts[m + 1][1]), maxY: Math.max(pts[m][1], pts[m + 1][1]) };
|
|
3299
3320
|
face2.loops.forEach(
|
|
3300
3321
|
(l, li) => l.segs.forEach((seg, si) => {
|
|
3301
|
-
const sb =
|
|
3322
|
+
const sb = _chunkVNYRI265cjs.segmentBounds.call(void 0, seg);
|
|
3302
3323
|
if (sb.maxX < kb.minX - eps || sb.minX > kb.maxX + eps || sb.maxY < kb.minY - eps || sb.minY > kb.maxY + eps) return;
|
|
3303
3324
|
for (const h of lineHits(pts[m], pts[m + 1], seg)) {
|
|
3304
3325
|
const s = m + h.s;
|
|
@@ -3313,7 +3334,7 @@ function knifePath(path, fillRule, knife) {
|
|
|
3313
3334
|
const m = Math.min(pts.length - 2, Math.floor(s));
|
|
3314
3335
|
const u = s - m;
|
|
3315
3336
|
const q = [pts[m][0] + (pts[m + 1][0] - pts[m][0]) * u, pts[m][1] + (pts[m + 1][1] - pts[m][1]) * u];
|
|
3316
|
-
return
|
|
3337
|
+
return _chunkVNYRI265cjs.windingNumber.call(void 0, face2.loops.map((l) => l.segs), q) !== 0;
|
|
3317
3338
|
};
|
|
3318
3339
|
for (let i = 0; i < unique.length - 1; i++) {
|
|
3319
3340
|
const from2 = unique[i];
|
|
@@ -3373,33 +3394,33 @@ function eraserRegion(points, width) {
|
|
|
3373
3394
|
];
|
|
3374
3395
|
}
|
|
3375
3396
|
const line2 = [{ type: "M", x: pts[0][0], y: pts[0][1] }, ...pts.slice(1).map((p) => ({ type: "L", x: p[0], y: p[1] }))];
|
|
3376
|
-
return
|
|
3397
|
+
return _chunkVNYRI265cjs.outlineStroke.call(void 0, line2, { width, cap: "round", join: "round" });
|
|
3377
3398
|
}
|
|
3378
3399
|
function eraseFromFill(path, fillRule, region) {
|
|
3379
|
-
const overlap =
|
|
3380
|
-
if (!
|
|
3381
|
-
const rest =
|
|
3400
|
+
const overlap = _chunkVNYRI265cjs.pathBoolean.call(void 0, "intersection", [{ path, fillRule }, { path: region }]).path;
|
|
3401
|
+
if (!_chunkVNYRI265cjs.pathToContours.call(void 0, overlap).some((c) => Math.abs(_chunkVNYRI265cjs.contourSignedArea.call(void 0, _chunkVNYRI265cjs.closeContour.call(void 0, c, true))) > 1e-9)) return null;
|
|
3402
|
+
const rest = _chunkVNYRI265cjs.pathBoolean.call(void 0, "difference", [{ path, fillRule }, { path: region }]).path;
|
|
3382
3403
|
return splitIntoFaces(rest);
|
|
3383
3404
|
}
|
|
3384
3405
|
function eraseFromOutline(sp, region) {
|
|
3385
|
-
const regionSegs =
|
|
3406
|
+
const regionSegs = _chunkVNYRI265cjs.pathToContours.call(void 0, region).flatMap((c) => _chunkVNYRI265cjs.closeContour.call(void 0, c, true));
|
|
3386
3407
|
if (!regionSegs.length) return null;
|
|
3387
|
-
const rb =
|
|
3408
|
+
const rb = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, region);
|
|
3388
3409
|
const count = subpathSegmentCount(sp);
|
|
3389
3410
|
if (!rb || count === 0) return null;
|
|
3390
|
-
const removed = (p) =>
|
|
3411
|
+
const removed = (p) => _chunkVNYRI265cjs.pointInBezierPath.call(void 0, region, p, "nonzero");
|
|
3391
3412
|
const runs = [];
|
|
3392
3413
|
let cur = [];
|
|
3393
3414
|
let any = false;
|
|
3394
3415
|
for (let i = 0; i < count; i++) {
|
|
3395
3416
|
const seg = subpathSegment(sp, i);
|
|
3396
|
-
const sb =
|
|
3417
|
+
const sb = _chunkVNYRI265cjs.segmentBounds.call(void 0, seg);
|
|
3397
3418
|
const ts = [0, 1];
|
|
3398
3419
|
if (!(sb.maxX < rb.minX || sb.minX > rb.maxX || sb.maxY < rb.minY || sb.minY > rb.maxY)) {
|
|
3399
3420
|
for (const r of regionSegs) {
|
|
3400
|
-
const b =
|
|
3421
|
+
const b = _chunkVNYRI265cjs.segmentBounds.call(void 0, r);
|
|
3401
3422
|
if (b.maxX < sb.minX || b.minX > sb.maxX || b.maxY < sb.minY || b.minY > sb.maxY) continue;
|
|
3402
|
-
for (const hit of
|
|
3423
|
+
for (const hit of _chunkVNYRI265cjs.segmentIntersections.call(void 0, seg, r)) if (hit.ta > 1e-9 && hit.ta < 1 - 1e-9) ts.push(hit.ta);
|
|
3403
3424
|
}
|
|
3404
3425
|
}
|
|
3405
3426
|
ts.sort((a, b) => a - b);
|
|
@@ -3407,7 +3428,7 @@ function eraseFromOutline(sp, region) {
|
|
|
3407
3428
|
const t0 = ts[k];
|
|
3408
3429
|
const t1 = ts[k + 1];
|
|
3409
3430
|
if (t1 - t0 < 1e-9) continue;
|
|
3410
|
-
if (removed(
|
|
3431
|
+
if (removed(_chunkVNYRI265cjs.segmentPoint.call(void 0, seg, (t0 + t1) / 2))) {
|
|
3411
3432
|
any = true;
|
|
3412
3433
|
if (cur.length) runs.push(cur);
|
|
3413
3434
|
cur = [];
|
|
@@ -3426,7 +3447,7 @@ function eraseFromOutline(sp, region) {
|
|
|
3426
3447
|
for (const run of runs) {
|
|
3427
3448
|
const anchors = [];
|
|
3428
3449
|
for (const { seg, t0, t1 } of run) {
|
|
3429
|
-
const c =
|
|
3450
|
+
const c = _chunkVNYRI265cjs.subSegment.call(void 0, subpathSegment(sp, seg), t0, t1);
|
|
3430
3451
|
const line2 = c.length === 2;
|
|
3431
3452
|
const start = c[0];
|
|
3432
3453
|
const end = c[c.length - 1];
|
|
@@ -3715,15 +3736,226 @@ function recognizeInkShape(points, options = {}) {
|
|
|
3715
3736
|
return roundish && rms < 0.1 ? ellipse() : null;
|
|
3716
3737
|
}
|
|
3717
3738
|
|
|
3739
|
+
// src/vector/builder.ts
|
|
3740
|
+
function vectorPathEntries(doc, roots, options = {}) {
|
|
3741
|
+
const out = [];
|
|
3742
|
+
const visit = (node, parent, inside) => {
|
|
3743
|
+
if (node.visible === false || node.locked && !options.locked) return;
|
|
3744
|
+
const picked = inside || roots === null || roots.includes(node.id);
|
|
3745
|
+
if (node.type === "group") {
|
|
3746
|
+
const m = multiplyMatrices(nodeMatrix(node), parent);
|
|
3747
|
+
for (const c of node.children) visit(c, m, picked);
|
|
3748
|
+
} else if (picked) out.push({ node, parent });
|
|
3749
|
+
};
|
|
3750
|
+
for (const n of doc.nodes) visit(n, IDENTITY_MATRIX, false);
|
|
3751
|
+
return out;
|
|
3752
|
+
}
|
|
3753
|
+
var usable = (sp) => sp.anchors.length > 1;
|
|
3754
|
+
function worldOf(entry, subpaths) {
|
|
3755
|
+
return vectorPathWorldBezier({ ...entry.node, subpaths }, entry.parent);
|
|
3756
|
+
}
|
|
3757
|
+
function subpathEnclosesArea(sp) {
|
|
3758
|
+
const contour = _chunkVNYRI265cjs.pathToContours.call(void 0, subpathsToBezier([{ ...sp, closed: true }]))[0];
|
|
3759
|
+
if (!contour) return false;
|
|
3760
|
+
const segs = _chunkVNYRI265cjs.closeContour.call(void 0, contour, true);
|
|
3761
|
+
const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, _chunkVNYRI265cjs.contoursToPath.call(void 0, [{ segments: segs, closed: true }]));
|
|
3762
|
+
if (!b) return false;
|
|
3763
|
+
const w = b.maxX - b.minX;
|
|
3764
|
+
const h = b.maxY - b.minY;
|
|
3765
|
+
return Math.abs(_chunkVNYRI265cjs.contourSignedArea.call(void 0, segs)) > 1e-9 * (w * w + h * h);
|
|
3766
|
+
}
|
|
3767
|
+
var paintKey = (paint) => typeof paint === "string" ? paint.trim().toLowerCase() : JSON.stringify(_nullishCoalesce(paint, () => ( null)));
|
|
3768
|
+
function vectorPathfinderShape(entry, op) {
|
|
3769
|
+
const { node } = entry;
|
|
3770
|
+
const subpaths = node.subpaths.filter(usable);
|
|
3771
|
+
const closed = subpaths.map((s) => ({ ...s, closed: true }));
|
|
3772
|
+
const fillRule = _nullishCoalesce(node.fillRule, () => ( "nonzero"));
|
|
3773
|
+
if (hasPaint(node.fill)) return { path: worldOf(entry, closed), fillRule, key: `fill:${paintKey(node.fill)}`, paint: "fill" };
|
|
3774
|
+
const open = subpaths.length > 0 && subpaths.every((s) => !s.closed);
|
|
3775
|
+
if (op === "divide" && open) return { path: worldOf(entry, subpaths), line: true, paint: "line" };
|
|
3776
|
+
if (hasPaint(node.stroke) && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0) {
|
|
3777
|
+
const path = vectorStrokeOutline({ ...node, subpaths }, entry.parent);
|
|
3778
|
+
return { path, fillRule: "nonzero", key: `fill:${paintKey(node.stroke)}`, paint: "stroke" };
|
|
3779
|
+
}
|
|
3780
|
+
return { path: worldOf(entry, closed), fillRule, key: "none", paint: "outline" };
|
|
3781
|
+
}
|
|
3782
|
+
var STROKE_KEYS = [
|
|
3783
|
+
"stroke",
|
|
3784
|
+
"strokeWidth",
|
|
3785
|
+
"strokeLinecap",
|
|
3786
|
+
"strokeLinejoin",
|
|
3787
|
+
"strokeDasharray",
|
|
3788
|
+
"strokeAlign",
|
|
3789
|
+
"startArrow",
|
|
3790
|
+
"endArrow",
|
|
3791
|
+
"arrowAlign",
|
|
3792
|
+
"startArrowScale",
|
|
3793
|
+
"endArrowScale",
|
|
3794
|
+
"strokeWidthProfile"
|
|
3795
|
+
];
|
|
3796
|
+
function vectorResultStyle(node, paint, edge = false) {
|
|
3797
|
+
const { id: _id, subpaths: _s, transform: _t, ...rest } = node;
|
|
3798
|
+
const base = { ...rest, fillRule: "nonzero" };
|
|
3799
|
+
if (edge) {
|
|
3800
|
+
for (const k of STROKE_KEYS) delete base[k];
|
|
3801
|
+
const stroke = paint === "stroke" || !hasPaint(node.fill) ? node.stroke : node.fill;
|
|
3802
|
+
return { ...base, fill: null, stroke: _nullishCoalesce(stroke, () => ( "#000000")), strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)) };
|
|
3803
|
+
}
|
|
3804
|
+
if (paint === "stroke") {
|
|
3805
|
+
for (const k of STROKE_KEYS) delete base[k];
|
|
3806
|
+
return { ...base, fill: _nullishCoalesce(node.stroke, () => ( null)), stroke: null };
|
|
3807
|
+
}
|
|
3808
|
+
return base;
|
|
3809
|
+
}
|
|
3810
|
+
function vectorShapeBuilderMap(entries) {
|
|
3811
|
+
const lines = [];
|
|
3812
|
+
const inputs = entries.map((entry) => {
|
|
3813
|
+
const filled = hasPaint(entry.node.fill);
|
|
3814
|
+
const subpaths = entry.node.subpaths.filter(usable).map((sp) => !sp.closed && filled && subpathEnclosesArea(sp) ? { ...sp, closed: true } : sp);
|
|
3815
|
+
lines.push(!subpaths.some((s) => s.closed));
|
|
3816
|
+
return { path: worldOf(entry, subpaths), fillRule: _nullishCoalesce(entry.node.fillRule, () => ( "nonzero")) };
|
|
3817
|
+
});
|
|
3818
|
+
const map = _chunkVNYRI265cjs.PlanarMap.build(inputs);
|
|
3819
|
+
if (!map) return null;
|
|
3820
|
+
let chains = null;
|
|
3821
|
+
const runs = (line2) => (chains ??= map.chains()).filter((c) => lines[c.source] === line2 && !(line2 && c.closed)).map((c) => {
|
|
3822
|
+
const path = _chunkVNYRI265cjs.contoursToPath.call(void 0, [{ segments: c.segments, closed: c.closed }]);
|
|
3823
|
+
return { path, segments: c.segments, closed: c.closed, source: c.source, bounds: _chunkVNYRI265cjs.bezierPathBounds.call(void 0, path) };
|
|
3824
|
+
});
|
|
3825
|
+
const pieces = lines.some(Boolean) ? runs(true) : [];
|
|
3826
|
+
let edges = null;
|
|
3827
|
+
let size = 0;
|
|
3828
|
+
for (const input of inputs) {
|
|
3829
|
+
const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, input.path);
|
|
3830
|
+
if (b) size = Math.max(size, b.maxX - b.minX, b.maxY - b.minY);
|
|
3831
|
+
}
|
|
3832
|
+
return {
|
|
3833
|
+
entries: [...entries],
|
|
3834
|
+
map,
|
|
3835
|
+
lines,
|
|
3836
|
+
pieces,
|
|
3837
|
+
get edges() {
|
|
3838
|
+
return edges ??= runs(false);
|
|
3839
|
+
},
|
|
3840
|
+
tolerance: 0.2 * Math.max(size / 2e3, 0.25)
|
|
3841
|
+
};
|
|
3842
|
+
}
|
|
3843
|
+
function pieceNear(pieces, p, tol) {
|
|
3844
|
+
const point = [p.x, p.y];
|
|
3845
|
+
let best = null;
|
|
3846
|
+
pieces.forEach((piece, index) => {
|
|
3847
|
+
const b = piece.bounds;
|
|
3848
|
+
if (p.x < b.minX - tol || p.x > b.maxX + tol || p.y < b.minY - tol || p.y > b.maxY + tol) return;
|
|
3849
|
+
const d = _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, piece.path, point);
|
|
3850
|
+
if (d <= tol && (!best || d < best.d)) best = { index, d };
|
|
3851
|
+
});
|
|
3852
|
+
return best;
|
|
3853
|
+
}
|
|
3854
|
+
function vectorShapeBuilderHit(m, p, lineTolerance = null) {
|
|
3855
|
+
if (lineTolerance !== null && lineTolerance > 0) {
|
|
3856
|
+
const line2 = pieceNear(m.pieces, p, lineTolerance);
|
|
3857
|
+
const edge = pieceNear(m.edges, p, lineTolerance);
|
|
3858
|
+
if (edge && (!line2 || edge.d < line2.d)) return { edge: edge.index };
|
|
3859
|
+
if (line2) return { line: line2.index };
|
|
3860
|
+
}
|
|
3861
|
+
const face = m.map.faceAt([p.x, p.y]);
|
|
3862
|
+
return face >= 0 ? { face } : null;
|
|
3863
|
+
}
|
|
3864
|
+
function samplePolyline(points, step) {
|
|
3865
|
+
const out = [];
|
|
3866
|
+
const s = Math.max(step, 1e-3);
|
|
3867
|
+
points.forEach((p, i) => {
|
|
3868
|
+
if (i > 0) {
|
|
3869
|
+
const a = points[i - 1];
|
|
3870
|
+
const n = Math.min(4e3, Math.ceil(Math.hypot(p.x - a.x, p.y - a.y) / s));
|
|
3871
|
+
for (let k = 1; k < n; k++) out.push({ x: a.x + (p.x - a.x) * k / n, y: a.y + (p.y - a.y) * k / n });
|
|
3872
|
+
}
|
|
3873
|
+
out.push(p);
|
|
3874
|
+
});
|
|
3875
|
+
return out;
|
|
3876
|
+
}
|
|
3877
|
+
function addBuilderHit(touched, hit) {
|
|
3878
|
+
if (!hit) return false;
|
|
3879
|
+
const [list, i] = "face" in hit ? [touched.faces, hit.face] : "line" in hit ? [touched.lines, hit.line] : [touched.edges, hit.edge];
|
|
3880
|
+
if (list.includes(i)) return false;
|
|
3881
|
+
list.push(i);
|
|
3882
|
+
return true;
|
|
3883
|
+
}
|
|
3884
|
+
function sides(m, piece) {
|
|
3885
|
+
const seg = piece.segments[Math.floor(piece.segments.length / 2)];
|
|
3886
|
+
const mid = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, 0.5);
|
|
3887
|
+
const t = _chunkVNYRI265cjs.segmentTangent.call(void 0, seg, 0.5);
|
|
3888
|
+
const chord = Math.hypot(seg[seg.length - 1][0] - seg[0][0], seg[seg.length - 1][1] - seg[0][1]);
|
|
3889
|
+
const off = Math.max(1e-6, Math.min(0.05, 0.05 * chord));
|
|
3890
|
+
return [m.map.faceAt([mid[0] - t[1] * off, mid[1] + t[0] * off]), m.map.faceAt([mid[0] + t[1] * off, mid[1] - t[0] * off])];
|
|
3891
|
+
}
|
|
3892
|
+
function vectorBuilderErasedEdges(m, touched) {
|
|
3893
|
+
if (!touched.edges.length) return [];
|
|
3894
|
+
const faces = new Set(touched.faces);
|
|
3895
|
+
return touched.edges.filter((k) => m.edges[k] && !sides(m, m.edges[k]).some((f) => f >= 0 && faces.has(f)));
|
|
3896
|
+
}
|
|
3897
|
+
function planShapeBuilder(m, touched, erase) {
|
|
3898
|
+
const replace = /* @__PURE__ */ new Map();
|
|
3899
|
+
const picked = new Set(touched.faces);
|
|
3900
|
+
const faces = m.map.faces;
|
|
3901
|
+
const sourcesOf = faces.map((_, i) => m.map.faceSources(i));
|
|
3902
|
+
const cuts = erase ? vectorBuilderErasedEdges(m, touched).map((k) => m.edges[k]) : [];
|
|
3903
|
+
m.entries.forEach((entry, i) => {
|
|
3904
|
+
if (m.lines[i]) {
|
|
3905
|
+
const own = m.pieces.flatMap((piece, k) => piece.source === i ? [k] : []);
|
|
3906
|
+
const keep = own.filter((k) => !touched.lines.includes(k) && !sides(m, m.pieces[k]).every((f) => f >= 0 && picked.has(f)));
|
|
3907
|
+
if (keep.length === own.length) return;
|
|
3908
|
+
replace.set(i, keep.length ? { kind: "pieces", paths: keep.map((k) => m.pieces[k].path) } : null);
|
|
3909
|
+
return;
|
|
3910
|
+
}
|
|
3911
|
+
const inUnion = touched.faces.some((f) => sourcesOf[f].includes(i));
|
|
3912
|
+
if (!inUnion && !cuts.length) return;
|
|
3913
|
+
let rest;
|
|
3914
|
+
if (inUnion) {
|
|
3915
|
+
const kept = faces.flatMap((_, f) => sourcesOf[f].includes(i) && !picked.has(f) ? [f] : []);
|
|
3916
|
+
rest = kept.length ? m.map.merge(kept) : [];
|
|
3917
|
+
} else rest = worldOf(entry, entry.node.subpaths.filter(usable));
|
|
3918
|
+
const fillCloses = hasPaint(entry.node.fill);
|
|
3919
|
+
let cut = false;
|
|
3920
|
+
for (const piece of cuts) {
|
|
3921
|
+
const r = rest.length ? _chunkVNYRI265cjs.cutOutPiece.call(void 0, rest, piece, fillCloses, m.tolerance) : null;
|
|
3922
|
+
if (r) {
|
|
3923
|
+
rest = r;
|
|
3924
|
+
cut = true;
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
if (!inUnion && !cut) return;
|
|
3928
|
+
replace.set(i, rest.length ? { kind: inUnion ? "fill" : "outline", path: rest } : null);
|
|
3929
|
+
});
|
|
3930
|
+
let merged = null;
|
|
3931
|
+
if (!erase && touched.faces.length) {
|
|
3932
|
+
const path = m.map.merge(touched.faces);
|
|
3933
|
+
const covered = touched.faces.map((f) => sourcesOf[f]).find((s) => s.length);
|
|
3934
|
+
const lastShape = m.lines.lastIndexOf(false);
|
|
3935
|
+
const style = covered ? covered[covered.length - 1] : lastShape >= 0 ? lastShape : m.entries.length - 1;
|
|
3936
|
+
if (path.length) merged = { path, style, currentFill: !covered };
|
|
3937
|
+
}
|
|
3938
|
+
return { replace, merged };
|
|
3939
|
+
}
|
|
3940
|
+
function vectorFillMap(doc, gap = 0) {
|
|
3941
|
+
const entries = vectorPathEntries(doc, null, { locked: true });
|
|
3942
|
+
return _chunkVNYRI265cjs.PlanarMap.build(
|
|
3943
|
+
entries.map((e) => ({ path: worldOf(e, e.node.subpaths.filter(usable)), fills: false })),
|
|
3944
|
+
{ gap, maxSegments: 2e4 }
|
|
3945
|
+
);
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3718
3948
|
// src/vector/controller.ts
|
|
3719
3949
|
var DEFAULT_VECTOR_SNAP = { grid: 0, objects: true, guides: true, threshold: 5, angles: VECTOR_CONSTRUCTION_ANGLES };
|
|
3950
|
+
var VECTOR_FILL_GAP = 6;
|
|
3720
3951
|
var DEFAULT_VECTOR_PATH_EDIT = {
|
|
3721
3952
|
keepShapeOnDelete: true,
|
|
3722
3953
|
curvatureMoves: false,
|
|
3723
3954
|
pencilSmoothing: 0,
|
|
3724
3955
|
recognizeShapes: false,
|
|
3725
3956
|
eraserSize: 10,
|
|
3726
|
-
pencilPressure: "pen"
|
|
3957
|
+
pencilPressure: "pen",
|
|
3958
|
+
fillGap: 0
|
|
3727
3959
|
};
|
|
3728
3960
|
var VECTOR_PENCIL_STRING_PX = 100;
|
|
3729
3961
|
var VECTOR_STYLE_KEYS = [
|
|
@@ -3962,9 +4194,27 @@ var TOOL_LABELS = {
|
|
|
3962
4194
|
scissors: "Scissors",
|
|
3963
4195
|
knife: "Knife",
|
|
3964
4196
|
eraser: "Eraser",
|
|
3965
|
-
width: "Width"
|
|
4197
|
+
width: "Width",
|
|
4198
|
+
shapeBuilder: "Shape Builder",
|
|
4199
|
+
paintBucket: "Paint Bucket"
|
|
4200
|
+
};
|
|
4201
|
+
var TOOL_KEYS = {
|
|
4202
|
+
v: "select",
|
|
4203
|
+
a: "direct",
|
|
4204
|
+
p: "pen",
|
|
4205
|
+
n: "pencil",
|
|
4206
|
+
r: "rect",
|
|
4207
|
+
o: "ellipse",
|
|
4208
|
+
y: "polygon",
|
|
4209
|
+
s: "star",
|
|
4210
|
+
l: "line",
|
|
4211
|
+
c: "scissors",
|
|
4212
|
+
k: "knife",
|
|
4213
|
+
e: "eraser",
|
|
4214
|
+
w: "width",
|
|
4215
|
+
m: "shapeBuilder",
|
|
4216
|
+
b: "paintBucket"
|
|
3966
4217
|
};
|
|
3967
|
-
var TOOL_KEYS = { v: "select", a: "direct", p: "pen", n: "pencil", r: "rect", o: "ellipse", y: "polygon", s: "star", l: "line", c: "scissors", k: "knife", e: "eraser", w: "width" };
|
|
3968
4218
|
function vectorToolLabel(tool) {
|
|
3969
4219
|
return TOOL_LABELS[tool];
|
|
3970
4220
|
}
|
|
@@ -3981,7 +4231,9 @@ var VECTOR_TOOL_SHORTCUTS = {
|
|
|
3981
4231
|
scissors: "C",
|
|
3982
4232
|
knife: "K",
|
|
3983
4233
|
eraser: "E",
|
|
3984
|
-
width: "W"
|
|
4234
|
+
width: "W",
|
|
4235
|
+
shapeBuilder: "M",
|
|
4236
|
+
paintBucket: "B"
|
|
3985
4237
|
};
|
|
3986
4238
|
var VECTOR_TOOL_GLYPHS = {
|
|
3987
4239
|
select: "\u2196",
|
|
@@ -3996,7 +4248,9 @@ var VECTOR_TOOL_GLYPHS = {
|
|
|
3996
4248
|
scissors: "\u2702",
|
|
3997
4249
|
knife: "\u27CB",
|
|
3998
4250
|
eraser: "\u232B",
|
|
3999
|
-
width: "\u21F9"
|
|
4251
|
+
width: "\u21F9",
|
|
4252
|
+
shapeBuilder: "\u2295",
|
|
4253
|
+
paintBucket: "\u25CD"
|
|
4000
4254
|
};
|
|
4001
4255
|
var SHAPE_TOOLS = /* @__PURE__ */ new Set(["rect", "ellipse", "polygon", "star", "line"]);
|
|
4002
4256
|
var BOOLEAN_OPS = {
|
|
@@ -4006,6 +4260,14 @@ var BOOLEAN_OPS = {
|
|
|
4006
4260
|
exclude: "xor"
|
|
4007
4261
|
};
|
|
4008
4262
|
var BOOLEAN_LABELS = { union: "Union", subtract: "Subtract", intersect: "Intersect", exclude: "Exclude" };
|
|
4263
|
+
var VECTOR_PATHFINDER_LABELS = {
|
|
4264
|
+
divide: "Divide",
|
|
4265
|
+
trim: "Trim",
|
|
4266
|
+
merge: "Merge",
|
|
4267
|
+
crop: "Crop",
|
|
4268
|
+
outline: "Outline",
|
|
4269
|
+
minusBack: "Minus Back"
|
|
4270
|
+
};
|
|
4009
4271
|
function mapTree(nodes, fn) {
|
|
4010
4272
|
let changed = false;
|
|
4011
4273
|
const out = [];
|
|
@@ -4070,16 +4332,23 @@ var VectorEditorController = (_class3 = class {
|
|
|
4070
4332
|
__init20() {this.hoverTargets = null}
|
|
4071
4333
|
__init21() {this.spaceHeld = false}
|
|
4072
4334
|
__init22() {this.clipboard = null}
|
|
4335
|
+
/** Shape Builder map of the selection, kept while the document and the selection stay the same. */
|
|
4336
|
+
__init23() {this.builderCache = null}
|
|
4337
|
+
/** Paint bucket map of the visible outlines. */
|
|
4338
|
+
__init24() {this.fillCache = null}
|
|
4339
|
+
__init25() {this.builderPreview = null}
|
|
4340
|
+
/** What the highlight shows, to skip notifying when the pointer stays over the same face. */
|
|
4341
|
+
__init26() {this.builderHoverKey = null}
|
|
4073
4342
|
|
|
4074
4343
|
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4344
|
+
__init27() {this.listeners = /* @__PURE__ */ new Set()}
|
|
4345
|
+
__init28() {this.cleanups = []}
|
|
4346
|
+
__init29() {this.applying = false}
|
|
4078
4347
|
/** Set while a commit records a change that was already applied, so `restore` still reports it. */
|
|
4079
|
-
|
|
4080
|
-
|
|
4348
|
+
__init30() {this.committing = false}
|
|
4349
|
+
__init31() {this.revision = 0}
|
|
4081
4350
|
|
|
4082
|
-
constructor(options = {}) {;_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);_class3.prototype.__init22.call(this);_class3.prototype.__init23.call(this);_class3.prototype.__init24.call(this);_class3.prototype.__init25.call(this);_class3.prototype.__init26.call(this);_class3.prototype.__init27.call(this);_class3.prototype.__init28.call(this);_class3.prototype.__init29.call(this);
|
|
4351
|
+
constructor(options = {}) {;_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);_class3.prototype.__init22.call(this);_class3.prototype.__init23.call(this);_class3.prototype.__init24.call(this);_class3.prototype.__init25.call(this);_class3.prototype.__init26.call(this);_class3.prototype.__init27.call(this);_class3.prototype.__init28.call(this);_class3.prototype.__init29.call(this);_class3.prototype.__init30.call(this);_class3.prototype.__init31.call(this);_class3.prototype.__init32.call(this);_class3.prototype.__init33.call(this);
|
|
4083
4352
|
this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkQKLRAA4Tcjs.HistoryManager)()));
|
|
4084
4353
|
this.doc = options.document ? cloneVectorDocument(options.document) : { width: 800, height: 600, nodes: [] };
|
|
4085
4354
|
this.tool = _nullishCoalesce(options.tool, () => ( "select"));
|
|
@@ -4108,9 +4377,9 @@ var VectorEditorController = (_class3 = class {
|
|
|
4108
4377
|
// State
|
|
4109
4378
|
// -------------------------------------------------------------------------
|
|
4110
4379
|
/** The current snapshot (stable until the next change). */
|
|
4111
|
-
|
|
4380
|
+
__init32() {this.getState = () => this.state}
|
|
4112
4381
|
/** Calls `listener` after every change. Returns an unsubscribe function. */
|
|
4113
|
-
|
|
4382
|
+
__init33() {this.subscribe = (listener) => {
|
|
4114
4383
|
this.listeners.add(listener);
|
|
4115
4384
|
return () => {
|
|
4116
4385
|
this.listeners.delete(listener);
|
|
@@ -4144,6 +4413,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4144
4413
|
interaction: this.interaction,
|
|
4145
4414
|
pen: this.pen,
|
|
4146
4415
|
pointer: this.pointer,
|
|
4416
|
+
builder: this.builderPreview,
|
|
4147
4417
|
canUndo: h.canUndo,
|
|
4148
4418
|
canRedo: h.canRedo,
|
|
4149
4419
|
undoLabel: h.undoName,
|
|
@@ -4202,6 +4472,11 @@ var VectorEditorController = (_class3 = class {
|
|
|
4202
4472
|
if (_optionalChain([this, 'access', _103 => _103.drag, 'optionalAccess', _104 => _104.kind]) === "width") return this.drag.mode === "move" ? "grabbing" : "ew-resize";
|
|
4203
4473
|
if (_optionalChain([h, 'optionalAccess', _105 => _105.widthPoint])) return h.widthPoint.part === "center" ? "grab" : "ew-resize";
|
|
4204
4474
|
return _optionalChain([h, 'optionalAccess', _106 => _106.strokeSpot]) ? "copy" : "default";
|
|
4475
|
+
case "shapeBuilder":
|
|
4476
|
+
if (!_optionalChain([this, 'access', _107 => _107.builderPreview, 'optionalAccess', _108 => _108.faces, 'access', _109 => _109.length]) && !_optionalChain([this, 'access', _110 => _110.builderPreview, 'optionalAccess', _111 => _111.lines, 'access', _112 => _112.length])) return "crosshair";
|
|
4477
|
+
return this.builderPreview.mode === "erase" ? "not-allowed" : "cell";
|
|
4478
|
+
case "paintBucket":
|
|
4479
|
+
return this.builderPreview ? "cell" : "crosshair";
|
|
4205
4480
|
default:
|
|
4206
4481
|
return "crosshair";
|
|
4207
4482
|
}
|
|
@@ -4221,7 +4496,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4221
4496
|
this.selection = s.selection.filter((id) => this.getNode(id));
|
|
4222
4497
|
this.anchors = s.anchors.filter((r) => getAnchor(this.doc, r));
|
|
4223
4498
|
this.editingId = s.editingId && this.getNode(s.editingId) ? s.editingId : null;
|
|
4224
|
-
this.pen = s.pen && _optionalChain([this, 'access',
|
|
4499
|
+
this.pen = s.pen && _optionalChain([this, 'access', _113 => _113.getNode, 'call', _114 => _114(s.pen.nodeId), 'optionalAccess', _115 => _115.subpaths, 'optionalAccess', _116 => _116[s.pen.subpath]]) ? s.pen : null;
|
|
4225
4500
|
} finally {
|
|
4226
4501
|
this.applying = false;
|
|
4227
4502
|
}
|
|
@@ -4328,6 +4603,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
4328
4603
|
this.hover = null;
|
|
4329
4604
|
this.guides = null;
|
|
4330
4605
|
this.widthPoint = null;
|
|
4606
|
+
this.builderPreview = null;
|
|
4607
|
+
this.builderHoverKey = null;
|
|
4331
4608
|
if (tool !== "direct") {
|
|
4332
4609
|
this.anchors = [];
|
|
4333
4610
|
this.editingId = null;
|
|
@@ -4386,7 +4663,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4386
4663
|
if (res.kind) {
|
|
4387
4664
|
this.snappedToObject = true;
|
|
4388
4665
|
this.setGuides(res);
|
|
4389
|
-
return _optionalChain([leave, 'optionalAccess',
|
|
4666
|
+
return _optionalChain([leave, 'optionalAccess', _117 => _117.constrain]) ? res.point : { x: res.x ? res.point.x : this.gridValue(res.point.x), y: res.y ? res.point.y : this.gridValue(res.point.y) };
|
|
4390
4667
|
}
|
|
4391
4668
|
}
|
|
4392
4669
|
this.setGuides(null);
|
|
@@ -4404,14 +4681,14 @@ var VectorEditorController = (_class3 = class {
|
|
|
4404
4681
|
/** Where the pointer at `p` would place a point with the pen or a shape tool (and the guides showing why). */
|
|
4405
4682
|
hoverSnap(p, input) {
|
|
4406
4683
|
if (this.tool === "pen") {
|
|
4407
|
-
const sp = this.pen ? _optionalChain([this, 'access',
|
|
4408
|
-
if (this.pen && sp && _optionalChain([this, 'access',
|
|
4684
|
+
const sp = this.pen ? _optionalChain([this, 'access', _118 => _118.getNode, 'call', _119 => _119(this.pen.nodeId), 'optionalAccess', _120 => _120.subpaths, 'access', _121 => _121[this.pen.subpath]]) : void 0;
|
|
4685
|
+
if (this.pen && sp && _optionalChain([this, 'access', _122 => _122.hover, 'optionalAccess', _123 => _123.anchor])) {
|
|
4409
4686
|
this.setGuides(null);
|
|
4410
4687
|
return p;
|
|
4411
4688
|
}
|
|
4412
4689
|
const last = this.pen && sp ? getAnchorWorld(this.doc, { nodeId: this.pen.nodeId, subpath: this.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
|
|
4413
4690
|
const leave = last ? { at: { x: last.x, y: last.y }, constrain: input.shift ? "angle" : null } : null;
|
|
4414
|
-
return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access',
|
|
4691
|
+
return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access', _124 => _124.pen, 'optionalAccess', _125 => _125.nodeId]), () => ( null))));
|
|
4415
4692
|
}
|
|
4416
4693
|
if (SHAPE_TOOLS.has(this.tool)) return this.snapDrawn(p, null, input, () => this.drawingTargets(null));
|
|
4417
4694
|
this.setGuides(null);
|
|
@@ -4559,7 +4836,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4559
4836
|
if (d.fillRule) out.fillRule = d.fillRule;
|
|
4560
4837
|
if (d.strokeAlign && d.strokeAlign !== "center") out.strokeAlign = d.strokeAlign;
|
|
4561
4838
|
for (const key of ["startArrow", "endArrow", "arrowAlign", "startArrowScale", "endArrowScale"]) if (d[key]) out[key] = d[key];
|
|
4562
|
-
if (_optionalChain([d, 'access',
|
|
4839
|
+
if (_optionalChain([d, 'access', _126 => _126.strokeWidthProfile, 'optionalAccess', _127 => _127.length])) out.strokeWidthProfile = d.strokeWidthProfile.map((p) => ({ ...p }));
|
|
4563
4840
|
return out;
|
|
4564
4841
|
}
|
|
4565
4842
|
/** Merges `patch` into a node (paths take style and geometry; groups name / visibility / opacity). */
|
|
@@ -4607,7 +4884,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4607
4884
|
/** Removes one width point of a path's profile (the width tool's Delete). */
|
|
4608
4885
|
removeWidthPoint(ref) {
|
|
4609
4886
|
const node = this.getNode(ref.nodeId);
|
|
4610
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
4887
|
+
if (_optionalChain([node, 'optionalAccess', _128 => _128.type]) !== "path" || !_optionalChain([node, 'access', _129 => _129.strokeWidthProfile, 'optionalAccess', _130 => _130[ref.index]])) return { ok: false, message: "There is no such width point." };
|
|
4611
4888
|
const rest = removeWidthPoints(sanitizeWidthProfile(node.strokeWidthProfile), [ref.index]);
|
|
4612
4889
|
this.widthPoint = null;
|
|
4613
4890
|
this.change("Delete Width Point", () => this.replaceNode(node.id, withStyle(node, { strokeWidthProfile: rest.length ? rest : null })));
|
|
@@ -4632,7 +4909,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4632
4909
|
const refs = this.cornerTargets(options);
|
|
4633
4910
|
if (!refs.length) return { ok: false, message: "Nothing is selected." };
|
|
4634
4911
|
this.change("Corner Kind", () => {
|
|
4635
|
-
this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access',
|
|
4912
|
+
this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _131 => _131.corner, 'optionalAccess', _132 => _132.radius]), () => ( 0)), kind));
|
|
4636
4913
|
});
|
|
4637
4914
|
return { ok: true };
|
|
4638
4915
|
}
|
|
@@ -4771,10 +5048,10 @@ var VectorEditorController = (_class3 = class {
|
|
|
4771
5048
|
return this.selection.filter((id) => {
|
|
4772
5049
|
let covered = false;
|
|
4773
5050
|
const loc = locateVectorNode(this.doc.nodes, id);
|
|
4774
|
-
let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess',
|
|
5051
|
+
let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _133 => _133.parent]), () => ( null));
|
|
4775
5052
|
while (parent) {
|
|
4776
5053
|
if (this.selection.includes(parent.id)) covered = true;
|
|
4777
|
-
parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call',
|
|
5054
|
+
parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _134 => _134(this.doc.nodes, parent.id), 'optionalAccess', _135 => _135.parent]), () => ( null));
|
|
4778
5055
|
}
|
|
4779
5056
|
return !covered;
|
|
4780
5057
|
});
|
|
@@ -4957,8 +5234,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
4957
5234
|
if (!ids.length) return null;
|
|
4958
5235
|
const locs = ids.map((id2) => locateVectorNode(this.doc.nodes, id2));
|
|
4959
5236
|
if (locs.some((l) => !l)) return null;
|
|
4960
|
-
const parent = _nullishCoalesce(_optionalChain([locs, 'access',
|
|
4961
|
-
if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access',
|
|
5237
|
+
const parent = _nullishCoalesce(_optionalChain([locs, 'access', _136 => _136[0], 'access', _137 => _137.parent, 'optionalAccess', _138 => _138.id]), () => ( null));
|
|
5238
|
+
if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _139 => _139.parent, 'optionalAccess', _140 => _140.id]), () => ( null))) !== parent)) return null;
|
|
4962
5239
|
const id = this.newId();
|
|
4963
5240
|
this.change("Group", () => {
|
|
4964
5241
|
const set = new Set(ids);
|
|
@@ -4981,7 +5258,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4981
5258
|
}
|
|
4982
5259
|
/** Replaces selected groups with their children. */
|
|
4983
5260
|
ungroup(options = {}) {
|
|
4984
|
-
const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess',
|
|
5261
|
+
const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _141 => _141.type]) === "group");
|
|
4985
5262
|
if (!groups.length) return { ok: false, message: "Select a group to ungroup." };
|
|
4986
5263
|
const set = new Set(groups.map((g) => g.id));
|
|
4987
5264
|
this.change("Ungroup", () => {
|
|
@@ -5041,7 +5318,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5041
5318
|
});
|
|
5042
5319
|
const paths = [...new Set(order)].map((id2) => this.getNode(id2));
|
|
5043
5320
|
if (paths.length < 2) return null;
|
|
5044
|
-
const result =
|
|
5321
|
+
const result = _chunkVNYRI265cjs.pathBoolean.call(void 0,
|
|
5045
5322
|
BOOLEAN_OPS[op],
|
|
5046
5323
|
paths.map((p) => ({
|
|
5047
5324
|
path: vectorPathWorldBezier(
|
|
@@ -5091,11 +5368,11 @@ var VectorEditorController = (_class3 = class {
|
|
|
5091
5368
|
/** A document-space path mapped into the parent space of node `id`. */
|
|
5092
5369
|
intoParentSpace(id, path) {
|
|
5093
5370
|
const parent = _nullishCoalesce(vectorParentMatrix(this.doc.nodes, id), () => ( IDENTITY_MATRIX));
|
|
5094
|
-
return isRoot(parent) ? path :
|
|
5371
|
+
return isRoot(parent) ? path : _chunkVNYRI265cjs.transformBezierPath.call(void 0, path, invertMatrix(parent));
|
|
5095
5372
|
}
|
|
5096
5373
|
/** Splits selected compound paths into one path per subpath. */
|
|
5097
5374
|
breakApart(options = {}) {
|
|
5098
|
-
const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess',
|
|
5375
|
+
const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _142 => _142.type]) === "path" && n.subpaths.length > 1);
|
|
5099
5376
|
if (!paths.length) return { ok: false, message: "Select a compound path to break apart." };
|
|
5100
5377
|
const created = [];
|
|
5101
5378
|
const set = new Set(paths.map((p) => p.id));
|
|
@@ -5115,6 +5392,255 @@ var VectorEditorController = (_class3 = class {
|
|
|
5115
5392
|
return { ok: true };
|
|
5116
5393
|
}
|
|
5117
5394
|
// -------------------------------------------------------------------------
|
|
5395
|
+
// Pathfinder, Shape Builder and paint bucket
|
|
5396
|
+
// -------------------------------------------------------------------------
|
|
5397
|
+
/**
|
|
5398
|
+
* Pathfinder: Divide, Trim, Merge, Crop, Outline or Minus Back over the selected (or given)
|
|
5399
|
+
* paths, in document space (rotated nodes and groups included, live corners cut). Unfilled
|
|
5400
|
+
* stroked paths take part as the area their stroke paints (Divide: open ones cut instead).
|
|
5401
|
+
* The results replace the operands at the place of the top-most one, grouped when there are
|
|
5402
|
+
* several; each keeps the style of the operand whose area it is. Returns the new path ids,
|
|
5403
|
+
* or an empty list when nothing came out.
|
|
5404
|
+
*/
|
|
5405
|
+
pathfinder(op, options = {}) {
|
|
5406
|
+
const roots = _nullishCoalesce(options.ids, () => ( this.selectedRoots()));
|
|
5407
|
+
const entries = vectorPathEntries(this.doc, roots);
|
|
5408
|
+
if (entries.length < (op === "divide" || op === "outline" ? 1 : 2)) return [];
|
|
5409
|
+
const shapes = entries.map((e) => vectorPathfinderShape(e, op));
|
|
5410
|
+
const result = _chunkVNYRI265cjs.pathfinder.call(void 0, op, shapes);
|
|
5411
|
+
if (result.error || !result.pieces.length) return [];
|
|
5412
|
+
const last = entries[entries.length - 1].node.id;
|
|
5413
|
+
const topRoot = _nullishCoalesce([...roots].reverse().find((r) => {
|
|
5414
|
+
const n = this.getNode(r);
|
|
5415
|
+
return !!n && !!findVectorNode([n], last);
|
|
5416
|
+
}), () => ( last));
|
|
5417
|
+
const nodes = [];
|
|
5418
|
+
for (const piece of result.pieces) {
|
|
5419
|
+
const subpaths = bezierToSubpaths(this.intoParentSpace(topRoot, piece.path)).map((sp) => piece.open ? { ...sp, closed: false } : sp);
|
|
5420
|
+
if (!subpaths.length) continue;
|
|
5421
|
+
const source = entries[piece.source].node;
|
|
5422
|
+
const style = vectorResultStyle(source, shapes[piece.source].paint, op === "outline");
|
|
5423
|
+
nodes.push({ ...style, type: "path", id: this.newId(), name: _nullishCoalesce(source.name, () => ( "Path")), subpaths });
|
|
5424
|
+
}
|
|
5425
|
+
if (!nodes.length) return [];
|
|
5426
|
+
const label = VECTOR_PATHFINDER_LABELS[op];
|
|
5427
|
+
const container = nodes.length > 1 ? { id: this.newId(), type: "group", name: label, children: nodes } : nodes[0];
|
|
5428
|
+
const drop = /* @__PURE__ */ new Set([...entries.map((e) => e.node.id), ...roots]);
|
|
5429
|
+
this.change(label, () => {
|
|
5430
|
+
this.setDoc(mapTree(this.doc.nodes, (n) => n.id === topRoot ? container : drop.has(n.id) ? null : n));
|
|
5431
|
+
this.selection = [container.id];
|
|
5432
|
+
this.anchors = [];
|
|
5433
|
+
this.editingId = null;
|
|
5434
|
+
});
|
|
5435
|
+
return nodes.map((n) => n.id);
|
|
5436
|
+
}
|
|
5437
|
+
/** The Shape Builder map of the selected (or given) paths, cached per document and selection. */
|
|
5438
|
+
shapeBuilderMap(ids) {
|
|
5439
|
+
const roots = _nullishCoalesce(ids, () => ( this.selectedRoots()));
|
|
5440
|
+
const key = roots.join("\0");
|
|
5441
|
+
if (_optionalChain([this, 'access', _143 => _143.builderCache, 'optionalAccess', _144 => _144.doc]) === this.doc && this.builderCache.key === key) return this.builderCache.map;
|
|
5442
|
+
const entries = roots.length ? vectorPathEntries(this.doc, roots) : [];
|
|
5443
|
+
const map = entries.length ? vectorShapeBuilderMap(entries) : null;
|
|
5444
|
+
this.builderCache = { doc: this.doc, key, map };
|
|
5445
|
+
return map;
|
|
5446
|
+
}
|
|
5447
|
+
/** The faces the Shape Builder offers for the selected (or given) paths (document units). */
|
|
5448
|
+
getShapeBuilderFaces(options = {}) {
|
|
5449
|
+
const m = this.shapeBuilderMap(options.ids);
|
|
5450
|
+
if (!m) return [];
|
|
5451
|
+
return m.map.faces.map((f, index) => {
|
|
5452
|
+
const p = m.map.faceInterior(index);
|
|
5453
|
+
return {
|
|
5454
|
+
index,
|
|
5455
|
+
d: _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, f.path, { precision: 3 }),
|
|
5456
|
+
area: f.area,
|
|
5457
|
+
sources: m.map.faceSources(index).map((i) => m.entries[i].node.id),
|
|
5458
|
+
point: p ? { x: p[0], y: p[1] } : null
|
|
5459
|
+
};
|
|
5460
|
+
});
|
|
5461
|
+
}
|
|
5462
|
+
/** Pick distance of the Shape Builder's erase for line pieces (document units). */
|
|
5463
|
+
builderLineTolerance() {
|
|
5464
|
+
return Math.max(this.hitRadius, 4) / this.viewport.zoom;
|
|
5465
|
+
}
|
|
5466
|
+
/**
|
|
5467
|
+
* Shape Builder gesture along `points` (document units; one point is a click) over the faces
|
|
5468
|
+
* the selected (or given) paths make. Merges the faces touched into one shape styled like the
|
|
5469
|
+
* top-most shape over the first face (the current fill for a face only outlines enclose);
|
|
5470
|
+
* with `erase` deletes them, the pieces of unfilled open paths and the edges of other outlines
|
|
5471
|
+
* (cut where paths meet) within `tolerance`: a deleted edge opens a closed subpath there,
|
|
5472
|
+
* splits an open one or takes a subpath it runs all the way round, and edges bounding a face
|
|
5473
|
+
* deleted in the same gesture go with the face. Every shape covering a touched face loses
|
|
5474
|
+
* that area; paths keep their own transforms. One undo step.
|
|
5475
|
+
*/
|
|
5476
|
+
shapeBuilder(points, options = {}) {
|
|
5477
|
+
const none = (message) => ({ ok: false, message, merged: null, faces: 0, lines: 0, edges: 0 });
|
|
5478
|
+
if (!points.length || !points.every((p) => Number.isFinite(p.x) && Number.isFinite(p.y))) return none("Give the points of the gesture.");
|
|
5479
|
+
const m = this.shapeBuilderMap(options.ids);
|
|
5480
|
+
if (!m) return none("Select paths that make faces.");
|
|
5481
|
+
const erase = !!options.erase;
|
|
5482
|
+
const tol = erase ? _nullishCoalesce(options.tolerance, () => ( this.builderLineTolerance())) : null;
|
|
5483
|
+
const touched = { faces: [], lines: [], edges: [] };
|
|
5484
|
+
const size = m.map.faces.reduce((s, f) => Math.max(s, f.bounds.maxX - f.bounds.minX, f.bounds.maxY - f.bounds.minY), 1);
|
|
5485
|
+
for (const p of samplePolyline(points, Math.max(size / 2e3, 0.25 / this.viewport.zoom))) addBuilderHit(touched, vectorShapeBuilderHit(m, p, tol));
|
|
5486
|
+
if (!touched.faces.length && !touched.lines.length && !touched.edges.length) return none("There is no face under the pointer.");
|
|
5487
|
+
return this.applyShapeBuilder(m, touched, erase);
|
|
5488
|
+
}
|
|
5489
|
+
applyShapeBuilder(m, touched, erase) {
|
|
5490
|
+
const plan = planShapeBuilder(m, touched, erase);
|
|
5491
|
+
let mergedId = null;
|
|
5492
|
+
const created = /* @__PURE__ */ new Map();
|
|
5493
|
+
this.change(erase ? "Shape Builder Delete" : "Shape Builder", () => {
|
|
5494
|
+
let nodes = this.doc.nodes;
|
|
5495
|
+
m.entries.forEach((entry, i) => {
|
|
5496
|
+
const node = entry.node;
|
|
5497
|
+
const toLocal = (path) => _chunkVNYRI265cjs.transformBezierPath.call(void 0, path, invertMatrix(multiplyMatrices(nodeMatrix(node), entry.parent)));
|
|
5498
|
+
const list = [];
|
|
5499
|
+
const r = plan.replace.get(i);
|
|
5500
|
+
if (r === void 0) list.push(node);
|
|
5501
|
+
else if (_optionalChain([r, 'optionalAccess', _145 => _145.kind]) === "fill") list.push({ ...node, fillRule: "nonzero", subpaths: bezierToSubpaths(toLocal(r.path)) });
|
|
5502
|
+
else if (_optionalChain([r, 'optionalAccess', _146 => _146.kind]) === "outline") list.push({ ...node, subpaths: bezierToSubpaths(toLocal(r.path)) });
|
|
5503
|
+
else if (_optionalChain([r, 'optionalAccess', _147 => _147.kind]) === "pieces") {
|
|
5504
|
+
r.paths.forEach(
|
|
5505
|
+
(path, k) => list.push({ ...node, id: k === 0 ? node.id : this.newId(), subpaths: bezierToSubpaths(toLocal(path)).map((sp) => ({ ...sp, closed: false })) })
|
|
5506
|
+
);
|
|
5507
|
+
}
|
|
5508
|
+
if (plan.merged && plan.merged.style === i) {
|
|
5509
|
+
mergedId = this.newId();
|
|
5510
|
+
const merged = {
|
|
5511
|
+
...vectorResultStyle(node, "fill"),
|
|
5512
|
+
type: "path",
|
|
5513
|
+
id: mergedId,
|
|
5514
|
+
name: "Shape",
|
|
5515
|
+
...node.transform ? { transform: node.transform } : {},
|
|
5516
|
+
subpaths: bezierToSubpaths(toLocal(plan.merged.path))
|
|
5517
|
+
};
|
|
5518
|
+
if (plan.merged.currentFill || !hasPaint(merged.fill)) merged.fill = hasPaint(this.defaults.fill) ? this.defaults.fill : "#808080";
|
|
5519
|
+
list.push(merged);
|
|
5520
|
+
}
|
|
5521
|
+
if (r === void 0 && list.length === 1) return;
|
|
5522
|
+
created.set(node.id, list.map((n) => n.id));
|
|
5523
|
+
nodes = spliceTree(nodes, node.id, list);
|
|
5524
|
+
});
|
|
5525
|
+
this.setDoc(nodes);
|
|
5526
|
+
const selection = this.selection.flatMap((id) => _nullishCoalesce(created.get(id), () => ( [id])));
|
|
5527
|
+
if (mergedId && !selection.includes(mergedId)) selection.push(mergedId);
|
|
5528
|
+
this.selection = selection.filter((id, k) => !!this.getNode(id) && selection.indexOf(id) === k);
|
|
5529
|
+
this.anchors = [];
|
|
5530
|
+
this.editingId = null;
|
|
5531
|
+
});
|
|
5532
|
+
this.builderCache = null;
|
|
5533
|
+
return { ok: true, merged: mergedId, faces: touched.faces.length, lines: touched.lines.length, edges: erase ? vectorBuilderErasedEdges(m, touched).length : 0 };
|
|
5534
|
+
}
|
|
5535
|
+
/** The paint bucket's map of the visible outlines, cached per document and gap. */
|
|
5536
|
+
fillMap(gap) {
|
|
5537
|
+
if (_optionalChain([this, 'access', _148 => _148.fillCache, 'optionalAccess', _149 => _149.doc]) === this.doc && this.fillCache.gap === gap) return this.fillCache.map;
|
|
5538
|
+
const map = vectorFillMap(this.doc, gap);
|
|
5539
|
+
this.fillCache = { doc: this.doc, gap, map };
|
|
5540
|
+
return map;
|
|
5541
|
+
}
|
|
5542
|
+
/**
|
|
5543
|
+
* Paint bucket: the region the visible outlines enclose around `point` (document units),
|
|
5544
|
+
* crossings split and islands left as holes, becomes a new path filled with the current fill
|
|
5545
|
+
* default, placed just below the selection (or on top when nothing is selected). `gap`
|
|
5546
|
+
* (default `editing.fillGap`) closes gaps up to that size between loose ends. Returns the new
|
|
5547
|
+
* path's id, or null when nothing encloses the point.
|
|
5548
|
+
*/
|
|
5549
|
+
fillRegion(point, options = {}) {
|
|
5550
|
+
if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) return null;
|
|
5551
|
+
const region = _optionalChain([this, 'access', _150 => _150.fillMap, 'call', _151 => _151(_nullishCoalesce(options.gap, () => ( this.editing.fillGap))), 'optionalAccess', _152 => _152.regionAt, 'call', _153 => _153([point.x, point.y])]);
|
|
5552
|
+
if (!_optionalChain([region, 'optionalAccess', _154 => _154.length])) return null;
|
|
5553
|
+
let below = null;
|
|
5554
|
+
const roots = new Set(this.selectedRoots());
|
|
5555
|
+
walkVectorNodes(this.doc.nodes, (n) => {
|
|
5556
|
+
if (!below && roots.has(n.id)) below = n.id;
|
|
5557
|
+
});
|
|
5558
|
+
const subpaths = bezierToSubpaths(below ? this.intoParentSpace(below, region) : region);
|
|
5559
|
+
if (!subpaths.length) return null;
|
|
5560
|
+
const id = this.newId();
|
|
5561
|
+
const node = { id, type: "path", name: "Fill", ...this.styleFor(false), stroke: null, fillRule: "nonzero", subpaths };
|
|
5562
|
+
if (!hasPaint(node.fill)) node.fill = "#808080";
|
|
5563
|
+
const target = below;
|
|
5564
|
+
this.change("Fill Region", () => {
|
|
5565
|
+
if (target) {
|
|
5566
|
+
const current = this.getNode(target);
|
|
5567
|
+
this.setDoc(spliceTree(this.doc.nodes, target, [node, current]));
|
|
5568
|
+
} else this.setDoc([...this.doc.nodes, node]);
|
|
5569
|
+
if (!target) this.selection = [id];
|
|
5570
|
+
this.anchors = [];
|
|
5571
|
+
this.editingId = null;
|
|
5572
|
+
});
|
|
5573
|
+
return id;
|
|
5574
|
+
}
|
|
5575
|
+
/** Updates the Shape Builder / paint bucket highlight for the pointer at `p`; true when it changed. */
|
|
5576
|
+
hoverBuilder(p, alt) {
|
|
5577
|
+
if (this.tool === "paintBucket") {
|
|
5578
|
+
const region = _nullishCoalesce(_optionalChain([this, 'access', _155 => _155.fillMap, 'call', _156 => _156(this.editing.fillGap), 'optionalAccess', _157 => _157.regionAt, 'call', _158 => _158([p.x, p.y])]), () => ( null));
|
|
5579
|
+
const key2 = region ? _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, region, { precision: 2 }) : null;
|
|
5580
|
+
if (key2 === this.builderHoverKey) return false;
|
|
5581
|
+
this.builderHoverKey = key2;
|
|
5582
|
+
this.builderPreview = region ? { mode: "fill", faces: [region], lines: [], trail: null } : null;
|
|
5583
|
+
return true;
|
|
5584
|
+
}
|
|
5585
|
+
const m = this.selectedRoots().length ? this.shapeBuilderMap() : null;
|
|
5586
|
+
const hit = m ? vectorShapeBuilderHit(m, p, alt ? this.builderLineTolerance() : null) : null;
|
|
5587
|
+
const key = hit ? `${alt ? "erase" : "merge"}:${JSON.stringify(hit)}` : null;
|
|
5588
|
+
if (key === this.builderHoverKey) return false;
|
|
5589
|
+
this.builderHoverKey = key;
|
|
5590
|
+
const touched = { faces: [], lines: [], edges: [] };
|
|
5591
|
+
addBuilderHit(touched, hit);
|
|
5592
|
+
this.builderPreview = hit && m ? this.builderPreviewOf(m, touched, alt, null) : null;
|
|
5593
|
+
return true;
|
|
5594
|
+
}
|
|
5595
|
+
builderPreviewOf(m, touched, erase, trail) {
|
|
5596
|
+
const faces = m.map.faces;
|
|
5597
|
+
return {
|
|
5598
|
+
mode: erase ? "erase" : "merge",
|
|
5599
|
+
faces: touched.faces.map((f) => faces[f].path),
|
|
5600
|
+
// Edges bounding a face touched too go with the face, so they are not shown apart.
|
|
5601
|
+
lines: [...touched.lines.map((k) => m.pieces[k].path), ...erase ? vectorBuilderErasedEdges(m, touched).map((k) => m.edges[k].path) : []],
|
|
5602
|
+
trail
|
|
5603
|
+
};
|
|
5604
|
+
}
|
|
5605
|
+
downBuilder(p, input) {
|
|
5606
|
+
this.builderHoverKey = null;
|
|
5607
|
+
if (this.tool === "paintBucket") {
|
|
5608
|
+
this.fillRegion(p);
|
|
5609
|
+
this.builderPreview = null;
|
|
5610
|
+
this.hoverBuilder(p, false);
|
|
5611
|
+
this.notify();
|
|
5612
|
+
return;
|
|
5613
|
+
}
|
|
5614
|
+
const m = this.selectedRoots().length ? this.shapeBuilderMap() : null;
|
|
5615
|
+
if (!m) return;
|
|
5616
|
+
const erase = !!input.alt;
|
|
5617
|
+
const touched = { faces: [], lines: [], edges: [] };
|
|
5618
|
+
addBuilderHit(touched, vectorShapeBuilderHit(m, p, erase ? this.builderLineTolerance() : null));
|
|
5619
|
+
this.drag = { kind: "builder", erase, points: [p], touched, map: m };
|
|
5620
|
+
this.interaction = { type: "builder", mode: erase ? "erase" : "merge", points: [p] };
|
|
5621
|
+
this.builderPreview = this.builderPreviewOf(m, touched, erase, [p]);
|
|
5622
|
+
this.notify();
|
|
5623
|
+
}
|
|
5624
|
+
moveBuilder(drag, p) {
|
|
5625
|
+
const last = drag.points[drag.points.length - 1];
|
|
5626
|
+
if (Math.hypot(p.x - last.x, p.y - last.y) * this.viewport.zoom < 1) return;
|
|
5627
|
+
const tol = drag.erase ? this.builderLineTolerance() : null;
|
|
5628
|
+
for (const q of samplePolyline([last, p], 2 / this.viewport.zoom)) addBuilderHit(drag.touched, vectorShapeBuilderHit(drag.map, q, tol));
|
|
5629
|
+
drag.points.push(p);
|
|
5630
|
+
this.interaction = { type: "builder", mode: drag.erase ? "erase" : "merge", points: drag.points.slice() };
|
|
5631
|
+
this.builderPreview = this.builderPreviewOf(drag.map, drag.touched, drag.erase, drag.points.slice());
|
|
5632
|
+
this.notify();
|
|
5633
|
+
}
|
|
5634
|
+
upBuilder(drag) {
|
|
5635
|
+
this.builderPreview = null;
|
|
5636
|
+
this.builderHoverKey = null;
|
|
5637
|
+
if (!drag.touched.faces.length && !drag.touched.lines.length && !drag.touched.edges.length) {
|
|
5638
|
+
this.notify();
|
|
5639
|
+
return;
|
|
5640
|
+
}
|
|
5641
|
+
this.applyShapeBuilder(drag.map, drag.touched, drag.erase);
|
|
5642
|
+
}
|
|
5643
|
+
// -------------------------------------------------------------------------
|
|
5118
5644
|
// Anchor editing
|
|
5119
5645
|
// -------------------------------------------------------------------------
|
|
5120
5646
|
updateAnchors(doc, refs, fn) {
|
|
@@ -5157,7 +5683,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5157
5683
|
/** `doc` with anchor `ref` moved to document point `to` by a Curvature-tool move. */
|
|
5158
5684
|
curvatureMoved(doc, ref, to) {
|
|
5159
5685
|
const node = findVectorNode(doc.nodes, ref.nodeId);
|
|
5160
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5686
|
+
if (_optionalChain([node, 'optionalAccess', _159 => _159.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
|
|
5161
5687
|
const q = this.toLocal(ref.nodeId, to, doc);
|
|
5162
5688
|
const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? curvatureMoveAnchor(sp, ref.index, q) : sp);
|
|
5163
5689
|
const nodes = mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n);
|
|
@@ -5166,7 +5692,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5166
5692
|
/** `doc` with segment `ref` bent through document point `p` at parameter `t`. */
|
|
5167
5693
|
bent(doc, ref, t, p) {
|
|
5168
5694
|
const node = findVectorNode(doc.nodes, ref.nodeId);
|
|
5169
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5695
|
+
if (_optionalChain([node, 'optionalAccess', _160 => _160.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
|
|
5170
5696
|
const q = this.toLocal(ref.nodeId, p, doc);
|
|
5171
5697
|
const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? bendSegment(sp, ref.segment, t, q) : sp);
|
|
5172
5698
|
return { ...doc, nodes: mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n) };
|
|
@@ -5177,7 +5703,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5177
5703
|
*/
|
|
5178
5704
|
bendSegment(ref, to, t = 0.5) {
|
|
5179
5705
|
const node = this.getNode(ref.nodeId);
|
|
5180
|
-
const sp = _optionalChain([node, 'optionalAccess',
|
|
5706
|
+
const sp = _optionalChain([node, 'optionalAccess', _161 => _161.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
|
|
5181
5707
|
if (!sp || ref.segment < 0 || ref.segment >= (sp.closed ? sp.anchors.length : sp.anchors.length - 1) || sp.anchors.length < 2) return { ok: false, message: "There is no such segment." };
|
|
5182
5708
|
if (node.locked) return { ok: false, message: "The path is locked." };
|
|
5183
5709
|
this.change("Bend Segment", () => {
|
|
@@ -5212,7 +5738,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5212
5738
|
/** Adds an anchor on the nearest segment of `nodeId` to document point `point` (shape unchanged). */
|
|
5213
5739
|
insertAnchorAt(nodeId, point) {
|
|
5214
5740
|
const node = this.getNode(nodeId);
|
|
5215
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5741
|
+
if (_optionalChain([node, 'optionalAccess', _162 => _162.type]) !== "path") return null;
|
|
5216
5742
|
const hit = nearestSegment(node, this.toLocal(nodeId, point));
|
|
5217
5743
|
if (!hit) return null;
|
|
5218
5744
|
const { subpath, index } = insertAnchor(node.subpaths[hit.subpath], hit.segment, hit.t);
|
|
@@ -5256,7 +5782,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5256
5782
|
setClosed(closed, nodeId) {
|
|
5257
5783
|
const targets = nodeId ? (() => {
|
|
5258
5784
|
const n = this.getNode(nodeId);
|
|
5259
|
-
return _optionalChain([n, 'optionalAccess',
|
|
5785
|
+
return _optionalChain([n, 'optionalAccess', _163 => _163.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
|
|
5260
5786
|
})() : this.anchors.map((r) => ({ nodeId: r.nodeId, subpath: r.subpath }));
|
|
5261
5787
|
if (!targets.length) return { ok: false, message: "Select a path or points." };
|
|
5262
5788
|
this.change(closed ? "Close Path" : "Open Path", () => {
|
|
@@ -5277,7 +5803,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5277
5803
|
this.setDoc(
|
|
5278
5804
|
mapTree(
|
|
5279
5805
|
this.doc.nodes,
|
|
5280
|
-
(n) => n.type === "path" && set.has(n.id) ? { ...n, subpaths: n.subpaths.map(reverseSubpath), ..._optionalChain([n, 'access',
|
|
5806
|
+
(n) => n.type === "path" && set.has(n.id) ? { ...n, subpaths: n.subpaths.map(reverseSubpath), ..._optionalChain([n, 'access', _164 => _164.strokeWidthProfile, 'optionalAccess', _165 => _165.length]) ? { strokeWidthProfile: reverseWidthProfile(n.strokeWidthProfile) } : {} } : n
|
|
5281
5807
|
)
|
|
5282
5808
|
);
|
|
5283
5809
|
this.anchors = [];
|
|
@@ -5415,7 +5941,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5415
5941
|
*/
|
|
5416
5942
|
cutPathAt(nodeId, point) {
|
|
5417
5943
|
const node = this.getNode(nodeId);
|
|
5418
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5944
|
+
if (_optionalChain([node, 'optionalAccess', _166 => _166.type]) !== "path" || node.locked) return null;
|
|
5419
5945
|
const local = this.toLocal(nodeId, point);
|
|
5420
5946
|
const hit = nearestSegment(node, local);
|
|
5421
5947
|
if (!hit) return null;
|
|
@@ -5465,7 +5991,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5465
5991
|
if (n.visible === false || n.locked || parent && blocked.has(parent.id)) blocked.add(n.id);
|
|
5466
5992
|
});
|
|
5467
5993
|
const visible = (p) => !blocked.has(p.id);
|
|
5468
|
-
if (_optionalChain([ids, 'optionalAccess',
|
|
5994
|
+
if (_optionalChain([ids, 'optionalAccess', _167 => _167.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
|
|
5469
5995
|
const box = polylineBounds(points.map(toPoint2), pad);
|
|
5470
5996
|
if (!box) return [];
|
|
5471
5997
|
const out = [];
|
|
@@ -5521,10 +6047,10 @@ var VectorEditorController = (_class3 = class {
|
|
|
5521
6047
|
const region = eraserRegion(pts, width);
|
|
5522
6048
|
if (!region.length) return [];
|
|
5523
6049
|
const plan = [];
|
|
5524
|
-
const rb =
|
|
6050
|
+
const rb = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, region);
|
|
5525
6051
|
const reach = rb ? [{ x: rb.minX, y: rb.minY }, { x: rb.maxX, y: rb.maxY }] : points;
|
|
5526
6052
|
for (const node of this.strokeTargets(reach, options.ids, 0)) {
|
|
5527
|
-
const local =
|
|
6053
|
+
const local = _chunkVNYRI265cjs.transformBezierPath.call(void 0, region, invertMatrix(this.worldOf(node.id)));
|
|
5528
6054
|
const live = node.subpaths.filter((sp) => sp.anchors.length > 1);
|
|
5529
6055
|
if (!live.length) continue;
|
|
5530
6056
|
if (hasPaint(node.fill) && live.every((sp) => sp.closed)) {
|
|
@@ -5551,7 +6077,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5551
6077
|
finishPath() {
|
|
5552
6078
|
if (!this.pen) return;
|
|
5553
6079
|
const node = this.getNode(this.pen.nodeId);
|
|
5554
|
-
const sp = _optionalChain([node, 'optionalAccess',
|
|
6080
|
+
const sp = _optionalChain([node, 'optionalAccess', _168 => _168.subpaths, 'access', _169 => _169[this.pen.subpath]]);
|
|
5555
6081
|
const pen = this.pen;
|
|
5556
6082
|
this.pen = null;
|
|
5557
6083
|
this.pointer = null;
|
|
@@ -5595,7 +6121,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5595
6121
|
if (trimmed.startsWith("{")) {
|
|
5596
6122
|
try {
|
|
5597
6123
|
const data = JSON.parse(trimmed);
|
|
5598
|
-
if (_optionalChain([data, 'optionalAccess',
|
|
6124
|
+
if (_optionalChain([data, 'optionalAccess', _170 => _170.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
|
|
5599
6125
|
} catch (e3) {
|
|
5600
6126
|
nodes = null;
|
|
5601
6127
|
}
|
|
@@ -5607,7 +6133,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5607
6133
|
}
|
|
5608
6134
|
}
|
|
5609
6135
|
} else nodes = this.clipboard;
|
|
5610
|
-
if (!_optionalChain([nodes, 'optionalAccess',
|
|
6136
|
+
if (!_optionalChain([nodes, 'optionalAccess', _171 => _171.length])) return [];
|
|
5611
6137
|
const offset = _nullishCoalesce(options.offset, () => ( (text && !text.trim().startsWith("{") ? { x: 0, y: 0 } : { x: 10, y: 10 })));
|
|
5612
6138
|
const copies = nodes.map((n) => transformVectorNode(this.freshIds(n), translateMatrix(offset.x, offset.y)));
|
|
5613
6139
|
this.change("Paste", () => {
|
|
@@ -5651,14 +6177,14 @@ var VectorEditorController = (_class3 = class {
|
|
|
5651
6177
|
if (!frame) return null;
|
|
5652
6178
|
const { box, handles } = getVectorSelectionBoxGeometry(frame, this.viewport);
|
|
5653
6179
|
const r = this.hitRadius + 2;
|
|
5654
|
-
const
|
|
5655
|
-
for (const h of
|
|
6180
|
+
const usable2 = box.width < 2 * r || box.height < 2 * r ? handles.filter((h) => h.handle.length === 2 || h.handle === "rotate") : handles;
|
|
6181
|
+
for (const h of usable2) if (Math.hypot(h.screen.x - screen.x, h.screen.y - screen.y) <= r * Math.SQRT2) return h.handle;
|
|
5656
6182
|
return null;
|
|
5657
6183
|
}
|
|
5658
6184
|
hitHandle(screen) {
|
|
5659
6185
|
for (const ref of getVisibleHandles(this.view()).reverse()) {
|
|
5660
6186
|
const a = getAnchorWorld(this.doc, ref);
|
|
5661
|
-
const h = _optionalChain([a, 'optionalAccess',
|
|
6187
|
+
const h = _optionalChain([a, 'optionalAccess', _172 => _172[ref.handle]]);
|
|
5662
6188
|
if (!h) continue;
|
|
5663
6189
|
const s = this.documentToScreen(h);
|
|
5664
6190
|
if (Math.hypot(s.x - screen.x, s.y - screen.y) <= this.hitRadius) return ref;
|
|
@@ -5828,9 +6354,9 @@ var VectorEditorController = (_class3 = class {
|
|
|
5828
6354
|
downWidth(screen, p, input) {
|
|
5829
6355
|
const hit = this.hitWidthHandle(screen);
|
|
5830
6356
|
const spot = hit ? null : this.strokeSpotAt(p);
|
|
5831
|
-
const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess',
|
|
6357
|
+
const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _173 => _173.ref, 'access', _174 => _174.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _175 => _175.nodeId])));
|
|
5832
6358
|
const node = nodeId ? this.getNode(nodeId) : void 0;
|
|
5833
|
-
const g = _optionalChain([node, 'optionalAccess',
|
|
6359
|
+
const g = _optionalChain([node, 'optionalAccess', _176 => _176.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
|
|
5834
6360
|
if (!node || node.type !== "path" || !g) {
|
|
5835
6361
|
if (this.widthPoint) {
|
|
5836
6362
|
this.widthPoint = null;
|
|
@@ -5849,7 +6375,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5849
6375
|
if (hit) {
|
|
5850
6376
|
profile = sanitizeWidthProfile(node.strokeWidthProfile);
|
|
5851
6377
|
ref = { nodeId: node.id, index: hit.ref.index, subpath: hit.ref.subpath };
|
|
5852
|
-
t = _nullishCoalesce(_optionalChain([profile, 'access',
|
|
6378
|
+
t = _nullishCoalesce(_optionalChain([profile, 'access', _177 => _177[ref.index], 'optionalAccess', _178 => _178.t]), () => ( 0));
|
|
5853
6379
|
subpath = hit.ref.subpath;
|
|
5854
6380
|
if (hit.ref.part === "center") mode = "move";
|
|
5855
6381
|
else if (input.alt) side = hit.ref.part;
|
|
@@ -5936,6 +6462,9 @@ var VectorEditorController = (_class3 = class {
|
|
|
5936
6462
|
return this.downPencil(p, input);
|
|
5937
6463
|
case "width":
|
|
5938
6464
|
return this.downWidth(screen, p, input);
|
|
6465
|
+
case "shapeBuilder":
|
|
6466
|
+
case "paintBucket":
|
|
6467
|
+
return this.downBuilder(p, input);
|
|
5939
6468
|
case "scissors": {
|
|
5940
6469
|
const seg = this.nearestOutline(p);
|
|
5941
6470
|
if (seg) this.cutPathAt(seg.nodeId, seg.point);
|
|
@@ -6071,7 +6600,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
6071
6600
|
}
|
|
6072
6601
|
downPen(screen, p, input) {
|
|
6073
6602
|
const before = this.snapshot();
|
|
6074
|
-
const sp = this.pen ? _optionalChain([this, 'access',
|
|
6603
|
+
const sp = this.pen ? _optionalChain([this, 'access', _179 => _179.getNode, 'call', _180 => _180(this.pen.nodeId), 'optionalAccess', _181 => _181.subpaths, 'access', _182 => _182[this.pen.subpath]]) : void 0;
|
|
6075
6604
|
if (this.pen && sp) {
|
|
6076
6605
|
const pen = this.pen;
|
|
6077
6606
|
const first = { nodeId: pen.nodeId, subpath: pen.subpath, index: 0 };
|
|
@@ -6165,6 +6694,11 @@ var VectorEditorController = (_class3 = class {
|
|
|
6165
6694
|
pointerMove(screen, input = {}) {
|
|
6166
6695
|
const p = this.screenToDocument(screen);
|
|
6167
6696
|
const drag = this.drag;
|
|
6697
|
+
if (!drag && (this.tool === "shapeBuilder" || this.tool === "paintBucket")) {
|
|
6698
|
+
this.pointer = p;
|
|
6699
|
+
if (this.hoverBuilder(p, !!input.alt)) this.notify();
|
|
6700
|
+
return;
|
|
6701
|
+
}
|
|
6168
6702
|
if (!drag) {
|
|
6169
6703
|
const hover = this.computeHover(screen);
|
|
6170
6704
|
const pointerMatters = this.tool === "pen" && !!this.pen;
|
|
@@ -6296,6 +6830,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
6296
6830
|
this.notify(true);
|
|
6297
6831
|
return;
|
|
6298
6832
|
}
|
|
6833
|
+
case "builder":
|
|
6834
|
+
return this.moveBuilder(drag, p);
|
|
6299
6835
|
case "stroke": {
|
|
6300
6836
|
const last = drag.points[drag.points.length - 1];
|
|
6301
6837
|
if (Math.hypot(p.x - last.x, p.y - last.y) * this.viewport.zoom < 1.5) return;
|
|
@@ -6326,7 +6862,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
6326
6862
|
}
|
|
6327
6863
|
case "shape": {
|
|
6328
6864
|
const node = this.getNode(drag.nodeId);
|
|
6329
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
6865
|
+
if (_optionalChain([node, 'optionalAccess', _183 => _183.type]) !== "path") return;
|
|
6330
6866
|
const leave = { at: drag.start, constrain: input.shift ? drag.tool === "line" ? "angle" : "square" : null, curves: false };
|
|
6331
6867
|
let end = this.snapDrawn(p, leave, input, () => drag.targets ??= this.drawingTargets(null));
|
|
6332
6868
|
if (!this.snappedToObject && drag.tool !== "line" && !input.shift && !input.mod && this.snap.objects && drag.targets) end = this.matchShapeSize(drag.targets, drag.start, end, input.alt);
|
|
@@ -6384,14 +6920,14 @@ var VectorEditorController = (_class3 = class {
|
|
|
6384
6920
|
for (const q of drag.lazy.push([p.x, p.y])) {
|
|
6385
6921
|
if (Math.hypot(q[0] - last[0], q[1] - last[1]) * this.viewport.zoom < 1.5) continue;
|
|
6386
6922
|
drag.points.push(q);
|
|
6387
|
-
_optionalChain([drag, 'access',
|
|
6923
|
+
_optionalChain([drag, 'access', _184 => _184.pressures, 'optionalAccess', _185 => _185.push, 'call', _186 => _186(drag.pressure)]);
|
|
6388
6924
|
moved = true;
|
|
6389
6925
|
}
|
|
6390
6926
|
const string = drag.lazy.string();
|
|
6391
6927
|
const node = this.getNode(drag.nodeId);
|
|
6392
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
6928
|
+
if (_optionalChain([node, 'optionalAccess', _187 => _187.type]) !== "path") return;
|
|
6393
6929
|
if (!moved) {
|
|
6394
|
-
if (string && _optionalChain([this, 'access',
|
|
6930
|
+
if (string && _optionalChain([this, 'access', _188 => _188.interaction, 'optionalAccess', _189 => _189.type]) === "draw") {
|
|
6395
6931
|
this.interaction = { ...this.interaction, string: [{ x: string[0][0], y: string[0][1] }, { x: string[1][0], y: string[1][1] }] };
|
|
6396
6932
|
this.notify();
|
|
6397
6933
|
}
|
|
@@ -6427,8 +6963,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
6427
6963
|
}
|
|
6428
6964
|
this.setGuides(res);
|
|
6429
6965
|
return {
|
|
6430
|
-
dx: _optionalChain([res, 'optionalAccess',
|
|
6431
|
-
dy: _optionalChain([res, 'optionalAccess',
|
|
6966
|
+
dx: _optionalChain([res, 'optionalAccess', _190 => _190.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
|
|
6967
|
+
dy: _optionalChain([res, 'optionalAccess', _191 => _191.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
|
|
6432
6968
|
};
|
|
6433
6969
|
}
|
|
6434
6970
|
/** The anchor a point drag snaps by, where it started: the grabbed one, else the moving one nearest the press. */
|
|
@@ -6507,7 +7043,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
6507
7043
|
if (drag.moved) return this.commit("Corner Radius", drag.before);
|
|
6508
7044
|
if (drag.alt) {
|
|
6509
7045
|
const kind = nextVectorCornerKind(drag.widget.kind);
|
|
6510
|
-
this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access',
|
|
7046
|
+
this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _192 => _192.corner, 'optionalAccess', _193 => _193.radius]), () => ( 0)), kind));
|
|
6511
7047
|
return this.commit("Corner Kind", drag.before);
|
|
6512
7048
|
}
|
|
6513
7049
|
const ref = drag.widget.ref;
|
|
@@ -6526,6 +7062,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
6526
7062
|
} else this.notify();
|
|
6527
7063
|
return;
|
|
6528
7064
|
}
|
|
7065
|
+
case "builder":
|
|
7066
|
+
return this.upBuilder(drag);
|
|
6529
7067
|
case "stroke": {
|
|
6530
7068
|
this.notify();
|
|
6531
7069
|
if (drag.tool === "knife") this.knife(drag.points);
|
|
@@ -6551,14 +7089,14 @@ var VectorEditorController = (_class3 = class {
|
|
|
6551
7089
|
}
|
|
6552
7090
|
case "pencil": {
|
|
6553
7091
|
const node = this.getNode(drag.nodeId);
|
|
6554
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
7092
|
+
if (_optionalChain([node, 'optionalAccess', _194 => _194.type]) !== "path" || drag.points.length < 2) {
|
|
6555
7093
|
this.doc = drag.before.doc;
|
|
6556
7094
|
this.notify(true);
|
|
6557
7095
|
return;
|
|
6558
7096
|
}
|
|
6559
7097
|
for (const q of drag.lazy.finish()) {
|
|
6560
7098
|
drag.points.push(q);
|
|
6561
|
-
_optionalChain([drag, 'access',
|
|
7099
|
+
_optionalChain([drag, 'access', _195 => _195.pressures, 'optionalAccess', _196 => _196.push, 'call', _197 => _197(drag.pressure)]);
|
|
6562
7100
|
}
|
|
6563
7101
|
const shape = this.editing.recognizeShapes ? recognizeInkShape(drag.points, { minSize: 6 / this.viewport.zoom }) : null;
|
|
6564
7102
|
if (shape) {
|
|
@@ -6566,7 +7104,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
6566
7104
|
this.selection = [drag.nodeId];
|
|
6567
7105
|
return this.commit(`Draw ${inkShapeLabel(shape)}`, drag.before);
|
|
6568
7106
|
}
|
|
6569
|
-
const fitted =
|
|
7107
|
+
const fitted = _chunkVNYRI265cjs.fitCubics.call(void 0, drag.points, 1.5 / this.viewport.zoom, { cornerAngleDeg: 60 });
|
|
6570
7108
|
const anchors = [];
|
|
6571
7109
|
for (const c of fitted) {
|
|
6572
7110
|
if (!anchors.length) anchors.push({ x: c.p0[0], y: c.p0[1] });
|
|
@@ -6597,7 +7135,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
6597
7135
|
this.drag = null;
|
|
6598
7136
|
this.interaction = null;
|
|
6599
7137
|
this.guides = null;
|
|
6600
|
-
if (drag.kind === "pan") {
|
|
7138
|
+
if (drag.kind === "pan" || drag.kind === "builder") {
|
|
7139
|
+
if (drag.kind === "builder") this.builderPreview = null;
|
|
6601
7140
|
this.notify();
|
|
6602
7141
|
return;
|
|
6603
7142
|
}
|
|
@@ -6629,7 +7168,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
6629
7168
|
this.convertAnchors(a.in || a.out ? "corner" : "smooth", [anchor]);
|
|
6630
7169
|
return;
|
|
6631
7170
|
}
|
|
6632
|
-
const id = _nullishCoalesce(_optionalChain([this, 'access',
|
|
7171
|
+
const id = _nullishCoalesce(_optionalChain([this, 'access', _198 => _198.hover, 'optionalAccess', _199 => _199.segment, 'optionalAccess', _200 => _200.nodeId]), () => ( this.editingId));
|
|
6633
7172
|
if (id) {
|
|
6634
7173
|
const node = this.getNode(id);
|
|
6635
7174
|
const seg = node ? nearestSegment(node, this.toLocal(id, p)) : null;
|
|
@@ -6712,7 +7251,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
6712
7251
|
this.finishPath();
|
|
6713
7252
|
return true;
|
|
6714
7253
|
}
|
|
6715
|
-
if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access',
|
|
7254
|
+
if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _201 => _201.getNode, 'call', _202 => _202(this.selection[0]), 'optionalAccess', _203 => _203.type]) === "path") {
|
|
6716
7255
|
this.tool = "direct";
|
|
6717
7256
|
this.editingId = this.selection[0];
|
|
6718
7257
|
this.notify();
|
|
@@ -6832,6 +7371,7 @@ function pencilPressureProfile(points, pressures) {
|
|
|
6832
7371
|
// src/vector/render.ts
|
|
6833
7372
|
var fmt = (n) => Math.round(n * 100) / 100;
|
|
6834
7373
|
var fmtMatrix = (m) => `matrix(${m.map((n) => Math.round(n * 1e6) / 1e6).join(" ")})`;
|
|
7374
|
+
var VECTOR_BUILDER_HATCH_GAP = 6;
|
|
6835
7375
|
function renderNode(node, defs, idPrefix) {
|
|
6836
7376
|
if (node.visible === false) return null;
|
|
6837
7377
|
if (node.type === "group") {
|
|
@@ -6854,7 +7394,7 @@ function renderNode(node, defs, idPrefix) {
|
|
|
6854
7394
|
strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)),
|
|
6855
7395
|
...node.strokeLinecap ? { strokeLinecap: node.strokeLinecap } : {},
|
|
6856
7396
|
...node.strokeLinejoin ? { strokeLinejoin: node.strokeLinejoin } : {},
|
|
6857
|
-
..._optionalChain([node, 'access',
|
|
7397
|
+
..._optionalChain([node, 'access', _204 => _204.strokeDasharray, 'optionalAccess', _205 => _205.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
|
|
6858
7398
|
fillRule: _nullishCoalesce(node.fillRule, () => ( "nonzero")),
|
|
6859
7399
|
opacity: _nullishCoalesce(node.opacity, () => ( 1))
|
|
6860
7400
|
};
|
|
@@ -6878,7 +7418,7 @@ function screenOutline(state, node) {
|
|
|
6878
7418
|
const v2 = state.viewport;
|
|
6879
7419
|
const view = [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y];
|
|
6880
7420
|
const parent = _nullishCoalesce(vectorParentMatrix(state.document.nodes, node.id), () => ( IDENTITY_MATRIX));
|
|
6881
|
-
return collectWithMatrix(node, parent).map(({ path, parent: m }) =>
|
|
7421
|
+
return collectWithMatrix(node, parent).map(({ path, parent: m }) => _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, _chunkVNYRI265cjs.transformBezierPath.call(void 0, vectorPathWorldBezier(path, m), view), { precision: 2 })).join(" ");
|
|
6882
7422
|
}
|
|
6883
7423
|
function collectWithMatrix(node, parent) {
|
|
6884
7424
|
if (node.type === "path") return [{ path: node, parent }];
|
|
@@ -6903,9 +7443,9 @@ function getVectorOverlayRenderData(state) {
|
|
|
6903
7443
|
};
|
|
6904
7444
|
for (const id of state.selection) outline(id, true);
|
|
6905
7445
|
if (state.editingId) outline(state.editingId, true);
|
|
6906
|
-
if (_optionalChain([state, 'access',
|
|
7446
|
+
if (_optionalChain([state, 'access', _206 => _206.hover, 'optionalAccess', _207 => _207.nodeId]) && !state.interaction) outline(state.hover.nodeId, false);
|
|
6907
7447
|
let selectionBox = null;
|
|
6908
|
-
if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access',
|
|
7448
|
+
if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _208 => _208.interaction, 'optionalAccess', _209 => _209.type]) !== "marquee") {
|
|
6909
7449
|
const g = getVectorSelectionBoxGeometry(state.selectionFrame, state.viewport);
|
|
6910
7450
|
selectionBox = { ...g.box, angle: g.angle, transform: g.transform, corners: g.corners, handles: g.handles };
|
|
6911
7451
|
}
|
|
@@ -6915,9 +7455,9 @@ function getVectorOverlayRenderData(state) {
|
|
|
6915
7455
|
const a = getAnchorWorld(doc, ref);
|
|
6916
7456
|
const s = toScreen(state, a);
|
|
6917
7457
|
const closes = !!state.pen && state.pen.nodeId === ref.nodeId && state.pen.subpath === ref.subpath && ref.index === 0;
|
|
6918
|
-
return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access',
|
|
7458
|
+
return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access', _210 => _210.hover, 'optionalAccess', _211 => _211.anchor]), ref), closes };
|
|
6919
7459
|
});
|
|
6920
|
-
if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access',
|
|
7460
|
+
if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _212 => _212.hover, 'optionalAccess', _213 => _213.anchor])) {
|
|
6921
7461
|
const a = getAnchorWorld(doc, state.hover.anchor);
|
|
6922
7462
|
if (a) {
|
|
6923
7463
|
const s = toScreen(state, a);
|
|
@@ -6926,15 +7466,15 @@ function getVectorOverlayRenderData(state) {
|
|
|
6926
7466
|
}
|
|
6927
7467
|
const handles = getVisibleHandles(state).flatMap((ref) => {
|
|
6928
7468
|
const a = getAnchorWorld(doc, ref);
|
|
6929
|
-
const h = _optionalChain([a, 'optionalAccess',
|
|
7469
|
+
const h = _optionalChain([a, 'optionalAccess', _214 => _214[ref.handle]]);
|
|
6930
7470
|
if (!a || !h) return [];
|
|
6931
7471
|
const s = toScreen(state, h);
|
|
6932
7472
|
const sa = toScreen(state, a);
|
|
6933
|
-
const hovered = !!_optionalChain([state, 'access',
|
|
7473
|
+
const hovered = !!_optionalChain([state, 'access', _215 => _215.hover, 'optionalAccess', _216 => _216.handle]) && sameAnchor(state.hover.handle, ref) && state.hover.handle.handle === ref.handle;
|
|
6934
7474
|
return [{ ref, x: s.x, y: s.y, anchorX: sa.x, anchorY: sa.y, hovered }];
|
|
6935
7475
|
});
|
|
6936
7476
|
let marquee = null;
|
|
6937
|
-
if (_optionalChain([state, 'access',
|
|
7477
|
+
if (_optionalChain([state, 'access', _217 => _217.interaction, 'optionalAccess', _218 => _218.type]) === "marquee") {
|
|
6938
7478
|
const b = state.interaction.bounds;
|
|
6939
7479
|
const tl = toScreen(state, b);
|
|
6940
7480
|
marquee = { x: tl.x, y: tl.y, width: b.width * z, height: b.height * z };
|
|
@@ -6942,7 +7482,7 @@ function getVectorOverlayRenderData(state) {
|
|
|
6942
7482
|
let penPreview = null;
|
|
6943
7483
|
if (state.tool === "pen" && state.pen && state.pointer && !state.interaction) {
|
|
6944
7484
|
const node = findVectorNode(doc.nodes, state.pen.nodeId);
|
|
6945
|
-
const sp = _optionalChain([node, 'optionalAccess',
|
|
7485
|
+
const sp = _optionalChain([node, 'optionalAccess', _219 => _219.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
|
|
6946
7486
|
const last = sp ? getAnchorWorld(doc, { nodeId: state.pen.nodeId, subpath: state.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
|
|
6947
7487
|
if (last) {
|
|
6948
7488
|
const a = toScreen(state, last);
|
|
@@ -6955,9 +7495,9 @@ function getVectorOverlayRenderData(state) {
|
|
|
6955
7495
|
const artboard = { x: origin.x, y: origin.y, width: doc.width * z, height: doc.height * z };
|
|
6956
7496
|
let status = null;
|
|
6957
7497
|
const it = state.interaction;
|
|
6958
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
6959
|
-
else if (_optionalChain([it, 'optionalAccess',
|
|
6960
|
-
else if (_optionalChain([it, 'optionalAccess',
|
|
7498
|
+
if (_optionalChain([it, 'optionalAccess', _220 => _220.type]) === "rotate") status = `${Math.round(it.angle)}\xB0`;
|
|
7499
|
+
else if (_optionalChain([it, 'optionalAccess', _221 => _221.type]) === "move" || _optionalChain([it, 'optionalAccess', _222 => _222.type]) === "anchors") status = `\u0394 ${fmt(it.dx)}, ${fmt(it.dy)}`;
|
|
7500
|
+
else if (_optionalChain([it, 'optionalAccess', _223 => _223.type]) === "scale" || _optionalChain([it, 'optionalAccess', _224 => _224.type]) === "draw") {
|
|
6961
7501
|
const b = it.type === "draw" ? findVectorNode(doc.nodes, it.nodeId) ? vectorNodeBounds(findVectorNode(doc.nodes, it.nodeId)) : null : state.selectionFrame;
|
|
6962
7502
|
if (b) status = `W ${fmt(b.width)} \xD7 H ${fmt(b.height)}`;
|
|
6963
7503
|
}
|
|
@@ -6974,24 +7514,24 @@ function getVectorOverlayRenderData(state) {
|
|
|
6974
7514
|
}
|
|
6975
7515
|
}
|
|
6976
7516
|
let toolStroke = null;
|
|
6977
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
7517
|
+
if (_optionalChain([it, 'optionalAccess', _225 => _225.type]) === "stroke") {
|
|
6978
7518
|
const pts = it.points.map((q) => toScreen(state, q));
|
|
6979
7519
|
const d = pts.map((q, i) => `${i ? "L" : "M"}${fmt(q.x)} ${fmt(q.y)}`).join("") + (pts.length === 1 ? `L${fmt(pts[0].x)} ${fmt(pts[0].y)}` : "");
|
|
6980
7520
|
toolStroke = { tool: it.tool, d, width: fmt(it.width * z) };
|
|
6981
7521
|
}
|
|
6982
7522
|
let pencilString = null;
|
|
6983
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
7523
|
+
if (_optionalChain([it, 'optionalAccess', _226 => _226.type]) === "draw" && it.string) {
|
|
6984
7524
|
const a = toScreen(state, it.string[0]);
|
|
6985
7525
|
const b = toScreen(state, it.string[1]);
|
|
6986
7526
|
pencilString = { x1: fmt(a.x), y1: fmt(a.y), x2: fmt(b.x), y2: fmt(b.y) };
|
|
6987
7527
|
}
|
|
6988
|
-
const dragged = _optionalChain([it, 'optionalAccess',
|
|
7528
|
+
const dragged = _optionalChain([it, 'optionalAccess', _227 => _227.type]) === "corner" ? it.ref : null;
|
|
6989
7529
|
const cornerWidgets = getVectorCornerWidgets(state).map((w) => {
|
|
6990
7530
|
const s = toScreen(state, w);
|
|
6991
|
-
return { ref: w.ref, x: fmt(s.x), y: fmt(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access',
|
|
7531
|
+
return { ref: w.ref, x: fmt(s.x), y: fmt(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access', _228 => _228.hover, 'optionalAccess', _229 => _229.corner]), w.ref), active: !!dragged };
|
|
6992
7532
|
});
|
|
6993
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
6994
|
-
const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access',
|
|
7533
|
+
if (_optionalChain([it, 'optionalAccess', _230 => _230.type]) === "corner") status = `R ${fmt(it.radius)}`;
|
|
7534
|
+
const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access', _231 => _231.hover, 'optionalAccess', _232 => _232.segment]) && !it ? (({ x, y }) => ({ x: fmt(x), y: fmt(y) }))(toScreen(state, state.hover.segment.point)) : null;
|
|
6995
7535
|
const sc = (p) => {
|
|
6996
7536
|
const q = toScreen(state, p);
|
|
6997
7537
|
return { x: fmt(q.x), y: fmt(q.y) };
|
|
@@ -6999,14 +7539,34 @@ function getVectorOverlayRenderData(state) {
|
|
|
6999
7539
|
const sameWidth = (a, b) => !!a && a.nodeId === b.nodeId && a.index === b.index;
|
|
7000
7540
|
const widthPoints = getVectorWidthHandles(state).map((h) => {
|
|
7001
7541
|
const c = sc(h);
|
|
7002
|
-
const hw = _optionalChain([state, 'access',
|
|
7542
|
+
const hw = _optionalChain([state, 'access', _233 => _233.hover, 'optionalAccess', _234 => _234.widthPoint]);
|
|
7003
7543
|
const hovered = hw && sameWidth(hw, h.ref) && hw.subpath === h.ref.subpath ? hw.part : null;
|
|
7004
|
-
return { ref: h.ref, x: c.x, y: c.y, left: sc(h.left), right: sc(h.right), selected: h.selected, hovered, active: _optionalChain([it, 'optionalAccess',
|
|
7544
|
+
return { ref: h.ref, x: c.x, y: c.y, left: sc(h.left), right: sc(h.right), selected: h.selected, hovered, active: _optionalChain([it, 'optionalAccess', _235 => _235.type]) === "width" && sameWidth(it.ref, h.ref) };
|
|
7005
7545
|
});
|
|
7006
|
-
const spot = state.tool === "width" && !it ? _optionalChain([state, 'access',
|
|
7546
|
+
const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _236 => _236.hover, 'optionalAccess', _237 => _237.strokeSpot]) : null;
|
|
7007
7547
|
const widthSpot = spot ? { ...sc(spot.point), left: sc(spot.left), right: sc(spot.right) } : null;
|
|
7008
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
7009
|
-
|
|
7548
|
+
if (_optionalChain([it, 'optionalAccess', _238 => _238.type]) === "width") status = it.mode === "move" ? "Move width point" : `W ${fmt(it.width)}`;
|
|
7549
|
+
let builder = null;
|
|
7550
|
+
if (state.builder) {
|
|
7551
|
+
const v2 = state.viewport;
|
|
7552
|
+
const view = [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y];
|
|
7553
|
+
const svg = (path) => _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, path, { precision: 2 });
|
|
7554
|
+
const screen = state.builder.faces.map((f) => _chunkVNYRI265cjs.transformBezierPath.call(void 0, f, view));
|
|
7555
|
+
const hatch = state.builder.mode !== "fill";
|
|
7556
|
+
const trail = state.builder.trail && state.builder.trail.length > 1 ? state.builder.trail.map((q, i) => `${i ? "L" : "M"}${sc(q).x} ${sc(q).y}`).join("") : null;
|
|
7557
|
+
builder = {
|
|
7558
|
+
mode: state.builder.mode,
|
|
7559
|
+
faces: screen.map(svg),
|
|
7560
|
+
hatches: screen.map((f) => hatch ? svg(_chunkVNYRI265cjs.hatchPath.call(void 0, f, { gap: VECTOR_BUILDER_HATCH_GAP })) : ""),
|
|
7561
|
+
lines: state.builder.lines.map((l) => svg(_chunkVNYRI265cjs.transformBezierPath.call(void 0, l, view))),
|
|
7562
|
+
trail
|
|
7563
|
+
};
|
|
7564
|
+
if (state.builder.mode !== "fill" && _optionalChain([it, 'optionalAccess', _239 => _239.type]) === "builder") {
|
|
7565
|
+
const n = state.builder.faces.length;
|
|
7566
|
+
status = state.builder.mode === "erase" ? `Delete ${n} ${n === 1 ? "face" : "faces"}` : `Merge ${n} ${n === 1 ? "face" : "faces"}`;
|
|
7567
|
+
}
|
|
7568
|
+
}
|
|
7569
|
+
return { outlines, selectionBox, anchors, handles, marquee, penPreview, artboard, guides, status, toolStroke, pencilString, cutPoint, cornerWidgets, widthPoints, widthSpot, builder };
|
|
7010
7570
|
}
|
|
7011
7571
|
var VECTOR_OVERLAY_THEME = {
|
|
7012
7572
|
accent: "#0ea5e9",
|
|
@@ -7022,7 +7582,14 @@ var VECTOR_OVERLAY_THEME = {
|
|
|
7022
7582
|
/** Radius of a live corner widget (a ring with a dot). */
|
|
7023
7583
|
cornerWidgetRadius: 4,
|
|
7024
7584
|
/** Half the diagonal of a width point's diamond. */
|
|
7025
|
-
widthPointSize: 5
|
|
7585
|
+
widthPointSize: 5,
|
|
7586
|
+
/** Shape Builder faces to merge and paint bucket regions. */
|
|
7587
|
+
builderFill: "rgba(14, 165, 233, 0.22)",
|
|
7588
|
+
/** Shape Builder faces and line pieces an Alt gesture deletes. */
|
|
7589
|
+
builderErase: "#ef4444",
|
|
7590
|
+
builderEraseFill: "rgba(239, 68, 68, 0.22)",
|
|
7591
|
+
/** Opacity of the hatch lines over Shape Builder faces (drawn in the face's outline colour). */
|
|
7592
|
+
builderHatchOpacity: 0.6
|
|
7026
7593
|
};
|
|
7027
7594
|
function vectorDiamondPath(x, y, r = VECTOR_OVERLAY_THEME.widthPointSize) {
|
|
7028
7595
|
return `M${fmt(x)} ${fmt(y - r)}L${fmt(x + r)} ${fmt(y)}L${fmt(x)} ${fmt(y + r)}L${fmt(x - r)} ${fmt(y)}Z`;
|
|
@@ -7046,7 +7613,7 @@ function isVectorTextTarget(target) {
|
|
|
7046
7613
|
if (!el || typeof el !== "object") return false;
|
|
7047
7614
|
const tag = (_nullishCoalesce(el.tagName, () => ( ""))).toUpperCase();
|
|
7048
7615
|
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
|
7049
|
-
return !!el.isContentEditable || _optionalChain([el, 'access',
|
|
7616
|
+
return !!el.isContentEditable || _optionalChain([el, 'access', _240 => _240.getAttribute, 'optionalCall', _241 => _241("contenteditable")]) === "true";
|
|
7050
7617
|
}
|
|
7051
7618
|
function getVectorSelectionStyle(state) {
|
|
7052
7619
|
const paths = [];
|
|
@@ -7054,12 +7621,12 @@ function getVectorSelectionStyle(state) {
|
|
|
7054
7621
|
const node = findVectorNode(state.document.nodes, id);
|
|
7055
7622
|
if (node) paths.push(...collect(node));
|
|
7056
7623
|
}
|
|
7057
|
-
const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access',
|
|
7624
|
+
const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _242 => _242.selectedAnchors, 'optionalAccess', _243 => _243.length]);
|
|
7058
7625
|
if (anchorMode) {
|
|
7059
7626
|
for (const r of state.selectedAnchors) {
|
|
7060
7627
|
if (paths.some((p) => p.id === r.nodeId)) continue;
|
|
7061
7628
|
const node = findVectorNode(state.document.nodes, r.nodeId);
|
|
7062
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
7629
|
+
if (_optionalChain([node, 'optionalAccess', _244 => _244.type]) === "path") paths.push(node);
|
|
7063
7630
|
}
|
|
7064
7631
|
}
|
|
7065
7632
|
if (!paths.length) return null;
|
|
@@ -7070,7 +7637,7 @@ function getVectorSelectionStyle(state) {
|
|
|
7070
7637
|
for (const c of vectorCorners(p.subpaths)) {
|
|
7071
7638
|
if (anchorMode && !state.selectedAnchors.some((r) => r.nodeId === p.id && r.subpath === c.subpath && r.index === c.index)) continue;
|
|
7072
7639
|
const corner = p.subpaths[c.subpath].anchors[c.index].corner;
|
|
7073
|
-
corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess',
|
|
7640
|
+
corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _245 => _245.radius]), () => ( 0)), kind: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _246 => _246.kind]), () => ( "round")) });
|
|
7074
7641
|
}
|
|
7075
7642
|
}
|
|
7076
7643
|
const c0 = _nullishCoalesce(corners2[0], () => ( { radius: 0, kind: "round" }));
|
|
@@ -7138,6 +7705,14 @@ var VECTOR_PATH_ACTIONS = [
|
|
|
7138
7705
|
{ id: "smooth", label: "\u223F", title: "Smooth", enabled: (s, p) => s + p > 0, run: (c) => c.smoothPaths() },
|
|
7139
7706
|
{ id: "outline", label: "\u22A1", title: "Outline Stroke", enabled: (s) => s > 0, run: (c) => c.outlineStroke() }
|
|
7140
7707
|
];
|
|
7708
|
+
var VECTOR_PATHFINDER_ACTIONS = [
|
|
7709
|
+
{ id: "divide", label: "\u229E", title: "Divide", min: 1 },
|
|
7710
|
+
{ id: "trim", label: "\u29C9", title: "Trim", min: 2 },
|
|
7711
|
+
{ id: "merge", label: "\u29C8", title: "Merge", min: 2 },
|
|
7712
|
+
{ id: "crop", label: "\u2317", title: "Crop", min: 2 },
|
|
7713
|
+
{ id: "outline", label: "\u2B1A", title: "Outline", min: 1 },
|
|
7714
|
+
{ id: "minusBack", label: "\u2296", title: "Minus Back", min: 2 }
|
|
7715
|
+
];
|
|
7141
7716
|
var VECTOR_EDIT_TOGGLES = [
|
|
7142
7717
|
{ key: "keepShapeOnDelete", label: "Keep", title: "Keep shape when deleting points" },
|
|
7143
7718
|
{ key: "curvatureMoves", label: "Curv", title: "Curvature point moves (Alt flips while dragging)" },
|
|
@@ -7210,17 +7785,17 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7210
7785
|
const base = { group, ...options.scope ? { scope: options.scope } : {} };
|
|
7211
7786
|
const hasSelection = () => controller.getState().selection.length ? true : "Nothing is selected.";
|
|
7212
7787
|
const ids = (params) => {
|
|
7213
|
-
const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess',
|
|
7788
|
+
const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _247 => _247.ids]), () => ( controller.getState().selection));
|
|
7214
7789
|
for (const id of list2) if (!controller.getNode(id)) fail(`There is no node "${id}".`);
|
|
7215
7790
|
if (!list2.length) fail("Nothing is selected; pass ids.");
|
|
7216
7791
|
return list2;
|
|
7217
7792
|
};
|
|
7218
|
-
const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess',
|
|
7793
|
+
const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _248 => _248.ids, 'optionalAccess', _249 => _249.length]) ? true : hasSelection();
|
|
7219
7794
|
const anchorsOf = (refs) => {
|
|
7220
7795
|
if (!refs) return [...controller.getState().selectedAnchors];
|
|
7221
7796
|
for (const r of refs) {
|
|
7222
7797
|
const node = controller.getNode(r.nodeId);
|
|
7223
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
7798
|
+
if (_optionalChain([node, 'optionalAccess', _250 => _250.type]) !== "path" || !_optionalChain([node, 'access', _251 => _251.subpaths, 'access', _252 => _252[r.subpath], 'optionalAccess', _253 => _253.anchors, 'access', _254 => _254[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
|
|
7224
7799
|
}
|
|
7225
7800
|
return refs;
|
|
7226
7801
|
};
|
|
@@ -7311,7 +7886,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7311
7886
|
run: (_ctx, params) => {
|
|
7312
7887
|
const id = controller.addPath(params.d, { ...pickStyle(params), ...params.name ? { name: params.name } : {} });
|
|
7313
7888
|
const node = controller.getNode(id);
|
|
7314
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
7889
|
+
if (_optionalChain([node, 'optionalAccess', _255 => _255.type]) === "path" && !node.subpaths.length) {
|
|
7315
7890
|
controller.undo();
|
|
7316
7891
|
fail("The path data has no points.");
|
|
7317
7892
|
}
|
|
@@ -7343,10 +7918,10 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7343
7918
|
params: { type: "object", properties: { radius: { type: "number", minimum: 0 }, kind: { type: "string", enum: VECTOR_CORNER_KINDS }, ids: IDS, anchors: ANCHORS } },
|
|
7344
7919
|
undoable: true,
|
|
7345
7920
|
run: (_ctx, params) => {
|
|
7346
|
-
const refs = _optionalChain([params, 'optionalAccess',
|
|
7347
|
-
const target = { refs, ids: _optionalChain([params, 'optionalAccess',
|
|
7348
|
-
if (_optionalChain([params, 'optionalAccess',
|
|
7349
|
-
else if (_optionalChain([params, 'optionalAccess',
|
|
7921
|
+
const refs = _optionalChain([params, 'optionalAccess', _256 => _256.anchors]) ? anchorsOf(params.anchors) : void 0;
|
|
7922
|
+
const target = { refs, ids: _optionalChain([params, 'optionalAccess', _257 => _257.ids]) ? ids(params) : void 0 };
|
|
7923
|
+
if (_optionalChain([params, 'optionalAccess', _258 => _258.radius]) !== void 0) check(controller.setCornerRadius(params.radius, { ...target, kind: params.kind }));
|
|
7924
|
+
else if (_optionalChain([params, 'optionalAccess', _259 => _259.kind])) check(controller.setCornerKind(params.kind, target));
|
|
7350
7925
|
else fail("Pass `radius` and / or `kind`.");
|
|
7351
7926
|
return { ok: true };
|
|
7352
7927
|
}
|
|
@@ -7381,12 +7956,12 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7381
7956
|
undoable: true,
|
|
7382
7957
|
run: (_ctx, params) => {
|
|
7383
7958
|
const target = { ids: ids(params) };
|
|
7384
|
-
if (_optionalChain([params, 'optionalAccess',
|
|
7385
|
-
else if (_optionalChain([params, 'optionalAccess',
|
|
7386
|
-
else if (_optionalChain([params, 'optionalAccess',
|
|
7959
|
+
if (_optionalChain([params, 'optionalAccess', _260 => _260.preset])) check(controller.setWidthProfile(params.preset, target));
|
|
7960
|
+
else if (_optionalChain([params, 'optionalAccess', _261 => _261.points]) !== void 0) check(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
|
|
7961
|
+
else if (_optionalChain([params, 'optionalAccess', _262 => _262.taper]) || _optionalChain([params, 'optionalAccess', _263 => _263.wave])) check(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
|
|
7387
7962
|
else fail("Pass `preset`, `points`, `taper` or `wave`.");
|
|
7388
7963
|
const node = controller.getNode(target.ids[0]);
|
|
7389
|
-
return { ok: true, points: _optionalChain([node, 'optionalAccess',
|
|
7964
|
+
return { ok: true, points: _optionalChain([node, 'optionalAccess', _264 => _264.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
|
|
7390
7965
|
}
|
|
7391
7966
|
},
|
|
7392
7967
|
{
|
|
@@ -7399,7 +7974,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7399
7974
|
enabled: enabledFor,
|
|
7400
7975
|
undoable: true,
|
|
7401
7976
|
run: (_ctx, params) => {
|
|
7402
|
-
const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess',
|
|
7977
|
+
const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _265 => _265.ids]) ? ids(params) : void 0 });
|
|
7403
7978
|
if (!created.length) fail("No selected path has a stroke.");
|
|
7404
7979
|
return { ids: created };
|
|
7405
7980
|
}
|
|
@@ -7461,6 +8036,62 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7461
8036
|
return { id };
|
|
7462
8037
|
}
|
|
7463
8038
|
},
|
|
8039
|
+
{
|
|
8040
|
+
...base,
|
|
8041
|
+
id: `${prefix}pathfinder`,
|
|
8042
|
+
label: "Pathfinder\u2026",
|
|
8043
|
+
keywords: ["divide", "trim", "merge", "crop", "outline", "minus back", "split", "faces"],
|
|
8044
|
+
description: "Pathfinder over the given paths (bottom to top): divide (every face its own shape, painted like the top-most shape over it; open unfilled paths cut), trim (hidden parts removed), merge (trim, then touching parts of one fill joined), crop (the top shape crops the others), outline (outlines cut into open strokes where they meet) or minusBack (the top shape minus everything below). Results replace the paths, grouped when there are several.",
|
|
8045
|
+
params: { type: "object", properties: { operation: { type: "string", enum: [...VECTOR_PATHFINDER_OPERATIONS] }, ids: IDS }, required: ["operation"] },
|
|
8046
|
+
undoable: true,
|
|
8047
|
+
run: (_ctx, params) => {
|
|
8048
|
+
if (!VECTOR_PATHFINDER_OPERATIONS.includes(params.operation)) fail(`Unknown Pathfinder operation "${params.operation}".`);
|
|
8049
|
+
const created = controller.pathfinder(params.operation, { ids: ids(params) });
|
|
8050
|
+
if (!created.length) fail("Nothing came out: select paths that overlap (two or more, except for divide and outline).");
|
|
8051
|
+
return { ids: created, selection: [...controller.getState().selection] };
|
|
8052
|
+
}
|
|
8053
|
+
},
|
|
8054
|
+
{
|
|
8055
|
+
...base,
|
|
8056
|
+
id: `${prefix}shapeBuilderFaces`,
|
|
8057
|
+
label: "List Shape Builder Faces",
|
|
8058
|
+
keywords: ["shape builder", "regions", "faces", "planar"],
|
|
8059
|
+
description: "Lists the faces the given paths divide the plane into: path data, area, a point inside and the ids of the paths filling each (empty when only outlines enclose it).",
|
|
8060
|
+
params: { type: "object", properties: { ids: IDS } },
|
|
8061
|
+
run: (_ctx, params) => ({ faces: controller.getShapeBuilderFaces({ ids: ids(params) }) })
|
|
8062
|
+
},
|
|
8063
|
+
{
|
|
8064
|
+
...base,
|
|
8065
|
+
id: `${prefix}shapeBuilder`,
|
|
8066
|
+
label: "Shape Builder",
|
|
8067
|
+
keywords: ["merge faces", "build shape", "combine regions", "delete region"],
|
|
8068
|
+
description: "Shape Builder gesture over the faces of the given paths: `points` is the pointer path in document units (one point is a click; [[x, y], \u2026]; use the points from shapeBuilderFaces). Merges the faces it touches into one shape, or with `erase: true` deletes them, the pieces of unfilled open paths and the edges of other outlines (cut where paths meet) within `tolerance`; a deleted edge opens its path there, and edges bounding a deleted face go with it. Shapes covering those faces lose that area. Returns the counts of faces, line pieces and edges.",
|
|
8069
|
+
params: {
|
|
8070
|
+
type: "object",
|
|
8071
|
+
properties: { points: POINTS, erase: { type: "boolean" }, tolerance: { type: "number", minimum: 0 }, ids: IDS },
|
|
8072
|
+
required: ["points"]
|
|
8073
|
+
},
|
|
8074
|
+
undoable: true,
|
|
8075
|
+
run: (_ctx, params) => {
|
|
8076
|
+
const result = controller.shapeBuilder(params.points.map(([x, y]) => ({ x, y })), { ids: ids(params), erase: params.erase, tolerance: params.tolerance });
|
|
8077
|
+
check(result);
|
|
8078
|
+
return { merged: result.merged, faces: result.faces, lines: result.lines, edges: result.edges };
|
|
8079
|
+
}
|
|
8080
|
+
},
|
|
8081
|
+
{
|
|
8082
|
+
...base,
|
|
8083
|
+
id: `${prefix}fillRegion`,
|
|
8084
|
+
label: "Fill Region",
|
|
8085
|
+
keywords: ["paint bucket", "live paint", "fill area", "enclosed"],
|
|
8086
|
+
description: "Paint bucket: fills the area the visible outlines enclose around `point` (crossings split, nested shapes left as holes) with a new path in the current fill, below the selection or on top. `gap` closes gaps up to that size between loose ends.",
|
|
8087
|
+
params: { type: "object", properties: { point: { type: "array", items: { type: "number" }, minItems: 2, maxItems: 2, description: "[x, y] in document units." }, gap: { type: "number", minimum: 0 } }, required: ["point"] },
|
|
8088
|
+
undoable: true,
|
|
8089
|
+
run: (_ctx, params) => {
|
|
8090
|
+
const id = controller.fillRegion({ x: params.point[0], y: params.point[1] }, { gap: params.gap });
|
|
8091
|
+
if (!id) fail("No closed region surrounds that point.");
|
|
8092
|
+
return { id };
|
|
8093
|
+
}
|
|
8094
|
+
},
|
|
7464
8095
|
{
|
|
7465
8096
|
...base,
|
|
7466
8097
|
id: `${prefix}align`,
|
|
@@ -7514,7 +8145,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7514
8145
|
enabled: enabledFor,
|
|
7515
8146
|
undoable: true,
|
|
7516
8147
|
run: (_ctx, params) => {
|
|
7517
|
-
const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess',
|
|
8148
|
+
const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _266 => _266.name]) });
|
|
7518
8149
|
if (!id) fail("Only nodes that share a parent can be grouped.");
|
|
7519
8150
|
return { id };
|
|
7520
8151
|
}
|
|
@@ -7542,7 +8173,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7542
8173
|
params: { type: "object", properties: { anchors: ANCHORS, keepShape: { type: "boolean" } } },
|
|
7543
8174
|
undoable: true,
|
|
7544
8175
|
run: (_ctx, params) => {
|
|
7545
|
-
check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess',
|
|
8176
|
+
check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _267 => _267.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _268 => _268.keepShape]) }));
|
|
7546
8177
|
return { ok: true };
|
|
7547
8178
|
}
|
|
7548
8179
|
},
|
|
@@ -7597,7 +8228,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7597
8228
|
params: { type: "object", properties: { ids: IDS, tolerance: { type: "number", minimum: 0 } } },
|
|
7598
8229
|
undoable: true,
|
|
7599
8230
|
run: (_ctx, params) => {
|
|
7600
|
-
check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess',
|
|
8231
|
+
check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _269 => _269.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _270 => _270.tolerance]) }));
|
|
7601
8232
|
return { selection: controller.getState().selection };
|
|
7602
8233
|
}
|
|
7603
8234
|
},
|
|
@@ -7611,7 +8242,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7611
8242
|
params: { type: "object", properties: { axis: { type: "string", enum: ["horizontal", "vertical", "both"] }, anchors: ANCHORS } },
|
|
7612
8243
|
undoable: true,
|
|
7613
8244
|
run: (_ctx, params) => {
|
|
7614
|
-
check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess',
|
|
8245
|
+
check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _271 => _271.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _272 => _272.anchors]))));
|
|
7615
8246
|
return { ok: true };
|
|
7616
8247
|
}
|
|
7617
8248
|
},
|
|
@@ -7625,7 +8256,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7625
8256
|
enabled: enabledFor,
|
|
7626
8257
|
undoable: true,
|
|
7627
8258
|
run: (_ctx, params) => {
|
|
7628
|
-
check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess',
|
|
8259
|
+
check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _273 => _273.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _274 => _274.tolerance]) }));
|
|
7629
8260
|
return { ok: true };
|
|
7630
8261
|
}
|
|
7631
8262
|
},
|
|
@@ -7638,7 +8269,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7638
8269
|
params: { type: "object", properties: { ids: IDS, amount: { type: "number", minimum: 0, maximum: 1 }, anchors: ANCHORS } },
|
|
7639
8270
|
undoable: true,
|
|
7640
8271
|
run: (_ctx, params) => {
|
|
7641
|
-
check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess',
|
|
8272
|
+
check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _275 => _275.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _276 => _276.amount]), refs: _optionalChain([params, 'optionalAccess', _277 => _277.anchors]) }));
|
|
7642
8273
|
return { ok: true };
|
|
7643
8274
|
}
|
|
7644
8275
|
},
|
|
@@ -7651,14 +8282,14 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7651
8282
|
params: { type: "object", properties: { nodeId: { type: "string" }, x: { type: "number" }, y: { type: "number" }, anchors: ANCHORS } },
|
|
7652
8283
|
undoable: true,
|
|
7653
8284
|
run: (_ctx, params) => {
|
|
7654
|
-
if (_optionalChain([params, 'optionalAccess',
|
|
8285
|
+
if (_optionalChain([params, 'optionalAccess', _278 => _278.nodeId]) !== void 0) {
|
|
7655
8286
|
if (!controller.getNode(params.nodeId)) fail(`There is no node "${params.nodeId}".`);
|
|
7656
8287
|
if (params.x === void 0 || params.y === void 0) fail("Pass x and y with nodeId.");
|
|
7657
8288
|
const created = controller.cutPathAt(params.nodeId, { x: params.x, y: params.y });
|
|
7658
8289
|
if (!created) fail("Nothing to cut there (the end of an open path, or a locked path).");
|
|
7659
8290
|
return { ids: created };
|
|
7660
8291
|
}
|
|
7661
|
-
check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess',
|
|
8292
|
+
check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _279 => _279.anchors]))));
|
|
7662
8293
|
return { ids: controller.getState().selection };
|
|
7663
8294
|
}
|
|
7664
8295
|
},
|
|
@@ -7709,7 +8340,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7709
8340
|
},
|
|
7710
8341
|
run: (_ctx, params) => {
|
|
7711
8342
|
const patch = {};
|
|
7712
|
-
for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess',
|
|
8343
|
+
for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess', _280 => _280[key]]) !== void 0) patch[key] = params[key];
|
|
7713
8344
|
controller.setEditing(patch);
|
|
7714
8345
|
return { editing: controller.getState().editing };
|
|
7715
8346
|
}
|
|
@@ -7734,7 +8365,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7734
8365
|
keywords: ["download", "save", "markup"],
|
|
7735
8366
|
description: "Returns the document as SVG markup.",
|
|
7736
8367
|
params: { type: "object", properties: { precision: { type: "integer", minimum: 0, maximum: 8 } } },
|
|
7737
|
-
run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess',
|
|
8368
|
+
run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _281 => _281.precision]) }) })
|
|
7738
8369
|
},
|
|
7739
8370
|
{
|
|
7740
8371
|
...base,
|
|
@@ -7932,5 +8563,21 @@ function createVectorCommands(controller, options = {}) {
|
|
|
7932
8563
|
|
|
7933
8564
|
|
|
7934
8565
|
|
|
7935
|
-
|
|
8566
|
+
|
|
8567
|
+
|
|
8568
|
+
|
|
8569
|
+
|
|
8570
|
+
|
|
8571
|
+
|
|
8572
|
+
|
|
8573
|
+
|
|
8574
|
+
|
|
8575
|
+
|
|
8576
|
+
|
|
8577
|
+
|
|
8578
|
+
|
|
8579
|
+
|
|
8580
|
+
|
|
8581
|
+
|
|
8582
|
+
exports.DEFAULT_VECTOR_PATH_EDIT = DEFAULT_VECTOR_PATH_EDIT; exports.DEFAULT_VECTOR_SNAP = DEFAULT_VECTOR_SNAP; exports.IDENTITY_MATRIX = IDENTITY_MATRIX; exports.KAPPA = KAPPA2; exports.LazyMouse = LazyMouse; exports.VECTOR_ARROWHEADS = VECTOR_ARROWHEADS; exports.VECTOR_ARROWHEAD_LABELS = VECTOR_ARROWHEAD_LABELS; exports.VECTOR_BUILDER_HATCH_GAP = VECTOR_BUILDER_HATCH_GAP; exports.VECTOR_CLIPBOARD_TYPE = VECTOR_CLIPBOARD_TYPE; exports.VECTOR_CONSTRUCTION_ANGLES = VECTOR_CONSTRUCTION_ANGLES; exports.VECTOR_CORNER_KINDS = VECTOR_CORNER_KINDS; exports.VECTOR_CORNER_KIND_LABELS = VECTOR_CORNER_KIND_LABELS; exports.VECTOR_CORNER_WIDGET_INSET = VECTOR_CORNER_WIDGET_INSET; exports.VECTOR_EDIT_TOGGLES = VECTOR_EDIT_TOGGLES; exports.VECTOR_FILL_GAP = VECTOR_FILL_GAP; exports.VECTOR_INK_MAX_CORNERS = VECTOR_INK_MAX_CORNERS; exports.VECTOR_OVERLAY_THEME = VECTOR_OVERLAY_THEME; exports.VECTOR_PATHFINDER_ACTIONS = VECTOR_PATHFINDER_ACTIONS; exports.VECTOR_PATHFINDER_LABELS = VECTOR_PATHFINDER_LABELS; exports.VECTOR_PATHFINDER_OPERATIONS = VECTOR_PATHFINDER_OPERATIONS; exports.VECTOR_PATH_ACTIONS = VECTOR_PATH_ACTIONS; exports.VECTOR_PENCIL_STRING_PX = VECTOR_PENCIL_STRING_PX; exports.VECTOR_PRESSURE_NOMINAL = VECTOR_PRESSURE_NOMINAL; exports.VECTOR_ROTATE_HANDLE_OFFSET = VECTOR_ROTATE_HANDLE_OFFSET; exports.VECTOR_STROKE_ALIGN_LABELS = VECTOR_STROKE_ALIGN_LABELS; exports.VECTOR_STYLE_KEYS = VECTOR_STYLE_KEYS; exports.VECTOR_TOOLS = VECTOR_TOOLS; exports.VECTOR_TOOL_GLYPHS = VECTOR_TOOL_GLYPHS; exports.VECTOR_TOOL_SHORTCUTS = VECTOR_TOOL_SHORTCUTS; exports.VECTOR_TRANSFORM_HANDLES = VECTOR_TRANSFORM_HANDLES; exports.VECTOR_WIDTH_PRESETS = VECTOR_WIDTH_PRESETS; exports.VECTOR_WIDTH_PRESET_IDS = VECTOR_WIDTH_PRESET_IDS; exports.VECTOR_WIDTH_PROFILE_MAX_POINTS = VECTOR_WIDTH_PROFILE_MAX_POINTS; exports.VECTOR_WIDTH_PROFILE_MAX_SCALE = VECTOR_WIDTH_PROFILE_MAX_SCALE; exports.VECTOR_WIDTH_SAME_T = VECTOR_WIDTH_SAME_T; exports.VectorEditorController = VectorEditorController; exports.VectorSnapTargets = VectorSnapTargets; exports.addBuilderHit = addBuilderHit; exports.applyMatrix = applyMatrix; exports.applyMatrixLinear = applyMatrixLinear; exports.applyVectorCornersAttribute = applyVectorCornersAttribute; exports.arrowheadInset = arrowheadInset; exports.arrowheadPath = arrowheadPath; exports.arrowheadWeight = arrowheadWeight; exports.bendSegment = bendSegment; exports.bezierToSubpaths = bezierToSubpaths; exports.boundsFromPoints = boundsFromPoints; exports.boundsIntersect = boundsIntersect; exports.cloneAnchor = cloneAnchor; exports.cloneSubpath = cloneSubpath; exports.cloneVectorDocument = cloneVectorDocument; exports.cloneVectorNode = cloneVectorNode; exports.collectPathNodes = collectPathNodes; exports.constrainToLeave = constrainToLeave; exports.convertAnchor = convertAnchor; exports.cornerBisectorPoint = cornerBisectorPoint; exports.cornerRadiusChange = cornerRadiusChange; exports.cornerSetback = cornerSetback; exports.createVectorCommands = createVectorCommands; exports.curvatureMoveAnchor = curvatureMoveAnchor; exports.cutSubpathAt = cutSubpathAt; exports.dashIntervals = dashIntervals; exports.decomposeRigid = decomposeRigid; exports.effectiveStrokeAlign = effectiveStrokeAlign; exports.ellipseSubpath = ellipseSubpath; exports.eraseFromFill = eraseFromFill; exports.eraseFromOutline = eraseFromOutline; exports.eraserRegion = eraserRegion; exports.expandVectorCorners = expandVectorCorners; exports.expandVectorCornersOf = expandVectorCornersOf; exports.findVectorNode = findVectorNode; exports.fitCornerRadius = fitCornerRadius; exports.generateWidthProfile = generateWidthProfile; exports.getAnchor = getAnchor; exports.getAnchorWorld = getAnchorWorld; exports.getEditablePathIds = getEditablePathIds; exports.getTransformHandlePositions = getTransformHandlePositions; exports.getVectorCornerWidgets = getVectorCornerWidgets; exports.getVectorOverlayRenderData = getVectorOverlayRenderData; exports.getVectorSceneRenderData = getVectorSceneRenderData; exports.getVectorSelectionBoxGeometry = getVectorSelectionBoxGeometry; exports.getVectorSelectionFrame = getVectorSelectionFrame; exports.getVectorSelectionStyle = getVectorSelectionStyle; exports.getVectorWidthHandles = getVectorWidthHandles; exports.getVisibleAnchors = getVisibleAnchors; exports.getVisibleHandles = getVisibleHandles; exports.hasPaint = hasPaint; exports.hasStrokeExtras = hasStrokeExtras; exports.hasVectorCorners = hasVectorCorners; exports.hitTestVectorNode = hitTestVectorNode; exports.hitTestVectorNodes = hitTestVectorNodes; exports.hitTestVectorStroke = hitTestVectorStroke; exports.inferAnchorType = inferAnchorType; exports.insertAnchor = insertAnchor; exports.insertWidthPoint = insertWidthPoint; exports.invertMatrix = invertMatrix; exports.isClosedBezierShape = isClosedBezierShape; exports.isIdentityMatrix = isIdentityMatrix; exports.isUniformWidthProfile = isUniformWidthProfile; exports.isVectorTextTarget = isVectorTextTarget; exports.joinSubpaths = joinSubpaths; exports.knifePath = knifePath; exports.lineSubpath = lineSubpath; exports.locateVectorNode = locateVectorNode; exports.matrixRotation = matrixRotation; exports.mirrorWidthProfile = mirrorWidthProfile; exports.moveAnchorHandle = moveAnchorHandle; exports.multiplyMatrices = multiplyMatrices; exports.nearestSegment = nearestSegment; exports.nearestStrokePosition = nearestStrokePosition; exports.nextVectorCornerKind = nextVectorCornerKind; exports.nodeMatrix = nodeMatrix; exports.parseSvgTransform = parseSvgTransform; exports.parseVectorSvg = parseVectorSvg; exports.planShapeBuilder = planShapeBuilder; exports.polygonSubpath = polygonSubpath; exports.polylineBounds = polylineBounds; exports.pressureWidthProfile = pressureWidthProfile; exports.recognizeInkShape = recognizeInkShape; exports.rectSubpath = rectSubpath; exports.removeAnchorKeepingShape = removeAnchorKeepingShape; exports.removeAnchors = removeAnchors; exports.removeAnchorsKeepingShape = removeAnchorsKeepingShape; exports.removeRedundantPoints = removeRedundantPoints; exports.removeWidthPoints = removeWidthPoints; exports.reverseSubpath = reverseSubpath; exports.reverseWidthProfile = reverseWidthProfile; exports.rotateMatrix = rotateMatrix; exports.roundSubpaths = roundSubpaths; exports.samplePolyline = samplePolyline; exports.sanitizeWidthProfile = sanitizeWidthProfile; exports.scaleFor = scaleFor; exports.scaleMatrix = scaleMatrix; exports.setAnchorCorner = setAnchorCorner; exports.setSubpathCorners = setSubpathCorners; exports.setWidthPoint = setWidthPoint; exports.simplifyPolyline = simplifyPolyline; exports.smoothSubpath = smoothSubpath; exports.splitIntoFaces = splitIntoFaces; exports.splitSubpathAt = splitSubpathAt; exports.starSubpath = starSubpath; exports.strokePositionPoint = strokePositionPoint; exports.strokeWidthProfileOf = strokeWidthProfileOf; exports.subpathEnclosesArea = subpathEnclosesArea; exports.subpathPointAt = subpathPointAt; exports.subpathSegment = subpathSegment; exports.subpathSegmentCount = subpathSegmentCount; exports.subpathsToBezier = subpathsToBezier; exports.taperWaveFactor = taperWaveFactor; exports.toVectorKeyInput = toVectorKeyInput; exports.toVectorModifiers = toVectorModifiers; exports.toVectorPointerInput = toVectorPointerInput; exports.transformVectorNode = transformVectorNode; exports.translateAnchor = translateAnchor; exports.translateMatrix = translateMatrix; exports.unionBounds = unionBounds; exports.variableStrokeOutline = variableStrokeOutline; exports.variableStrokeRings = variableStrokeRings; exports.vectorBuilderErasedEdges = vectorBuilderErasedEdges; exports.vectorCornerAt = vectorCornerAt; exports.vectorCorners = vectorCorners; exports.vectorCornersAttribute = vectorCornersAttribute; exports.vectorDiamondPath = vectorDiamondPath; exports.vectorDocumentToSvg = vectorDocumentToSvg; exports.vectorFillMap = vectorFillMap; exports.vectorInkShapeName = vectorInkShapeName; exports.vectorNodeBounds = vectorNodeBounds; exports.vectorNodeRotation = vectorNodeRotation; exports.vectorNodeToBezier = vectorNodeToBezier; exports.vectorPaintToHex = vectorPaintToHex; exports.vectorPaintToSvg = vectorPaintToSvg; exports.vectorParentMatrix = vectorParentMatrix; exports.vectorPathData = vectorPathData; exports.vectorPathEntries = vectorPathEntries; exports.vectorPathWorldBezier = vectorPathWorldBezier; exports.vectorPathfinderShape = vectorPathfinderShape; exports.vectorResizeCursor = vectorResizeCursor; exports.vectorResultStyle = vectorResultStyle; exports.vectorShapeBuilderHit = vectorShapeBuilderHit; exports.vectorShapeBuilderMap = vectorShapeBuilderMap; exports.vectorStrokeLineArea = vectorStrokeLineArea; exports.vectorStrokeOutline = vectorStrokeOutline; exports.vectorStrokeOutlinePath = vectorStrokeOutlinePath; exports.vectorStrokeParts = vectorStrokeParts; exports.vectorStrokeReach = vectorStrokeReach; exports.vectorStrokeSvgParts = vectorStrokeSvgParts; exports.vectorStrokeWidthGeometry = vectorStrokeWidthGeometry; exports.vectorToolLabel = vectorToolLabel; exports.vectorWorldMatrix = vectorWorldMatrix; exports.walkVectorNodes = walkVectorNodes; exports.widthProfileAt = widthProfileAt; exports.widthProfileFromAttribute = widthProfileFromAttribute; exports.widthProfileMaxScale = widthProfileMaxScale; exports.widthProfilePreset = widthProfilePreset; exports.widthProfilePresetId = widthProfilePresetId; exports.widthProfileToAttribute = widthProfileToAttribute;
|
|
7936
8583
|
//# sourceMappingURL=index.cjs.map
|