@weasel-js/geom 1.9.3 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/3d/index.js +1 -1
- package/dist/booleans/index.d.ts +51 -29
- package/dist/booleans/index.js +562 -482
- package/dist/booleans/index.js.map +1 -1
- package/dist/{chunk-7ROQRYOA.js → chunk-755Y4YZS.js} +6 -3
- package/dist/chunk-755Y4YZS.js.map +1 -0
- package/dist/{chunk-6T5I3PR5.js → chunk-MDT7F32A.js} +16 -5
- package/dist/chunk-MDT7F32A.js.map +1 -0
- package/dist/{chunk-HEZTRG2M.js → chunk-OXH3NOXC.js} +10 -3
- package/dist/chunk-OXH3NOXC.js.map +1 -0
- package/dist/{chunk-RQYCDPU5.js → chunk-WQMYOCFB.js} +27 -18
- package/dist/chunk-WQMYOCFB.js.map +1 -0
- package/dist/{chunk-HPVINMOM.js → chunk-XS6ERH3X.js} +2 -2
- package/dist/chunk-XS6ERH3X.js.map +1 -0
- package/dist/cubicMath-CFXbq6vp.d.ts +116 -0
- package/dist/curves/index.d.ts +1 -1
- package/dist/curves/index.js +18 -71
- package/dist/curves/index.js.map +1 -1
- package/dist/index.d.ts +612 -116
- package/dist/index.js +904 -112
- package/dist/index.js.map +1 -1
- package/dist/{path-D0CoudGM.d.ts → path-Bf9KeVxC.d.ts} +10 -11
- package/dist/tessellate/index.d.ts +8 -12
- package/dist/tessellate/index.js +36 -10
- package/dist/tessellate/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6T5I3PR5.js.map +0 -1
- package/dist/chunk-7ROQRYOA.js.map +0 -1
- package/dist/chunk-HEZTRG2M.js.map +0 -1
- package/dist/chunk-HPVINMOM.js.map +0 -1
- package/dist/chunk-RQYCDPU5.js.map +0 -1
- package/dist/cubicMath-CpCvuEl8.d.ts +0 -37
package/dist/index.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { PORT_REACH, portControls, portCurvePoints } from './chunk-YQADYJJ7.js';
|
|
2
2
|
export { PORT_REACH } from './chunk-YQADYJJ7.js';
|
|
3
|
-
import { cubicPointAt } from './chunk-
|
|
4
|
-
export { cubicPointAt, fitCubicThroughDeletion, splitCubicAtT } from './chunk-
|
|
3
|
+
import { cubicPointAt, splitCubicAtT, fitCubicThroughDeletion } from './chunk-XS6ERH3X.js';
|
|
4
|
+
export { cubicPointAt, fitCubicThroughDeletion, splitCubicAtT } from './chunk-XS6ERH3X.js';
|
|
5
5
|
import { cubicEvalAt, elevateQuadraticToCubic, cubicBounds } from './chunk-URQMDR6Q.js';
|
|
6
6
|
export { cubicBounds, cubicEvalAt, elevateQuadraticToCubic, quadraticEvalAt, splitCubicAt, splitLineAt, splitQuadraticAt } from './chunk-URQMDR6Q.js';
|
|
7
|
-
import { extractPolylines } from './chunk-
|
|
8
|
-
export { boundsOfCoords, boxContainsBox, boxContainsPoint, rectToContour, unionBox } from './chunk-
|
|
9
|
-
import {
|
|
10
|
-
export { DEFAULT_FLATTEN_TOLERANCE, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, pointInPolygon, pointSegmentDist2, segmentsCross } from './chunk-
|
|
11
|
-
import { SINGULAR_RATIO } from './chunk-
|
|
12
|
-
export { EPS, approxEq, cross, dot, len2, sign, sub } from './chunk-
|
|
13
|
-
import { forEachSegment, PATH_M, PATH_L, PATH_Q, PATH_C, PATH_Z, pathCommandCoordCount } from './chunk-
|
|
14
|
-
export { PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, forEachSegment, pathCommandCoordCount } from './chunk-
|
|
7
|
+
import { extractPolylines, rectToContour } from './chunk-MDT7F32A.js';
|
|
8
|
+
export { boundsOfCoords, boxContainsBox, boxContainsPoint, rectToContour, unionBox } from './chunk-MDT7F32A.js';
|
|
9
|
+
import { fillsOpenSubpaths, pointInPolygon, pointSegmentDist2, flattenQuadratic, flattenCubic, DEFAULT_FLATTEN_TOLERANCE, segmentsCross } from './chunk-WQMYOCFB.js';
|
|
10
|
+
export { DEFAULT_FLATTEN_TOLERANCE, defaultOpenFill, fillsOpenSubpaths, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, pointInPolygon, pointSegmentDist2, segmentsCross, setDefaultOpenFill } from './chunk-WQMYOCFB.js';
|
|
11
|
+
import { SINGULAR_RATIO } from './chunk-755Y4YZS.js';
|
|
12
|
+
export { EPS, approxEq, clamp, cross, dot, len2, sign, sub } from './chunk-755Y4YZS.js';
|
|
13
|
+
import { forEachSegment, PATH_M, PATH_L, PATH_Q, PATH_C, PATH_Z, pathCommandCoordCount } from './chunk-OXH3NOXC.js';
|
|
14
|
+
export { PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, forEachSegment, pathCommandCoordCount } from './chunk-OXH3NOXC.js';
|
|
15
|
+
|
|
16
|
+
// src/view.ts
|
|
17
|
+
var ZOOM_FLOOR = 1e-9;
|
|
18
|
+
function normalizeZoom(zoom) {
|
|
19
|
+
return zoom >= ZOOM_FLOOR && zoom < Infinity ? zoom : ZOOM_FLOOR;
|
|
20
|
+
}
|
|
15
21
|
|
|
16
22
|
// src/mat3.ts
|
|
17
23
|
function identity() {
|
|
@@ -404,10 +410,11 @@ function transformCoords(coords, m) {
|
|
|
404
410
|
}
|
|
405
411
|
|
|
406
412
|
// src/paths/transformPath.ts
|
|
413
|
+
var AXIS_ALIGNED_EPSILON = 1e-9;
|
|
407
414
|
function transformPath(path, m) {
|
|
408
415
|
const [a, b, c, d, e, f] = m;
|
|
409
416
|
if (path.kind === "rect") {
|
|
410
|
-
if (b
|
|
417
|
+
if (Math.abs(b) < AXIS_ALIGNED_EPSILON && Math.abs(c) < AXIS_ALIGNED_EPSILON) {
|
|
411
418
|
const x0 = a * path.x + e;
|
|
412
419
|
const y0 = d * path.y + f;
|
|
413
420
|
const x1 = a * (path.x + path.width) + e;
|
|
@@ -446,7 +453,7 @@ function translatePolygonCopy(path, dx, dy) {
|
|
|
446
453
|
next[ci + k + 1] = coords[ci + k + 1] + dy;
|
|
447
454
|
}
|
|
448
455
|
});
|
|
449
|
-
return {
|
|
456
|
+
return { ...path, coords: next };
|
|
450
457
|
}
|
|
451
458
|
function scalePathToBounds(path, target) {
|
|
452
459
|
if (path.kind === "rect") {
|
|
@@ -470,68 +477,80 @@ function decomposePath(parent, world) {
|
|
|
470
477
|
return translatePath(world, -origin.x, -origin.y);
|
|
471
478
|
}
|
|
472
479
|
function pathOrigin(path) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
let minY = Infinity;
|
|
476
|
-
const { coords } = path;
|
|
477
|
-
for (let i = 0; i < coords.length; i += 2) {
|
|
478
|
-
if (coords[i] < minX) minX = coords[i];
|
|
479
|
-
if (coords[i + 1] < minY) minY = coords[i + 1];
|
|
480
|
-
}
|
|
481
|
-
if (minX === Infinity) return { x: 0, y: 0 };
|
|
482
|
-
return { x: minX, y: minY };
|
|
480
|
+
const { x, y } = boundsOfPath(path);
|
|
481
|
+
return { x, y };
|
|
483
482
|
}
|
|
484
483
|
|
|
485
484
|
// src/paths/splitSubpaths.ts
|
|
486
485
|
function splitSubpaths(path) {
|
|
487
|
-
const { commands, coords
|
|
486
|
+
const { commands, coords } = path;
|
|
488
487
|
const out = [];
|
|
489
488
|
let cmdStart = 0;
|
|
490
489
|
let coordStart = 0;
|
|
491
490
|
forEachSegment(commands, coords, (cmd, ci, _px, _py, i) => {
|
|
492
491
|
if (cmd !== PATH_M || i <= cmdStart) return;
|
|
493
|
-
out.push({
|
|
494
|
-
kind: "polygon",
|
|
495
|
-
commands: commands.slice(cmdStart, i),
|
|
496
|
-
coords: coords.slice(coordStart, ci),
|
|
497
|
-
fillRule
|
|
498
|
-
});
|
|
492
|
+
out.push({ ...path, commands: commands.slice(cmdStart, i), coords: coords.slice(coordStart, ci) });
|
|
499
493
|
cmdStart = i;
|
|
500
494
|
coordStart = ci;
|
|
501
495
|
});
|
|
502
|
-
out.push({
|
|
503
|
-
kind: "polygon",
|
|
504
|
-
commands: commands.slice(cmdStart),
|
|
505
|
-
coords: coords.slice(coordStart),
|
|
506
|
-
fillRule
|
|
507
|
-
});
|
|
496
|
+
out.push({ ...path, commands: commands.slice(cmdStart), coords: coords.slice(coordStart) });
|
|
508
497
|
return out;
|
|
509
498
|
}
|
|
510
499
|
|
|
500
|
+
// src/paths/splitByClosure.ts
|
|
501
|
+
var endsInZ = (sub3) => sub3.commands[sub3.commands.length - 1] === PATH_Z;
|
|
502
|
+
function hasOpenSubpath(path) {
|
|
503
|
+
return path.kind === "polygon" && path.commands.length > 0 && splitSubpaths(path).some((sub3) => !endsInZ(sub3));
|
|
504
|
+
}
|
|
505
|
+
function splitByClosure(path) {
|
|
506
|
+
const closed = [];
|
|
507
|
+
const open = [];
|
|
508
|
+
if (path.commands.length > 0) {
|
|
509
|
+
for (const sub3 of splitSubpaths(path)) (endsInZ(sub3) ? closed : open).push(sub3);
|
|
510
|
+
}
|
|
511
|
+
const join = (subs) => {
|
|
512
|
+
if (subs.length === 0) return null;
|
|
513
|
+
const commands = new Uint8Array(subs.reduce((n, s) => n + s.commands.length, 0));
|
|
514
|
+
const coords = new Float32Array(subs.reduce((n, s) => n + s.coords.length, 0));
|
|
515
|
+
let ci = 0, xi = 0;
|
|
516
|
+
for (const s of subs) {
|
|
517
|
+
commands.set(s.commands, ci);
|
|
518
|
+
coords.set(s.coords, xi);
|
|
519
|
+
ci += s.commands.length;
|
|
520
|
+
xi += s.coords.length;
|
|
521
|
+
}
|
|
522
|
+
return { ...path, commands, coords };
|
|
523
|
+
};
|
|
524
|
+
return { closed: join(closed), open: join(open) };
|
|
525
|
+
}
|
|
526
|
+
|
|
511
527
|
// src/paths/winding.ts
|
|
512
528
|
var GL_T = [0.5 - Math.sqrt(15) / 10, 0.5, 0.5 + Math.sqrt(15) / 10];
|
|
513
529
|
var GL_W = [5 / 18, 8 / 18, 5 / 18];
|
|
514
530
|
function pathSignedArea(path) {
|
|
515
531
|
if (path.kind === "rect") return path.width * path.height;
|
|
516
532
|
const { commands, coords } = path;
|
|
533
|
+
const fillsOpen = fillsOpenSubpaths(path);
|
|
534
|
+
let total = 0;
|
|
517
535
|
let twice = 0;
|
|
518
536
|
let startX = 0, startY = 0;
|
|
519
537
|
let open = false;
|
|
520
538
|
let endX = 0, endY = 0;
|
|
521
|
-
const close = () => {
|
|
522
|
-
if (open)
|
|
539
|
+
const close = (drawn) => {
|
|
540
|
+
if (open && (drawn || fillsOpen)) total += twice + endX * startY - startX * endY;
|
|
541
|
+
twice = 0;
|
|
523
542
|
open = false;
|
|
524
543
|
};
|
|
525
544
|
forEachSegment(commands, coords, (cmd, ci, px, py) => {
|
|
526
545
|
if (cmd === PATH_M) {
|
|
527
|
-
close();
|
|
546
|
+
close(false);
|
|
528
547
|
startX = endX = coords[ci];
|
|
529
548
|
startY = endY = coords[ci + 1];
|
|
530
549
|
open = true;
|
|
531
550
|
return;
|
|
532
551
|
}
|
|
533
552
|
if (cmd === PATH_Z) {
|
|
534
|
-
close();
|
|
553
|
+
close(true);
|
|
535
554
|
endX = startX;
|
|
536
555
|
endY = startY;
|
|
537
556
|
return;
|
|
@@ -570,8 +589,8 @@ function pathSignedArea(path) {
|
|
|
570
589
|
endX = x3;
|
|
571
590
|
endY = y3;
|
|
572
591
|
});
|
|
573
|
-
close();
|
|
574
|
-
return
|
|
592
|
+
close(false);
|
|
593
|
+
return total / 2;
|
|
575
594
|
}
|
|
576
595
|
function reversePath(path) {
|
|
577
596
|
const cmds = [];
|
|
@@ -628,12 +647,7 @@ function reversePath(path) {
|
|
|
628
647
|
segs.push({ cmd, args: Array.from(coords.subarray(ci, ci + n)), fromX: px, fromY: py });
|
|
629
648
|
});
|
|
630
649
|
flush(false);
|
|
631
|
-
return {
|
|
632
|
-
kind: "polygon",
|
|
633
|
-
commands: new Uint8Array(cmds),
|
|
634
|
-
coords: new Float32Array(out),
|
|
635
|
-
fillRule: path.fillRule
|
|
636
|
-
};
|
|
650
|
+
return { ...path, commands: new Uint8Array(cmds), coords: new Float32Array(out) };
|
|
637
651
|
}
|
|
638
652
|
|
|
639
653
|
// src/paths/pathFromD.ts
|
|
@@ -724,6 +738,7 @@ function pathFromD(d, onWarn) {
|
|
|
724
738
|
lastCubicCtrl: null,
|
|
725
739
|
lastQuadCtrl: null
|
|
726
740
|
};
|
|
741
|
+
let started = false;
|
|
727
742
|
for (const { cmd, args } of tokens) {
|
|
728
743
|
const upper = cmd.toUpperCase();
|
|
729
744
|
const relative = cmd !== upper;
|
|
@@ -732,6 +747,10 @@ function pathFromD(d, onWarn) {
|
|
|
732
747
|
onWarn?.(`unknown path command: ${cmd}`);
|
|
733
748
|
continue;
|
|
734
749
|
}
|
|
750
|
+
if (!started && upper !== "M") {
|
|
751
|
+
onWarn?.(`path data does not begin with a moveto ("${cmd}" comes first); nothing is drawn`);
|
|
752
|
+
break;
|
|
753
|
+
}
|
|
735
754
|
if (upper === "Z") {
|
|
736
755
|
b.close();
|
|
737
756
|
st.x = st.startX;
|
|
@@ -740,11 +759,16 @@ function pathFromD(d, onWarn) {
|
|
|
740
759
|
st.lastQuadCtrl = null;
|
|
741
760
|
continue;
|
|
742
761
|
}
|
|
743
|
-
const groups =
|
|
762
|
+
const groups = Math.floor(args.length / argCount);
|
|
744
763
|
for (let g = 0; g < groups; g++) {
|
|
745
764
|
const a = args.slice(g * argCount, (g + 1) * argCount);
|
|
746
765
|
const effectiveUpper = upper === "M" && g > 0 ? "L" : upper;
|
|
747
766
|
runCommand(effectiveUpper, relative, a, st, b);
|
|
767
|
+
started = true;
|
|
768
|
+
}
|
|
769
|
+
if (groups === 0 || args.length % argCount !== 0) {
|
|
770
|
+
onWarn?.(`path command "${cmd}" takes ${argCount} arguments at a time and has ${args.length}; the path ends before it`);
|
|
771
|
+
break;
|
|
748
772
|
}
|
|
749
773
|
}
|
|
750
774
|
return b.build();
|
|
@@ -1042,8 +1066,7 @@ function measureError(samples, fit) {
|
|
|
1042
1066
|
let worstError = 0;
|
|
1043
1067
|
const a = samples[0];
|
|
1044
1068
|
for (let i = 1; i < samples.length - 1; i++) {
|
|
1045
|
-
const
|
|
1046
|
-
const q = cubicPointAt(a, fit.cp1, fit.cp2, fit.end, t);
|
|
1069
|
+
const q = cubicPointAt(a, fit.cp1, fit.cp2, fit.end, fit.ts[i]);
|
|
1047
1070
|
const dx = samples[i].x - q.x;
|
|
1048
1071
|
const dy = samples[i].y - q.y;
|
|
1049
1072
|
const sq = dx * dx + dy * dy;
|
|
@@ -1061,7 +1084,7 @@ function fitOneCubic(samples) {
|
|
|
1061
1084
|
const tStart = unit(sub2(samples[1], a));
|
|
1062
1085
|
const tEnd = unit(sub2(samples[n - 2], e));
|
|
1063
1086
|
const ts = chordLengthParam(samples);
|
|
1064
|
-
if (ts === null) return { cp1: { ...a }, cp2: { ...e }, end: e };
|
|
1087
|
+
if (ts === null) return { cp1: { ...a }, cp2: { ...e }, end: e, ts: samples.map(() => 0) };
|
|
1065
1088
|
let fit = solveLS(samples, ts, a, e, tStart, tEnd);
|
|
1066
1089
|
for (let pass = 0; pass < 4; pass++) {
|
|
1067
1090
|
reparameterize(samples, ts, a, e, fit);
|
|
@@ -1121,7 +1144,8 @@ function solveLS(samples, ts, a, e, tStart, tEnd) {
|
|
|
1121
1144
|
return {
|
|
1122
1145
|
cp1: { x: a.x + tStart.x * alpha1, y: a.y + tStart.y * alpha1 },
|
|
1123
1146
|
cp2: { x: e.x + tEnd.x * alpha2, y: e.y + tEnd.y * alpha2 },
|
|
1124
|
-
end: e
|
|
1147
|
+
end: e,
|
|
1148
|
+
ts
|
|
1125
1149
|
};
|
|
1126
1150
|
}
|
|
1127
1151
|
function reparameterize(samples, ts, a, e, fit) {
|
|
@@ -1165,6 +1189,72 @@ function emitStraightCubic(b, a, c) {
|
|
|
1165
1189
|
b.curveTo(cp1x, cp1y, cp2x, cp2y, c.x, c.y);
|
|
1166
1190
|
}
|
|
1167
1191
|
|
|
1192
|
+
// src/pathSubpaths.ts
|
|
1193
|
+
function flatSubpaths(path, tolerance) {
|
|
1194
|
+
const { commands, coords } = path;
|
|
1195
|
+
const closed = [];
|
|
1196
|
+
const open = [];
|
|
1197
|
+
let sub3 = [];
|
|
1198
|
+
forEachSegment(commands, coords, (cmd, ci, curX, curY, _i, opensSubpath) => {
|
|
1199
|
+
if (opensSubpath) sub3 = [curX, curY];
|
|
1200
|
+
switch (cmd) {
|
|
1201
|
+
case PATH_M:
|
|
1202
|
+
if (sub3.length >= 2) open.push(sub3);
|
|
1203
|
+
sub3 = [coords[ci], coords[ci + 1]];
|
|
1204
|
+
break;
|
|
1205
|
+
case PATH_L:
|
|
1206
|
+
sub3.push(coords[ci], coords[ci + 1]);
|
|
1207
|
+
break;
|
|
1208
|
+
case PATH_C:
|
|
1209
|
+
flattenCubic(
|
|
1210
|
+
curX,
|
|
1211
|
+
curY,
|
|
1212
|
+
coords[ci],
|
|
1213
|
+
coords[ci + 1],
|
|
1214
|
+
coords[ci + 2],
|
|
1215
|
+
coords[ci + 3],
|
|
1216
|
+
coords[ci + 4],
|
|
1217
|
+
coords[ci + 5],
|
|
1218
|
+
tolerance,
|
|
1219
|
+
sub3
|
|
1220
|
+
);
|
|
1221
|
+
break;
|
|
1222
|
+
case PATH_Q:
|
|
1223
|
+
flattenQuadratic(
|
|
1224
|
+
curX,
|
|
1225
|
+
curY,
|
|
1226
|
+
coords[ci],
|
|
1227
|
+
coords[ci + 1],
|
|
1228
|
+
coords[ci + 2],
|
|
1229
|
+
coords[ci + 3],
|
|
1230
|
+
tolerance,
|
|
1231
|
+
sub3
|
|
1232
|
+
);
|
|
1233
|
+
break;
|
|
1234
|
+
case PATH_Z:
|
|
1235
|
+
if (sub3.length >= 6) closed.push(sub3);
|
|
1236
|
+
else if (sub3.length >= 2) open.push(sub3);
|
|
1237
|
+
sub3 = [];
|
|
1238
|
+
break;
|
|
1239
|
+
default:
|
|
1240
|
+
throw new Error(`pathHitTest: unknown command ${cmd}`);
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
if (sub3.length >= 2) open.push(sub3);
|
|
1244
|
+
return { closed, open };
|
|
1245
|
+
}
|
|
1246
|
+
function regionSubpaths(path, opts) {
|
|
1247
|
+
const flat = flatSubpaths(path, opts.tolerance ?? DEFAULT_FLATTEN_TOLERANCE);
|
|
1248
|
+
if (!fillsOpenSubpaths(path)) return flat;
|
|
1249
|
+
return {
|
|
1250
|
+
closed: [...flat.closed, ...flat.open.filter((sub3) => sub3.length >= 6)],
|
|
1251
|
+
open: flat.open.filter((sub3) => sub3.length < 6)
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
function closedSubpaths(path, opts) {
|
|
1255
|
+
return regionSubpaths(path, opts).closed;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1168
1258
|
// src/screenBand.ts
|
|
1169
1259
|
function stretchOf(m) {
|
|
1170
1260
|
const e = (m.a + m.d) / 2;
|
|
@@ -1268,61 +1358,6 @@ function distToEllipse(e0, e1, y0, y1) {
|
|
|
1268
1358
|
}
|
|
1269
1359
|
|
|
1270
1360
|
// src/pathHitTest.ts
|
|
1271
|
-
function flatSubpaths(path, tolerance) {
|
|
1272
|
-
const { commands, coords } = path;
|
|
1273
|
-
const closed = [];
|
|
1274
|
-
const open = [];
|
|
1275
|
-
let sub3 = [];
|
|
1276
|
-
forEachSegment(commands, coords, (cmd, ci, curX, curY) => {
|
|
1277
|
-
switch (cmd) {
|
|
1278
|
-
case PATH_M:
|
|
1279
|
-
if (sub3.length >= 2) open.push(sub3);
|
|
1280
|
-
sub3 = [coords[ci], coords[ci + 1]];
|
|
1281
|
-
break;
|
|
1282
|
-
case PATH_L:
|
|
1283
|
-
sub3.push(coords[ci], coords[ci + 1]);
|
|
1284
|
-
break;
|
|
1285
|
-
case PATH_C:
|
|
1286
|
-
flattenCubic(
|
|
1287
|
-
curX,
|
|
1288
|
-
curY,
|
|
1289
|
-
coords[ci],
|
|
1290
|
-
coords[ci + 1],
|
|
1291
|
-
coords[ci + 2],
|
|
1292
|
-
coords[ci + 3],
|
|
1293
|
-
coords[ci + 4],
|
|
1294
|
-
coords[ci + 5],
|
|
1295
|
-
tolerance,
|
|
1296
|
-
sub3
|
|
1297
|
-
);
|
|
1298
|
-
break;
|
|
1299
|
-
case PATH_Q:
|
|
1300
|
-
flattenQuadratic(
|
|
1301
|
-
curX,
|
|
1302
|
-
curY,
|
|
1303
|
-
coords[ci],
|
|
1304
|
-
coords[ci + 1],
|
|
1305
|
-
coords[ci + 2],
|
|
1306
|
-
coords[ci + 3],
|
|
1307
|
-
tolerance,
|
|
1308
|
-
sub3
|
|
1309
|
-
);
|
|
1310
|
-
break;
|
|
1311
|
-
case PATH_Z:
|
|
1312
|
-
if (sub3.length >= 6) closed.push(sub3);
|
|
1313
|
-
else if (sub3.length >= 2) open.push(sub3);
|
|
1314
|
-
sub3 = [];
|
|
1315
|
-
break;
|
|
1316
|
-
default:
|
|
1317
|
-
throw new Error(`pathHitTest: unknown command ${cmd}`);
|
|
1318
|
-
}
|
|
1319
|
-
});
|
|
1320
|
-
if (sub3.length >= 2) open.push(sub3);
|
|
1321
|
-
return { closed, open };
|
|
1322
|
-
}
|
|
1323
|
-
function closedSubpaths(path, opts) {
|
|
1324
|
-
return flatSubpaths(path, opts.tolerance ?? DEFAULT_FLATTEN_TOLERANCE).closed;
|
|
1325
|
-
}
|
|
1326
1361
|
function pointInPath(path, x, y, opts = {}) {
|
|
1327
1362
|
if (path.kind === "rect") {
|
|
1328
1363
|
return x >= path.x && x <= path.x + path.width && y >= path.y && y <= path.y + path.height;
|
|
@@ -1349,6 +1384,7 @@ function strokeHitTest(path, x, y, threshold, opts = {}) {
|
|
|
1349
1384
|
const [a, b, c, d] = slop.transform;
|
|
1350
1385
|
const m = { a, b, c, d };
|
|
1351
1386
|
const st = stretchOf(m);
|
|
1387
|
+
if (st.s1 === 0) return false;
|
|
1352
1388
|
if (isSimilarity(st)) {
|
|
1353
1389
|
return strokeHitTest(path, x, y, threshold + slop.px / st.s1, { tolerance: opts.tolerance });
|
|
1354
1390
|
}
|
|
@@ -1519,7 +1555,7 @@ function polygonContainsPath(polygon, path, opts = {}) {
|
|
|
1519
1555
|
if (path.kind === "rect") {
|
|
1520
1556
|
subpaths = [flattenVerts(rectToVerts(path))];
|
|
1521
1557
|
} else {
|
|
1522
|
-
const { closed, open } =
|
|
1558
|
+
const { closed, open } = regionSubpaths(path, opts);
|
|
1523
1559
|
subpaths = [...closed, ...open];
|
|
1524
1560
|
}
|
|
1525
1561
|
if (subpaths.length === 0) return false;
|
|
@@ -1533,14 +1569,349 @@ function polygonContainsPath(polygon, path, opts = {}) {
|
|
|
1533
1569
|
}
|
|
1534
1570
|
function polygonIntersectsPath(polygon, path, opts = {}) {
|
|
1535
1571
|
if (polygon.length < 3) return false;
|
|
1536
|
-
|
|
1537
|
-
|
|
1572
|
+
const filled = opts.filled !== false;
|
|
1573
|
+
if (path.kind === "rect" && filled) return polygonsIntersect(rectToVerts(path), polygon);
|
|
1574
|
+
const { closed, open } = path.kind === "rect" ? { closed: [flattenVerts(rectToVerts(path))], open: [] } : regionSubpaths(path, opts);
|
|
1538
1575
|
const flatPoly = flattenVerts(polygon);
|
|
1539
1576
|
if (anyVertexInPolygon(closed, flatPoly) || anyVertexInPolygon(open, flatPoly)) return true;
|
|
1540
1577
|
if (anyEdgeCrossesPolygon(closed, polygon) || anyOpenEdgeCrossesPolygon(open, polygon)) {
|
|
1541
1578
|
return true;
|
|
1542
1579
|
}
|
|
1543
|
-
return closed.length > 0 && pointInPath(path, polygon[0].x, polygon[0].y, opts);
|
|
1580
|
+
return filled && closed.length > 0 && pointInPath(path, polygon[0].x, polygon[0].y, opts);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
// src/paths/markers.ts
|
|
1584
|
+
function circlePath(cx, cy, r, segments = 32) {
|
|
1585
|
+
const cmds = new Uint8Array(segments + 1);
|
|
1586
|
+
const coords = new Float32Array(segments * 2);
|
|
1587
|
+
cmds[0] = PATH_M;
|
|
1588
|
+
coords[0] = cx + r;
|
|
1589
|
+
coords[1] = cy;
|
|
1590
|
+
for (let i = 1; i < segments; i++) {
|
|
1591
|
+
cmds[i] = PATH_L;
|
|
1592
|
+
const theta = i / segments * Math.PI * 2;
|
|
1593
|
+
coords[i * 2] = cx + r * Math.cos(theta);
|
|
1594
|
+
coords[i * 2 + 1] = cy + r * Math.sin(theta);
|
|
1595
|
+
}
|
|
1596
|
+
cmds[segments] = PATH_Z;
|
|
1597
|
+
return { kind: "polygon", commands: cmds, coords, fillRule: "nonzero" };
|
|
1598
|
+
}
|
|
1599
|
+
function squarePath(cx, cy, size) {
|
|
1600
|
+
const half = size / 2;
|
|
1601
|
+
const x0 = cx - half, y0 = cy - half;
|
|
1602
|
+
const x1 = cx + half, y1 = cy + half;
|
|
1603
|
+
return {
|
|
1604
|
+
kind: "polygon",
|
|
1605
|
+
commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]),
|
|
1606
|
+
coords: new Float32Array([x0, y0, x1, y0, x1, y1, x0, y1]),
|
|
1607
|
+
fillRule: "nonzero"
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
function rectMarkerPath(x, y, width, height) {
|
|
1611
|
+
return {
|
|
1612
|
+
kind: "polygon",
|
|
1613
|
+
commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]),
|
|
1614
|
+
coords: Float32Array.from(rectToContour(x, y, width, height)),
|
|
1615
|
+
fillRule: "nonzero"
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
function roundRectPath(x, y, width, height, r, cornerSamples = 8) {
|
|
1619
|
+
const radius = Math.max(0, Math.min(r, Math.min(width, height) / 2));
|
|
1620
|
+
if (radius === 0) return rectMarkerPath(x, y, width, height);
|
|
1621
|
+
const HALF_PI = Math.PI / 2;
|
|
1622
|
+
const corners = [
|
|
1623
|
+
[x + radius, y + radius, Math.PI],
|
|
1624
|
+
[x + width - radius, y + radius, -HALF_PI],
|
|
1625
|
+
[x + width - radius, y + height - radius, 0],
|
|
1626
|
+
[x + radius, y + height - radius, HALF_PI]
|
|
1627
|
+
];
|
|
1628
|
+
const perCorner = cornerSamples + 1;
|
|
1629
|
+
const count = corners.length * perCorner;
|
|
1630
|
+
const cmds = new Uint8Array(count + 1);
|
|
1631
|
+
const coords = new Float32Array(count * 2);
|
|
1632
|
+
let i = 0;
|
|
1633
|
+
for (const [cx, cy, start] of corners) {
|
|
1634
|
+
for (let s = 0; s <= cornerSamples; s++) {
|
|
1635
|
+
const theta = start + s / cornerSamples * HALF_PI;
|
|
1636
|
+
cmds[i] = i === 0 ? PATH_M : PATH_L;
|
|
1637
|
+
coords[i * 2] = cx + radius * Math.cos(theta);
|
|
1638
|
+
coords[i * 2 + 1] = cy + radius * Math.sin(theta);
|
|
1639
|
+
i++;
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
cmds[count] = PATH_Z;
|
|
1643
|
+
return { kind: "polygon", commands: cmds, coords, fillRule: "nonzero" };
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// src/paths/anchors.ts
|
|
1647
|
+
function pathToAnchors(path) {
|
|
1648
|
+
const { commands, coords } = path;
|
|
1649
|
+
const anchors = [];
|
|
1650
|
+
const closed = [];
|
|
1651
|
+
let current = null;
|
|
1652
|
+
forEachSegment(commands, coords, (cmd, ci) => {
|
|
1653
|
+
switch (cmd) {
|
|
1654
|
+
case PATH_M: {
|
|
1655
|
+
if (current) {
|
|
1656
|
+
anchors.push(current);
|
|
1657
|
+
closed.push(false);
|
|
1658
|
+
}
|
|
1659
|
+
current = [{ x: coords[ci], y: coords[ci + 1] }];
|
|
1660
|
+
break;
|
|
1661
|
+
}
|
|
1662
|
+
case PATH_L: {
|
|
1663
|
+
if (!current) throw new Error("pathToAnchors: L without prior M");
|
|
1664
|
+
current.push({ x: coords[ci], y: coords[ci + 1] });
|
|
1665
|
+
break;
|
|
1666
|
+
}
|
|
1667
|
+
case PATH_C: {
|
|
1668
|
+
if (!current) throw new Error("pathToAnchors: C without prior M");
|
|
1669
|
+
const prev = current[current.length - 1];
|
|
1670
|
+
prev.outHandle = { x: coords[ci], y: coords[ci + 1] };
|
|
1671
|
+
current.push({
|
|
1672
|
+
x: coords[ci + 4],
|
|
1673
|
+
y: coords[ci + 5],
|
|
1674
|
+
inHandle: { x: coords[ci + 2], y: coords[ci + 3] }
|
|
1675
|
+
});
|
|
1676
|
+
break;
|
|
1677
|
+
}
|
|
1678
|
+
case PATH_Q: {
|
|
1679
|
+
if (!current) throw new Error("pathToAnchors: Q without prior M");
|
|
1680
|
+
const handle = { x: coords[ci], y: coords[ci + 1] };
|
|
1681
|
+
const prev = current[current.length - 1];
|
|
1682
|
+
prev.outHandle = handle;
|
|
1683
|
+
current.push({ x: coords[ci + 2], y: coords[ci + 3], inHandle: { ...handle } });
|
|
1684
|
+
break;
|
|
1685
|
+
}
|
|
1686
|
+
case PATH_Z: {
|
|
1687
|
+
if (current) {
|
|
1688
|
+
foldClosingCurve(current);
|
|
1689
|
+
anchors.push(current);
|
|
1690
|
+
closed.push(true);
|
|
1691
|
+
current = null;
|
|
1692
|
+
}
|
|
1693
|
+
break;
|
|
1694
|
+
}
|
|
1695
|
+
default:
|
|
1696
|
+
throw new Error(`pathToAnchors: unknown command ${cmd}`);
|
|
1697
|
+
}
|
|
1698
|
+
});
|
|
1699
|
+
if (current) {
|
|
1700
|
+
anchors.push(current);
|
|
1701
|
+
closed.push(false);
|
|
1702
|
+
}
|
|
1703
|
+
return { anchors, closed };
|
|
1704
|
+
}
|
|
1705
|
+
function foldClosingCurve(sub3) {
|
|
1706
|
+
if (sub3.length < 2) return;
|
|
1707
|
+
const first = sub3[0];
|
|
1708
|
+
const last = sub3[sub3.length - 1];
|
|
1709
|
+
if (!last.inHandle || last.x !== first.x || last.y !== first.y) return;
|
|
1710
|
+
sub3.pop();
|
|
1711
|
+
first.inHandle = last.inHandle;
|
|
1712
|
+
}
|
|
1713
|
+
function anchorsToPath(anchors, closed, like) {
|
|
1714
|
+
const b = new PathBuilder();
|
|
1715
|
+
for (let s = 0; s < anchors.length; s++) {
|
|
1716
|
+
const sub3 = anchors[s];
|
|
1717
|
+
if (sub3.length === 0) continue;
|
|
1718
|
+
b.moveTo(sub3[0].x, sub3[0].y);
|
|
1719
|
+
for (let i = 1; i < sub3.length; i++) {
|
|
1720
|
+
const prev = sub3[i - 1];
|
|
1721
|
+
const cur = sub3[i];
|
|
1722
|
+
const hasHandle = prev.outHandle != null || cur.inHandle != null;
|
|
1723
|
+
if (!hasHandle) {
|
|
1724
|
+
b.lineTo(cur.x, cur.y);
|
|
1725
|
+
} else {
|
|
1726
|
+
const c1 = prev.outHandle ?? { x: prev.x, y: prev.y };
|
|
1727
|
+
const c2 = cur.inHandle ?? { x: cur.x, y: cur.y };
|
|
1728
|
+
b.curveTo(c1.x, c1.y, c2.x, c2.y, cur.x, cur.y);
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
if (closed[s]) {
|
|
1732
|
+
const last = sub3[sub3.length - 1];
|
|
1733
|
+
const first = sub3[0];
|
|
1734
|
+
const hasHandle = last.outHandle != null || first.inHandle != null;
|
|
1735
|
+
if (hasHandle) {
|
|
1736
|
+
const c1 = last.outHandle ?? { x: last.x, y: last.y };
|
|
1737
|
+
const c2 = first.inHandle ?? { x: first.x, y: first.y };
|
|
1738
|
+
b.curveTo(c1.x, c1.y, c2.x, c2.y, first.x, first.y);
|
|
1739
|
+
}
|
|
1740
|
+
b.close();
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
const built = b.build();
|
|
1744
|
+
return like ? { ...like, commands: built.commands, coords: built.coords } : built;
|
|
1745
|
+
}
|
|
1746
|
+
var SMOOTH_THRESHOLD = 1e-3;
|
|
1747
|
+
function isAnchorSmooth(a) {
|
|
1748
|
+
if (!a.inHandle || !a.outHandle) return false;
|
|
1749
|
+
const inDX = a.inHandle.x - a.x;
|
|
1750
|
+
const inDY = a.inHandle.y - a.y;
|
|
1751
|
+
const outDX = a.outHandle.x - a.x;
|
|
1752
|
+
const outDY = a.outHandle.y - a.y;
|
|
1753
|
+
const inLen = Math.hypot(inDX, inDY);
|
|
1754
|
+
const outLen = Math.hypot(outDX, outDY);
|
|
1755
|
+
if (inLen === 0 || outLen === 0) return false;
|
|
1756
|
+
const cross2 = (inDX * outDY - inDY * outDX) / (inLen * outLen);
|
|
1757
|
+
return Math.abs(cross2) < SMOOTH_THRESHOLD;
|
|
1758
|
+
}
|
|
1759
|
+
function countPathAnchors(path) {
|
|
1760
|
+
if (path.kind === "rect") return 4;
|
|
1761
|
+
const cmds = path.commands;
|
|
1762
|
+
let n = 0;
|
|
1763
|
+
for (let i = 0; i < cmds.length; i++) {
|
|
1764
|
+
const c = cmds[i];
|
|
1765
|
+
if (c === PATH_M || c === PATH_L || c === PATH_C || c === PATH_Q) n++;
|
|
1766
|
+
}
|
|
1767
|
+
return n;
|
|
1768
|
+
}
|
|
1769
|
+
function segmentEnds(anchors, closed, sub3, segIdx) {
|
|
1770
|
+
const s = anchors[sub3];
|
|
1771
|
+
if (!s || segIdx < 0) return null;
|
|
1772
|
+
if (segIdx + 1 < s.length) return { a: s[segIdx], b: s[segIdx + 1] };
|
|
1773
|
+
if (closed?.[sub3] && s.length > 1 && segIdx === s.length - 1) return { a: s[segIdx], b: s[0] };
|
|
1774
|
+
return null;
|
|
1775
|
+
}
|
|
1776
|
+
function isStraightSegment(a, b) {
|
|
1777
|
+
return a.outHandle == null && b.inHandle == null;
|
|
1778
|
+
}
|
|
1779
|
+
function nearestOnSegment(a, b, x, y) {
|
|
1780
|
+
const p1 = a.outHandle ?? a;
|
|
1781
|
+
const p2 = b.inHandle ?? b;
|
|
1782
|
+
const hit = isStraightSegment(a, b) ? nearestOnLine(x, y, a.x, a.y, b.x, b.y) : nearestOnCubic(x, y, a.x, a.y, p1.x, p1.y, p2.x, p2.y, b.x, b.y);
|
|
1783
|
+
return { t: hit.t, d2: hit.dist * hit.dist };
|
|
1784
|
+
}
|
|
1785
|
+
function nearestSegmentT(anchors, wx, wy, closed) {
|
|
1786
|
+
let bestD2 = Infinity;
|
|
1787
|
+
let best = null;
|
|
1788
|
+
for (let s = 0; s < anchors.length; s++) {
|
|
1789
|
+
const segCount = anchors[s].length - (closed?.[s] ? 0 : 1);
|
|
1790
|
+
for (let i = 0; i < segCount; i++) {
|
|
1791
|
+
const ends = segmentEnds(anchors, closed, s, i);
|
|
1792
|
+
if (!ends) continue;
|
|
1793
|
+
const hit = nearestOnSegment(ends.a, ends.b, wx, wy);
|
|
1794
|
+
if (hit.d2 < bestD2) {
|
|
1795
|
+
bestD2 = hit.d2;
|
|
1796
|
+
best = { sub: s, segIdx: i, t: hit.t };
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return best;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
// src/glMat3.ts
|
|
1804
|
+
function create(a, b, c, d, tx, ty) {
|
|
1805
|
+
return new Float64Array([a, b, 0, c, d, 0, tx, ty, 1]);
|
|
1806
|
+
}
|
|
1807
|
+
function identity2() {
|
|
1808
|
+
return create(1, 0, 0, 1, 0, 0);
|
|
1809
|
+
}
|
|
1810
|
+
function multiply2(out, m) {
|
|
1811
|
+
const a = out[0], b = out[1];
|
|
1812
|
+
const c = out[3], d = out[4];
|
|
1813
|
+
const tx = out[6], ty = out[7];
|
|
1814
|
+
const ma = m[0], mb = m[1];
|
|
1815
|
+
const mc = m[3], md = m[4];
|
|
1816
|
+
const mtx = m[6], mty = m[7];
|
|
1817
|
+
return create(
|
|
1818
|
+
a * ma + c * mb,
|
|
1819
|
+
// new a
|
|
1820
|
+
b * ma + d * mb,
|
|
1821
|
+
// new b
|
|
1822
|
+
a * mc + c * md,
|
|
1823
|
+
// new c
|
|
1824
|
+
b * mc + d * md,
|
|
1825
|
+
// new d
|
|
1826
|
+
a * mtx + c * mty + tx,
|
|
1827
|
+
// new tx
|
|
1828
|
+
b * mtx + d * mty + ty
|
|
1829
|
+
// new ty
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
function translated(m, tx, ty) {
|
|
1833
|
+
const t = create(1, 0, 0, 1, tx, ty);
|
|
1834
|
+
return multiply2(m, t);
|
|
1835
|
+
}
|
|
1836
|
+
function scaled(m, sx, sy) {
|
|
1837
|
+
const s = create(sx, 0, 0, sy, 0, 0);
|
|
1838
|
+
return multiply2(m, s);
|
|
1839
|
+
}
|
|
1840
|
+
function toAffine(m) {
|
|
1841
|
+
return [m[0], m[1], m[3], m[4], m[6], m[7]];
|
|
1842
|
+
}
|
|
1843
|
+
function fromAffine(a) {
|
|
1844
|
+
return create(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
1845
|
+
}
|
|
1846
|
+
function invert2(m) {
|
|
1847
|
+
const inv = invert(toAffine(m));
|
|
1848
|
+
return inv && fromAffine(inv);
|
|
1849
|
+
}
|
|
1850
|
+
function toUniform(m) {
|
|
1851
|
+
return Float32Array.from(m);
|
|
1852
|
+
}
|
|
1853
|
+
function apply(m, x, y) {
|
|
1854
|
+
const a = m[0], b = m[1];
|
|
1855
|
+
const c = m[3], d = m[4];
|
|
1856
|
+
const tx = m[6], ty = m[7];
|
|
1857
|
+
return [a * x + c * y + tx, b * x + d * y + ty];
|
|
1858
|
+
}
|
|
1859
|
+
function screenToClip(width, height) {
|
|
1860
|
+
return create(
|
|
1861
|
+
2 / width,
|
|
1862
|
+
// a
|
|
1863
|
+
0,
|
|
1864
|
+
// b
|
|
1865
|
+
0,
|
|
1866
|
+
// c
|
|
1867
|
+
-2 / height,
|
|
1868
|
+
// d
|
|
1869
|
+
-1,
|
|
1870
|
+
// tx
|
|
1871
|
+
1
|
|
1872
|
+
// ty
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
function meanScaleOf(m) {
|
|
1876
|
+
return Math.sqrt(Math.abs(m[0] * m[4] - m[1] * m[3]));
|
|
1877
|
+
}
|
|
1878
|
+
function minScaleOf(m) {
|
|
1879
|
+
const sum = m[0] * m[0] + m[1] * m[1] + m[3] * m[3] + m[4] * m[4];
|
|
1880
|
+
const det = m[0] * m[4] - m[1] * m[3];
|
|
1881
|
+
return Math.sqrt(Math.max(0, (sum - Math.sqrt(Math.max(0, sum * sum - 4 * det * det))) / 2));
|
|
1882
|
+
}
|
|
1883
|
+
var mat3 = {
|
|
1884
|
+
identity: identity2,
|
|
1885
|
+
toAffine,
|
|
1886
|
+
fromAffine,
|
|
1887
|
+
multiply: multiply2,
|
|
1888
|
+
translated,
|
|
1889
|
+
scaled,
|
|
1890
|
+
invert: invert2,
|
|
1891
|
+
toUniform,
|
|
1892
|
+
apply,
|
|
1893
|
+
screenToClip,
|
|
1894
|
+
meanScaleOf,
|
|
1895
|
+
minScaleOf
|
|
1896
|
+
};
|
|
1897
|
+
|
|
1898
|
+
// src/viewToMat3.ts
|
|
1899
|
+
function viewToMat3(view) {
|
|
1900
|
+
const sx = view.scale.x;
|
|
1901
|
+
const sy = view.scale.y;
|
|
1902
|
+
const tx = -view.x * sx + 0;
|
|
1903
|
+
const ty = -view.y * sy + 0;
|
|
1904
|
+
return new Float64Array([
|
|
1905
|
+
sx,
|
|
1906
|
+
0,
|
|
1907
|
+
0,
|
|
1908
|
+
0,
|
|
1909
|
+
sy,
|
|
1910
|
+
0,
|
|
1911
|
+
tx,
|
|
1912
|
+
ty,
|
|
1913
|
+
1
|
|
1914
|
+
]);
|
|
1544
1915
|
}
|
|
1545
1916
|
|
|
1546
1917
|
// src/place.ts
|
|
@@ -1764,6 +2135,7 @@ function cubicBezierEasing(x1, y1, x2, y2) {
|
|
|
1764
2135
|
};
|
|
1765
2136
|
}
|
|
1766
2137
|
var bezierCache = /* @__PURE__ */ new Map();
|
|
2138
|
+
var BEZIER_CACHE_LIMIT = 256;
|
|
1767
2139
|
function isBezier(spec) {
|
|
1768
2140
|
return typeof spec === "object" && spec !== null && "bezier" in spec;
|
|
1769
2141
|
}
|
|
@@ -1781,6 +2153,7 @@ function resolveEasing(spec) {
|
|
|
1781
2153
|
let fn = bezierCache.get(key);
|
|
1782
2154
|
if (!fn) {
|
|
1783
2155
|
fn = cubicBezierEasing(x1, y1, x2, y2);
|
|
2156
|
+
if (bezierCache.size >= BEZIER_CACHE_LIMIT) bezierCache.delete(bezierCache.keys().next().value);
|
|
1784
2157
|
bezierCache.set(key, fn);
|
|
1785
2158
|
}
|
|
1786
2159
|
return fn;
|
|
@@ -1788,6 +2161,425 @@ function resolveEasing(spec) {
|
|
|
1788
2161
|
throw new Error("resolveEasing: unrecognized easing spec");
|
|
1789
2162
|
}
|
|
1790
2163
|
|
|
1791
|
-
|
|
2164
|
+
// src/meanScale.ts
|
|
2165
|
+
function meanScale(s) {
|
|
2166
|
+
return Math.sqrt(Math.abs(s.x * s.y));
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
// src/pxExtent.ts
|
|
2170
|
+
function pxExtent(px, scale2, rotation = 0) {
|
|
2171
|
+
if (!rotation) {
|
|
2172
|
+
return {
|
|
2173
|
+
x: px / Math.abs(scale2.x),
|
|
2174
|
+
y: px / Math.abs(scale2.y)
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
2177
|
+
const c = Math.cos(rotation), s = Math.sin(rotation);
|
|
2178
|
+
return {
|
|
2179
|
+
x: px * Math.hypot(c / scale2.x, s / scale2.y),
|
|
2180
|
+
y: px * Math.hypot(s / scale2.x, c / scale2.y)
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
function scaleDelta(dx, dy, scale2) {
|
|
2184
|
+
return { x: dx * scale2.x, y: dy * scale2.y };
|
|
2185
|
+
}
|
|
2186
|
+
function withinPxBox(dx, dy, px, scale2) {
|
|
2187
|
+
const s = scaleDelta(dx, dy, scale2);
|
|
2188
|
+
return Math.abs(s.x) <= px && Math.abs(s.y) <= px;
|
|
2189
|
+
}
|
|
2190
|
+
function withinPxRadius(dx, dy, px, scale2) {
|
|
2191
|
+
const s = scaleDelta(dx, dy, scale2);
|
|
2192
|
+
return s.x * s.x + s.y * s.y <= px * px;
|
|
2193
|
+
}
|
|
2194
|
+
function standoff(anchor, normal, px, scale2) {
|
|
2195
|
+
const k = Math.sign(scale2.x * scale2.y) || 1;
|
|
2196
|
+
let nx = normal.x * scale2.y * k;
|
|
2197
|
+
let ny = normal.y * scale2.x * k;
|
|
2198
|
+
const l = Math.hypot(nx, ny) || 1;
|
|
2199
|
+
nx /= l;
|
|
2200
|
+
ny /= l;
|
|
2201
|
+
return { x: anchor.x + nx * px / scale2.x, y: anchor.y + ny * px / scale2.y, nx, ny };
|
|
2202
|
+
}
|
|
2203
|
+
function screenAngleOf(rotation, scale2) {
|
|
2204
|
+
return Math.atan2(Math.sin(rotation) * scale2.y, Math.cos(rotation) * scale2.x);
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
// src/poseRotation.ts
|
|
2208
|
+
function poseRotationOf(pose) {
|
|
2209
|
+
const p = pose;
|
|
2210
|
+
if (p.rotation && p.x != null && p.y != null && p.width != null && p.height != null) {
|
|
2211
|
+
return { cx: p.x + p.width / 2, cy: p.y + p.height / 2, rotation: p.rotation };
|
|
2212
|
+
}
|
|
2213
|
+
return null;
|
|
2214
|
+
}
|
|
2215
|
+
function rotatePathAround(path, cx, cy, rotation) {
|
|
2216
|
+
if (path.kind === "rect") {
|
|
2217
|
+
return rotateRectCorners(path.x, path.y, path.width, path.height, cx, cy, rotation);
|
|
2218
|
+
}
|
|
2219
|
+
return rotatePolygon(path, cx, cy, rotation);
|
|
2220
|
+
}
|
|
2221
|
+
function rotatePolygon(path, cx, cy, rotation) {
|
|
2222
|
+
const cos = Math.cos(rotation);
|
|
2223
|
+
const sin = Math.sin(rotation);
|
|
2224
|
+
const { commands, coords } = path;
|
|
2225
|
+
const next = new Float32Array(coords.length);
|
|
2226
|
+
forEachSegment(commands, coords, (cmd, ci) => {
|
|
2227
|
+
for (let k = 0, len = pathCommandCoordCount(cmd); k < len; k += 2) {
|
|
2228
|
+
const dx = coords[ci + k] - cx;
|
|
2229
|
+
const dy = coords[ci + k + 1] - cy;
|
|
2230
|
+
next[ci + k] = cx + dx * cos - dy * sin;
|
|
2231
|
+
next[ci + k + 1] = cy + dx * sin + dy * cos;
|
|
2232
|
+
}
|
|
2233
|
+
});
|
|
2234
|
+
return { ...path, coords: next };
|
|
2235
|
+
}
|
|
2236
|
+
function rotateRectCorners(x, y, w, h, cx, cy, rotation) {
|
|
2237
|
+
const cos = Math.cos(rotation);
|
|
2238
|
+
const sin = Math.sin(rotation);
|
|
2239
|
+
const rotate2 = (px, py) => {
|
|
2240
|
+
const dx = px - cx;
|
|
2241
|
+
const dy = py - cy;
|
|
2242
|
+
return [cx + dx * cos - dy * sin, cy + dx * sin + dy * cos];
|
|
2243
|
+
};
|
|
2244
|
+
const [x0, y0] = rotate2(x, y);
|
|
2245
|
+
const [x1, y1] = rotate2(x + w, y);
|
|
2246
|
+
const [x2, y2] = rotate2(x + w, y + h);
|
|
2247
|
+
const [x3, y3] = rotate2(x, y + h);
|
|
2248
|
+
const commands = new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]);
|
|
2249
|
+
const coords = new Float32Array([x0, y0, x1, y1, x2, y2, x3, y3]);
|
|
2250
|
+
return { kind: "polygon", commands, coords, fillRule: "nonzero" };
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
// src/poseFrame.ts
|
|
2254
|
+
function poseLinearOf(pose) {
|
|
2255
|
+
const t = pose?.transform;
|
|
2256
|
+
if (!Array.isArray(t) || t.length !== 4) return null;
|
|
2257
|
+
if (t[0] === 1 && t[1] === 0 && t[2] === 0 && t[3] === 1) return null;
|
|
2258
|
+
return t;
|
|
2259
|
+
}
|
|
2260
|
+
function poseFrameOf(pose) {
|
|
2261
|
+
const p = pose;
|
|
2262
|
+
if (!p || p.x == null || p.y == null || p.width == null || p.height == null) return null;
|
|
2263
|
+
const linear2 = poseLinearOf(p);
|
|
2264
|
+
if (!p.rotation && !linear2) return null;
|
|
2265
|
+
const cx = p.x + p.width / 2;
|
|
2266
|
+
const cy = p.y + p.height / 2;
|
|
2267
|
+
if (!linear2) return rotateAboutPoint(cx, cy, p.rotation);
|
|
2268
|
+
const [a, b, c, d] = linear2;
|
|
2269
|
+
const about = [a, b, c, d, cx - (a * cx + c * cy), cy - (b * cx + d * cy)];
|
|
2270
|
+
return p.rotation ? multiply(rotateAboutPoint(cx, cy, p.rotation), about) : about;
|
|
2271
|
+
}
|
|
2272
|
+
function poseFrameInverseOf(pose) {
|
|
2273
|
+
if (!poseLinearOf(pose)) {
|
|
2274
|
+
const r = poseRotationOf(pose);
|
|
2275
|
+
return r && rotateAboutPoint(r.cx, r.cy, -r.rotation);
|
|
2276
|
+
}
|
|
2277
|
+
const frame = poseFrameOf(pose);
|
|
2278
|
+
return frame && invert(frame);
|
|
2279
|
+
}
|
|
2280
|
+
function pathThroughPoseFrame(path, pose) {
|
|
2281
|
+
if (poseLinearOf(pose)) {
|
|
2282
|
+
const frame = poseFrameOf(pose);
|
|
2283
|
+
return frame ? transformPath(path, frame) : path;
|
|
2284
|
+
}
|
|
2285
|
+
const r = poseRotationOf(pose);
|
|
2286
|
+
return r ? rotatePathAround(path, r.cx, r.cy, r.rotation) : path;
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
// src/paths/anchorEdits.ts
|
|
2290
|
+
function anchorCount(set) {
|
|
2291
|
+
let n = 0;
|
|
2292
|
+
for (const sub3 of set.anchors) n += sub3.length;
|
|
2293
|
+
return n;
|
|
2294
|
+
}
|
|
2295
|
+
function locateAnchor(set, flatIndex) {
|
|
2296
|
+
if (flatIndex < 0) return null;
|
|
2297
|
+
let remaining = flatIndex;
|
|
2298
|
+
for (let sub3 = 0; sub3 < set.anchors.length; sub3++) {
|
|
2299
|
+
const len = set.anchors[sub3].length;
|
|
2300
|
+
if (remaining < len) return { sub: sub3, idx: remaining };
|
|
2301
|
+
remaining -= len;
|
|
2302
|
+
}
|
|
2303
|
+
return null;
|
|
2304
|
+
}
|
|
2305
|
+
function flatAnchorIndex(set, sub3, idx) {
|
|
2306
|
+
if (sub3 < 0 || sub3 >= set.anchors.length) return -1;
|
|
2307
|
+
if (idx < 0 || idx >= set.anchors[sub3].length) return -1;
|
|
2308
|
+
let base = 0;
|
|
2309
|
+
for (let s = 0; s < sub3; s++) base += set.anchors[s].length;
|
|
2310
|
+
return base + idx;
|
|
2311
|
+
}
|
|
2312
|
+
function anchorAt(set, flatIndex) {
|
|
2313
|
+
const loc = locateAnchor(set, flatIndex);
|
|
2314
|
+
if (!loc) return null;
|
|
2315
|
+
return set.anchors[loc.sub][loc.idx] ?? null;
|
|
2316
|
+
}
|
|
2317
|
+
function editAnchorSet(path, edit) {
|
|
2318
|
+
const set = pathToAnchors(path);
|
|
2319
|
+
const changed = edit(set);
|
|
2320
|
+
if (changed === false) return null;
|
|
2321
|
+
return anchorsToPath(set.anchors, set.closed, path);
|
|
2322
|
+
}
|
|
2323
|
+
function translateAnchorBy(set, flatIndex, dx, dy) {
|
|
2324
|
+
const a = anchorAt(set, flatIndex);
|
|
2325
|
+
if (!a) return false;
|
|
2326
|
+
a.x += dx;
|
|
2327
|
+
a.y += dy;
|
|
2328
|
+
if (a.inHandle) {
|
|
2329
|
+
a.inHandle.x += dx;
|
|
2330
|
+
a.inHandle.y += dy;
|
|
2331
|
+
}
|
|
2332
|
+
if (a.outHandle) {
|
|
2333
|
+
a.outHandle.x += dx;
|
|
2334
|
+
a.outHandle.y += dy;
|
|
2335
|
+
}
|
|
2336
|
+
return true;
|
|
2337
|
+
}
|
|
2338
|
+
function moveHandleTo(set, flatIndex, side, toX, toY, breakSmoothness) {
|
|
2339
|
+
const a = anchorAt(set, flatIndex);
|
|
2340
|
+
if (!a) return false;
|
|
2341
|
+
const wasSmooth = isAnchorSmooth(a);
|
|
2342
|
+
const target = { x: toX, y: toY };
|
|
2343
|
+
if (side === "out") a.outHandle = target;
|
|
2344
|
+
else a.inHandle = target;
|
|
2345
|
+
const oppositeSide = side === "out" ? "in" : "out";
|
|
2346
|
+
const opposite = oppositeSide === "in" ? a.inHandle : a.outHandle;
|
|
2347
|
+
if (!breakSmoothness && wasSmooth && opposite) {
|
|
2348
|
+
const mirrored = { x: 2 * a.x - target.x, y: 2 * a.y - target.y };
|
|
2349
|
+
if (oppositeSide === "in") a.inHandle = mirrored;
|
|
2350
|
+
else a.outHandle = mirrored;
|
|
2351
|
+
}
|
|
2352
|
+
return true;
|
|
2353
|
+
}
|
|
2354
|
+
function insertAnchorOnSegment(set, args) {
|
|
2355
|
+
const ends = segmentEnds(set.anchors, set.closed, args.sub, args.segIdx);
|
|
2356
|
+
if (!ends) return -1;
|
|
2357
|
+
const { a, b } = ends;
|
|
2358
|
+
const at = args.segIdx + 1;
|
|
2359
|
+
if (isStraightSegment(a, b)) {
|
|
2360
|
+
set.anchors[args.sub].splice(at, 0, {
|
|
2361
|
+
x: a.x + (b.x - a.x) * args.t,
|
|
2362
|
+
y: a.y + (b.y - a.y) * args.t
|
|
2363
|
+
});
|
|
2364
|
+
return flatAnchorIndex(set, args.sub, at);
|
|
2365
|
+
}
|
|
2366
|
+
const p0 = a, p1 = a.outHandle ?? a, p2 = b.inHandle ?? b, p3 = b;
|
|
2367
|
+
const { left, right } = splitCubicAtT(p0, p1, p2, p3, args.t);
|
|
2368
|
+
a.outHandle = { x: left[1].x, y: left[1].y };
|
|
2369
|
+
b.inHandle = { x: right[2].x, y: right[2].y };
|
|
2370
|
+
set.anchors[args.sub].splice(at, 0, {
|
|
2371
|
+
x: left[3].x,
|
|
2372
|
+
y: left[3].y,
|
|
2373
|
+
inHandle: { x: left[2].x, y: left[2].y },
|
|
2374
|
+
outHandle: { x: right[1].x, y: right[1].y }
|
|
2375
|
+
});
|
|
2376
|
+
return flatAnchorIndex(set, args.sub, at);
|
|
2377
|
+
}
|
|
2378
|
+
function segmentAt(set, x, y, opts) {
|
|
2379
|
+
const scale2 = opts.scale ?? { x: 1, y: 1 };
|
|
2380
|
+
const onScreen = (p) => ({ x: p.x * scale2.x, y: p.y * scale2.y });
|
|
2381
|
+
const screenAnchors = set.anchors.map((sub3) => sub3.map((a) => ({
|
|
2382
|
+
...onScreen(a),
|
|
2383
|
+
...a.inHandle ? { inHandle: onScreen(a.inHandle) } : {},
|
|
2384
|
+
...a.outHandle ? { outHandle: onScreen(a.outHandle) } : {}
|
|
2385
|
+
})));
|
|
2386
|
+
const hit = nearestSegmentT(screenAnchors, x * scale2.x, y * scale2.y, set.closed);
|
|
2387
|
+
if (!hit) return null;
|
|
2388
|
+
const ends = segmentEnds(set.anchors, set.closed, hit.sub, hit.segIdx);
|
|
2389
|
+
const point = pointOnSegment(ends.a, ends.b, hit.t);
|
|
2390
|
+
const tol = opts.tolerancePx;
|
|
2391
|
+
if (!withinPxRadius(point.x - x, point.y - y, tol, scale2)) return null;
|
|
2392
|
+
if (withinPxRadius(point.x - ends.a.x, point.y - ends.a.y, tol, scale2)) return null;
|
|
2393
|
+
if (withinPxRadius(point.x - ends.b.x, point.y - ends.b.y, tol, scale2)) return null;
|
|
2394
|
+
return { sub: hit.sub, segIdx: hit.segIdx, t: hit.t, x: point.x, y: point.y };
|
|
2395
|
+
}
|
|
2396
|
+
function pointOnSegment(a, b, t) {
|
|
2397
|
+
if (isStraightSegment(a, b)) return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
2398
|
+
return cubicPointAt(a, a.outHandle ?? a, b.inHandle ?? b, b, t);
|
|
2399
|
+
}
|
|
2400
|
+
function deleteAnchorsAt(set, flatIndexes) {
|
|
2401
|
+
const bySub = /* @__PURE__ */ new Map();
|
|
2402
|
+
for (const flat of new Set(flatIndexes)) {
|
|
2403
|
+
const loc = locateAnchor(set, flat);
|
|
2404
|
+
if (!loc) continue;
|
|
2405
|
+
const list = bySub.get(loc.sub);
|
|
2406
|
+
if (list) list.push(loc.idx);
|
|
2407
|
+
else bySub.set(loc.sub, [loc.idx]);
|
|
2408
|
+
}
|
|
2409
|
+
if (bySub.size === 0) return false;
|
|
2410
|
+
let survivors = 0;
|
|
2411
|
+
for (let s = 0; s < set.anchors.length; s++) {
|
|
2412
|
+
const doomed = bySub.get(s)?.length ?? 0;
|
|
2413
|
+
if (set.anchors[s].length - doomed >= 2) survivors++;
|
|
2414
|
+
}
|
|
2415
|
+
if (survivors === 0) return false;
|
|
2416
|
+
for (const [s, indices] of bySub) {
|
|
2417
|
+
const sub3 = set.anchors[s];
|
|
2418
|
+
if (!sub3) continue;
|
|
2419
|
+
indices.sort((a, b) => b - a);
|
|
2420
|
+
for (const i of indices) {
|
|
2421
|
+
const wraps = set.closed[s] && sub3.length > 2;
|
|
2422
|
+
const prev = wraps ? sub3[(i - 1 + sub3.length) % sub3.length] : sub3[i - 1];
|
|
2423
|
+
const next = wraps ? sub3[(i + 1) % sub3.length] : sub3[i + 1];
|
|
2424
|
+
if (prev && next) {
|
|
2425
|
+
const { c1, c2 } = fitCubicThroughDeletion(prev, next);
|
|
2426
|
+
prev.outHandle = c1;
|
|
2427
|
+
next.inHandle = c2;
|
|
2428
|
+
}
|
|
2429
|
+
sub3.splice(i, 1);
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
for (let s = set.anchors.length - 1; s >= 0; s--) {
|
|
2433
|
+
if (set.anchors[s].length < 2) {
|
|
2434
|
+
set.anchors.splice(s, 1);
|
|
2435
|
+
set.closed.splice(s, 1);
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
return true;
|
|
2439
|
+
}
|
|
2440
|
+
function openSubpathAt(set, flatIndex) {
|
|
2441
|
+
const loc = locateAnchor(set, flatIndex);
|
|
2442
|
+
if (!loc) return false;
|
|
2443
|
+
if (!set.closed[loc.sub]) return false;
|
|
2444
|
+
const sub3 = set.anchors[loc.sub];
|
|
2445
|
+
if (!sub3) return false;
|
|
2446
|
+
const { inHandle, ...start } = sub3[loc.idx];
|
|
2447
|
+
const end = { x: start.x, y: start.y, ...inHandle ? { inHandle } : {} };
|
|
2448
|
+
set.anchors[loc.sub] = [start, ...sub3.slice(loc.idx + 1), ...sub3.slice(0, loc.idx), end];
|
|
2449
|
+
set.closed[loc.sub] = false;
|
|
2450
|
+
return true;
|
|
2451
|
+
}
|
|
2452
|
+
function anchorsInRect(set, rect) {
|
|
2453
|
+
const x2 = rect.x + rect.width;
|
|
2454
|
+
const y2 = rect.y + rect.height;
|
|
2455
|
+
const hits = [];
|
|
2456
|
+
let flat = 0;
|
|
2457
|
+
for (const sub3 of set.anchors) {
|
|
2458
|
+
for (const a of sub3) {
|
|
2459
|
+
if (a.x >= rect.x && a.x <= x2 && a.y >= rect.y && a.y <= y2) hits.push(flat);
|
|
2460
|
+
flat++;
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
return hits;
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
// src/paths/nearestAnchor.ts
|
|
2467
|
+
function nearestPathAnchor(paths, point, px, scale2, accept) {
|
|
2468
|
+
let best = null;
|
|
2469
|
+
let bestD2 = px * px;
|
|
2470
|
+
for (const { id, path } of paths) {
|
|
2471
|
+
const { anchors, closed } = pathToAnchors(path);
|
|
2472
|
+
for (let sub3 = 0; sub3 < anchors.length; sub3++) {
|
|
2473
|
+
const list = anchors[sub3];
|
|
2474
|
+
for (let idx = 0; idx < list.length; idx++) {
|
|
2475
|
+
const a = list[idx];
|
|
2476
|
+
const s = scaleDelta(a.x - point.x, a.y - point.y, scale2);
|
|
2477
|
+
const d2 = s.x * s.x + s.y * s.y;
|
|
2478
|
+
if (d2 > bestD2 || best !== null && d2 === bestD2) continue;
|
|
2479
|
+
const end = closed[sub3] ? null : idx === list.length - 1 ? "last" : idx === 0 ? "first" : null;
|
|
2480
|
+
const hit = { id, sub: sub3, idx, x: a.x, y: a.y, end };
|
|
2481
|
+
if (accept && !accept(hit)) continue;
|
|
2482
|
+
best = hit;
|
|
2483
|
+
bestD2 = d2;
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
return best;
|
|
2488
|
+
}
|
|
2489
|
+
function reverseAnchors(anchors) {
|
|
2490
|
+
return anchors.map((a) => {
|
|
2491
|
+
const { inHandle, outHandle, ...rest } = a;
|
|
2492
|
+
const r = { ...rest };
|
|
2493
|
+
if (outHandle) r.inHandle = { ...outHandle };
|
|
2494
|
+
if (inHandle) r.outHandle = { ...inHandle };
|
|
2495
|
+
return r;
|
|
2496
|
+
}).reverse();
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// src/paths/pathInWorld.ts
|
|
2500
|
+
function pathInPoseFrame(path, pose) {
|
|
2501
|
+
if (path.kind === "rect") {
|
|
2502
|
+
if (path.x === pose.x && path.y === pose.y && path.width === pose.width && path.height === pose.height) return path;
|
|
2503
|
+
return { kind: "rect", x: pose.x, y: pose.y, width: pose.width, height: pose.height };
|
|
2504
|
+
}
|
|
2505
|
+
const b = boundsOfPath(path);
|
|
2506
|
+
if (b.x === pose.x && b.y === pose.y && b.width === pose.width && b.height === pose.height) {
|
|
2507
|
+
return path;
|
|
2508
|
+
}
|
|
2509
|
+
const m = boxToBox(b.x, b.y, b.width, b.height, pose.x, pose.y, pose.width, pose.height);
|
|
2510
|
+
return transformPath(path, m);
|
|
2511
|
+
}
|
|
2512
|
+
function pathInWorld(path, pose) {
|
|
2513
|
+
const local = pathInPoseFrame(path, pose);
|
|
2514
|
+
const frame = poseFrameOf(pose);
|
|
2515
|
+
if (!frame) return local;
|
|
2516
|
+
return transformPath(local, frame);
|
|
2517
|
+
}
|
|
2518
|
+
function worldEditToStorage(pose, worldPath) {
|
|
2519
|
+
const back = poseFrameInverseOf(pose);
|
|
2520
|
+
const frame = back && poseFrameOf(pose);
|
|
2521
|
+
const unrotated = back ? transformPath(worldPath, back) : worldPath;
|
|
2522
|
+
const b = boundsOfPath(unrotated);
|
|
2523
|
+
const aligned = translatePath(unrotated, -b.x, -b.y);
|
|
2524
|
+
let x = b.x, y = b.y;
|
|
2525
|
+
if (frame) {
|
|
2526
|
+
const [cx, cy] = applyToPoint(frame, b.x + b.width / 2, b.y + b.height / 2);
|
|
2527
|
+
x = cx - b.width / 2;
|
|
2528
|
+
y = cy - b.height / 2;
|
|
2529
|
+
}
|
|
2530
|
+
return {
|
|
2531
|
+
pose: { ...pose, x, y, width: b.width, height: b.height },
|
|
2532
|
+
path: aligned
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
// src/typedArrayJson.ts
|
|
2537
|
+
var TYPED_ARRAY_CONSTRUCTORS = {
|
|
2538
|
+
i8: Int8Array,
|
|
2539
|
+
u8: Uint8Array,
|
|
2540
|
+
u8c: Uint8ClampedArray,
|
|
2541
|
+
i16: Int16Array,
|
|
2542
|
+
u16: Uint16Array,
|
|
2543
|
+
i32: Int32Array,
|
|
2544
|
+
u32: Uint32Array,
|
|
2545
|
+
f32: Float32Array,
|
|
2546
|
+
f64: Float64Array
|
|
2547
|
+
};
|
|
2548
|
+
var TAGS = new Map(
|
|
2549
|
+
Object.keys(TYPED_ARRAY_CONSTRUCTORS).map((tag) => [TYPED_ARRAY_CONSTRUCTORS[tag].name, tag])
|
|
2550
|
+
);
|
|
2551
|
+
var classOf = (value) => Object.prototype.toString.call(value).slice(8, -1);
|
|
2552
|
+
function tagTypedArray(value) {
|
|
2553
|
+
if (!ArrayBuffer.isView(value)) return void 0;
|
|
2554
|
+
const tag = TAGS.get(classOf(value));
|
|
2555
|
+
return tag && { __ta: tag, data: Array.from(value) };
|
|
2556
|
+
}
|
|
2557
|
+
function untagTypedArray(value) {
|
|
2558
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
2559
|
+
const { __ta: tag, data } = value;
|
|
2560
|
+
if (typeof tag !== "string" || !Object.hasOwn(TYPED_ARRAY_CONSTRUCTORS, tag) || !Array.isArray(data)) return void 0;
|
|
2561
|
+
return TYPED_ARRAY_CONSTRUCTORS[tag].from(data);
|
|
2562
|
+
}
|
|
2563
|
+
var isPlain = (value) => classOf(value) === "Object";
|
|
2564
|
+
function mapDeep(value, leaf) {
|
|
2565
|
+
const swapped = leaf(value);
|
|
2566
|
+
if (swapped !== void 0) return swapped;
|
|
2567
|
+
if (Array.isArray(value)) return value.map((v) => mapDeep(v, leaf));
|
|
2568
|
+
if (!isPlain(value)) return value;
|
|
2569
|
+
const out = {};
|
|
2570
|
+
for (const key of Object.keys(value)) out[key] = mapDeep(value[key], leaf);
|
|
2571
|
+
return out;
|
|
2572
|
+
}
|
|
2573
|
+
function tagTypedArrays(value) {
|
|
2574
|
+
return mapDeep(value, tagTypedArray);
|
|
2575
|
+
}
|
|
2576
|
+
function reviveTypedArrays(value) {
|
|
2577
|
+
return mapDeep(value, untagTypedArray);
|
|
2578
|
+
}
|
|
2579
|
+
function typedArrayReplacer(_key, value) {
|
|
2580
|
+
return tagTypedArray(value) ?? value;
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
export { EASINGS, PathBuilder, SPRING_PRESETS, TYPED_ARRAY_CONSTRUCTORS, ZOOM_FLOOR, anchorAt, anchorCount, anchorsInRect, anchorsToPath, applyToPoint, boundsOfPath, boxToBox, circlePath, clampRectWithin, composePath, countPathAnchors, cubicBezierEasing, decomposePath, deleteAnchorsAt, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSet, ellipsePath, flatAnchorIndex, hasOpenSubpath, identity, insertAnchorOnSegment, invert, isAnchorSmooth, isStraightSegment, linePath, linear, locateAnchor, mat3, meanScale, moveHandleTo, multiply, nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic, nearestPathAnchor, nearestSegmentT, normalizeZoom, openSubpathAt, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathFromD, pathInPoseFrame, pathInWorld, pathIntersectsPolygon, pathIntersectsRect, pathSignedArea, pathThroughPoseFrame, pathToAnchors, placeRect, pointAlongPath, pointInPath, polygonContainsPath, polygonFromPoints, polygonIntersectsPath, polylineFromPoints, portControls2 as portControls, portCurvePoints2 as portCurvePoints, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, pxExtent, rectMarkerPath, rectPath, regularPolygonPath, resolveEasing, reverseAnchors, reversePath, reviveTypedArrays, rotate, rotateAboutPoint, rotatePathAround, roundRectPath, scale, scaleDelta, scalePathToBounds, schneiderFit, screenAngleOf, segmentAt, segmentEnds, splitByClosure, splitSubpaths, squarePath, standoff, starPath, strokeHitTest, tagTypedArray, tagTypedArrays, transformCoords, transformPath, translate, translateAnchorBy, translatePath, typedArrayReplacer, unionBoundsPath, untagTypedArray, viewToMat3, withinPxBox, withinPxRadius, worldEditToStorage };
|
|
1792
2584
|
//# sourceMappingURL=index.js.map
|
|
1793
2585
|
//# sourceMappingURL=index.js.map
|