@weasel-js/core 1.0.1 → 1.0.2
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/CHANGELOG.md +269 -0
- package/dist/{chunk-FVNWK7U3.js → chunk-PI56ORHE.js} +1593 -1316
- package/dist/chunk-PI56ORHE.js.map +1 -0
- package/dist/{chunk-DCIU3SRK.js → chunk-W2WB4352.js} +79 -151
- package/dist/chunk-W2WB4352.js.map +1 -0
- package/dist/clipboard.d.ts +1 -1
- package/dist/clipboard.js +0 -1
- package/dist/clone.d.ts +2 -2
- package/dist/clone.js +0 -1
- package/dist/{geometry-DVeZ2i-c.d.ts → geometry-CnISZ11w.d.ts} +1 -1
- package/dist/{grid-XcFQVS0f.d.ts → grid-CBiLBnyc.d.ts} +2 -2
- package/dist/index.d.ts +163 -43
- package/dist/index.js +2 -3
- package/dist/insert.d.ts +3 -3
- package/dist/insert.js +0 -1
- package/dist/insert.js.map +1 -1
- package/dist/move.d.ts +5 -5
- package/dist/move.js +0 -1
- package/dist/move.js.map +1 -1
- package/dist/{options-wAvCnOZd.d.ts → options-DoOvx50U.d.ts} +1 -1
- package/dist/patterns-builtin.js +0 -1
- package/dist/{pointSnapToGrid-BuDZWBrL.d.ts → pointSnapToGrid-Bj4r_lEQ.d.ts} +3 -3
- package/dist/{index-DPI8DV0A.d.ts → registry-BQL4oyTg.d.ts} +139 -348
- package/dist/renderer.d.ts +11 -0
- package/dist/renderer.js +2 -3
- package/dist/resize.d.ts +5 -5
- package/dist/resize.js +0 -1
- package/dist/routing.d.ts +104 -5
- package/dist/routing.js +1 -2
- package/dist/{types-B_-khFM0.d.ts → types-Ch0Goo-j.d.ts} +12 -0
- package/dist/{types-BhJJ2OCM.d.ts → types-Ct4n0Z38.d.ts} +1 -1
- package/dist/{types-BJ8_cyT7.d.ts → types-Dtxe7jTS.d.ts} +20 -1
- package/package.json +6 -6
- package/dist/chunk-DCIU3SRK.js.map +0 -1
- package/dist/chunk-FVNWK7U3.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js +0 -9
- package/dist/chunk-PZ5AY32C.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionDisabledReason,
|
|
1
|
+
import { ActionDisabledReason, useOptionalDepRegistry, DepRegistryProvider, useActionsRegistry, ActionsProvider, useDepRegistry, reportRouteConflicts, buildDepsFromRequires, useDepSource, actionBindings } from './chunk-W2WB4352.js';
|
|
2
2
|
import { scratchKey, createTransformOp, snap, getScratch, createReparentOp, setScratch } from './chunk-UB6A6L77.js';
|
|
3
3
|
import { fixedCornerOf, DEFAULT_RESIZE_BEHAVIORS, CORNER_ANCHORS, cornerPoint } from './chunk-Z3KNFTTS.js';
|
|
4
4
|
import { AUTO_POSE_DESCRIPTOR, RECT_POSE_DESCRIPTOR, resolveUnit, pathPoseDescriptor, polygonFromPoints, starPath, regularPolygonPath, linePath, ellipsePath, rectPath, strokeHitTest, withinPxRadius, boundsOfPath, PATH_M, PATH_L, PATH_Z, PATH_Q, PATH_C, DEFAULT_FLATTEN_TOLERANCE, flattenQuadratic, flattenCubic, PathBuilder, pointInPath, transformPath, translatePath, pxExtent, remapRotatedLeaf, withinPxBox, flattenCubicWithArcLen, flattenQuadraticWithArcLen, PATH_CMD_LENGTHS, pointToGridCell } from './chunk-6SHZHXXR.js';
|
|
@@ -13,13 +13,13 @@ import earcut from 'earcut';
|
|
|
13
13
|
import { applyToPoint, rotateAboutPoint, boxToBox, pointInPolygon, segmentsCross } from '@weasel-js/geom';
|
|
14
14
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
15
15
|
import polygonClipping from 'polygon-clipping';
|
|
16
|
-
import { matchSpec, parseTargetSpec, mimeMatchesGlob } from '@weasel-js/gestures';
|
|
16
|
+
import { matchSpec, RESERVED_ID_PREFIXES, RESERVED_ID_NAMES, parseTargetSpec, mimeMatchesGlob } from '@weasel-js/gestures';
|
|
17
17
|
import { NORMAL, IMPLICIT_TAGS } from '@weasel-js/modes';
|
|
18
18
|
import { createHistory } from '@weasel-js/history';
|
|
19
19
|
export * from '@weasel-js/history';
|
|
20
20
|
|
|
21
21
|
// src/version.ts
|
|
22
|
-
var VERSION = "1.0.
|
|
22
|
+
var VERSION = "1.0.2" ;
|
|
23
23
|
|
|
24
24
|
// src/features/grid/roundToCell.ts
|
|
25
25
|
function roundToCell(value, cellSize) {
|
|
@@ -399,6 +399,8 @@ var GLMeshCache = class {
|
|
|
399
399
|
gl;
|
|
400
400
|
aPositionLoc;
|
|
401
401
|
map = /* @__PURE__ */ new WeakMap();
|
|
402
|
+
/** Meshes this context has drawn at least once; see `uploadRecurring`. */
|
|
403
|
+
seen = /* @__PURE__ */ new WeakSet();
|
|
402
404
|
finalizer;
|
|
403
405
|
pendingDeletes = [];
|
|
404
406
|
/** Transient resources allocated this frame; freed at end of render(). */
|
|
@@ -423,6 +425,19 @@ var GLMeshCache = class {
|
|
|
423
425
|
this.transientThisFrame.push({ vao: handle.vao, vbo, ibo });
|
|
424
426
|
return handle;
|
|
425
427
|
}
|
|
428
|
+
/**
|
|
429
|
+
* Upload a Mesh that may or may not recur across frames. Its first sight in
|
|
430
|
+
* *this* context takes `uploadTransient`; every later one takes the
|
|
431
|
+
* persistent handle. One transient upload to find out is cheaper than
|
|
432
|
+
* stranding a persistent VAO on a mesh that never returns, whose release
|
|
433
|
+
* would wait on GC. The transient upload does not populate the persistent
|
|
434
|
+
* map, so steady-state reuse begins on the third frame.
|
|
435
|
+
*/
|
|
436
|
+
uploadRecurring(mesh) {
|
|
437
|
+
if (this.seen.has(mesh)) return this.handleFor(mesh);
|
|
438
|
+
this.seen.add(mesh);
|
|
439
|
+
return this.uploadTransient(mesh);
|
|
440
|
+
}
|
|
426
441
|
/**
|
|
427
442
|
* Free all transient resources allocated since the last call. Called by
|
|
428
443
|
* the renderer at the end of each `render()`. Safe under context loss.
|
|
@@ -1532,1269 +1547,1269 @@ function getMesh(path) {
|
|
|
1532
1547
|
cache.set(path, mesh);
|
|
1533
1548
|
return mesh;
|
|
1534
1549
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
}
|
|
1541
|
-
function extractRect(p) {
|
|
1542
|
-
const { x, y, width: w, height: h } = p;
|
|
1543
|
-
return {
|
|
1544
|
-
points: [x, y, x + w, y, x + w, y + h, x, y + h],
|
|
1545
|
-
closed: true,
|
|
1546
|
-
anchorA: new Uint32Array([0, 1, 2, 3]),
|
|
1547
|
-
anchorB: new Uint32Array([0, 1, 2, 3]),
|
|
1548
|
-
anchorT: new Float32Array([0, 0, 0, 0])
|
|
1549
|
-
};
|
|
1550
|
+
var UNDERLINE_OFFSET = 0.1;
|
|
1551
|
+
var STRIKETHROUGH_OFFSET = -0.3;
|
|
1552
|
+
var DECORATION_THICKNESS = 0.05;
|
|
1553
|
+
function fillKey(p) {
|
|
1554
|
+
if ("color" in p) return `s:${p.color}:${p.opacity ?? 1}`;
|
|
1555
|
+
return `nx:${Math.random()}`;
|
|
1550
1556
|
}
|
|
1551
|
-
function
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
let anchorCounter = 0;
|
|
1556
|
-
let pts = null;
|
|
1557
|
-
let aA = null;
|
|
1558
|
-
let aB = null;
|
|
1559
|
-
let aT = null;
|
|
1560
|
-
let current = null;
|
|
1561
|
-
let coordIdx = 0;
|
|
1562
|
-
let prevX = 0;
|
|
1563
|
-
let prevY = 0;
|
|
1564
|
-
let prevAnchor = -1;
|
|
1565
|
-
const beginContour = () => {
|
|
1566
|
-
pts = [];
|
|
1567
|
-
aA = [];
|
|
1568
|
-
aB = [];
|
|
1569
|
-
aT = [];
|
|
1570
|
-
const next = { points: pts, closed: false };
|
|
1571
|
-
out.push(next);
|
|
1572
|
-
return next;
|
|
1573
|
-
};
|
|
1574
|
-
const dropDuplicateClosingPoint = () => {
|
|
1575
|
-
if (!pts || !aA || !aB || !aT) return;
|
|
1576
|
-
const n = pts.length / 2;
|
|
1577
|
-
if (n < 2) return;
|
|
1578
|
-
if (pts[0] !== pts[(n - 1) * 2] || pts[1] !== pts[(n - 1) * 2 + 1]) return;
|
|
1579
|
-
pts.length -= 2;
|
|
1580
|
-
aA.length -= 1;
|
|
1581
|
-
aB.length -= 1;
|
|
1582
|
-
aT.length -= 1;
|
|
1583
|
-
};
|
|
1584
|
-
const commit = (target) => {
|
|
1585
|
-
if (!pts || !aA || !aB || !aT) return;
|
|
1586
|
-
target.anchorA = new Uint32Array(aA);
|
|
1587
|
-
target.anchorB = new Uint32Array(aB);
|
|
1588
|
-
target.anchorT = new Float32Array(aT);
|
|
1589
|
-
};
|
|
1590
|
-
for (let cmdIdx = 0; cmdIdx < commands.length; cmdIdx++) {
|
|
1591
|
-
const cmd = commands[cmdIdx];
|
|
1592
|
-
switch (cmd) {
|
|
1593
|
-
case PATH_M: {
|
|
1594
|
-
if (current) commit(current);
|
|
1595
|
-
current = beginContour();
|
|
1596
|
-
prevX = coords[coordIdx];
|
|
1597
|
-
prevY = coords[coordIdx + 1];
|
|
1598
|
-
pts.push(prevX, prevY);
|
|
1599
|
-
aA.push(anchorCounter);
|
|
1600
|
-
aB.push(anchorCounter);
|
|
1601
|
-
aT.push(0);
|
|
1602
|
-
prevAnchor = anchorCounter;
|
|
1603
|
-
anchorCounter++;
|
|
1604
|
-
coordIdx += 2;
|
|
1605
|
-
break;
|
|
1606
|
-
}
|
|
1607
|
-
case PATH_L: {
|
|
1608
|
-
prevX = coords[coordIdx];
|
|
1609
|
-
prevY = coords[coordIdx + 1];
|
|
1610
|
-
pts.push(prevX, prevY);
|
|
1611
|
-
aA.push(anchorCounter);
|
|
1612
|
-
aB.push(anchorCounter);
|
|
1613
|
-
aT.push(0);
|
|
1614
|
-
prevAnchor = anchorCounter;
|
|
1615
|
-
anchorCounter++;
|
|
1616
|
-
coordIdx += 2;
|
|
1617
|
-
break;
|
|
1618
|
-
}
|
|
1619
|
-
case PATH_Q: {
|
|
1620
|
-
const cx = coords[coordIdx], cy = coords[coordIdx + 1];
|
|
1621
|
-
const ex = coords[coordIdx + 2], ey = coords[coordIdx + 3];
|
|
1622
|
-
const targetAnchor = anchorCounter;
|
|
1623
|
-
const segStart = pts.length / 2;
|
|
1624
|
-
const arcAccum = [];
|
|
1625
|
-
const total = flattenQuadraticWithArcLen(prevX, prevY, cx, cy, ex, ey, tolerance, pts, arcAccum);
|
|
1626
|
-
for (let k = 0; k < arcAccum.length; k++) {
|
|
1627
|
-
aA.push(prevAnchor);
|
|
1628
|
-
aB.push(targetAnchor);
|
|
1629
|
-
aT.push(total > 0 ? arcAccum[k] / total : 0);
|
|
1630
|
-
}
|
|
1631
|
-
const lastIdx = segStart + arcAccum.length - 1;
|
|
1632
|
-
aA[lastIdx] = targetAnchor;
|
|
1633
|
-
aB[lastIdx] = targetAnchor;
|
|
1634
|
-
aT[lastIdx] = 0;
|
|
1635
|
-
prevX = ex;
|
|
1636
|
-
prevY = ey;
|
|
1637
|
-
prevAnchor = targetAnchor;
|
|
1638
|
-
anchorCounter++;
|
|
1639
|
-
coordIdx += 4;
|
|
1640
|
-
break;
|
|
1641
|
-
}
|
|
1642
|
-
case PATH_C: {
|
|
1643
|
-
const c1x = coords[coordIdx], c1y = coords[coordIdx + 1];
|
|
1644
|
-
const c2x = coords[coordIdx + 2], c2y = coords[coordIdx + 3];
|
|
1645
|
-
const ex = coords[coordIdx + 4], ey = coords[coordIdx + 5];
|
|
1646
|
-
const targetAnchor = anchorCounter;
|
|
1647
|
-
const segStart = pts.length / 2;
|
|
1648
|
-
const arcAccum = [];
|
|
1649
|
-
const total = flattenCubicWithArcLen(prevX, prevY, c1x, c1y, c2x, c2y, ex, ey, tolerance, pts, arcAccum);
|
|
1650
|
-
for (let k = 0; k < arcAccum.length; k++) {
|
|
1651
|
-
aA.push(prevAnchor);
|
|
1652
|
-
aB.push(targetAnchor);
|
|
1653
|
-
aT.push(total > 0 ? arcAccum[k] / total : 0);
|
|
1654
|
-
}
|
|
1655
|
-
const lastIdx = segStart + arcAccum.length - 1;
|
|
1656
|
-
aA[lastIdx] = targetAnchor;
|
|
1657
|
-
aB[lastIdx] = targetAnchor;
|
|
1658
|
-
aT[lastIdx] = 0;
|
|
1659
|
-
prevX = ex;
|
|
1660
|
-
prevY = ey;
|
|
1661
|
-
prevAnchor = targetAnchor;
|
|
1662
|
-
anchorCounter++;
|
|
1663
|
-
coordIdx += 6;
|
|
1664
|
-
break;
|
|
1665
|
-
}
|
|
1666
|
-
case PATH_Z: {
|
|
1667
|
-
if (current) {
|
|
1668
|
-
current.closed = true;
|
|
1669
|
-
dropDuplicateClosingPoint();
|
|
1670
|
-
}
|
|
1671
|
-
break;
|
|
1672
|
-
}
|
|
1673
|
-
default:
|
|
1674
|
-
throw new Error(`extractPolylines: unknown command code ${cmd}`);
|
|
1675
|
-
}
|
|
1557
|
+
function sameFill(a, b) {
|
|
1558
|
+
if (a === b) return true;
|
|
1559
|
+
if ("color" in a && "color" in b) {
|
|
1560
|
+
return a.color === b.color && (a.opacity ?? 1) === (b.opacity ?? 1);
|
|
1676
1561
|
}
|
|
1677
|
-
|
|
1678
|
-
return out;
|
|
1562
|
+
return false;
|
|
1679
1563
|
}
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
const
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1564
|
+
function strokeKey(s) {
|
|
1565
|
+
if (!s) return "-";
|
|
1566
|
+
return [
|
|
1567
|
+
fillKey(s.paint),
|
|
1568
|
+
s.width ?? 1,
|
|
1569
|
+
s.join ?? "miter",
|
|
1570
|
+
s.cap ?? "butt",
|
|
1571
|
+
s.miterLimit ?? "",
|
|
1572
|
+
s.align ?? "center",
|
|
1573
|
+
(s.dash ?? []).join(",")
|
|
1574
|
+
].join(":");
|
|
1575
|
+
}
|
|
1576
|
+
function groupKey(family, weight, style, synthetic, fill, stroke, source, page) {
|
|
1577
|
+
return `${family}|${weight}|${style}|${synthetic.bold ? 1 : 0}${synthetic.italic ? 1 : 0}|${fillKey(fill)}|${strokeKey(stroke)}|${source}|${page}`;
|
|
1578
|
+
}
|
|
1579
|
+
function getOrCreateGroup(ctx, run, resolved, page, sourceOverride) {
|
|
1580
|
+
const atlasFamily = resolved.resolved.family;
|
|
1581
|
+
const resolvedWeight = resolved.resolved.weight;
|
|
1582
|
+
const resolvedStyle = resolved.resolved.style;
|
|
1583
|
+
const source = sourceOverride ?? resolved.source;
|
|
1584
|
+
const key = groupKey(
|
|
1585
|
+
atlasFamily,
|
|
1586
|
+
resolvedWeight,
|
|
1587
|
+
resolvedStyle,
|
|
1588
|
+
resolved.synthetic,
|
|
1589
|
+
run.fill,
|
|
1590
|
+
source === "outline" ? run.stroke : void 0,
|
|
1591
|
+
source,
|
|
1592
|
+
page
|
|
1593
|
+
);
|
|
1594
|
+
let g = ctx.groups.get(key);
|
|
1595
|
+
if (!g) {
|
|
1596
|
+
g = {
|
|
1597
|
+
family: atlasFamily,
|
|
1598
|
+
weight: resolvedWeight,
|
|
1599
|
+
style: resolvedStyle,
|
|
1600
|
+
synthetic: { ...resolved.synthetic },
|
|
1601
|
+
source,
|
|
1602
|
+
page,
|
|
1603
|
+
fill: run.fill,
|
|
1604
|
+
// Only the outline tier can paint it, and carrying it on an SDF group
|
|
1605
|
+
// would be a promise the renderer cannot keep.
|
|
1606
|
+
...source === "outline" && run.stroke !== void 0 ? { stroke: run.stroke } : {},
|
|
1607
|
+
quads: [],
|
|
1608
|
+
glyphs: []
|
|
1706
1609
|
};
|
|
1610
|
+
ctx.groups.set(key, g);
|
|
1707
1611
|
}
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
const
|
|
1714
|
-
const
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
const subs = dash.length > 0 ? splitForDash(pl, dash) : [pl];
|
|
1720
|
-
for (const sub2 of subs) {
|
|
1721
|
-
expandPolyline(sub2, width, join, cap, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT);
|
|
1612
|
+
return g;
|
|
1613
|
+
}
|
|
1614
|
+
function resolveGlyph(run, font, resolved, cp) {
|
|
1615
|
+
const direct = font.charMap.get(cp);
|
|
1616
|
+
if (direct) return { glyph: direct, font, resolved };
|
|
1617
|
+
const fallback = resolveGlyphFallback(run.fontFamily, run.fontWeight, run.fontStyle);
|
|
1618
|
+
const face = fallback?.dynamicFace;
|
|
1619
|
+
if (fallback && face) {
|
|
1620
|
+
const glyph = face.requestGlyph(cp);
|
|
1621
|
+
if (glyph.xadvance > 0 || glyph.width > 0) {
|
|
1622
|
+
return { glyph, font: face.font, resolved: fallback };
|
|
1722
1623
|
}
|
|
1723
1624
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
indices: new Uint32Array(idx),
|
|
1727
|
-
anchorA: new Uint32Array(anchorA),
|
|
1728
|
-
anchorB: new Uint32Array(anchorB),
|
|
1729
|
-
anchorT: new Float32Array(anchorT)
|
|
1730
|
-
};
|
|
1625
|
+
warnMissingGlyphOnce(resolved.resolved.family, cp);
|
|
1626
|
+
return null;
|
|
1731
1627
|
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
const
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1628
|
+
var warnedMissingGlyphs = /* @__PURE__ */ new Set();
|
|
1629
|
+
function warnMissingGlyphOnce(family, cp) {
|
|
1630
|
+
const key = `${family}|${cp}`;
|
|
1631
|
+
if (warnedMissingGlyphs.has(key)) return;
|
|
1632
|
+
warnedMissingGlyphs.add(key);
|
|
1633
|
+
const ch = String.fromCodePoint(cp);
|
|
1634
|
+
console.warn(
|
|
1635
|
+
`weasel layoutRuns: no glyph for U+${cp.toString(16).toUpperCase().padStart(4, "0")} (${JSON.stringify(ch)}) in "${family}", and the dynamic tier could not rasterize it \u2014 skipping the character. Bake it into the atlas, or call registerCanvasFont("${family}") to serve missing codepoints from installed fonts.`
|
|
1636
|
+
);
|
|
1637
|
+
}
|
|
1638
|
+
function layoutRuns(runs, opts) {
|
|
1639
|
+
const ctx = { groups: /* @__PURE__ */ new Map() };
|
|
1640
|
+
const entries = [];
|
|
1641
|
+
let prevCp;
|
|
1642
|
+
let prevFont;
|
|
1643
|
+
let prevFontSize;
|
|
1644
|
+
for (const run of runs) {
|
|
1645
|
+
const resolved = resolveFontVariant(run.fontFamily, run.fontWeight, run.fontStyle);
|
|
1646
|
+
const font = resolved.entry?.font ?? resolved.dynamicFace?.font;
|
|
1647
|
+
if (!font) {
|
|
1648
|
+
prevCp = void 0;
|
|
1649
|
+
prevFont = void 0;
|
|
1650
|
+
prevFontSize = void 0;
|
|
1651
|
+
continue;
|
|
1751
1652
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1653
|
+
const scale2 = run.fontSize / font.info.size;
|
|
1654
|
+
const tracking = run.letterSpacing;
|
|
1655
|
+
for (const ch of [...run.text]) {
|
|
1656
|
+
const cp = ch.codePointAt(0);
|
|
1657
|
+
const isNewline = cp === 10;
|
|
1658
|
+
const isSpace = cp === 32;
|
|
1659
|
+
if (isNewline) {
|
|
1660
|
+
entries.push({
|
|
1661
|
+
run,
|
|
1662
|
+
font,
|
|
1663
|
+
glyph: { id: cp, x: 0, y: 0, width: 0, height: 0, xoffset: 0, yoffset: 0, xadvance: 0, page: 0 },
|
|
1664
|
+
// A newline consumes no advance, so it takes no tracking either.
|
|
1665
|
+
cp,
|
|
1666
|
+
advance: 0,
|
|
1667
|
+
tracking: 0,
|
|
1668
|
+
kerningBefore: 0,
|
|
1669
|
+
isSpace: false,
|
|
1670
|
+
isNewline: true,
|
|
1671
|
+
resolved,
|
|
1672
|
+
fontSize: run.fontSize
|
|
1673
|
+
});
|
|
1674
|
+
prevCp = void 0;
|
|
1675
|
+
prevFont = void 0;
|
|
1676
|
+
prevFontSize = void 0;
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
if (isSpace) {
|
|
1680
|
+
const spaceGlyph = resolved.dynamicFace ? resolved.dynamicFace.requestGlyph(32) : font.charMap.get(32);
|
|
1681
|
+
const advance = spaceGlyph ? spaceGlyph.xadvance * scale2 : run.fontSize * 0.25;
|
|
1682
|
+
let kerningBefore2 = 0;
|
|
1683
|
+
if (prevCp !== void 0 && prevFont !== void 0 && prevFontSize !== void 0) {
|
|
1684
|
+
const kAtlas = prevFont.kerningMap.get(prevCp)?.get(cp) ?? 0;
|
|
1685
|
+
kerningBefore2 = kAtlas * (prevFontSize / prevFont.info.size);
|
|
1686
|
+
}
|
|
1687
|
+
entries.push({
|
|
1688
|
+
run,
|
|
1689
|
+
font,
|
|
1690
|
+
glyph: spaceGlyph ?? { id: 32, x: 0, y: 0, width: 0, height: 0, xoffset: 0, yoffset: 0, xadvance: 0, page: 0 },
|
|
1691
|
+
cp,
|
|
1692
|
+
advance,
|
|
1693
|
+
tracking,
|
|
1694
|
+
kerningBefore: kerningBefore2,
|
|
1695
|
+
isSpace: true,
|
|
1696
|
+
isNewline: false,
|
|
1697
|
+
resolved,
|
|
1698
|
+
fontSize: run.fontSize
|
|
1699
|
+
});
|
|
1700
|
+
prevCp = cp;
|
|
1701
|
+
prevFont = font;
|
|
1702
|
+
prevFontSize = run.fontSize;
|
|
1703
|
+
continue;
|
|
1704
|
+
}
|
|
1705
|
+
const hit = resolved.dynamicFace ? { glyph: resolved.dynamicFace.requestGlyph(cp), font, resolved } : resolveGlyph(run, font, resolved, cp);
|
|
1706
|
+
if (!hit) {
|
|
1707
|
+
prevCp = cp;
|
|
1708
|
+
prevFont = font;
|
|
1709
|
+
prevFontSize = run.fontSize;
|
|
1710
|
+
continue;
|
|
1711
|
+
}
|
|
1712
|
+
const glyphFont = hit.font;
|
|
1713
|
+
const glyphScale = run.fontSize / glyphFont.info.size;
|
|
1714
|
+
let kerningBefore = 0;
|
|
1715
|
+
if (prevCp !== void 0 && prevFont !== void 0 && prevFontSize !== void 0) {
|
|
1716
|
+
const kAtlas = prevFont.kerningMap.get(prevCp)?.get(cp) ?? 0;
|
|
1717
|
+
kerningBefore = kAtlas * (prevFontSize / prevFont.info.size);
|
|
1718
|
+
}
|
|
1719
|
+
entries.push({
|
|
1720
|
+
run,
|
|
1721
|
+
font: glyphFont,
|
|
1722
|
+
glyph: hit.glyph,
|
|
1723
|
+
cp,
|
|
1724
|
+
advance: hit.glyph.xadvance * glyphScale,
|
|
1725
|
+
tracking,
|
|
1726
|
+
kerningBefore,
|
|
1727
|
+
isSpace,
|
|
1728
|
+
isNewline: false,
|
|
1729
|
+
resolved: hit.resolved,
|
|
1730
|
+
fontSize: run.fontSize
|
|
1731
|
+
});
|
|
1732
|
+
prevCp = cp;
|
|
1733
|
+
prevFont = glyphFont;
|
|
1734
|
+
prevFontSize = run.fontSize;
|
|
1764
1735
|
}
|
|
1765
1736
|
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
const endSrc = s === segs.length - 1 && pl.closed && closerSrcIdx >= 0 ? 0 : startSrc + 1;
|
|
1772
|
-
const base = verts.length / 2;
|
|
1773
|
-
segBaseIdx.push(base);
|
|
1774
|
-
const nxA = seg.nxUnit * seg.halfA, nyA = seg.nyUnit * seg.halfA;
|
|
1775
|
-
const nxB = seg.nxUnit * seg.halfB, nyB = seg.nyUnit * seg.halfB;
|
|
1776
|
-
verts.push(seg.ax + nxA, seg.ay + nyA);
|
|
1777
|
-
anchorA.push(plA[startSrc]);
|
|
1778
|
-
anchorB.push(plB[startSrc]);
|
|
1779
|
-
anchorT.push(plT[startSrc]);
|
|
1780
|
-
verts.push(seg.ax - nxA, seg.ay - nyA);
|
|
1781
|
-
anchorA.push(plA[startSrc]);
|
|
1782
|
-
anchorB.push(plB[startSrc]);
|
|
1783
|
-
anchorT.push(plT[startSrc]);
|
|
1784
|
-
verts.push(seg.bx + nxB, seg.by + nyB);
|
|
1785
|
-
anchorA.push(plA[endSrc]);
|
|
1786
|
-
anchorB.push(plB[endSrc]);
|
|
1787
|
-
anchorT.push(plT[endSrc]);
|
|
1788
|
-
verts.push(seg.bx - nxB, seg.by - nyB);
|
|
1789
|
-
anchorA.push(plA[endSrc]);
|
|
1790
|
-
anchorB.push(plB[endSrc]);
|
|
1791
|
-
anchorT.push(plT[endSrc]);
|
|
1792
|
-
idx.push(base, base + 1, base + 2, base + 1, base + 3, base + 2);
|
|
1793
|
-
}
|
|
1794
|
-
const joinCount = pl.closed ? segs.length : segs.length - 1;
|
|
1795
|
-
for (let j = 0; j < joinCount; j++) {
|
|
1796
|
-
emitJoin(segs, segBaseIdx, j, join, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT, segSrcIdx, plA, plB, plT);
|
|
1797
|
-
}
|
|
1798
|
-
if (!pl.closed && cap !== "butt") {
|
|
1799
|
-
const first = segs[0];
|
|
1800
|
-
const firstBase = segBaseIdx[0];
|
|
1801
|
-
emitCap(first, firstBase + 0, firstBase + 1, false, first.halfA, cap, verts, idx, anchorA, anchorB, anchorT, plA[0], plB[0], plT[0]);
|
|
1802
|
-
const last = segs[segs.length - 1];
|
|
1803
|
-
const lastBase = segBaseIdx[segs.length - 1];
|
|
1804
|
-
const lastSrc = segSrcIdx[segs.length - 1] + 1;
|
|
1805
|
-
emitCap(last, lastBase + 2, lastBase + 3, true, last.halfB, cap, verts, idx, anchorA, anchorB, anchorT, plA[lastSrc], plB[lastSrc], plT[lastSrc]);
|
|
1737
|
+
const lines = [];
|
|
1738
|
+
let cur = { entries: [], width: 0, height: 0 };
|
|
1739
|
+
function commitLine() {
|
|
1740
|
+
lines.push(cur);
|
|
1741
|
+
cur = { entries: [], width: 0, height: 0 };
|
|
1806
1742
|
}
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
};
|
|
1819
|
-
for (let i = 0; i < ptCount; i++) {
|
|
1820
|
-
const a = aA[i], b = aB[i], t = aT[i];
|
|
1821
|
-
if (a === b) {
|
|
1822
|
-
widths[i] = read(a);
|
|
1823
|
-
} else {
|
|
1824
|
-
const wa = read(a);
|
|
1825
|
-
const wb = read(b);
|
|
1826
|
-
widths[i] = wa + (wb - wa) * t;
|
|
1743
|
+
let i = 0;
|
|
1744
|
+
while (i < entries.length) {
|
|
1745
|
+
const e = entries[i];
|
|
1746
|
+
if (e.isNewline) {
|
|
1747
|
+
if (cur.entries.length === 0) {
|
|
1748
|
+
cur.height = Math.max(cur.height, e.fontSize * opts.lineHeight);
|
|
1749
|
+
cur.blank = e;
|
|
1750
|
+
}
|
|
1751
|
+
commitLine();
|
|
1752
|
+
i++;
|
|
1753
|
+
continue;
|
|
1827
1754
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
const cx = atEnd ? seg.bx : seg.ax;
|
|
1837
|
-
const cy = atEnd ? seg.by : seg.ay;
|
|
1838
|
-
const nx = seg.nxUnit * half;
|
|
1839
|
-
const ny = seg.nyUnit * half;
|
|
1840
|
-
if (cap === "square") {
|
|
1841
|
-
const ox = cx + dx * half;
|
|
1842
|
-
const oy = cy + dy * half;
|
|
1843
|
-
const lOut = verts.length / 2;
|
|
1844
|
-
verts.push(ox + nx, oy + ny);
|
|
1845
|
-
anchorA.push(endA);
|
|
1846
|
-
anchorB.push(endB);
|
|
1847
|
-
anchorT.push(endT);
|
|
1848
|
-
const rOut = verts.length / 2;
|
|
1849
|
-
verts.push(ox - nx, oy - ny);
|
|
1850
|
-
anchorA.push(endA);
|
|
1851
|
-
anchorB.push(endB);
|
|
1852
|
-
anchorT.push(endT);
|
|
1853
|
-
if (atEnd) {
|
|
1854
|
-
idx.push(leftIdx, lOut, rOut, leftIdx, rOut, rightIdx);
|
|
1855
|
-
} else {
|
|
1856
|
-
idx.push(leftIdx, rOut, lOut, leftIdx, rightIdx, rOut);
|
|
1755
|
+
if (e.isSpace) {
|
|
1756
|
+
if (cur.entries.length > 0) {
|
|
1757
|
+
cur.entries.push(e);
|
|
1758
|
+
cur.width += e.kerningBefore + e.advance + e.tracking;
|
|
1759
|
+
cur.height = Math.max(cur.height, e.fontSize * opts.lineHeight);
|
|
1760
|
+
}
|
|
1761
|
+
i++;
|
|
1762
|
+
continue;
|
|
1857
1763
|
}
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
anchorB.push(endB);
|
|
1865
|
-
anchorT.push(endT);
|
|
1866
|
-
const startAngle = Math.atan2(ny, nx);
|
|
1867
|
-
const sweep = atEnd ? -Math.PI : Math.PI;
|
|
1868
|
-
const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_CAP_STEP_RAD));
|
|
1869
|
-
const stepAngle = sweep / steps;
|
|
1870
|
-
let prevIdx = leftIdx;
|
|
1871
|
-
for (let i = 1; i < steps; i++) {
|
|
1872
|
-
const ang = startAngle + i * stepAngle;
|
|
1873
|
-
const fx = cx + Math.cos(ang) * half;
|
|
1874
|
-
const fy = cy + Math.sin(ang) * half;
|
|
1875
|
-
const newIdx = verts.length / 2;
|
|
1876
|
-
verts.push(fx, fy);
|
|
1877
|
-
anchorA.push(endA);
|
|
1878
|
-
anchorB.push(endB);
|
|
1879
|
-
anchorT.push(endT);
|
|
1880
|
-
if (atEnd) idx.push(prevIdx, newIdx, pivotIdx);
|
|
1881
|
-
else idx.push(prevIdx, pivotIdx, newIdx);
|
|
1882
|
-
prevIdx = newIdx;
|
|
1764
|
+
let j = i;
|
|
1765
|
+
let wordWidth = 0;
|
|
1766
|
+
while (j < entries.length && !entries[j].isSpace && !entries[j].isNewline) {
|
|
1767
|
+
const w = entries[j];
|
|
1768
|
+
wordWidth += w.kerningBefore + w.advance + w.tracking;
|
|
1769
|
+
j++;
|
|
1883
1770
|
}
|
|
1884
|
-
if (
|
|
1885
|
-
|
|
1771
|
+
if (Number.isFinite(opts.maxWidth) && cur.width + wordWidth > opts.maxWidth && cur.entries.length > 0) {
|
|
1772
|
+
commitLine();
|
|
1773
|
+
}
|
|
1774
|
+
for (let k = i; k < j; k++) {
|
|
1775
|
+
const w = entries[k];
|
|
1776
|
+
const kerningBefore = cur.entries.length === 0 ? 0 : w.kerningBefore;
|
|
1777
|
+
cur.entries.push({ ...w, kerningBefore });
|
|
1778
|
+
cur.width += kerningBefore + w.advance + w.tracking;
|
|
1779
|
+
cur.height = Math.max(cur.height, w.fontSize * opts.lineHeight);
|
|
1780
|
+
}
|
|
1781
|
+
i = j;
|
|
1886
1782
|
}
|
|
1887
|
-
|
|
1888
|
-
function
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
let
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
anchorA: new Uint32Array(curA),
|
|
1906
|
-
anchorB: new Uint32Array(curB),
|
|
1907
|
-
anchorT: new Float32Array(curT)
|
|
1908
|
-
});
|
|
1783
|
+
if (cur.entries.length > 0) commitLine();
|
|
1784
|
+
function outlineFor(e) {
|
|
1785
|
+
const min = opts.outlineMinSize;
|
|
1786
|
+
if (min === void 0 || e.fontSize < min) return null;
|
|
1787
|
+
if (e.resolved.synthetic.bold) return null;
|
|
1788
|
+
const r = e.resolved.resolved;
|
|
1789
|
+
return glyphOutline(r.family, r.weight, r.style, e.cp);
|
|
1790
|
+
}
|
|
1791
|
+
const decorations = [];
|
|
1792
|
+
let span = null;
|
|
1793
|
+
function flushSpan() {
|
|
1794
|
+
const s = span;
|
|
1795
|
+
span = null;
|
|
1796
|
+
if (!s || s.x1 <= s.x0) return;
|
|
1797
|
+
const thickness = s.fontSize * DECORATION_THICKNESS;
|
|
1798
|
+
if (s.underline) {
|
|
1799
|
+
const y0 = s.baselineY + s.fontSize * UNDERLINE_OFFSET;
|
|
1800
|
+
decorations.push({ kind: "underline", x0: s.x0, y0, x1: s.x1, y1: y0 + thickness, fill: s.fill });
|
|
1909
1801
|
}
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
const
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
prevX = cx;
|
|
1941
|
-
prevY = cy;
|
|
1942
|
-
traveled = segFullLen;
|
|
1943
|
-
segLen = 0;
|
|
1944
|
-
if (dashRemaining <= 1e-9) {
|
|
1945
|
-
flushAndAdvance();
|
|
1946
|
-
if (onPhase) {
|
|
1947
|
-
curPts = [prevX, prevY];
|
|
1948
|
-
curA = [endA];
|
|
1949
|
-
curB = [endB];
|
|
1950
|
-
curT = [endT];
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
} else {
|
|
1954
|
-
const tConsume = dashRemaining / segLen;
|
|
1955
|
-
const ix = prevX + segDx * tConsume;
|
|
1956
|
-
const iy = prevY + segDy * tConsume;
|
|
1957
|
-
traveled += dashRemaining;
|
|
1958
|
-
const frac = traveled / segFullLen;
|
|
1959
|
-
let mA, mB, mT;
|
|
1960
|
-
if (startA === endA && startB === endB) {
|
|
1961
|
-
mA = startA;
|
|
1962
|
-
mB = startB;
|
|
1963
|
-
mT = startT + (endT - startT) * frac;
|
|
1802
|
+
if (s.strikethrough) {
|
|
1803
|
+
const y0 = s.baselineY + s.fontSize * STRIKETHROUGH_OFFSET;
|
|
1804
|
+
decorations.push({ kind: "strikethrough", x0: s.x0, y0, x1: s.x1, y1: y0 + thickness, fill: s.fill });
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
const lineBoxes = [];
|
|
1808
|
+
let penY = 0;
|
|
1809
|
+
let maxLineWidth = 0;
|
|
1810
|
+
const finiteWidth = Number.isFinite(opts.maxWidth) ? opts.maxWidth : 0;
|
|
1811
|
+
for (const line of lines) {
|
|
1812
|
+
const alignShift = (() => {
|
|
1813
|
+
if (opts.align === "left") return 0;
|
|
1814
|
+
if (!Number.isFinite(opts.maxWidth)) {
|
|
1815
|
+
return opts.align === "center" ? -line.width / 2 : -line.width;
|
|
1816
|
+
}
|
|
1817
|
+
const slack = finiteWidth - line.width;
|
|
1818
|
+
return opts.align === "center" ? slack / 2 : slack;
|
|
1819
|
+
})();
|
|
1820
|
+
const lineX0 = alignShift;
|
|
1821
|
+
const baselineSource = line.entries[0] ?? line.blank;
|
|
1822
|
+
const lineBaselineY = baselineSource ? penY + baselineSource.font.common.base * (baselineSource.fontSize / baselineSource.font.info.size) : penY;
|
|
1823
|
+
let penX = lineX0;
|
|
1824
|
+
for (const e of line.entries) {
|
|
1825
|
+
penX += e.kerningBefore;
|
|
1826
|
+
const step = e.advance + e.tracking;
|
|
1827
|
+
const scale2 = e.fontSize / e.font.info.size;
|
|
1828
|
+
const baselineY = penY + e.font.common.base * scale2;
|
|
1829
|
+
if (e.run.underline || e.run.strikethrough) {
|
|
1830
|
+
if (span !== null && span.underline === e.run.underline && span.strikethrough === e.run.strikethrough && span.fontSize === e.fontSize && span.baselineY === baselineY && sameFill(span.fill, e.run.fill)) {
|
|
1831
|
+
span.x1 = penX + step;
|
|
1964
1832
|
} else {
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
if (onPhase && curPts) {
|
|
1976
|
-
curPts.push(ix, iy);
|
|
1977
|
-
curA.push(mA);
|
|
1978
|
-
curB.push(mB);
|
|
1979
|
-
curT.push(mT);
|
|
1980
|
-
}
|
|
1981
|
-
prevX = ix;
|
|
1982
|
-
prevY = iy;
|
|
1983
|
-
segDx = cx - prevX;
|
|
1984
|
-
segDy = cy - prevY;
|
|
1985
|
-
segLen = Math.hypot(segDx, segDy);
|
|
1986
|
-
flushAndAdvance();
|
|
1987
|
-
if (onPhase) {
|
|
1988
|
-
curPts = [prevX, prevY];
|
|
1989
|
-
curA = [mA];
|
|
1990
|
-
curB = [mB];
|
|
1991
|
-
curT = [mT];
|
|
1833
|
+
flushSpan();
|
|
1834
|
+
span = {
|
|
1835
|
+
underline: e.run.underline,
|
|
1836
|
+
strikethrough: e.run.strikethrough,
|
|
1837
|
+
fill: e.run.fill,
|
|
1838
|
+
fontSize: e.fontSize,
|
|
1839
|
+
baselineY,
|
|
1840
|
+
x0: penX,
|
|
1841
|
+
x1: penX + step
|
|
1842
|
+
};
|
|
1992
1843
|
}
|
|
1844
|
+
} else {
|
|
1845
|
+
flushSpan();
|
|
1846
|
+
}
|
|
1847
|
+
const outlineD = outlineFor(e);
|
|
1848
|
+
if (outlineD !== null) {
|
|
1849
|
+
const group2 = getOrCreateGroup(ctx, e.run, e.resolved, 0, "outline");
|
|
1850
|
+
group2.glyphs.push({
|
|
1851
|
+
d: outlineD,
|
|
1852
|
+
key: `${e.resolved.resolved.family}|${e.resolved.resolved.weight}|${e.resolved.resolved.style}|${e.cp}`,
|
|
1853
|
+
x: penX,
|
|
1854
|
+
baselineY,
|
|
1855
|
+
// Em space is unit-scale, so world units per em is just the size.
|
|
1856
|
+
scale: e.fontSize
|
|
1857
|
+
});
|
|
1858
|
+
penX += step;
|
|
1859
|
+
continue;
|
|
1860
|
+
}
|
|
1861
|
+
if (e.advance === 0 || e.glyph.width === 0 || e.glyph.page < 0) {
|
|
1862
|
+
penX += step;
|
|
1863
|
+
continue;
|
|
1993
1864
|
}
|
|
1865
|
+
const group = getOrCreateGroup(ctx, e.run, e.resolved, e.glyph.page);
|
|
1866
|
+
const atlasW = e.font.common.scaleW;
|
|
1867
|
+
const atlasH = e.font.common.scaleH;
|
|
1868
|
+
const qx0 = penX + e.glyph.xoffset * scale2;
|
|
1869
|
+
const qy0 = penY + e.glyph.yoffset * scale2;
|
|
1870
|
+
const qx1 = qx0 + e.glyph.width * scale2;
|
|
1871
|
+
const qy1 = qy0 + e.glyph.height * scale2;
|
|
1872
|
+
const u0 = e.glyph.x / atlasW;
|
|
1873
|
+
const v0 = e.glyph.y / atlasH;
|
|
1874
|
+
const u1 = (e.glyph.x + e.glyph.width) / atlasW;
|
|
1875
|
+
const v1 = (e.glyph.y + e.glyph.height) / atlasH;
|
|
1876
|
+
group.quads.push({ x0: qx0, y0: qy0, x1: qx1, y1: qy1, u0, v0, u1, v1, baselineY });
|
|
1877
|
+
penX += step;
|
|
1994
1878
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
anchorT: new Float32Array(curT)
|
|
1879
|
+
flushSpan();
|
|
1880
|
+
lineBoxes.push({
|
|
1881
|
+
x0: lineX0,
|
|
1882
|
+
y0: penY,
|
|
1883
|
+
x1: lineX0 + line.width,
|
|
1884
|
+
y1: penY + line.height,
|
|
1885
|
+
baselineY: lineBaselineY
|
|
2003
1886
|
});
|
|
1887
|
+
maxLineWidth = Math.max(maxLineWidth, line.width);
|
|
1888
|
+
penY += line.height;
|
|
2004
1889
|
}
|
|
2005
|
-
return out;
|
|
2006
|
-
}
|
|
2007
|
-
function makeSeg(ax, ay, bx, by, halfA, halfB) {
|
|
2008
|
-
const dx = bx - ax, dy = by - ay;
|
|
2009
|
-
const len = Math.hypot(dx, dy);
|
|
2010
|
-
if (len === 0) return null;
|
|
2011
1890
|
return {
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
nxUnit: -dy / len,
|
|
2017
|
-
nyUnit: dx / len,
|
|
2018
|
-
halfA,
|
|
2019
|
-
halfB,
|
|
2020
|
-
len
|
|
1891
|
+
groups: [...ctx.groups.values()],
|
|
1892
|
+
decorations,
|
|
1893
|
+
lines: lineBoxes,
|
|
1894
|
+
bounds: { width: maxLineWidth, height: penY }
|
|
2021
1895
|
};
|
|
2022
1896
|
}
|
|
2023
|
-
var
|
|
2024
|
-
var
|
|
2025
|
-
function
|
|
2026
|
-
|
|
2027
|
-
const
|
|
2028
|
-
const
|
|
2029
|
-
|
|
2030
|
-
const
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
const
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
const forceBevelForVarying = taperA > varyingThreshold || taperB > varyingThreshold;
|
|
2046
|
-
if (join === "bevel" || forceBevelForVarying) {
|
|
2047
|
-
emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);
|
|
2048
|
-
return;
|
|
1897
|
+
var LAYOUT_CACHE_VARIANT_LIMIT = 8;
|
|
1898
|
+
var cache2 = /* @__PURE__ */ new WeakMap();
|
|
1899
|
+
function outlineBucket(runs, min) {
|
|
1900
|
+
if (min === void 0) return -1;
|
|
1901
|
+
const sizes = /* @__PURE__ */ new Set();
|
|
1902
|
+
for (const r of runs) sizes.add(r.fontSize);
|
|
1903
|
+
let n = 0;
|
|
1904
|
+
for (const size of sizes) if (size >= min) n++;
|
|
1905
|
+
return n;
|
|
1906
|
+
}
|
|
1907
|
+
function variantKey(runs, opts) {
|
|
1908
|
+
return `${opts.maxWidth}|${opts.lineHeight}|${opts.align}|${outlineBucket(runs, opts.outlineMinSize)}`;
|
|
1909
|
+
}
|
|
1910
|
+
function cachedLayoutRuns(runs, opts) {
|
|
1911
|
+
const fonts = glyphGeneration();
|
|
1912
|
+
let entry = cache2.get(runs);
|
|
1913
|
+
if (entry === void 0) {
|
|
1914
|
+
entry = { generation: fonts, byVariant: /* @__PURE__ */ new Map() };
|
|
1915
|
+
cache2.set(runs, entry);
|
|
1916
|
+
} else if (entry.generation !== fonts) {
|
|
1917
|
+
entry.generation = fonts;
|
|
1918
|
+
entry.byVariant.clear();
|
|
2049
1919
|
}
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
if (
|
|
2074
|
-
|
|
2075
|
-
|
|
1920
|
+
const key = variantKey(runs, opts);
|
|
1921
|
+
const hit = entry.byVariant.get(key);
|
|
1922
|
+
if (hit !== void 0) return hit;
|
|
1923
|
+
const laid = layoutRuns(runs, opts);
|
|
1924
|
+
if (entry.byVariant.size >= LAYOUT_CACHE_VARIANT_LIMIT) entry.byVariant.clear();
|
|
1925
|
+
entry.byVariant.set(key, laid);
|
|
1926
|
+
return laid;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
// src/features/text/verticalAlign.ts
|
|
1930
|
+
function verticalAlignOffset(align, boxHeight, textHeight) {
|
|
1931
|
+
if (align === void 0 || align === "top" || boxHeight === void 0) return 0;
|
|
1932
|
+
const slack = boxHeight - textHeight;
|
|
1933
|
+
return align === "center" ? slack / 2 : slack;
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
// src/features/paths/pathFromD.ts
|
|
1937
|
+
var NUM_RE = /[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g;
|
|
1938
|
+
function tokenize(d) {
|
|
1939
|
+
const out = [];
|
|
1940
|
+
let i = 0;
|
|
1941
|
+
while (i < d.length) {
|
|
1942
|
+
const ch = d[i];
|
|
1943
|
+
if (/[A-Za-z]/.test(ch)) {
|
|
1944
|
+
let j = i + 1;
|
|
1945
|
+
while (j < d.length && !/[A-Za-z]/.test(d[j])) j++;
|
|
1946
|
+
const argSlice = d.slice(i + 1, j);
|
|
1947
|
+
out.push({ cmd: ch, args: readNumbers(argSlice) });
|
|
1948
|
+
i = j;
|
|
2076
1949
|
} else {
|
|
2077
|
-
|
|
2078
|
-
idx.push(aOuterEnd, jIdx, bOuterStart);
|
|
1950
|
+
i++;
|
|
2079
1951
|
}
|
|
2080
|
-
return;
|
|
2081
|
-
}
|
|
2082
|
-
if (join === "round") {
|
|
2083
|
-
emitRoundJoin(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);
|
|
2084
|
-
return;
|
|
2085
1952
|
}
|
|
1953
|
+
return out;
|
|
2086
1954
|
}
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
anchorT.push(cornerT);
|
|
2095
|
-
const startX = verts[aOuterEnd * 2] - cx;
|
|
2096
|
-
const startY = verts[aOuterEnd * 2 + 1] - cy;
|
|
2097
|
-
const endX = verts[bOuterStart * 2] - cx;
|
|
2098
|
-
const endY = verts[bOuterStart * 2 + 1] - cy;
|
|
2099
|
-
const r = Math.hypot(startX, startY);
|
|
2100
|
-
const startAngle = Math.atan2(startY, startX);
|
|
2101
|
-
const endAngle = Math.atan2(endY, endX);
|
|
2102
|
-
let sweep = endAngle - startAngle;
|
|
2103
|
-
if (onPositive && sweep < 0) sweep += 2 * Math.PI;
|
|
2104
|
-
else if (!onPositive && sweep > 0) sweep -= 2 * Math.PI;
|
|
2105
|
-
const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_STEP_RAD));
|
|
2106
|
-
const stepAngle = sweep / steps;
|
|
2107
|
-
let prevIdx = aOuterEnd;
|
|
2108
|
-
for (let i = 1; i < steps; i++) {
|
|
2109
|
-
const ang = startAngle + i * stepAngle;
|
|
2110
|
-
const fx = cx + Math.cos(ang) * r;
|
|
2111
|
-
const fy = cy + Math.sin(ang) * r;
|
|
2112
|
-
const newIdx = verts.length / 2;
|
|
2113
|
-
verts.push(fx, fy);
|
|
2114
|
-
anchorA.push(cornerA);
|
|
2115
|
-
anchorB.push(cornerB);
|
|
2116
|
-
anchorT.push(cornerT);
|
|
2117
|
-
if (onPositive) idx.push(prevIdx, pivotIdx, newIdx);
|
|
2118
|
-
else idx.push(prevIdx, newIdx, pivotIdx);
|
|
2119
|
-
prevIdx = newIdx;
|
|
1955
|
+
function readNumbers(s) {
|
|
1956
|
+
const out = [];
|
|
1957
|
+
let m;
|
|
1958
|
+
NUM_RE.lastIndex = 0;
|
|
1959
|
+
while ((m = NUM_RE.exec(s)) !== null) {
|
|
1960
|
+
const n = Number(m[0]);
|
|
1961
|
+
if (Number.isFinite(n)) out.push(n);
|
|
2120
1962
|
}
|
|
2121
|
-
|
|
2122
|
-
else idx.push(prevIdx, bOuterStart, pivotIdx);
|
|
2123
|
-
}
|
|
2124
|
-
function emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT) {
|
|
2125
|
-
const jIdx = verts.length / 2;
|
|
2126
|
-
verts.push(a.bx, a.by);
|
|
2127
|
-
anchorA.push(cornerA);
|
|
2128
|
-
anchorB.push(cornerB);
|
|
2129
|
-
anchorT.push(cornerT);
|
|
2130
|
-
if (onPositive) idx.push(aOuterEnd, jIdx, bOuterStart);
|
|
2131
|
-
else idx.push(aOuterEnd, bOuterStart, jIdx);
|
|
2132
|
-
}
|
|
2133
|
-
function lineLineIntersect(apx, apy, adx, ady, bpx, bpy, bdx, bdy) {
|
|
2134
|
-
const denom = adx * bdy - ady * bdx;
|
|
2135
|
-
if (Math.abs(denom) < 1e-9) return null;
|
|
2136
|
-
const t = ((bpx - apx) * bdy - (bpy - apy) * bdx) / denom;
|
|
2137
|
-
return [apx + t * adx, apy + t * ady];
|
|
2138
|
-
}
|
|
2139
|
-
var UNDERLINE_OFFSET = 0.1;
|
|
2140
|
-
var STRIKETHROUGH_OFFSET = -0.3;
|
|
2141
|
-
var DECORATION_THICKNESS = 0.05;
|
|
2142
|
-
function fillKey(p) {
|
|
2143
|
-
if ("color" in p) return `s:${p.color}:${p.opacity ?? 1}`;
|
|
2144
|
-
return `nx:${Math.random()}`;
|
|
1963
|
+
return out;
|
|
2145
1964
|
}
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
1965
|
+
var ARG_COUNTS = {
|
|
1966
|
+
M: 2,
|
|
1967
|
+
L: 2,
|
|
1968
|
+
H: 1,
|
|
1969
|
+
V: 1,
|
|
1970
|
+
C: 6,
|
|
1971
|
+
S: 4,
|
|
1972
|
+
Q: 4,
|
|
1973
|
+
T: 2,
|
|
1974
|
+
A: 7,
|
|
1975
|
+
Z: 0
|
|
1976
|
+
};
|
|
1977
|
+
function pathFromD(d, onWarn) {
|
|
1978
|
+
const tokens = tokenize(d);
|
|
1979
|
+
const b = new PathBuilder();
|
|
1980
|
+
const st = {
|
|
1981
|
+
x: 0,
|
|
1982
|
+
y: 0,
|
|
1983
|
+
startX: 0,
|
|
1984
|
+
startY: 0,
|
|
1985
|
+
lastCubicCtrl: null,
|
|
1986
|
+
lastQuadCtrl: null
|
|
1987
|
+
};
|
|
1988
|
+
for (const { cmd, args } of tokens) {
|
|
1989
|
+
const upper = cmd.toUpperCase();
|
|
1990
|
+
const relative = cmd !== upper;
|
|
1991
|
+
const argCount = ARG_COUNTS[upper];
|
|
1992
|
+
if (argCount === void 0) {
|
|
1993
|
+
onWarn?.(`unknown path command: ${cmd}`);
|
|
1994
|
+
continue;
|
|
1995
|
+
}
|
|
1996
|
+
if (upper === "Z") {
|
|
1997
|
+
b.close();
|
|
1998
|
+
st.x = st.startX;
|
|
1999
|
+
st.y = st.startY;
|
|
2000
|
+
st.lastCubicCtrl = null;
|
|
2001
|
+
st.lastQuadCtrl = null;
|
|
2002
|
+
continue;
|
|
2003
|
+
}
|
|
2004
|
+
const groups = argCount === 0 ? 1 : Math.floor(args.length / argCount);
|
|
2005
|
+
for (let g = 0; g < groups; g++) {
|
|
2006
|
+
const a = args.slice(g * argCount, (g + 1) * argCount);
|
|
2007
|
+
const effectiveUpper = upper === "M" && g > 0 ? "L" : upper;
|
|
2008
|
+
runCommand(effectiveUpper, relative, a, st, b);
|
|
2009
|
+
}
|
|
2150
2010
|
}
|
|
2151
|
-
return
|
|
2011
|
+
return b.build();
|
|
2152
2012
|
}
|
|
2153
|
-
function
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2013
|
+
function runCommand(upper, relative, a, st, b) {
|
|
2014
|
+
const rx = relative ? st.x : 0;
|
|
2015
|
+
const ry = relative ? st.y : 0;
|
|
2016
|
+
switch (upper) {
|
|
2017
|
+
case "M": {
|
|
2018
|
+
const x = a[0] + rx;
|
|
2019
|
+
const y = a[1] + ry;
|
|
2020
|
+
b.moveTo(x, y);
|
|
2021
|
+
st.x = x;
|
|
2022
|
+
st.y = y;
|
|
2023
|
+
st.startX = x;
|
|
2024
|
+
st.startY = y;
|
|
2025
|
+
st.lastCubicCtrl = null;
|
|
2026
|
+
st.lastQuadCtrl = null;
|
|
2027
|
+
return;
|
|
2028
|
+
}
|
|
2029
|
+
case "L": {
|
|
2030
|
+
const x = a[0] + rx;
|
|
2031
|
+
const y = a[1] + ry;
|
|
2032
|
+
b.lineTo(x, y);
|
|
2033
|
+
st.x = x;
|
|
2034
|
+
st.y = y;
|
|
2035
|
+
st.lastCubicCtrl = null;
|
|
2036
|
+
st.lastQuadCtrl = null;
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
case "H": {
|
|
2040
|
+
const x = a[0] + (relative ? st.x : 0);
|
|
2041
|
+
b.lineTo(x, st.y);
|
|
2042
|
+
st.x = x;
|
|
2043
|
+
st.lastCubicCtrl = null;
|
|
2044
|
+
st.lastQuadCtrl = null;
|
|
2045
|
+
return;
|
|
2046
|
+
}
|
|
2047
|
+
case "V": {
|
|
2048
|
+
const y = a[0] + (relative ? st.y : 0);
|
|
2049
|
+
b.lineTo(st.x, y);
|
|
2050
|
+
st.y = y;
|
|
2051
|
+
st.lastCubicCtrl = null;
|
|
2052
|
+
st.lastQuadCtrl = null;
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2055
|
+
case "C": {
|
|
2056
|
+
const x1 = a[0] + rx, y1 = a[1] + ry;
|
|
2057
|
+
const x2 = a[2] + rx, y2 = a[3] + ry;
|
|
2058
|
+
const x = a[4] + rx, y = a[5] + ry;
|
|
2059
|
+
b.curveTo(x1, y1, x2, y2, x, y);
|
|
2060
|
+
st.x = x;
|
|
2061
|
+
st.y = y;
|
|
2062
|
+
st.lastCubicCtrl = { x: x2, y: y2 };
|
|
2063
|
+
st.lastQuadCtrl = null;
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
2066
|
+
case "S": {
|
|
2067
|
+
const ref = st.lastCubicCtrl ?? { x: st.x, y: st.y };
|
|
2068
|
+
const x1 = 2 * st.x - ref.x;
|
|
2069
|
+
const y1 = 2 * st.y - ref.y;
|
|
2070
|
+
const x2 = a[0] + rx, y2 = a[1] + ry;
|
|
2071
|
+
const x = a[2] + rx, y = a[3] + ry;
|
|
2072
|
+
b.curveTo(x1, y1, x2, y2, x, y);
|
|
2073
|
+
st.x = x;
|
|
2074
|
+
st.y = y;
|
|
2075
|
+
st.lastCubicCtrl = { x: x2, y: y2 };
|
|
2076
|
+
st.lastQuadCtrl = null;
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
case "Q": {
|
|
2080
|
+
const x1 = a[0] + rx, y1 = a[1] + ry;
|
|
2081
|
+
const x = a[2] + rx, y = a[3] + ry;
|
|
2082
|
+
b.quadTo(x1, y1, x, y);
|
|
2083
|
+
st.x = x;
|
|
2084
|
+
st.y = y;
|
|
2085
|
+
st.lastQuadCtrl = { x: x1, y: y1 };
|
|
2086
|
+
st.lastCubicCtrl = null;
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
case "T": {
|
|
2090
|
+
const ref = st.lastQuadCtrl ?? { x: st.x, y: st.y };
|
|
2091
|
+
const x1 = 2 * st.x - ref.x;
|
|
2092
|
+
const y1 = 2 * st.y - ref.y;
|
|
2093
|
+
const x = a[0] + rx, y = a[1] + ry;
|
|
2094
|
+
b.quadTo(x1, y1, x, y);
|
|
2095
|
+
st.x = x;
|
|
2096
|
+
st.y = y;
|
|
2097
|
+
st.lastQuadCtrl = { x: x1, y: y1 };
|
|
2098
|
+
st.lastCubicCtrl = null;
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
case "A": {
|
|
2102
|
+
const rxA = Math.abs(a[0]);
|
|
2103
|
+
const ryA = Math.abs(a[1]);
|
|
2104
|
+
const xRot = a[2];
|
|
2105
|
+
const largeArc = a[3] !== 0;
|
|
2106
|
+
const sweep = a[4] !== 0;
|
|
2107
|
+
const ex = a[5] + rx;
|
|
2108
|
+
const ey = a[6] + ry;
|
|
2109
|
+
arcToCubics(st.x, st.y, ex, ey, rxA, ryA, xRot, largeArc, sweep, b);
|
|
2110
|
+
st.x = ex;
|
|
2111
|
+
st.y = ey;
|
|
2112
|
+
st.lastCubicCtrl = null;
|
|
2113
|
+
st.lastQuadCtrl = null;
|
|
2114
|
+
return;
|
|
2115
|
+
}
|
|
2116
|
+
default:
|
|
2117
|
+
return;
|
|
2118
|
+
}
|
|
2167
2119
|
}
|
|
2168
|
-
function
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2120
|
+
function arcToCubics(x1, y1, x2, y2, rx, ry, xAxisRotationDeg, largeArc, sweep, b) {
|
|
2121
|
+
if (x1 === x2 && y1 === y2) return;
|
|
2122
|
+
if (rx === 0 || ry === 0) {
|
|
2123
|
+
b.lineTo(x2, y2);
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
const phi = xAxisRotationDeg * Math.PI / 180;
|
|
2127
|
+
const cosPhi = Math.cos(phi);
|
|
2128
|
+
const sinPhi = Math.sin(phi);
|
|
2129
|
+
const dx = (x1 - x2) / 2;
|
|
2130
|
+
const dy = (y1 - y2) / 2;
|
|
2131
|
+
const x1p = cosPhi * dx + sinPhi * dy;
|
|
2132
|
+
const y1p = -sinPhi * dx + cosPhi * dy;
|
|
2133
|
+
let rxs = rx * rx;
|
|
2134
|
+
let rys = ry * ry;
|
|
2135
|
+
const x1ps = x1p * x1p;
|
|
2136
|
+
const y1ps = y1p * y1p;
|
|
2137
|
+
const lambda = x1ps / rxs + y1ps / rys;
|
|
2138
|
+
let rxFixed = rx;
|
|
2139
|
+
let ryFixed = ry;
|
|
2140
|
+
if (lambda > 1) {
|
|
2141
|
+
const sqrtLambda = Math.sqrt(lambda);
|
|
2142
|
+
rxFixed = sqrtLambda * rx;
|
|
2143
|
+
ryFixed = sqrtLambda * ry;
|
|
2144
|
+
rxs = rxFixed * rxFixed;
|
|
2145
|
+
rys = ryFixed * ryFixed;
|
|
2146
|
+
}
|
|
2147
|
+
const sign = largeArc === sweep ? -1 : 1;
|
|
2148
|
+
const num = rxs * rys - rxs * y1ps - rys * x1ps;
|
|
2149
|
+
const den = rxs * y1ps + rys * x1ps;
|
|
2150
|
+
const factor = sign * Math.sqrt(Math.max(0, num / den));
|
|
2151
|
+
const cxp = factor * (rxFixed * y1p) / ryFixed;
|
|
2152
|
+
const cyp = factor * -(ryFixed * x1p) / rxFixed;
|
|
2153
|
+
const cx = cosPhi * cxp - sinPhi * cyp + (x1 + x2) / 2;
|
|
2154
|
+
const cy = sinPhi * cxp + cosPhi * cyp + (y1 + y2) / 2;
|
|
2155
|
+
const angle = (ux, uy, vx, vy) => {
|
|
2156
|
+
const dot = ux * vx + uy * vy;
|
|
2157
|
+
const len = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
|
|
2158
|
+
let a = Math.acos(Math.max(-1, Math.min(1, dot / len)));
|
|
2159
|
+
if (ux * vy - uy * vx < 0) a = -a;
|
|
2160
|
+
return a;
|
|
2161
|
+
};
|
|
2162
|
+
const theta1 = angle(1, 0, (x1p - cxp) / rxFixed, (y1p - cyp) / ryFixed);
|
|
2163
|
+
let dTheta = angle(
|
|
2164
|
+
(x1p - cxp) / rxFixed,
|
|
2165
|
+
(y1p - cyp) / ryFixed,
|
|
2166
|
+
(-x1p - cxp) / rxFixed,
|
|
2167
|
+
(-y1p - cyp) / ryFixed
|
|
2182
2168
|
);
|
|
2183
|
-
|
|
2184
|
-
if (
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2169
|
+
if (!sweep && dTheta > 0) dTheta -= 2 * Math.PI;
|
|
2170
|
+
else if (sweep && dTheta < 0) dTheta += 2 * Math.PI;
|
|
2171
|
+
const segCount = Math.max(1, Math.ceil(Math.abs(dTheta) / (Math.PI / 2)));
|
|
2172
|
+
const segAngle = dTheta / segCount;
|
|
2173
|
+
const t = 4 / 3 * Math.tan(segAngle / 4);
|
|
2174
|
+
let prevX = x1;
|
|
2175
|
+
let prevY = y1;
|
|
2176
|
+
let prevDx = -Math.sin(theta1) * rxFixed;
|
|
2177
|
+
let prevDy = Math.cos(theta1) * ryFixed;
|
|
2178
|
+
for (let i = 1; i <= segCount; i++) {
|
|
2179
|
+
const theta = theta1 + i * segAngle;
|
|
2180
|
+
const cosT = Math.cos(theta);
|
|
2181
|
+
const sinT = Math.sin(theta);
|
|
2182
|
+
const px = cosPhi * (cosT * rxFixed) - sinPhi * (sinT * ryFixed) + cx;
|
|
2183
|
+
const py = sinPhi * (cosT * rxFixed) + cosPhi * (sinT * ryFixed) + cy;
|
|
2184
|
+
const dxNew = -sinT * rxFixed;
|
|
2185
|
+
const dyNew = cosT * ryFixed;
|
|
2186
|
+
const c1x = prevX + cosPhi * (t * prevDx) - sinPhi * (t * prevDy);
|
|
2187
|
+
const c1y = prevY + sinPhi * (t * prevDx) + cosPhi * (t * prevDy);
|
|
2188
|
+
const c2x = px - cosPhi * (t * dxNew) + sinPhi * (t * dyNew);
|
|
2189
|
+
const c2y = py - sinPhi * (t * dxNew) - cosPhi * (t * dyNew);
|
|
2190
|
+
b.curveTo(c1x, c1y, c2x, c2y, px, py);
|
|
2191
|
+
prevX = px;
|
|
2192
|
+
prevY = py;
|
|
2193
|
+
prevDx = dxNew;
|
|
2194
|
+
prevDy = dyNew;
|
|
2200
2195
|
}
|
|
2201
|
-
return g;
|
|
2202
2196
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
return null;
|
|
2197
|
+
|
|
2198
|
+
// src/renderer/cache/outlineMeshCache.ts
|
|
2199
|
+
var OUTLINE_FLATTEN_TOLERANCE = 1 / 4096;
|
|
2200
|
+
var OUTLINE_MESH_CACHE_LIMIT = 2048;
|
|
2201
|
+
var cache3 = /* @__PURE__ */ new Map();
|
|
2202
|
+
function outlineMesh(key, d) {
|
|
2203
|
+
const cached = cache3.get(key);
|
|
2204
|
+
if (cached !== void 0) return cached;
|
|
2205
|
+
if (cache3.size >= OUTLINE_MESH_CACHE_LIMIT) cache3 = /* @__PURE__ */ new Map();
|
|
2206
|
+
const mesh = tessellate(pathFromD(d), { flattenTolerance: OUTLINE_FLATTEN_TOLERANCE });
|
|
2207
|
+
cache3.set(key, mesh);
|
|
2208
|
+
return mesh;
|
|
2216
2209
|
}
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
if (
|
|
2221
|
-
|
|
2222
|
-
const ch = String.fromCodePoint(cp);
|
|
2223
|
-
console.warn(
|
|
2224
|
-
`weasel layoutRuns: no glyph for U+${cp.toString(16).toUpperCase().padStart(4, "0")} (${JSON.stringify(ch)}) in "${family}", and the dynamic tier could not rasterize it \u2014 skipping the character. Bake it into the atlas, or call registerCanvasFont("${family}") to serve missing codepoints from installed fonts.`
|
|
2225
|
-
);
|
|
2210
|
+
|
|
2211
|
+
// src/features/paths/tessellate/polyline.ts
|
|
2212
|
+
function extractPolylines(path, opts = {}) {
|
|
2213
|
+
if (path.kind === "rect") return [extractRect(path)];
|
|
2214
|
+
return extractPolygon(path, opts);
|
|
2226
2215
|
}
|
|
2227
|
-
function
|
|
2228
|
-
const
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
continue;
|
|
2216
|
+
function extractRect(p) {
|
|
2217
|
+
const { x, y, width: w, height: h } = p;
|
|
2218
|
+
return {
|
|
2219
|
+
points: [x, y, x + w, y, x + w, y + h, x, y + h],
|
|
2220
|
+
closed: true,
|
|
2221
|
+
anchorA: new Uint32Array([0, 1, 2, 3]),
|
|
2222
|
+
anchorB: new Uint32Array([0, 1, 2, 3]),
|
|
2223
|
+
anchorT: new Float32Array([0, 0, 0, 0])
|
|
2224
|
+
};
|
|
2225
|
+
}
|
|
2226
|
+
function extractPolygon(p, opts) {
|
|
2227
|
+
const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;
|
|
2228
|
+
const { commands, coords } = p;
|
|
2229
|
+
const out = [];
|
|
2230
|
+
let anchorCounter = 0;
|
|
2231
|
+
let pts = null;
|
|
2232
|
+
let aA = null;
|
|
2233
|
+
let aB = null;
|
|
2234
|
+
let aT = null;
|
|
2235
|
+
let current = null;
|
|
2236
|
+
let coordIdx = 0;
|
|
2237
|
+
let prevX = 0;
|
|
2238
|
+
let prevY = 0;
|
|
2239
|
+
let prevAnchor = -1;
|
|
2240
|
+
const beginContour = () => {
|
|
2241
|
+
pts = [];
|
|
2242
|
+
aA = [];
|
|
2243
|
+
aB = [];
|
|
2244
|
+
aT = [];
|
|
2245
|
+
const next = { points: pts, closed: false };
|
|
2246
|
+
out.push(next);
|
|
2247
|
+
return next;
|
|
2248
|
+
};
|
|
2249
|
+
const dropDuplicateClosingPoint = () => {
|
|
2250
|
+
if (!pts || !aA || !aB || !aT) return;
|
|
2251
|
+
const n = pts.length / 2;
|
|
2252
|
+
if (n < 2) return;
|
|
2253
|
+
if (pts[0] !== pts[(n - 1) * 2] || pts[1] !== pts[(n - 1) * 2 + 1]) return;
|
|
2254
|
+
pts.length -= 2;
|
|
2255
|
+
aA.length -= 1;
|
|
2256
|
+
aB.length -= 1;
|
|
2257
|
+
aT.length -= 1;
|
|
2258
|
+
};
|
|
2259
|
+
const commit = (target) => {
|
|
2260
|
+
if (!pts || !aA || !aB || !aT) return;
|
|
2261
|
+
target.anchorA = new Uint32Array(aA);
|
|
2262
|
+
target.anchorB = new Uint32Array(aB);
|
|
2263
|
+
target.anchorT = new Float32Array(aT);
|
|
2264
|
+
};
|
|
2265
|
+
for (let cmdIdx = 0; cmdIdx < commands.length; cmdIdx++) {
|
|
2266
|
+
const cmd = commands[cmdIdx];
|
|
2267
|
+
switch (cmd) {
|
|
2268
|
+
case PATH_M: {
|
|
2269
|
+
if (current) commit(current);
|
|
2270
|
+
current = beginContour();
|
|
2271
|
+
prevX = coords[coordIdx];
|
|
2272
|
+
prevY = coords[coordIdx + 1];
|
|
2273
|
+
pts.push(prevX, prevY);
|
|
2274
|
+
aA.push(anchorCounter);
|
|
2275
|
+
aB.push(anchorCounter);
|
|
2276
|
+
aT.push(0);
|
|
2277
|
+
prevAnchor = anchorCounter;
|
|
2278
|
+
anchorCounter++;
|
|
2279
|
+
coordIdx += 2;
|
|
2280
|
+
break;
|
|
2293
2281
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2282
|
+
case PATH_L: {
|
|
2283
|
+
prevX = coords[coordIdx];
|
|
2284
|
+
prevY = coords[coordIdx + 1];
|
|
2285
|
+
pts.push(prevX, prevY);
|
|
2286
|
+
aA.push(anchorCounter);
|
|
2287
|
+
aB.push(anchorCounter);
|
|
2288
|
+
aT.push(0);
|
|
2289
|
+
prevAnchor = anchorCounter;
|
|
2290
|
+
anchorCounter++;
|
|
2291
|
+
coordIdx += 2;
|
|
2292
|
+
break;
|
|
2300
2293
|
}
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
const
|
|
2306
|
-
|
|
2294
|
+
case PATH_Q: {
|
|
2295
|
+
const cx = coords[coordIdx], cy = coords[coordIdx + 1];
|
|
2296
|
+
const ex = coords[coordIdx + 2], ey = coords[coordIdx + 3];
|
|
2297
|
+
const targetAnchor = anchorCounter;
|
|
2298
|
+
const segStart = pts.length / 2;
|
|
2299
|
+
const arcAccum = [];
|
|
2300
|
+
const total = flattenQuadraticWithArcLen(prevX, prevY, cx, cy, ex, ey, tolerance, pts, arcAccum);
|
|
2301
|
+
for (let k = 0; k < arcAccum.length; k++) {
|
|
2302
|
+
aA.push(prevAnchor);
|
|
2303
|
+
aB.push(targetAnchor);
|
|
2304
|
+
aT.push(total > 0 ? arcAccum[k] / total : 0);
|
|
2305
|
+
}
|
|
2306
|
+
const lastIdx = segStart + arcAccum.length - 1;
|
|
2307
|
+
aA[lastIdx] = targetAnchor;
|
|
2308
|
+
aB[lastIdx] = targetAnchor;
|
|
2309
|
+
aT[lastIdx] = 0;
|
|
2310
|
+
prevX = ex;
|
|
2311
|
+
prevY = ey;
|
|
2312
|
+
prevAnchor = targetAnchor;
|
|
2313
|
+
anchorCounter++;
|
|
2314
|
+
coordIdx += 4;
|
|
2315
|
+
break;
|
|
2307
2316
|
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
}
|
|
2332
|
-
let i = 0;
|
|
2333
|
-
while (i < entries.length) {
|
|
2334
|
-
const e = entries[i];
|
|
2335
|
-
if (e.isNewline) {
|
|
2336
|
-
if (cur.entries.length === 0) {
|
|
2337
|
-
cur.height = Math.max(cur.height, e.fontSize * opts.lineHeight);
|
|
2338
|
-
cur.blank = e;
|
|
2317
|
+
case PATH_C: {
|
|
2318
|
+
const c1x = coords[coordIdx], c1y = coords[coordIdx + 1];
|
|
2319
|
+
const c2x = coords[coordIdx + 2], c2y = coords[coordIdx + 3];
|
|
2320
|
+
const ex = coords[coordIdx + 4], ey = coords[coordIdx + 5];
|
|
2321
|
+
const targetAnchor = anchorCounter;
|
|
2322
|
+
const segStart = pts.length / 2;
|
|
2323
|
+
const arcAccum = [];
|
|
2324
|
+
const total = flattenCubicWithArcLen(prevX, prevY, c1x, c1y, c2x, c2y, ex, ey, tolerance, pts, arcAccum);
|
|
2325
|
+
for (let k = 0; k < arcAccum.length; k++) {
|
|
2326
|
+
aA.push(prevAnchor);
|
|
2327
|
+
aB.push(targetAnchor);
|
|
2328
|
+
aT.push(total > 0 ? arcAccum[k] / total : 0);
|
|
2329
|
+
}
|
|
2330
|
+
const lastIdx = segStart + arcAccum.length - 1;
|
|
2331
|
+
aA[lastIdx] = targetAnchor;
|
|
2332
|
+
aB[lastIdx] = targetAnchor;
|
|
2333
|
+
aT[lastIdx] = 0;
|
|
2334
|
+
prevX = ex;
|
|
2335
|
+
prevY = ey;
|
|
2336
|
+
prevAnchor = targetAnchor;
|
|
2337
|
+
anchorCounter++;
|
|
2338
|
+
coordIdx += 6;
|
|
2339
|
+
break;
|
|
2339
2340
|
}
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
cur.entries.push(e);
|
|
2347
|
-
cur.width += e.kerningBefore + e.advance + e.tracking;
|
|
2348
|
-
cur.height = Math.max(cur.height, e.fontSize * opts.lineHeight);
|
|
2341
|
+
case PATH_Z: {
|
|
2342
|
+
if (current) {
|
|
2343
|
+
current.closed = true;
|
|
2344
|
+
dropDuplicateClosingPoint();
|
|
2345
|
+
}
|
|
2346
|
+
break;
|
|
2349
2347
|
}
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
}
|
|
2353
|
-
let j = i;
|
|
2354
|
-
let wordWidth = 0;
|
|
2355
|
-
while (j < entries.length && !entries[j].isSpace && !entries[j].isNewline) {
|
|
2356
|
-
const w = entries[j];
|
|
2357
|
-
wordWidth += w.kerningBefore + w.advance + w.tracking;
|
|
2358
|
-
j++;
|
|
2359
|
-
}
|
|
2360
|
-
if (Number.isFinite(opts.maxWidth) && cur.width + wordWidth > opts.maxWidth && cur.entries.length > 0) {
|
|
2361
|
-
commitLine();
|
|
2362
|
-
}
|
|
2363
|
-
for (let k = i; k < j; k++) {
|
|
2364
|
-
const w = entries[k];
|
|
2365
|
-
const kerningBefore = cur.entries.length === 0 ? 0 : w.kerningBefore;
|
|
2366
|
-
cur.entries.push({ ...w, kerningBefore });
|
|
2367
|
-
cur.width += kerningBefore + w.advance + w.tracking;
|
|
2368
|
-
cur.height = Math.max(cur.height, w.fontSize * opts.lineHeight);
|
|
2348
|
+
default:
|
|
2349
|
+
throw new Error(`extractPolylines: unknown command code ${cmd}`);
|
|
2369
2350
|
}
|
|
2370
|
-
i = j;
|
|
2371
2351
|
}
|
|
2372
|
-
if (
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2352
|
+
if (current) commit(current);
|
|
2353
|
+
return out;
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
// src/features/paths/tessellate/stroke.ts
|
|
2357
|
+
var EMPTY_MESH = {
|
|
2358
|
+
vertices: new Float32Array(0),
|
|
2359
|
+
indices: new Uint32Array(0),
|
|
2360
|
+
anchorA: new Uint32Array(0),
|
|
2361
|
+
anchorB: new Uint32Array(0),
|
|
2362
|
+
anchorT: new Float32Array(0)
|
|
2363
|
+
};
|
|
2364
|
+
function tessellateStroke(path, stroke, opts = {}) {
|
|
2365
|
+
const width = stroke.width ?? 1;
|
|
2366
|
+
if (width <= 0) return EMPTY_MESH;
|
|
2367
|
+
const join = stroke.join ?? "miter";
|
|
2368
|
+
const cap = stroke.cap ?? "butt";
|
|
2369
|
+
const align = stroke.align ?? "center";
|
|
2370
|
+
const miterLimit = stroke.miterLimit ?? DEFAULT_MITER_LIMIT;
|
|
2371
|
+
const varyingThreshold = stroke.varyingWidthJoinThreshold ?? DEFAULT_VARYING_WIDTH_JOIN_THRESHOLD;
|
|
2372
|
+
let workingPath = path;
|
|
2373
|
+
if (path.kind === "rect" && align !== "center") {
|
|
2374
|
+
const aligned = alignedStrokeRect(path, align, width);
|
|
2375
|
+
workingPath = {
|
|
2376
|
+
kind: "rect",
|
|
2377
|
+
x: aligned.x,
|
|
2378
|
+
y: aligned.y,
|
|
2379
|
+
width: aligned.width,
|
|
2380
|
+
height: aligned.height
|
|
2381
|
+
};
|
|
2379
2382
|
}
|
|
2380
|
-
const
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2383
|
+
const polylines = extractPolylines(workingPath, opts);
|
|
2384
|
+
if (stroke.vertexWidths && stroke.vertexWidths.length > 0) {
|
|
2385
|
+
for (const pl of polylines) populatePolylineWidths(pl, stroke.vertexWidths, width);
|
|
2386
|
+
}
|
|
2387
|
+
const dash = stroke.dash ?? [];
|
|
2388
|
+
const verts = [];
|
|
2389
|
+
const idx = [];
|
|
2390
|
+
const anchorA = [];
|
|
2391
|
+
const anchorB = [];
|
|
2392
|
+
const anchorT = [];
|
|
2393
|
+
for (const pl of polylines) {
|
|
2394
|
+
const subs = dash.length > 0 ? splitForDash(pl, dash) : [pl];
|
|
2395
|
+
for (const sub2 of subs) {
|
|
2396
|
+
expandPolyline(sub2, width, join, cap, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT);
|
|
2390
2397
|
}
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2398
|
+
}
|
|
2399
|
+
return {
|
|
2400
|
+
vertices: new Float32Array(verts),
|
|
2401
|
+
indices: new Uint32Array(idx),
|
|
2402
|
+
anchorA: new Uint32Array(anchorA),
|
|
2403
|
+
anchorB: new Uint32Array(anchorB),
|
|
2404
|
+
anchorT: new Float32Array(anchorT)
|
|
2405
|
+
};
|
|
2406
|
+
}
|
|
2407
|
+
function expandPolyline(pl, width, join, cap, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT) {
|
|
2408
|
+
const half = width / 2;
|
|
2409
|
+
const pts = pl.points;
|
|
2410
|
+
const ptCount = pts.length / 2;
|
|
2411
|
+
const segCount = ptCount - 1;
|
|
2412
|
+
if (segCount < 1) return;
|
|
2413
|
+
const plA = pl.anchorA ?? new Uint32Array(ptCount);
|
|
2414
|
+
const plB = pl.anchorB ?? new Uint32Array(ptCount);
|
|
2415
|
+
const plT = pl.anchorT ?? new Float32Array(ptCount);
|
|
2416
|
+
const plHalf = pl.widths ? pl.widths.map((w) => w / 2) : null;
|
|
2417
|
+
const segs = [];
|
|
2418
|
+
const segSrcIdx = [];
|
|
2419
|
+
for (let s = 0; s < segCount; s++) {
|
|
2420
|
+
const ha = plHalf ? plHalf[s] : half;
|
|
2421
|
+
const hb = plHalf ? plHalf[s + 1] : half;
|
|
2422
|
+
const seg = makeSeg(pts[s * 2], pts[s * 2 + 1], pts[(s + 1) * 2], pts[(s + 1) * 2 + 1], ha, hb);
|
|
2423
|
+
if (seg) {
|
|
2424
|
+
segs.push(seg);
|
|
2425
|
+
segSrcIdx.push(s);
|
|
2394
2426
|
}
|
|
2395
2427
|
}
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
const
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
return opts.align === "center" ? slack / 2 : slack;
|
|
2408
|
-
})();
|
|
2409
|
-
const lineX0 = alignShift;
|
|
2410
|
-
const baselineSource = line.entries[0] ?? line.blank;
|
|
2411
|
-
const lineBaselineY = baselineSource ? penY + baselineSource.font.common.base * (baselineSource.fontSize / baselineSource.font.info.size) : penY;
|
|
2412
|
-
let penX = lineX0;
|
|
2413
|
-
for (const e of line.entries) {
|
|
2414
|
-
penX += e.kerningBefore;
|
|
2415
|
-
const step = e.advance + e.tracking;
|
|
2416
|
-
const scale2 = e.fontSize / e.font.info.size;
|
|
2417
|
-
const baselineY = penY + e.font.common.base * scale2;
|
|
2418
|
-
if (e.run.underline || e.run.strikethrough) {
|
|
2419
|
-
if (span !== null && span.underline === e.run.underline && span.strikethrough === e.run.strikethrough && span.fontSize === e.fontSize && span.baselineY === baselineY && sameFill(span.fill, e.run.fill)) {
|
|
2420
|
-
span.x1 = penX + step;
|
|
2421
|
-
} else {
|
|
2422
|
-
flushSpan();
|
|
2423
|
-
span = {
|
|
2424
|
-
underline: e.run.underline,
|
|
2425
|
-
strikethrough: e.run.strikethrough,
|
|
2426
|
-
fill: e.run.fill,
|
|
2427
|
-
fontSize: e.fontSize,
|
|
2428
|
-
baselineY,
|
|
2429
|
-
x0: penX,
|
|
2430
|
-
x1: penX + step
|
|
2431
|
-
};
|
|
2432
|
-
}
|
|
2433
|
-
} else {
|
|
2434
|
-
flushSpan();
|
|
2435
|
-
}
|
|
2436
|
-
const outlineD = outlineFor(e);
|
|
2437
|
-
if (outlineD !== null) {
|
|
2438
|
-
const group2 = getOrCreateGroup(ctx, e.run, e.resolved, 0, "outline");
|
|
2439
|
-
group2.glyphs.push({
|
|
2440
|
-
d: outlineD,
|
|
2441
|
-
key: `${e.resolved.resolved.family}|${e.resolved.resolved.weight}|${e.resolved.resolved.style}|${e.cp}`,
|
|
2442
|
-
x: penX,
|
|
2443
|
-
baselineY,
|
|
2444
|
-
// Em space is unit-scale, so world units per em is just the size.
|
|
2445
|
-
scale: e.fontSize
|
|
2446
|
-
});
|
|
2447
|
-
penX += step;
|
|
2448
|
-
continue;
|
|
2449
|
-
}
|
|
2450
|
-
if (e.advance === 0 || e.glyph.width === 0 || e.glyph.page < 0) {
|
|
2451
|
-
penX += step;
|
|
2452
|
-
continue;
|
|
2453
|
-
}
|
|
2454
|
-
const group = getOrCreateGroup(ctx, e.run, e.resolved, e.glyph.page);
|
|
2455
|
-
const atlasW = e.font.common.scaleW;
|
|
2456
|
-
const atlasH = e.font.common.scaleH;
|
|
2457
|
-
const qx0 = penX + e.glyph.xoffset * scale2;
|
|
2458
|
-
const qy0 = penY + e.glyph.yoffset * scale2;
|
|
2459
|
-
const qx1 = qx0 + e.glyph.width * scale2;
|
|
2460
|
-
const qy1 = qy0 + e.glyph.height * scale2;
|
|
2461
|
-
const u0 = e.glyph.x / atlasW;
|
|
2462
|
-
const v0 = e.glyph.y / atlasH;
|
|
2463
|
-
const u1 = (e.glyph.x + e.glyph.width) / atlasW;
|
|
2464
|
-
const v1 = (e.glyph.y + e.glyph.height) / atlasH;
|
|
2465
|
-
group.quads.push({ x0: qx0, y0: qy0, x1: qx1, y1: qy1, u0, v0, u1, v1, baselineY });
|
|
2466
|
-
penX += step;
|
|
2428
|
+
let closerSrcIdx = -1;
|
|
2429
|
+
if (pl.closed && segs.length >= 1) {
|
|
2430
|
+
const last = segs[segs.length - 1];
|
|
2431
|
+
const first = segs[0];
|
|
2432
|
+
const haCloser = plHalf ? plHalf[ptCount - 1] : half;
|
|
2433
|
+
const hbCloser = plHalf ? plHalf[0] : half;
|
|
2434
|
+
const closer = makeSeg(last.bx, last.by, first.ax, first.ay, haCloser, hbCloser);
|
|
2435
|
+
if (closer) {
|
|
2436
|
+
segs.push(closer);
|
|
2437
|
+
closerSrcIdx = ptCount - 1;
|
|
2438
|
+
segSrcIdx.push(closerSrcIdx);
|
|
2467
2439
|
}
|
|
2468
|
-
flushSpan();
|
|
2469
|
-
lineBoxes.push({
|
|
2470
|
-
x0: lineX0,
|
|
2471
|
-
y0: penY,
|
|
2472
|
-
x1: lineX0 + line.width,
|
|
2473
|
-
y1: penY + line.height,
|
|
2474
|
-
baselineY: lineBaselineY
|
|
2475
|
-
});
|
|
2476
|
-
maxLineWidth = Math.max(maxLineWidth, line.width);
|
|
2477
|
-
penY += line.height;
|
|
2478
2440
|
}
|
|
2479
|
-
return
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2441
|
+
if (segs.length === 0) return;
|
|
2442
|
+
const segBaseIdx = [];
|
|
2443
|
+
for (let s = 0; s < segs.length; s++) {
|
|
2444
|
+
const seg = segs[s];
|
|
2445
|
+
const startSrc = segSrcIdx[s];
|
|
2446
|
+
const endSrc = s === segs.length - 1 && pl.closed && closerSrcIdx >= 0 ? 0 : startSrc + 1;
|
|
2447
|
+
const base = verts.length / 2;
|
|
2448
|
+
segBaseIdx.push(base);
|
|
2449
|
+
const nxA = seg.nxUnit * seg.halfA, nyA = seg.nyUnit * seg.halfA;
|
|
2450
|
+
const nxB = seg.nxUnit * seg.halfB, nyB = seg.nyUnit * seg.halfB;
|
|
2451
|
+
verts.push(seg.ax + nxA, seg.ay + nyA);
|
|
2452
|
+
anchorA.push(plA[startSrc]);
|
|
2453
|
+
anchorB.push(plB[startSrc]);
|
|
2454
|
+
anchorT.push(plT[startSrc]);
|
|
2455
|
+
verts.push(seg.ax - nxA, seg.ay - nyA);
|
|
2456
|
+
anchorA.push(plA[startSrc]);
|
|
2457
|
+
anchorB.push(plB[startSrc]);
|
|
2458
|
+
anchorT.push(plT[startSrc]);
|
|
2459
|
+
verts.push(seg.bx + nxB, seg.by + nyB);
|
|
2460
|
+
anchorA.push(plA[endSrc]);
|
|
2461
|
+
anchorB.push(plB[endSrc]);
|
|
2462
|
+
anchorT.push(plT[endSrc]);
|
|
2463
|
+
verts.push(seg.bx - nxB, seg.by - nyB);
|
|
2464
|
+
anchorA.push(plA[endSrc]);
|
|
2465
|
+
anchorB.push(plB[endSrc]);
|
|
2466
|
+
anchorT.push(plT[endSrc]);
|
|
2467
|
+
idx.push(base, base + 1, base + 2, base + 1, base + 3, base + 2);
|
|
2468
|
+
}
|
|
2469
|
+
const joinCount = pl.closed ? segs.length : segs.length - 1;
|
|
2470
|
+
for (let j = 0; j < joinCount; j++) {
|
|
2471
|
+
emitJoin(segs, segBaseIdx, j, join, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT, segSrcIdx, plA, plB, plT);
|
|
2472
|
+
}
|
|
2473
|
+
if (!pl.closed && cap !== "butt") {
|
|
2474
|
+
const first = segs[0];
|
|
2475
|
+
const firstBase = segBaseIdx[0];
|
|
2476
|
+
emitCap(first, firstBase + 0, firstBase + 1, false, first.halfA, cap, verts, idx, anchorA, anchorB, anchorT, plA[0], plB[0], plT[0]);
|
|
2477
|
+
const last = segs[segs.length - 1];
|
|
2478
|
+
const lastBase = segBaseIdx[segs.length - 1];
|
|
2479
|
+
const lastSrc = segSrcIdx[segs.length - 1] + 1;
|
|
2480
|
+
emitCap(last, lastBase + 2, lastBase + 3, true, last.halfB, cap, verts, idx, anchorA, anchorB, anchorT, plA[lastSrc], plB[lastSrc], plT[lastSrc]);
|
|
2481
|
+
}
|
|
2498
2482
|
}
|
|
2499
|
-
function
|
|
2500
|
-
const
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2483
|
+
function populatePolylineWidths(pl, vertexWidths, fallbackWidth) {
|
|
2484
|
+
const ptCount = pl.points.length / 2;
|
|
2485
|
+
if (ptCount === 0) return;
|
|
2486
|
+
const aA = pl.anchorA ?? new Uint32Array(ptCount);
|
|
2487
|
+
const aB = pl.anchorB ?? new Uint32Array(ptCount);
|
|
2488
|
+
const aT = pl.anchorT ?? new Float32Array(ptCount);
|
|
2489
|
+
const widths = new Float32Array(ptCount);
|
|
2490
|
+
const read = (i) => {
|
|
2491
|
+
const v = vertexWidths[i];
|
|
2492
|
+
return typeof v === "number" && isFinite(v) && v > 0 ? v : fallbackWidth;
|
|
2493
|
+
};
|
|
2494
|
+
for (let i = 0; i < ptCount; i++) {
|
|
2495
|
+
const a = aA[i], b = aB[i], t = aT[i];
|
|
2496
|
+
if (a === b) {
|
|
2497
|
+
widths[i] = read(a);
|
|
2498
|
+
} else {
|
|
2499
|
+
const wa = read(a);
|
|
2500
|
+
const wb = read(b);
|
|
2501
|
+
widths[i] = wa + (wb - wa) * t;
|
|
2502
|
+
}
|
|
2508
2503
|
}
|
|
2509
|
-
|
|
2510
|
-
const hit = entry.byVariant.get(key);
|
|
2511
|
-
if (hit !== void 0) return hit;
|
|
2512
|
-
const laid = layoutRuns(runs, opts);
|
|
2513
|
-
if (entry.byVariant.size >= LAYOUT_CACHE_VARIANT_LIMIT) entry.byVariant.clear();
|
|
2514
|
-
entry.byVariant.set(key, laid);
|
|
2515
|
-
return laid;
|
|
2504
|
+
pl.widths = widths;
|
|
2516
2505
|
}
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
const
|
|
2522
|
-
|
|
2506
|
+
var ROUND_CAP_STEP_RAD = 10 * Math.PI / 180;
|
|
2507
|
+
function emitCap(seg, leftIdx, rightIdx, atEnd, half, cap, verts, idx, anchorA, anchorB, anchorT, endA, endB, endT) {
|
|
2508
|
+
const sign = atEnd ? 1 : -1;
|
|
2509
|
+
const dx = (seg.bx - seg.ax) / seg.len * sign;
|
|
2510
|
+
const dy = (seg.by - seg.ay) / seg.len * sign;
|
|
2511
|
+
const cx = atEnd ? seg.bx : seg.ax;
|
|
2512
|
+
const cy = atEnd ? seg.by : seg.ay;
|
|
2513
|
+
const nx = seg.nxUnit * half;
|
|
2514
|
+
const ny = seg.nyUnit * half;
|
|
2515
|
+
if (cap === "square") {
|
|
2516
|
+
const ox = cx + dx * half;
|
|
2517
|
+
const oy = cy + dy * half;
|
|
2518
|
+
const lOut = verts.length / 2;
|
|
2519
|
+
verts.push(ox + nx, oy + ny);
|
|
2520
|
+
anchorA.push(endA);
|
|
2521
|
+
anchorB.push(endB);
|
|
2522
|
+
anchorT.push(endT);
|
|
2523
|
+
const rOut = verts.length / 2;
|
|
2524
|
+
verts.push(ox - nx, oy - ny);
|
|
2525
|
+
anchorA.push(endA);
|
|
2526
|
+
anchorB.push(endB);
|
|
2527
|
+
anchorT.push(endT);
|
|
2528
|
+
if (atEnd) {
|
|
2529
|
+
idx.push(leftIdx, lOut, rOut, leftIdx, rOut, rightIdx);
|
|
2530
|
+
} else {
|
|
2531
|
+
idx.push(leftIdx, rOut, lOut, leftIdx, rightIdx, rOut);
|
|
2532
|
+
}
|
|
2533
|
+
return;
|
|
2534
|
+
}
|
|
2535
|
+
if (cap === "round") {
|
|
2536
|
+
const pivotIdx = verts.length / 2;
|
|
2537
|
+
verts.push(cx, cy);
|
|
2538
|
+
anchorA.push(endA);
|
|
2539
|
+
anchorB.push(endB);
|
|
2540
|
+
anchorT.push(endT);
|
|
2541
|
+
const startAngle = Math.atan2(ny, nx);
|
|
2542
|
+
const sweep = atEnd ? -Math.PI : Math.PI;
|
|
2543
|
+
const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_CAP_STEP_RAD));
|
|
2544
|
+
const stepAngle = sweep / steps;
|
|
2545
|
+
let prevIdx = leftIdx;
|
|
2546
|
+
for (let i = 1; i < steps; i++) {
|
|
2547
|
+
const ang = startAngle + i * stepAngle;
|
|
2548
|
+
const fx = cx + Math.cos(ang) * half;
|
|
2549
|
+
const fy = cy + Math.sin(ang) * half;
|
|
2550
|
+
const newIdx = verts.length / 2;
|
|
2551
|
+
verts.push(fx, fy);
|
|
2552
|
+
anchorA.push(endA);
|
|
2553
|
+
anchorB.push(endB);
|
|
2554
|
+
anchorT.push(endT);
|
|
2555
|
+
if (atEnd) idx.push(prevIdx, newIdx, pivotIdx);
|
|
2556
|
+
else idx.push(prevIdx, pivotIdx, newIdx);
|
|
2557
|
+
prevIdx = newIdx;
|
|
2558
|
+
}
|
|
2559
|
+
if (atEnd) idx.push(prevIdx, rightIdx, pivotIdx);
|
|
2560
|
+
else idx.push(prevIdx, pivotIdx, rightIdx);
|
|
2561
|
+
}
|
|
2523
2562
|
}
|
|
2524
|
-
|
|
2525
|
-
// src/features/paths/pathFromD.ts
|
|
2526
|
-
var NUM_RE = /[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g;
|
|
2527
|
-
function tokenize(d) {
|
|
2563
|
+
function splitForDash(pl, dash) {
|
|
2528
2564
|
const out = [];
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2565
|
+
const plA = pl.anchorA ?? new Uint32Array(pl.points.length / 2);
|
|
2566
|
+
const plB = pl.anchorB ?? new Uint32Array(pl.points.length / 2);
|
|
2567
|
+
const plT = pl.anchorT ?? new Float32Array(pl.points.length / 2);
|
|
2568
|
+
let dashIdx = 0;
|
|
2569
|
+
let dashRemaining = dash[0];
|
|
2570
|
+
let onPhase = true;
|
|
2571
|
+
let curPts = onPhase ? [pl.points[0], pl.points[1]] : null;
|
|
2572
|
+
let curA = onPhase ? [plA[0]] : null;
|
|
2573
|
+
let curB = onPhase ? [plB[0]] : null;
|
|
2574
|
+
let curT = onPhase ? [plT[0]] : null;
|
|
2575
|
+
const flushAndAdvance = () => {
|
|
2576
|
+
if (curPts && curPts.length >= 4) {
|
|
2577
|
+
out.push({
|
|
2578
|
+
points: curPts,
|
|
2579
|
+
closed: false,
|
|
2580
|
+
anchorA: new Uint32Array(curA),
|
|
2581
|
+
anchorB: new Uint32Array(curB),
|
|
2582
|
+
anchorT: new Float32Array(curT)
|
|
2583
|
+
});
|
|
2584
|
+
}
|
|
2585
|
+
curPts = null;
|
|
2586
|
+
curA = null;
|
|
2587
|
+
curB = null;
|
|
2588
|
+
curT = null;
|
|
2589
|
+
dashIdx = (dashIdx + 1) % dash.length;
|
|
2590
|
+
dashRemaining = dash[dashIdx];
|
|
2591
|
+
onPhase = !onPhase;
|
|
2592
|
+
};
|
|
2593
|
+
let prevX = pl.points[0], prevY = pl.points[1];
|
|
2594
|
+
const ptCount = pl.points.length / 2;
|
|
2595
|
+
const segCount = pl.closed ? ptCount : ptCount - 1;
|
|
2596
|
+
for (let i = 0; i < segCount; i++) {
|
|
2597
|
+
const nextIdx = (i + 1) % ptCount;
|
|
2598
|
+
const cx = pl.points[nextIdx * 2], cy = pl.points[nextIdx * 2 + 1];
|
|
2599
|
+
const startA = plA[i], startB = plB[i], startT = plT[i];
|
|
2600
|
+
const endA = plA[nextIdx], endB = plB[nextIdx], endT = plT[nextIdx];
|
|
2601
|
+
const segFullDx = cx - prevX, segFullDy = cy - prevY;
|
|
2602
|
+
const segFullLen = Math.hypot(segFullDx, segFullDy);
|
|
2603
|
+
let segDx = segFullDx, segDy = segFullDy;
|
|
2604
|
+
let segLen = segFullLen;
|
|
2605
|
+
let traveled = 0;
|
|
2606
|
+
while (segLen > 1e-9) {
|
|
2607
|
+
if (segLen <= dashRemaining) {
|
|
2608
|
+
if (onPhase && curPts) {
|
|
2609
|
+
curPts.push(cx, cy);
|
|
2610
|
+
curA.push(endA);
|
|
2611
|
+
curB.push(endB);
|
|
2612
|
+
curT.push(endT);
|
|
2613
|
+
}
|
|
2614
|
+
dashRemaining -= segLen;
|
|
2615
|
+
prevX = cx;
|
|
2616
|
+
prevY = cy;
|
|
2617
|
+
traveled = segFullLen;
|
|
2618
|
+
segLen = 0;
|
|
2619
|
+
if (dashRemaining <= 1e-9) {
|
|
2620
|
+
flushAndAdvance();
|
|
2621
|
+
if (onPhase) {
|
|
2622
|
+
curPts = [prevX, prevY];
|
|
2623
|
+
curA = [endA];
|
|
2624
|
+
curB = [endB];
|
|
2625
|
+
curT = [endT];
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
} else {
|
|
2629
|
+
const tConsume = dashRemaining / segLen;
|
|
2630
|
+
const ix = prevX + segDx * tConsume;
|
|
2631
|
+
const iy = prevY + segDy * tConsume;
|
|
2632
|
+
traveled += dashRemaining;
|
|
2633
|
+
const frac = traveled / segFullLen;
|
|
2634
|
+
let mA, mB, mT;
|
|
2635
|
+
if (startA === endA && startB === endB) {
|
|
2636
|
+
mA = startA;
|
|
2637
|
+
mB = startB;
|
|
2638
|
+
mT = startT + (endT - startT) * frac;
|
|
2639
|
+
} else {
|
|
2640
|
+
if (frac < 0.5) {
|
|
2641
|
+
mA = startA;
|
|
2642
|
+
mB = startB;
|
|
2643
|
+
mT = startT;
|
|
2644
|
+
} else {
|
|
2645
|
+
mA = endA;
|
|
2646
|
+
mB = endB;
|
|
2647
|
+
mT = endT;
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
if (onPhase && curPts) {
|
|
2651
|
+
curPts.push(ix, iy);
|
|
2652
|
+
curA.push(mA);
|
|
2653
|
+
curB.push(mB);
|
|
2654
|
+
curT.push(mT);
|
|
2655
|
+
}
|
|
2656
|
+
prevX = ix;
|
|
2657
|
+
prevY = iy;
|
|
2658
|
+
segDx = cx - prevX;
|
|
2659
|
+
segDy = cy - prevY;
|
|
2660
|
+
segLen = Math.hypot(segDx, segDy);
|
|
2661
|
+
flushAndAdvance();
|
|
2662
|
+
if (onPhase) {
|
|
2663
|
+
curPts = [prevX, prevY];
|
|
2664
|
+
curA = [mA];
|
|
2665
|
+
curB = [mB];
|
|
2666
|
+
curT = [mT];
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2540
2669
|
}
|
|
2541
2670
|
}
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
if (Number.isFinite(n)) out.push(n);
|
|
2671
|
+
if (curPts && curPts.length >= 4) {
|
|
2672
|
+
out.push({
|
|
2673
|
+
points: curPts,
|
|
2674
|
+
closed: false,
|
|
2675
|
+
anchorA: new Uint32Array(curA),
|
|
2676
|
+
anchorB: new Uint32Array(curB),
|
|
2677
|
+
anchorT: new Float32Array(curT)
|
|
2678
|
+
});
|
|
2551
2679
|
}
|
|
2552
2680
|
return out;
|
|
2553
2681
|
}
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
const b = new PathBuilder();
|
|
2569
|
-
const st = {
|
|
2570
|
-
x: 0,
|
|
2571
|
-
y: 0,
|
|
2572
|
-
startX: 0,
|
|
2573
|
-
startY: 0,
|
|
2574
|
-
lastCubicCtrl: null,
|
|
2575
|
-
lastQuadCtrl: null
|
|
2682
|
+
function makeSeg(ax, ay, bx, by, halfA, halfB) {
|
|
2683
|
+
const dx = bx - ax, dy = by - ay;
|
|
2684
|
+
const len = Math.hypot(dx, dy);
|
|
2685
|
+
if (len === 0) return null;
|
|
2686
|
+
return {
|
|
2687
|
+
ax,
|
|
2688
|
+
ay,
|
|
2689
|
+
bx,
|
|
2690
|
+
by,
|
|
2691
|
+
nxUnit: -dy / len,
|
|
2692
|
+
nyUnit: dx / len,
|
|
2693
|
+
halfA,
|
|
2694
|
+
halfB,
|
|
2695
|
+
len
|
|
2576
2696
|
};
|
|
2577
|
-
for (const { cmd, args } of tokens) {
|
|
2578
|
-
const upper = cmd.toUpperCase();
|
|
2579
|
-
const relative = cmd !== upper;
|
|
2580
|
-
const argCount = ARG_COUNTS[upper];
|
|
2581
|
-
if (argCount === void 0) {
|
|
2582
|
-
onWarn?.(`unknown path command: ${cmd}`);
|
|
2583
|
-
continue;
|
|
2584
|
-
}
|
|
2585
|
-
if (upper === "Z") {
|
|
2586
|
-
b.close();
|
|
2587
|
-
st.x = st.startX;
|
|
2588
|
-
st.y = st.startY;
|
|
2589
|
-
st.lastCubicCtrl = null;
|
|
2590
|
-
st.lastQuadCtrl = null;
|
|
2591
|
-
continue;
|
|
2592
|
-
}
|
|
2593
|
-
const groups = argCount === 0 ? 1 : Math.floor(args.length / argCount);
|
|
2594
|
-
for (let g = 0; g < groups; g++) {
|
|
2595
|
-
const a = args.slice(g * argCount, (g + 1) * argCount);
|
|
2596
|
-
const effectiveUpper = upper === "M" && g > 0 ? "L" : upper;
|
|
2597
|
-
runCommand(effectiveUpper, relative, a, st, b);
|
|
2598
|
-
}
|
|
2599
|
-
}
|
|
2600
|
-
return b.build();
|
|
2601
2697
|
}
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
}
|
|
2636
|
-
case "V": {
|
|
2637
|
-
const y = a[0] + (relative ? st.y : 0);
|
|
2638
|
-
b.lineTo(st.x, y);
|
|
2639
|
-
st.y = y;
|
|
2640
|
-
st.lastCubicCtrl = null;
|
|
2641
|
-
st.lastQuadCtrl = null;
|
|
2642
|
-
return;
|
|
2643
|
-
}
|
|
2644
|
-
case "C": {
|
|
2645
|
-
const x1 = a[0] + rx, y1 = a[1] + ry;
|
|
2646
|
-
const x2 = a[2] + rx, y2 = a[3] + ry;
|
|
2647
|
-
const x = a[4] + rx, y = a[5] + ry;
|
|
2648
|
-
b.curveTo(x1, y1, x2, y2, x, y);
|
|
2649
|
-
st.x = x;
|
|
2650
|
-
st.y = y;
|
|
2651
|
-
st.lastCubicCtrl = { x: x2, y: y2 };
|
|
2652
|
-
st.lastQuadCtrl = null;
|
|
2653
|
-
return;
|
|
2654
|
-
}
|
|
2655
|
-
case "S": {
|
|
2656
|
-
const ref = st.lastCubicCtrl ?? { x: st.x, y: st.y };
|
|
2657
|
-
const x1 = 2 * st.x - ref.x;
|
|
2658
|
-
const y1 = 2 * st.y - ref.y;
|
|
2659
|
-
const x2 = a[0] + rx, y2 = a[1] + ry;
|
|
2660
|
-
const x = a[2] + rx, y = a[3] + ry;
|
|
2661
|
-
b.curveTo(x1, y1, x2, y2, x, y);
|
|
2662
|
-
st.x = x;
|
|
2663
|
-
st.y = y;
|
|
2664
|
-
st.lastCubicCtrl = { x: x2, y: y2 };
|
|
2665
|
-
st.lastQuadCtrl = null;
|
|
2666
|
-
return;
|
|
2667
|
-
}
|
|
2668
|
-
case "Q": {
|
|
2669
|
-
const x1 = a[0] + rx, y1 = a[1] + ry;
|
|
2670
|
-
const x = a[2] + rx, y = a[3] + ry;
|
|
2671
|
-
b.quadTo(x1, y1, x, y);
|
|
2672
|
-
st.x = x;
|
|
2673
|
-
st.y = y;
|
|
2674
|
-
st.lastQuadCtrl = { x: x1, y: y1 };
|
|
2675
|
-
st.lastCubicCtrl = null;
|
|
2676
|
-
return;
|
|
2677
|
-
}
|
|
2678
|
-
case "T": {
|
|
2679
|
-
const ref = st.lastQuadCtrl ?? { x: st.x, y: st.y };
|
|
2680
|
-
const x1 = 2 * st.x - ref.x;
|
|
2681
|
-
const y1 = 2 * st.y - ref.y;
|
|
2682
|
-
const x = a[0] + rx, y = a[1] + ry;
|
|
2683
|
-
b.quadTo(x1, y1, x, y);
|
|
2684
|
-
st.x = x;
|
|
2685
|
-
st.y = y;
|
|
2686
|
-
st.lastQuadCtrl = { x: x1, y: y1 };
|
|
2687
|
-
st.lastCubicCtrl = null;
|
|
2698
|
+
var DEFAULT_MITER_LIMIT = 10;
|
|
2699
|
+
var DEFAULT_VARYING_WIDTH_JOIN_THRESHOLD = 1.5;
|
|
2700
|
+
function emitJoin(segs, segBaseIdx, j, join, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT, segSrcIdx, plA, plB, plT) {
|
|
2701
|
+
const a = segs[j];
|
|
2702
|
+
const b = segs[(j + 1) % segs.length];
|
|
2703
|
+
const aBase = segBaseIdx[j];
|
|
2704
|
+
const bBase = segBaseIdx[(j + 1) % segs.length];
|
|
2705
|
+
const adx = a.bx - a.ax, ady = a.by - a.ay;
|
|
2706
|
+
const bdx = b.bx - b.ax, bdy = b.by - b.ay;
|
|
2707
|
+
const cross = adx * bdy - ady * bdx;
|
|
2708
|
+
if (cross === 0) return;
|
|
2709
|
+
const onPositive = cross > 0;
|
|
2710
|
+
const aOuterEnd = onPositive ? aBase + 3 : aBase + 2;
|
|
2711
|
+
const bOuterStart = onPositive ? bBase + 1 : bBase + 0;
|
|
2712
|
+
const nextSeg = (j + 1) % segs.length;
|
|
2713
|
+
const cornerSrc = segSrcIdx[nextSeg];
|
|
2714
|
+
const cornerA = plA[cornerSrc];
|
|
2715
|
+
const cornerB = plB[cornerSrc];
|
|
2716
|
+
const cornerT = plT[cornerSrc];
|
|
2717
|
+
const halfAtCorner = a.halfB;
|
|
2718
|
+
const taperA = Math.max(a.halfA, a.halfB) / Math.max(1e-9, Math.min(a.halfA, a.halfB));
|
|
2719
|
+
const taperB = Math.max(b.halfA, b.halfB) / Math.max(1e-9, Math.min(b.halfA, b.halfB));
|
|
2720
|
+
const forceBevelForVarying = taperA > varyingThreshold || taperB > varyingThreshold;
|
|
2721
|
+
if (join === "bevel" || forceBevelForVarying) {
|
|
2722
|
+
emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);
|
|
2723
|
+
return;
|
|
2724
|
+
}
|
|
2725
|
+
if (join === "miter") {
|
|
2726
|
+
const aOX = verts[aOuterEnd * 2], aOY = verts[aOuterEnd * 2 + 1];
|
|
2727
|
+
const bOX = verts[bOuterStart * 2], bOY = verts[bOuterStart * 2 + 1];
|
|
2728
|
+
const apex = lineLineIntersect(aOX, aOY, adx, ady, bOX, bOY, -bdx, -bdy);
|
|
2729
|
+
if (!apex) {
|
|
2730
|
+
emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);
|
|
2688
2731
|
return;
|
|
2689
2732
|
}
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
const xRot = a[2];
|
|
2694
|
-
const largeArc = a[3] !== 0;
|
|
2695
|
-
const sweep = a[4] !== 0;
|
|
2696
|
-
const ex = a[5] + rx;
|
|
2697
|
-
const ey = a[6] + ry;
|
|
2698
|
-
arcToCubics(st.x, st.y, ex, ey, rxA, ryA, xRot, largeArc, sweep, b);
|
|
2699
|
-
st.x = ex;
|
|
2700
|
-
st.y = ey;
|
|
2701
|
-
st.lastCubicCtrl = null;
|
|
2702
|
-
st.lastQuadCtrl = null;
|
|
2733
|
+
const miterLen = Math.hypot(apex[0] - a.bx, apex[1] - a.by);
|
|
2734
|
+
if (miterLen > miterLimit * halfAtCorner) {
|
|
2735
|
+
emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);
|
|
2703
2736
|
return;
|
|
2704
2737
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
let rys = ry * ry;
|
|
2724
|
-
const x1ps = x1p * x1p;
|
|
2725
|
-
const y1ps = y1p * y1p;
|
|
2726
|
-
const lambda = x1ps / rxs + y1ps / rys;
|
|
2727
|
-
let rxFixed = rx;
|
|
2728
|
-
let ryFixed = ry;
|
|
2729
|
-
if (lambda > 1) {
|
|
2730
|
-
const sqrtLambda = Math.sqrt(lambda);
|
|
2731
|
-
rxFixed = sqrtLambda * rx;
|
|
2732
|
-
ryFixed = sqrtLambda * ry;
|
|
2733
|
-
rxs = rxFixed * rxFixed;
|
|
2734
|
-
rys = ryFixed * ryFixed;
|
|
2738
|
+
const apexIdx = verts.length / 2;
|
|
2739
|
+
verts.push(apex[0], apex[1]);
|
|
2740
|
+
anchorA.push(cornerA);
|
|
2741
|
+
anchorB.push(cornerB);
|
|
2742
|
+
anchorT.push(cornerT);
|
|
2743
|
+
const jIdx = verts.length / 2;
|
|
2744
|
+
verts.push(a.bx, a.by);
|
|
2745
|
+
anchorA.push(cornerA);
|
|
2746
|
+
anchorB.push(cornerB);
|
|
2747
|
+
anchorT.push(cornerT);
|
|
2748
|
+
if (onPositive) {
|
|
2749
|
+
idx.push(aOuterEnd, apexIdx, bOuterStart);
|
|
2750
|
+
idx.push(aOuterEnd, bOuterStart, jIdx);
|
|
2751
|
+
} else {
|
|
2752
|
+
idx.push(aOuterEnd, bOuterStart, apexIdx);
|
|
2753
|
+
idx.push(aOuterEnd, jIdx, bOuterStart);
|
|
2754
|
+
}
|
|
2755
|
+
return;
|
|
2735
2756
|
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
const factor = sign * Math.sqrt(Math.max(0, num / den));
|
|
2740
|
-
const cxp = factor * (rxFixed * y1p) / ryFixed;
|
|
2741
|
-
const cyp = factor * -(ryFixed * x1p) / rxFixed;
|
|
2742
|
-
const cx = cosPhi * cxp - sinPhi * cyp + (x1 + x2) / 2;
|
|
2743
|
-
const cy = sinPhi * cxp + cosPhi * cyp + (y1 + y2) / 2;
|
|
2744
|
-
const angle = (ux, uy, vx, vy) => {
|
|
2745
|
-
const dot = ux * vx + uy * vy;
|
|
2746
|
-
const len = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
|
|
2747
|
-
let a = Math.acos(Math.max(-1, Math.min(1, dot / len)));
|
|
2748
|
-
if (ux * vy - uy * vx < 0) a = -a;
|
|
2749
|
-
return a;
|
|
2750
|
-
};
|
|
2751
|
-
const theta1 = angle(1, 0, (x1p - cxp) / rxFixed, (y1p - cyp) / ryFixed);
|
|
2752
|
-
let dTheta = angle(
|
|
2753
|
-
(x1p - cxp) / rxFixed,
|
|
2754
|
-
(y1p - cyp) / ryFixed,
|
|
2755
|
-
(-x1p - cxp) / rxFixed,
|
|
2756
|
-
(-y1p - cyp) / ryFixed
|
|
2757
|
-
);
|
|
2758
|
-
if (!sweep && dTheta > 0) dTheta -= 2 * Math.PI;
|
|
2759
|
-
else if (sweep && dTheta < 0) dTheta += 2 * Math.PI;
|
|
2760
|
-
const segCount = Math.max(1, Math.ceil(Math.abs(dTheta) / (Math.PI / 2)));
|
|
2761
|
-
const segAngle = dTheta / segCount;
|
|
2762
|
-
const t = 4 / 3 * Math.tan(segAngle / 4);
|
|
2763
|
-
let prevX = x1;
|
|
2764
|
-
let prevY = y1;
|
|
2765
|
-
let prevDx = -Math.sin(theta1) * rxFixed;
|
|
2766
|
-
let prevDy = Math.cos(theta1) * ryFixed;
|
|
2767
|
-
for (let i = 1; i <= segCount; i++) {
|
|
2768
|
-
const theta = theta1 + i * segAngle;
|
|
2769
|
-
const cosT = Math.cos(theta);
|
|
2770
|
-
const sinT = Math.sin(theta);
|
|
2771
|
-
const px = cosPhi * (cosT * rxFixed) - sinPhi * (sinT * ryFixed) + cx;
|
|
2772
|
-
const py = sinPhi * (cosT * rxFixed) + cosPhi * (sinT * ryFixed) + cy;
|
|
2773
|
-
const dxNew = -sinT * rxFixed;
|
|
2774
|
-
const dyNew = cosT * ryFixed;
|
|
2775
|
-
const c1x = prevX + cosPhi * (t * prevDx) - sinPhi * (t * prevDy);
|
|
2776
|
-
const c1y = prevY + sinPhi * (t * prevDx) + cosPhi * (t * prevDy);
|
|
2777
|
-
const c2x = px - cosPhi * (t * dxNew) + sinPhi * (t * dyNew);
|
|
2778
|
-
const c2y = py - sinPhi * (t * dxNew) - cosPhi * (t * dyNew);
|
|
2779
|
-
b.curveTo(c1x, c1y, c2x, c2y, px, py);
|
|
2780
|
-
prevX = px;
|
|
2781
|
-
prevY = py;
|
|
2782
|
-
prevDx = dxNew;
|
|
2783
|
-
prevDy = dyNew;
|
|
2757
|
+
if (join === "round") {
|
|
2758
|
+
emitRoundJoin(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);
|
|
2759
|
+
return;
|
|
2784
2760
|
}
|
|
2785
2761
|
}
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
const
|
|
2796
|
-
|
|
2797
|
-
|
|
2762
|
+
var ROUND_STEP_RAD = 10 * Math.PI / 180;
|
|
2763
|
+
function emitRoundJoin(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT) {
|
|
2764
|
+
const cx = a.bx, cy = a.by;
|
|
2765
|
+
const pivotIdx = verts.length / 2;
|
|
2766
|
+
verts.push(cx, cy);
|
|
2767
|
+
anchorA.push(cornerA);
|
|
2768
|
+
anchorB.push(cornerB);
|
|
2769
|
+
anchorT.push(cornerT);
|
|
2770
|
+
const startX = verts[aOuterEnd * 2] - cx;
|
|
2771
|
+
const startY = verts[aOuterEnd * 2 + 1] - cy;
|
|
2772
|
+
const endX = verts[bOuterStart * 2] - cx;
|
|
2773
|
+
const endY = verts[bOuterStart * 2 + 1] - cy;
|
|
2774
|
+
const r = Math.hypot(startX, startY);
|
|
2775
|
+
const startAngle = Math.atan2(startY, startX);
|
|
2776
|
+
const endAngle = Math.atan2(endY, endX);
|
|
2777
|
+
let sweep = endAngle - startAngle;
|
|
2778
|
+
if (onPositive && sweep < 0) sweep += 2 * Math.PI;
|
|
2779
|
+
else if (!onPositive && sweep > 0) sweep -= 2 * Math.PI;
|
|
2780
|
+
const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_STEP_RAD));
|
|
2781
|
+
const stepAngle = sweep / steps;
|
|
2782
|
+
let prevIdx = aOuterEnd;
|
|
2783
|
+
for (let i = 1; i < steps; i++) {
|
|
2784
|
+
const ang = startAngle + i * stepAngle;
|
|
2785
|
+
const fx = cx + Math.cos(ang) * r;
|
|
2786
|
+
const fy = cy + Math.sin(ang) * r;
|
|
2787
|
+
const newIdx = verts.length / 2;
|
|
2788
|
+
verts.push(fx, fy);
|
|
2789
|
+
anchorA.push(cornerA);
|
|
2790
|
+
anchorB.push(cornerB);
|
|
2791
|
+
anchorT.push(cornerT);
|
|
2792
|
+
if (onPositive) idx.push(prevIdx, pivotIdx, newIdx);
|
|
2793
|
+
else idx.push(prevIdx, newIdx, pivotIdx);
|
|
2794
|
+
prevIdx = newIdx;
|
|
2795
|
+
}
|
|
2796
|
+
if (onPositive) idx.push(prevIdx, pivotIdx, bOuterStart);
|
|
2797
|
+
else idx.push(prevIdx, bOuterStart, pivotIdx);
|
|
2798
|
+
}
|
|
2799
|
+
function emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT) {
|
|
2800
|
+
const jIdx = verts.length / 2;
|
|
2801
|
+
verts.push(a.bx, a.by);
|
|
2802
|
+
anchorA.push(cornerA);
|
|
2803
|
+
anchorB.push(cornerB);
|
|
2804
|
+
anchorT.push(cornerT);
|
|
2805
|
+
if (onPositive) idx.push(aOuterEnd, jIdx, bOuterStart);
|
|
2806
|
+
else idx.push(aOuterEnd, bOuterStart, jIdx);
|
|
2807
|
+
}
|
|
2808
|
+
function lineLineIntersect(apx, apy, adx, ady, bpx, bpy, bdx, bdy) {
|
|
2809
|
+
const denom = adx * bdy - ady * bdx;
|
|
2810
|
+
if (Math.abs(denom) < 1e-9) return null;
|
|
2811
|
+
const t = ((bpx - apx) * bdy - (bpy - apy) * bdx) / denom;
|
|
2812
|
+
return [apx + t * adx, apy + t * ady];
|
|
2798
2813
|
}
|
|
2799
2814
|
|
|
2800
2815
|
// src/renderer/cache/outlineStrokeMeshCache.ts
|
|
@@ -2827,6 +2842,38 @@ function outlineStrokeMesh(glyphKey, d, emWidth, stroke) {
|
|
|
2827
2842
|
return mesh.indices.length === 0 ? null : mesh;
|
|
2828
2843
|
}
|
|
2829
2844
|
|
|
2845
|
+
// src/renderer/cache/strokeMeshCache.ts
|
|
2846
|
+
var STROKE_CONFIGS_PER_PATH = 8;
|
|
2847
|
+
var cache5 = /* @__PURE__ */ new WeakMap();
|
|
2848
|
+
function configKey(stroke, flattenTolerance) {
|
|
2849
|
+
return [
|
|
2850
|
+
stroke.width ?? 1,
|
|
2851
|
+
stroke.cap ?? "butt",
|
|
2852
|
+
stroke.join ?? "miter",
|
|
2853
|
+
stroke.miterLimit ?? "",
|
|
2854
|
+
stroke.align ?? "center",
|
|
2855
|
+
(stroke.dash ?? []).join(","),
|
|
2856
|
+
stroke.varyingWidthJoinThreshold ?? "",
|
|
2857
|
+
flattenTolerance ?? ""
|
|
2858
|
+
].join("|");
|
|
2859
|
+
}
|
|
2860
|
+
function strokeMesh(path, stroke, flattenTolerance) {
|
|
2861
|
+
let byConfig = cache5.get(path);
|
|
2862
|
+
if (byConfig === void 0) {
|
|
2863
|
+
byConfig = /* @__PURE__ */ new Map();
|
|
2864
|
+
cache5.set(path, byConfig);
|
|
2865
|
+
}
|
|
2866
|
+
const key = configKey(stroke, flattenTolerance);
|
|
2867
|
+
const entry = byConfig.get(key);
|
|
2868
|
+
if (entry !== void 0 && entry.vertexWidths === stroke.vertexWidths) {
|
|
2869
|
+
return entry.mesh;
|
|
2870
|
+
}
|
|
2871
|
+
const mesh = tessellateStroke(path, stroke, { flattenTolerance });
|
|
2872
|
+
if (entry === void 0 && byConfig.size >= STROKE_CONFIGS_PER_PATH) byConfig.clear();
|
|
2873
|
+
byConfig.set(key, { mesh, vertexWidths: stroke.vertexWidths });
|
|
2874
|
+
return mesh;
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2830
2877
|
// src/renderer/solidBatch.ts
|
|
2831
2878
|
var MAX_VERTICES_PER_BATCH = 32768;
|
|
2832
2879
|
var FLOATS_PER_VERTEX = 6;
|
|
@@ -3231,44 +3278,40 @@ function drawGroup(ctx, cmd) {
|
|
|
3231
3278
|
"weasel: clip nesting depth exceeded (max 7). You can't nest more than 7 levels of clipped containers in a single draw tree. Flatten the hierarchy or compose poses outside the scene graph."
|
|
3232
3279
|
);
|
|
3233
3280
|
}
|
|
3234
|
-
flushSolids(ctx);
|
|
3235
3281
|
pushClip(ctx, cmd.clip, newDepth);
|
|
3236
3282
|
ctx.clipDepth = newDepth;
|
|
3237
3283
|
}
|
|
3238
3284
|
for (const child of cmd.children) dispatch(ctx, child);
|
|
3239
3285
|
if (cmd.clip) {
|
|
3240
|
-
flushSolids(ctx);
|
|
3241
3286
|
popClip(ctx, cmd.clip, ctx.clipDepth - 1);
|
|
3242
3287
|
ctx.clipDepth -= 1;
|
|
3243
3288
|
}
|
|
3244
3289
|
ctx.state.pop();
|
|
3245
3290
|
}
|
|
3246
3291
|
function drawPath(ctx, cmd) {
|
|
3247
|
-
if (
|
|
3248
|
-
if (cmd.fill) {
|
|
3249
|
-
const batchablePaint = (cmd.fill.fill === void 0 || cmd.fill.fill === "solid") && (!cmd.vertexColors || cmd.vertexColors.length === 0);
|
|
3250
|
-
const solid = cmd.fill;
|
|
3251
|
-
if (batchablePaint && cmd.path.kind === "rect") {
|
|
3252
|
-
pushRect(ctx, cmd.path, solid);
|
|
3253
|
-
} else {
|
|
3254
|
-
const mesh = fillMesh(ctx, cmd.path);
|
|
3255
|
-
if (batchablePaint && canBatchMesh(mesh)) {
|
|
3256
|
-
pushMesh(ctx, mesh, solid);
|
|
3257
|
-
} else {
|
|
3258
|
-
flushSolids(ctx);
|
|
3259
|
-
const handle = meshHandle(ctx, mesh);
|
|
3260
|
-
if (cmd.vertexColors && cmd.vertexColors.length > 0 && (cmd.fill.fill === void 0 || cmd.fill.fill === "solid")) {
|
|
3261
|
-
drawPathFillVColor(ctx, cmd, solid, handle);
|
|
3262
|
-
} else if (handle.requiresStencil) {
|
|
3263
|
-
drawPathFillStencil(ctx, cmd.fill, handle);
|
|
3264
|
-
} else {
|
|
3265
|
-
drawPathFillByKind(ctx, cmd.fill, handle);
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
}
|
|
3269
|
-
}
|
|
3292
|
+
if (cmd.fill) drawPathFill(ctx, cmd);
|
|
3270
3293
|
if (cmd.stroke) drawPathStroke(ctx, cmd);
|
|
3271
3294
|
}
|
|
3295
|
+
function drawPathFill(ctx, cmd) {
|
|
3296
|
+
const fill = cmd.fill;
|
|
3297
|
+
const isSolid = fill.fill === void 0 || fill.fill === "solid";
|
|
3298
|
+
const hasVColors = !!(cmd.vertexColors && cmd.vertexColors.length > 0);
|
|
3299
|
+
const solid = fill;
|
|
3300
|
+
if (isSolid && !hasVColors && cmd.path.kind === "rect") {
|
|
3301
|
+
pushRect(ctx, cmd.path, solid);
|
|
3302
|
+
return;
|
|
3303
|
+
}
|
|
3304
|
+
const mesh = fillMesh(ctx, cmd.path);
|
|
3305
|
+
if (tryStageSolid(ctx, mesh, isSolid && !hasVColors ? solid : void 0)) return;
|
|
3306
|
+
const handle = meshHandle(ctx, mesh);
|
|
3307
|
+
if (isSolid && hasVColors) {
|
|
3308
|
+
drawPathFillVColor(ctx, cmd, solid, handle);
|
|
3309
|
+
} else if (handle.requiresStencil) {
|
|
3310
|
+
drawPathFillStencil(ctx, fill, handle);
|
|
3311
|
+
} else {
|
|
3312
|
+
drawPathFillByKind(ctx, fill, handle);
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3272
3315
|
function isIdentityColorMatrix(cm) {
|
|
3273
3316
|
return cm === IDENTITY_COLOR_MATRIX || sameValues(IDENTITY_COLOR_MATRIX, cm);
|
|
3274
3317
|
}
|
|
@@ -3321,6 +3364,14 @@ function pushMesh(ctx, mesh, paint) {
|
|
|
3321
3364
|
const [r, g, b, a] = stagedColor(ctx, staged, paint);
|
|
3322
3365
|
ctx.solidBatch.pushMesh(mesh, ctx.state.transform, r, g, b, a);
|
|
3323
3366
|
}
|
|
3367
|
+
function tryStageSolid(ctx, mesh, paint) {
|
|
3368
|
+
if (paint !== void 0 && canBatchMesh(mesh)) {
|
|
3369
|
+
pushMesh(ctx, mesh, paint);
|
|
3370
|
+
return true;
|
|
3371
|
+
}
|
|
3372
|
+
flushSolids(ctx);
|
|
3373
|
+
return false;
|
|
3374
|
+
}
|
|
3324
3375
|
function flushSolids(ctx) {
|
|
3325
3376
|
const batch = ctx.solidBatch;
|
|
3326
3377
|
const staged = ctx.solidState;
|
|
@@ -3524,6 +3575,7 @@ function rasterizePathToStencil(ctx, path) {
|
|
|
3524
3575
|
gl.bindVertexArray(null);
|
|
3525
3576
|
}
|
|
3526
3577
|
function pushClip(ctx, path, newDepth) {
|
|
3578
|
+
flushSolids(ctx);
|
|
3527
3579
|
const gl = ctx.gl;
|
|
3528
3580
|
const ancestors = ancestorMask(newDepth - 1);
|
|
3529
3581
|
const newBit = 1 << newDepth;
|
|
@@ -3538,6 +3590,7 @@ function pushClip(ctx, path, newDepth) {
|
|
|
3538
3590
|
gl.stencilMask(255);
|
|
3539
3591
|
}
|
|
3540
3592
|
function popClip(ctx, path, oldDepth) {
|
|
3593
|
+
flushSolids(ctx);
|
|
3541
3594
|
const gl = ctx.gl;
|
|
3542
3595
|
gl.enable(gl.STENCIL_TEST);
|
|
3543
3596
|
const oldBit = 1 << oldDepth + 1;
|
|
@@ -3594,17 +3647,13 @@ function drawPathStroke(ctx, cmd) {
|
|
|
3594
3647
|
function drawPathStrokeUnclipped(ctx, cmd) {
|
|
3595
3648
|
const stroke = cmd.stroke;
|
|
3596
3649
|
const solid = stroke.paint;
|
|
3597
|
-
const mesh =
|
|
3650
|
+
const mesh = strokeMesh(cmd.path, stroke, ctx.flattenTolerance);
|
|
3598
3651
|
if (mesh.indices.length === 0) return;
|
|
3599
3652
|
const hasVColors = !!(stroke.vertexColors && stroke.vertexColors.length > 0);
|
|
3600
|
-
if (
|
|
3601
|
-
|
|
3602
|
-
return;
|
|
3603
|
-
}
|
|
3604
|
-
flushSolids(ctx);
|
|
3605
|
-
const handle = ctx.meshCache.uploadTransient(mesh);
|
|
3653
|
+
if (tryStageSolid(ctx, mesh, hasVColors ? void 0 : solid)) return;
|
|
3654
|
+
const handle = hasVColors ? ctx.meshCache.uploadTransient(mesh) : ctx.meshCache.uploadRecurring(mesh);
|
|
3606
3655
|
const gl = ctx.gl;
|
|
3607
|
-
if (
|
|
3656
|
+
if (hasVColors) {
|
|
3608
3657
|
const prog = ctx.pathFillVColor;
|
|
3609
3658
|
gl.useProgram(prog.handle);
|
|
3610
3659
|
gl.bindVertexArray(handle.vao);
|
|
@@ -3635,16 +3684,30 @@ function drawPathStrokeUnclipped(ctx, cmd) {
|
|
|
3635
3684
|
gl.drawElements(gl.TRIANGLES, handle.indexCount, gl.UNSIGNED_INT, 0);
|
|
3636
3685
|
gl.bindVertexArray(null);
|
|
3637
3686
|
}
|
|
3687
|
+
var DOUBLED_VERTEX_WIDTHS = /* @__PURE__ */ new WeakMap();
|
|
3688
|
+
function doubledVertexWidths(widths) {
|
|
3689
|
+
let doubled = DOUBLED_VERTEX_WIDTHS.get(widths);
|
|
3690
|
+
if (doubled === void 0) {
|
|
3691
|
+
doubled = widths.map((w) => w * 2);
|
|
3692
|
+
DOUBLED_VERTEX_WIDTHS.set(widths, doubled);
|
|
3693
|
+
}
|
|
3694
|
+
return doubled;
|
|
3695
|
+
}
|
|
3638
3696
|
function drawPathStrokeStenciled(ctx, cmd, align) {
|
|
3639
3697
|
const stroke = cmd.stroke;
|
|
3640
3698
|
const solid = stroke.paint;
|
|
3641
|
-
const widerStroke = {
|
|
3699
|
+
const widerStroke = {
|
|
3700
|
+
...stroke,
|
|
3701
|
+
width: (stroke.width ?? 1) * 2,
|
|
3702
|
+
...stroke.vertexWidths ? { vertexWidths: doubledVertexWidths(stroke.vertexWidths) } : {},
|
|
3703
|
+
align: "center"
|
|
3704
|
+
};
|
|
3705
|
+
const useVColor = !!(stroke.vertexColors && stroke.vertexColors.length > 0);
|
|
3642
3706
|
const fillHandle = fillMeshHandle(ctx, cmd.path);
|
|
3643
|
-
const ribbonMesh =
|
|
3707
|
+
const ribbonMesh = strokeMesh(cmd.path, widerStroke, ctx.flattenTolerance);
|
|
3644
3708
|
if (ribbonMesh.indices.length === 0) return;
|
|
3645
|
-
const ribbonHandle = ctx.meshCache.uploadTransient(ribbonMesh);
|
|
3709
|
+
const ribbonHandle = useVColor ? ctx.meshCache.uploadTransient(ribbonMesh) : ctx.meshCache.uploadRecurring(ribbonMesh);
|
|
3646
3710
|
const gl = ctx.gl;
|
|
3647
|
-
const useVColor = !!(stroke.vertexColors && stroke.vertexColors.length > 0);
|
|
3648
3711
|
const prog = useVColor ? ctx.pathFillVColor : ctx.pathFill;
|
|
3649
3712
|
gl.useProgram(prog.handle);
|
|
3650
3713
|
setProjAndModel(ctx, prog);
|
|
@@ -3680,11 +3743,11 @@ function drawPathStrokeStenciled(ctx, cmd, align) {
|
|
|
3680
3743
|
}
|
|
3681
3744
|
}
|
|
3682
3745
|
gl.drawElements(gl.TRIANGLES, ribbonHandle.indexCount, gl.UNSIGNED_INT, 0);
|
|
3683
|
-
if (colorVbo) gl.deleteBuffer(colorVbo);
|
|
3684
3746
|
gl.stencilMask(1);
|
|
3685
3747
|
gl.clear(gl.STENCIL_BUFFER_BIT);
|
|
3686
3748
|
gl.disable(gl.STENCIL_TEST);
|
|
3687
3749
|
gl.bindVertexArray(null);
|
|
3750
|
+
if (colorVbo) gl.deleteBuffer(colorVbo);
|
|
3688
3751
|
}
|
|
3689
3752
|
var OUTLINE_MIN_SCREEN_PX = 48;
|
|
3690
3753
|
function modelScale(m) {
|
|
@@ -3733,9 +3796,9 @@ function drawTextOutlineGroup(ctx, group, dx, dy) {
|
|
|
3733
3796
|
const mesh = outlineGroupMesh(group, dx, dy);
|
|
3734
3797
|
if (mesh) drawPathFillByKind(ctx, group.fill, ctx.meshCache.uploadTransient(mesh));
|
|
3735
3798
|
if (!group.stroke) return;
|
|
3736
|
-
const
|
|
3737
|
-
if (
|
|
3738
|
-
drawPathFillByKind(ctx, group.stroke.paint, ctx.meshCache.uploadTransient(
|
|
3799
|
+
const ribbon = outlineGroupStrokeMesh(group, dx, dy);
|
|
3800
|
+
if (ribbon) {
|
|
3801
|
+
drawPathFillByKind(ctx, group.stroke.paint, ctx.meshCache.uploadTransient(ribbon));
|
|
3739
3802
|
}
|
|
3740
3803
|
}
|
|
3741
3804
|
function outlineGroupMesh(group, dx, dy) {
|
|
@@ -4075,16 +4138,28 @@ function registerProgram(id, vert, frag) {
|
|
|
4075
4138
|
}
|
|
4076
4139
|
|
|
4077
4140
|
// src/renderer/WeaselRenderer.ts
|
|
4141
|
+
var UNIFORM_QUALIFIER = /^(?:lowp|mediump|highp|precise|invariant|centroid|flat|smooth|noperspective)$/;
|
|
4078
4142
|
function extractUniformNames(glsl) {
|
|
4079
|
-
const
|
|
4080
|
-
const reArray = /\buniform\s+\S+\s+(\w+)\s*\[\s*(\d+)\s*\]\s*;/g;
|
|
4143
|
+
const re = /\buniform\s+([^;{]+);/g;
|
|
4081
4144
|
const names = [];
|
|
4082
4145
|
let m;
|
|
4083
|
-
while ((m =
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4146
|
+
while ((m = re.exec(glsl)) !== null) {
|
|
4147
|
+
const words = m[1].trim().split(/\s+/);
|
|
4148
|
+
let i = 0;
|
|
4149
|
+
while (i < words.length && UNIFORM_QUALIFIER.test(words[i])) i++;
|
|
4150
|
+
i++;
|
|
4151
|
+
const declarators = words.slice(i).join(" ");
|
|
4152
|
+
if (!declarators) continue;
|
|
4153
|
+
for (const raw of declarators.split(",")) {
|
|
4154
|
+
const d = raw.trim();
|
|
4155
|
+
const arr = /^(\w+)\s*\[\s*(\d+)\s*\]$/.exec(d);
|
|
4156
|
+
if (arr) {
|
|
4157
|
+
const size = parseInt(arr[2], 10);
|
|
4158
|
+
for (let k = 0; k < size; k++) names.push(`${arr[1]}[${k}]`);
|
|
4159
|
+
} else if (/^\w+$/.test(d)) {
|
|
4160
|
+
names.push(d);
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4088
4163
|
}
|
|
4089
4164
|
return names;
|
|
4090
4165
|
}
|
|
@@ -4613,6 +4688,14 @@ function createViewportLayer(opts) {
|
|
|
4613
4688
|
id,
|
|
4614
4689
|
label,
|
|
4615
4690
|
space: "screen",
|
|
4691
|
+
reproject(outer, dims, screen) {
|
|
4692
|
+
const b = bounds(outer, dims);
|
|
4693
|
+
if (screen.x < b.x || screen.x >= b.x + b.w || screen.y < b.y || screen.y >= b.y + b.h) return null;
|
|
4694
|
+
return {
|
|
4695
|
+
x: (screen.x - b.x) / view.scale.x + view.x,
|
|
4696
|
+
y: (screen.y - b.y) / view.scale.y + view.y
|
|
4697
|
+
};
|
|
4698
|
+
},
|
|
4616
4699
|
draw: (data, outerView, dims) => {
|
|
4617
4700
|
const b = bounds(outerView, dims);
|
|
4618
4701
|
const children = [];
|
|
@@ -4639,6 +4722,14 @@ function createViewportLayer(opts) {
|
|
|
4639
4722
|
}
|
|
4640
4723
|
};
|
|
4641
4724
|
}
|
|
4725
|
+
function viewportsAt(layers, outer, dims, screen) {
|
|
4726
|
+
for (let i = layers.length - 1; i >= 0; i--) {
|
|
4727
|
+
const layer = layers[i];
|
|
4728
|
+
const point = layer.reproject(outer, dims, screen);
|
|
4729
|
+
if (point) return { layer, point };
|
|
4730
|
+
}
|
|
4731
|
+
return null;
|
|
4732
|
+
}
|
|
4642
4733
|
|
|
4643
4734
|
// src/features/parallax/deriveParallaxView.ts
|
|
4644
4735
|
function asXY(v) {
|
|
@@ -5772,6 +5863,12 @@ function runLayoutPass(scratch, moveCtx) {
|
|
|
5772
5863
|
if (layout2.contains) return layout2.contains(cPose, draggedCenter);
|
|
5773
5864
|
return draggedCenter.x >= aabb.x && draggedCenter.x < aabb.x + aabb.width && draggedCenter.y >= aabb.y && draggedCenter.y < aabb.y + aabb.height;
|
|
5774
5865
|
};
|
|
5866
|
+
const draggedArg = {
|
|
5867
|
+
id: draggedId,
|
|
5868
|
+
originPose: startWorld,
|
|
5869
|
+
pose: draggedWorld,
|
|
5870
|
+
sourceContainerId
|
|
5871
|
+
};
|
|
5775
5872
|
const consider = (id, zPath) => {
|
|
5776
5873
|
if (id === draggedId) return;
|
|
5777
5874
|
const layout2 = layoutDep.getLayout(id);
|
|
@@ -5781,6 +5878,7 @@ function runLayoutPass(scratch, moveCtx) {
|
|
|
5781
5878
|
const worldPose = composeWorldPose(poseAdapter, id, pc.compose);
|
|
5782
5879
|
const worldAABB = boundsOf2(worldPose);
|
|
5783
5880
|
if (!testInside(worldPose, worldAABB, layout2)) return;
|
|
5881
|
+
if (layout2.acceptsDrop && !layout2.acceptsDrop({ id, bounds: worldAABB }, draggedArg)) return;
|
|
5784
5882
|
candidates.push({
|
|
5785
5883
|
id,
|
|
5786
5884
|
bounds: worldAABB,
|
|
@@ -5829,20 +5927,16 @@ function runLayoutPass(scratch, moveCtx) {
|
|
|
5829
5927
|
id: cid,
|
|
5830
5928
|
pose: composeWorldPose(poseAdapter, cid, pc.compose)
|
|
5831
5929
|
}));
|
|
5832
|
-
const draggedArg = {
|
|
5833
|
-
id: draggedId,
|
|
5834
|
-
originPose: startWorld,
|
|
5835
|
-
pose: draggedWorld,
|
|
5836
|
-
sourceContainerId
|
|
5837
|
-
};
|
|
5838
5930
|
const targets = layout.getDropTargets(container, children, draggedArg);
|
|
5839
5931
|
const target = layout.snap.pickTarget(targets, { x: moveCtx.drag.current.x, y: moveCtx.drag.current.y });
|
|
5840
5932
|
if (!target) return;
|
|
5933
|
+
const reflowIds = /* @__PURE__ */ new Set();
|
|
5841
5934
|
for (const [cid, pose] of layout.reflowPoses(container, children, draggedArg, target)) {
|
|
5842
5935
|
if (asNodeId(cid) === draggedId) continue;
|
|
5843
5936
|
const parent = scene.get(asNodeId(cid))?.parent ?? null;
|
|
5844
5937
|
const local = rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose);
|
|
5845
5938
|
scratch.previews.set(asNodeId(cid), local);
|
|
5939
|
+
reflowIds.add(asNodeId(cid));
|
|
5846
5940
|
}
|
|
5847
5941
|
const sourceReflow = /* @__PURE__ */ new Map();
|
|
5848
5942
|
if (sourceContainerId && sourceContainerId !== dest.id) {
|
|
@@ -5865,10 +5959,11 @@ function runLayoutPass(scratch, moveCtx) {
|
|
|
5865
5959
|
sourceReflow.set(cid, pose);
|
|
5866
5960
|
const parent = scene.get(asNodeId(cid))?.parent ?? null;
|
|
5867
5961
|
scratch.previews.set(asNodeId(cid), rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose));
|
|
5962
|
+
reflowIds.add(asNodeId(cid));
|
|
5868
5963
|
}
|
|
5869
5964
|
}
|
|
5870
5965
|
}
|
|
5871
|
-
scratch.layoutPass = { layout, container, children, target, sourceReflow };
|
|
5966
|
+
scratch.layoutPass = { layout, container, children, target, sourceReflow, reflowIds };
|
|
5872
5967
|
}
|
|
5873
5968
|
function scenePoseAdapter(scene) {
|
|
5874
5969
|
return {
|
|
@@ -6176,7 +6271,8 @@ var moveAction = {
|
|
|
6176
6271
|
scratch.previews.clear();
|
|
6177
6272
|
},
|
|
6178
6273
|
previewIds: () => scratch.previews.keys(),
|
|
6179
|
-
previewPose: (id) => scratch.previews.get(id) ?? null
|
|
6274
|
+
previewPose: (id) => scratch.previews.get(id) ?? null,
|
|
6275
|
+
previewOpaqueIds: () => scratch.layoutPass?.reflowIds ?? null
|
|
6180
6276
|
};
|
|
6181
6277
|
}
|
|
6182
6278
|
},
|
|
@@ -6945,7 +7041,8 @@ var KIT_INSERT_KINDS = /* @__PURE__ */ new Set([
|
|
|
6945
7041
|
"line",
|
|
6946
7042
|
"polygon",
|
|
6947
7043
|
"star",
|
|
6948
|
-
"pencil"
|
|
7044
|
+
"pencil",
|
|
7045
|
+
"image"
|
|
6949
7046
|
]);
|
|
6950
7047
|
var liveInsertScratch = null;
|
|
6951
7048
|
function effectiveOriginMode(paramsOrigin, altHeld) {
|
|
@@ -8074,7 +8171,7 @@ var pinchZoomAction = {
|
|
|
8074
8171
|
const multiTouch = ctx.multiTouch;
|
|
8075
8172
|
if (!multiTouch) return {};
|
|
8076
8173
|
const startSpread = multiTouch.spread > 0 ? multiTouch.spread : 1;
|
|
8077
|
-
const scratch = { view, startSpread };
|
|
8174
|
+
const scratch = { view, startSpread, centroid: multiTouch.centroid };
|
|
8078
8175
|
return {
|
|
8079
8176
|
kind: "pinch",
|
|
8080
8177
|
onMove(moveCtx) {
|
|
@@ -8084,8 +8181,15 @@ var pinchZoomAction = {
|
|
|
8084
8181
|
if (currentSpread <= 0 || scratch.startSpread <= 0) return;
|
|
8085
8182
|
const factor = currentSpread / scratch.startSpread;
|
|
8086
8183
|
scratch.startSpread = currentSpread;
|
|
8184
|
+
const prev = scratch.centroid;
|
|
8185
|
+
scratch.centroid = centroid;
|
|
8087
8186
|
const current = scratch.view.get();
|
|
8088
|
-
|
|
8187
|
+
const zoomed = zoomAt(current, prev, factor);
|
|
8188
|
+
scratch.view.set({
|
|
8189
|
+
scale: zoomed.scale,
|
|
8190
|
+
x: zoomed.x - (centroid.x - prev.x) / zoomed.scale.x,
|
|
8191
|
+
y: zoomed.y - (centroid.y - prev.y) / zoomed.scale.y
|
|
8192
|
+
});
|
|
8089
8193
|
}
|
|
8090
8194
|
// onEnd: nothing to do — zoom was applied each frame.
|
|
8091
8195
|
};
|
|
@@ -8569,10 +8673,12 @@ function normalizeNegativeExtent(pose) {
|
|
|
8569
8673
|
}
|
|
8570
8674
|
|
|
8571
8675
|
// src/interactions/actions/defaults/flip.ts
|
|
8572
|
-
function flipSelection(selection, scene, axis, applyOps, geometryProjection) {
|
|
8676
|
+
function flipSelection(selection, scene, axis, pivot, applyOps, geometryProjection) {
|
|
8573
8677
|
const ids = selection.get();
|
|
8574
8678
|
if (ids.length === 0) return;
|
|
8575
8679
|
const geom = AUTO_POSE_DESCRIPTOR;
|
|
8680
|
+
const nodes = ids.map((id) => scene.get(id)).filter((n) => n != null);
|
|
8681
|
+
const unionPivot = pivot === "union" ? unionBounds(nodes.map((n) => geom.getBounds(n.pose))) : null;
|
|
8576
8682
|
const ops = [];
|
|
8577
8683
|
for (const id of ids) {
|
|
8578
8684
|
const node = scene.get(id);
|
|
@@ -8580,10 +8686,10 @@ function flipSelection(selection, scene, axis, applyOps, geometryProjection) {
|
|
|
8580
8686
|
ops.push(createTransformOp({
|
|
8581
8687
|
id,
|
|
8582
8688
|
from: node.pose,
|
|
8583
|
-
to: flipPoseViaDescriptor(node.pose, axis, geom),
|
|
8689
|
+
to: unionPivot ? flipPoseAboutBounds(node.pose, axis, geom, unionPivot) : flipPoseViaDescriptor(node.pose, axis, geom),
|
|
8584
8690
|
label: "Flip"
|
|
8585
8691
|
}));
|
|
8586
|
-
const g = geom.getBounds(node.pose);
|
|
8692
|
+
const g = unionPivot ?? geom.getBounds(node.pose);
|
|
8587
8693
|
const cx = g.x + g.width / 2;
|
|
8588
8694
|
const cy = g.y + g.height / 2;
|
|
8589
8695
|
const m = axis === "x" ? [-1, 0, 0, 1, 2 * cx, 0] : [1, 0, 0, -1, 0, 2 * cy];
|
|
@@ -8612,12 +8718,13 @@ var flipAction = {
|
|
|
8612
8718
|
timing: "immediate",
|
|
8613
8719
|
run: (deps, params) => {
|
|
8614
8720
|
const axis = params?.axis ?? "x";
|
|
8721
|
+
const pivot = params?.pivot ?? "each";
|
|
8615
8722
|
const selection = deps.selection;
|
|
8616
8723
|
const scene = deps.scene;
|
|
8617
8724
|
const applyOps = deps.applyOps;
|
|
8618
8725
|
const geometryProjection = deps.geometryProjection;
|
|
8619
8726
|
if (!selection || !scene) return;
|
|
8620
|
-
flipSelection(selection, scene, axis, applyOps, geometryProjection);
|
|
8727
|
+
flipSelection(selection, scene, axis, pivot, applyOps, geometryProjection);
|
|
8621
8728
|
}
|
|
8622
8729
|
},
|
|
8623
8730
|
enabled: requiresSelection
|
|
@@ -10566,6 +10673,12 @@ var DEFAULT_DEBUG_THEME = {
|
|
|
10566
10673
|
fpsText: "#e0e0e0",
|
|
10567
10674
|
fpsTextBg: "rgba(0, 0, 0, 0.6)"
|
|
10568
10675
|
};
|
|
10676
|
+
var DEFAULT_DEBUG_STROKES = {
|
|
10677
|
+
hitbox: { width: 1, dash: [2, 2] },
|
|
10678
|
+
bounds: { width: 1 },
|
|
10679
|
+
handle: { width: 1 },
|
|
10680
|
+
snap: { width: 1 }
|
|
10681
|
+
};
|
|
10569
10682
|
|
|
10570
10683
|
// src/debug/createDebugOverlayLayer.ts
|
|
10571
10684
|
function createDebugOverlayLayer({
|
|
@@ -10573,6 +10686,7 @@ function createDebugOverlayLayer({
|
|
|
10573
10686
|
config
|
|
10574
10687
|
}) {
|
|
10575
10688
|
const theme = { ...DEFAULT_DEBUG_THEME, ...config.theme ?? {} };
|
|
10689
|
+
const strokes = { ...DEFAULT_DEBUG_STROKES, ...config.strokes ?? {} };
|
|
10576
10690
|
const fpsHistory = [];
|
|
10577
10691
|
const FPS_WINDOW = 60;
|
|
10578
10692
|
return {
|
|
@@ -10584,11 +10698,11 @@ function createDebugOverlayLayer({
|
|
|
10584
10698
|
const s = sink.snapshot();
|
|
10585
10699
|
const t = viewToTransform(view);
|
|
10586
10700
|
const out = [];
|
|
10587
|
-
if (config.hitboxes) emitHitboxes(out, s, view, t, theme);
|
|
10588
|
-
if (config.bounds) emitBounds(out, s, view, t, theme);
|
|
10589
|
-
if (config.handles) emitHandles(out, s, t, theme);
|
|
10701
|
+
if (config.hitboxes) emitHitboxes(out, s, view, t, theme, strokes);
|
|
10702
|
+
if (config.bounds) emitBounds(out, s, view, t, theme, strokes);
|
|
10703
|
+
if (config.handles) emitHandles(out, s, t, theme, strokes);
|
|
10590
10704
|
if (config.origins) emitOrigins(out, s, t, theme);
|
|
10591
|
-
if (config.snap) emitSnap(out, s, t, theme);
|
|
10705
|
+
if (config.snap) emitSnap(out, s, t, theme, strokes);
|
|
10592
10706
|
if (config.ids) emitIds(out, s, t, theme);
|
|
10593
10707
|
if (config.layers) emitLayersPanel(out, s, dims, theme);
|
|
10594
10708
|
if (config.fps) {
|
|
@@ -10621,9 +10735,16 @@ function approxCircleScreen(cx, cy, r, segments = 24) {
|
|
|
10621
10735
|
function rectPath2(x, y, w, h) {
|
|
10622
10736
|
return { kind: "rect", x, y, width: w, height: h };
|
|
10623
10737
|
}
|
|
10624
|
-
function
|
|
10738
|
+
function strokeOf(s, color) {
|
|
10739
|
+
return {
|
|
10740
|
+
paint: { fill: "solid", color },
|
|
10741
|
+
width: s.width,
|
|
10742
|
+
...s.dash && s.dash.length > 0 ? { dash: [...s.dash] } : {}
|
|
10743
|
+
};
|
|
10744
|
+
}
|
|
10745
|
+
function emitHitboxes(out, s, view, t, theme, strokes) {
|
|
10625
10746
|
const fill = { fill: "solid", color: theme.hitboxFill };
|
|
10626
|
-
const stroke =
|
|
10747
|
+
const stroke = strokeOf(strokes.hitbox, theme.hitboxStroke);
|
|
10627
10748
|
for (const h of s.hitboxes) {
|
|
10628
10749
|
if (h.shape.kind === "rect") {
|
|
10629
10750
|
const [sx, sy] = worldToScreen(h.shape.x, h.shape.y, t);
|
|
@@ -10637,8 +10758,8 @@ function emitHitboxes(out, s, view, t, theme) {
|
|
|
10637
10758
|
}
|
|
10638
10759
|
}
|
|
10639
10760
|
}
|
|
10640
|
-
function emitBounds(out, s, view, t, theme) {
|
|
10641
|
-
const stroke =
|
|
10761
|
+
function emitBounds(out, s, view, t, theme, strokes) {
|
|
10762
|
+
const stroke = strokeOf(strokes.bounds, theme.bounds);
|
|
10642
10763
|
for (const b of s.bounds) {
|
|
10643
10764
|
const [sx, sy] = worldToScreen(b.bounds.x, b.bounds.y, t);
|
|
10644
10765
|
const sw = b.bounds.width * view.scale.x;
|
|
@@ -10646,8 +10767,8 @@ function emitBounds(out, s, view, t, theme) {
|
|
|
10646
10767
|
out.push({ kind: "path", path: rectPath2(sx, sy, sw, sh), stroke });
|
|
10647
10768
|
}
|
|
10648
10769
|
}
|
|
10649
|
-
function emitHandles(out, s, t, theme) {
|
|
10650
|
-
const stroke =
|
|
10770
|
+
function emitHandles(out, s, t, theme, strokes) {
|
|
10771
|
+
const stroke = strokeOf(strokes.handle, theme.handle);
|
|
10651
10772
|
for (const h of s.handles) {
|
|
10652
10773
|
const [cx, cy] = worldToScreen(h.position.x, h.position.y, t);
|
|
10653
10774
|
const horiz = {
|
|
@@ -10673,14 +10794,14 @@ function emitOrigins(out, s, t, theme) {
|
|
|
10673
10794
|
out.push({ kind: "path", path: approxCircleScreen(cx, cy, 3), fill });
|
|
10674
10795
|
}
|
|
10675
10796
|
}
|
|
10676
|
-
function emitSnap(out, s, t, theme) {
|
|
10797
|
+
function emitSnap(out, s, t, theme, strokes) {
|
|
10677
10798
|
const color = theme.snap;
|
|
10678
10799
|
for (const c of s.snap) {
|
|
10679
10800
|
const [cx, cy] = worldToScreen(c.point.x, c.point.y, t);
|
|
10680
10801
|
const cmd = {
|
|
10681
10802
|
kind: "path",
|
|
10682
10803
|
path: approxCircleScreen(cx, cy, 4),
|
|
10683
|
-
...c.accepted ? { fill: { fill: "solid", color } } : { stroke:
|
|
10804
|
+
...c.accepted ? { fill: { fill: "solid", color } } : { stroke: strokeOf(strokes.snap, color) }
|
|
10684
10805
|
};
|
|
10685
10806
|
out.push(cmd);
|
|
10686
10807
|
}
|
|
@@ -11063,11 +11184,22 @@ function reportDeadClaim(owner, warn) {
|
|
|
11063
11184
|
`[weasel] exclusive claim by "${key}" matched no binding: no \`affordance:\` or \`kindOf\` target resolved against it, so the press was dropped.`
|
|
11064
11185
|
);
|
|
11065
11186
|
}
|
|
11187
|
+
function phaseRank(spec) {
|
|
11188
|
+
if (spec === void 0) return 0;
|
|
11189
|
+
const atoms = typeof spec === "string" ? [{ channel: "&", phase: spec }] : spec;
|
|
11190
|
+
if (atoms.length === 0) return 0;
|
|
11191
|
+
let min = 2;
|
|
11192
|
+
for (const a of atoms) {
|
|
11193
|
+
const rank = (a.channel === "*" ? 0 : 1) + (a.phase === "*" ? 0 : 1);
|
|
11194
|
+
if (rank < min) min = rank;
|
|
11195
|
+
}
|
|
11196
|
+
return min;
|
|
11197
|
+
}
|
|
11066
11198
|
function specificity(spec) {
|
|
11067
11199
|
const t = targetRank(specTargetOf(spec));
|
|
11068
11200
|
const mods = "mods" in spec ? spec.mods : void 0;
|
|
11069
11201
|
const m = modsCount(mods);
|
|
11070
|
-
const p = "phase" in spec
|
|
11202
|
+
const p = phaseRank("phase" in spec ? spec.phase : void 0);
|
|
11071
11203
|
const typed = (spec.kind === "drop" || spec.kind === "paste") && spec.types !== void 0 && spec.types.length > 0 ? 2 : 1;
|
|
11072
11204
|
return [t, m, p, typed];
|
|
11073
11205
|
}
|
|
@@ -12727,8 +12859,7 @@ function useGestureDispatcher(opts) {
|
|
|
12727
12859
|
if (!cd) return;
|
|
12728
12860
|
const items = itemsFromClipboardData(cd);
|
|
12729
12861
|
if (items.length === 0) return;
|
|
12730
|
-
|
|
12731
|
-
dispatch2({
|
|
12862
|
+
const result = dispatch2({
|
|
12732
12863
|
kind: "paste",
|
|
12733
12864
|
items,
|
|
12734
12865
|
// ClipboardEvent carries no modifier state.
|
|
@@ -12737,6 +12868,7 @@ function useGestureDispatcher(opts) {
|
|
|
12737
12868
|
metaKey: false,
|
|
12738
12869
|
shiftKey: false
|
|
12739
12870
|
});
|
|
12871
|
+
if (result === "handled") e.preventDefault();
|
|
12740
12872
|
};
|
|
12741
12873
|
if (keyboard) {
|
|
12742
12874
|
window.addEventListener("keydown", onKeyDown);
|
|
@@ -13080,6 +13212,52 @@ function useViewAnimation(setView) {
|
|
|
13080
13212
|
);
|
|
13081
13213
|
return { animateTo, animateToBounds, cancel };
|
|
13082
13214
|
}
|
|
13215
|
+
function validateId(id, kind) {
|
|
13216
|
+
if (id.length === 0) {
|
|
13217
|
+
throw new Error(`weasel: ${kind} id may not be empty`);
|
|
13218
|
+
}
|
|
13219
|
+
if (RESERVED_ID_PREFIXES.has(id[0])) {
|
|
13220
|
+
throw new Error(
|
|
13221
|
+
`weasel: ${kind} id "${id}" starts with reserved sigil "${id[0]}" (reserved set: ${[...RESERVED_ID_PREFIXES].join(" ")})`
|
|
13222
|
+
);
|
|
13223
|
+
}
|
|
13224
|
+
if (RESERVED_ID_NAMES.has(id)) {
|
|
13225
|
+
throw new Error(
|
|
13226
|
+
`weasel: ${kind} id "${id}" collides with a reserved phase keyword (reserved: ${[...RESERVED_ID_NAMES].join(", ")})`
|
|
13227
|
+
);
|
|
13228
|
+
}
|
|
13229
|
+
}
|
|
13230
|
+
function defineTool(def) {
|
|
13231
|
+
validateId(def.id, "tool");
|
|
13232
|
+
const resolveCursor = (ctx) => {
|
|
13233
|
+
if (def.cursor == null) return "";
|
|
13234
|
+
return typeof def.cursor === "function" ? def.cursor(ctx) : def.cursor;
|
|
13235
|
+
};
|
|
13236
|
+
return {
|
|
13237
|
+
id: def.id,
|
|
13238
|
+
eligibility: {
|
|
13239
|
+
focus: true,
|
|
13240
|
+
capabilities: def.capabilities,
|
|
13241
|
+
...def.hotkey ? { offhand: def.hotkey } : {}
|
|
13242
|
+
},
|
|
13243
|
+
actions: def.actions,
|
|
13244
|
+
def,
|
|
13245
|
+
presentation: def.presentation,
|
|
13246
|
+
keybinding: def.keybinding,
|
|
13247
|
+
onActivate: def.onActivate,
|
|
13248
|
+
onDeactivate: def.onDeactivate,
|
|
13249
|
+
initScratch: def.initScratch ?? (() => null),
|
|
13250
|
+
cursor: resolveCursor,
|
|
13251
|
+
bindings: def.bindings,
|
|
13252
|
+
overlay: def.overlay,
|
|
13253
|
+
overlayPosition: def.overlayPosition
|
|
13254
|
+
};
|
|
13255
|
+
}
|
|
13256
|
+
|
|
13257
|
+
// src/tools/defineViewportTool.ts
|
|
13258
|
+
function defineViewportTool(def) {
|
|
13259
|
+
return defineTool(def);
|
|
13260
|
+
}
|
|
13083
13261
|
|
|
13084
13262
|
// src/interactions/actions/defaults/toolOffhand.ts
|
|
13085
13263
|
var TOOL_OFFHAND_ID = "tool.offhand";
|
|
@@ -13174,17 +13352,19 @@ function useContributions(opts) {
|
|
|
13174
13352
|
const { ordered, state } = snapshot();
|
|
13175
13353
|
return scopeBindings(ordered, state);
|
|
13176
13354
|
}, [snapshot]);
|
|
13177
|
-
const overlays = useCallback(() => {
|
|
13355
|
+
const overlays = useCallback((position = "top") => {
|
|
13178
13356
|
const { ordered, state } = snapshot();
|
|
13179
13357
|
const active = [];
|
|
13180
13358
|
const hotkey = [];
|
|
13181
13359
|
const ambient = [];
|
|
13182
13360
|
for (const entry of ordered) {
|
|
13183
13361
|
if (!entry.overlay) continue;
|
|
13362
|
+
if ((entry.overlayPosition ?? "top") !== position) continue;
|
|
13363
|
+
const layers = Array.isArray(entry.overlay) ? entry.overlay : [entry.overlay];
|
|
13184
13364
|
const scope = liveScope(entry.id, entry.eligibility ?? {}, state);
|
|
13185
|
-
if (scope === "active") active.push(
|
|
13186
|
-
else if (scope === "hotkey") hotkey.push(
|
|
13187
|
-
else if (scope === "ambient") ambient.push(
|
|
13365
|
+
if (scope === "active") active.push(...layers);
|
|
13366
|
+
else if (scope === "hotkey") hotkey.push(...layers);
|
|
13367
|
+
else if (scope === "ambient") ambient.push(...layers);
|
|
13188
13368
|
}
|
|
13189
13369
|
return [...active, ...hotkey, ...ambient];
|
|
13190
13370
|
}, [snapshot]);
|
|
@@ -14011,7 +14191,7 @@ function isBoundsGradient(fill) {
|
|
|
14011
14191
|
}
|
|
14012
14192
|
|
|
14013
14193
|
// src/features/patterns/resolveSpec.ts
|
|
14014
|
-
var
|
|
14194
|
+
var cache6 = /* @__PURE__ */ new Map();
|
|
14015
14195
|
function specKey(spec) {
|
|
14016
14196
|
const keys = Object.keys(spec).sort();
|
|
14017
14197
|
const bag = spec;
|
|
@@ -14019,10 +14199,10 @@ function specKey(spec) {
|
|
|
14019
14199
|
}
|
|
14020
14200
|
function resolvePatternSpec(spec) {
|
|
14021
14201
|
const key = specKey(spec);
|
|
14022
|
-
const hit =
|
|
14202
|
+
const hit = cache6.get(key);
|
|
14023
14203
|
if (hit !== void 0) return hit;
|
|
14024
14204
|
const built = buildTile(spec);
|
|
14025
|
-
|
|
14205
|
+
cache6.set(key, built);
|
|
14026
14206
|
return built;
|
|
14027
14207
|
}
|
|
14028
14208
|
function buildTile(spec) {
|
|
@@ -14058,7 +14238,7 @@ function resolveFillPattern(fill) {
|
|
|
14058
14238
|
}
|
|
14059
14239
|
|
|
14060
14240
|
// src/features/images/imageCache.ts
|
|
14061
|
-
var
|
|
14241
|
+
var cache7 = /* @__PURE__ */ new Map();
|
|
14062
14242
|
var subscribers = /* @__PURE__ */ new Set();
|
|
14063
14243
|
var defaultLoader = async (src) => {
|
|
14064
14244
|
if (typeof Image === "undefined" || typeof createImageBitmap === "undefined") {
|
|
@@ -14076,28 +14256,28 @@ function notify() {
|
|
|
14076
14256
|
}
|
|
14077
14257
|
function startLoad(src) {
|
|
14078
14258
|
const entry = { status: "loading" };
|
|
14079
|
-
|
|
14259
|
+
cache7.set(src, entry);
|
|
14080
14260
|
loader(src).then(
|
|
14081
14261
|
(bitmap) => {
|
|
14082
|
-
if (
|
|
14083
|
-
|
|
14262
|
+
if (cache7.get(src) !== entry) return;
|
|
14263
|
+
cache7.set(src, { status: "ready", bitmap });
|
|
14084
14264
|
notify();
|
|
14085
14265
|
},
|
|
14086
14266
|
() => {
|
|
14087
|
-
if (
|
|
14088
|
-
|
|
14267
|
+
if (cache7.get(src) !== entry) return;
|
|
14268
|
+
cache7.set(src, { status: "error" });
|
|
14089
14269
|
notify();
|
|
14090
14270
|
}
|
|
14091
14271
|
);
|
|
14092
14272
|
}
|
|
14093
14273
|
function getImageBitmap(src) {
|
|
14094
|
-
const entry =
|
|
14274
|
+
const entry = cache7.get(src);
|
|
14095
14275
|
if (entry) return entry.bitmap;
|
|
14096
14276
|
startLoad(src);
|
|
14097
14277
|
return void 0;
|
|
14098
14278
|
}
|
|
14099
14279
|
function imageStatus(src) {
|
|
14100
|
-
return
|
|
14280
|
+
return cache7.get(src)?.status ?? "idle";
|
|
14101
14281
|
}
|
|
14102
14282
|
function subscribeImageReady(cb) {
|
|
14103
14283
|
subscribers.add(cb);
|
|
@@ -14464,6 +14644,7 @@ registerBuiltInShapePainters();
|
|
|
14464
14644
|
function pickTopMostHit(ids, adapter) {
|
|
14465
14645
|
if (ids.length === 0) return null;
|
|
14466
14646
|
if (ids.length === 1) return ids[0];
|
|
14647
|
+
let candidates = ids;
|
|
14467
14648
|
const getParent = adapter?.getParent;
|
|
14468
14649
|
if (typeof getParent === "function") {
|
|
14469
14650
|
const set = new Set(ids);
|
|
@@ -14478,15 +14659,40 @@ function pickTopMostHit(ids, adapter) {
|
|
|
14478
14659
|
}
|
|
14479
14660
|
if (dropped.size > 0) {
|
|
14480
14661
|
const filtered = ids.filter((id) => !dropped.has(id));
|
|
14481
|
-
if (filtered.length ===
|
|
14482
|
-
|
|
14483
|
-
|
|
14484
|
-
|
|
14662
|
+
if (filtered.length === 1) return filtered[0];
|
|
14663
|
+
if (filtered.length > 1) candidates = filtered;
|
|
14664
|
+
}
|
|
14665
|
+
}
|
|
14666
|
+
return pickHighestZ(candidates, adapter);
|
|
14667
|
+
}
|
|
14668
|
+
function pickHighestZ(ids, adapter) {
|
|
14669
|
+
const compareZ = adapter?.compareZ;
|
|
14670
|
+
if (typeof compareZ === "function") {
|
|
14671
|
+
let best = ids[0];
|
|
14672
|
+
for (let i = 1; i < ids.length; i++) {
|
|
14673
|
+
if (compareZ(ids[i], best) >= 0) best = ids[i];
|
|
14674
|
+
}
|
|
14675
|
+
return best;
|
|
14676
|
+
}
|
|
14677
|
+
const getZIndex = adapter?.getZIndex;
|
|
14678
|
+
if (typeof getZIndex === "function") {
|
|
14679
|
+
let best = ids[0];
|
|
14680
|
+
let bestZ = zOf(getZIndex, best);
|
|
14681
|
+
for (let i = 1; i < ids.length; i++) {
|
|
14682
|
+
const z = zOf(getZIndex, ids[i]);
|
|
14683
|
+
if (z >= bestZ) {
|
|
14684
|
+
best = ids[i];
|
|
14685
|
+
bestZ = z;
|
|
14485
14686
|
}
|
|
14486
14687
|
}
|
|
14688
|
+
return best;
|
|
14487
14689
|
}
|
|
14488
14690
|
return ids[ids.length - 1];
|
|
14489
14691
|
}
|
|
14692
|
+
function zOf(getZIndex, id) {
|
|
14693
|
+
const z = getZIndex(id);
|
|
14694
|
+
return typeof z === "number" && Number.isFinite(z) ? z : -Infinity;
|
|
14695
|
+
}
|
|
14490
14696
|
|
|
14491
14697
|
// src/core/selection/selectionTarget.ts
|
|
14492
14698
|
var MULTI_RESIZE_TARGET_ID = "__weasel:multi-selection";
|
|
@@ -14891,9 +15097,19 @@ function composeAffordanceLayer(id, label, affordances) {
|
|
|
14891
15097
|
},
|
|
14892
15098
|
// The walk itself lives in `hitAffordanceRegions` so this layer and
|
|
14893
15099
|
// `buildAffordanceAt` share one implementation rather than two that can
|
|
14894
|
-
// drift. This wrapper
|
|
14895
|
-
// binding
|
|
14896
|
-
hitTest: (wx, wy, state, view, _dims, isVisible) =>
|
|
15100
|
+
// drift. This wrapper lifts the region's declared cursor and claim onto
|
|
15101
|
+
// the binding, the way `buildAffordanceAt` lifts them onto `AffordanceHit`.
|
|
15102
|
+
hitTest: (wx, wy, state, view, _dims, isVisible) => {
|
|
15103
|
+
const hit = hitAffordanceRegions(affordances, wx, wy, state, view, isVisible);
|
|
15104
|
+
if (!hit) return null;
|
|
15105
|
+
const { cursor, strength, claimedKinds } = hit.region;
|
|
15106
|
+
return {
|
|
15107
|
+
...hit.binding,
|
|
15108
|
+
...cursor !== void 0 ? { cursor } : {},
|
|
15109
|
+
...strength !== void 0 ? { strength } : {},
|
|
15110
|
+
...claimedKinds !== void 0 ? { claimedKinds } : {}
|
|
15111
|
+
};
|
|
15112
|
+
}
|
|
14897
15113
|
};
|
|
14898
15114
|
}
|
|
14899
15115
|
function asChromeState(data) {
|
|
@@ -15676,7 +15892,7 @@ function useEllipseTool() {
|
|
|
15676
15892
|
);
|
|
15677
15893
|
}
|
|
15678
15894
|
function useImageTool(options) {
|
|
15679
|
-
const { src, label = "Image" } = options;
|
|
15895
|
+
const { src, label = "Image", preview = "bitmap" } = options;
|
|
15680
15896
|
return useMemo(
|
|
15681
15897
|
() => defineTool({
|
|
15682
15898
|
id: "image",
|
|
@@ -15695,11 +15911,11 @@ function useImageTool(options) {
|
|
|
15695
15911
|
{
|
|
15696
15912
|
spec: { kind: "drag" },
|
|
15697
15913
|
actionId: "insert",
|
|
15698
|
-
opts: { params: { kind: "image", src } }
|
|
15914
|
+
opts: { params: { kind: "image", src, preview } }
|
|
15699
15915
|
}
|
|
15700
15916
|
]
|
|
15701
15917
|
}),
|
|
15702
|
-
[src, label]
|
|
15918
|
+
[src, label, preview]
|
|
15703
15919
|
);
|
|
15704
15920
|
}
|
|
15705
15921
|
function useEyedropperTool(opts) {
|
|
@@ -16166,6 +16382,19 @@ function composeOrderedLayers(layersMap, standardLayers, sceneLayers) {
|
|
|
16166
16382
|
}
|
|
16167
16383
|
return out;
|
|
16168
16384
|
}
|
|
16385
|
+
function placeToolOverlays(ordered, selectionOverlay, overlays) {
|
|
16386
|
+
const before = overlays("before-selection");
|
|
16387
|
+
const after = overlays("after-selection");
|
|
16388
|
+
const at = selectionOverlay ? ordered.indexOf(selectionOverlay) : -1;
|
|
16389
|
+
if (at >= 0) {
|
|
16390
|
+
ordered.splice(at + 1, 0, ...after);
|
|
16391
|
+
ordered.splice(at, 0, ...before);
|
|
16392
|
+
} else {
|
|
16393
|
+
ordered.push(...before, ...after);
|
|
16394
|
+
}
|
|
16395
|
+
ordered.push(...overlays("top"));
|
|
16396
|
+
return ordered;
|
|
16397
|
+
}
|
|
16169
16398
|
|
|
16170
16399
|
// src/canvas/toolPreview.ts
|
|
16171
16400
|
function* toolsInPriorityOrder(tools) {
|
|
@@ -17712,7 +17941,7 @@ function CanvasInner(props, ref) {
|
|
|
17712
17941
|
const out = composeOrderedLayers(effectiveLayersMap, standardLayers, sceneLayers);
|
|
17713
17942
|
if (decorationLayer) out.push(decorationLayer);
|
|
17714
17943
|
if (tools) {
|
|
17715
|
-
out.
|
|
17944
|
+
placeToolOverlays(out, standardLayers.selectionOverlay, tools.getActiveOverlays);
|
|
17716
17945
|
}
|
|
17717
17946
|
return out;
|
|
17718
17947
|
}, [layersMap, adapter, selectedIds, effectiveBoundsOf, multiActive2, debugSink, tools, backgroundLayer, decorationLayer]);
|
|
@@ -19379,6 +19608,7 @@ function useSceneSelectTool(args) {
|
|
|
19379
19608
|
boundsOf: wiredBoundsOf
|
|
19380
19609
|
};
|
|
19381
19610
|
}
|
|
19611
|
+
var GHOST_ALPHA = 0.85;
|
|
19382
19612
|
function usePreviewGhostLayer(args) {
|
|
19383
19613
|
const { scene, tools, sceneSlot, dispatcher } = args;
|
|
19384
19614
|
const sceneRef = useRef(scene);
|
|
@@ -19465,15 +19695,26 @@ function usePreviewGhostLayer(args) {
|
|
|
19465
19695
|
}
|
|
19466
19696
|
return [group];
|
|
19467
19697
|
};
|
|
19698
|
+
const opaqueSet = /* @__PURE__ */ new Set();
|
|
19699
|
+
for (const source of sources) {
|
|
19700
|
+
const ids = source.previewOpaqueIds?.();
|
|
19701
|
+
if (!ids) continue;
|
|
19702
|
+
for (const id of ids) opaqueSet.add(id);
|
|
19703
|
+
}
|
|
19468
19704
|
const children = [];
|
|
19705
|
+
const opaque = [];
|
|
19469
19706
|
for (const id of idSet) {
|
|
19470
19707
|
const node = sc.get(asNodeId(id));
|
|
19471
19708
|
const parent = node?.parent;
|
|
19472
19709
|
if (parent != null && idSet.has(parent)) continue;
|
|
19473
|
-
|
|
19710
|
+
const sink = opaqueSet.has(id) ? opaque : children;
|
|
19711
|
+
for (const cmd of buildSubtree(id)) sink.push(cmd);
|
|
19474
19712
|
}
|
|
19475
|
-
if (children.length === 0) return [];
|
|
19476
|
-
|
|
19713
|
+
if (children.length === 0 && opaque.length === 0) return [];
|
|
19714
|
+
const out = [];
|
|
19715
|
+
if (opaque.length > 0) out.push({ kind: "group", children: opaque });
|
|
19716
|
+
if (children.length > 0) out.push({ kind: "group", alpha: GHOST_ALPHA, children });
|
|
19717
|
+
return out;
|
|
19477
19718
|
}
|
|
19478
19719
|
}), []);
|
|
19479
19720
|
}
|
|
@@ -19483,6 +19724,7 @@ var DEFAULT_STYLE = {
|
|
|
19483
19724
|
dash: [3, 3],
|
|
19484
19725
|
lineWidth: 1
|
|
19485
19726
|
};
|
|
19727
|
+
var PREVIEW_CONTENT_OPACITY = 0.85;
|
|
19486
19728
|
function useDispatcherOverlayLayer(args) {
|
|
19487
19729
|
const { dispatcher, style } = args;
|
|
19488
19730
|
const dispatcherRef = useRef(dispatcher);
|
|
@@ -19545,6 +19787,26 @@ function useDispatcherOverlayLayer(args) {
|
|
|
19545
19787
|
pathCmd = rectPath(sx, sy, b.width * view.scale.x, b.height * view.scale.y);
|
|
19546
19788
|
break;
|
|
19547
19789
|
}
|
|
19790
|
+
case "image": {
|
|
19791
|
+
const e = ov.extras;
|
|
19792
|
+
const [sx, sy] = worldToScreen(b.x, b.y, t);
|
|
19793
|
+
const sw = b.width * view.scale.x;
|
|
19794
|
+
const sh = b.height * view.scale.y;
|
|
19795
|
+
const bmp = e.preview === "outline" || !e.src ? void 0 : getImageBitmap(e.src);
|
|
19796
|
+
if (bmp) {
|
|
19797
|
+
out.push({
|
|
19798
|
+
kind: "image",
|
|
19799
|
+
image: bmp,
|
|
19800
|
+
x: sx,
|
|
19801
|
+
y: sy,
|
|
19802
|
+
w: sw,
|
|
19803
|
+
h: sh,
|
|
19804
|
+
opacity: PREVIEW_CONTENT_OPACITY
|
|
19805
|
+
});
|
|
19806
|
+
}
|
|
19807
|
+
pathCmd = rectPath(sx, sy, sw, sh);
|
|
19808
|
+
break;
|
|
19809
|
+
}
|
|
19548
19810
|
case "ellipse": {
|
|
19549
19811
|
const [sx, sy] = worldToScreen(b.x, b.y, t);
|
|
19550
19812
|
pathCmd = ellipsePath({
|
|
@@ -19603,7 +19865,7 @@ function useDispatcherOverlayLayer(args) {
|
|
|
19603
19865
|
const cmd = {
|
|
19604
19866
|
kind: "path",
|
|
19605
19867
|
path: pathCmd,
|
|
19606
|
-
fill: ov.shape === "line" || ov.shape === "pencil" ? void 0 : { color: cfg.fill },
|
|
19868
|
+
fill: ov.shape === "line" || ov.shape === "pencil" || ov.shape === "image" ? void 0 : { color: cfg.fill },
|
|
19607
19869
|
stroke: { paint: { color: cfg.stroke }, width: cfg.lineWidth, dash: cfg.dash }
|
|
19608
19870
|
};
|
|
19609
19871
|
out.push(cmd);
|
|
@@ -20316,9 +20578,6 @@ function buildClassifyTarget(getSelection, pickBest, kindOfNode) {
|
|
|
20316
20578
|
function w2s3(wx, wy, view) {
|
|
20317
20579
|
return [(wx - view.x) * view.scale.x, (wy - view.y) * view.scale.y];
|
|
20318
20580
|
}
|
|
20319
|
-
function r2s(radiusWorld, view) {
|
|
20320
|
-
return radiusWorld * meanScale(view.scale);
|
|
20321
|
-
}
|
|
20322
20581
|
var SLOP_FILL = "rgba(255, 80, 140, 0.18)";
|
|
20323
20582
|
var SLOP_STROKE = "rgba(255, 80, 140, 0.55)";
|
|
20324
20583
|
function createSlopsDebugLayer(opts) {
|
|
@@ -20329,7 +20588,7 @@ function createSlopsDebugLayer(opts) {
|
|
|
20329
20588
|
draw: (_data, view) => {
|
|
20330
20589
|
const out = [];
|
|
20331
20590
|
const sel = opts.selectionRef.current?.current ?? [];
|
|
20332
|
-
const r =
|
|
20591
|
+
const r = HANDLE_HIT_RADIUS;
|
|
20333
20592
|
for (const id of sel) {
|
|
20334
20593
|
const b = opts.boundsOf(id);
|
|
20335
20594
|
if (!b) continue;
|
|
@@ -20366,6 +20625,7 @@ function createSlopsDebugLayer(opts) {
|
|
|
20366
20625
|
}
|
|
20367
20626
|
const editingId = opts.getEditingId();
|
|
20368
20627
|
if (editingId) {
|
|
20628
|
+
const anchorR = ANCHOR_HIT_RADIUS;
|
|
20369
20629
|
const pose = opts.getPose(editingId);
|
|
20370
20630
|
if (pose && pose.kind === "polygon") {
|
|
20371
20631
|
const anchors = enumerateAnchors(pose);
|
|
@@ -20373,7 +20633,7 @@ function createSlopsDebugLayer(opts) {
|
|
|
20373
20633
|
const [sx, sy] = w2s3(a.x, a.y, view);
|
|
20374
20634
|
out.push({
|
|
20375
20635
|
kind: "path",
|
|
20376
|
-
path: circlePath(sx, sy,
|
|
20636
|
+
path: circlePath(sx, sy, anchorR),
|
|
20377
20637
|
fill: { fill: "solid", color: SLOP_FILL },
|
|
20378
20638
|
stroke: { paint: { fill: "solid", color: SLOP_STROKE }, width: 1 }
|
|
20379
20639
|
});
|
|
@@ -20381,7 +20641,7 @@ function createSlopsDebugLayer(opts) {
|
|
|
20381
20641
|
const [csx, csy] = w2s3(a.controlIn.x, a.controlIn.y, view);
|
|
20382
20642
|
out.push({
|
|
20383
20643
|
kind: "path",
|
|
20384
|
-
path: circlePath(csx, csy,
|
|
20644
|
+
path: circlePath(csx, csy, anchorR),
|
|
20385
20645
|
fill: { fill: "solid", color: SLOP_FILL },
|
|
20386
20646
|
stroke: { paint: { fill: "solid", color: SLOP_STROKE }, width: 1 }
|
|
20387
20647
|
});
|
|
@@ -20390,7 +20650,7 @@ function createSlopsDebugLayer(opts) {
|
|
|
20390
20650
|
const [csx, csy] = w2s3(a.controlOut.x, a.controlOut.y, view);
|
|
20391
20651
|
out.push({
|
|
20392
20652
|
kind: "path",
|
|
20393
|
-
path: circlePath(csx, csy,
|
|
20653
|
+
path: circlePath(csx, csy, anchorR),
|
|
20394
20654
|
fill: { fill: "solid", color: SLOP_FILL },
|
|
20395
20655
|
stroke: { paint: { fill: "solid", color: SLOP_STROKE }, width: 1 }
|
|
20396
20656
|
});
|
|
@@ -20472,9 +20732,9 @@ function DepRegistryProviderIfRoot({ children }) {
|
|
|
20472
20732
|
function hitTestArea(scene, bounds) {
|
|
20473
20733
|
const { x, y, width: w, height: h } = bounds;
|
|
20474
20734
|
const area = [x, y, x + w, y, x + w, y + h, x, y + h];
|
|
20475
|
-
return hitTestAreaPolygon(scene, area, { x, y, width: w, height: h });
|
|
20735
|
+
return hitTestAreaPolygon(scene, area, { x, y, width: w, height: h }, true);
|
|
20476
20736
|
}
|
|
20477
|
-
function hitTestAreaPolygon(scene, area, areaBounds) {
|
|
20737
|
+
function hitTestAreaPolygon(scene, area, areaBounds, areaIsRect = false) {
|
|
20478
20738
|
const ab = areaBounds ?? boundsOf(area);
|
|
20479
20739
|
if (!ab) return [];
|
|
20480
20740
|
const hits = [];
|
|
@@ -20491,13 +20751,22 @@ function hitTestAreaPolygon(scene, area, areaBounds) {
|
|
|
20491
20751
|
if (b.x >= ab.x + ab.width || b.x + b.width <= ab.x || b.y >= ab.y + ab.height || b.y + b.height <= ab.y) {
|
|
20492
20752
|
continue;
|
|
20493
20753
|
}
|
|
20494
|
-
if (
|
|
20754
|
+
if (areaIsRect && b.x >= ab.x && b.y >= ab.y && b.x + b.width <= ab.x + ab.width && b.y + b.height <= ab.y + ab.height) {
|
|
20495
20755
|
hits.push(node.id);
|
|
20496
20756
|
continue;
|
|
20497
20757
|
}
|
|
20498
|
-
if (
|
|
20499
|
-
|
|
20758
|
+
if (silhouette) {
|
|
20759
|
+
if (silhouetteOverlapsArea(pose.coords, area)) {
|
|
20760
|
+
hits.push(node.id);
|
|
20761
|
+
}
|
|
20762
|
+
continue;
|
|
20763
|
+
}
|
|
20764
|
+
const drawn = findShapeSilhouette(node, pose);
|
|
20765
|
+
if (drawn?.kind === "polygon") {
|
|
20766
|
+
if (silhouetteOverlapsArea(drawn.coords, area)) hits.push(node.id);
|
|
20767
|
+
continue;
|
|
20500
20768
|
}
|
|
20769
|
+
hits.push(node.id);
|
|
20501
20770
|
}
|
|
20502
20771
|
return hits;
|
|
20503
20772
|
}
|
|
@@ -24324,6 +24593,14 @@ function useSceneTextEdit(scene, container, options = {}) {
|
|
|
24324
24593
|
const setter = optsRef.current.setRuns;
|
|
24325
24594
|
const data = setter ? setter(node.data, runs) : { ...node.data, runs };
|
|
24326
24595
|
sceneRef.current.update(nid, { data });
|
|
24596
|
+
},
|
|
24597
|
+
setStyle: (id, style) => {
|
|
24598
|
+
const nid = asNodeId(id);
|
|
24599
|
+
const node = sceneRef.current.get(nid);
|
|
24600
|
+
if (!node) return;
|
|
24601
|
+
const setter = optsRef.current.setStyle;
|
|
24602
|
+
const data = setter ? setter(node.data, style) : { ...node.data, style };
|
|
24603
|
+
sceneRef.current.update(nid, { data });
|
|
24327
24604
|
}
|
|
24328
24605
|
});
|
|
24329
24606
|
const onDoubleClick = useCallback((e) => {
|
|
@@ -28032,6 +28309,6 @@ function mergeContributions(...bundles) {
|
|
|
28032
28309
|
return out;
|
|
28033
28310
|
}
|
|
28034
28311
|
|
|
28035
|
-
export { ALWAYS, ANCHOR_HIT_BASE_PX, ActionsProviderIfRoot, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, BUNDLE_TOOLS, COARSE_TARGET_SCALE, CURVE_REPS, ColorOverrideRegistry, CropIcon, CursorCoordsHud, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_THEME, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_HANDLE_SIZE2 as DEFAULT_HANDLE_SIZE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_STYLE, DEFAULT_VELOCITY_DECAY, DepRegistryProviderIfRoot, DeviceProfileProvider, DivideIcon, EASINGS, EllipseIcon, ExcludeIcon, EyedropperIcon, FALLBACK_FIT_VIEW, GHOST_STROKE, HANDLE_BASE_PX, HandIcon, IDENTITY_COLOR_MATRIX, IDENTITY_POSE_COMPOSITION, IntersectIcon, KIT_SHAPE_KINDS, LassoIcon, LineIcon, MIXED, MOVE_ANCHORS, MinimapCanvas, NEVER, OUTLINE_MIN_SCREEN_PX, PATH_ANCHOR_CHROME_ID, PenIcon, PencilIcon, PickHud, PointerProviderIfRoot, PolygonIcon, RECT_ALIGN_PROJECTION, ROTATION_HANDLE_BASE_PX, RectIcon, SPRING_PRESETS, SceneCanvas, SceneViewCanvas, SelectIcon, SelectionContextProvider, SelectionContextProviderIfRoot, ShaderCompileError, StarIcon, SubtractIcon, TextIcon, UnionIcon, UnknownIcon, VERSION, WeaselProvider, WeaselRenderer, aabbCenter, actionIs, alignDeltaFor, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, alignedStrokeRect, always, and, animateLifecycle, animateOnSetPose, annulusSemiAxes, applyBooleanOp, applyHitExistingGate, applyStyleToRange, areaSelectAction, arrayAdapter, asNodeId, bezierCubic, bezierQuadratic, buildChromeCtx, buildGradientRamp, buildRuleCtx, buildSceneViewCommands, canBringForward, canHover, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, caretIndexAt, cellAt, charOffsetToDomPosition, clampView, clearSelectionAction, clientToCanvas, clipboardCopyAction, clipboardCutAction, cloneAction, coarsePointer, composeAffordanceLayer, composePath, composeRectPose, composeSelectionPose, composeWorldPose, computeFitView2 as computeFitView, computeIndicatorCommand, computeWheelAction, cond, constrainTo45, containedThenNearest, countPathAnchors, createCellHighlightLayer, createChildrenLayer, createCornerResizeAffordance, createDebugOverlayLayer, createDebugSink, createDispatcher, createGridLayer, createGuidesLayer, createHistory2 as createHistory, createMarkdownRenderer, createMoveToIndexOp, createNodeProperties, createNodeRouting, createParallaxLayer, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathLayer, createPenPreviewLayer, createReorderOp, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetDataOp, createSetLayerOp, createSetPathOp, createSetTextOp, createTextLayer, createViewportLayer, cycleVertexColors, decomposePath, decomposeRectPose, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultVisibilityRules, deriveAlignmentGuides, deriveParallaxView, describeRule, domPositionToCharOffset, domToRuns, drawLayers, 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, easeOutCubic2 as easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, enterTextEditAction, enumerateAnchors, evaluate, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findShapeInk, findShapeSilhouette, fitTextPose, fitToBounds, fitViewToBounds, fitZoom, focused, fontString, forEachCoalesced, freeform, gateLayer, gesturing, getAlpha01, getImageBitmap, getNodeShapes, getStylusData, gradientForBounds, gradientGeometry, hexToRgba, hitAffordanceRegions, hitAnchor, hitRotationHandle, hovering, hoveringSelected, imageStatus, inferredNodeProperties, inferredNodeRouting, insertAction, isEditableTarget2 as isEditableTarget, isPatternSpec, lassoSelectAction, layoutMarkdown, lerpColorArray, lerpOklab, lerpOklch, linear, liveScope, makeViewportZoomAction, markdownToRuns, mat3, matchAlignment, matchesKeyBinding, meanScale, measureText, measureTextBounds, measuredWidth, mergeAlphaFromPrev, mergeContributions, modeIn, modeIs, modeNot, modifierHeld, momentum, moveAction, multiActive, nearest, nearestWithin, nestedHitTester, never, nodeHasFlag, none, normalizeHex, not, nurbs, oklabToOklch, oklabToSrgbU8, oklchToOklab, openFilePicker, or, parseColor, parseColorToRgba255, parseDebugFlags, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathDivide, pathExclude, pathFromD, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathOriginProjection, pathSubtract, pathToAnchors, pathUnion, pickTopMostHit, pinchZoomAction, planPixelRender, pointInRotatedRect, pointInTextPose, poseRotationOf, pressureToWidth, rainbowVertexColors, rebaseLocalPose, rectCorners, registerContentHandler, registerNodeShape, registerProgram, renderLabel, renderSceneToCanvas, renderSceneToPixels, resizeAction, resolveColor, resolveDeviceProfile, resolveFillPattern, resolvePatternSpec, resolveRuns, resolveTextStyle, resolveVisibility, rgbaToHex, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatedRectCorners, rotationDegreesUnit, rotationHandle, roundToCell, runsToDom, runsToMarkdown, runsToPlainText, sampleGradientStops, sceneFromJSON, sceneNodeClientRect, sceneToAdapter, scopeBindings, screenToWorld, selectFromLasso, selectionAtLeast, selectionEmpty, selectionIs, setFlagOverRange, shapeCoversPoint, sliceAction, snapPoint, solidVertexColors, specificity, spiro, splitPathByLine, splitSubpaths, springPose, springVertexColors, srgbU8ToOklab, staggerVertexColors, startThresholdDrag, styleAtRange, subscribeImageReady, tessellate, tessellateStroke, textCommand, textLineBoxes, tileGrid, toHex8, toRuns, translatePoseViaDescriptor, translateRectPose, tweenPose, tweenVertexColors, unionBounds, unionBoundsPath, useActiveToolContext, useAlign, useAnimator, useArrayAdapter, useAutoCenter, useBooleans, useBooleansAdapter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEllipseTool, useEyedropperTool, useGestureDispatcher, useGridCellHover, useGuides, useHandTool, useHandleDrag, useHoverTracking, useImageTool, useKeybindings, useLassoTool, useLineTool, useOptionalActiveToolContext, usePenTool, usePencilTool, usePinchGesture, usePinchZoomTool, usePointerStylus, usePolygonTool, usePublishSelection, useRectTool, useResizePolicy, useRotateTool, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelection, useSelectionContext, useSimulation, useSliceDep, useStandardActions, useStarTool, useTextEdit, useTextTool, useTools, useVelocityTracker, useViewAnimation, useViewTween, useZoom, verticalAlignOffset, viewToMat3, viewToTransform, viewportDragPanAction, viewportZoomAction, when, withAlpha01, withCoord, withGradientKind, worldEditToStorage, worldPoseLookup, worldToScreen, zoomAt, zoomAtLeast };
|
|
28036
|
-
//# sourceMappingURL=chunk-
|
|
28037
|
-
//# sourceMappingURL=chunk-
|
|
28312
|
+
export { ALWAYS, ANCHOR_HIT_BASE_PX, ActionsProviderIfRoot, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, BUNDLE_TOOLS, COARSE_TARGET_SCALE, CURVE_REPS, ColorOverrideRegistry, CropIcon, CursorCoordsHud, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_HANDLE_SIZE2 as DEFAULT_HANDLE_SIZE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_STYLE, DEFAULT_VELOCITY_DECAY, DepRegistryProviderIfRoot, DeviceProfileProvider, DivideIcon, EASINGS, EllipseIcon, ExcludeIcon, EyedropperIcon, FALLBACK_FIT_VIEW, GHOST_STROKE, HANDLE_BASE_PX, HandIcon, IDENTITY_COLOR_MATRIX, IDENTITY_POSE_COMPOSITION, IntersectIcon, KIT_SHAPE_KINDS, LassoIcon, LineIcon, MIXED, MOVE_ANCHORS, MinimapCanvas, NEVER, OUTLINE_MIN_SCREEN_PX, PATH_ANCHOR_CHROME_ID, PenIcon, PencilIcon, PickHud, PointerProviderIfRoot, PolygonIcon, RECT_ALIGN_PROJECTION, ROTATION_HANDLE_BASE_PX, RectIcon, SPRING_PRESETS, SceneCanvas, SceneViewCanvas, SelectIcon, SelectionContextProvider, SelectionContextProviderIfRoot, ShaderCompileError, StarIcon, SubtractIcon, TextIcon, UnionIcon, UnknownIcon, VERSION, WeaselProvider, WeaselRenderer, aabbCenter, actionIs, alignDeltaFor, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, alignedStrokeRect, always, and, animateLifecycle, animateOnSetPose, annulusSemiAxes, applyBooleanOp, applyHitExistingGate, applyStyleToRange, areaSelectAction, arrayAdapter, asNodeId, bezierCubic, bezierQuadratic, buildChromeCtx, buildGradientRamp, buildRuleCtx, buildSceneViewCommands, canBringForward, canHover, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, caretIndexAt, cellAt, charOffsetToDomPosition, clampView, clearSelectionAction, clientToCanvas, clipboardCopyAction, clipboardCutAction, cloneAction, coarsePointer, composeAffordanceLayer, composePath, composeRectPose, composeSelectionPose, composeWorldPose, computeFitView2 as computeFitView, computeIndicatorCommand, computeWheelAction, cond, constrainTo45, containedThenNearest, countPathAnchors, createCellHighlightLayer, createChildrenLayer, createCornerResizeAffordance, createDebugOverlayLayer, createDebugSink, createDispatcher, createGridLayer, createGuidesLayer, createHistory2 as createHistory, createMarkdownRenderer, createMoveToIndexOp, createNodeProperties, createNodeRouting, createParallaxLayer, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathLayer, createPenPreviewLayer, createReorderOp, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetDataOp, createSetLayerOp, createSetPathOp, createSetTextOp, createTextLayer, createViewportLayer, cycleVertexColors, decomposePath, decomposeRectPose, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultVisibilityRules, defineTool, defineViewportTool, deriveAlignmentGuides, deriveParallaxView, describeRule, domPositionToCharOffset, domToRuns, drawLayers, 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, easeOutCubic2 as easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, enterTextEditAction, enumerateAnchors, evaluate, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findShapeInk, findShapeSilhouette, fitTextPose, fitToBounds, fitViewToBounds, fitZoom, focused, fontString, forEachCoalesced, freeform, gateLayer, gesturing, getAlpha01, getImageBitmap, getNodeShapes, getStylusData, gradientForBounds, gradientGeometry, hexToRgba, hitAffordanceRegions, hitAnchor, hitRotationHandle, hovering, hoveringSelected, imageStatus, inferredNodeProperties, inferredNodeRouting, insertAction, isEditableTarget2 as isEditableTarget, isPatternSpec, lassoSelectAction, layoutMarkdown, lerpColorArray, lerpOklab, lerpOklch, linear, liveScope, makeViewportZoomAction, markdownToRuns, mat3, matchAlignment, matchesKeyBinding, meanScale, measureText, measureTextBounds, measuredWidth, mergeAlphaFromPrev, mergeContributions, modeIn, modeIs, modeNot, modifierHeld, momentum, moveAction, multiActive, nearest, nearestWithin, nestedHitTester, never, nodeHasFlag, none, normalizeHex, not, nurbs, oklabToOklch, oklabToSrgbU8, oklchToOklab, openFilePicker, or, parseColor, parseColorToRgba255, parseDebugFlags, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathDivide, pathExclude, pathFromD, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathOriginProjection, pathSubtract, pathToAnchors, pathUnion, pickTopMostHit, pinchZoomAction, planPixelRender, pointInRotatedRect, pointInTextPose, poseRotationOf, pressureToWidth, rainbowVertexColors, rebaseLocalPose, rectCorners, registerContentHandler, registerNodeShape, registerProgram, renderLabel, renderSceneToCanvas, renderSceneToPixels, resizeAction, resolveColor, resolveDeviceProfile, resolveFillPattern, resolvePatternSpec, resolveRuns, resolveTextStyle, resolveVisibility, rgbaToHex, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatedRectCorners, rotationDegreesUnit, rotationHandle, roundToCell, runsToDom, runsToMarkdown, runsToPlainText, sampleGradientStops, sceneFromJSON, sceneNodeClientRect, sceneToAdapter, scopeBindings, screenToWorld, selectFromLasso, selectionAtLeast, selectionEmpty, selectionIs, setFlagOverRange, shapeCoversPoint, sliceAction, snapPoint, solidVertexColors, specificity, spiro, splitPathByLine, splitSubpaths, springPose, springVertexColors, srgbU8ToOklab, staggerVertexColors, startThresholdDrag, styleAtRange, subscribeImageReady, tessellate, tessellateStroke, textCommand, textLineBoxes, tileGrid, toHex8, toRuns, translatePoseViaDescriptor, translateRectPose, tweenPose, tweenVertexColors, unionBounds, unionBoundsPath, useActiveToolContext, useAlign, useAnimator, useArrayAdapter, useAutoCenter, useBooleans, useBooleansAdapter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEllipseTool, useEyedropperTool, useGestureDispatcher, useGridCellHover, useGuides, useHandTool, useHandleDrag, useHoverTracking, useImageTool, useKeybindings, useLassoTool, useLineTool, useOptionalActiveToolContext, usePenTool, usePencilTool, usePinchGesture, usePinchZoomTool, usePointerStylus, usePolygonTool, usePublishSelection, useRectTool, useResizePolicy, useRotateTool, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelection, useSelectionContext, useSimulation, useSliceDep, useStandardActions, useStarTool, useTextEdit, useTextTool, useTools, useVelocityTracker, useViewAnimation, useViewTween, useZoom, verticalAlignOffset, viewToMat3, viewToTransform, viewportDragPanAction, viewportZoomAction, viewportsAt, when, withAlpha01, withCoord, withGradientKind, worldEditToStorage, worldPoseLookup, worldToScreen, zoomAt, zoomAtLeast };
|
|
28313
|
+
//# sourceMappingURL=chunk-PI56ORHE.js.map
|
|
28314
|
+
//# sourceMappingURL=chunk-PI56ORHE.js.map
|