@pixerate/editor 0.36.0 → 0.37.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 +10 -0
- package/dist/canvas/index.cjs +25 -25
- package/dist/canvas/index.d.cts +3 -217
- package/dist/canvas/index.d.ts +3 -217
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-BGNPT5PE.cjs → chunk-GVB7ZPLZ.cjs} +24 -3
- package/dist/chunk-GVB7ZPLZ.cjs.map +1 -0
- package/dist/{chunk-EGPIVUEF.js → chunk-HPEKB352.js} +23 -2
- package/dist/chunk-HPEKB352.js.map +1 -0
- package/dist/{bezier-D8bsO-L0.d.cts → stroke-CWjFKal4.d.cts} +215 -1
- package/dist/{bezier-BvqVmWMg.d.ts → stroke-ysgaPpAo.d.ts} +215 -1
- package/dist/vector/index.cjs +1301 -284
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +381 -8
- package/dist/vector/index.d.ts +381 -8
- package/dist/vector/index.js +1100 -83
- package/dist/vector/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-BGNPT5PE.cjs.map +0 -1
- package/dist/chunk-EGPIVUEF.js.map +0 -1
package/dist/vector/index.cjs
CHANGED
|
@@ -31,12 +31,15 @@ var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
var _chunkGVB7ZPLZcjs = require('../chunk-GVB7ZPLZ.cjs');
|
|
35
38
|
|
|
36
39
|
// src/vector/types.ts
|
|
37
40
|
var VECTOR_CORNER_KINDS = ["round", "inverted", "chamfer"];
|
|
38
41
|
var VECTOR_ARROWHEADS = ["triangle", "arrow", "open", "circle", "square", "bar"];
|
|
39
|
-
var VECTOR_TOOLS = ["select", "direct", "pen", "pencil", "rect", "ellipse", "polygon", "star", "line", "scissors", "knife", "eraser"];
|
|
42
|
+
var VECTOR_TOOLS = ["select", "direct", "pen", "pencil", "rect", "ellipse", "polygon", "star", "line", "scissors", "knife", "eraser", "width"];
|
|
40
43
|
var VECTOR_TRANSFORM_HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w", "rotate"];
|
|
41
44
|
|
|
42
45
|
// src/vector/corners.ts
|
|
@@ -58,7 +61,7 @@ var Side = class {
|
|
|
58
61
|
constructor(a, h1, h2, b) {
|
|
59
62
|
this.straight = onAnchor(a, h1) && onAnchor(b, h2);
|
|
60
63
|
this.curve = this.straight ? [pt(a), pt(b)] : [pt(a), pt(_nullishCoalesce(h1, () => ( a))), pt(_nullishCoalesce(h2, () => ( b))), pt(b)];
|
|
61
|
-
this.length = this.straight ? Math.hypot(b.x - a.x, b.y - a.y) :
|
|
64
|
+
this.length = this.straight ? Math.hypot(b.x - a.x, b.y - a.y) : _chunkGVB7ZPLZcjs.segmentLength.call(void 0, this.curve);
|
|
62
65
|
}
|
|
63
66
|
/** Unit direction the side leaves the corner in (towards its first control point off the corner). */
|
|
64
67
|
direction() {
|
|
@@ -76,10 +79,10 @@ var Side = class {
|
|
|
76
79
|
const t2 = this.length > EPS ? Math.min(1, Math.max(0, s / this.length)) : 0;
|
|
77
80
|
return { t: t2, p: add(vec(this.curve[0]), mul(u, s)), dir: u };
|
|
78
81
|
}
|
|
79
|
-
const t =
|
|
80
|
-
const d = vec(
|
|
82
|
+
const t = _chunkGVB7ZPLZcjs.segmentParamAtLength.call(void 0, this.curve, s, this.length);
|
|
83
|
+
const d = vec(_chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, this.curve, t));
|
|
81
84
|
const l = len(d);
|
|
82
|
-
return { t, p: vec(
|
|
85
|
+
return { t, p: vec(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, this.curve, t)), dir: l > EPS ? mul(d, 1 / l) : u };
|
|
83
86
|
}
|
|
84
87
|
};
|
|
85
88
|
function cornerOf(sp, s, i) {
|
|
@@ -180,7 +183,7 @@ function expandVectorCornersOf(sp, subpath = 0) {
|
|
|
180
183
|
const s0 = from ? from.tv : 0;
|
|
181
184
|
const s1 = to ? 1 - to.tu : 1;
|
|
182
185
|
const seg = [pt(a), pt(_nullishCoalesce(a.out, () => ( a))), pt(_nullishCoalesce(b.in, () => ( b))), pt(b)];
|
|
183
|
-
const part =
|
|
186
|
+
const part = _chunkGVB7ZPLZcjs.subSegment.call(void 0, seg, s0, Math.max(s0, s1));
|
|
184
187
|
return { out: vec(part[1]), in: vec(part[2]) };
|
|
185
188
|
});
|
|
186
189
|
const anchors = [];
|
|
@@ -245,19 +248,561 @@ function setSubpathCorners(sp, radius, kind) {
|
|
|
245
248
|
return { closed: sp.closed, anchors: sp.anchors.map((a) => setAnchorCorner(a, radius, kind)) };
|
|
246
249
|
}
|
|
247
250
|
|
|
251
|
+
// src/vector/width.ts
|
|
252
|
+
var VECTOR_WIDTH_PROFILE_MAX_POINTS = 64;
|
|
253
|
+
var VECTOR_WIDTH_PROFILE_MAX_SCALE = 1e3;
|
|
254
|
+
var VECTOR_WIDTH_SAME_T = 1e-6;
|
|
255
|
+
var sym = (t, s) => ({ t, left: s, right: s });
|
|
256
|
+
var VECTOR_WIDTH_PRESETS = [
|
|
257
|
+
{ id: "uniform", label: "Uniform", points: [] },
|
|
258
|
+
{ id: "taperStart", label: "Taper start", points: [sym(0, 0), sym(1, 1)] },
|
|
259
|
+
{ id: "taperEnd", label: "Taper end", points: [sym(0, 1), sym(1, 0)] },
|
|
260
|
+
{ id: "taperBoth", label: "Taper both", points: [sym(0, 0), sym(0.5, 1), sym(1, 0)] },
|
|
261
|
+
// Full width at the ends, swelling to twice the width in the middle.
|
|
262
|
+
{ id: "bulge", label: "Bulge", points: [sym(0, 1), sym(0.5, 2), sym(1, 1)] },
|
|
263
|
+
// Full width at the ends, pinched to a quarter in the middle.
|
|
264
|
+
{ id: "pinch", label: "Pinch", points: [sym(0, 1), sym(0.5, 0.25), sym(1, 1)] },
|
|
265
|
+
// A round head a fifth of the way along, then a long taper to the end.
|
|
266
|
+
{ id: "teardrop", label: "Teardrop", points: [sym(0, 0), sym(0.2, 1), sym(1, 0)] },
|
|
267
|
+
// Two swells between narrow necks.
|
|
268
|
+
{ id: "wave", label: "Wave", points: [sym(0, 0.3), sym(0.25, 1), sym(0.5, 0.3), sym(0.75, 1), sym(1, 0.3)] },
|
|
269
|
+
// A pen stroke: a quick press, a slow lift.
|
|
270
|
+
{ id: "pressure", label: "Pressure", points: [sym(0, 0.15), sym(0.12, 0.85), sym(0.45, 1), sym(0.8, 0.7), sym(1, 0.05)] }
|
|
271
|
+
];
|
|
272
|
+
var VECTOR_WIDTH_PRESET_IDS = VECTOR_WIDTH_PRESETS.map((p) => p.id);
|
|
273
|
+
var clean = (v2, max) => typeof v2 === "number" && Number.isFinite(v2) ? Math.min(Math.max(v2, 0), max) : null;
|
|
274
|
+
function sanitizeWidthProfile(points) {
|
|
275
|
+
if (!Array.isArray(points)) return [];
|
|
276
|
+
const out = [];
|
|
277
|
+
for (const p of points) {
|
|
278
|
+
if (!p || typeof p !== "object") continue;
|
|
279
|
+
const t = clean(p.t, 1);
|
|
280
|
+
const l = clean(p.left, VECTOR_WIDTH_PROFILE_MAX_SCALE);
|
|
281
|
+
const r = clean(p.right, VECTOR_WIDTH_PROFILE_MAX_SCALE);
|
|
282
|
+
if (t === null || l === null && r === null) continue;
|
|
283
|
+
out.push({ t, left: _nullishCoalesce(l, () => ( r)), right: _nullishCoalesce(r, () => ( l)) });
|
|
284
|
+
if (out.length >= VECTOR_WIDTH_PROFILE_MAX_POINTS) break;
|
|
285
|
+
}
|
|
286
|
+
return out.map((p, i) => [p, i]).sort((a, b) => a[0].t - b[0].t || a[1] - b[1]).map(([p]) => p);
|
|
287
|
+
}
|
|
288
|
+
function isUniformWidthProfile(points) {
|
|
289
|
+
return !_optionalChain([points, 'optionalAccess', _7 => _7.length]) || points.every((p) => p.left === 1 && p.right === 1);
|
|
290
|
+
}
|
|
291
|
+
function secant(pts, i, k) {
|
|
292
|
+
const a = pts[i];
|
|
293
|
+
const b = pts[i + 1];
|
|
294
|
+
return a && b && b.t - a.t > 1e-12 ? (b[k] - a[k]) / (b.t - a.t) : 0;
|
|
295
|
+
}
|
|
296
|
+
function tangent(pts, i, k) {
|
|
297
|
+
const last = pts.length - 1;
|
|
298
|
+
if (i <= 0) return secant(pts, 0, k);
|
|
299
|
+
if (i >= last) return secant(pts, last - 1, k);
|
|
300
|
+
const d0 = secant(pts, i - 1, k);
|
|
301
|
+
const d1 = secant(pts, i, k);
|
|
302
|
+
return d0 * d1 <= 0 ? 0 : 2 * d0 * d1 / (d0 + d1);
|
|
303
|
+
}
|
|
304
|
+
function interp(pts, t, k) {
|
|
305
|
+
const first = pts[0];
|
|
306
|
+
const last = pts[pts.length - 1];
|
|
307
|
+
if (!(t > first.t)) return first[k];
|
|
308
|
+
if (t >= last.t) return last[k];
|
|
309
|
+
let i = 0;
|
|
310
|
+
while (i + 1 < pts.length && pts[i + 1].t <= t) i++;
|
|
311
|
+
const a = pts[i];
|
|
312
|
+
const b = pts[i + 1];
|
|
313
|
+
const h = b.t - a.t;
|
|
314
|
+
if (h <= 1e-12) return b[k];
|
|
315
|
+
const u = (t - a.t) / h;
|
|
316
|
+
const u2 = u * u;
|
|
317
|
+
const u3 = u2 * u;
|
|
318
|
+
const w = (2 * u3 - 3 * u2 + 1) * a[k] + (u3 - 2 * u2 + u) * h * tangent(pts, i, k) + (3 * u2 - 2 * u3) * b[k] + (u3 - u2) * h * tangent(pts, i + 1, k);
|
|
319
|
+
return Math.max(0, w);
|
|
320
|
+
}
|
|
321
|
+
function widthProfileAt(points, t) {
|
|
322
|
+
if (!_optionalChain([points, 'optionalAccess', _8 => _8.length])) return { left: 1, right: 1 };
|
|
323
|
+
return { left: interp(points, t, "left"), right: interp(points, t, "right") };
|
|
324
|
+
}
|
|
325
|
+
function widthProfileMaxScale(points) {
|
|
326
|
+
if (!_optionalChain([points, 'optionalAccess', _9 => _9.length])) return 1;
|
|
327
|
+
return points.reduce((m, p) => Math.max(m, p.left, p.right), 0);
|
|
328
|
+
}
|
|
329
|
+
function widthProfilePreset(id) {
|
|
330
|
+
const p = VECTOR_WIDTH_PRESETS.find((q) => q.id === id);
|
|
331
|
+
return p ? p.points.map((q) => ({ ...q })) : null;
|
|
332
|
+
}
|
|
333
|
+
function widthProfilePresetId(points) {
|
|
334
|
+
if (isUniformWidthProfile(points)) return "uniform";
|
|
335
|
+
const same = (a, b) => a.length === b.length && a.every((p, i) => Math.abs(p.t - b[i].t) < 1e-9 && Math.abs(p.left - b[i].left) < 1e-9 && Math.abs(p.right - b[i].right) < 1e-9);
|
|
336
|
+
return _nullishCoalesce(_optionalChain([VECTOR_WIDTH_PRESETS, 'access', _10 => _10.find, 'call', _11 => _11((p) => p.points.length && same(points, p.points)), 'optionalAccess', _12 => _12.id]), () => ( "custom"));
|
|
337
|
+
}
|
|
338
|
+
function reverseWidthProfile(points) {
|
|
339
|
+
return points.map((p) => ({ t: 1 - p.t, left: p.right, right: p.left })).reverse();
|
|
340
|
+
}
|
|
341
|
+
function mirrorWidthProfile(points) {
|
|
342
|
+
return points.map((p) => ({ t: p.t, left: p.right, right: p.left }));
|
|
343
|
+
}
|
|
344
|
+
function editable(points) {
|
|
345
|
+
return _optionalChain([points, 'optionalAccess', _13 => _13.length]) ? points.map((p) => ({ ...p })) : [sym(0, 1), sym(1, 1)];
|
|
346
|
+
}
|
|
347
|
+
function insertWidthPoint(points, t, sides = {}, options = {}) {
|
|
348
|
+
const pts = editable(points);
|
|
349
|
+
const tt = Math.min(Math.max(Number.isFinite(t) ? t : 0, 0), 1);
|
|
350
|
+
const here = widthProfileAt(_optionalChain([points, 'optionalAccess', _14 => _14.length]) ? points : null, tt);
|
|
351
|
+
const p = {
|
|
352
|
+
t: tt,
|
|
353
|
+
left: _nullishCoalesce(clean(sides.left, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.left)),
|
|
354
|
+
right: _nullishCoalesce(clean(sides.right, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.right))
|
|
355
|
+
};
|
|
356
|
+
const same = pts.findIndex((q) => Math.abs(q.t - tt) <= VECTOR_WIDTH_SAME_T);
|
|
357
|
+
if (same >= 0 && !options.step) {
|
|
358
|
+
pts[same] = { ...p, t: pts[same].t };
|
|
359
|
+
return { points: pts, index: same };
|
|
360
|
+
}
|
|
361
|
+
let i = 0;
|
|
362
|
+
while (i < pts.length && pts[i].t <= tt) i++;
|
|
363
|
+
if (pts.length >= VECTOR_WIDTH_PROFILE_MAX_POINTS) return { points: pts, index: Math.max(0, i - 1) };
|
|
364
|
+
pts.splice(i, 0, p);
|
|
365
|
+
return { points: pts, index: i };
|
|
366
|
+
}
|
|
367
|
+
function setWidthPoint(points, index, patch) {
|
|
368
|
+
const pts = points.map((p2) => ({ ...p2 }));
|
|
369
|
+
const p = pts[index];
|
|
370
|
+
if (!p) return pts;
|
|
371
|
+
if (typeof patch.t === "number" && Number.isFinite(patch.t)) {
|
|
372
|
+
const lo = index > 0 ? pts[index - 1].t : 0;
|
|
373
|
+
const hi = index < pts.length - 1 ? pts[index + 1].t : 1;
|
|
374
|
+
p.t = Math.min(Math.max(patch.t, lo), Math.max(hi, lo));
|
|
375
|
+
}
|
|
376
|
+
const l = clean(patch.left, VECTOR_WIDTH_PROFILE_MAX_SCALE);
|
|
377
|
+
const r = clean(patch.right, VECTOR_WIDTH_PROFILE_MAX_SCALE);
|
|
378
|
+
if (l !== null) p.left = l;
|
|
379
|
+
if (r !== null) p.right = r;
|
|
380
|
+
return pts;
|
|
381
|
+
}
|
|
382
|
+
function removeWidthPoints(points, indices) {
|
|
383
|
+
const drop = new Set(indices);
|
|
384
|
+
return points.filter((_, i) => !drop.has(i)).map((p) => ({ ...p }));
|
|
385
|
+
}
|
|
386
|
+
function ease(u, e) {
|
|
387
|
+
const x = Math.min(Math.max(u, 0), 1);
|
|
388
|
+
const round = Math.sqrt(Math.max(0, 1 - (1 - x) * (1 - x)));
|
|
389
|
+
return x + (round - x) * Math.min(Math.max(e, 0), 1);
|
|
390
|
+
}
|
|
391
|
+
function taperWaveFactor(t, taper, wave) {
|
|
392
|
+
let k = 1;
|
|
393
|
+
if (taper) {
|
|
394
|
+
let ls = Math.max(0, _nullishCoalesce(taper.startLength, () => ( 0)));
|
|
395
|
+
let le = Math.max(0, _nullishCoalesce(taper.endLength, () => ( 0)));
|
|
396
|
+
if (ls + le > 1) {
|
|
397
|
+
const f = 1 / (ls + le);
|
|
398
|
+
ls *= f;
|
|
399
|
+
le *= f;
|
|
400
|
+
}
|
|
401
|
+
const sw = Math.min(Math.max(_nullishCoalesce(taper.startWidth, () => ( 0)), 0), 1);
|
|
402
|
+
const ew = Math.min(Math.max(_nullishCoalesce(taper.endWidth, () => ( 0)), 0), 1);
|
|
403
|
+
if (ls > 0 && t < ls) k = Math.min(k, sw + (1 - sw) * ease(t / ls, _nullishCoalesce(taper.startEase, () => ( 0))));
|
|
404
|
+
if (le > 0 && t > 1 - le) k = Math.min(k, ew + (1 - ew) * ease((1 - t) / le, _nullishCoalesce(taper.endEase, () => ( 0))));
|
|
405
|
+
}
|
|
406
|
+
if (wave) {
|
|
407
|
+
const cycles = _nullishCoalesce(wave.cycles, () => ( 4));
|
|
408
|
+
const amount = Math.min(Math.max(_nullishCoalesce(wave.amount, () => ( 0.5)), 0), 1);
|
|
409
|
+
if (cycles > 0 && amount > 0) {
|
|
410
|
+
const ph = 2 * Math.PI * t * cycles + (_nullishCoalesce(wave.phase, () => ( 0))) * Math.PI / 180;
|
|
411
|
+
k *= 1 - amount * (0.5 - 0.5 * Math.cos(ph));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return k;
|
|
415
|
+
}
|
|
416
|
+
function generateWidthProfile(options) {
|
|
417
|
+
const cycles = options.wave ? Math.max(0, _nullishCoalesce(options.wave.cycles, () => ( 4))) : 0;
|
|
418
|
+
const n = Math.max(8, Math.min(VECTOR_WIDTH_PROFILE_MAX_POINTS * 4, _nullishCoalesce(options.samples, () => ( Math.ceil(32 + cycles * 16)))));
|
|
419
|
+
const raw = [];
|
|
420
|
+
for (let i = 0; i <= n; i++) raw.push([i / n, taperWaveFactor(i / n, options.taper, options.wave)]);
|
|
421
|
+
const ts = [_optionalChain([options, 'access', _15 => _15.taper, 'optionalAccess', _16 => _16.startLength]), _optionalChain([options, 'access', _17 => _17.taper, 'optionalAccess', _18 => _18.endLength]) !== void 0 ? 1 - options.taper.endLength : void 0];
|
|
422
|
+
for (const t of ts) if (typeof t === "number" && t > 0 && t < 1) raw.push([t, taperWaveFactor(t, options.taper, options.wave)]);
|
|
423
|
+
raw.sort((a, b) => a[0] - b[0]);
|
|
424
|
+
const kept = simplifySamples(raw, _nullishCoalesce(options.tolerance, () => ( 0.01)), VECTOR_WIDTH_PROFILE_MAX_POINTS);
|
|
425
|
+
return kept.map(([t, k]) => sym(t, k));
|
|
426
|
+
}
|
|
427
|
+
function simplifySamples(samples, tolerance, max) {
|
|
428
|
+
if (samples.length <= 2) return samples.slice();
|
|
429
|
+
const keep = new Array(samples.length).fill(false);
|
|
430
|
+
keep[0] = keep[samples.length - 1] = true;
|
|
431
|
+
const stack = [[0, samples.length - 1]];
|
|
432
|
+
while (stack.length) {
|
|
433
|
+
const [a, b] = stack.pop();
|
|
434
|
+
const [ta, va] = samples[a];
|
|
435
|
+
const [tb, vb] = samples[b];
|
|
436
|
+
let worst = -1;
|
|
437
|
+
let err = tolerance;
|
|
438
|
+
for (let i = a + 1; i < b; i++) {
|
|
439
|
+
const [t, v2] = samples[i];
|
|
440
|
+
const lin = tb - ta > 1e-12 ? va + (vb - va) * (t - ta) / (tb - ta) : va;
|
|
441
|
+
const e = Math.abs(v2 - lin);
|
|
442
|
+
if (e > err) {
|
|
443
|
+
err = e;
|
|
444
|
+
worst = i;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (worst >= 0) {
|
|
448
|
+
keep[worst] = true;
|
|
449
|
+
stack.push([a, worst], [worst, b]);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
let out = samples.filter((_, i) => keep[i]);
|
|
453
|
+
while (out.length > max) out = out.filter((_, i) => i === 0 || i === out.length - 1 || i % 2 === 0);
|
|
454
|
+
return out;
|
|
455
|
+
}
|
|
456
|
+
var VECTOR_PRESSURE_NOMINAL = 0.5;
|
|
457
|
+
function pressureWidthProfile(samples, options = {}) {
|
|
458
|
+
const raw = samples.filter((s) => Number.isFinite(s.t) && Number.isFinite(s.pressure)).map((s) => [Math.min(Math.max(s.t, 0), 1), Math.max(0.05, Math.min(1, Math.max(0, s.pressure)) / VECTOR_PRESSURE_NOMINAL)]);
|
|
459
|
+
if (raw.length < 2) return [];
|
|
460
|
+
if (raw.every((s) => Math.abs(s[1] - raw[0][1]) < 1e-6)) return [];
|
|
461
|
+
return simplifySamples(raw, _nullishCoalesce(options.tolerance, () => ( 0.02)), VECTOR_WIDTH_PROFILE_MAX_POINTS).map(([t, k]) => sym(t, Math.round(k * 1e3) / 1e3));
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// src/vector/varstroke.ts
|
|
465
|
+
var SAMPLES_PER_SUBPATH = 128;
|
|
466
|
+
var MAX_DASHES = 5e3;
|
|
467
|
+
var sub2 = (a, b) => [a[0] - b[0], a[1] - b[1]];
|
|
468
|
+
var along = (p, v2, k) => [p[0] + v2[0] * k, p[1] + v2[1] * k];
|
|
469
|
+
var lerp = (a, b, u) => [a[0] + (b[0] - a[0]) * u, a[1] + (b[1] - a[1]) * u];
|
|
470
|
+
var dist = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1]);
|
|
471
|
+
var unitOf = (v2) => {
|
|
472
|
+
const l = Math.hypot(v2[0], v2[1]);
|
|
473
|
+
return l > 0 ? [v2[0] / l, v2[1] / l] : [1, 0];
|
|
474
|
+
};
|
|
475
|
+
var leftNormal = (d) => [d[1], -d[0]];
|
|
476
|
+
function flatten(segments, closed, tol) {
|
|
477
|
+
const pts = [];
|
|
478
|
+
const corner = [];
|
|
479
|
+
const push = (p, isCorner) => {
|
|
480
|
+
const last = pts[pts.length - 1];
|
|
481
|
+
if (last && dist(last, p) <= 1e-9) {
|
|
482
|
+
corner[corner.length - 1] ||= isCorner;
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
pts.push(p);
|
|
486
|
+
corner.push(isCorner);
|
|
487
|
+
};
|
|
488
|
+
for (const seg of segments) {
|
|
489
|
+
const flat = _chunkGVB7ZPLZcjs.flattenChain.call(void 0, [seg], tol);
|
|
490
|
+
if (dist(seg[0], seg[seg.length - 1]) <= 1e-12 && flat.length > 1) flat.push(seg[seg.length - 1]);
|
|
491
|
+
flat.forEach((p, i) => push(p, i === 0 || i === flat.length - 1));
|
|
492
|
+
}
|
|
493
|
+
if (closed && pts.length > 2 && dist(pts[0], pts[pts.length - 1]) > 1e-9) push(pts[0], true);
|
|
494
|
+
if (pts.length < 2) return null;
|
|
495
|
+
let total = 0;
|
|
496
|
+
for (let i = 1; i < pts.length; i++) total += dist(pts[i - 1], pts[i]);
|
|
497
|
+
if (!(total > 0)) return null;
|
|
498
|
+
const step = Math.max(total / SAMPLES_PER_SUBPATH, tol);
|
|
499
|
+
const fine = [pts[0]];
|
|
500
|
+
const fineCorner = [corner[0]];
|
|
501
|
+
for (let i = 1; i < pts.length; i++) {
|
|
502
|
+
const n = Math.max(1, Math.ceil(dist(pts[i - 1], pts[i]) / step));
|
|
503
|
+
for (let k = 1; k <= n; k++) {
|
|
504
|
+
fine.push(k === n ? pts[i] : lerp(pts[i - 1], pts[i], k / n));
|
|
505
|
+
fineCorner.push(k === n ? corner[i] : false);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
const s = [0];
|
|
509
|
+
for (let i = 1; i < fine.length; i++) s.push(s[i - 1] + dist(fine[i - 1], fine[i]));
|
|
510
|
+
return { pts: fine, s, corner: fineCorner, closed };
|
|
511
|
+
}
|
|
512
|
+
function dashIntervals(pattern, offset, len2) {
|
|
513
|
+
let pat = pattern.map((v2) => Number.isFinite(v2) ? Math.max(0, v2) : 0);
|
|
514
|
+
if (pat.length % 2 === 1) pat = [...pat, ...pat];
|
|
515
|
+
const period = pat.reduce((a, b) => a + b, 0);
|
|
516
|
+
if (pat.length < 2 || !(period > 1e-9) || !(len2 > 0)) return [[0, len2]];
|
|
517
|
+
let pos = ((Number.isFinite(offset) ? offset : 0) % period + period) % period;
|
|
518
|
+
let idx = 0;
|
|
519
|
+
while (pos >= pat[idx]) {
|
|
520
|
+
pos -= pat[idx];
|
|
521
|
+
idx = (idx + 1) % pat.length;
|
|
522
|
+
}
|
|
523
|
+
const out = [];
|
|
524
|
+
let s = 0;
|
|
525
|
+
let guard = 0;
|
|
526
|
+
while (s < len2 && guard++ < MAX_DASHES * pat.length) {
|
|
527
|
+
const e = Math.min(s + pat[idx] - pos, len2);
|
|
528
|
+
if (idx % 2 === 0 && e >= s) out.push([s, e]);
|
|
529
|
+
s += pat[idx] - pos;
|
|
530
|
+
pos = 0;
|
|
531
|
+
idx = (idx + 1) % pat.length;
|
|
532
|
+
}
|
|
533
|
+
return out;
|
|
534
|
+
}
|
|
535
|
+
function at(poly, t) {
|
|
536
|
+
let i = 1;
|
|
537
|
+
while (i < poly.pts.length - 1 && poly.s[i] <= t) i++;
|
|
538
|
+
const a = poly.s[i - 1];
|
|
539
|
+
const b = poly.s[i];
|
|
540
|
+
const u = b > a ? Math.min(Math.max((t - a) / (b - a), 0), 1) : 0;
|
|
541
|
+
return [lerp(poly.pts[i - 1], poly.pts[i], u), i];
|
|
542
|
+
}
|
|
543
|
+
function arcPoints(c, a0, sweep, r0, r1, tol) {
|
|
544
|
+
const r = Math.max(r0, r1);
|
|
545
|
+
if (!(r > tol * 0.5) || !Number.isFinite(sweep)) return [];
|
|
546
|
+
const stepAngle = 2 * Math.acos(Math.min(Math.max(1 - tol / r, -1), 1));
|
|
547
|
+
const n = Math.min(128, Math.max(2, Math.ceil(Math.abs(sweep) / Math.max(stepAngle, 1e-3))));
|
|
548
|
+
const out = [];
|
|
549
|
+
for (let k = 1; k < n; k++) {
|
|
550
|
+
const f = k / n;
|
|
551
|
+
const a = a0 + sweep * f;
|
|
552
|
+
const rr = r0 + (r1 - r0) * f;
|
|
553
|
+
out.push([c[0] + Math.cos(a) * rr, c[1] + Math.sin(a) * rr]);
|
|
554
|
+
}
|
|
555
|
+
return out;
|
|
556
|
+
}
|
|
557
|
+
function crossing(a0, a1, b0, b1) {
|
|
558
|
+
const r = sub2(a1, a0);
|
|
559
|
+
const q = sub2(b1, b0);
|
|
560
|
+
const den = r[0] * q[1] - r[1] * q[0];
|
|
561
|
+
if (Math.abs(den) < 1e-12) return null;
|
|
562
|
+
const w = sub2(b0, a0);
|
|
563
|
+
const t = (w[0] * q[1] - w[1] * q[0]) / den;
|
|
564
|
+
const u = (w[0] * r[1] - w[1] * r[0]) / den;
|
|
565
|
+
return t > 1e-9 && t <= 1 && u >= 0 && u < 1 - 1e-9 ? [a0[0] + r[0] * t, a0[1] + r[1] * t] : null;
|
|
566
|
+
}
|
|
567
|
+
function variableStrokeRings(path, options) {
|
|
568
|
+
const half = options.width / 2;
|
|
569
|
+
if (!(half > 0) || !Number.isFinite(half)) return [];
|
|
570
|
+
const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : 0.05;
|
|
571
|
+
const join = _nullishCoalesce(options.join, () => ( "miter"));
|
|
572
|
+
const cap = _nullishCoalesce(options.cap, () => ( "butt"));
|
|
573
|
+
const miterLimit = options.miterLimit && options.miterLimit >= 1 ? options.miterLimit : 4;
|
|
574
|
+
const rings = [];
|
|
575
|
+
const push = (out, p) => {
|
|
576
|
+
const last = out[out.length - 1];
|
|
577
|
+
if (!last || dist(last, p) > 1e-12) out.push(p);
|
|
578
|
+
};
|
|
579
|
+
for (const contour of _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path)) {
|
|
580
|
+
if (!contour.segments.length) continue;
|
|
581
|
+
const poly = flatten(contour.segments, contour.closed, Math.min(tol, half) / 4);
|
|
582
|
+
if (!poly) continue;
|
|
583
|
+
const len2 = poly.s[poly.s.length - 1];
|
|
584
|
+
const sides = (s) => {
|
|
585
|
+
const w = widthProfileAt(options.profile, s / len2);
|
|
586
|
+
return [w.left * half, w.right * half];
|
|
587
|
+
};
|
|
588
|
+
const intervals = _optionalChain([options, 'access', _19 => _19.dash, 'optionalAccess', _20 => _20.some, 'call', _21 => _21((v2) => v2 > 0)]) ? dashIntervals(options.dash, _nullishCoalesce(options.dashOffset, () => ( 0)), len2) : [[0, len2]];
|
|
589
|
+
const whole = intervals.length === 1 && intervals[0][0] <= 0 && intervals[0][1] >= len2;
|
|
590
|
+
for (const [a, b] of intervals) {
|
|
591
|
+
const [pa, ia] = at(poly, a);
|
|
592
|
+
const [pb, ib] = at(poly, b);
|
|
593
|
+
const pts = [{ p: pa, s: a, corner: poly.corner[0] && a <= 0 }];
|
|
594
|
+
for (let i = ia; i < ib; i++) pts.push({ p: poly.pts[i], s: poly.s[i], corner: poly.corner[i] });
|
|
595
|
+
pts.push({ p: pb, s: b, corner: false });
|
|
596
|
+
const run = pts.filter((q, i) => i === 0 || dist(q.p, pts[i - 1].p) > 1e-9);
|
|
597
|
+
if (run.length < 2) {
|
|
598
|
+
const [l, r] = sides(a);
|
|
599
|
+
const w2 = (l + r) / 2;
|
|
600
|
+
if (cap === "round" && w2 > 0) rings.push([[pa[0] + w2, pa[1]], ...arcPoints(pa, 0, 2 * Math.PI, w2, w2, tol)]);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
const closed = whole && poly.closed;
|
|
604
|
+
const m = run.length - 1;
|
|
605
|
+
const dirs = [];
|
|
606
|
+
for (let i = 0; i < m; i++) dirs.push(unitOf(sub2(run[i + 1].p, run[i].p)));
|
|
607
|
+
const normals = dirs.map(leftNormal);
|
|
608
|
+
const w = run.map((q) => sides(q.s));
|
|
609
|
+
const side = (sigma) => {
|
|
610
|
+
const k = sigma > 0 ? 0 : 1;
|
|
611
|
+
const S = (i) => along(run[i].p, normals[i], sigma * w[i][k]);
|
|
612
|
+
const E = (i) => along(run[i + 1].p, normals[i], sigma * w[i + 1][k]);
|
|
613
|
+
const out = [S(0)];
|
|
614
|
+
for (let i = 0; i < m; i++) {
|
|
615
|
+
const seam = i === m - 1;
|
|
616
|
+
if (seam && !closed) {
|
|
617
|
+
push(out, E(i));
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
const j = seam ? 0 : i + 1;
|
|
621
|
+
const p = run[i + 1].p;
|
|
622
|
+
const d0 = dirs[i];
|
|
623
|
+
const d1 = dirs[j];
|
|
624
|
+
const cross2 = d0[0] * d1[1] - d0[1] * d1[0];
|
|
625
|
+
const dot2 = d0[0] * d1[0] + d0[1] * d1[1];
|
|
626
|
+
const r0 = w[i + 1][k];
|
|
627
|
+
const r1 = w[j][k];
|
|
628
|
+
const e = E(i);
|
|
629
|
+
const st = S(j);
|
|
630
|
+
if (Math.abs(cross2) < 1e-12 && dot2 > 0) {
|
|
631
|
+
push(out, e);
|
|
632
|
+
if (!seam) push(out, st);
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
const uturn = Math.abs(cross2) < 1e-12;
|
|
636
|
+
const outer = uturn ? sigma > 0 : cross2 * sigma > 0;
|
|
637
|
+
if (!outer) {
|
|
638
|
+
const x = seam ? null : crossing(out[out.length - 1], e, st, E(j));
|
|
639
|
+
if (x) push(out, x);
|
|
640
|
+
else {
|
|
641
|
+
push(out, e);
|
|
642
|
+
push(out, p);
|
|
643
|
+
if (!seam) push(out, st);
|
|
644
|
+
}
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
push(out, e);
|
|
648
|
+
const theta = uturn ? Math.PI : Math.atan2(cross2, dot2);
|
|
649
|
+
const r = (r0 + r1) / 2;
|
|
650
|
+
const kind = run[i + 1].corner || seam && poly.corner[0] ? join : "round";
|
|
651
|
+
if (r > 1e-9) {
|
|
652
|
+
if (kind === "round") {
|
|
653
|
+
if (r * (1 - Math.cos(Math.abs(theta) / 2)) > tol * 0.25) {
|
|
654
|
+
for (const q of arcPoints(p, Math.atan2(e[1] - p[1], e[0] - p[0]), theta, r0, r1, tol)) push(out, q);
|
|
655
|
+
}
|
|
656
|
+
} else if (kind === "miter") {
|
|
657
|
+
const halfCos = Math.cos(theta / 2);
|
|
658
|
+
const bis = [normals[i][0] + normals[j][0], normals[i][1] + normals[j][1]];
|
|
659
|
+
const bl = Math.hypot(bis[0], bis[1]);
|
|
660
|
+
if (halfCos > 1e-6 && 1 / halfCos <= miterLimit && bl > 1e-9) push(out, along(p, bis, sigma * r / halfCos / bl));
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
if (!seam) push(out, st);
|
|
664
|
+
}
|
|
665
|
+
if (closed && out.length > 1 && dist(out[0], out[out.length - 1]) <= 1e-12) out.pop();
|
|
666
|
+
return out;
|
|
667
|
+
};
|
|
668
|
+
const left = side(1);
|
|
669
|
+
const right = side(-1);
|
|
670
|
+
if (closed) {
|
|
671
|
+
rings.push(left, right.reverse());
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
const capPoints = (atStart) => {
|
|
675
|
+
if (cap === "butt") return [];
|
|
676
|
+
const i = atStart ? 0 : m;
|
|
677
|
+
const d = atStart ? dirs[0] : dirs[m - 1];
|
|
678
|
+
const [l, r] = w[i];
|
|
679
|
+
if (!(l + r > 1e-9)) return [];
|
|
680
|
+
const p = run[i].p;
|
|
681
|
+
const n = leftNormal(d);
|
|
682
|
+
const L = along(p, n, l);
|
|
683
|
+
const R = along(p, n, -r);
|
|
684
|
+
if (cap === "round") {
|
|
685
|
+
const a0 = Math.atan2(d[1], d[0]) + (atStart ? Math.PI / 2 : -Math.PI / 2);
|
|
686
|
+
return arcPoints(p, a0, Math.PI, atStart ? r : l, atStart ? l : r, tol);
|
|
687
|
+
}
|
|
688
|
+
const ext = (l + r) / 2;
|
|
689
|
+
const o = atStart ? [-d[0], -d[1]] : d;
|
|
690
|
+
return atStart ? [along(R, o, ext), along(L, o, ext)] : [along(L, o, ext), along(R, o, ext)];
|
|
691
|
+
};
|
|
692
|
+
const ring = [];
|
|
693
|
+
for (const q of [...left, ...capPoints(false), ...right.reverse(), ...capPoints(true)]) push(ring, q);
|
|
694
|
+
if (ring.length > 2) rings.push(ring);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return rings;
|
|
698
|
+
}
|
|
699
|
+
function variableStrokeOutline(path, options) {
|
|
700
|
+
const pieces = variableStrokeRings(path, options);
|
|
701
|
+
if (!pieces.length) return [];
|
|
702
|
+
const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : 0.05;
|
|
703
|
+
let polygons;
|
|
704
|
+
try {
|
|
705
|
+
polygons = _chunkGVB7ZPLZcjs.polygonBoolean.call(void 0, "union", [{ rings: pieces, fillRule: "nonzero" }]);
|
|
706
|
+
} catch (e2) {
|
|
707
|
+
return [];
|
|
708
|
+
}
|
|
709
|
+
const out = [];
|
|
710
|
+
for (const polygon2 of polygons) {
|
|
711
|
+
for (const ring of polygon2) {
|
|
712
|
+
if (ring.length < 3) continue;
|
|
713
|
+
const cubics = _chunkGVB7ZPLZcjs.fitCubics.call(void 0, ring, tol, { closed: true, cornerAngleDeg: 25 });
|
|
714
|
+
if (!cubics.length) continue;
|
|
715
|
+
out.push({ type: "M", x: cubics[0].p0[0], y: cubics[0].p0[1] });
|
|
716
|
+
cubics.forEach((c, i) => {
|
|
717
|
+
if (_chunkGVB7ZPLZcjs.isStraightCubic.call(void 0, c, tol * 0.02)) {
|
|
718
|
+
if (i < cubics.length - 1) out.push({ type: "L", x: c.p3[0], y: c.p3[1] });
|
|
719
|
+
} 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
|
+
});
|
|
721
|
+
out.push({ type: "Z" });
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
return out;
|
|
725
|
+
}
|
|
726
|
+
function nearestStrokePosition(path, p, only) {
|
|
727
|
+
let best = null;
|
|
728
|
+
_chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).forEach((c, ci) => {
|
|
729
|
+
if (!c.segments.length || only !== void 0 && ci !== only) return;
|
|
730
|
+
const lengths = c.segments.map((s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s));
|
|
731
|
+
const total = lengths.reduce((a, b) => a + b, 0);
|
|
732
|
+
if (!(total > 0)) return;
|
|
733
|
+
let acc = 0;
|
|
734
|
+
c.segments.forEach((seg, si) => {
|
|
735
|
+
const near2 = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, seg, p);
|
|
736
|
+
if (!best || near2.distance < best.distance) {
|
|
737
|
+
const s = acc + _chunkGVB7ZPLZcjs.segmentLength.call(void 0, seg, 0, near2.t);
|
|
738
|
+
const tan = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, seg, near2.t);
|
|
739
|
+
const pt2 = seg.length === 2 ? lerp(seg[0], seg[1], near2.t) : evalSeg(seg, near2.t);
|
|
740
|
+
const n = leftNormal([tan[0], tan[1]]);
|
|
741
|
+
const side = (p[0] - pt2[0]) * n[0] + (p[1] - pt2[1]) * n[1] >= 0 ? "left" : "right";
|
|
742
|
+
best = { contour: ci, t: Math.min(Math.max(s / total, 0), 1), distance: near2.distance, side, point: pt2, tangent: [tan[0], tan[1]], length: total };
|
|
743
|
+
}
|
|
744
|
+
acc += lengths[si];
|
|
745
|
+
});
|
|
746
|
+
});
|
|
747
|
+
return best;
|
|
748
|
+
}
|
|
749
|
+
function evalSeg(seg, t) {
|
|
750
|
+
let pts = seg.map((q) => [q[0], q[1]]);
|
|
751
|
+
while (pts.length > 1) pts = pts.slice(1).map((q, i) => lerp(pts[i], q, t));
|
|
752
|
+
return pts[0];
|
|
753
|
+
}
|
|
754
|
+
function strokePositionPoint(path, index, t) {
|
|
755
|
+
const c = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path)[index];
|
|
756
|
+
if (!_optionalChain([c, 'optionalAccess', _22 => _22.segments, 'access', _23 => _23.length])) return null;
|
|
757
|
+
const lengths = c.segments.map((s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s));
|
|
758
|
+
const total = lengths.reduce((a, b) => a + b, 0);
|
|
759
|
+
let want = Math.min(Math.max(t, 0), 1) * total;
|
|
760
|
+
for (let i = 0; i < c.segments.length; i++) {
|
|
761
|
+
const seg = c.segments[i];
|
|
762
|
+
if (want <= lengths[i] + 1e-12 || i === c.segments.length - 1) {
|
|
763
|
+
let lo = 0;
|
|
764
|
+
let hi = 1;
|
|
765
|
+
const target = Math.min(want, lengths[i]);
|
|
766
|
+
for (let k = 0; k < 40; k++) {
|
|
767
|
+
const mid = (lo + hi) / 2;
|
|
768
|
+
if (_chunkGVB7ZPLZcjs.segmentLength.call(void 0, seg, 0, mid) < target) lo = mid;
|
|
769
|
+
else hi = mid;
|
|
770
|
+
}
|
|
771
|
+
const u = (lo + hi) / 2;
|
|
772
|
+
const tan = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, seg, u);
|
|
773
|
+
return { point: evalSeg(seg, u), tangent: [tan[0], tan[1]] };
|
|
774
|
+
}
|
|
775
|
+
want -= lengths[i];
|
|
776
|
+
}
|
|
777
|
+
return null;
|
|
778
|
+
}
|
|
779
|
+
|
|
248
780
|
// src/vector/stroke.ts
|
|
249
781
|
var KAPPA = 0.5522847498307936;
|
|
250
782
|
var NOTCH = 0.7;
|
|
251
783
|
function isClosedBezierShape(path) {
|
|
252
|
-
const contours =
|
|
784
|
+
const contours = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
|
|
253
785
|
return contours.length > 0 && contours.every((c) => c.closed);
|
|
254
786
|
}
|
|
255
787
|
function effectiveStrokeAlign(style, closedShape) {
|
|
256
788
|
const a = _nullishCoalesce(style.strokeAlign, () => ( "center"));
|
|
257
789
|
return closedShape ? a : "center";
|
|
258
790
|
}
|
|
791
|
+
function strokeWidthProfileOf(style) {
|
|
792
|
+
if (!_optionalChain([style, 'access', _24 => _24.strokeWidthProfile, 'optionalAccess', _25 => _25.length])) return null;
|
|
793
|
+
const p = sanitizeWidthProfile(style.strokeWidthProfile);
|
|
794
|
+
return isUniformWidthProfile(p) ? null : p;
|
|
795
|
+
}
|
|
259
796
|
function hasStrokeExtras(style) {
|
|
260
|
-
return (_nullishCoalesce(style.strokeAlign, () => ( "center"))) !== "center" || !!style.startArrow || !!style.endArrow;
|
|
797
|
+
return (_nullishCoalesce(style.strokeAlign, () => ( "center"))) !== "center" || !!style.startArrow || !!style.endArrow || !!strokeWidthProfileOf(style);
|
|
798
|
+
}
|
|
799
|
+
function vectorStrokeLineArea(parts, style, tolerance) {
|
|
800
|
+
const profile = strokeWidthProfileOf(style);
|
|
801
|
+
const dash = _optionalChain([style, 'access', _26 => _26.strokeDasharray, 'optionalAccess', _27 => _27.length]) ? { dash: style.strokeDasharray } : {};
|
|
802
|
+
const join = _nullishCoalesce(style.strokeLinejoin, () => ( "miter"));
|
|
803
|
+
const cap = _nullishCoalesce(style.strokeLinecap, () => ( "butt"));
|
|
804
|
+
if (profile) return variableStrokeOutline(parts.line, { width: parts.drawWidth, profile, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
|
|
805
|
+
return _chunkGVB7ZPLZcjs.outlineStroke.call(void 0, parts.line, { width: parts.drawWidth, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
|
|
261
806
|
}
|
|
262
807
|
var capExtent = (style, width) => style.strokeLinecap === "round" || style.strokeLinecap === "square" ? width / 2 : 0;
|
|
263
808
|
function arrowheadWeight(style, end) {
|
|
@@ -334,27 +879,27 @@ function arrowheadPath(kind, tip, dir, hw) {
|
|
|
334
879
|
}
|
|
335
880
|
}
|
|
336
881
|
var toVec = (p) => ({ x: p[0], y: p[1] });
|
|
337
|
-
var segLen = (s) =>
|
|
882
|
+
var segLen = (s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s);
|
|
338
883
|
function endOf(segs, atStart) {
|
|
339
884
|
const long = (s2) => segLen(s2) > 1e-9;
|
|
340
885
|
if (atStart) {
|
|
341
886
|
const s2 = _nullishCoalesce(segs.find(long), () => ( segs[0]));
|
|
342
|
-
const t2 =
|
|
887
|
+
const t2 = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, s2, 0);
|
|
343
888
|
return { p: toVec(segs[0][0]), out: v(-t2[0], -t2[1]) };
|
|
344
889
|
}
|
|
345
890
|
const s = _nullishCoalesce([...segs].reverse().find(long), () => ( segs[segs.length - 1]));
|
|
346
|
-
const t =
|
|
891
|
+
const t = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, s, 1);
|
|
347
892
|
const last = segs[segs.length - 1];
|
|
348
893
|
return { p: toVec(last[last.length - 1]), out: v(t[0], t[1]) };
|
|
349
894
|
}
|
|
350
|
-
function pointAlong(segs, fromStart,
|
|
895
|
+
function pointAlong(segs, fromStart, dist4) {
|
|
351
896
|
const order = fromStart ? segs : [...segs].reverse();
|
|
352
897
|
let acc = 0;
|
|
353
898
|
for (const s of order) {
|
|
354
899
|
const l = segLen(s);
|
|
355
|
-
if (acc + l >=
|
|
356
|
-
const want = fromStart ?
|
|
357
|
-
const pts =
|
|
900
|
+
if (acc + l >= dist4) {
|
|
901
|
+
const want = fromStart ? dist4 - acc : l - (dist4 - acc);
|
|
902
|
+
const pts = _chunkGVB7ZPLZcjs.trimSegments.call(void 0, [s], 0, want);
|
|
358
903
|
const p = pts.length ? pts[0][pts[0].length - 1] : s[0];
|
|
359
904
|
return toVec(p);
|
|
360
905
|
}
|
|
@@ -364,7 +909,7 @@ function pointAlong(segs, fromStart, dist3) {
|
|
|
364
909
|
}
|
|
365
910
|
function vectorStrokeParts(path, style) {
|
|
366
911
|
const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
|
|
367
|
-
const contours =
|
|
912
|
+
const contours = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
|
|
368
913
|
const closedShape = contours.length > 0 && contours.every((c) => c.closed);
|
|
369
914
|
const align = effectiveStrokeAlign(style, closedShape);
|
|
370
915
|
const drawWidth = align === "center" ? width : width * 2;
|
|
@@ -404,42 +949,54 @@ function vectorStrokeParts(path, style) {
|
|
|
404
949
|
if (!s0 && !s1) return c;
|
|
405
950
|
const lengths = c.segments.map(segLen);
|
|
406
951
|
const total = lengths.reduce((a, b) => a + b, 0);
|
|
407
|
-
return { closed: false, segments: total - s1 > s0 ?
|
|
952
|
+
return { closed: false, segments: total - s1 > s0 ? _chunkGVB7ZPLZcjs.trimSegments.call(void 0, c.segments, s0, total - s1, lengths) : [] };
|
|
408
953
|
});
|
|
409
|
-
return { align, line:
|
|
954
|
+
return { align, line: _chunkGVB7ZPLZcjs.contoursToPath.call(void 0, trimmed), drawWidth, heads };
|
|
410
955
|
}
|
|
411
956
|
function vectorStrokeOutlinePath(path, style) {
|
|
412
957
|
const parts = vectorStrokeParts(path, style);
|
|
413
|
-
const stroke =
|
|
414
|
-
width: parts.drawWidth,
|
|
415
|
-
join: _nullishCoalesce(style.strokeLinejoin, () => ( "miter")),
|
|
416
|
-
cap: _nullishCoalesce(style.strokeLinecap, () => ( "butt")),
|
|
417
|
-
..._optionalChain([style, 'access', _7 => _7.strokeDasharray, 'optionalAccess', _8 => _8.length]) ? { dash: style.strokeDasharray } : {}
|
|
418
|
-
});
|
|
958
|
+
const stroke = vectorStrokeLineArea(parts, style);
|
|
419
959
|
const fill = { path, fillRule: _nullishCoalesce(style.fillRule, () => ( "nonzero")) };
|
|
420
960
|
let area = stroke;
|
|
421
|
-
if (parts.align === "inside") area =
|
|
422
|
-
else if (parts.align === "outside") area =
|
|
961
|
+
if (parts.align === "inside") area = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "intersection", [stroke, fill]).path;
|
|
962
|
+
else if (parts.align === "outside") area = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "difference", [stroke, fill]).path;
|
|
423
963
|
if (!parts.heads.length) return area;
|
|
424
|
-
return
|
|
964
|
+
return _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "union", [area, ...parts.heads.map((h) => h.path)]).path;
|
|
425
965
|
}
|
|
426
966
|
function hitTestVectorStroke(path, p, style, tolerance = 0) {
|
|
427
967
|
const parts = vectorStrokeParts(path, style);
|
|
428
968
|
const point = [p.x, p.y];
|
|
429
969
|
const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
|
|
430
970
|
for (const h of parts.heads) {
|
|
431
|
-
if (
|
|
971
|
+
if (_chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, h.path, point) || tolerance > 0 && _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, h.path, point) <= tolerance) return true;
|
|
432
972
|
}
|
|
433
973
|
if (!parts.line.length) return false;
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
974
|
+
const profile = strokeWidthProfileOf(style);
|
|
975
|
+
let d;
|
|
976
|
+
let reach = width / 2;
|
|
977
|
+
if (profile) {
|
|
978
|
+
const near2 = nearestStrokePosition(parts.line, point);
|
|
979
|
+
if (!near2) return false;
|
|
980
|
+
d = near2.distance;
|
|
981
|
+
const w = widthProfileAt(profile, near2.t);
|
|
982
|
+
reach = width / 2 * (near2.side === "left" ? w.left : w.right);
|
|
983
|
+
if (parts.align !== "center") reach *= 2;
|
|
984
|
+
const atEnd = near2.t <= 1e-9 || near2.t >= 1 - 1e-9;
|
|
985
|
+
if (atEnd && (style.strokeLinecap === "round" || style.strokeLinecap === "square") && d > reach) {
|
|
986
|
+
reach = Math.max(reach, width / 2 * (w.left + w.right) / 2);
|
|
987
|
+
}
|
|
988
|
+
} else {
|
|
989
|
+
d = _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, parts.line, point);
|
|
990
|
+
if (parts.align !== "center") reach = width;
|
|
991
|
+
}
|
|
992
|
+
if (parts.align === "center") return d <= reach + tolerance;
|
|
993
|
+
if (d > reach + tolerance) return false;
|
|
437
994
|
if (d <= tolerance) return true;
|
|
438
|
-
const inside =
|
|
995
|
+
const inside = _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(style.fillRule, () => ( "nonzero")));
|
|
439
996
|
return parts.align === "inside" ? inside : !inside;
|
|
440
997
|
}
|
|
441
998
|
function vectorStrokeReach(style) {
|
|
442
|
-
const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
|
|
999
|
+
const width = (_nullishCoalesce(style.strokeWidth, () => ( 1))) * widthProfileMaxScale(strokeWidthProfileOf(style));
|
|
443
1000
|
const align = _nullishCoalesce(style.strokeAlign, () => ( "center"));
|
|
444
1001
|
let reach = align === "center" ? width / 2 : align === "outside" ? width : 0;
|
|
445
1002
|
if (style.strokeLinejoin !== "round" && style.strokeLinejoin !== "bevel") reach *= 4;
|
|
@@ -511,7 +1068,7 @@ function vectorNodeToBezier(node) {
|
|
|
511
1068
|
}
|
|
512
1069
|
function vectorPathData(input, precision = 3) {
|
|
513
1070
|
const subpaths = Array.isArray(input) ? input : input.subpaths;
|
|
514
|
-
return
|
|
1071
|
+
return _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, subpathsToBezier(subpaths), { precision });
|
|
515
1072
|
}
|
|
516
1073
|
function inferAnchorType(a) {
|
|
517
1074
|
if (isOnAnchor(a, a.in) || isOnAnchor(a, a.out)) return "corner";
|
|
@@ -527,7 +1084,7 @@ function inferAnchorType(a) {
|
|
|
527
1084
|
return Math.abs(li - lo) <= 1e-3 * Math.max(li, lo) ? "symmetric" : "smooth";
|
|
528
1085
|
}
|
|
529
1086
|
function bezierToSubpaths(input) {
|
|
530
|
-
const path =
|
|
1087
|
+
const path = _chunkGVB7ZPLZcjs.toBezierPath.call(void 0, input);
|
|
531
1088
|
const out = [];
|
|
532
1089
|
let current = null;
|
|
533
1090
|
const last = () => current.anchors[current.anchors.length - 1];
|
|
@@ -624,14 +1181,14 @@ function nodeMatrix(node) {
|
|
|
624
1181
|
function vectorPathWorldBezier(node, parent = IDENTITY_MATRIX) {
|
|
625
1182
|
const m = multiplyMatrices(nodeMatrix(node), parent);
|
|
626
1183
|
const path = subpathsToBezier(node.subpaths);
|
|
627
|
-
return isIdentityMatrix(m) ? path :
|
|
1184
|
+
return isIdentityMatrix(m) ? path : _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, path, m);
|
|
628
1185
|
}
|
|
629
1186
|
function vectorNodeBounds(node, parent = IDENTITY_MATRIX) {
|
|
630
1187
|
if (node.type === "group") {
|
|
631
1188
|
const m = multiplyMatrices(nodeMatrix(node), parent);
|
|
632
1189
|
return unionBounds(node.children.map((c) => vectorNodeBounds(c, m)));
|
|
633
1190
|
}
|
|
634
|
-
const b =
|
|
1191
|
+
const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, vectorPathWorldBezier(node, parent));
|
|
635
1192
|
if (!b) return null;
|
|
636
1193
|
return { x: b.minX, y: b.minY, width: b.maxX - b.minX, height: b.maxY - b.minY };
|
|
637
1194
|
}
|
|
@@ -665,9 +1222,9 @@ function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX) {
|
|
|
665
1222
|
const path = vectorPathWorldBezier(node, parent);
|
|
666
1223
|
if (path.length === 0) return false;
|
|
667
1224
|
const point = [p.x, p.y];
|
|
668
|
-
if (hasPaint(node.fill) &&
|
|
1225
|
+
if (hasPaint(node.fill) && _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(node.fillRule, () => ( "nonzero")))) return true;
|
|
669
1226
|
if (hasPaint(node.stroke)) return hitTestVectorStroke(path, p, node, tolerance);
|
|
670
|
-
return
|
|
1227
|
+
return _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, path, point) <= tolerance;
|
|
671
1228
|
}
|
|
672
1229
|
function vectorStrokeOutline(node, parent = IDENTITY_MATRIX) {
|
|
673
1230
|
if (!hasPaint(node.stroke) || !((_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0)) return [];
|
|
@@ -687,9 +1244,9 @@ function nearestSegment(node, p) {
|
|
|
687
1244
|
const count = subpathSegmentCount(sp);
|
|
688
1245
|
for (let i = 0; i < count; i++) {
|
|
689
1246
|
const seg = subpathSegment(sp, i);
|
|
690
|
-
const hit =
|
|
1247
|
+
const hit = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, seg, [p.x, p.y]);
|
|
691
1248
|
if (!best || hit.distance < best.distance) {
|
|
692
|
-
const pt2 =
|
|
1249
|
+
const pt2 = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, hit.t);
|
|
693
1250
|
best = { subpath: s, segment: i, t: hit.t, point: { x: pt2[0], y: pt2[1] }, distance: hit.distance };
|
|
694
1251
|
}
|
|
695
1252
|
}
|
|
@@ -749,8 +1306,10 @@ function bakeIntoGeometry(node, m) {
|
|
|
749
1306
|
if (isIdentityMatrix(m)) return node;
|
|
750
1307
|
if (node.type === "group") return { ...node, children: node.children.map((c) => transformVectorNode(c, m)) };
|
|
751
1308
|
const path = node;
|
|
1309
|
+
const mirrored = m[0] * m[3] - m[1] * m[2] < 0 && _optionalChain([path, 'access', _28 => _28.strokeWidthProfile, 'optionalAccess', _29 => _29.length]);
|
|
752
1310
|
return {
|
|
753
1311
|
...path,
|
|
1312
|
+
...mirrored ? { strokeWidthProfile: mirrorWidthProfile(path.strokeWidthProfile) } : {},
|
|
754
1313
|
subpaths: path.subpaths.map((sp) => ({
|
|
755
1314
|
closed: sp.closed,
|
|
756
1315
|
anchors: sp.anchors.map((a) => {
|
|
@@ -861,7 +1420,7 @@ function insertAnchor(sp, segment, t) {
|
|
|
861
1420
|
const ia = segment;
|
|
862
1421
|
const ib = (segment + 1) % n;
|
|
863
1422
|
const seg = subpathSegment(sp, segment);
|
|
864
|
-
const [left, right] =
|
|
1423
|
+
const [left, right] = _chunkGVB7ZPLZcjs.splitSegment.call(void 0, seg, t);
|
|
865
1424
|
const mid = left[left.length - 1];
|
|
866
1425
|
const anchor = { x: mid[0], y: mid[1] };
|
|
867
1426
|
if (seg.length === 4) {
|
|
@@ -957,7 +1516,7 @@ function vectorCornersAttribute(subpaths, precision = 3) {
|
|
|
957
1516
|
subpaths.forEach(
|
|
958
1517
|
(sp, s) => sp.anchors.forEach((a, i) => {
|
|
959
1518
|
if (!a.corner || !(a.corner.radius > 0)) return;
|
|
960
|
-
out.push(`${s}.${i}:${
|
|
1519
|
+
out.push(`${s}.${i}:${_chunkGVB7ZPLZcjs.formatNumber.call(void 0, a.corner.radius, precision)}${a.corner.kind && a.corner.kind !== "round" ? `:${a.corner.kind}` : ""}`);
|
|
961
1520
|
})
|
|
962
1521
|
);
|
|
963
1522
|
return out.join(" ");
|
|
@@ -966,7 +1525,7 @@ function applyVectorCornersAttribute(subpaths, value) {
|
|
|
966
1525
|
for (const item of value.trim().split(/\s+/)) {
|
|
967
1526
|
const m = /^(\d+)\.(\d+):([\d.eE+-]+)(?::([a-z]+))?$/.exec(item);
|
|
968
1527
|
if (!m) continue;
|
|
969
|
-
const a = _optionalChain([subpaths, 'access',
|
|
1528
|
+
const a = _optionalChain([subpaths, 'access', _30 => _30[+m[1]], 'optionalAccess', _31 => _31.anchors, 'access', _32 => _32[+m[2]]]);
|
|
970
1529
|
const radius = parseFloat(m[3]);
|
|
971
1530
|
if (!a || !(radius > 0)) continue;
|
|
972
1531
|
const kind = VECTOR_CORNER_KINDS.includes(m[4]) ? m[4] : void 0;
|
|
@@ -978,21 +1537,49 @@ var escapeAttr = (value) => value.replace(/&/g, "&").replace(/"/g, """)
|
|
|
978
1537
|
function vectorPaintToSvg(paint, gradientId) {
|
|
979
1538
|
if (!hasPaint(paint)) return { value: "none", gradient: null };
|
|
980
1539
|
if (typeof paint === "string") return { value: paint, gradient: null };
|
|
981
|
-
return { value: `url(#${gradientId})`, gradient:
|
|
1540
|
+
return { value: `url(#${gradientId})`, gradient: _chunkGVB7ZPLZcjs.gradientToSvgDef.call(void 0, paint, gradientId) };
|
|
982
1541
|
}
|
|
1542
|
+
var partsCache = /* @__PURE__ */ new WeakMap();
|
|
983
1543
|
function vectorStrokeSvgParts(node, clipId, precision = 3) {
|
|
984
1544
|
if (!hasPaint(node.stroke) || !hasStrokeExtras(node)) return void 0;
|
|
1545
|
+
const hit = partsCache.get(node);
|
|
1546
|
+
if (hit && hit.clipId === clipId && hit.precision === precision) return hit.parts;
|
|
1547
|
+
const parts = computeStrokeSvgParts(node, clipId, precision);
|
|
1548
|
+
partsCache.set(node, { clipId, precision, parts });
|
|
1549
|
+
return parts;
|
|
1550
|
+
}
|
|
1551
|
+
function computeStrokeSvgParts(node, clipId, precision) {
|
|
985
1552
|
const path = subpathsToBezier(node.subpaths);
|
|
986
1553
|
const parts = vectorStrokeParts(path, node);
|
|
987
|
-
|
|
1554
|
+
const profiled = !!strokeWidthProfileOf(node);
|
|
1555
|
+
if (parts.align === "center" && !parts.heads.length && !profiled) return void 0;
|
|
988
1556
|
let clip = null;
|
|
989
1557
|
if (parts.align !== "center") {
|
|
990
|
-
const b =
|
|
1558
|
+
const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, path);
|
|
991
1559
|
const pad = vectorStrokeReach(node) + 1;
|
|
992
1560
|
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 };
|
|
993
1561
|
clip = { kind: parts.align === "inside" ? "clip" : "mask", id: clipId, bounds };
|
|
994
1562
|
}
|
|
995
|
-
return {
|
|
1563
|
+
return {
|
|
1564
|
+
align: parts.align,
|
|
1565
|
+
d: _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, parts.line, { precision }),
|
|
1566
|
+
width: parts.drawWidth,
|
|
1567
|
+
...profiled && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0 ? { outline: _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, vectorStrokeLineArea(parts, node), { precision }) } : {},
|
|
1568
|
+
clip,
|
|
1569
|
+
heads: parts.heads.map((h) => _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, h.path, { precision }))
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
function widthProfileToAttribute(points, precision = 4) {
|
|
1573
|
+
return points.map((p) => [p.t, p.left, p.right].map((n) => _chunkGVB7ZPLZcjs.formatNumber.call(void 0, n, precision)).join(",")).join(";");
|
|
1574
|
+
}
|
|
1575
|
+
function widthProfileFromAttribute(value) {
|
|
1576
|
+
if (!value) return [];
|
|
1577
|
+
return sanitizeWidthProfile(
|
|
1578
|
+
value.split(";").map((part) => {
|
|
1579
|
+
const [t, left, right] = part.split(",").map((n) => parseFloat(n));
|
|
1580
|
+
return { t, left, right: Number.isFinite(right) ? right : left };
|
|
1581
|
+
})
|
|
1582
|
+
);
|
|
996
1583
|
}
|
|
997
1584
|
var round2 = (n) => Math.round(n * 100) / 100;
|
|
998
1585
|
function gradientMarkup(def) {
|
|
@@ -1007,11 +1594,11 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
1007
1594
|
const pretty = options.pretty !== false;
|
|
1008
1595
|
const defs = [];
|
|
1009
1596
|
const lines = [];
|
|
1010
|
-
const num = (n) =>
|
|
1597
|
+
const num = (n) => _chunkGVB7ZPLZcjs.formatNumber.call(void 0, n, precision);
|
|
1011
1598
|
const indent = (depth) => pretty ? " ".repeat(depth) : "";
|
|
1012
1599
|
const common = (node) => {
|
|
1013
1600
|
let out2 = ` id="${escapeAttr(node.id)}"`;
|
|
1014
|
-
if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) =>
|
|
1601
|
+
if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) => _chunkGVB7ZPLZcjs.formatNumber.call(void 0, n, 6)).join(" ")})"`;
|
|
1015
1602
|
if (node.opacity !== void 0 && node.opacity < 1) out2 += ` opacity="${num(node.opacity)}"`;
|
|
1016
1603
|
if (node.visible === false) out2 += ` display="none"`;
|
|
1017
1604
|
return out2;
|
|
@@ -1030,13 +1617,13 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
1030
1617
|
if (stroke.gradient) defs.push(gradientMarkup(stroke.gradient));
|
|
1031
1618
|
const d = vectorPathData(node, precision);
|
|
1032
1619
|
const corners2 = vectorCornersAttribute(node.subpaths, precision);
|
|
1033
|
-
const live = corners2 ? ` data-vector-d="${
|
|
1620
|
+
const live = corners2 ? ` data-vector-d="${_chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, subpathsToBezier(node.subpaths, { corners: false }), { precision })}" data-vector-corners="${corners2}"` : "";
|
|
1034
1621
|
const fillAttrs = ` fill="${escapeAttr(fill.value)}"${node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : ""}`;
|
|
1035
1622
|
const lineAttrs = (width) => {
|
|
1036
1623
|
let out2 = ` stroke="${escapeAttr(stroke.value)}" stroke-width="${num(width)}"`;
|
|
1037
1624
|
if (node.strokeLinecap && node.strokeLinecap !== "butt") out2 += ` stroke-linecap="${node.strokeLinecap}"`;
|
|
1038
1625
|
if (node.strokeLinejoin && node.strokeLinejoin !== "miter") out2 += ` stroke-linejoin="${node.strokeLinejoin}"`;
|
|
1039
|
-
if (_optionalChain([node, 'access',
|
|
1626
|
+
if (_optionalChain([node, 'access', _33 => _33.strokeDasharray, 'optionalAccess', _34 => _34.length])) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num).join(" ")}"`;
|
|
1040
1627
|
return out2;
|
|
1041
1628
|
};
|
|
1042
1629
|
const parts = stroke.value !== "none" ? vectorStrokeSvgParts(node, `${prefix}clip-${node.id}`, precision) : void 0;
|
|
@@ -1051,10 +1638,17 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
1051
1638
|
if (node.arrowAlign && node.arrowAlign !== "extend") data += ` data-vector-arrow-align="${node.arrowAlign}"`;
|
|
1052
1639
|
if (node.startArrowScale !== void 0 && node.startArrowScale !== 1) data += ` data-vector-start-arrow-scale="${num(node.startArrowScale)}"`;
|
|
1053
1640
|
if (node.endArrowScale !== void 0 && node.endArrowScale !== 1) data += ` data-vector-end-arrow-scale="${num(node.endArrowScale)}"`;
|
|
1641
|
+
const profile = strokeWidthProfileOf(node);
|
|
1642
|
+
if (profile) {
|
|
1643
|
+
data += ` data-vector-width-profile="${widthProfileToAttribute(profile)}"`;
|
|
1644
|
+
if (node.strokeLinecap && node.strokeLinecap !== "butt") data += ` data-vector-stroke-linecap="${node.strokeLinecap}"`;
|
|
1645
|
+
if (node.strokeLinejoin && node.strokeLinejoin !== "miter") data += ` data-vector-stroke-linejoin="${node.strokeLinejoin}"`;
|
|
1646
|
+
if (_optionalChain([node, 'access', _35 => _35.strokeDasharray, 'optionalAccess', _36 => _36.length])) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num).join(" ")}"`;
|
|
1647
|
+
}
|
|
1054
1648
|
lines.push(`${indent(depth)}<g${common(node)}${data}>`);
|
|
1055
1649
|
lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
|
|
1056
1650
|
if (options.strokes === "outline") {
|
|
1057
|
-
const area =
|
|
1651
|
+
const area = _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
|
|
1058
1652
|
lines.push(`${indent(depth + 1)}<path data-vector-part="stroke-outline" d="${area}" fill="${escapeAttr(stroke.value)}"/>`);
|
|
1059
1653
|
} else {
|
|
1060
1654
|
let clip = "";
|
|
@@ -1071,7 +1665,8 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
1071
1665
|
clip = ` mask="url(#${id})"`;
|
|
1072
1666
|
}
|
|
1073
1667
|
}
|
|
1074
|
-
lines.push(`${indent(depth + 1)}<path data-vector-part="stroke" d="${parts.
|
|
1668
|
+
if (parts.outline !== void 0) lines.push(`${indent(depth + 1)}<path data-vector-part="stroke-outline" d="${parts.outline}" fill="${escapeAttr(stroke.value)}"${clip}/>`);
|
|
1669
|
+
else lines.push(`${indent(depth + 1)}<path data-vector-part="stroke" d="${parts.d}" fill="none"${lineAttrs(parts.width)}${clip}/>`);
|
|
1075
1670
|
for (const h2 of parts.heads) lines.push(`${indent(depth + 1)}<path data-vector-part="head" d="${h2}" fill="${escapeAttr(stroke.value)}"/>`);
|
|
1076
1671
|
}
|
|
1077
1672
|
lines.push(`${indent(depth)}</g>`);
|
|
@@ -1217,7 +1812,7 @@ function resolveGradient(id, raw, seen = /* @__PURE__ */ new Set()) {
|
|
|
1217
1812
|
seen.add(id);
|
|
1218
1813
|
let stops = readStops(el);
|
|
1219
1814
|
const href = _nullishCoalesce(el.attrs.href, () => ( el.attrs["xlink:href"]));
|
|
1220
|
-
if (!stops.length && _optionalChain([href, 'optionalAccess',
|
|
1815
|
+
if (!stops.length && _optionalChain([href, 'optionalAccess', _37 => _37.startsWith, 'call', _38 => _38("#")])) stops = _nullishCoalesce(_optionalChain([resolveGradient, 'call', _39 => _39(href.slice(1), raw, seen), 'optionalAccess', _40 => _40.stops]), () => ( []));
|
|
1221
1816
|
if (!stops.length) return null;
|
|
1222
1817
|
if (el.name === "radialGradient") {
|
|
1223
1818
|
return { type: "radial", cx: fraction(el.attrs.cx, 0.5), cy: fraction(el.attrs.cy, 0.5), r: fraction(el.attrs.r, 0.5), stops };
|
|
@@ -1321,7 +1916,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
1321
1916
|
const part = (name) => g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === name);
|
|
1322
1917
|
const fillEl = part("fill");
|
|
1323
1918
|
const subpaths = fillEl ? shapeOf(fillEl) : null;
|
|
1324
|
-
if (!fillEl || !_optionalChain([subpaths, 'optionalAccess',
|
|
1919
|
+
if (!fillEl || !_optionalChain([subpaths, 'optionalAccess', _41 => _41.length])) return null;
|
|
1325
1920
|
const a = g.attrs;
|
|
1326
1921
|
const fs = readStyle(fillEl, style);
|
|
1327
1922
|
const strokeEl = part("stroke");
|
|
@@ -1334,6 +1929,11 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
1334
1929
|
return n > 0 ? n : void 0;
|
|
1335
1930
|
};
|
|
1336
1931
|
const align = a["data-vector-stroke-align"];
|
|
1932
|
+
const profile = widthProfileFromAttribute(a["data-vector-width-profile"]);
|
|
1933
|
+
const kept = (key, values) => values.includes(a[key]) ? a[key] : void 0;
|
|
1934
|
+
const keptCap = kept("data-vector-stroke-linecap", ["round", "square"]);
|
|
1935
|
+
const keptJoin = kept("data-vector-stroke-linejoin", ["round", "bevel"]);
|
|
1936
|
+
const keptDash = a["data-vector-stroke-dasharray"] ? numberList(a["data-vector-stroke-dasharray"]) : void 0;
|
|
1337
1937
|
const node = {
|
|
1338
1938
|
id: idFor(g),
|
|
1339
1939
|
type: "path",
|
|
@@ -1349,7 +1949,11 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
1349
1949
|
...arrow(a["data-vector-end-arrow"]) ? { endArrow: arrow(a["data-vector-end-arrow"]) } : {},
|
|
1350
1950
|
...a["data-vector-arrow-align"] === "tip" ? { arrowAlign: "tip" } : {},
|
|
1351
1951
|
...scale(a["data-vector-start-arrow-scale"]) ? { startArrowScale: scale(a["data-vector-start-arrow-scale"]) } : {},
|
|
1352
|
-
...scale(a["data-vector-end-arrow-scale"]) ? { endArrowScale: scale(a["data-vector-end-arrow-scale"]) } : {}
|
|
1952
|
+
...scale(a["data-vector-end-arrow-scale"]) ? { endArrowScale: scale(a["data-vector-end-arrow-scale"]) } : {},
|
|
1953
|
+
...profile.length ? { strokeWidthProfile: profile } : {},
|
|
1954
|
+
...keptCap ? { strokeLinecap: keptCap } : {},
|
|
1955
|
+
...keptJoin ? { strokeLinejoin: keptJoin } : {},
|
|
1956
|
+
..._optionalChain([keptDash, 'optionalAccess', _42 => _42.length]) ? { strokeDasharray: keptDash } : {}
|
|
1353
1957
|
};
|
|
1354
1958
|
return placed(node, m);
|
|
1355
1959
|
};
|
|
@@ -1403,7 +2007,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
1403
2007
|
// src/vector/snap.ts
|
|
1404
2008
|
var VECTOR_CONSTRUCTION_ANGLES = [0, 45, 90, 135];
|
|
1405
2009
|
function constrainToLeave(leave, p) {
|
|
1406
|
-
if (!_optionalChain([leave, 'optionalAccess',
|
|
2010
|
+
if (!_optionalChain([leave, 'optionalAccess', _43 => _43.constrain])) return p;
|
|
1407
2011
|
const dx = p.x - leave.at.x;
|
|
1408
2012
|
const dy = p.y - leave.at.y;
|
|
1409
2013
|
switch (leave.constrain) {
|
|
@@ -1514,7 +2118,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1514
2118
|
moving.set(r.nodeId, set);
|
|
1515
2119
|
}
|
|
1516
2120
|
const t = _VectorSnapTargets.collect(doc, new Set(moving.keys()), "segments", false);
|
|
1517
|
-
t.pushPaths(doc, new Set(moving.keys()), (id, s, i) => !!_optionalChain([moving, 'access',
|
|
2121
|
+
t.pushPaths(doc, new Set(moving.keys()), (id, s, i) => !!_optionalChain([moving, 'access', _44 => _44.get, 'call', _45 => _45(id), 'optionalAccess', _46 => _46.has, 'call', _47 => _47(`${s}:${i}`)]), true);
|
|
1518
2122
|
return t.index();
|
|
1519
2123
|
}
|
|
1520
2124
|
/**
|
|
@@ -1632,7 +2236,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1632
2236
|
}
|
|
1633
2237
|
const b = vectorNodeBounds(n, parent);
|
|
1634
2238
|
const f = nodeFrame(n, parent, b);
|
|
1635
|
-
if (b) self.pushRect(b, "edge", _nullishCoalesce(_optionalChain([f, 'optionalAccess',
|
|
2239
|
+
if (b) self.pushRect(b, "edge", _nullishCoalesce(_optionalChain([f, 'optionalAccess', _48 => _48.centre]), () => ( null)));
|
|
1636
2240
|
}
|
|
1637
2241
|
};
|
|
1638
2242
|
visit(doc.nodes, IDENTITY_MATRIX);
|
|
@@ -1669,7 +2273,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1669
2273
|
*/
|
|
1670
2274
|
snapFrom(p, leave, tol) {
|
|
1671
2275
|
const none = (q) => ({ point: q, kind: null, x: false, y: false, lines: [], labels: [] });
|
|
1672
|
-
const
|
|
2276
|
+
const at2 = (q, kind, lines2 = []) => ({
|
|
1673
2277
|
point: q,
|
|
1674
2278
|
kind,
|
|
1675
2279
|
x: true,
|
|
@@ -1677,23 +2281,23 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1677
2281
|
lines: lines2,
|
|
1678
2282
|
labels: [this.label(q, kind)]
|
|
1679
2283
|
});
|
|
1680
|
-
if (_optionalChain([leave, 'optionalAccess',
|
|
2284
|
+
if (_optionalChain([leave, 'optionalAccess', _49 => _49.constrain])) {
|
|
1681
2285
|
const q = constrainToLeave(leave, p);
|
|
1682
2286
|
const hit = this.slide(leave.at, { x: q.x - leave.at.x, y: q.y - leave.at.y }, q, tol, true);
|
|
1683
2287
|
return hit ? { point: hit.point, x: true, y: true, ...this.linedUp(hit.point, hit.from) } : none(q);
|
|
1684
2288
|
}
|
|
1685
2289
|
const point = this.nearestPoint(p, tol);
|
|
1686
|
-
if (point) return
|
|
2290
|
+
if (point) return at2(point.p, point.kind);
|
|
1687
2291
|
const near2 = this.segmentsNear(p, tol);
|
|
1688
|
-
const
|
|
1689
|
-
if (
|
|
2292
|
+
const crossing2 = this.crossing(near2, p, tol);
|
|
2293
|
+
if (crossing2) return at2(crossing2, "intersect");
|
|
1690
2294
|
if (leave && leave.curves !== false) {
|
|
1691
2295
|
const foot = this.curvePoint(near2, leave.at, p, tol);
|
|
1692
|
-
if (foot) return
|
|
2296
|
+
if (foot) return at2(foot.point, foot.kind, [line("construction", leave.at, foot.point)]);
|
|
1693
2297
|
}
|
|
1694
2298
|
const on = this.onSegment(near2);
|
|
1695
|
-
if (on) return
|
|
1696
|
-
if (_optionalChain([leave, 'optionalAccess',
|
|
2299
|
+
if (on) return at2(on, "path");
|
|
2300
|
+
if (_optionalChain([leave, 'optionalAccess', _50 => _50.angles, 'optionalAccess', _51 => _51.length])) {
|
|
1697
2301
|
const c = construction(leave, p, tol);
|
|
1698
2302
|
if (c) {
|
|
1699
2303
|
const hit = this.slide(leave.at, c.dir, c.point, tol, false);
|
|
@@ -1739,7 +2343,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1739
2343
|
* the nearest target line crosses it, at most twice `tol` away: where it lands and the
|
|
1740
2344
|
* target point that line comes from.
|
|
1741
2345
|
*/
|
|
1742
|
-
slide(
|
|
2346
|
+
slide(at2, dir, q, tol, ray) {
|
|
1743
2347
|
const len2 = dir.x * dir.x + dir.y * dir.y;
|
|
1744
2348
|
if (!Number.isFinite(len2) || len2 <= 1e-18) return null;
|
|
1745
2349
|
const reach = 2 * tol;
|
|
@@ -1747,10 +2351,10 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1747
2351
|
for (const vertical of [true, false]) {
|
|
1748
2352
|
const d = vertical ? dir.x : dir.y;
|
|
1749
2353
|
if (Math.abs(d) <= 1e-9) continue;
|
|
1750
|
-
const a = vertical ?
|
|
2354
|
+
const a = vertical ? at2.x : at2.y;
|
|
1751
2355
|
for (const l of linesNear(vertical ? this.xs : this.ys, vertical ? q.x : q.y, reach)) {
|
|
1752
2356
|
const s = (l.v - a) / d;
|
|
1753
|
-
const hit = vertical ? { x: l.v, y:
|
|
2357
|
+
const hit = vertical ? { x: l.v, y: at2.y + dir.y * s } : { x: at2.x + dir.x * s, y: l.v };
|
|
1754
2358
|
const moved = distance(hit, q);
|
|
1755
2359
|
if (moved <= reach && (!ray || s > 0) && (!best || moved < best.moved)) best = { moved, point: hit, from: l.from };
|
|
1756
2360
|
}
|
|
@@ -1769,13 +2373,13 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1769
2373
|
const pt2 = toPoint(p);
|
|
1770
2374
|
for (const s of this.segments) {
|
|
1771
2375
|
if (p.x < s.minX - tol || p.x > s.maxX + tol || p.y < s.minY - tol || p.y > s.maxY + tol) continue;
|
|
1772
|
-
const hit =
|
|
2376
|
+
const hit = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, s.seg, pt2);
|
|
1773
2377
|
if (hit.distance <= tol) out.push({ seg: s.seg, t: hit.t, distance: hit.distance });
|
|
1774
2378
|
}
|
|
1775
2379
|
return out.sort((a, b) => a.distance - b.distance);
|
|
1776
2380
|
}
|
|
1777
2381
|
onSegment(near2) {
|
|
1778
|
-
return near2.length ? toVec2(
|
|
2382
|
+
return near2.length ? toVec2(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
|
|
1779
2383
|
}
|
|
1780
2384
|
/** Where two of the target segments near `p` cross, the crossing nearest `p` within `tol`. */
|
|
1781
2385
|
crossing(near2, p, tol) {
|
|
@@ -1784,7 +2388,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1784
2388
|
let bestD = Infinity;
|
|
1785
2389
|
for (let i = 0; i < list.length; i++) {
|
|
1786
2390
|
for (let j = i + 1; j < list.length; j++) {
|
|
1787
|
-
for (const hit of
|
|
2391
|
+
for (const hit of _chunkGVB7ZPLZcjs.segmentIntersections.call(void 0, list[i].seg, list[j].seg)) {
|
|
1788
2392
|
const q = toVec2(hit.point);
|
|
1789
2393
|
const d = distance(q, p);
|
|
1790
2394
|
if (d <= tol && d < bestD) {
|
|
@@ -1823,7 +2427,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1823
2427
|
* with nothing spaces the box evenly in its row or column. Returns the correction and guides.
|
|
1824
2428
|
*/
|
|
1825
2429
|
snapRect(r, tol, options = {}) {
|
|
1826
|
-
const axes = { x: _optionalChain([options, 'access',
|
|
2430
|
+
const axes = { x: _optionalChain([options, 'access', _52 => _52.axes, 'optionalAccess', _53 => _53.x]) !== false, y: _optionalChain([options, 'access', _54 => _54.axes, 'optionalAccess', _55 => _55.y]) !== false };
|
|
1827
2431
|
const nearest = (lines, values) => {
|
|
1828
2432
|
let best = null;
|
|
1829
2433
|
for (const v2 of values) for (const l of linesNear(lines, v2, tol)) if (!best || Math.abs(l.v - v2) < Math.abs(best.d)) best = { d: l.v - v2, from: l.from };
|
|
@@ -1831,7 +2435,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1831
2435
|
};
|
|
1832
2436
|
const bx = axes.x ? nearest(this.xs, [r.x, r.x + r.width / 2, r.x + r.width]) : null;
|
|
1833
2437
|
const by = axes.y ? nearest(this.ys, [r.y, r.y + r.height / 2, r.y + r.height]) : null;
|
|
1834
|
-
const out = { dx: _nullishCoalesce(_optionalChain([bx, 'optionalAccess',
|
|
2438
|
+
const out = { dx: _nullishCoalesce(_optionalChain([bx, 'optionalAccess', _56 => _56.d]), () => ( 0)), dy: _nullishCoalesce(_optionalChain([by, 'optionalAccess', _57 => _57.d]), () => ( 0)), x: !!bx, y: !!by, lines: [], labels: [] };
|
|
1835
2439
|
const done = { ...r, x: r.x + out.dx, y: r.y + out.dy };
|
|
1836
2440
|
if (bx) {
|
|
1837
2441
|
const x = bx.from.x;
|
|
@@ -1898,11 +2502,11 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1898
2502
|
for (const s of starts) if (Math.abs(s.start - r0) <= tol && (!pick || Math.abs(s.start - r0) < Math.abs(pick.start - r0))) pick = s;
|
|
1899
2503
|
if (!pick) return null;
|
|
1900
2504
|
const { start, repeats } = pick;
|
|
1901
|
-
const
|
|
2505
|
+
const at2 = horizontal ? { ...r, x: start } : { ...r, y: start };
|
|
1902
2506
|
const end = start + len2;
|
|
1903
2507
|
const gaps = [];
|
|
1904
|
-
if (before && (repeats === null || Math.abs(start - before.a1 - repeats) <= EQUAL)) gaps.push([before.a1, start, mid(before.b,
|
|
1905
|
-
if (after && (repeats === null || Math.abs(after.a0 - end - repeats) <= EQUAL)) gaps.push([end, after.a0, mid(after.b,
|
|
2508
|
+
if (before && (repeats === null || Math.abs(start - before.a1 - repeats) <= EQUAL)) gaps.push([before.a1, start, mid(before.b, at2)]);
|
|
2509
|
+
if (after && (repeats === null || Math.abs(after.a0 - end - repeats) <= EQUAL)) gaps.push([end, after.a0, mid(after.b, at2)]);
|
|
1906
2510
|
if (repeats !== null) {
|
|
1907
2511
|
for (const p of pairs) if (Math.abs(p.g - repeats) <= EQUAL) gaps.push(p.gap);
|
|
1908
2512
|
}
|
|
@@ -1954,9 +2558,9 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
|
|
|
1954
2558
|
const on = this.nearestPoint(p, tol);
|
|
1955
2559
|
const tries = [];
|
|
1956
2560
|
if (on) tries.push({ tx: on.p.x, ty: on.p.y, s: { hx: null, hy: null, on } });
|
|
1957
|
-
tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess',
|
|
1958
|
-
tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess',
|
|
1959
|
-
tries.push({ tx: null, ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess',
|
|
2561
|
+
tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _58 => _58.v]), () => ( null)), ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _59 => _59.v]), () => ( null)), s: { hx, hy, on: null } });
|
|
2562
|
+
tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _60 => _60.v]), () => ( null)), ty: null, s: { hx, hy: null, on: null } });
|
|
2563
|
+
tries.push({ tx: null, ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _61 => _61.v]), () => ( null)), s: { hx: null, hy, on: null } });
|
|
1960
2564
|
for (const { tx, ty, s } of tries) {
|
|
1961
2565
|
if (tx === null && ty === null) continue;
|
|
1962
2566
|
const q = applyMatrix(toLocal, { x: _nullishCoalesce(tx, () => ( p.x)), y: _nullishCoalesce(ty, () => ( p.y)) });
|
|
@@ -2106,15 +2710,15 @@ var crossCondition = (r, d) => r[0] * d[1] - r[1] * d[0];
|
|
|
2106
2710
|
function solveOnSegment(seg, base, cond) {
|
|
2107
2711
|
const b = [base.x, base.y];
|
|
2108
2712
|
const g = (t) => {
|
|
2109
|
-
const p =
|
|
2110
|
-
return cond([p[0] - b[0], p[1] - b[1]],
|
|
2713
|
+
const p = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
|
|
2714
|
+
return cond([p[0] - b[0], p[1] - b[1]], _chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, seg, t));
|
|
2111
2715
|
};
|
|
2112
2716
|
const vals = [];
|
|
2113
2717
|
let scale = 0;
|
|
2114
2718
|
for (let i = 0; i <= CURVE_SAMPLES; i++) {
|
|
2115
2719
|
const t = i / CURVE_SAMPLES;
|
|
2116
|
-
const p =
|
|
2117
|
-
const d =
|
|
2720
|
+
const p = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
|
|
2721
|
+
const d = _chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, seg, t);
|
|
2118
2722
|
const r = [p[0] - b[0], p[1] - b[1]];
|
|
2119
2723
|
vals.push(cond(r, d));
|
|
2120
2724
|
scale = Math.max(scale, Math.hypot(r[0], r[1]) * Math.hypot(d[0], d[1]));
|
|
@@ -2141,8 +2745,8 @@ function solveOnSegment(seg, base, cond) {
|
|
|
2141
2745
|
} else hi = m;
|
|
2142
2746
|
}
|
|
2143
2747
|
const t = (lo + hi) / 2;
|
|
2144
|
-
const p =
|
|
2145
|
-
const dv =
|
|
2748
|
+
const p = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
|
|
2749
|
+
const dv = _chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, seg, t);
|
|
2146
2750
|
const r = Math.hypot(p[0] - b[0], p[1] - b[1]);
|
|
2147
2751
|
const dl = Math.hypot(dv[0], dv[1]);
|
|
2148
2752
|
if (!(r > 1e-9 && dl > 0) || Math.abs(cond([p[0] - b[0], p[1] - b[1]], dv)) > 1e-6 * r * dl) continue;
|
|
@@ -2179,7 +2783,7 @@ function endTangent(c) {
|
|
|
2179
2783
|
return [1, 0];
|
|
2180
2784
|
}
|
|
2181
2785
|
function sample(c, n, out, withStart) {
|
|
2182
|
-
for (let i = withStart ? 0 : 1; i <= n; i++) out.push(
|
|
2786
|
+
for (let i = withStart ? 0 : 1; i <= n; i++) out.push(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, c, i / n));
|
|
2183
2787
|
}
|
|
2184
2788
|
var onAnchor2 = (a, h) => !h || Math.abs(h.x - a.x) < EPS3 && Math.abs(h.y - a.y) < EPS3;
|
|
2185
2789
|
function tidy(a, keepType = true) {
|
|
@@ -2225,7 +2829,7 @@ function fitAcross(pts, N, t0, t1) {
|
|
|
2225
2829
|
const u = [];
|
|
2226
2830
|
for (let i = 0; i <= N; i++) u.push(k * i / N);
|
|
2227
2831
|
for (let i = 1; i <= N; i++) u.push(k + (1 - k) * i / N);
|
|
2228
|
-
return
|
|
2832
|
+
return _chunkGVB7ZPLZcjs.fitCubicWithTangents.call(void 0, pts, u, t0, t1);
|
|
2229
2833
|
};
|
|
2230
2834
|
return goldenMin(fit, 0, 1);
|
|
2231
2835
|
}
|
|
@@ -2285,7 +2889,7 @@ function bendSegment(sp, segment, t, p) {
|
|
|
2285
2889
|
return { anchors, closed: sp.closed };
|
|
2286
2890
|
}
|
|
2287
2891
|
function subpathPointAt(sp, segment, t) {
|
|
2288
|
-
const [x, y] =
|
|
2892
|
+
const [x, y] = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, subpathSegment(sp, segment), t);
|
|
2289
2893
|
return { x, y };
|
|
2290
2894
|
}
|
|
2291
2895
|
function curvatureMoveAnchor(sp, index, q) {
|
|
@@ -2331,9 +2935,9 @@ function curvatureMoveAnchor(sp, index, q) {
|
|
|
2331
2935
|
anchors[index] = moved;
|
|
2332
2936
|
return { anchors, closed: sp.closed };
|
|
2333
2937
|
}
|
|
2334
|
-
function cutSubpathAt(sp,
|
|
2938
|
+
function cutSubpathAt(sp, at2) {
|
|
2335
2939
|
const n = sp.anchors.length;
|
|
2336
|
-
const cuts = [...new Set(
|
|
2940
|
+
const cuts = [...new Set(at2)].filter((i) => Number.isInteger(i) && i >= 0 && i < n && (sp.closed || i > 0 && i < n - 1)).sort((a, b) => a - b);
|
|
2337
2941
|
if (!cuts.length || n < 2) return [{ anchors: sp.anchors.map(cloneAnchor), closed: sp.closed }];
|
|
2338
2942
|
const first = cuts[0];
|
|
2339
2943
|
const run = sp.closed ? Array.from({ length: n + 1 }, (_, i) => sp.anchors[(first + i) % n]) : sp.anchors;
|
|
@@ -2364,7 +2968,7 @@ function splitSubpathAt(sp, segment, t, endTolerance = 1e-6) {
|
|
|
2364
2968
|
return cutSubpathAt(subpath, [index]);
|
|
2365
2969
|
}
|
|
2366
2970
|
var endOf2 = (sp, last) => sp.anchors[last ? sp.anchors.length - 1 : 0];
|
|
2367
|
-
var
|
|
2971
|
+
var dist2 = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
|
|
2368
2972
|
function reverse(sp) {
|
|
2369
2973
|
return {
|
|
2370
2974
|
closed: sp.closed,
|
|
@@ -2391,7 +2995,7 @@ function joinSubpaths(subpaths, tolerance) {
|
|
|
2391
2995
|
const sp = open[0];
|
|
2392
2996
|
const first = sp.anchors[0];
|
|
2393
2997
|
const last = sp.anchors[sp.anchors.length - 1];
|
|
2394
|
-
if (sp.anchors.length > 2 &&
|
|
2998
|
+
if (sp.anchors.length > 2 && dist2(first, last) <= tolerance) {
|
|
2395
2999
|
sp.anchors.pop();
|
|
2396
3000
|
sp.anchors[0] = tidy({ ...first, in: _nullishCoalesce(last.in, () => ( null)) }, false);
|
|
2397
3001
|
} else {
|
|
@@ -2407,7 +3011,7 @@ function joinSubpaths(subpaths, tolerance) {
|
|
|
2407
3011
|
for (let j = i + 1; j < open.length; j++) {
|
|
2408
3012
|
for (const ei of [false, true]) {
|
|
2409
3013
|
for (const ej of [false, true]) {
|
|
2410
|
-
const d =
|
|
3014
|
+
const d = dist2(endOf2(open[i], ei), endOf2(open[j], ej));
|
|
2411
3015
|
if (d < best.d) best = { d, i, j, ei, ej };
|
|
2412
3016
|
}
|
|
2413
3017
|
}
|
|
@@ -2447,8 +3051,8 @@ function smoothSubpath(sp, amount = 1, only) {
|
|
|
2447
3051
|
const p = orig[i];
|
|
2448
3052
|
const dir = unit2(next.x - prev.x, next.y - prev.y);
|
|
2449
3053
|
if (!dir) continue;
|
|
2450
|
-
const li =
|
|
2451
|
-
const lo =
|
|
3054
|
+
const li = dist2(p, prev) / 3;
|
|
3055
|
+
const lo = dist2(p, next) / 3;
|
|
2452
3056
|
const hin = _nullishCoalesce(p.in, () => ( p));
|
|
2453
3057
|
const hout = _nullishCoalesce(p.out, () => ( p));
|
|
2454
3058
|
const target = (h, x, y) => ({ x: h.x + (x - h.x) * t, y: h.y + (y - h.y) * t });
|
|
@@ -2475,12 +3079,12 @@ function segsOf(sp) {
|
|
|
2475
3079
|
function segsToSubpath(segs, closed, types) {
|
|
2476
3080
|
if (!segs.length) return null;
|
|
2477
3081
|
const anchors = [];
|
|
2478
|
-
const
|
|
2479
|
-
anchors.push(
|
|
3082
|
+
const at2 = (p) => ({ x: p[0], y: p[1] });
|
|
3083
|
+
anchors.push(at2(segs[0].c[0]));
|
|
2480
3084
|
for (const s of segs) {
|
|
2481
3085
|
const end = s.c[s.c.length - 1];
|
|
2482
3086
|
if (!s.line) anchors[anchors.length - 1].out = { x: s.c[1][0], y: s.c[1][1] };
|
|
2483
|
-
const next =
|
|
3087
|
+
const next = at2(end);
|
|
2484
3088
|
if (!s.line) next.in = { x: s.c[2][0], y: s.c[2][1] };
|
|
2485
3089
|
anchors.push(next);
|
|
2486
3090
|
}
|
|
@@ -2506,8 +3110,8 @@ function mergePair(a, b, tol) {
|
|
|
2506
3110
|
if (len2 < 1e-12) return null;
|
|
2507
3111
|
const mx = a3[0] - a0[0];
|
|
2508
3112
|
const my = a3[1] - a0[1];
|
|
2509
|
-
const
|
|
2510
|
-
return Math.abs((mx * cy - my * cx) / len2) <= tol &&
|
|
3113
|
+
const along2 = (mx * cx + my * cy) / len2;
|
|
3114
|
+
return Math.abs((mx * cy - my * cx) / len2) <= tol && along2 >= 0 && along2 <= len2 ? { c: [a0, b3], line: true } : null;
|
|
2511
3115
|
}
|
|
2512
3116
|
const ca = a.line ? [a0, a0, a3, a3] : a.c;
|
|
2513
3117
|
const cb = b.line ? [a3, a3, b3, b3] : b.c;
|
|
@@ -2546,12 +3150,12 @@ function removeRedundantPoints(sp, tolerance) {
|
|
|
2546
3150
|
}
|
|
2547
3151
|
|
|
2548
3152
|
// src/vector/pathCut.ts
|
|
2549
|
-
var loopArea = (l) =>
|
|
3153
|
+
var loopArea = (l) => _chunkGVB7ZPLZcjs.contourSignedArea.call(void 0, l.segs);
|
|
2550
3154
|
function loopSample(l) {
|
|
2551
3155
|
const k = l.chord.findIndex((c) => !c);
|
|
2552
|
-
return
|
|
3156
|
+
return _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, l.segs[k >= 0 ? k : 0], 0.5);
|
|
2553
3157
|
}
|
|
2554
|
-
var contains2 = (l, p) =>
|
|
3158
|
+
var contains2 = (l, p) => _chunkGVB7ZPLZcjs.windingNumber.call(void 0, [l.segs], p) !== 0;
|
|
2555
3159
|
function groupFaces(loops) {
|
|
2556
3160
|
const usable = loops.filter((l) => l.segs.length && Math.abs(loopArea(l)) > 1e-12);
|
|
2557
3161
|
if (!usable.length) return [];
|
|
@@ -2567,12 +3171,12 @@ function groupFaces(loops) {
|
|
|
2567
3171
|
return outers.reverse().map((o) => faces.get(o));
|
|
2568
3172
|
}
|
|
2569
3173
|
function faceToPath(face) {
|
|
2570
|
-
return
|
|
3174
|
+
return _chunkGVB7ZPLZcjs.contoursToPath.call(void 0, face.loops.map((l) => ({ segments: l.segs, closed: true })));
|
|
2571
3175
|
}
|
|
2572
3176
|
function facesOf(path, fillRule) {
|
|
2573
|
-
const normalized =
|
|
2574
|
-
const loops =
|
|
2575
|
-
const segs =
|
|
3177
|
+
const normalized = _chunkGVB7ZPLZcjs.normalizeBezierPath.call(void 0, path, fillRule);
|
|
3178
|
+
const loops = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, normalized).map((c) => {
|
|
3179
|
+
const segs = _chunkGVB7ZPLZcjs.closeContour.call(void 0, c, true).map((s) => s.slice());
|
|
2576
3180
|
return { segs, chord: segs.map(() => false) };
|
|
2577
3181
|
});
|
|
2578
3182
|
return groupFaces(loops);
|
|
@@ -2642,7 +3246,7 @@ function lineHits(p, q, seg) {
|
|
|
2642
3246
|
const scale = Math.sqrt(len2) * Math.max(1, ...seg.map((pt2) => Math.abs(pt2[0]) + Math.abs(pt2[1])));
|
|
2643
3247
|
const out = [];
|
|
2644
3248
|
for (const t of rootsInUnit(...coeffs, scale)) {
|
|
2645
|
-
const point =
|
|
3249
|
+
const point = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
|
|
2646
3250
|
const s = ((point[0] - p[0]) * dx + (point[1] - p[1]) * dy) / len2;
|
|
2647
3251
|
if (s >= -1e-9 && s <= 1 + 1e-9) out.push({ s: Math.min(1, Math.max(0, s)), t, point });
|
|
2648
3252
|
}
|
|
@@ -2655,7 +3259,7 @@ function arc(l, a, b, eps) {
|
|
|
2655
3259
|
const segs = [];
|
|
2656
3260
|
const chord = [];
|
|
2657
3261
|
const push = (k, t0, t1) => {
|
|
2658
|
-
const piece = t0 <= 0 && t1 >= 1 ? l.segs[k].slice() :
|
|
3262
|
+
const piece = t0 <= 0 && t1 >= 1 ? l.segs[k].slice() : _chunkGVB7ZPLZcjs.subSegment.call(void 0, l.segs[k], t0, t1);
|
|
2659
3263
|
if (!degenerate(piece, eps)) {
|
|
2660
3264
|
segs.push(piece);
|
|
2661
3265
|
chord.push(l.chord[k]);
|
|
@@ -2680,7 +3284,7 @@ function knifePath(path, fillRule, knife) {
|
|
|
2680
3284
|
if (pts.length < 2) return null;
|
|
2681
3285
|
let faces = facesOf(path, fillRule);
|
|
2682
3286
|
if (!faces.length) return null;
|
|
2683
|
-
const b =
|
|
3287
|
+
const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, path);
|
|
2684
3288
|
const size = b ? Math.max(b.maxX - b.minX, b.maxY - b.minY, 1) : 1;
|
|
2685
3289
|
const eps = size * 1e-9;
|
|
2686
3290
|
let cursor = -Infinity;
|
|
@@ -2694,7 +3298,7 @@ function knifePath(path, fillRule, knife) {
|
|
|
2694
3298
|
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]) };
|
|
2695
3299
|
face2.loops.forEach(
|
|
2696
3300
|
(l, li) => l.segs.forEach((seg, si) => {
|
|
2697
|
-
const sb =
|
|
3301
|
+
const sb = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, seg);
|
|
2698
3302
|
if (sb.maxX < kb.minX - eps || sb.minX > kb.maxX + eps || sb.maxY < kb.minY - eps || sb.minY > kb.maxY + eps) return;
|
|
2699
3303
|
for (const h of lineHits(pts[m], pts[m + 1], seg)) {
|
|
2700
3304
|
const s = m + h.s;
|
|
@@ -2709,7 +3313,7 @@ function knifePath(path, fillRule, knife) {
|
|
|
2709
3313
|
const m = Math.min(pts.length - 2, Math.floor(s));
|
|
2710
3314
|
const u = s - m;
|
|
2711
3315
|
const q = [pts[m][0] + (pts[m + 1][0] - pts[m][0]) * u, pts[m][1] + (pts[m + 1][1] - pts[m][1]) * u];
|
|
2712
|
-
return
|
|
3316
|
+
return _chunkGVB7ZPLZcjs.windingNumber.call(void 0, face2.loops.map((l) => l.segs), q) !== 0;
|
|
2713
3317
|
};
|
|
2714
3318
|
for (let i = 0; i < unique.length - 1; i++) {
|
|
2715
3319
|
const from2 = unique[i];
|
|
@@ -2769,33 +3373,33 @@ function eraserRegion(points, width) {
|
|
|
2769
3373
|
];
|
|
2770
3374
|
}
|
|
2771
3375
|
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] }))];
|
|
2772
|
-
return
|
|
3376
|
+
return _chunkGVB7ZPLZcjs.outlineStroke.call(void 0, line2, { width, cap: "round", join: "round" });
|
|
2773
3377
|
}
|
|
2774
3378
|
function eraseFromFill(path, fillRule, region) {
|
|
2775
|
-
const overlap =
|
|
2776
|
-
if (!
|
|
2777
|
-
const rest =
|
|
3379
|
+
const overlap = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "intersection", [{ path, fillRule }, { path: region }]).path;
|
|
3380
|
+
if (!_chunkGVB7ZPLZcjs.pathToContours.call(void 0, overlap).some((c) => Math.abs(_chunkGVB7ZPLZcjs.contourSignedArea.call(void 0, _chunkGVB7ZPLZcjs.closeContour.call(void 0, c, true))) > 1e-9)) return null;
|
|
3381
|
+
const rest = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "difference", [{ path, fillRule }, { path: region }]).path;
|
|
2778
3382
|
return splitIntoFaces(rest);
|
|
2779
3383
|
}
|
|
2780
3384
|
function eraseFromOutline(sp, region) {
|
|
2781
|
-
const regionSegs =
|
|
3385
|
+
const regionSegs = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, region).flatMap((c) => _chunkGVB7ZPLZcjs.closeContour.call(void 0, c, true));
|
|
2782
3386
|
if (!regionSegs.length) return null;
|
|
2783
|
-
const rb =
|
|
3387
|
+
const rb = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, region);
|
|
2784
3388
|
const count = subpathSegmentCount(sp);
|
|
2785
3389
|
if (!rb || count === 0) return null;
|
|
2786
|
-
const removed = (p) =>
|
|
3390
|
+
const removed = (p) => _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, region, p, "nonzero");
|
|
2787
3391
|
const runs = [];
|
|
2788
3392
|
let cur = [];
|
|
2789
3393
|
let any = false;
|
|
2790
3394
|
for (let i = 0; i < count; i++) {
|
|
2791
3395
|
const seg = subpathSegment(sp, i);
|
|
2792
|
-
const sb =
|
|
3396
|
+
const sb = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, seg);
|
|
2793
3397
|
const ts = [0, 1];
|
|
2794
3398
|
if (!(sb.maxX < rb.minX || sb.minX > rb.maxX || sb.maxY < rb.minY || sb.minY > rb.maxY)) {
|
|
2795
3399
|
for (const r of regionSegs) {
|
|
2796
|
-
const b =
|
|
3400
|
+
const b = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, r);
|
|
2797
3401
|
if (b.maxX < sb.minX || b.minX > sb.maxX || b.maxY < sb.minY || b.minY > sb.maxY) continue;
|
|
2798
|
-
for (const hit of
|
|
3402
|
+
for (const hit of _chunkGVB7ZPLZcjs.segmentIntersections.call(void 0, seg, r)) if (hit.ta > 1e-9 && hit.ta < 1 - 1e-9) ts.push(hit.ta);
|
|
2799
3403
|
}
|
|
2800
3404
|
}
|
|
2801
3405
|
ts.sort((a, b) => a - b);
|
|
@@ -2803,7 +3407,7 @@ function eraseFromOutline(sp, region) {
|
|
|
2803
3407
|
const t0 = ts[k];
|
|
2804
3408
|
const t1 = ts[k + 1];
|
|
2805
3409
|
if (t1 - t0 < 1e-9) continue;
|
|
2806
|
-
if (removed(
|
|
3410
|
+
if (removed(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, (t0 + t1) / 2))) {
|
|
2807
3411
|
any = true;
|
|
2808
3412
|
if (cur.length) runs.push(cur);
|
|
2809
3413
|
cur = [];
|
|
@@ -2822,7 +3426,7 @@ function eraseFromOutline(sp, region) {
|
|
|
2822
3426
|
for (const run of runs) {
|
|
2823
3427
|
const anchors = [];
|
|
2824
3428
|
for (const { seg, t0, t1 } of run) {
|
|
2825
|
-
const c =
|
|
3429
|
+
const c = _chunkGVB7ZPLZcjs.subSegment.call(void 0, subpathSegment(sp, seg), t0, t1);
|
|
2826
3430
|
const line2 = c.length === 2;
|
|
2827
3431
|
const start = c[0];
|
|
2828
3432
|
const end = c[c.length - 1];
|
|
@@ -2939,7 +3543,7 @@ function vectorInkShapeName(shape) {
|
|
|
2939
3543
|
return shape.points.length === 3 ? "triangle" : "polygon";
|
|
2940
3544
|
}
|
|
2941
3545
|
}
|
|
2942
|
-
var
|
|
3546
|
+
var dist3 = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1]);
|
|
2943
3547
|
function bbox(pts) {
|
|
2944
3548
|
if (!pts.length) return [0, 0, 0, 0];
|
|
2945
3549
|
let [x0, y0] = pts[0];
|
|
@@ -2957,7 +3561,7 @@ function segDistance(a, b, p) {
|
|
|
2957
3561
|
const dy = b[1] - a[1];
|
|
2958
3562
|
const len2 = dx * dx + dy * dy;
|
|
2959
3563
|
const t = len2 > 0 ? Math.min(1, Math.max(0, ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / len2)) : 0;
|
|
2960
|
-
return
|
|
3564
|
+
return dist3([a[0] + t * dx, a[1] + t * dy], p);
|
|
2961
3565
|
}
|
|
2962
3566
|
function polygonDistance(c, p) {
|
|
2963
3567
|
let best = Infinity;
|
|
@@ -3019,7 +3623,7 @@ function corners(p, diag) {
|
|
|
3019
3623
|
let far = 0;
|
|
3020
3624
|
let farD = 0;
|
|
3021
3625
|
p.forEach((q, i) => {
|
|
3022
|
-
const d =
|
|
3626
|
+
const d = dist3(start, q);
|
|
3023
3627
|
if (d > farD) {
|
|
3024
3628
|
farD = d;
|
|
3025
3629
|
far = i;
|
|
@@ -3046,7 +3650,7 @@ function corners(p, diag) {
|
|
|
3046
3650
|
}
|
|
3047
3651
|
let short = -1;
|
|
3048
3652
|
for (let j = 0; j < n; j++) {
|
|
3049
|
-
if (
|
|
3653
|
+
if (dist3(ring[j], ring[(j + 1) % n]) < 0.1 * diag) {
|
|
3050
3654
|
short = j;
|
|
3051
3655
|
break;
|
|
3052
3656
|
}
|
|
@@ -3086,8 +3690,8 @@ function recognizeInkShape(points, options = {}) {
|
|
|
3086
3690
|
const diag = Math.hypot(w, h);
|
|
3087
3691
|
if (size < minSize) return null;
|
|
3088
3692
|
let length2 = 0;
|
|
3089
|
-
for (let i = 1; i < p.length; i++) length2 +=
|
|
3090
|
-
const gap =
|
|
3693
|
+
for (let i = 1; i < p.length; i++) length2 += dist3(p[i - 1], p[i]);
|
|
3694
|
+
const gap = dist3(first, last);
|
|
3091
3695
|
if (gap > 0.85 * length2 && gap >= minSize) {
|
|
3092
3696
|
const off = Math.max(...p.map((q) => segDistance(first, last, q)));
|
|
3093
3697
|
if (off <= Math.max(0.06 * gap, 1.5 * minSize / 6)) return { kind: "line", a: first, b: last };
|
|
@@ -3113,7 +3717,14 @@ function recognizeInkShape(points, options = {}) {
|
|
|
3113
3717
|
|
|
3114
3718
|
// src/vector/controller.ts
|
|
3115
3719
|
var DEFAULT_VECTOR_SNAP = { grid: 0, objects: true, guides: true, threshold: 5, angles: VECTOR_CONSTRUCTION_ANGLES };
|
|
3116
|
-
var DEFAULT_VECTOR_PATH_EDIT = {
|
|
3720
|
+
var DEFAULT_VECTOR_PATH_EDIT = {
|
|
3721
|
+
keepShapeOnDelete: true,
|
|
3722
|
+
curvatureMoves: false,
|
|
3723
|
+
pencilSmoothing: 0,
|
|
3724
|
+
recognizeShapes: false,
|
|
3725
|
+
eraserSize: 10,
|
|
3726
|
+
pencilPressure: "pen"
|
|
3727
|
+
};
|
|
3117
3728
|
var VECTOR_PENCIL_STRING_PX = 100;
|
|
3118
3729
|
var VECTOR_STYLE_KEYS = [
|
|
3119
3730
|
"fill",
|
|
@@ -3128,7 +3739,8 @@ var VECTOR_STYLE_KEYS = [
|
|
|
3128
3739
|
"endArrow",
|
|
3129
3740
|
"arrowAlign",
|
|
3130
3741
|
"startArrowScale",
|
|
3131
|
-
"endArrowScale"
|
|
3742
|
+
"endArrowScale",
|
|
3743
|
+
"strokeWidthProfile"
|
|
3132
3744
|
];
|
|
3133
3745
|
var VECTOR_CLIPBOARD_TYPE = "pixerate/vector";
|
|
3134
3746
|
var DEFAULT_DEFAULTS = {
|
|
@@ -3157,7 +3769,7 @@ function getEditablePathIds(state) {
|
|
|
3157
3769
|
}
|
|
3158
3770
|
}
|
|
3159
3771
|
}
|
|
3160
|
-
return [...ids].filter((id) => _optionalChain([findVectorNode, 'call',
|
|
3772
|
+
return [...ids].filter((id) => _optionalChain([findVectorNode, 'call', _62 => _62(state.document.nodes, id), 'optionalAccess', _63 => _63.type]) === "path");
|
|
3161
3773
|
}
|
|
3162
3774
|
function getVisibleAnchors(state) {
|
|
3163
3775
|
const out = [];
|
|
@@ -3172,7 +3784,7 @@ function getVisibleHandles(state) {
|
|
|
3172
3784
|
const seen = /* @__PURE__ */ new Set();
|
|
3173
3785
|
const push = (node, s, i, handle) => {
|
|
3174
3786
|
const sp = node.subpaths[s];
|
|
3175
|
-
const a = _optionalChain([sp, 'optionalAccess',
|
|
3787
|
+
const a = _optionalChain([sp, 'optionalAccess', _64 => _64.anchors, 'access', _65 => _65[i]]);
|
|
3176
3788
|
if (!a || !a[handle]) return;
|
|
3177
3789
|
const key = `${node.id}:${s}:${i}:${handle}`;
|
|
3178
3790
|
if (seen.has(key)) return;
|
|
@@ -3181,8 +3793,8 @@ function getVisibleHandles(state) {
|
|
|
3181
3793
|
};
|
|
3182
3794
|
if (state.tool === "pen" && state.pen) {
|
|
3183
3795
|
const node = findVectorNode(state.document.nodes, state.pen.nodeId);
|
|
3184
|
-
const sp = _optionalChain([node, 'optionalAccess',
|
|
3185
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
3796
|
+
const sp = _optionalChain([node, 'optionalAccess', _66 => _66.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
|
|
3797
|
+
if (_optionalChain([node, 'optionalAccess', _67 => _67.type]) === "path" && sp) {
|
|
3186
3798
|
const last = sp.anchors.length - 1;
|
|
3187
3799
|
push(node, state.pen.subpath, last, "in");
|
|
3188
3800
|
push(node, state.pen.subpath, last, "out");
|
|
@@ -3190,9 +3802,9 @@ function getVisibleHandles(state) {
|
|
|
3190
3802
|
return out;
|
|
3191
3803
|
}
|
|
3192
3804
|
if (state.tool !== "direct") return out;
|
|
3193
|
-
const
|
|
3805
|
+
const editable2 = new Set(getEditablePathIds(state));
|
|
3194
3806
|
for (const ref of state.selectedAnchors) {
|
|
3195
|
-
if (!
|
|
3807
|
+
if (!editable2.has(ref.nodeId)) continue;
|
|
3196
3808
|
const node = findVectorNode(state.document.nodes, ref.nodeId);
|
|
3197
3809
|
const sp = node.subpaths[ref.subpath];
|
|
3198
3810
|
if (!sp) continue;
|
|
@@ -3220,18 +3832,68 @@ function getVectorCornerWidgets(state) {
|
|
|
3220
3832
|
const side = Math.min(c.lu, c.lv);
|
|
3221
3833
|
if (side * zoom < 3 * VECTOR_CORNER_WIDGET_INSET) continue;
|
|
3222
3834
|
const a = node.subpaths[c.subpath].anchors[c.index];
|
|
3223
|
-
const radius = _nullishCoalesce(_optionalChain([a, 'access',
|
|
3835
|
+
const radius = _nullishCoalesce(_optionalChain([a, 'access', _68 => _68.corner, 'optionalAccess', _69 => _69.radius]), () => ( 0));
|
|
3224
3836
|
const drawn = fitCornerRadius(c, radius);
|
|
3225
3837
|
const k = Math.min(Math.max(drawn / c.sin, VECTOR_CORNER_WIDGET_INSET / (zoom * Math.sqrt(1 + c.cos))), side / 2);
|
|
3226
3838
|
const p = applyMatrix(m, cornerBisectorPoint(c, k));
|
|
3227
|
-
out.push({ ref: { nodeId: id, subpath: c.subpath, index: c.index }, x: p.x, y: p.y, radius, drawnRadius: drawn, kind: _nullishCoalesce(_optionalChain([a, 'access',
|
|
3839
|
+
out.push({ ref: { nodeId: id, subpath: c.subpath, index: c.index }, x: p.x, y: p.y, radius, drawnRadius: drawn, kind: _nullishCoalesce(_optionalChain([a, 'access', _70 => _70.corner, 'optionalAccess', _71 => _71.kind]), () => ( "round")), corner: c });
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
return out;
|
|
3843
|
+
}
|
|
3844
|
+
function vectorStrokeWidthGeometry(node) {
|
|
3845
|
+
if (!hasPaint(node.stroke) || !((_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0)) return null;
|
|
3846
|
+
const parts = vectorStrokeParts(subpathsToBezier(node.subpaths), node);
|
|
3847
|
+
return parts.line.length ? { line: parts.line, unit: parts.drawWidth / 2 } : null;
|
|
3848
|
+
}
|
|
3849
|
+
function getVectorWidthHandles(state) {
|
|
3850
|
+
if (state.tool !== "width") return [];
|
|
3851
|
+
const ids = /* @__PURE__ */ new Set();
|
|
3852
|
+
for (const id of state.selection) {
|
|
3853
|
+
const n = findVectorNode(state.document.nodes, id);
|
|
3854
|
+
if (n) for (const p of collectPathNodes(n)) ids.add(p.id);
|
|
3855
|
+
}
|
|
3856
|
+
if (_optionalChain([state, 'access', _72 => _72.hover, 'optionalAccess', _73 => _73.nodeId])) ids.add(state.hover.nodeId);
|
|
3857
|
+
if (_optionalChain([state, 'access', _74 => _74.interaction, 'optionalAccess', _75 => _75.type]) === "width") ids.add(state.interaction.ref.nodeId);
|
|
3858
|
+
if (state.selectedWidthPoint) ids.add(state.selectedWidthPoint.nodeId);
|
|
3859
|
+
const out = [];
|
|
3860
|
+
for (const id of ids) {
|
|
3861
|
+
const node = findVectorNode(state.document.nodes, id);
|
|
3862
|
+
if (_optionalChain([node, 'optionalAccess', _76 => _76.type]) !== "path" || node.visible === false || !_optionalChain([node, 'access', _77 => _77.strokeWidthProfile, 'optionalAccess', _78 => _78.length])) continue;
|
|
3863
|
+
const g = vectorStrokeWidthGeometry(node);
|
|
3864
|
+
if (!g) continue;
|
|
3865
|
+
const profile = sanitizeWidthProfile(node.strokeWidthProfile);
|
|
3866
|
+
const m = _nullishCoalesce(vectorWorldMatrix(state.document.nodes, id), () => ( IDENTITY_MATRIX));
|
|
3867
|
+
const contours = node.subpaths.length;
|
|
3868
|
+
for (let sp = 0; sp < contours; sp++) {
|
|
3869
|
+
profile.forEach((w, index) => {
|
|
3870
|
+
const at2 = strokePositionPoint(g.line, sp, w.t);
|
|
3871
|
+
if (!at2) return;
|
|
3872
|
+
const n = { x: at2.tangent[1], y: -at2.tangent[0] };
|
|
3873
|
+
const c = { x: at2.point[0], y: at2.point[1] };
|
|
3874
|
+
const p = applyMatrix(m, c);
|
|
3875
|
+
const l = applyMatrix(m, { x: c.x + n.x * w.left * g.unit, y: c.y + n.y * w.left * g.unit });
|
|
3876
|
+
const r = applyMatrix(m, { x: c.x - n.x * w.right * g.unit, y: c.y - n.y * w.right * g.unit });
|
|
3877
|
+
const sel = state.selectedWidthPoint;
|
|
3878
|
+
out.push({
|
|
3879
|
+
ref: { nodeId: id, index, subpath: sp },
|
|
3880
|
+
x: p.x,
|
|
3881
|
+
y: p.y,
|
|
3882
|
+
left: l,
|
|
3883
|
+
right: r,
|
|
3884
|
+
t: w.t,
|
|
3885
|
+
leftScale: w.left,
|
|
3886
|
+
rightScale: w.right,
|
|
3887
|
+
selected: !!sel && sel.nodeId === id && sel.index === index
|
|
3888
|
+
});
|
|
3889
|
+
});
|
|
3228
3890
|
}
|
|
3229
3891
|
}
|
|
3230
3892
|
return out;
|
|
3231
3893
|
}
|
|
3232
3894
|
function getAnchor(doc, ref) {
|
|
3233
3895
|
const node = findVectorNode(doc.nodes, ref.nodeId);
|
|
3234
|
-
return _optionalChain([node, 'optionalAccess',
|
|
3896
|
+
return _optionalChain([node, 'optionalAccess', _79 => _79.type]) === "path" ? _optionalChain([node, 'access', _80 => _80.subpaths, 'access', _81 => _81[ref.subpath], 'optionalAccess', _82 => _82.anchors, 'access', _83 => _83[ref.index]]) : void 0;
|
|
3235
3897
|
}
|
|
3236
3898
|
function getAnchorWorld(doc, ref) {
|
|
3237
3899
|
const a = getAnchor(doc, ref);
|
|
@@ -3299,9 +3961,10 @@ var TOOL_LABELS = {
|
|
|
3299
3961
|
line: "Line",
|
|
3300
3962
|
scissors: "Scissors",
|
|
3301
3963
|
knife: "Knife",
|
|
3302
|
-
eraser: "Eraser"
|
|
3964
|
+
eraser: "Eraser",
|
|
3965
|
+
width: "Width"
|
|
3303
3966
|
};
|
|
3304
|
-
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" };
|
|
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" };
|
|
3305
3968
|
function vectorToolLabel(tool) {
|
|
3306
3969
|
return TOOL_LABELS[tool];
|
|
3307
3970
|
}
|
|
@@ -3317,7 +3980,8 @@ var VECTOR_TOOL_SHORTCUTS = {
|
|
|
3317
3980
|
line: "L",
|
|
3318
3981
|
scissors: "C",
|
|
3319
3982
|
knife: "K",
|
|
3320
|
-
eraser: "E"
|
|
3983
|
+
eraser: "E",
|
|
3984
|
+
width: "W"
|
|
3321
3985
|
};
|
|
3322
3986
|
var VECTOR_TOOL_GLYPHS = {
|
|
3323
3987
|
select: "\u2196",
|
|
@@ -3331,7 +3995,8 @@ var VECTOR_TOOL_GLYPHS = {
|
|
|
3331
3995
|
line: "\u2571",
|
|
3332
3996
|
scissors: "\u2702",
|
|
3333
3997
|
knife: "\u27CB",
|
|
3334
|
-
eraser: "\u232B"
|
|
3998
|
+
eraser: "\u232B",
|
|
3999
|
+
width: "\u21F9"
|
|
3335
4000
|
};
|
|
3336
4001
|
var SHAPE_TOOLS = /* @__PURE__ */ new Set(["rect", "ellipse", "polygon", "star", "line"]);
|
|
3337
4002
|
var BOOLEAN_OPS = {
|
|
@@ -3385,35 +4050,36 @@ var VectorEditorController = (_class3 = class {
|
|
|
3385
4050
|
|
|
3386
4051
|
__init9() {this.selection = []}
|
|
3387
4052
|
__init10() {this.anchors = []}
|
|
3388
|
-
__init11() {this.
|
|
3389
|
-
__init12() {this.
|
|
4053
|
+
__init11() {this.widthPoint = null}
|
|
4054
|
+
__init12() {this.editingId = null}
|
|
4055
|
+
__init13() {this.pen = null}
|
|
3390
4056
|
|
|
3391
4057
|
|
|
3392
4058
|
|
|
3393
4059
|
|
|
3394
4060
|
|
|
3395
4061
|
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
4062
|
+
__init14() {this.hover = null}
|
|
4063
|
+
__init15() {this.pointer = null}
|
|
4064
|
+
__init16() {this.drag = null}
|
|
4065
|
+
__init17() {this.interaction = null}
|
|
4066
|
+
__init18() {this.guides = null}
|
|
3401
4067
|
/** Whether the last `snapDrawn` landed on an object (guides may be hidden). */
|
|
3402
|
-
|
|
4068
|
+
__init19() {this.snappedToObject = false}
|
|
3403
4069
|
/** Drawing targets for hovering the pen and shape tools, kept while the document and the excluded path stay the same. */
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
4070
|
+
__init20() {this.hoverTargets = null}
|
|
4071
|
+
__init21() {this.spaceHeld = false}
|
|
4072
|
+
__init22() {this.clipboard = null}
|
|
3407
4073
|
|
|
3408
4074
|
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
4075
|
+
__init23() {this.listeners = /* @__PURE__ */ new Set()}
|
|
4076
|
+
__init24() {this.cleanups = []}
|
|
4077
|
+
__init25() {this.applying = false}
|
|
3412
4078
|
/** Set while a commit records a change that was already applied, so `restore` still reports it. */
|
|
3413
|
-
|
|
3414
|
-
|
|
4079
|
+
__init26() {this.committing = false}
|
|
4080
|
+
__init27() {this.revision = 0}
|
|
3415
4081
|
|
|
3416
|
-
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);
|
|
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);
|
|
3417
4083
|
this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkQKLRAA4Tcjs.HistoryManager)()));
|
|
3418
4084
|
this.doc = options.document ? cloneVectorDocument(options.document) : { width: 800, height: 600, nodes: [] };
|
|
3419
4085
|
this.tool = _nullishCoalesce(options.tool, () => ( "select"));
|
|
@@ -3442,9 +4108,9 @@ var VectorEditorController = (_class3 = class {
|
|
|
3442
4108
|
// State
|
|
3443
4109
|
// -------------------------------------------------------------------------
|
|
3444
4110
|
/** The current snapshot (stable until the next change). */
|
|
3445
|
-
|
|
4111
|
+
__init28() {this.getState = () => this.state}
|
|
3446
4112
|
/** Calls `listener` after every change. Returns an unsubscribe function. */
|
|
3447
|
-
|
|
4113
|
+
__init29() {this.subscribe = (listener) => {
|
|
3448
4114
|
this.listeners.add(listener);
|
|
3449
4115
|
return () => {
|
|
3450
4116
|
this.listeners.delete(listener);
|
|
@@ -3463,6 +4129,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3463
4129
|
tool: this.tool,
|
|
3464
4130
|
selection: this.selection,
|
|
3465
4131
|
selectedAnchors: this.anchors,
|
|
4132
|
+
selectedWidthPoint: this.widthPoint,
|
|
3466
4133
|
editingId: this.editingId,
|
|
3467
4134
|
selectionBounds: this.boundsOf(this.selection),
|
|
3468
4135
|
selectionFrame: this.frameOf(this.selectedRoots()),
|
|
@@ -3487,7 +4154,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3487
4154
|
notify(docChanged = false) {
|
|
3488
4155
|
this.revision++;
|
|
3489
4156
|
this.state = this.computeState();
|
|
3490
|
-
if (docChanged) _optionalChain([this, 'access',
|
|
4157
|
+
if (docChanged) _optionalChain([this, 'access', _84 => _84.onChange, 'optionalCall', _85 => _85(this.doc)]);
|
|
3491
4158
|
const state = this.state;
|
|
3492
4159
|
this.listeners.forEach((listener) => {
|
|
3493
4160
|
try {
|
|
@@ -3517,20 +4184,24 @@ var VectorEditorController = (_class3 = class {
|
|
|
3517
4184
|
return applyMatrix(invertMatrix(this.worldOf(id, doc)), p);
|
|
3518
4185
|
}
|
|
3519
4186
|
cursorFor() {
|
|
3520
|
-
if (_optionalChain([this, 'access',
|
|
3521
|
-
if (_optionalChain([this, 'access',
|
|
3522
|
-
if (_optionalChain([this, 'access',
|
|
4187
|
+
if (_optionalChain([this, 'access', _86 => _86.drag, 'optionalAccess', _87 => _87.kind]) === "pan" || this.spaceHeld) return this.drag ? "grabbing" : "grab";
|
|
4188
|
+
if (_optionalChain([this, 'access', _88 => _88.drag, 'optionalAccess', _89 => _89.kind]) === "rotate") return "grabbing";
|
|
4189
|
+
if (_optionalChain([this, 'access', _90 => _90.drag, 'optionalAccess', _91 => _91.kind]) === "move") return "move";
|
|
3523
4190
|
const h = this.hover;
|
|
3524
4191
|
switch (this.tool) {
|
|
3525
4192
|
case "select":
|
|
3526
|
-
if (_optionalChain([h, 'optionalAccess',
|
|
3527
|
-
return _optionalChain([h, 'optionalAccess',
|
|
4193
|
+
if (_optionalChain([h, 'optionalAccess', _92 => _92.transformHandle])) return vectorResizeCursor(h.transformHandle, _nullishCoalesce(_optionalChain([this, 'access', _93 => _93.frameOf, 'call', _94 => _94(this.selectedRoots()), 'optionalAccess', _95 => _95.angle]), () => ( 0)));
|
|
4194
|
+
return _optionalChain([h, 'optionalAccess', _96 => _96.nodeId]) ? "move" : "default";
|
|
3528
4195
|
case "direct":
|
|
3529
|
-
if (_optionalChain([h, 'optionalAccess',
|
|
3530
|
-
if (_optionalChain([h, 'optionalAccess',
|
|
3531
|
-
return _optionalChain([h, 'optionalAccess',
|
|
4196
|
+
if (_optionalChain([h, 'optionalAccess', _97 => _97.anchor]) || _optionalChain([h, 'optionalAccess', _98 => _98.handle]) || _optionalChain([h, 'optionalAccess', _99 => _99.corner])) return "pointer";
|
|
4197
|
+
if (_optionalChain([h, 'optionalAccess', _100 => _100.segment])) return "copy";
|
|
4198
|
+
return _optionalChain([h, 'optionalAccess', _101 => _101.nodeId]) ? "move" : "default";
|
|
3532
4199
|
case "pen":
|
|
3533
|
-
return _optionalChain([h, 'optionalAccess',
|
|
4200
|
+
return _optionalChain([h, 'optionalAccess', _102 => _102.anchor]) ? "pointer" : "crosshair";
|
|
4201
|
+
case "width":
|
|
4202
|
+
if (_optionalChain([this, 'access', _103 => _103.drag, 'optionalAccess', _104 => _104.kind]) === "width") return this.drag.mode === "move" ? "grabbing" : "ew-resize";
|
|
4203
|
+
if (_optionalChain([h, 'optionalAccess', _105 => _105.widthPoint])) return h.widthPoint.part === "center" ? "grab" : "ew-resize";
|
|
4204
|
+
return _optionalChain([h, 'optionalAccess', _106 => _106.strokeSpot]) ? "copy" : "default";
|
|
3534
4205
|
default:
|
|
3535
4206
|
return "crosshair";
|
|
3536
4207
|
}
|
|
@@ -3550,7 +4221,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3550
4221
|
this.selection = s.selection.filter((id) => this.getNode(id));
|
|
3551
4222
|
this.anchors = s.anchors.filter((r) => getAnchor(this.doc, r));
|
|
3552
4223
|
this.editingId = s.editingId && this.getNode(s.editingId) ? s.editingId : null;
|
|
3553
|
-
this.pen = s.pen && _optionalChain([this, 'access',
|
|
4224
|
+
this.pen = s.pen && _optionalChain([this, 'access', _107 => _107.getNode, 'call', _108 => _108(s.pen.nodeId), 'optionalAccess', _109 => _109.subpaths, 'optionalAccess', _110 => _110[s.pen.subpath]]) ? s.pen : null;
|
|
3554
4225
|
} finally {
|
|
3555
4226
|
this.applying = false;
|
|
3556
4227
|
}
|
|
@@ -3656,6 +4327,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3656
4327
|
this.tool = tool;
|
|
3657
4328
|
this.hover = null;
|
|
3658
4329
|
this.guides = null;
|
|
4330
|
+
this.widthPoint = null;
|
|
3659
4331
|
if (tool !== "direct") {
|
|
3660
4332
|
this.anchors = [];
|
|
3661
4333
|
this.editingId = null;
|
|
@@ -3714,7 +4386,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3714
4386
|
if (res.kind) {
|
|
3715
4387
|
this.snappedToObject = true;
|
|
3716
4388
|
this.setGuides(res);
|
|
3717
|
-
return _optionalChain([leave, 'optionalAccess',
|
|
4389
|
+
return _optionalChain([leave, 'optionalAccess', _111 => _111.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) };
|
|
3718
4390
|
}
|
|
3719
4391
|
}
|
|
3720
4392
|
this.setGuides(null);
|
|
@@ -3732,14 +4404,14 @@ var VectorEditorController = (_class3 = class {
|
|
|
3732
4404
|
/** Where the pointer at `p` would place a point with the pen or a shape tool (and the guides showing why). */
|
|
3733
4405
|
hoverSnap(p, input) {
|
|
3734
4406
|
if (this.tool === "pen") {
|
|
3735
|
-
const sp = this.pen ? _optionalChain([this, 'access',
|
|
3736
|
-
if (this.pen && sp && _optionalChain([this, 'access',
|
|
4407
|
+
const sp = this.pen ? _optionalChain([this, 'access', _112 => _112.getNode, 'call', _113 => _113(this.pen.nodeId), 'optionalAccess', _114 => _114.subpaths, 'access', _115 => _115[this.pen.subpath]]) : void 0;
|
|
4408
|
+
if (this.pen && sp && _optionalChain([this, 'access', _116 => _116.hover, 'optionalAccess', _117 => _117.anchor])) {
|
|
3737
4409
|
this.setGuides(null);
|
|
3738
4410
|
return p;
|
|
3739
4411
|
}
|
|
3740
4412
|
const last = this.pen && sp ? getAnchorWorld(this.doc, { nodeId: this.pen.nodeId, subpath: this.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
|
|
3741
4413
|
const leave = last ? { at: { x: last.x, y: last.y }, constrain: input.shift ? "angle" : null } : null;
|
|
3742
|
-
return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access',
|
|
4414
|
+
return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access', _118 => _118.pen, 'optionalAccess', _119 => _119.nodeId]), () => ( null))));
|
|
3743
4415
|
}
|
|
3744
4416
|
if (SHAPE_TOOLS.has(this.tool)) return this.snapDrawn(p, null, input, () => this.drawingTargets(null));
|
|
3745
4417
|
this.setGuides(null);
|
|
@@ -3887,6 +4559,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3887
4559
|
if (d.fillRule) out.fillRule = d.fillRule;
|
|
3888
4560
|
if (d.strokeAlign && d.strokeAlign !== "center") out.strokeAlign = d.strokeAlign;
|
|
3889
4561
|
for (const key of ["startArrow", "endArrow", "arrowAlign", "startArrowScale", "endArrowScale"]) if (d[key]) out[key] = d[key];
|
|
4562
|
+
if (_optionalChain([d, 'access', _120 => _120.strokeWidthProfile, 'optionalAccess', _121 => _121.length])) out.strokeWidthProfile = d.strokeWidthProfile.map((p) => ({ ...p }));
|
|
3890
4563
|
return out;
|
|
3891
4564
|
}
|
|
3892
4565
|
/** Merges `patch` into a node (paths take style and geometry; groups name / visibility / opacity). */
|
|
@@ -3907,10 +4580,39 @@ var VectorEditorController = (_class3 = class {
|
|
|
3907
4580
|
}
|
|
3908
4581
|
if (!targets.size) return { ok: false, message: "Nothing is selected." };
|
|
3909
4582
|
this.change(_nullishCoalesce(options.label, () => ( "Change Style")), () => {
|
|
3910
|
-
this.setDoc(mapTree(this.doc.nodes, (n) => targets.has(n.id) ?
|
|
4583
|
+
this.setDoc(mapTree(this.doc.nodes, (n) => targets.has(n.id) ? withStyle(n, style) : n));
|
|
3911
4584
|
});
|
|
3912
4585
|
return { ok: true };
|
|
3913
4586
|
}
|
|
4587
|
+
/**
|
|
4588
|
+
* Sets the variable-width profile of the selected (or given) paths: a preset id
|
|
4589
|
+
* (`uniform` removes the profile), points, or a parametric taper / wave. Returns an error for
|
|
4590
|
+
* an unknown preset.
|
|
4591
|
+
*/
|
|
4592
|
+
setWidthProfile(profile, options = {}) {
|
|
4593
|
+
let points;
|
|
4594
|
+
if (profile === null) points = [];
|
|
4595
|
+
else if (typeof profile === "string") {
|
|
4596
|
+
const preset = widthProfilePreset(profile);
|
|
4597
|
+
if (!preset) return { ok: false, message: `There is no width profile "${profile}".` };
|
|
4598
|
+
points = preset;
|
|
4599
|
+
} else if (Array.isArray(profile)) points = sanitizeWidthProfile(profile);
|
|
4600
|
+
else {
|
|
4601
|
+
const p = profile;
|
|
4602
|
+
points = p.taper || p.wave ? generateWidthProfile(p) : [];
|
|
4603
|
+
}
|
|
4604
|
+
this.widthPoint = null;
|
|
4605
|
+
return this.setStyle({ strokeWidthProfile: points.length ? points : null }, _nullishCoalesce(options.ids, () => ( this.selection)), { label: points.length ? "Width Profile" : "Uniform Width" });
|
|
4606
|
+
}
|
|
4607
|
+
/** Removes one width point of a path's profile (the width tool's Delete). */
|
|
4608
|
+
removeWidthPoint(ref) {
|
|
4609
|
+
const node = this.getNode(ref.nodeId);
|
|
4610
|
+
if (_optionalChain([node, 'optionalAccess', _122 => _122.type]) !== "path" || !_optionalChain([node, 'access', _123 => _123.strokeWidthProfile, 'optionalAccess', _124 => _124[ref.index]])) return { ok: false, message: "There is no such width point." };
|
|
4611
|
+
const rest = removeWidthPoints(sanitizeWidthProfile(node.strokeWidthProfile), [ref.index]);
|
|
4612
|
+
this.widthPoint = null;
|
|
4613
|
+
this.change("Delete Width Point", () => this.replaceNode(node.id, withStyle(node, { strokeWidthProfile: rest.length ? rest : null })));
|
|
4614
|
+
return { ok: true };
|
|
4615
|
+
}
|
|
3914
4616
|
/**
|
|
3915
4617
|
* Sets the live corner radius (and optionally the kind) of anchors: `refs`, else the selected
|
|
3916
4618
|
* anchors (direct tool), else every anchor of the `ids` / selected paths. Radius 0 makes the
|
|
@@ -3930,7 +4632,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3930
4632
|
const refs = this.cornerTargets(options);
|
|
3931
4633
|
if (!refs.length) return { ok: false, message: "Nothing is selected." };
|
|
3932
4634
|
this.change("Corner Kind", () => {
|
|
3933
|
-
this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access',
|
|
4635
|
+
this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _125 => _125.corner, 'optionalAccess', _126 => _126.radius]), () => ( 0)), kind));
|
|
3934
4636
|
});
|
|
3935
4637
|
return { ok: true };
|
|
3936
4638
|
}
|
|
@@ -3981,6 +4683,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
3981
4683
|
arrowAlign: _al,
|
|
3982
4684
|
startArrowScale: _ss,
|
|
3983
4685
|
endArrowScale: _es,
|
|
4686
|
+
strokeWidthProfile: _wp,
|
|
3984
4687
|
...rest
|
|
3985
4688
|
} = cloneVectorNode(p);
|
|
3986
4689
|
const id = this.newId();
|
|
@@ -4068,10 +4771,10 @@ var VectorEditorController = (_class3 = class {
|
|
|
4068
4771
|
return this.selection.filter((id) => {
|
|
4069
4772
|
let covered = false;
|
|
4070
4773
|
const loc = locateVectorNode(this.doc.nodes, id);
|
|
4071
|
-
let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess',
|
|
4774
|
+
let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _127 => _127.parent]), () => ( null));
|
|
4072
4775
|
while (parent) {
|
|
4073
4776
|
if (this.selection.includes(parent.id)) covered = true;
|
|
4074
|
-
parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call',
|
|
4777
|
+
parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _128 => _128(this.doc.nodes, parent.id), 'optionalAccess', _129 => _129.parent]), () => ( null));
|
|
4075
4778
|
}
|
|
4076
4779
|
return !covered;
|
|
4077
4780
|
});
|
|
@@ -4254,8 +4957,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
4254
4957
|
if (!ids.length) return null;
|
|
4255
4958
|
const locs = ids.map((id2) => locateVectorNode(this.doc.nodes, id2));
|
|
4256
4959
|
if (locs.some((l) => !l)) return null;
|
|
4257
|
-
const parent = _nullishCoalesce(_optionalChain([locs, 'access',
|
|
4258
|
-
if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access',
|
|
4960
|
+
const parent = _nullishCoalesce(_optionalChain([locs, 'access', _130 => _130[0], 'access', _131 => _131.parent, 'optionalAccess', _132 => _132.id]), () => ( null));
|
|
4961
|
+
if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _133 => _133.parent, 'optionalAccess', _134 => _134.id]), () => ( null))) !== parent)) return null;
|
|
4259
4962
|
const id = this.newId();
|
|
4260
4963
|
this.change("Group", () => {
|
|
4261
4964
|
const set = new Set(ids);
|
|
@@ -4278,11 +4981,11 @@ var VectorEditorController = (_class3 = class {
|
|
|
4278
4981
|
}
|
|
4279
4982
|
/** Replaces selected groups with their children. */
|
|
4280
4983
|
ungroup(options = {}) {
|
|
4281
|
-
const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess',
|
|
4984
|
+
const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _135 => _135.type]) === "group");
|
|
4282
4985
|
if (!groups.length) return { ok: false, message: "Select a group to ungroup." };
|
|
4283
4986
|
const set = new Set(groups.map((g) => g.id));
|
|
4284
4987
|
this.change("Ungroup", () => {
|
|
4285
|
-
const
|
|
4988
|
+
const flatten2 = (list) => {
|
|
4286
4989
|
const out = [];
|
|
4287
4990
|
let changed = false;
|
|
4288
4991
|
for (const n of list) {
|
|
@@ -4294,14 +4997,14 @@ var VectorEditorController = (_class3 = class {
|
|
|
4294
4997
|
...n.children.map((c) => n.transform ? transformVectorNode(c, m) : c).map((c) => opacity !== void 0 && opacity < 1 ? { ...c, opacity: (_nullishCoalesce(c.opacity, () => ( 1))) * opacity } : c)
|
|
4295
4998
|
);
|
|
4296
4999
|
} else if (n.type === "group") {
|
|
4297
|
-
const children =
|
|
5000
|
+
const children = flatten2(n.children);
|
|
4298
5001
|
if (children !== n.children) changed = true;
|
|
4299
5002
|
out.push(children !== n.children ? { ...n, children } : n);
|
|
4300
5003
|
} else out.push(n);
|
|
4301
5004
|
}
|
|
4302
5005
|
return changed ? out : list;
|
|
4303
5006
|
};
|
|
4304
|
-
this.setDoc(
|
|
5007
|
+
this.setDoc(flatten2(this.doc.nodes));
|
|
4305
5008
|
this.selection = groups.flatMap((g) => g.children.map((c) => c.id));
|
|
4306
5009
|
});
|
|
4307
5010
|
return { ok: true };
|
|
@@ -4338,7 +5041,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4338
5041
|
});
|
|
4339
5042
|
const paths = [...new Set(order)].map((id2) => this.getNode(id2));
|
|
4340
5043
|
if (paths.length < 2) return null;
|
|
4341
|
-
const result =
|
|
5044
|
+
const result = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0,
|
|
4342
5045
|
BOOLEAN_OPS[op],
|
|
4343
5046
|
paths.map((p) => ({
|
|
4344
5047
|
path: vectorPathWorldBezier(
|
|
@@ -4388,11 +5091,11 @@ var VectorEditorController = (_class3 = class {
|
|
|
4388
5091
|
/** A document-space path mapped into the parent space of node `id`. */
|
|
4389
5092
|
intoParentSpace(id, path) {
|
|
4390
5093
|
const parent = _nullishCoalesce(vectorParentMatrix(this.doc.nodes, id), () => ( IDENTITY_MATRIX));
|
|
4391
|
-
return isRoot(parent) ? path :
|
|
5094
|
+
return isRoot(parent) ? path : _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, path, invertMatrix(parent));
|
|
4392
5095
|
}
|
|
4393
5096
|
/** Splits selected compound paths into one path per subpath. */
|
|
4394
5097
|
breakApart(options = {}) {
|
|
4395
|
-
const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess',
|
|
5098
|
+
const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _136 => _136.type]) === "path" && n.subpaths.length > 1);
|
|
4396
5099
|
if (!paths.length) return { ok: false, message: "Select a compound path to break apart." };
|
|
4397
5100
|
const created = [];
|
|
4398
5101
|
const set = new Set(paths.map((p) => p.id));
|
|
@@ -4454,7 +5157,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4454
5157
|
/** `doc` with anchor `ref` moved to document point `to` by a Curvature-tool move. */
|
|
4455
5158
|
curvatureMoved(doc, ref, to) {
|
|
4456
5159
|
const node = findVectorNode(doc.nodes, ref.nodeId);
|
|
4457
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5160
|
+
if (_optionalChain([node, 'optionalAccess', _137 => _137.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
|
|
4458
5161
|
const q = this.toLocal(ref.nodeId, to, doc);
|
|
4459
5162
|
const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? curvatureMoveAnchor(sp, ref.index, q) : sp);
|
|
4460
5163
|
const nodes = mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n);
|
|
@@ -4463,7 +5166,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4463
5166
|
/** `doc` with segment `ref` bent through document point `p` at parameter `t`. */
|
|
4464
5167
|
bent(doc, ref, t, p) {
|
|
4465
5168
|
const node = findVectorNode(doc.nodes, ref.nodeId);
|
|
4466
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5169
|
+
if (_optionalChain([node, 'optionalAccess', _138 => _138.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
|
|
4467
5170
|
const q = this.toLocal(ref.nodeId, p, doc);
|
|
4468
5171
|
const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? bendSegment(sp, ref.segment, t, q) : sp);
|
|
4469
5172
|
return { ...doc, nodes: mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n) };
|
|
@@ -4474,7 +5177,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4474
5177
|
*/
|
|
4475
5178
|
bendSegment(ref, to, t = 0.5) {
|
|
4476
5179
|
const node = this.getNode(ref.nodeId);
|
|
4477
|
-
const sp = _optionalChain([node, 'optionalAccess',
|
|
5180
|
+
const sp = _optionalChain([node, 'optionalAccess', _139 => _139.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
|
|
4478
5181
|
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." };
|
|
4479
5182
|
if (node.locked) return { ok: false, message: "The path is locked." };
|
|
4480
5183
|
this.change("Bend Segment", () => {
|
|
@@ -4509,7 +5212,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4509
5212
|
/** Adds an anchor on the nearest segment of `nodeId` to document point `point` (shape unchanged). */
|
|
4510
5213
|
insertAnchorAt(nodeId, point) {
|
|
4511
5214
|
const node = this.getNode(nodeId);
|
|
4512
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5215
|
+
if (_optionalChain([node, 'optionalAccess', _140 => _140.type]) !== "path") return null;
|
|
4513
5216
|
const hit = nearestSegment(node, this.toLocal(nodeId, point));
|
|
4514
5217
|
if (!hit) return null;
|
|
4515
5218
|
const { subpath, index } = insertAnchor(node.subpaths[hit.subpath], hit.segment, hit.t);
|
|
@@ -4553,7 +5256,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4553
5256
|
setClosed(closed, nodeId) {
|
|
4554
5257
|
const targets = nodeId ? (() => {
|
|
4555
5258
|
const n = this.getNode(nodeId);
|
|
4556
|
-
return _optionalChain([n, 'optionalAccess',
|
|
5259
|
+
return _optionalChain([n, 'optionalAccess', _141 => _141.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
|
|
4557
5260
|
})() : this.anchors.map((r) => ({ nodeId: r.nodeId, subpath: r.subpath }));
|
|
4558
5261
|
if (!targets.length) return { ok: false, message: "Select a path or points." };
|
|
4559
5262
|
this.change(closed ? "Close Path" : "Open Path", () => {
|
|
@@ -4571,7 +5274,12 @@ var VectorEditorController = (_class3 = class {
|
|
|
4571
5274
|
const set = new Set(ids.flatMap((id) => this.getNode(id) ? collectPathNodes(this.getNode(id)) : []).map((p) => p.id));
|
|
4572
5275
|
if (!set.size) return { ok: false, message: "Select a path." };
|
|
4573
5276
|
this.change("Reverse Path", () => {
|
|
4574
|
-
this.setDoc(
|
|
5277
|
+
this.setDoc(
|
|
5278
|
+
mapTree(
|
|
5279
|
+
this.doc.nodes,
|
|
5280
|
+
(n) => n.type === "path" && set.has(n.id) ? { ...n, subpaths: n.subpaths.map(reverseSubpath), ..._optionalChain([n, 'access', _142 => _142.strokeWidthProfile, 'optionalAccess', _143 => _143.length]) ? { strokeWidthProfile: reverseWidthProfile(n.strokeWidthProfile) } : {} } : n
|
|
5281
|
+
)
|
|
5282
|
+
);
|
|
4575
5283
|
this.anchors = [];
|
|
4576
5284
|
});
|
|
4577
5285
|
return { ok: true };
|
|
@@ -4652,9 +5360,9 @@ var VectorEditorController = (_class3 = class {
|
|
|
4652
5360
|
const cx = points.reduce((s, p) => s + p.at.x, 0) / points.length;
|
|
4653
5361
|
const cy = points.reduce((s, p) => s + p.at.y, 0) / points.length;
|
|
4654
5362
|
this.change("Average", () => {
|
|
4655
|
-
for (const { ref, at } of points) {
|
|
4656
|
-
const dx = axis === "horizontal" ? 0 : cx -
|
|
4657
|
-
const dy = axis === "vertical" ? 0 : cy -
|
|
5363
|
+
for (const { ref, at: at2 } of points) {
|
|
5364
|
+
const dx = axis === "horizontal" ? 0 : cx - at2.x;
|
|
5365
|
+
const dy = axis === "vertical" ? 0 : cy - at2.y;
|
|
4658
5366
|
if (dx || dy) this.doc = this.movedAnchors(this.doc, [ref], dx, dy);
|
|
4659
5367
|
}
|
|
4660
5368
|
});
|
|
@@ -4707,7 +5415,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4707
5415
|
*/
|
|
4708
5416
|
cutPathAt(nodeId, point) {
|
|
4709
5417
|
const node = this.getNode(nodeId);
|
|
4710
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
5418
|
+
if (_optionalChain([node, 'optionalAccess', _144 => _144.type]) !== "path" || node.locked) return null;
|
|
4711
5419
|
const local = this.toLocal(nodeId, point);
|
|
4712
5420
|
const hit = nearestSegment(node, local);
|
|
4713
5421
|
if (!hit) return null;
|
|
@@ -4738,8 +5446,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
4738
5446
|
const node = this.getNode(id);
|
|
4739
5447
|
if (node.locked) continue;
|
|
4740
5448
|
const ids = this.applyCuts(node, (sp, i) => {
|
|
4741
|
-
const
|
|
4742
|
-
const pieces =
|
|
5449
|
+
const at2 = list.filter((r) => r.subpath === i).map((r) => r.index);
|
|
5450
|
+
const pieces = at2.length ? cutSubpathAt(sp, at2) : null;
|
|
4743
5451
|
return pieces && !(pieces.length === 1 && pieces[0].closed === sp.closed) ? pieces : null;
|
|
4744
5452
|
});
|
|
4745
5453
|
if (ids) created.push(...ids);
|
|
@@ -4757,7 +5465,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4757
5465
|
if (n.visible === false || n.locked || parent && blocked.has(parent.id)) blocked.add(n.id);
|
|
4758
5466
|
});
|
|
4759
5467
|
const visible = (p) => !blocked.has(p.id);
|
|
4760
|
-
if (_optionalChain([ids, 'optionalAccess',
|
|
5468
|
+
if (_optionalChain([ids, 'optionalAccess', _145 => _145.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
|
|
4761
5469
|
const box = polylineBounds(points.map(toPoint2), pad);
|
|
4762
5470
|
if (!box) return [];
|
|
4763
5471
|
const out = [];
|
|
@@ -4813,10 +5521,10 @@ var VectorEditorController = (_class3 = class {
|
|
|
4813
5521
|
const region = eraserRegion(pts, width);
|
|
4814
5522
|
if (!region.length) return [];
|
|
4815
5523
|
const plan = [];
|
|
4816
|
-
const rb =
|
|
5524
|
+
const rb = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, region);
|
|
4817
5525
|
const reach = rb ? [{ x: rb.minX, y: rb.minY }, { x: rb.maxX, y: rb.maxY }] : points;
|
|
4818
5526
|
for (const node of this.strokeTargets(reach, options.ids, 0)) {
|
|
4819
|
-
const local =
|
|
5527
|
+
const local = _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, region, invertMatrix(this.worldOf(node.id)));
|
|
4820
5528
|
const live = node.subpaths.filter((sp) => sp.anchors.length > 1);
|
|
4821
5529
|
if (!live.length) continue;
|
|
4822
5530
|
if (hasPaint(node.fill) && live.every((sp) => sp.closed)) {
|
|
@@ -4843,7 +5551,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4843
5551
|
finishPath() {
|
|
4844
5552
|
if (!this.pen) return;
|
|
4845
5553
|
const node = this.getNode(this.pen.nodeId);
|
|
4846
|
-
const sp = _optionalChain([node, 'optionalAccess',
|
|
5554
|
+
const sp = _optionalChain([node, 'optionalAccess', _146 => _146.subpaths, 'access', _147 => _147[this.pen.subpath]]);
|
|
4847
5555
|
const pen = this.pen;
|
|
4848
5556
|
this.pen = null;
|
|
4849
5557
|
this.pointer = null;
|
|
@@ -4887,19 +5595,19 @@ var VectorEditorController = (_class3 = class {
|
|
|
4887
5595
|
if (trimmed.startsWith("{")) {
|
|
4888
5596
|
try {
|
|
4889
5597
|
const data = JSON.parse(trimmed);
|
|
4890
|
-
if (_optionalChain([data, 'optionalAccess',
|
|
4891
|
-
} catch (
|
|
5598
|
+
if (_optionalChain([data, 'optionalAccess', _148 => _148.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
|
|
5599
|
+
} catch (e3) {
|
|
4892
5600
|
nodes = null;
|
|
4893
5601
|
}
|
|
4894
5602
|
} else if (/<svg[\s>]/i.test(trimmed)) {
|
|
4895
5603
|
try {
|
|
4896
5604
|
nodes = parseVectorSvg(trimmed).nodes;
|
|
4897
|
-
} catch (
|
|
5605
|
+
} catch (e4) {
|
|
4898
5606
|
nodes = null;
|
|
4899
5607
|
}
|
|
4900
5608
|
}
|
|
4901
5609
|
} else nodes = this.clipboard;
|
|
4902
|
-
if (!_optionalChain([nodes, 'optionalAccess',
|
|
5610
|
+
if (!_optionalChain([nodes, 'optionalAccess', _149 => _149.length])) return [];
|
|
4903
5611
|
const offset = _nullishCoalesce(options.offset, () => ( (text && !text.trim().startsWith("{") ? { x: 0, y: 0 } : { x: 10, y: 10 })));
|
|
4904
5612
|
const copies = nodes.map((n) => transformVectorNode(this.freshIds(n), translateMatrix(offset.x, offset.y)));
|
|
4905
5613
|
this.change("Paste", () => {
|
|
@@ -4950,7 +5658,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
4950
5658
|
hitHandle(screen) {
|
|
4951
5659
|
for (const ref of getVisibleHandles(this.view()).reverse()) {
|
|
4952
5660
|
const a = getAnchorWorld(this.doc, ref);
|
|
4953
|
-
const h = _optionalChain([a, 'optionalAccess',
|
|
5661
|
+
const h = _optionalChain([a, 'optionalAccess', _150 => _150[ref.handle]]);
|
|
4954
5662
|
if (!h) continue;
|
|
4955
5663
|
const s = this.documentToScreen(h);
|
|
4956
5664
|
if (Math.hypot(s.x - screen.x, s.y - screen.y) <= this.hitRadius) return ref;
|
|
@@ -5053,10 +5761,131 @@ var VectorEditorController = (_class3 = class {
|
|
|
5053
5761
|
const seg = this.nearestOutline(p);
|
|
5054
5762
|
return seg ? { nodeId: seg.nodeId, segment: seg } : null;
|
|
5055
5763
|
}
|
|
5764
|
+
case "width": {
|
|
5765
|
+
const hit = this.hitWidthHandle(screen);
|
|
5766
|
+
if (hit) return { nodeId: hit.ref.nodeId, widthPoint: hit.ref };
|
|
5767
|
+
const spot = this.strokeSpotAt(p);
|
|
5768
|
+
return spot ? { nodeId: spot.nodeId, strokeSpot: spot } : null;
|
|
5769
|
+
}
|
|
5056
5770
|
default:
|
|
5057
5771
|
return null;
|
|
5058
5772
|
}
|
|
5059
5773
|
}
|
|
5774
|
+
widthView() {
|
|
5775
|
+
return { document: this.doc, selection: this.selection, tool: this.tool, hover: this.hover, interaction: this.interaction, selectedWidthPoint: this.widthPoint };
|
|
5776
|
+
}
|
|
5777
|
+
/** The width point centre or side end under `screen` (width tool). */
|
|
5778
|
+
hitWidthHandle(screen) {
|
|
5779
|
+
let best = null;
|
|
5780
|
+
let bestD = Infinity;
|
|
5781
|
+
for (const h of getVectorWidthHandles(this.widthView())) {
|
|
5782
|
+
for (const [part, q] of [["center", h], ["left", h.left], ["right", h.right]]) {
|
|
5783
|
+
const s = this.documentToScreen(q);
|
|
5784
|
+
const d = Math.hypot(s.x - screen.x, s.y - screen.y);
|
|
5785
|
+
if (d <= this.hitRadius && d < bestD - 1e-9) {
|
|
5786
|
+
best = { ref: { ...h.ref, part } };
|
|
5787
|
+
bestD = d;
|
|
5788
|
+
}
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
return best;
|
|
5792
|
+
}
|
|
5793
|
+
/** The nearest stroked, unlocked visible path whose stroke is under document point `p` (width tool). */
|
|
5794
|
+
strokeSpotAt(p) {
|
|
5795
|
+
let best = null;
|
|
5796
|
+
const tol = this.tolerance();
|
|
5797
|
+
walkVectorNodes(this.doc.nodes, (n) => {
|
|
5798
|
+
if (n.type !== "path" || n.visible === false || n.locked) return;
|
|
5799
|
+
if (hiddenOrLocked(this.doc.nodes, n.id)) return;
|
|
5800
|
+
const g = vectorStrokeWidthGeometry(n);
|
|
5801
|
+
if (!g) return;
|
|
5802
|
+
const m = this.worldOf(n.id);
|
|
5803
|
+
const local = applyMatrix(invertMatrix(m), p);
|
|
5804
|
+
const near2 = nearestStrokePosition(g.line, [local.x, local.y]);
|
|
5805
|
+
if (!near2) return;
|
|
5806
|
+
const profile = strokeWidthProfileOf(n);
|
|
5807
|
+
const w = widthProfileAt(profile, near2.t);
|
|
5808
|
+
const reach = Math.max(near2.side === "left" ? w.left : w.right, 0) * g.unit + tol;
|
|
5809
|
+
if (near2.distance > reach || near2.distance > widthProfileMaxScale(profile) * g.unit + tol) return;
|
|
5810
|
+
if (best && near2.distance >= best.distance) return;
|
|
5811
|
+
const nx = near2.tangent[1];
|
|
5812
|
+
const ny = -near2.tangent[0];
|
|
5813
|
+
const [cx, cy] = near2.point;
|
|
5814
|
+
best = {
|
|
5815
|
+
nodeId: n.id,
|
|
5816
|
+
subpath: near2.contour,
|
|
5817
|
+
t: near2.t,
|
|
5818
|
+
point: applyMatrix(m, { x: cx, y: cy }),
|
|
5819
|
+
left: applyMatrix(m, { x: cx + nx * w.left * g.unit, y: cy + ny * w.left * g.unit }),
|
|
5820
|
+
right: applyMatrix(m, { x: cx - nx * w.right * g.unit, y: cy - ny * w.right * g.unit }),
|
|
5821
|
+
distance: near2.distance
|
|
5822
|
+
};
|
|
5823
|
+
});
|
|
5824
|
+
if (!best) return null;
|
|
5825
|
+
const { distance: _d, ...spot } = best;
|
|
5826
|
+
return spot;
|
|
5827
|
+
}
|
|
5828
|
+
downWidth(screen, p, input) {
|
|
5829
|
+
const hit = this.hitWidthHandle(screen);
|
|
5830
|
+
const spot = hit ? null : this.strokeSpotAt(p);
|
|
5831
|
+
const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _151 => _151.ref, 'access', _152 => _152.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _153 => _153.nodeId])));
|
|
5832
|
+
const node = nodeId ? this.getNode(nodeId) : void 0;
|
|
5833
|
+
const g = _optionalChain([node, 'optionalAccess', _154 => _154.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
|
|
5834
|
+
if (!node || node.type !== "path" || !g) {
|
|
5835
|
+
if (this.widthPoint) {
|
|
5836
|
+
this.widthPoint = null;
|
|
5837
|
+
this.notify();
|
|
5838
|
+
}
|
|
5839
|
+
return;
|
|
5840
|
+
}
|
|
5841
|
+
const before = this.snapshot();
|
|
5842
|
+
const local = this.toLocal(node.id, p);
|
|
5843
|
+
let profile;
|
|
5844
|
+
let ref;
|
|
5845
|
+
let mode = "width";
|
|
5846
|
+
let side = "both";
|
|
5847
|
+
let t;
|
|
5848
|
+
let subpath;
|
|
5849
|
+
if (hit) {
|
|
5850
|
+
profile = sanitizeWidthProfile(node.strokeWidthProfile);
|
|
5851
|
+
ref = { nodeId: node.id, index: hit.ref.index, subpath: hit.ref.subpath };
|
|
5852
|
+
t = _nullishCoalesce(_optionalChain([profile, 'access', _155 => _155[ref.index], 'optionalAccess', _156 => _156.t]), () => ( 0));
|
|
5853
|
+
subpath = hit.ref.subpath;
|
|
5854
|
+
if (hit.ref.part === "center") mode = "move";
|
|
5855
|
+
else if (input.alt) side = hit.ref.part;
|
|
5856
|
+
} else {
|
|
5857
|
+
const near2 = nearestStrokePosition(g.line, [local.x, local.y]);
|
|
5858
|
+
const inserted = insertWidthPoint(strokeWidthProfileOf(node), near2.t);
|
|
5859
|
+
profile = inserted.points;
|
|
5860
|
+
subpath = near2.contour;
|
|
5861
|
+
t = near2.t;
|
|
5862
|
+
ref = { nodeId: node.id, index: inserted.index, subpath };
|
|
5863
|
+
if (input.alt) side = near2.side;
|
|
5864
|
+
}
|
|
5865
|
+
const at2 = strokePositionPoint(g.line, subpath, t);
|
|
5866
|
+
if (!at2) return;
|
|
5867
|
+
const base = { ...this.doc, nodes: mapTree(this.doc.nodes, (n) => n.id === node.id ? { ...n, strokeWidthProfile: profile } : n) };
|
|
5868
|
+
this.doc = base;
|
|
5869
|
+
this.widthPoint = { nodeId: node.id, index: ref.index, subpath };
|
|
5870
|
+
this.drag = {
|
|
5871
|
+
kind: "width",
|
|
5872
|
+
ref,
|
|
5873
|
+
mode,
|
|
5874
|
+
side,
|
|
5875
|
+
origin: { x: at2.point[0], y: at2.point[1] },
|
|
5876
|
+
normal: { x: at2.tangent[1], y: -at2.tangent[0] },
|
|
5877
|
+
unit: g.unit,
|
|
5878
|
+
profile,
|
|
5879
|
+
before,
|
|
5880
|
+
base,
|
|
5881
|
+
start: p,
|
|
5882
|
+
moved: false,
|
|
5883
|
+
created: !hit
|
|
5884
|
+
};
|
|
5885
|
+
const w = profile[ref.index];
|
|
5886
|
+
this.interaction = { type: "width", ref, mode, width: (w.left + w.right) * g.unit };
|
|
5887
|
+
this.notify(!hit);
|
|
5888
|
+
}
|
|
5060
5889
|
/** The nearest outline point of any visible, unlocked path within the pick distance of document point `p`. */
|
|
5061
5890
|
nearestOutline(p) {
|
|
5062
5891
|
let best = null;
|
|
@@ -5104,7 +5933,9 @@ var VectorEditorController = (_class3 = class {
|
|
|
5104
5933
|
case "pen":
|
|
5105
5934
|
return this.downPen(screen, p, input);
|
|
5106
5935
|
case "pencil":
|
|
5107
|
-
return this.downPencil(p);
|
|
5936
|
+
return this.downPencil(p, input);
|
|
5937
|
+
case "width":
|
|
5938
|
+
return this.downWidth(screen, p, input);
|
|
5108
5939
|
case "scissors": {
|
|
5109
5940
|
const seg = this.nearestOutline(p);
|
|
5110
5941
|
if (seg) this.cutPathAt(seg.nodeId, seg.point);
|
|
@@ -5240,7 +6071,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5240
6071
|
}
|
|
5241
6072
|
downPen(screen, p, input) {
|
|
5242
6073
|
const before = this.snapshot();
|
|
5243
|
-
const sp = this.pen ? _optionalChain([this, 'access',
|
|
6074
|
+
const sp = this.pen ? _optionalChain([this, 'access', _157 => _157.getNode, 'call', _158 => _158(this.pen.nodeId), 'optionalAccess', _159 => _159.subpaths, 'access', _160 => _160[this.pen.subpath]]) : void 0;
|
|
5244
6075
|
if (this.pen && sp) {
|
|
5245
6076
|
const pen = this.pen;
|
|
5246
6077
|
const first = { nodeId: pen.nodeId, subpath: pen.subpath, index: 0 };
|
|
@@ -5297,7 +6128,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5297
6128
|
this.interaction = { type: "pen", nodeId: node.id };
|
|
5298
6129
|
this.notify(true);
|
|
5299
6130
|
}
|
|
5300
|
-
downPencil(p) {
|
|
6131
|
+
downPencil(p, input = {}) {
|
|
5301
6132
|
const before = this.snapshot();
|
|
5302
6133
|
const node = {
|
|
5303
6134
|
id: this.newId(),
|
|
@@ -5311,7 +6142,11 @@ var VectorEditorController = (_class3 = class {
|
|
|
5311
6142
|
this.setDoc([...this.doc.nodes, node]);
|
|
5312
6143
|
const lazy = new LazyMouse(this.editing.pencilSmoothing * VECTOR_PENCIL_STRING_PX / this.viewport.zoom);
|
|
5313
6144
|
lazy.push([p.x, p.y]);
|
|
5314
|
-
|
|
6145
|
+
const mode = this.editing.pencilPressure;
|
|
6146
|
+
const hasPressure = typeof input.pressure === "number" && Number.isFinite(input.pressure);
|
|
6147
|
+
const record = hasPressure && (mode === "all" || mode === "pen" && input.pointerType === "pen");
|
|
6148
|
+
const pressure = hasPressure ? input.pressure : 0.5;
|
|
6149
|
+
this.drag = { kind: "pencil", nodeId: node.id, points: [[p.x, p.y]], before, lazy, pressures: record ? [pressure] : null, pressure };
|
|
5315
6150
|
this.interaction = { type: "draw", tool: "pencil", nodeId: node.id, bounds: { x: p.x, y: p.y, width: 0, height: 0 } };
|
|
5316
6151
|
this.notify(true);
|
|
5317
6152
|
}
|
|
@@ -5491,7 +6326,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5491
6326
|
}
|
|
5492
6327
|
case "shape": {
|
|
5493
6328
|
const node = this.getNode(drag.nodeId);
|
|
5494
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
6329
|
+
if (_optionalChain([node, 'optionalAccess', _161 => _161.type]) !== "path") return;
|
|
5495
6330
|
const leave = { at: drag.start, constrain: input.shift ? drag.tool === "line" ? "angle" : "square" : null, curves: false };
|
|
5496
6331
|
let end = this.snapDrawn(p, leave, input, () => drag.targets ??= this.drawingTargets(null));
|
|
5497
6332
|
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);
|
|
@@ -5520,19 +6355,43 @@ var VectorEditorController = (_class3 = class {
|
|
|
5520
6355
|
this.notify(true);
|
|
5521
6356
|
return;
|
|
5522
6357
|
}
|
|
6358
|
+
case "width": {
|
|
6359
|
+
if (!drag.moved && Math.hypot(p.x - drag.start.x, p.y - drag.start.y) * this.viewport.zoom < 2) return;
|
|
6360
|
+
drag.moved = true;
|
|
6361
|
+
const node = findVectorNode(drag.base.nodes, drag.ref.nodeId);
|
|
6362
|
+
const local = this.toLocal(node.id, p, drag.base);
|
|
6363
|
+
let profile;
|
|
6364
|
+
if (drag.mode === "move") {
|
|
6365
|
+
const g = vectorStrokeWidthGeometry(node);
|
|
6366
|
+
const near2 = g ? nearestStrokePosition(g.line, [local.x, local.y], drag.ref.subpath) : null;
|
|
6367
|
+
if (!near2) return;
|
|
6368
|
+
profile = setWidthPoint(drag.profile, drag.ref.index, { t: near2.t });
|
|
6369
|
+
} else {
|
|
6370
|
+
const off = ((local.x - drag.origin.x) * drag.normal.x + (local.y - drag.origin.y) * drag.normal.y) / drag.unit;
|
|
6371
|
+
const patch = drag.side === "both" ? { left: Math.abs(off), right: Math.abs(off) } : drag.side === "left" ? { left: Math.max(0, off) } : { right: Math.max(0, -off) };
|
|
6372
|
+
profile = setWidthPoint(drag.profile, drag.ref.index, patch);
|
|
6373
|
+
}
|
|
6374
|
+
this.doc = { ...drag.base, nodes: mapTree(drag.base.nodes, (n) => n.id === node.id ? { ...n, strokeWidthProfile: profile } : n) };
|
|
6375
|
+
const w = profile[drag.ref.index];
|
|
6376
|
+
this.interaction = { type: "width", ref: drag.ref, mode: drag.mode, width: (w.left + w.right) * drag.unit };
|
|
6377
|
+
this.notify(true);
|
|
6378
|
+
return;
|
|
6379
|
+
}
|
|
5523
6380
|
case "pencil": {
|
|
5524
6381
|
const last = drag.points[drag.points.length - 1];
|
|
5525
6382
|
let moved = false;
|
|
6383
|
+
if (typeof input.pressure === "number" && Number.isFinite(input.pressure)) drag.pressure = input.pressure;
|
|
5526
6384
|
for (const q of drag.lazy.push([p.x, p.y])) {
|
|
5527
6385
|
if (Math.hypot(q[0] - last[0], q[1] - last[1]) * this.viewport.zoom < 1.5) continue;
|
|
5528
6386
|
drag.points.push(q);
|
|
6387
|
+
_optionalChain([drag, 'access', _162 => _162.pressures, 'optionalAccess', _163 => _163.push, 'call', _164 => _164(drag.pressure)]);
|
|
5529
6388
|
moved = true;
|
|
5530
6389
|
}
|
|
5531
6390
|
const string = drag.lazy.string();
|
|
5532
6391
|
const node = this.getNode(drag.nodeId);
|
|
5533
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
6392
|
+
if (_optionalChain([node, 'optionalAccess', _165 => _165.type]) !== "path") return;
|
|
5534
6393
|
if (!moved) {
|
|
5535
|
-
if (string && _optionalChain([this, 'access',
|
|
6394
|
+
if (string && _optionalChain([this, 'access', _166 => _166.interaction, 'optionalAccess', _167 => _167.type]) === "draw") {
|
|
5536
6395
|
this.interaction = { ...this.interaction, string: [{ x: string[0][0], y: string[0][1] }, { x: string[1][0], y: string[1][1] }] };
|
|
5537
6396
|
this.notify();
|
|
5538
6397
|
}
|
|
@@ -5568,8 +6427,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
5568
6427
|
}
|
|
5569
6428
|
this.setGuides(res);
|
|
5570
6429
|
return {
|
|
5571
|
-
dx: _optionalChain([res, 'optionalAccess',
|
|
5572
|
-
dy: _optionalChain([res, 'optionalAccess',
|
|
6430
|
+
dx: _optionalChain([res, 'optionalAccess', _168 => _168.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
|
|
6431
|
+
dy: _optionalChain([res, 'optionalAccess', _169 => _169.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
|
|
5573
6432
|
};
|
|
5574
6433
|
}
|
|
5575
6434
|
/** The anchor a point drag snaps by, where it started: the grabbed one, else the moving one nearest the press. */
|
|
@@ -5606,7 +6465,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5606
6465
|
}
|
|
5607
6466
|
/** Primary button released. */
|
|
5608
6467
|
pointerUp(screen, input = {}) {
|
|
5609
|
-
if (screen && this.drag && this.drag.kind !== "pan") this.pointerMove(screen, input);
|
|
6468
|
+
if (screen && this.drag && this.drag.kind !== "pan") this.pointerMove(screen, { ...input, pressure: void 0 });
|
|
5610
6469
|
const drag = this.drag;
|
|
5611
6470
|
this.drag = null;
|
|
5612
6471
|
this.interaction = null;
|
|
@@ -5648,7 +6507,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5648
6507
|
if (drag.moved) return this.commit("Corner Radius", drag.before);
|
|
5649
6508
|
if (drag.alt) {
|
|
5650
6509
|
const kind = nextVectorCornerKind(drag.widget.kind);
|
|
5651
|
-
this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access',
|
|
6510
|
+
this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _170 => _170.corner, 'optionalAccess', _171 => _171.radius]), () => ( 0)), kind));
|
|
5652
6511
|
return this.commit("Corner Kind", drag.before);
|
|
5653
6512
|
}
|
|
5654
6513
|
const ref = drag.widget.ref;
|
|
@@ -5658,6 +6517,15 @@ var VectorEditorController = (_class3 = class {
|
|
|
5658
6517
|
this.notify();
|
|
5659
6518
|
return;
|
|
5660
6519
|
}
|
|
6520
|
+
case "width": {
|
|
6521
|
+
if (drag.moved) return this.commit(drag.mode === "move" ? "Move Width Point" : "Width Point", drag.before);
|
|
6522
|
+
if (drag.created) {
|
|
6523
|
+
this.doc = drag.before.doc;
|
|
6524
|
+
this.widthPoint = null;
|
|
6525
|
+
this.notify(true);
|
|
6526
|
+
} else this.notify();
|
|
6527
|
+
return;
|
|
6528
|
+
}
|
|
5661
6529
|
case "stroke": {
|
|
5662
6530
|
this.notify();
|
|
5663
6531
|
if (drag.tool === "knife") this.knife(drag.points);
|
|
@@ -5683,19 +6551,22 @@ var VectorEditorController = (_class3 = class {
|
|
|
5683
6551
|
}
|
|
5684
6552
|
case "pencil": {
|
|
5685
6553
|
const node = this.getNode(drag.nodeId);
|
|
5686
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
6554
|
+
if (_optionalChain([node, 'optionalAccess', _172 => _172.type]) !== "path" || drag.points.length < 2) {
|
|
5687
6555
|
this.doc = drag.before.doc;
|
|
5688
6556
|
this.notify(true);
|
|
5689
6557
|
return;
|
|
5690
6558
|
}
|
|
5691
|
-
for (const q of drag.lazy.finish())
|
|
6559
|
+
for (const q of drag.lazy.finish()) {
|
|
6560
|
+
drag.points.push(q);
|
|
6561
|
+
_optionalChain([drag, 'access', _173 => _173.pressures, 'optionalAccess', _174 => _174.push, 'call', _175 => _175(drag.pressure)]);
|
|
6562
|
+
}
|
|
5692
6563
|
const shape = this.editing.recognizeShapes ? recognizeInkShape(drag.points, { minSize: 6 / this.viewport.zoom }) : null;
|
|
5693
6564
|
if (shape) {
|
|
5694
6565
|
this.replaceNode(drag.nodeId, { ...node, name: inkShapeLabel(shape), subpaths: [inkShapeSubpath(shape)] });
|
|
5695
6566
|
this.selection = [drag.nodeId];
|
|
5696
6567
|
return this.commit(`Draw ${inkShapeLabel(shape)}`, drag.before);
|
|
5697
6568
|
}
|
|
5698
|
-
const fitted =
|
|
6569
|
+
const fitted = _chunkGVB7ZPLZcjs.fitCubics.call(void 0, drag.points, 1.5 / this.viewport.zoom, { cornerAngleDeg: 60 });
|
|
5699
6570
|
const anchors = [];
|
|
5700
6571
|
for (const c of fitted) {
|
|
5701
6572
|
if (!anchors.length) anchors.push({ x: c.p0[0], y: c.p0[1] });
|
|
@@ -5703,7 +6574,8 @@ var VectorEditorController = (_class3 = class {
|
|
|
5703
6574
|
anchors.push({ x: c.p3[0], y: c.p3[1], in: { x: c.p2[0], y: c.p2[1] } });
|
|
5704
6575
|
}
|
|
5705
6576
|
const subpaths = anchors.length > 1 ? bezierToSubpaths(subpathsToBezier([{ anchors, closed: false }])) : node.subpaths;
|
|
5706
|
-
|
|
6577
|
+
const profile = drag.pressures ? pencilPressureProfile(drag.points, drag.pressures) : [];
|
|
6578
|
+
this.replaceNode(drag.nodeId, { ...node, subpaths, ...profile.length ? { strokeWidthProfile: profile } : {} });
|
|
5707
6579
|
this.selection = [drag.nodeId];
|
|
5708
6580
|
return this.commit("Draw", drag.before);
|
|
5709
6581
|
}
|
|
@@ -5757,7 +6629,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5757
6629
|
this.convertAnchors(a.in || a.out ? "corner" : "smooth", [anchor]);
|
|
5758
6630
|
return;
|
|
5759
6631
|
}
|
|
5760
|
-
const id = _nullishCoalesce(_optionalChain([this, 'access',
|
|
6632
|
+
const id = _nullishCoalesce(_optionalChain([this, 'access', _176 => _176.hover, 'optionalAccess', _177 => _177.segment, 'optionalAccess', _178 => _178.nodeId]), () => ( this.editingId));
|
|
5761
6633
|
if (id) {
|
|
5762
6634
|
const node = this.getNode(id);
|
|
5763
6635
|
const seg = node ? nearestSegment(node, this.toLocal(id, p)) : null;
|
|
@@ -5825,7 +6697,10 @@ var VectorEditorController = (_class3 = class {
|
|
|
5825
6697
|
switch (key) {
|
|
5826
6698
|
case "Escape":
|
|
5827
6699
|
if (this.drag) this.cancelDrag();
|
|
5828
|
-
else if (this.
|
|
6700
|
+
else if (this.tool === "width" && this.widthPoint) {
|
|
6701
|
+
this.widthPoint = null;
|
|
6702
|
+
this.notify();
|
|
6703
|
+
} else if (this.pen) this.finishPath();
|
|
5829
6704
|
else if (this.tool === "direct" && this.anchors.length) {
|
|
5830
6705
|
this.anchors = [];
|
|
5831
6706
|
this.notify();
|
|
@@ -5837,7 +6712,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5837
6712
|
this.finishPath();
|
|
5838
6713
|
return true;
|
|
5839
6714
|
}
|
|
5840
|
-
if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access',
|
|
6715
|
+
if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _179 => _179.getNode, 'call', _180 => _180(this.selection[0]), 'optionalAccess', _181 => _181.type]) === "path") {
|
|
5841
6716
|
this.tool = "direct";
|
|
5842
6717
|
this.editingId = this.selection[0];
|
|
5843
6718
|
this.notify();
|
|
@@ -5846,6 +6721,7 @@ var VectorEditorController = (_class3 = class {
|
|
|
5846
6721
|
return false;
|
|
5847
6722
|
case "Delete":
|
|
5848
6723
|
case "Backspace":
|
|
6724
|
+
if (this.tool === "width" && this.widthPoint) return this.removeWidthPoint(this.widthPoint).ok;
|
|
5849
6725
|
if (this.pen) {
|
|
5850
6726
|
const node = this.getNode(this.pen.nodeId);
|
|
5851
6727
|
const sp = node.subpaths[this.pen.subpath];
|
|
@@ -5927,6 +6803,31 @@ function scaleFor(handle, b, p, mods = {}) {
|
|
|
5927
6803
|
}
|
|
5928
6804
|
return { sx, sy, origin };
|
|
5929
6805
|
}
|
|
6806
|
+
function withStyle(node, style) {
|
|
6807
|
+
const next = { ...node, ...style };
|
|
6808
|
+
if ("strokeWidthProfile" in style) {
|
|
6809
|
+
const p = style.strokeWidthProfile ? sanitizeWidthProfile(style.strokeWidthProfile) : [];
|
|
6810
|
+
if (p.length) next.strokeWidthProfile = p;
|
|
6811
|
+
else delete next.strokeWidthProfile;
|
|
6812
|
+
}
|
|
6813
|
+
return next;
|
|
6814
|
+
}
|
|
6815
|
+
function hiddenOrLocked(nodes, id) {
|
|
6816
|
+
const loc = locateVectorNode(nodes, id);
|
|
6817
|
+
if (!loc) return false;
|
|
6818
|
+
const n = loc.list[loc.index];
|
|
6819
|
+
if (n.locked || n.visible === false) return true;
|
|
6820
|
+
return loc.parent ? hiddenOrLocked(nodes, loc.parent.id) : false;
|
|
6821
|
+
}
|
|
6822
|
+
function pencilPressureProfile(points, pressures) {
|
|
6823
|
+
const n = Math.min(points.length, pressures.length);
|
|
6824
|
+
if (n < 2) return [];
|
|
6825
|
+
const s = [0];
|
|
6826
|
+
for (let i = 1; i < n; i++) s.push(s[i - 1] + Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]));
|
|
6827
|
+
const total = s[n - 1];
|
|
6828
|
+
if (!(total > 0)) return [];
|
|
6829
|
+
return pressureWidthProfile(s.map((d, i) => ({ t: d / total, pressure: pressures[i] })));
|
|
6830
|
+
}
|
|
5930
6831
|
|
|
5931
6832
|
// src/vector/render.ts
|
|
5932
6833
|
var fmt = (n) => Math.round(n * 100) / 100;
|
|
@@ -5953,7 +6854,7 @@ function renderNode(node, defs, idPrefix) {
|
|
|
5953
6854
|
strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)),
|
|
5954
6855
|
...node.strokeLinecap ? { strokeLinecap: node.strokeLinecap } : {},
|
|
5955
6856
|
...node.strokeLinejoin ? { strokeLinejoin: node.strokeLinejoin } : {},
|
|
5956
|
-
..._optionalChain([node, 'access',
|
|
6857
|
+
..._optionalChain([node, 'access', _182 => _182.strokeDasharray, 'optionalAccess', _183 => _183.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
|
|
5957
6858
|
fillRule: _nullishCoalesce(node.fillRule, () => ( "nonzero")),
|
|
5958
6859
|
opacity: _nullishCoalesce(node.opacity, () => ( 1))
|
|
5959
6860
|
};
|
|
@@ -5977,7 +6878,7 @@ function screenOutline(state, node) {
|
|
|
5977
6878
|
const v2 = state.viewport;
|
|
5978
6879
|
const view = [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y];
|
|
5979
6880
|
const parent = _nullishCoalesce(vectorParentMatrix(state.document.nodes, node.id), () => ( IDENTITY_MATRIX));
|
|
5980
|
-
return collectWithMatrix(node, parent).map(({ path, parent: m }) =>
|
|
6881
|
+
return collectWithMatrix(node, parent).map(({ path, parent: m }) => _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, vectorPathWorldBezier(path, m), view), { precision: 2 })).join(" ");
|
|
5981
6882
|
}
|
|
5982
6883
|
function collectWithMatrix(node, parent) {
|
|
5983
6884
|
if (node.type === "path") return [{ path: node, parent }];
|
|
@@ -6002,9 +6903,9 @@ function getVectorOverlayRenderData(state) {
|
|
|
6002
6903
|
};
|
|
6003
6904
|
for (const id of state.selection) outline(id, true);
|
|
6004
6905
|
if (state.editingId) outline(state.editingId, true);
|
|
6005
|
-
if (_optionalChain([state, 'access',
|
|
6906
|
+
if (_optionalChain([state, 'access', _184 => _184.hover, 'optionalAccess', _185 => _185.nodeId]) && !state.interaction) outline(state.hover.nodeId, false);
|
|
6006
6907
|
let selectionBox = null;
|
|
6007
|
-
if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access',
|
|
6908
|
+
if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _186 => _186.interaction, 'optionalAccess', _187 => _187.type]) !== "marquee") {
|
|
6008
6909
|
const g = getVectorSelectionBoxGeometry(state.selectionFrame, state.viewport);
|
|
6009
6910
|
selectionBox = { ...g.box, angle: g.angle, transform: g.transform, corners: g.corners, handles: g.handles };
|
|
6010
6911
|
}
|
|
@@ -6014,9 +6915,9 @@ function getVectorOverlayRenderData(state) {
|
|
|
6014
6915
|
const a = getAnchorWorld(doc, ref);
|
|
6015
6916
|
const s = toScreen(state, a);
|
|
6016
6917
|
const closes = !!state.pen && state.pen.nodeId === ref.nodeId && state.pen.subpath === ref.subpath && ref.index === 0;
|
|
6017
|
-
return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access',
|
|
6918
|
+
return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access', _188 => _188.hover, 'optionalAccess', _189 => _189.anchor]), ref), closes };
|
|
6018
6919
|
});
|
|
6019
|
-
if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access',
|
|
6920
|
+
if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _190 => _190.hover, 'optionalAccess', _191 => _191.anchor])) {
|
|
6020
6921
|
const a = getAnchorWorld(doc, state.hover.anchor);
|
|
6021
6922
|
if (a) {
|
|
6022
6923
|
const s = toScreen(state, a);
|
|
@@ -6025,15 +6926,15 @@ function getVectorOverlayRenderData(state) {
|
|
|
6025
6926
|
}
|
|
6026
6927
|
const handles = getVisibleHandles(state).flatMap((ref) => {
|
|
6027
6928
|
const a = getAnchorWorld(doc, ref);
|
|
6028
|
-
const h = _optionalChain([a, 'optionalAccess',
|
|
6929
|
+
const h = _optionalChain([a, 'optionalAccess', _192 => _192[ref.handle]]);
|
|
6029
6930
|
if (!a || !h) return [];
|
|
6030
6931
|
const s = toScreen(state, h);
|
|
6031
6932
|
const sa = toScreen(state, a);
|
|
6032
|
-
const hovered = !!_optionalChain([state, 'access',
|
|
6933
|
+
const hovered = !!_optionalChain([state, 'access', _193 => _193.hover, 'optionalAccess', _194 => _194.handle]) && sameAnchor(state.hover.handle, ref) && state.hover.handle.handle === ref.handle;
|
|
6033
6934
|
return [{ ref, x: s.x, y: s.y, anchorX: sa.x, anchorY: sa.y, hovered }];
|
|
6034
6935
|
});
|
|
6035
6936
|
let marquee = null;
|
|
6036
|
-
if (_optionalChain([state, 'access',
|
|
6937
|
+
if (_optionalChain([state, 'access', _195 => _195.interaction, 'optionalAccess', _196 => _196.type]) === "marquee") {
|
|
6037
6938
|
const b = state.interaction.bounds;
|
|
6038
6939
|
const tl = toScreen(state, b);
|
|
6039
6940
|
marquee = { x: tl.x, y: tl.y, width: b.width * z, height: b.height * z };
|
|
@@ -6041,7 +6942,7 @@ function getVectorOverlayRenderData(state) {
|
|
|
6041
6942
|
let penPreview = null;
|
|
6042
6943
|
if (state.tool === "pen" && state.pen && state.pointer && !state.interaction) {
|
|
6043
6944
|
const node = findVectorNode(doc.nodes, state.pen.nodeId);
|
|
6044
|
-
const sp = _optionalChain([node, 'optionalAccess',
|
|
6945
|
+
const sp = _optionalChain([node, 'optionalAccess', _197 => _197.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
|
|
6045
6946
|
const last = sp ? getAnchorWorld(doc, { nodeId: state.pen.nodeId, subpath: state.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
|
|
6046
6947
|
if (last) {
|
|
6047
6948
|
const a = toScreen(state, last);
|
|
@@ -6054,9 +6955,9 @@ function getVectorOverlayRenderData(state) {
|
|
|
6054
6955
|
const artboard = { x: origin.x, y: origin.y, width: doc.width * z, height: doc.height * z };
|
|
6055
6956
|
let status = null;
|
|
6056
6957
|
const it = state.interaction;
|
|
6057
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
6058
|
-
else if (_optionalChain([it, 'optionalAccess',
|
|
6059
|
-
else if (_optionalChain([it, 'optionalAccess',
|
|
6958
|
+
if (_optionalChain([it, 'optionalAccess', _198 => _198.type]) === "rotate") status = `${Math.round(it.angle)}\xB0`;
|
|
6959
|
+
else if (_optionalChain([it, 'optionalAccess', _199 => _199.type]) === "move" || _optionalChain([it, 'optionalAccess', _200 => _200.type]) === "anchors") status = `\u0394 ${fmt(it.dx)}, ${fmt(it.dy)}`;
|
|
6960
|
+
else if (_optionalChain([it, 'optionalAccess', _201 => _201.type]) === "scale" || _optionalChain([it, 'optionalAccess', _202 => _202.type]) === "draw") {
|
|
6060
6961
|
const b = it.type === "draw" ? findVectorNode(doc.nodes, it.nodeId) ? vectorNodeBounds(findVectorNode(doc.nodes, it.nodeId)) : null : state.selectionFrame;
|
|
6061
6962
|
if (b) status = `W ${fmt(b.width)} \xD7 H ${fmt(b.height)}`;
|
|
6062
6963
|
}
|
|
@@ -6073,25 +6974,39 @@ function getVectorOverlayRenderData(state) {
|
|
|
6073
6974
|
}
|
|
6074
6975
|
}
|
|
6075
6976
|
let toolStroke = null;
|
|
6076
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
6977
|
+
if (_optionalChain([it, 'optionalAccess', _203 => _203.type]) === "stroke") {
|
|
6077
6978
|
const pts = it.points.map((q) => toScreen(state, q));
|
|
6078
6979
|
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)}` : "");
|
|
6079
6980
|
toolStroke = { tool: it.tool, d, width: fmt(it.width * z) };
|
|
6080
6981
|
}
|
|
6081
6982
|
let pencilString = null;
|
|
6082
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
6983
|
+
if (_optionalChain([it, 'optionalAccess', _204 => _204.type]) === "draw" && it.string) {
|
|
6083
6984
|
const a = toScreen(state, it.string[0]);
|
|
6084
6985
|
const b = toScreen(state, it.string[1]);
|
|
6085
6986
|
pencilString = { x1: fmt(a.x), y1: fmt(a.y), x2: fmt(b.x), y2: fmt(b.y) };
|
|
6086
6987
|
}
|
|
6087
|
-
const dragged = _optionalChain([it, 'optionalAccess',
|
|
6988
|
+
const dragged = _optionalChain([it, 'optionalAccess', _205 => _205.type]) === "corner" ? it.ref : null;
|
|
6088
6989
|
const cornerWidgets = getVectorCornerWidgets(state).map((w) => {
|
|
6089
6990
|
const s = toScreen(state, w);
|
|
6090
|
-
return { ref: w.ref, x: fmt(s.x), y: fmt(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access',
|
|
6991
|
+
return { ref: w.ref, x: fmt(s.x), y: fmt(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access', _206 => _206.hover, 'optionalAccess', _207 => _207.corner]), w.ref), active: !!dragged };
|
|
6091
6992
|
});
|
|
6092
|
-
if (_optionalChain([it, 'optionalAccess',
|
|
6093
|
-
const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access',
|
|
6094
|
-
|
|
6993
|
+
if (_optionalChain([it, 'optionalAccess', _208 => _208.type]) === "corner") status = `R ${fmt(it.radius)}`;
|
|
6994
|
+
const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access', _209 => _209.hover, 'optionalAccess', _210 => _210.segment]) && !it ? (({ x, y }) => ({ x: fmt(x), y: fmt(y) }))(toScreen(state, state.hover.segment.point)) : null;
|
|
6995
|
+
const sc = (p) => {
|
|
6996
|
+
const q = toScreen(state, p);
|
|
6997
|
+
return { x: fmt(q.x), y: fmt(q.y) };
|
|
6998
|
+
};
|
|
6999
|
+
const sameWidth = (a, b) => !!a && a.nodeId === b.nodeId && a.index === b.index;
|
|
7000
|
+
const widthPoints = getVectorWidthHandles(state).map((h) => {
|
|
7001
|
+
const c = sc(h);
|
|
7002
|
+
const hw = _optionalChain([state, 'access', _211 => _211.hover, 'optionalAccess', _212 => _212.widthPoint]);
|
|
7003
|
+
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', _213 => _213.type]) === "width" && sameWidth(it.ref, h.ref) };
|
|
7005
|
+
});
|
|
7006
|
+
const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _214 => _214.hover, 'optionalAccess', _215 => _215.strokeSpot]) : null;
|
|
7007
|
+
const widthSpot = spot ? { ...sc(spot.point), left: sc(spot.left), right: sc(spot.right) } : null;
|
|
7008
|
+
if (_optionalChain([it, 'optionalAccess', _216 => _216.type]) === "width") status = it.mode === "move" ? "Move width point" : `W ${fmt(it.width)}`;
|
|
7009
|
+
return { outlines, selectionBox, anchors, handles, marquee, penPreview, artboard, guides, status, toolStroke, pencilString, cutPoint, cornerWidgets, widthPoints, widthSpot };
|
|
6095
7010
|
}
|
|
6096
7011
|
var VECTOR_OVERLAY_THEME = {
|
|
6097
7012
|
accent: "#0ea5e9",
|
|
@@ -6105,13 +7020,23 @@ var VECTOR_OVERLAY_THEME = {
|
|
|
6105
7020
|
anchorSize: 7,
|
|
6106
7021
|
handleRadius: 3.5,
|
|
6107
7022
|
/** Radius of a live corner widget (a ring with a dot). */
|
|
6108
|
-
cornerWidgetRadius: 4
|
|
7023
|
+
cornerWidgetRadius: 4,
|
|
7024
|
+
/** Half the diagonal of a width point's diamond. */
|
|
7025
|
+
widthPointSize: 5
|
|
6109
7026
|
};
|
|
7027
|
+
function vectorDiamondPath(x, y, r = VECTOR_OVERLAY_THEME.widthPointSize) {
|
|
7028
|
+
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`;
|
|
7029
|
+
}
|
|
6110
7030
|
function toVectorModifiers(event) {
|
|
6111
7031
|
return { shift: !!event.shiftKey, alt: !!event.altKey, mod: !!(event.metaKey || event.ctrlKey) };
|
|
6112
7032
|
}
|
|
6113
7033
|
function toVectorPointerInput(event) {
|
|
6114
|
-
return {
|
|
7034
|
+
return {
|
|
7035
|
+
...toVectorModifiers(event),
|
|
7036
|
+
button: event.button,
|
|
7037
|
+
...typeof event.pressure === "number" ? { pressure: event.pressure } : {},
|
|
7038
|
+
...event.pointerType ? { pointerType: event.pointerType } : {}
|
|
7039
|
+
};
|
|
6115
7040
|
}
|
|
6116
7041
|
function toVectorKeyInput(event) {
|
|
6117
7042
|
return { key: event.key, ...toVectorModifiers(event) };
|
|
@@ -6121,7 +7046,7 @@ function isVectorTextTarget(target) {
|
|
|
6121
7046
|
if (!el || typeof el !== "object") return false;
|
|
6122
7047
|
const tag = (_nullishCoalesce(el.tagName, () => ( ""))).toUpperCase();
|
|
6123
7048
|
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
|
6124
|
-
return !!el.isContentEditable || _optionalChain([el, 'access',
|
|
7049
|
+
return !!el.isContentEditable || _optionalChain([el, 'access', _217 => _217.getAttribute, 'optionalCall', _218 => _218("contenteditable")]) === "true";
|
|
6125
7050
|
}
|
|
6126
7051
|
function getVectorSelectionStyle(state) {
|
|
6127
7052
|
const paths = [];
|
|
@@ -6129,12 +7054,12 @@ function getVectorSelectionStyle(state) {
|
|
|
6129
7054
|
const node = findVectorNode(state.document.nodes, id);
|
|
6130
7055
|
if (node) paths.push(...collect(node));
|
|
6131
7056
|
}
|
|
6132
|
-
const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access',
|
|
7057
|
+
const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _219 => _219.selectedAnchors, 'optionalAccess', _220 => _220.length]);
|
|
6133
7058
|
if (anchorMode) {
|
|
6134
7059
|
for (const r of state.selectedAnchors) {
|
|
6135
7060
|
if (paths.some((p) => p.id === r.nodeId)) continue;
|
|
6136
7061
|
const node = findVectorNode(state.document.nodes, r.nodeId);
|
|
6137
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
7062
|
+
if (_optionalChain([node, 'optionalAccess', _221 => _221.type]) === "path") paths.push(node);
|
|
6138
7063
|
}
|
|
6139
7064
|
}
|
|
6140
7065
|
if (!paths.length) return null;
|
|
@@ -6145,7 +7070,7 @@ function getVectorSelectionStyle(state) {
|
|
|
6145
7070
|
for (const c of vectorCorners(p.subpaths)) {
|
|
6146
7071
|
if (anchorMode && !state.selectedAnchors.some((r) => r.nodeId === p.id && r.subpath === c.subpath && r.index === c.index)) continue;
|
|
6147
7072
|
const corner = p.subpaths[c.subpath].anchors[c.index].corner;
|
|
6148
|
-
corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess',
|
|
7073
|
+
corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _222 => _222.radius]), () => ( 0)), kind: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _223 => _223.kind]), () => ( "round")) });
|
|
6149
7074
|
}
|
|
6150
7075
|
}
|
|
6151
7076
|
const c0 = _nullishCoalesce(corners2[0], () => ( { radius: 0, kind: "round" }));
|
|
@@ -6160,6 +7085,8 @@ function getVectorSelectionStyle(state) {
|
|
|
6160
7085
|
arrowAlign: _nullishCoalesce(first.arrowAlign, () => ( "extend")),
|
|
6161
7086
|
startArrowScale: _nullishCoalesce(first.startArrowScale, () => ( 1)),
|
|
6162
7087
|
endArrowScale: _nullishCoalesce(first.endArrowScale, () => ( 1)),
|
|
7088
|
+
strokeWidthProfile: profileOf(first),
|
|
7089
|
+
widthProfile: widthProfilePresetId(profileOf(first)),
|
|
6163
7090
|
cornerRadius: c0.radius,
|
|
6164
7091
|
cornerKind: c0.kind,
|
|
6165
7092
|
corners: corners2.length,
|
|
@@ -6175,12 +7102,17 @@ function getVectorSelectionStyle(state) {
|
|
|
6175
7102
|
arrowAlign: !same((p) => _nullishCoalesce(p.arrowAlign, () => ( "extend"))),
|
|
6176
7103
|
startArrowScale: !same((p) => _nullishCoalesce(p.startArrowScale, () => ( 1))),
|
|
6177
7104
|
endArrowScale: !same((p) => _nullishCoalesce(p.endArrowScale, () => ( 1))),
|
|
7105
|
+
widthProfile: !same(profileOf),
|
|
6178
7106
|
cornerRadius: corners2.some((c) => c.radius !== c0.radius),
|
|
6179
7107
|
cornerKind: corners2.some((c) => c.kind !== c0.kind)
|
|
6180
7108
|
},
|
|
6181
7109
|
pathIds: paths.map((p) => p.id)
|
|
6182
7110
|
};
|
|
6183
7111
|
}
|
|
7112
|
+
function profileOf(p) {
|
|
7113
|
+
const points = sanitizeWidthProfile(p.strokeWidthProfile);
|
|
7114
|
+
return points.length && widthProfilePresetId(points) !== "uniform" ? points : null;
|
|
7115
|
+
}
|
|
6184
7116
|
var VECTOR_STROKE_ALIGN_LABELS = { center: "Center", inside: "Inside", outside: "Outside" };
|
|
6185
7117
|
var VECTOR_CORNER_KIND_LABELS = { round: "Round", inverted: "Inverted", chamfer: "Chamfer" };
|
|
6186
7118
|
var VECTOR_ARROWHEAD_LABELS = {
|
|
@@ -6232,6 +7164,19 @@ var POINTS = {
|
|
|
6232
7164
|
minItems: 1,
|
|
6233
7165
|
description: "Polyline [[x, y], \u2026] in document units."
|
|
6234
7166
|
};
|
|
7167
|
+
var WIDTH_POINTS = {
|
|
7168
|
+
type: ["array", "null"],
|
|
7169
|
+
items: {
|
|
7170
|
+
type: "object",
|
|
7171
|
+
properties: {
|
|
7172
|
+
t: { type: "number", minimum: 0, maximum: 1, description: "Position along each subpath by length (0 start, 1 end)." },
|
|
7173
|
+
left: { type: "number", minimum: 0, description: "Left side as a multiple of half the stroke width (1 = uniform)." },
|
|
7174
|
+
right: { type: "number", minimum: 0, description: "Right side (looking along the path, y down)." }
|
|
7175
|
+
},
|
|
7176
|
+
required: ["t", "left", "right"]
|
|
7177
|
+
},
|
|
7178
|
+
description: "Variable-width profile points, interpolated smoothly (monotone cubic); two points at one `t` make a step. `null` or `[]` strokes at a uniform width."
|
|
7179
|
+
};
|
|
6235
7180
|
var PAINT = {
|
|
6236
7181
|
description: 'A CSS colour, `null` for none, or a gradient `{ type: "linear", angle, stops: [{ offset, color }] }`.'
|
|
6237
7182
|
};
|
|
@@ -6248,7 +7193,8 @@ var STYLE_PROPS = {
|
|
|
6248
7193
|
endArrow: { type: ["string", "null"], enum: [...VECTOR_ARROWHEADS, null], description: "Head at the end of an open path, or null for none." },
|
|
6249
7194
|
arrowAlign: { type: "string", enum: ["extend", "tip"], description: "`extend`: the tip sits past the end point; `tip`: on it, the stroke shortened under the head." },
|
|
6250
7195
|
startArrowScale: { type: "number", exclusiveMinimum: 0, description: "Start head size as a multiple of the stroke width (default 1)." },
|
|
6251
|
-
endArrowScale: { type: "number", exclusiveMinimum: 0, description: "End head size as a multiple of the stroke width (default 1)." }
|
|
7196
|
+
endArrowScale: { type: "number", exclusiveMinimum: 0, description: "End head size as a multiple of the stroke width (default 1)." },
|
|
7197
|
+
strokeWidthProfile: WIDTH_POINTS
|
|
6252
7198
|
};
|
|
6253
7199
|
var pickStyle = (params) => {
|
|
6254
7200
|
const out = {};
|
|
@@ -6264,17 +7210,17 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6264
7210
|
const base = { group, ...options.scope ? { scope: options.scope } : {} };
|
|
6265
7211
|
const hasSelection = () => controller.getState().selection.length ? true : "Nothing is selected.";
|
|
6266
7212
|
const ids = (params) => {
|
|
6267
|
-
const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess',
|
|
7213
|
+
const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _224 => _224.ids]), () => ( controller.getState().selection));
|
|
6268
7214
|
for (const id of list2) if (!controller.getNode(id)) fail(`There is no node "${id}".`);
|
|
6269
7215
|
if (!list2.length) fail("Nothing is selected; pass ids.");
|
|
6270
7216
|
return list2;
|
|
6271
7217
|
};
|
|
6272
|
-
const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess',
|
|
7218
|
+
const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _225 => _225.ids, 'optionalAccess', _226 => _226.length]) ? true : hasSelection();
|
|
6273
7219
|
const anchorsOf = (refs) => {
|
|
6274
7220
|
if (!refs) return [...controller.getState().selectedAnchors];
|
|
6275
7221
|
for (const r of refs) {
|
|
6276
7222
|
const node = controller.getNode(r.nodeId);
|
|
6277
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
7223
|
+
if (_optionalChain([node, 'optionalAccess', _227 => _227.type]) !== "path" || !_optionalChain([node, 'access', _228 => _228.subpaths, 'access', _229 => _229[r.subpath], 'optionalAccess', _230 => _230.anchors, 'access', _231 => _231[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
|
|
6278
7224
|
}
|
|
6279
7225
|
return refs;
|
|
6280
7226
|
};
|
|
@@ -6365,7 +7311,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6365
7311
|
run: (_ctx, params) => {
|
|
6366
7312
|
const id = controller.addPath(params.d, { ...pickStyle(params), ...params.name ? { name: params.name } : {} });
|
|
6367
7313
|
const node = controller.getNode(id);
|
|
6368
|
-
if (_optionalChain([node, 'optionalAccess',
|
|
7314
|
+
if (_optionalChain([node, 'optionalAccess', _232 => _232.type]) === "path" && !node.subpaths.length) {
|
|
6369
7315
|
controller.undo();
|
|
6370
7316
|
fail("The path data has no points.");
|
|
6371
7317
|
}
|
|
@@ -6397,14 +7343,52 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6397
7343
|
params: { type: "object", properties: { radius: { type: "number", minimum: 0 }, kind: { type: "string", enum: VECTOR_CORNER_KINDS }, ids: IDS, anchors: ANCHORS } },
|
|
6398
7344
|
undoable: true,
|
|
6399
7345
|
run: (_ctx, params) => {
|
|
6400
|
-
const refs = _optionalChain([params, 'optionalAccess',
|
|
6401
|
-
const target = { refs, ids: _optionalChain([params, 'optionalAccess',
|
|
6402
|
-
if (_optionalChain([params, 'optionalAccess',
|
|
6403
|
-
else if (_optionalChain([params, 'optionalAccess',
|
|
7346
|
+
const refs = _optionalChain([params, 'optionalAccess', _233 => _233.anchors]) ? anchorsOf(params.anchors) : void 0;
|
|
7347
|
+
const target = { refs, ids: _optionalChain([params, 'optionalAccess', _234 => _234.ids]) ? ids(params) : void 0 };
|
|
7348
|
+
if (_optionalChain([params, 'optionalAccess', _235 => _235.radius]) !== void 0) check(controller.setCornerRadius(params.radius, { ...target, kind: params.kind }));
|
|
7349
|
+
else if (_optionalChain([params, 'optionalAccess', _236 => _236.kind])) check(controller.setCornerKind(params.kind, target));
|
|
6404
7350
|
else fail("Pass `radius` and / or `kind`.");
|
|
6405
7351
|
return { ok: true };
|
|
6406
7352
|
}
|
|
6407
7353
|
},
|
|
7354
|
+
{
|
|
7355
|
+
...base,
|
|
7356
|
+
id: `${prefix}setWidthProfile`,
|
|
7357
|
+
label: "Width Profile\u2026",
|
|
7358
|
+
keywords: ["variable width", "taper", "tapered", "pressure", "profile", "brush", "calligraphy", "bulge", "thick", "thin"],
|
|
7359
|
+
description: "Gives the stroke of paths a variable width: a `preset` (`uniform` removes the profile), explicit `points` ({ t, left, right }: side scales along each subpath), or a parametric `taper` (startLength / endLength as fractions of the path, startWidth / endWidth 0\u20131, startEase / endEase 0\u20131) and / or `wave` (amount 0\u20131, cycles, phase in degrees). Profiled strokes draw as filled outlines; Outline Stroke bakes them.",
|
|
7360
|
+
params: {
|
|
7361
|
+
type: "object",
|
|
7362
|
+
properties: {
|
|
7363
|
+
ids: IDS,
|
|
7364
|
+
preset: { type: "string", enum: VECTOR_WIDTH_PRESET_IDS },
|
|
7365
|
+
points: WIDTH_POINTS,
|
|
7366
|
+
taper: {
|
|
7367
|
+
type: "object",
|
|
7368
|
+
properties: {
|
|
7369
|
+
startLength: { type: "number", minimum: 0, maximum: 1 },
|
|
7370
|
+
endLength: { type: "number", minimum: 0, maximum: 1 },
|
|
7371
|
+
startWidth: { type: "number", minimum: 0, maximum: 1 },
|
|
7372
|
+
endWidth: { type: "number", minimum: 0, maximum: 1 },
|
|
7373
|
+
startEase: { type: "number", minimum: 0, maximum: 1 },
|
|
7374
|
+
endEase: { type: "number", minimum: 0, maximum: 1 }
|
|
7375
|
+
}
|
|
7376
|
+
},
|
|
7377
|
+
wave: { type: "object", properties: { amount: { type: "number", minimum: 0, maximum: 1 }, cycles: { type: "number", exclusiveMinimum: 0 }, phase: { type: "number" } } }
|
|
7378
|
+
}
|
|
7379
|
+
},
|
|
7380
|
+
enabled: enabledFor,
|
|
7381
|
+
undoable: true,
|
|
7382
|
+
run: (_ctx, params) => {
|
|
7383
|
+
const target = { ids: ids(params) };
|
|
7384
|
+
if (_optionalChain([params, 'optionalAccess', _237 => _237.preset])) check(controller.setWidthProfile(params.preset, target));
|
|
7385
|
+
else if (_optionalChain([params, 'optionalAccess', _238 => _238.points]) !== void 0) check(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
|
|
7386
|
+
else if (_optionalChain([params, 'optionalAccess', _239 => _239.taper]) || _optionalChain([params, 'optionalAccess', _240 => _240.wave])) check(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
|
|
7387
|
+
else fail("Pass `preset`, `points`, `taper` or `wave`.");
|
|
7388
|
+
const node = controller.getNode(target.ids[0]);
|
|
7389
|
+
return { ok: true, points: _optionalChain([node, 'optionalAccess', _241 => _241.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
|
|
7390
|
+
}
|
|
7391
|
+
},
|
|
6408
7392
|
{
|
|
6409
7393
|
...base,
|
|
6410
7394
|
id: `${prefix}outlineStroke`,
|
|
@@ -6415,7 +7399,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6415
7399
|
enabled: enabledFor,
|
|
6416
7400
|
undoable: true,
|
|
6417
7401
|
run: (_ctx, params) => {
|
|
6418
|
-
const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess',
|
|
7402
|
+
const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _242 => _242.ids]) ? ids(params) : void 0 });
|
|
6419
7403
|
if (!created.length) fail("No selected path has a stroke.");
|
|
6420
7404
|
return { ids: created };
|
|
6421
7405
|
}
|
|
@@ -6530,7 +7514,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6530
7514
|
enabled: enabledFor,
|
|
6531
7515
|
undoable: true,
|
|
6532
7516
|
run: (_ctx, params) => {
|
|
6533
|
-
const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess',
|
|
7517
|
+
const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _243 => _243.name]) });
|
|
6534
7518
|
if (!id) fail("Only nodes that share a parent can be grouped.");
|
|
6535
7519
|
return { id };
|
|
6536
7520
|
}
|
|
@@ -6558,7 +7542,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6558
7542
|
params: { type: "object", properties: { anchors: ANCHORS, keepShape: { type: "boolean" } } },
|
|
6559
7543
|
undoable: true,
|
|
6560
7544
|
run: (_ctx, params) => {
|
|
6561
|
-
check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess',
|
|
7545
|
+
check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _244 => _244.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _245 => _245.keepShape]) }));
|
|
6562
7546
|
return { ok: true };
|
|
6563
7547
|
}
|
|
6564
7548
|
},
|
|
@@ -6613,7 +7597,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6613
7597
|
params: { type: "object", properties: { ids: IDS, tolerance: { type: "number", minimum: 0 } } },
|
|
6614
7598
|
undoable: true,
|
|
6615
7599
|
run: (_ctx, params) => {
|
|
6616
|
-
check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess',
|
|
7600
|
+
check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _246 => _246.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _247 => _247.tolerance]) }));
|
|
6617
7601
|
return { selection: controller.getState().selection };
|
|
6618
7602
|
}
|
|
6619
7603
|
},
|
|
@@ -6627,7 +7611,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6627
7611
|
params: { type: "object", properties: { axis: { type: "string", enum: ["horizontal", "vertical", "both"] }, anchors: ANCHORS } },
|
|
6628
7612
|
undoable: true,
|
|
6629
7613
|
run: (_ctx, params) => {
|
|
6630
|
-
check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess',
|
|
7614
|
+
check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _248 => _248.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _249 => _249.anchors]))));
|
|
6631
7615
|
return { ok: true };
|
|
6632
7616
|
}
|
|
6633
7617
|
},
|
|
@@ -6641,7 +7625,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6641
7625
|
enabled: enabledFor,
|
|
6642
7626
|
undoable: true,
|
|
6643
7627
|
run: (_ctx, params) => {
|
|
6644
|
-
check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess',
|
|
7628
|
+
check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _250 => _250.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _251 => _251.tolerance]) }));
|
|
6645
7629
|
return { ok: true };
|
|
6646
7630
|
}
|
|
6647
7631
|
},
|
|
@@ -6654,7 +7638,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6654
7638
|
params: { type: "object", properties: { ids: IDS, amount: { type: "number", minimum: 0, maximum: 1 }, anchors: ANCHORS } },
|
|
6655
7639
|
undoable: true,
|
|
6656
7640
|
run: (_ctx, params) => {
|
|
6657
|
-
check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess',
|
|
7641
|
+
check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _252 => _252.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _253 => _253.amount]), refs: _optionalChain([params, 'optionalAccess', _254 => _254.anchors]) }));
|
|
6658
7642
|
return { ok: true };
|
|
6659
7643
|
}
|
|
6660
7644
|
},
|
|
@@ -6667,14 +7651,14 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6667
7651
|
params: { type: "object", properties: { nodeId: { type: "string" }, x: { type: "number" }, y: { type: "number" }, anchors: ANCHORS } },
|
|
6668
7652
|
undoable: true,
|
|
6669
7653
|
run: (_ctx, params) => {
|
|
6670
|
-
if (_optionalChain([params, 'optionalAccess',
|
|
7654
|
+
if (_optionalChain([params, 'optionalAccess', _255 => _255.nodeId]) !== void 0) {
|
|
6671
7655
|
if (!controller.getNode(params.nodeId)) fail(`There is no node "${params.nodeId}".`);
|
|
6672
7656
|
if (params.x === void 0 || params.y === void 0) fail("Pass x and y with nodeId.");
|
|
6673
7657
|
const created = controller.cutPathAt(params.nodeId, { x: params.x, y: params.y });
|
|
6674
7658
|
if (!created) fail("Nothing to cut there (the end of an open path, or a locked path).");
|
|
6675
7659
|
return { ids: created };
|
|
6676
7660
|
}
|
|
6677
|
-
check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess',
|
|
7661
|
+
check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _256 => _256.anchors]))));
|
|
6678
7662
|
return { ids: controller.getState().selection };
|
|
6679
7663
|
}
|
|
6680
7664
|
},
|
|
@@ -6711,7 +7695,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6711
7695
|
id: `${prefix}setEditing`,
|
|
6712
7696
|
label: "Path Editing Options\u2026",
|
|
6713
7697
|
keywords: ["settings", "curvature", "pencil", "smoothing", "lazy mouse", "shapes", "eraser"],
|
|
6714
|
-
description: "Sets how editing behaves: `keepShapeOnDelete`, `curvatureMoves` (anchor drags bend like the Curvature tool), `pencilSmoothing` (lazy mouse, 0\u20131), `recognizeShapes` (pencil scribbles become lines, rectangles, ellipses, polygons) and `
|
|
7698
|
+
description: "Sets how editing behaves: `keepShapeOnDelete`, `curvatureMoves` (anchor drags bend like the Curvature tool), `pencilSmoothing` (lazy mouse, 0\u20131), `recognizeShapes` (pencil scribbles become lines, rectangles, ellipses, polygons), `eraserSize` and `pencilPressure` (`pen`: record pen pressure on pencil strokes as a width profile, `all`: any pointer reporting pressure, `off`).",
|
|
6715
7699
|
params: {
|
|
6716
7700
|
type: "object",
|
|
6717
7701
|
properties: {
|
|
@@ -6719,12 +7703,13 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6719
7703
|
curvatureMoves: { type: "boolean" },
|
|
6720
7704
|
pencilSmoothing: { type: "number", minimum: 0, maximum: 1 },
|
|
6721
7705
|
recognizeShapes: { type: "boolean" },
|
|
6722
|
-
eraserSize: { type: "number", exclusiveMinimum: 0 }
|
|
7706
|
+
eraserSize: { type: "number", exclusiveMinimum: 0 },
|
|
7707
|
+
pencilPressure: { type: "string", enum: ["pen", "all", "off"] }
|
|
6723
7708
|
}
|
|
6724
7709
|
},
|
|
6725
7710
|
run: (_ctx, params) => {
|
|
6726
7711
|
const patch = {};
|
|
6727
|
-
for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize"]) if (_optionalChain([params, 'optionalAccess',
|
|
7712
|
+
for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess', _257 => _257[key]]) !== void 0) patch[key] = params[key];
|
|
6728
7713
|
controller.setEditing(patch);
|
|
6729
7714
|
return { editing: controller.getState().editing };
|
|
6730
7715
|
}
|
|
@@ -6749,7 +7734,7 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6749
7734
|
keywords: ["download", "save", "markup"],
|
|
6750
7735
|
description: "Returns the document as SVG markup.",
|
|
6751
7736
|
params: { type: "object", properties: { precision: { type: "integer", minimum: 0, maximum: 8 } } },
|
|
6752
|
-
run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess',
|
|
7737
|
+
run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _258 => _258.precision]) }) })
|
|
6753
7738
|
},
|
|
6754
7739
|
{
|
|
6755
7740
|
...base,
|
|
@@ -6915,5 +7900,37 @@ function createVectorCommands(controller, options = {}) {
|
|
|
6915
7900
|
|
|
6916
7901
|
|
|
6917
7902
|
|
|
6918
|
-
|
|
7903
|
+
|
|
7904
|
+
|
|
7905
|
+
|
|
7906
|
+
|
|
7907
|
+
|
|
7908
|
+
|
|
7909
|
+
|
|
7910
|
+
|
|
7911
|
+
|
|
7912
|
+
|
|
7913
|
+
|
|
7914
|
+
|
|
7915
|
+
|
|
7916
|
+
|
|
7917
|
+
|
|
7918
|
+
|
|
7919
|
+
|
|
7920
|
+
|
|
7921
|
+
|
|
7922
|
+
|
|
7923
|
+
|
|
7924
|
+
|
|
7925
|
+
|
|
7926
|
+
|
|
7927
|
+
|
|
7928
|
+
|
|
7929
|
+
|
|
7930
|
+
|
|
7931
|
+
|
|
7932
|
+
|
|
7933
|
+
|
|
7934
|
+
|
|
7935
|
+
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_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_INK_MAX_CORNERS = VECTOR_INK_MAX_CORNERS; exports.VECTOR_OVERLAY_THEME = VECTOR_OVERLAY_THEME; 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.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.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.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.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.vectorCornerAt = vectorCornerAt; exports.vectorCorners = vectorCorners; exports.vectorCornersAttribute = vectorCornersAttribute; exports.vectorDiamondPath = vectorDiamondPath; exports.vectorDocumentToSvg = vectorDocumentToSvg; 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.vectorPathWorldBezier = vectorPathWorldBezier; exports.vectorResizeCursor = vectorResizeCursor; 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;
|
|
6919
7936
|
//# sourceMappingURL=index.cjs.map
|