@weasel-js/stroke 1.9.4 → 1.10.1
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/README.md +1 -1
- package/dist/{chunk-HZ37OTXN.js → chunk-FQB7N6YD.js} +2 -2
- package/dist/{chunk-HZ37OTXN.js.map → chunk-FQB7N6YD.js.map} +1 -1
- package/dist/index.d.ts +37 -5
- package/dist/index.js +43 -15
- package/dist/index.js.map +1 -1
- package/dist/{test-seams-YByeMj7r.d.ts → test-seams-D-zMT-bn.d.ts} +2 -2
- package/dist/test-seams.d.ts +1 -1
- package/dist/test-seams.js +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ cap it, and the region its ink covers as a path.
|
|
|
5
5
|
|
|
6
6
|
Part of [weasel](https://github.com/orochi235/weasel), a domain-agnostic 2D
|
|
7
7
|
scene-graph canvas kit for React. See the
|
|
8
|
-
[API reference](https://orochi235.github.io/weasel/
|
|
8
|
+
[API reference](https://orochi235.github.io/weasel/#pkg/stroke).
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
11
|
npm install @weasel-js/stroke
|
|
@@ -104,5 +104,5 @@ function _resetMarkersForTests() {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
export { BUILTIN_MARKERS, _resetMarkersForTests, getMarker, listMarkers, markerGeneration, markerRegistry, registerMarker };
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
107
|
+
//# sourceMappingURL=chunk-FQB7N6YD.js.map
|
|
108
|
+
//# sourceMappingURL=chunk-FQB7N6YD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/strokeMarkerShapes.ts","../src/strokeMarkers.ts"],"names":[],"mappings":"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","file":"chunk-HZ37OTXN.js","sourcesContent":["/**\n * The kit's built-in stroke-marker vocabulary.\n *\n * Every entry is authored with its anchor at the origin and pointing +X, so\n * the line arrives from -X and no geometry sits at positive X. Coordinates are\n * in units of `MarkerCtx.size`, which defaults to the resolved stroke width —\n * one definition is therefore correct at any line weight.\n *\n * Not to be confused with `features/paths/markers.ts`, which builds\n * decorative chrome shapes and is unrelated.\n */\n\nimport { PATH_M, PATH_L, PATH_Z, type PolygonPath } from '@weasel-js/geom';\nimport type { MarkerCtx, MarkerEntry } from './strokeMarkers';\n\nfunction poly(pts: readonly number[], size: number, close = true): PolygonPath {\n const n = pts.length / 2;\n const commands = new Uint8Array(close ? n + 1 : n);\n commands[0] = PATH_M;\n for (let i = 1; i < n; i++) commands[i] = PATH_L;\n if (close) commands[n] = PATH_Z;\n const coords = new Float32Array(pts.length);\n for (let i = 0; i < pts.length; i++) coords[i] = pts[i] * size;\n return { kind: 'polygon', commands, coords, fillRule: 'nonzero' };\n}\n\n/** Circle of radius `r` centred at `cx`, in marker units. */\nfunction circle(cx: number, r: number, size: number, segments = 32): PolygonPath {\n const pts: number[] = [];\n for (let i = 0; i < segments; i++) {\n const theta = (i / segments) * Math.PI * 2;\n pts.push(cx + r * Math.cos(theta), r * Math.sin(theta));\n }\n return poly(pts, size);\n}\n\n/** The markers the registry is seeded with: `arrow`, `arrow-open`,\n * `arrow-concave`, `diamond`, `diamond-hollow`, `circle`, `square` and `bar`. */\nexport const BUILTIN_MARKERS: readonly MarkerEntry[] = [\n {\n id: 'arrow',\n reads: [],\n inset: 3,\n path: ({ size }: MarkerCtx) => poly([0, 0, -3, -1.5, -3, 1.5], size),\n },\n {\n id: 'arrow-open',\n reads: [],\n inset: 0,\n fill: 'none',\n outline: { width: 1 },\n // Open at the back, so the ribbon runs to the vertex and the arms meet it.\n // Arms 3.5 long at ±35°: the back opening is 4 units against 2 units of\n // arm, so the V still reads open. Shorter or narrower and the two arms\n // close the gap themselves and it paints as a solid triangle.\n path: ({ size }: MarkerCtx) =>\n poly([-2.867, -2.007, 0, 0, -2.867, 2.007], size, false),\n },\n {\n id: 'arrow-concave',\n reads: [],\n inset: 3,\n path: ({ size }: MarkerCtx) => poly([0, 0, -3, -1.5, -2, 0, -3, 1.5], size),\n },\n {\n id: 'diamond',\n reads: [],\n inset: 4,\n path: ({ size }: MarkerCtx) => poly([0, 0, -2, -1.2, -4, 0, -2, 1.2], size),\n },\n {\n id: 'diamond-hollow',\n reads: [],\n inset: 4,\n fill: 'none',\n outline: { width: 0.5 },\n path: ({ size }: MarkerCtx) => poly([0, 0, -2, -1.2, -4, 0, -2, 1.2], size),\n },\n {\n id: 'circle',\n reads: [],\n inset: 2,\n path: ({ size }: MarkerCtx) => circle(-1, 1, size),\n },\n {\n id: 'square',\n reads: [],\n inset: 2,\n path: ({ size }: MarkerCtx) => poly([0, -1, 0, 1, -2, 1, -2, -1], size),\n },\n {\n id: 'bar',\n reads: [],\n inset: 0,\n fill: 'none',\n outline: { width: 1 },\n path: ({ size }: MarkerCtx) => poly([0, -1.5, 0, 1.5], size, false),\n },\n];\n","/**\n * The stroke-marker registry — arrowheads and other line terminators.\n *\n * Keyed by string, because a key is what sits in `stroke.markerEnd`. That is\n * the difference from `registerNodeShape`, which resolves by first-matching\n * predicate and whose `id` is only a label.\n *\n * A built-in's SVG slot lives in `@weasel-js/svg` and cannot be imported here\n * without inverting a package dependency, so an entry carries `toSvg` for that\n * package to consume — the same split `PaintKindEntry` uses.\n */\n\nimport type { FillStyle, MarkerKey, Stroke } from '@weasel-js/paint';\nimport type { Path } from '@weasel-js/geom';\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\nimport { BUILTIN_MARKERS } from './strokeMarkerShapes';\n\n/** What an entry's `path` is given. Entries that ignore it may return a\n * constant path. */\nexport interface MarkerCtx {\n /** One geometry unit, in the same world units the ribbon is tessellated in.\n * Defaults to the resolved stroke width. */\n readonly size: number;\n /** The stroke this marker belongs to, already width-resolved. */\n readonly stroke: Stroke;\n}\n\n/** `'line'` means the stroke's own paint — SVG 2's `context-stroke`, as the\n * default rather than an opt-in. */\nexport type MarkerPaint = FillStyle | 'line' | 'none';\n\n/** A stroke-marker registry entry: a terminator's geometry, paint and inset. */\nexport interface MarkerEntry {\n /** `'kit:'`-free for built-ins so the key matches the SVG attribute value;\n * consumers should prefix (`'app-my-head'`). A key becomes the `id` of the\n * emitted `<marker>` def, so it must be a valid XML name — no colons. */\n id: MarkerKey;\n /** Geometry with its anchor at the origin, pointing +X, in units of\n * `ctx.size`. An arbitrary anchor is expressed by where the geometry is\n * drawn, which is why there is no `refX`/`refY`. */\n path(ctx: MarkerCtx): Path;\n /** Default `'line'`. */\n fill?: MarkerPaint;\n /** Outline width is in the same units as `path`. `false` (the default)\n * means no outline. */\n outline?: { width: number; paint?: MarkerPaint } | false;\n /** How far back along the line the stroke stops, in units of `ctx.size`.\n * Default 0. A property of the shape, not a setting on the stroke: an open\n * V needs 0 or its arms stop meeting the line. */\n inset?: number;\n /** `'auto'` (default) follows the line; a number is a fixed angle in\n * radians, ignoring the line — SVG's `orient=\"<angle>\"`. */\n orient?: 'auto' | number;\n /** The stroke fields `path` reads besides `ctx.size` — `[]` for a shape\n * drawn from size alone. Declared, a head is reused across stroke objects\n * whose listed fields are equal; omitted, only across frames that pass the\n * same stroke object, since `path` might read any of it. */\n reads?: readonly (keyof Stroke)[];\n /** Emits the `<marker>` def. Consumed by `@weasel-js/svg`. */\n toSvg?(id: string, entry: MarkerEntry): string;\n}\n\nconst MARKERS = createReflectable<MarkerEntry>();\n\nfunction seedBuiltins(): void {\n for (const entry of BUILTIN_MARKERS) MARKERS.push(entry.id, entry, { source: 'kit' });\n}\nseedBuiltins();\n\n/** Every registered marker, with the overrides each displaced. */\nexport const markerRegistry: Reflection<MarkerEntry> = MARKERS.reflection;\n\n/** Bumped whenever the registered set changes, for caches of marker geometry. */\nexport function markerGeneration(): number {\n return MARKERS.getVersion();\n}\n\n/** Register a marker. Returns a disposer. Re-registering an existing id is an\n * override; disposing it uncovers whatever it displaced rather than deleting the key. */\nexport function registerMarker(entry: MarkerEntry): () => void {\n return MARKERS.push(entry.id, entry);\n}\n\n/** The entry for `key`, or `undefined`. */\nexport function getMarker(key: string | undefined): MarkerEntry | undefined {\n return key === undefined ? undefined : MARKERS.get(key);\n}\n\n/** Every registered marker, built-ins first, in registration order. */\nexport function listMarkers(): readonly MarkerEntry[] {\n return MARKERS.entries().map((e) => e.value);\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetMarkersForTests(): void {\n MARKERS.clear();\n seedBuiltins();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/strokeMarkerShapes.ts","../src/strokeMarkers.ts"],"names":[],"mappings":"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","file":"chunk-FQB7N6YD.js","sourcesContent":["/**\n * The kit's built-in stroke-marker vocabulary.\n *\n * Every entry is authored with its anchor at the origin and pointing +X, so\n * the line arrives from -X and no geometry sits at positive X. Coordinates are\n * in units of `MarkerCtx.size`, which defaults to the resolved stroke width —\n * one definition is therefore correct at any line weight.\n *\n * Not to be confused with `features/paths/markers.ts`, which builds\n * decorative chrome shapes and is unrelated.\n */\n\nimport { PATH_M, PATH_L, PATH_Z, type PolygonPath } from '@weasel-js/geom';\nimport type { MarkerCtx, MarkerEntry } from './strokeMarkers';\n\nfunction poly(pts: readonly number[], size: number, close = true): PolygonPath {\n const n = pts.length / 2;\n const commands = new Uint8Array(close ? n + 1 : n);\n commands[0] = PATH_M;\n for (let i = 1; i < n; i++) commands[i] = PATH_L;\n if (close) commands[n] = PATH_Z;\n const coords = new Float32Array(pts.length);\n for (let i = 0; i < pts.length; i++) coords[i] = pts[i] * size;\n return { kind: 'polygon', commands, coords, fillRule: 'nonzero' };\n}\n\n/** Circle of radius `r` centred at `cx`, in marker units. */\nfunction circle(cx: number, r: number, size: number, segments = 32): PolygonPath {\n const pts: number[] = [];\n for (let i = 0; i < segments; i++) {\n const theta = (i / segments) * Math.PI * 2;\n pts.push(cx + r * Math.cos(theta), r * Math.sin(theta));\n }\n return poly(pts, size);\n}\n\n/** The markers the registry is seeded with: `arrow`, `arrow-open`,\n * `arrow-concave`, `diamond`, `diamond-hollow`, `circle`, `square` and `bar`. */\nexport const BUILTIN_MARKERS: readonly MarkerEntry[] = [\n {\n id: 'arrow',\n reads: [],\n inset: 3,\n path: ({ size }: MarkerCtx) => poly([0, 0, -3, -1.5, -3, 1.5], size),\n },\n {\n id: 'arrow-open',\n reads: [],\n inset: 0,\n fill: 'none',\n outline: { width: 1 },\n // Open at the back, so the ribbon runs to the vertex and the arms meet it.\n // Arms 3.5 long at ±35°: the back opening is 4 units against 2 units of\n // arm, so the V still reads open. Shorter or narrower and the two arms\n // close the gap themselves and it paints as a solid triangle.\n path: ({ size }: MarkerCtx) =>\n poly([-2.867, -2.007, 0, 0, -2.867, 2.007], size, false),\n },\n {\n id: 'arrow-concave',\n reads: [],\n inset: 3,\n path: ({ size }: MarkerCtx) => poly([0, 0, -3, -1.5, -2, 0, -3, 1.5], size),\n },\n {\n id: 'diamond',\n reads: [],\n inset: 4,\n path: ({ size }: MarkerCtx) => poly([0, 0, -2, -1.2, -4, 0, -2, 1.2], size),\n },\n {\n id: 'diamond-hollow',\n reads: [],\n inset: 4,\n fill: 'none',\n outline: { width: 0.5 },\n path: ({ size }: MarkerCtx) => poly([0, 0, -2, -1.2, -4, 0, -2, 1.2], size),\n },\n {\n id: 'circle',\n reads: [],\n inset: 2,\n path: ({ size }: MarkerCtx) => circle(-1, 1, size),\n },\n {\n id: 'square',\n reads: [],\n inset: 2,\n path: ({ size }: MarkerCtx) => poly([0, -1, 0, 1, -2, 1, -2, -1], size),\n },\n {\n id: 'bar',\n reads: [],\n inset: 0,\n fill: 'none',\n outline: { width: 1 },\n path: ({ size }: MarkerCtx) => poly([0, -1.5, 0, 1.5], size, false),\n },\n];\n","/**\n * The stroke-marker registry — arrowheads and other line terminators.\n *\n * Keyed by string, because a key is what sits in `stroke.markerEnd`. That is\n * the difference from `registerNodeShape`, which resolves by first-matching\n * predicate and whose `id` is only a label.\n *\n * A built-in's SVG slot lives in `@weasel-js/svg` and cannot be imported here\n * without inverting a package dependency, so an entry carries `toSvg` for that\n * package to consume — the same split `PaintKindEntry` uses.\n */\n\nimport type { Paint, MarkerKey, Stroke } from '@weasel-js/paint';\nimport type { Path } from '@weasel-js/geom';\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\nimport { BUILTIN_MARKERS } from './strokeMarkerShapes';\n\n/** What an entry's `path` is given. Entries that ignore it may return a\n * constant path. */\nexport interface MarkerCtx {\n /** One geometry unit, in the same world units the ribbon is tessellated in.\n * Defaults to the resolved stroke width. */\n readonly size: number;\n /** The stroke this marker belongs to, already width-resolved. */\n readonly stroke: Stroke;\n}\n\n/** `'line'` means the stroke's own paint — SVG 2's `context-stroke`, as the\n * default rather than an opt-in. */\nexport type MarkerPaint = Paint | 'line' | 'none';\n\n/** A stroke-marker registry entry: a terminator's geometry, paint and inset. */\nexport interface MarkerEntry {\n /** `'kit:'`-free for built-ins so the key matches the SVG attribute value;\n * consumers should prefix (`'app-my-head'`). A key becomes the `id` of the\n * emitted `<marker>` def, so it must be a valid XML name — no colons. */\n id: MarkerKey;\n /** Geometry with its anchor at the origin, pointing +X, in units of\n * `ctx.size`. An arbitrary anchor is expressed by where the geometry is\n * drawn, which is why there is no `refX`/`refY`. */\n path(ctx: MarkerCtx): Path;\n /** Default `'line'`. */\n fill?: MarkerPaint;\n /** Outline width is in the same units as `path`. `false` (the default)\n * means no outline. */\n outline?: { width: number; paint?: MarkerPaint } | false;\n /** How far back along the line the stroke stops, in units of `ctx.size`.\n * Default 0. A property of the shape, not a setting on the stroke: an open\n * V needs 0 or its arms stop meeting the line. */\n inset?: number;\n /** `'auto'` (default) follows the line; a number is a fixed angle in\n * radians, ignoring the line — SVG's `orient=\"<angle>\"`. */\n orient?: 'auto' | number;\n /** The stroke fields `path` reads besides `ctx.size` — `[]` for a shape\n * drawn from size alone. Declared, a head is reused across stroke objects\n * whose listed fields are equal; omitted, only across frames that pass the\n * same stroke object, since `path` might read any of it. */\n reads?: readonly (keyof Stroke)[];\n /** Emits the `<marker>` def. Consumed by `@weasel-js/svg`. */\n toSvg?(id: string, entry: MarkerEntry): string;\n}\n\nconst MARKERS = createReflectable<MarkerEntry>();\n\nfunction seedBuiltins(): void {\n for (const entry of BUILTIN_MARKERS) MARKERS.push(entry.id, entry, { source: 'kit' });\n}\nseedBuiltins();\n\n/** Every registered marker, with the overrides each displaced. */\nexport const markerRegistry: Reflection<MarkerEntry> = MARKERS.reflection;\n\n/** Bumped whenever the registered set changes, for caches of marker geometry. */\nexport function markerGeneration(): number {\n return MARKERS.getVersion();\n}\n\n/** Register a marker. Returns a disposer. Re-registering an existing id is an\n * override; disposing it uncovers whatever it displaced rather than deleting the key. */\nexport function registerMarker(entry: MarkerEntry): () => void {\n return MARKERS.push(entry.id, entry);\n}\n\n/** The entry for `key`, or `undefined`. */\nexport function getMarker(key: string | undefined): MarkerEntry | undefined {\n return key === undefined ? undefined : MARKERS.get(key);\n}\n\n/** Every registered marker, built-ins first, in registration order. */\nexport function listMarkers(): readonly MarkerEntry[] {\n return MARKERS.entries().map((e) => e.value);\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetMarkersForTests(): void {\n MARKERS.clear();\n seedBuiltins();\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Path, PolygonPath } from '@weasel-js/geom';
|
|
1
|
+
import { Path, PolygonPath, Affine } from '@weasel-js/geom';
|
|
2
2
|
import { ScreenLength, Stroke, MarkerRef } from '@weasel-js/paint';
|
|
3
3
|
import { Polyline, Mesh } from '@weasel-js/geom/tessellate';
|
|
4
|
-
import { M as MarkerEntry } from './test-seams-
|
|
5
|
-
export { a as MarkerCtx, b as MarkerPaint, g as getMarker, l as listMarkers, m as markerGeneration, c as markerRegistry, r as registerMarker } from './test-seams-
|
|
4
|
+
import { M as MarkerEntry } from './test-seams-D-zMT-bn.js';
|
|
5
|
+
export { a as MarkerCtx, b as MarkerPaint, g as getMarker, l as listMarkers, m as markerGeneration, c as markerRegistry, r as registerMarker } from './test-seams-D-zMT-bn.js';
|
|
6
6
|
import '@weasel-js/registry';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -310,13 +310,45 @@ interface StrokeToPathOptions {
|
|
|
310
310
|
scale?: number;
|
|
311
311
|
/** Flatness tolerance for curves, in the path's units. */
|
|
312
312
|
flattenTolerance?: number;
|
|
313
|
+
/**
|
|
314
|
+
* The frame the stroke is drawn in, as the matrix taking that frame to the
|
|
315
|
+
* path's coordinates: a node's `poseFrameOf`. A frame that skews or
|
|
316
|
+
* stretches does the same to the stroke, as it does on the canvas. For a
|
|
317
|
+
* `{ px }` width under a view that scales each axis apart, the frame is the
|
|
318
|
+
* screen: the inverse of the view's scale, with `scale` left at 1.
|
|
319
|
+
*/
|
|
320
|
+
frame?: Affine;
|
|
313
321
|
}
|
|
314
322
|
/**
|
|
315
323
|
* The region `stroke` covers when drawn along `path`, as a path to fill:
|
|
316
324
|
* width, cap, join, miter limit, dash, alignment, per-vertex widths, and
|
|
317
325
|
* marker heads all included. Curves are flattened, so the result holds only
|
|
318
|
-
* M/L/Z. A stroke with no width answers an empty path
|
|
326
|
+
* M/L/Z. A stroke with no width answers an empty path, and so does one drawn
|
|
327
|
+
* in a `frame` that flattens it.
|
|
319
328
|
*/
|
|
320
329
|
declare function strokeToPath(path: Path, stroke: Stroke, opts?: StrokeToPathOptions): PolygonPath;
|
|
321
330
|
|
|
322
|
-
|
|
331
|
+
/** Options for {@link offsetPath}. */
|
|
332
|
+
interface OffsetPathOptions {
|
|
333
|
+
/** How the offset outline turns a corner. Default `'miter'`. */
|
|
334
|
+
join?: 'miter' | 'round' | 'bevel';
|
|
335
|
+
/** Past this ratio of miter length to distance a miter corner is beveled.
|
|
336
|
+
* Default 4. */
|
|
337
|
+
miterLimit?: number;
|
|
338
|
+
/** How closely curves are followed, in the path's units. Default 0.1. */
|
|
339
|
+
tolerance?: number;
|
|
340
|
+
/** Refit the outline's flattened curves as cubics (`simplifyPath` at
|
|
341
|
+
* `tolerance`). Default true; false leaves a polygon. */
|
|
342
|
+
refit?: boolean;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* The outline of the region `path` fills, grown by `distance` (shrunk by a
|
|
346
|
+
* negative one), as a path to fill. Every subpath counts as closed. The
|
|
347
|
+
* outline is where a stroke of twice `distance` centered on the path has its
|
|
348
|
+
* outer (or inner) edge, so it takes that stroke's joins; overlaps resolve
|
|
349
|
+
* the way a union does, and a region shrunk past its own width is gone.
|
|
350
|
+
* Returns an empty path when nothing is left.
|
|
351
|
+
*/
|
|
352
|
+
declare function offsetPath(path: Path, distance: number, opts?: OffsetPathOptions): PolygonPath;
|
|
353
|
+
|
|
354
|
+
export { BUILTIN_MARKERS, type InsetLength, MarkerEntry, type MarkerHead, type MarkerSite, type MarkerSiteRequest, type MeasuredLength, type OffsetPathOptions, type ScreenSpace, type StrokeMetric, type StrokeOptions, type StrokeSpaces, type StrokeToPathOptions, type WidthScale, coordsOutOfMetric, markerHeads, markerInset, markerKeyOf, markerReach, markerReadsKey, markerSites, metricKeepsRects, metricKey, offsetPath, polylineIntoMetric, polylineOutOfMetric, populatePolylineWidths, rectIntoMetric, resolveMarkerSize, resolveStrokeWidth, sameMetric, screenSpaceKey, splitForDash, strokeInsets, strokeSpaceOf, strokeToPath, tessellateStroke, trimInSpace, worldWidthInMetric, worldWidthInMetricAlongWorld };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getMarker } from './chunk-
|
|
2
|
-
export { BUILTIN_MARKERS, getMarker, listMarkers, markerGeneration, markerRegistry, registerMarker } from './chunk-
|
|
1
|
+
import { getMarker } from './chunk-FQB7N6YD.js';
|
|
2
|
+
export { BUILTIN_MARKERS, getMarker, listMarkers, markerGeneration, markerRegistry, registerMarker } from './chunk-FQB7N6YD.js';
|
|
3
3
|
import { resolveScreenLength, alignedStrokeRect } from '@weasel-js/paint';
|
|
4
4
|
import { trimPolyline, extractPolylines } from '@weasel-js/geom/tessellate';
|
|
5
|
-
import { boundsOfPath } from '@weasel-js/geom';
|
|
5
|
+
import { invert, transformPath, simplifyPath, anchorsToPath, pathToAnchors, DEFAULT_FLATTEN_TOLERANCE, boundsOfPath } from '@weasel-js/geom';
|
|
6
6
|
import { trianglesToPath, pathIntersect, pathSubtract, pathUnion } from '@weasel-js/geom/booleans';
|
|
7
7
|
|
|
8
8
|
// src/tessellate/dash.ts
|
|
@@ -149,6 +149,13 @@ function joinAtSeam(tail, head) {
|
|
|
149
149
|
anchorT: Float32Array.from([...tail.anchorT, ...head.anchorT.subarray(1)])
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
|
+
var STROKE_MAX_TURN = Math.PI / 18;
|
|
153
|
+
function strokeFlattening(flattenTolerance, width, vertexWidths) {
|
|
154
|
+
const tolerance = flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;
|
|
155
|
+
let widest = width;
|
|
156
|
+
if (vertexWidths) for (const w of vertexWidths) widest = Math.max(widest, w);
|
|
157
|
+
return widest / 2 > tolerance ? { flattenTolerance, maxTurn: STROKE_MAX_TURN } : { flattenTolerance };
|
|
158
|
+
}
|
|
152
159
|
|
|
153
160
|
// src/tessellate/vertexWidths.ts
|
|
154
161
|
function populatePolylineWidths(pl, vertexWidths, fallbackWidth, scale) {
|
|
@@ -313,17 +320,10 @@ function tessellateStroke(path, stroke, opts = {}) {
|
|
|
313
320
|
const rectInMetric = metric && path.kind === "rect" ? rectIntoMetric(path, metric) : null;
|
|
314
321
|
let workingPath = rectInMetric ?? path;
|
|
315
322
|
if (workingPath.kind === "rect" && align !== "center") {
|
|
316
|
-
|
|
317
|
-
workingPath = {
|
|
318
|
-
kind: "rect",
|
|
319
|
-
x: aligned.x,
|
|
320
|
-
y: aligned.y,
|
|
321
|
-
width: aligned.width,
|
|
322
|
-
height: aligned.height
|
|
323
|
-
};
|
|
323
|
+
workingPath = { kind: "rect", ...alignedStrokeRect(workingPath, align, width) };
|
|
324
324
|
}
|
|
325
|
-
const polylines = extractPolylines(workingPath, opts);
|
|
326
325
|
const vertexWidths = stroke.vertexWidths && stroke.vertexWidths.length > 0 ? stroke.vertexWidths : null;
|
|
326
|
+
const polylines = extractPolylines(workingPath, strokeFlattening(opts.flattenTolerance, width, vertexWidths ?? void 0));
|
|
327
327
|
const scale = !metric ? void 0 : rectInMetric ? (tx, ty) => worldWidthInMetric(metric, tx, ty) : (ux, uy) => worldWidthInMetricAlongWorld(metric, ux, uy);
|
|
328
328
|
const dash = stroke.dash ?? [];
|
|
329
329
|
const verts = [];
|
|
@@ -704,7 +704,7 @@ function placed(path, site) {
|
|
|
704
704
|
coords[i] = site.x + x * cos - y * sin;
|
|
705
705
|
coords[i + 1] = site.y + x * sin + y * cos;
|
|
706
706
|
}
|
|
707
|
-
return {
|
|
707
|
+
return { ...src, coords };
|
|
708
708
|
}
|
|
709
709
|
function markerHeads(path, stroke, strokeWidth, flattenTolerance, spaces = {}) {
|
|
710
710
|
const refs = { start: stroke.markerStart, mid: stroke.markerMid, end: stroke.markerEnd };
|
|
@@ -718,7 +718,7 @@ function markerHeads(path, stroke, strokeWidth, flattenTolerance, spaces = {}) {
|
|
|
718
718
|
want[role] = true;
|
|
719
719
|
}
|
|
720
720
|
const out = [];
|
|
721
|
-
for (const pl of extractPolylines(path,
|
|
721
|
+
for (const pl of extractPolylines(path, strokeFlattening(flattenTolerance, strokeWidth, stroke.vertexWidths))) {
|
|
722
722
|
for (const [space, want] of groups) {
|
|
723
723
|
const inSpace = space ? { ...pl, points: pl.points.slice() } : pl;
|
|
724
724
|
if (space) polylineIntoMetric(inSpace, space.metric);
|
|
@@ -789,6 +789,13 @@ var EMPTY = {
|
|
|
789
789
|
fillRule: "nonzero"
|
|
790
790
|
};
|
|
791
791
|
function strokeToPath(path, stroke, opts = {}) {
|
|
792
|
+
const { frame, ...drawn } = opts;
|
|
793
|
+
if (!frame) return outlineOf(path, stroke, drawn);
|
|
794
|
+
const back = invert(frame);
|
|
795
|
+
if (!back) return EMPTY;
|
|
796
|
+
return transformPath(outlineOf(transformPath(path, back), stroke, drawn), frame);
|
|
797
|
+
}
|
|
798
|
+
function outlineOf(path, stroke, opts) {
|
|
792
799
|
const width = resolveStrokeWidth(stroke.width ?? 1, opts.scale ?? 1);
|
|
793
800
|
if (!(width > 0)) return EMPTY;
|
|
794
801
|
const tolerance = opts.flattenTolerance;
|
|
@@ -813,7 +820,28 @@ function strokeToPath(path, stroke, opts = {}) {
|
|
|
813
820
|
}
|
|
814
821
|
return heads.length === 0 ? ribbon : pathUnion(ribbon, ...heads);
|
|
815
822
|
}
|
|
823
|
+
function offsetPath(path, distance, opts = {}) {
|
|
824
|
+
const region = closedRegion(path);
|
|
825
|
+
if (distance === 0) return region;
|
|
826
|
+
const tolerance = opts.tolerance ?? 0.1;
|
|
827
|
+
const band = strokeToPath(region, {
|
|
828
|
+
width: Math.abs(distance) * 2,
|
|
829
|
+
join: opts.join ?? "miter",
|
|
830
|
+
miterLimit: opts.miterLimit ?? 4
|
|
831
|
+
}, { flattenTolerance: tolerance });
|
|
832
|
+
const grown = distance > 0 ? pathUnion(region, band) : pathSubtract(region, band);
|
|
833
|
+
return opts.refit === false || grown.commands.length === 0 ? grown : simplifyPath(grown, tolerance);
|
|
834
|
+
}
|
|
835
|
+
function closedRegion(path) {
|
|
836
|
+
if (path.kind === "rect") {
|
|
837
|
+
const { x, y, width: w, height: h } = path;
|
|
838
|
+
return anchorsToPath([[{ x, y }, { x: x + w, y }, { x: x + w, y: y + h }, { x, y: y + h }]], [true]);
|
|
839
|
+
}
|
|
840
|
+
const { anchors, closed } = pathToAnchors(path);
|
|
841
|
+
if (closed.every(Boolean)) return path;
|
|
842
|
+
return anchorsToPath(anchors, closed.map(() => true), path);
|
|
843
|
+
}
|
|
816
844
|
|
|
817
|
-
export { coordsOutOfMetric, markerHeads, markerInset, markerKeyOf, markerReach, markerReadsKey, markerSites, metricKeepsRects, metricKey, polylineIntoMetric, polylineOutOfMetric, populatePolylineWidths, rectIntoMetric, resolveMarkerSize, resolveStrokeWidth, sameMetric, screenSpaceKey, splitForDash, strokeInsets, strokeSpaceOf, strokeToPath, tessellateStroke, trimInSpace, worldWidthInMetric, worldWidthInMetricAlongWorld };
|
|
845
|
+
export { coordsOutOfMetric, markerHeads, markerInset, markerKeyOf, markerReach, markerReadsKey, markerSites, metricKeepsRects, metricKey, offsetPath, polylineIntoMetric, polylineOutOfMetric, populatePolylineWidths, rectIntoMetric, resolveMarkerSize, resolveStrokeWidth, sameMetric, screenSpaceKey, splitForDash, strokeInsets, strokeSpaceOf, strokeToPath, tessellateStroke, trimInSpace, worldWidthInMetric, worldWidthInMetricAlongWorld };
|
|
818
846
|
//# sourceMappingURL=index.js.map
|
|
819
847
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tessellate/dash.ts","../src/tessellate/vertexWidths.ts","../src/tessellate/metric.ts","../src/tessellate/insets.ts","../src/tessellate/stroke.ts","../src/markerInset.ts","../src/markerSites.ts","../src/markerHeads.ts","../src/strokeToPath.ts"],"names":["len","resolveScreenLength","extractPolylines","reach"],"mappings":"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","file":"index.js","sourcesContent":["import type { Polyline } from '@weasel-js/geom/tessellate';\n\n/**\n * Split a polyline into open sub-polylines for the \"on\" portions of a dash\n * pattern. Each output sub-polyline gets caps from the stroke's `cap` setting.\n * The \"off\" portions become invisible gaps. Anchor params are carried through:\n * sub-polyline endpoints inherit their source polyline-point's anchor params;\n * dash boundaries that land mid-segment (between two polyline points) snap\n * their anchor params to whichever endpoint they're closer to when the\n * segment crosses a path-anchor boundary, otherwise interpolate `t` linearly.\n */\nexport function splitForDash(pl: Polyline, dash: number[]): Polyline[] {\n const out: Polyline[] = [];\n const plA = pl.anchorA ?? new Uint32Array(pl.points.length / 2);\n const plB = pl.anchorB ?? new Uint32Array(pl.points.length / 2);\n const plT = pl.anchorT ?? new Float32Array(pl.points.length / 2);\n\n let dashIdx = 0;\n let dashRemaining = dash[0];\n let onPhase = true;\n let curPts: number[] | null = onPhase ? [pl.points[0], pl.points[1]] : null;\n let curA: number[] | null = onPhase ? [plA[0]] : null;\n let curB: number[] | null = onPhase ? [plB[0]] : null;\n let curT: number[] | null = onPhase ? [plT[0]] : null;\n\n const flushAndAdvance = () => {\n if (curPts && curPts.length >= 4) {\n out.push({\n points: curPts,\n closed: false,\n anchorA: new Uint32Array(curA!),\n anchorB: new Uint32Array(curB!),\n anchorT: new Float32Array(curT!),\n });\n }\n curPts = null; curA = null; curB = null; curT = null;\n dashIdx = (dashIdx + 1) % dash.length;\n dashRemaining = dash[dashIdx];\n onPhase = !onPhase;\n };\n\n let prevX = pl.points[0], prevY = pl.points[1];\n const ptCount = pl.points.length / 2;\n const segCount = pl.closed ? ptCount : ptCount - 1;\n\n for (let i = 0; i < segCount; i++) {\n const nextIdx = (i + 1) % ptCount;\n const cx = pl.points[nextIdx * 2], cy = pl.points[nextIdx * 2 + 1];\n const startA = plA[i], startB = plB[i], startT = plT[i];\n const endA = plA[nextIdx], endB = plB[nextIdx], endT = plT[nextIdx];\n const segFullDx = cx - prevX, segFullDy = cy - prevY;\n const segFullLen = Math.hypot(segFullDx, segFullDy);\n let segDx = segFullDx, segDy = segFullDy;\n let segLen = segFullLen;\n let traveled = 0;\n\n while (segLen > 1e-9) {\n if (segLen <= dashRemaining) {\n if (onPhase && curPts) {\n curPts.push(cx, cy);\n curA!.push(endA); curB!.push(endB); curT!.push(endT);\n }\n dashRemaining -= segLen;\n prevX = cx; prevY = cy;\n traveled = segFullLen;\n segLen = 0;\n if (dashRemaining <= 1e-9) {\n flushAndAdvance();\n if (onPhase) {\n curPts = [prevX, prevY];\n curA = [endA]; curB = [endB]; curT = [endT];\n }\n }\n } else {\n const tConsume = dashRemaining / segLen;\n const ix = prevX + segDx * tConsume;\n const iy = prevY + segDy * tConsume;\n traveled += dashRemaining;\n const frac = traveled / segFullLen;\n let mA: number, mB: number, mT: number;\n if (startA === endA && startB === endB) {\n mA = startA; mB = startB;\n mT = startT + (endT - startT) * frac;\n } else {\n // Cross-anchor segment: pick the nearer endpoint's params.\n if (frac < 0.5) { mA = startA; mB = startB; mT = startT; }\n else { mA = endA; mB = endB; mT = endT; }\n }\n if (onPhase && curPts) {\n curPts.push(ix, iy);\n curA!.push(mA); curB!.push(mB); curT!.push(mT);\n }\n prevX = ix; prevY = iy;\n segDx = cx - prevX; segDy = cy - prevY;\n segLen = Math.hypot(segDx, segDy);\n flushAndAdvance();\n if (onPhase) {\n curPts = [prevX, prevY];\n curA = [mA]; curB = [mB]; curT = [mT];\n }\n }\n }\n }\n\n if (curPts && curPts.length >= 4) {\n const tail: Polyline = {\n points: curPts,\n closed: false,\n anchorA: new Uint32Array(curA!),\n anchorB: new Uint32Array(curB!),\n anchorT: new Float32Array(curT!),\n };\n // A closed subpath's walk ends at the vertex it started from, so the run\n // still open there and the run that started there are one dash. Pushed\n // separately they are two butt-capped ribbons meeting at the seam — the\n // visible artifact whenever the pattern doesn't divide the perimeter.\n const tx = curPts[curPts.length - 2], ty = curPts[curPts.length - 1];\n const meets = (x: number, y: number) => Math.hypot(tx - x, ty - y) <= 1e-9;\n if (pl.closed && out.length > 0 && meets(out[0].points[0], out[0].points[1])) {\n out[0] = joinAtSeam(tail, out[0]);\n } else if (pl.closed && out.length === 0 && meets(curPts[0], curPts[1])) {\n // Every gap fell outside the perimeter: the dash is the whole loop, and\n // a loop stroked as an open run seams at its own start vertex too.\n out.push({\n points: curPts.slice(0, -2),\n closed: true,\n anchorA: tail.anchorA!.slice(0, -1),\n anchorB: tail.anchorB!.slice(0, -1),\n anchorT: tail.anchorT!.slice(0, -1),\n });\n } else {\n out.push(tail);\n }\n }\n return out;\n}\n\n/** `tail` continued by `head`, which starts where `tail` ends — the shared\n * vertex is carried once. */\nfunction joinAtSeam(tail: Polyline, head: Polyline): Polyline {\n return {\n points: [...tail.points, ...head.points.slice(2)],\n closed: false,\n anchorA: Uint32Array.from([...tail.anchorA!, ...head.anchorA!.subarray(1)]),\n anchorB: Uint32Array.from([...tail.anchorB!, ...head.anchorB!.subarray(1)]),\n anchorT: Float32Array.from([...tail.anchorT!, ...head.anchorT!.subarray(1)]),\n };\n}\n","import type { Polyline } from '@weasel-js/geom/tessellate';\n\n/** What one unit of a `vertexWidths` entry measures across the line at a\n * point whose unit tangent, in the polyline's own space, is `(tx, ty)`. */\nexport type WidthScale = (tx: number, ty: number) => number;\n\n/** Fill `pl.widths` by interpolating `vertexWidths` across each point's\n * (anchorA, anchorB, anchorT). Anchor-aligned points (A === B) read the\n * anchor's value directly. Out-of-range / non-finite anchor entries fall\n * back to `fallbackWidth`. Given `scale`, each entry is scaled at the point\n * that reads it, and the fallback is not. */\nexport function populatePolylineWidths(\n pl: Polyline,\n vertexWidths: number[],\n fallbackWidth: number,\n scale?: WidthScale,\n): void {\n const ptCount = pl.points.length / 2;\n if (ptCount === 0) return;\n const aA = pl.anchorA ?? new Uint32Array(ptCount);\n const aB = pl.anchorB ?? new Uint32Array(ptCount);\n const aT = pl.anchorT ?? new Float32Array(ptCount);\n const widths = new Float32Array(ptCount);\n let k = 1;\n const read = (i: number): number => {\n const v = vertexWidths[i];\n return typeof v === 'number' && isFinite(v) && v > 0 ? v * k : fallbackWidth;\n };\n for (let i = 0; i < ptCount; i++) {\n if (scale) k = scaleAt(pl, i, scale);\n const a = aA[i], b = aB[i], t = aT[i];\n if (a === b) {\n widths[i] = read(a);\n } else {\n const wa = read(a);\n const wb = read(b);\n widths[i] = wa + (wb - wa) * t;\n }\n }\n pl.widths = widths;\n}\n\n/** `scale` along the line's direction at point `i`: the bisector of the\n * segments either side, or the one segment at an open end. */\nfunction scaleAt(pl: Polyline, i: number, scale: WidthScale): number {\n const pts = pl.points;\n const n = pts.length / 2;\n let tx = 0, ty = 0;\n const add = (from: number, to: number) => {\n const dx = pts[to * 2] - pts[from * 2], dy = pts[to * 2 + 1] - pts[from * 2 + 1];\n const len = Math.hypot(dx, dy);\n if (len > 0) { tx += dx / len; ty += dy / len; }\n };\n if (i > 0) add(i - 1, i);\n else if (pl.closed && n > 1) add(n - 1, 0);\n if (i < n - 1) add(i, i + 1);\n else if (pl.closed && n > 1) add(n - 1, 0);\n const len = Math.hypot(tx, ty);\n return len > 0 ? scale(tx / len, ty / len) : 1;\n}\n","/**\n * The space a screen-pixel stroke is built in.\n *\n * A `{ px }` stroke is exact on screen only when its ribbon is offset in a\n * space that measures lengths the way the screen does. The transform's linear\n * part is `scale · R · P`: a uniform scale, a rotation (or reflection) that\n * moves no lengths, and `P`, the symmetric unit-determinant stretch left over.\n * Offsetting the ribbon after `P` and mapping it back through `P⁻¹` gives a\n * world-space mesh that the full transform turns into a ribbon of exactly\n * `width · scale` pixels in every direction — and keeps the mesh drawable by\n * every path that draws a world-space ribbon.\n *\n * `P` depends only on the lengths the transform induces (`LᵀL`), not on any\n * rotation applied after it, so a view that only pans or zooms uniformly keeps\n * the same metric and the ribbon cache keeps hitting.\n */\nimport type { Polyline } from '@weasel-js/geom/tessellate';\n\n/** `P` = [[p, q], [q, r]], with `pr − q² = 1`. */\nexport interface StrokeMetric {\n readonly p: number;\n readonly q: number;\n readonly r: number;\n}\n\n/** A space a screen-sized part of a stroke is built in: the metric, and how\n * many screen pixels one of its units is. */\nexport interface ScreenSpace {\n readonly metric: StrokeMetric;\n readonly pxPerUnit: number;\n}\n\n/**\n * Where each part of a stroke is built. An absent part is built in world:\n * everything is under a similarity, and otherwise a part whose size is a world\n * length. The ribbon is screen-sized for a `{ px }` width; a head for a\n * `{ px }` size, or for no size on a screen-sized ribbon, since it then takes\n * the stroke width.\n */\nexport interface StrokeSpaces {\n readonly ribbon?: ScreenSpace;\n readonly start?: ScreenSpace;\n readonly mid?: ScreenSpace;\n readonly end?: ScreenSpace;\n}\n\n/** A cache-key fragment naming `space`; empty for world. */\nexport function screenSpaceKey(space: ScreenSpace | undefined): string {\n return space === undefined ? '' : `${metricKey(space.metric)}@${space.pxPerUnit}`;\n}\n\n/** Below this, a stretch is a rounding error and the transform a similarity. */\nconst CONFORMAL_EPSILON = 1e-9;\n\n/**\n * Split the linear map `x' = a·x + c·y, y' = b·x + d·y` — a GL `mat3`'s\n * `m[0], m[1], m[3], m[4]` — into its geometric-mean scale and its stroke\n * metric. `metric` is `null` when the map is a similarity, where world space\n * already measures like the screen; `scale` is `0` for a singular map.\n */\nexport function strokeSpaceOf(\n a: number, b: number, c: number, d: number,\n): { scale: number; metric: StrokeMetric | null } {\n const det2 = Math.abs(a * d - b * c);\n const scale = Math.sqrt(det2);\n if (!(det2 > 0) || !Number.isFinite(det2)) return { scale: 0, metric: null };\n // G = LᵀL / det, whose determinant is 1, so √G = (G + I) / √(tr G + 2).\n const g11 = (a * a + b * b) / det2;\n const g12 = (a * c + b * d) / det2;\n const g22 = (c * c + d * d) / det2;\n const s = Math.sqrt(g11 + g22 + 2);\n const p = (g11 + 1) / s;\n const q = g12 / s;\n const r = (g22 + 1) / s;\n if (Math.abs(q) < CONFORMAL_EPSILON && Math.abs(p - r) < CONFORMAL_EPSILON) {\n return { scale, metric: null };\n }\n return { scale, metric: { p, q, r } };\n}\n\n/** A cache-key fragment naming `metric`; empty for none. */\nexport function metricKey(metric: StrokeMetric | undefined): string {\n return metric === undefined ? '' : `${metric.p},${metric.q},${metric.r}`;\n}\n\n/** Map `pl`'s points through `P`, in place. */\nexport function polylineIntoMetric(pl: Polyline, m: StrokeMetric): void {\n const pts = pl.points;\n for (let i = 0; i < pts.length; i += 2) {\n const x = pts[i], y = pts[i + 1];\n pts[i] = m.p * x + m.q * y;\n pts[i + 1] = m.q * x + m.r * y;\n }\n}\n\n/** Map `pl`'s points back out through `P⁻¹`, in place. */\nexport function polylineOutOfMetric(pl: Polyline, m: StrokeMetric): void {\n const pts = pl.points;\n for (let i = 0; i < pts.length; i += 2) {\n const x = pts[i], y = pts[i + 1];\n pts[i] = m.r * x - m.q * y;\n pts[i + 1] = m.p * y - m.q * x;\n }\n}\n\n/** Whether two spaces are the same — world being `null`. */\nexport function sameMetric(a: StrokeMetric | null, b: StrokeMetric | null): boolean {\n if (a === b) return true;\n return a !== null && b !== null && a.p === b.p && a.q === b.q && a.r === b.r;\n}\n\n/**\n * What one world unit of width, across a line running along the unit\n * direction `(tx, ty)` of the metric's own space, measures in that space.\n * `P` keeps areas, so a strip keeps its area while its length stretches by\n * `|P u|` (`u` the line's world direction): its width shrinks by the same,\n * and `1 / |P u|` is `|P⁻¹ t|`.\n */\nexport function worldWidthInMetric(m: StrokeMetric, tx: number, ty: number): number {\n return Math.hypot(m.r * tx - m.q * ty, m.p * ty - m.q * tx);\n}\n\n/** The same, for a line running along the unit world direction `(ux, uy)`. */\nexport function worldWidthInMetricAlongWorld(m: StrokeMetric, ux: number, uy: number): number {\n return 1 / Math.hypot(m.p * ux + m.q * uy, m.q * ux + m.r * uy);\n}\n\n/** Map interleaved x,y pairs back out through `P⁻¹` = [[r, −q], [−q, p]], in\n * place. */\nexport function coordsOutOfMetric(coords: Float32Array, m: StrokeMetric): void {\n for (let i = 0; i < coords.length; i += 2) {\n const x = coords[i], y = coords[i + 1];\n coords[i] = m.r * x - m.q * y;\n coords[i + 1] = m.p * y - m.q * x;\n }\n}\n\n/** Whether `P` takes an axis-aligned rect to another one. */\nexport function metricKeepsRects(m: StrokeMetric): boolean {\n return m.q === 0;\n}\n\n/** `rect` in the metric's space, while `P` keeps it axis-aligned; otherwise\n * `null`, and the rect has to be carried as a polygon. */\nexport function rectIntoMetric(\n rect: { x: number; y: number; width: number; height: number },\n m: StrokeMetric,\n): { kind: 'rect'; x: number; y: number; width: number; height: number } | null {\n if (!metricKeepsRects(m)) return null;\n return { kind: 'rect', x: m.p * rect.x, y: m.r * rect.y, width: m.p * rect.width, height: m.r * rect.height };\n}\n","/**\n * Trimming a stroke's ends where each inset is measured.\n *\n * A head stops the line by a length in the head's own space, which need not be\n * the ribbon's: a world-sized head on a `{ px }` stroke stops it a world\n * distance short, a `{ px }` head on a world-width stroke a screen distance.\n * Under a stretching view one length means different distances in the two\n * spaces depending on which way the line runs, so each end is trimmed in its\n * own space rather than converted.\n */\nimport { type Polyline, trimPolyline } from '@weasel-js/geom/tessellate';\nimport {\n type StrokeMetric, polylineIntoMetric, polylineOutOfMetric, sameMetric,\n} from './metric';\n\n/** A length along the line measured in `metric`'s space, or in world where\n * `metric` is `null`. */\nexport interface MeasuredLength {\n readonly length: number;\n readonly metric: StrokeMetric | null;\n}\n\n/** A plain number is a length in the ribbon's own space. */\nexport type InsetLength = number | MeasuredLength;\n\ninterface Trim {\n length: number;\n metric: StrokeMetric | null;\n}\n\nconst trimOf = (inset: InsetLength | undefined, ribbon: StrokeMetric | null): Trim =>\n inset === undefined ? { length: 0, metric: ribbon }\n : typeof inset === 'number' ? { length: inset, metric: ribbon }\n : inset;\n\n/**\n * `pl`, whose points are in `from`'s space, trimmed by `start` and `end` and\n * carried into `ribbon`'s — `null` for world in both. `pl` may be mapped in\n * place. Returns `null` when the insets consume the whole run.\n */\nexport function trimInSpace(\n pl: Polyline,\n from: StrokeMetric | null,\n ribbon: StrokeMetric | null,\n start: InsetLength | undefined,\n end: InsetLength | undefined,\n): Polyline | null {\n const s = trimOf(start, ribbon);\n const e = trimOf(end, ribbon);\n let cur: Polyline | null = pl;\n let space = from;\n const moveTo = (to: StrokeMetric | null) => {\n if (cur === null || sameMetric(space, to)) return;\n if (space !== null) polylineOutOfMetric(cur, space);\n if (to !== null) polylineIntoMetric(cur, to);\n space = to;\n };\n if (s.length > 0 || e.length > 0) {\n if (sameMetric(s.metric, e.metric)) {\n moveTo(s.metric);\n cur = trimPolyline(cur, s.length, e.length);\n } else {\n for (const [len, metric, atStart] of [[s.length, s.metric, true], [e.length, e.metric, false]] as const) {\n if (!(len > 0) || cur === null) continue;\n moveTo(metric);\n cur = trimPolyline(cur, atStart ? len : 0, atStart ? 0 : len);\n }\n }\n }\n moveTo(ribbon);\n return cur;\n}\n","import type { Path } from '@weasel-js/geom';\nimport type { ScreenLength, Stroke } from '@weasel-js/paint';\nimport { alignedStrokeRect, resolveScreenLength } from '@weasel-js/paint';\nimport { type Mesh, extractPolylines, type Polyline } from '@weasel-js/geom/tessellate';\nimport { splitForDash } from './dash';\nimport { populatePolylineWidths, type WidthScale } from './vertexWidths';\nimport { type InsetLength, trimInSpace } from './insets';\nimport {\n type StrokeMetric, coordsOutOfMetric, rectIntoMetric, worldWidthInMetric, worldWidthInMetricAlongWorld,\n} from './metric';\n\n/** Options for stroke tessellation. */\nexport interface StrokeOptions {\n flattenTolerance?: number;\n /**\n * Shorten each open subpath by this much at its start / end: a length in\n * the ribbon's space, or one measured in a space of its own. Stroke markers\n * use this so a filled head is not speared by its own line; the caller\n * resolves the distance, because this layer knows nothing about the marker\n * registry.\n */\n startInset?: InsetLength;\n endInset?: InsetLength;\n /**\n * Build the ribbon in this metric's space and map it back out, so the\n * transform it was derived from draws it at an exact screen width — see\n * `./metric`. Width and dash are then lengths in that space; `vertexWidths`\n * stay world widths. The path is flattened in world first, so the ribbon\n * follows the same vertices its fill does.\n */\n metric?: StrokeMetric;\n}\n\nconst EMPTY_MESH: Mesh = {\n vertices: new Float32Array(0),\n indices: new Uint32Array(0),\n anchorA: new Uint32Array(0),\n anchorB: new Uint32Array(0),\n anchorT: new Float32Array(0),\n};\n\ntype Cap = 'butt' | 'round' | 'square';\ntype Join = 'miter' | 'round' | 'bevel';\n\n/** Per-segment data the join code needs. */\ninterface Seg {\n ax: number; ay: number;\n bx: number; by: number;\n /** Unit perpendicular (rotated 90° CCW from direction). */\n nxUnit: number; nyUnit: number;\n /** Half-width at the start (a) and end (b) endpoints. Equal for uniform\n * strokes; differ when the polyline carries per-point widths. */\n halfA: number; halfB: number;\n len: number;\n}\n\n/** Resolve a stroke width to world units. A number is already world units;\n * `{ px }` is screen pixels divided by the accumulated scale, so it holds its\n * on-screen thickness as the view zooms. */\nexport function resolveStrokeWidth(width: ScreenLength, scale: number): number {\n return resolveScreenLength(width, scale);\n}\n\n/**\n * Build a triangle-mesh ribbon from a stroked Path.\n *\n * Supports:\n * - cap: 'butt' | 'round' | 'square'\n * - join: 'miter' | 'round' | 'bevel'\n * - center alignment directly; RectPath inner/outer alignment via a\n * pre-shifted rect; PolygonPath inner/outer alignment via stencil at the\n * renderer level\n * - dash splitting\n */\nexport function tessellateStroke(\n path: Path,\n stroke: Stroke,\n opts: StrokeOptions = {},\n): Mesh {\n // The renderer resolves `{ px }` against the accumulated transform before it\n // gets here; a stroke that reaches the tessellator unresolved is read at\n // scale 1, matching what the ribbon cache keys it under.\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n if (width <= 0) return EMPTY_MESH;\n const join: Join = stroke.join ?? 'miter';\n const cap: Cap = stroke.cap ?? 'butt';\n const align = stroke.align ?? 'center';\n const miterLimit = stroke.miterLimit ?? DEFAULT_MITER_LIMIT;\n const varyingThreshold = stroke.varyingWidthJoinThreshold ?? DEFAULT_VARYING_WIDTH_JOIN_THRESHOLD;\n\n // RectPath fast path for inner/outer alignment: shift the rect by half-width\n // so the ribbon's center alignment lands the stroke on the desired side of\n // the original geometric edge. Arbitrary paths handle alignment via stencil\n // clipping at the renderer level (not here).\n const metric = opts.metric;\n const rectInMetric = metric && path.kind === 'rect' ? rectIntoMetric(path, metric) : null;\n let workingPath: Path = rectInMetric ?? path;\n if (workingPath.kind === 'rect' && align !== 'center') {\n const aligned = alignedStrokeRect(workingPath, align, width);\n workingPath = {\n kind: 'rect',\n x: aligned.x,\n y: aligned.y,\n width: aligned.width,\n height: aligned.height,\n };\n }\n\n const polylines = extractPolylines(workingPath, opts);\n // Per-point widths come first, in the space the points are in, so a trim\n // interpolates them rather than re-reading an anchor's.\n const vertexWidths = stroke.vertexWidths && stroke.vertexWidths.length > 0 ? stroke.vertexWidths : null;\n const scale: WidthScale | undefined = !metric ? undefined\n : rectInMetric ? (tx, ty) => worldWidthInMetric(metric, tx, ty)\n : (ux, uy) => worldWidthInMetricAlongWorld(metric, ux, uy);\n const dash = stroke.dash ?? [];\n const verts: number[] = [];\n const idx: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n\n // Trim before dashing, so the dash pattern fits the visible line rather than\n // running off under a marker head.\n const ribbonSpace = metric ?? null;\n for (const pl of polylines) {\n if (vertexWidths) populatePolylineWidths(pl, vertexWidths, width, scale);\n const trimmed = trimInSpace(pl, rectInMetric ? ribbonSpace : null, ribbonSpace, opts.startInset, opts.endInset);\n if (trimmed === null) continue;\n const subs = dash.length > 0 ? splitForDash(trimmed, dash) : [trimmed];\n for (const sub of subs) {\n expandPolyline(sub, width, join, cap, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT);\n }\n }\n\n const vertices = new Float32Array(verts);\n if (metric) coordsOutOfMetric(vertices, metric);\n return {\n vertices,\n indices: new Uint32Array(idx),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n\nfunction expandPolyline(\n pl: Polyline,\n width: number,\n join: Join,\n cap: Cap,\n miterLimit: number,\n varyingThreshold: number,\n verts: number[],\n idx: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): void {\n const half = width / 2;\n const pts = pl.points;\n const ptCount = pts.length / 2;\n const segCount = ptCount - 1;\n if (segCount < 1) return;\n\n // Anchor params per polyline point (set by extractPolylines; splitForDash\n // re-derives them on dash boundaries). Default to A=B=0,t=0 if missing.\n const plA = pl.anchorA ?? new Uint32Array(ptCount);\n const plB = pl.anchorB ?? new Uint32Array(ptCount);\n const plT = pl.anchorT ?? new Float32Array(ptCount);\n // Per-point half-widths: derived from pl.widths if present, else the\n // uniform half. Indexing matches `pts` (one entry per polyline point).\n const plHalf = pl.widths\n ? pl.widths.map((w) => w / 2)\n : null;\n\n const segs: Seg[] = [];\n const segSrcIdx: number[] = []; // For each seg, the polyline-point index of its start.\n for (let s = 0; s < segCount; s++) {\n const ha = plHalf ? plHalf[s] : half;\n const hb = plHalf ? plHalf[s + 1] : half;\n const seg = makeSeg(pts[s * 2], pts[s * 2 + 1], pts[(s + 1) * 2], pts[(s + 1) * 2 + 1], ha, hb);\n if (seg) {\n segs.push(seg);\n segSrcIdx.push(s);\n }\n }\n let closerSrcIdx = -1;\n if (pl.closed && segs.length >= 1) {\n const last = segs[segs.length - 1];\n const first = segs[0];\n // Closer: from last point back to point 0. Half-widths are the\n // already-resolved ones at those source indices.\n const haCloser = plHalf ? plHalf[ptCount - 1] : half;\n const hbCloser = plHalf ? plHalf[0] : half;\n const closer = makeSeg(last.bx, last.by, first.ax, first.ay, haCloser, hbCloser);\n if (closer) {\n segs.push(closer);\n closerSrcIdx = ptCount - 1; // start is the last polyline point.\n segSrcIdx.push(closerSrcIdx);\n }\n }\n if (segs.length === 0) return;\n\n // Emit ribbon quads. For each emitted vertex, record the (A, B, t) of the\n // source polyline point that the geometric vertex sits at. Per-end\n // half-widths produce trapezoidal segments when the stroke tapers.\n const segBaseIdx: number[] = [];\n for (let s = 0; s < segs.length; s++) {\n const seg = segs[s];\n const startSrc = segSrcIdx[s];\n // End-source index for the seg. For closer (closed-path wraparound), end is point 0.\n const endSrc = (s === segs.length - 1 && pl.closed && closerSrcIdx >= 0) ? 0 : startSrc + 1;\n const base = verts.length / 2;\n segBaseIdx.push(base);\n const nxA = seg.nxUnit * seg.halfA, nyA = seg.nyUnit * seg.halfA;\n const nxB = seg.nxUnit * seg.halfB, nyB = seg.nyUnit * seg.halfB;\n // L0, R0 — at seg.ax/ay with start half-width.\n verts.push(seg.ax + nxA, seg.ay + nyA);\n anchorA.push(plA[startSrc]); anchorB.push(plB[startSrc]); anchorT.push(plT[startSrc]);\n verts.push(seg.ax - nxA, seg.ay - nyA);\n anchorA.push(plA[startSrc]); anchorB.push(plB[startSrc]); anchorT.push(plT[startSrc]);\n // L1, R1 — at seg.bx/by with end half-width.\n verts.push(seg.bx + nxB, seg.by + nyB);\n anchorA.push(plA[endSrc]); anchorB.push(plB[endSrc]); anchorT.push(plT[endSrc]);\n verts.push(seg.bx - nxB, seg.by - nyB);\n anchorA.push(plA[endSrc]); anchorB.push(plB[endSrc]); anchorT.push(plT[endSrc]);\n idx.push(base, base + 1, base + 2, base + 1, base + 3, base + 2);\n }\n\n // Joins between consecutive segments.\n const joinCount = pl.closed ? segs.length : segs.length - 1;\n for (let j = 0; j < joinCount; j++) {\n emitJoin(segs, segBaseIdx, j, join, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT, segSrcIdx, plA, plB, plT);\n }\n\n // Caps. Use the local half-width at the cap end (seg.halfA at start, seg.halfB at end).\n if (!pl.closed && cap !== 'butt') {\n const first = segs[0];\n const firstBase = segBaseIdx[0];\n emitCap(first, firstBase + 0, firstBase + 1, false, first.halfA, cap, verts, idx, anchorA, anchorB, anchorT, plA[0], plB[0], plT[0]);\n\n const last = segs[segs.length - 1];\n const lastBase = segBaseIdx[segs.length - 1];\n const lastSrc = segSrcIdx[segs.length - 1] + 1;\n emitCap(last, lastBase + 2, lastBase + 3, true, last.halfB, cap, verts, idx, anchorA, anchorB, anchorT, plA[lastSrc], plB[lastSrc], plT[lastSrc]);\n }\n}\n\nconst ROUND_CAP_STEP_RAD = (10 * Math.PI) / 180;\n\n/**\n * Emit a cap at one end of a segment. `leftIdx`/`rightIdx` are the buffer\n * indices of the L (perpendicular +n) and R (perpendicular -n) vertices at\n * the segment endpoint where the cap attaches. `atEnd` chooses which end of\n * the segment to extend from (and which cap-direction sign to use).\n */\nfunction emitCap(\n seg: Seg, leftIdx: number, rightIdx: number, atEnd: boolean,\n half: number, cap: Cap,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n endA: number, endB: number, endT: number,\n): void {\n // Outward direction = forward at end, backward at start.\n const sign = atEnd ? 1 : -1;\n const dx = (seg.bx - seg.ax) / seg.len * sign;\n const dy = (seg.by - seg.ay) / seg.len * sign;\n const cx = atEnd ? seg.bx : seg.ax;\n const cy = atEnd ? seg.by : seg.ay;\n\n // Perpendicular offset at this cap end uses the local half-width\n // (varies along the polyline when vertexWidths is set).\n const nx = seg.nxUnit * half;\n const ny = seg.nyUnit * half;\n\n if (cap === 'square') {\n const ox = cx + dx * half;\n const oy = cy + dy * half;\n const lOut = verts.length / 2;\n verts.push(ox + nx, oy + ny);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n const rOut = verts.length / 2;\n verts.push(ox - nx, oy - ny);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n // Two triangles forming the cap rectangle. Wind so triangles are CCW\n // viewed from the front; orientation symmetric for start vs. end caps.\n if (atEnd) {\n idx.push(leftIdx, lOut, rOut, leftIdx, rOut, rightIdx);\n } else {\n idx.push(leftIdx, rOut, lOut, leftIdx, rightIdx, rOut);\n }\n return;\n }\n\n if (cap === 'round') {\n // Pivot vertex at the endpoint center; fan from L through the outward\n // 180° arc to R.\n const pivotIdx = verts.length / 2;\n verts.push(cx, cy);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n\n // Starting angle: direction from pivot to L (= +n direction).\n const startAngle = Math.atan2(ny, nx);\n // Sweep 180° toward the outward direction. The outward unit is (dx, dy);\n // we rotate from +n to -n the \"outward\" way. The dot product of (dx, dy)\n // with the perpendicular tells us which way around the arc to go.\n // A start-cap (sign = -1) sweeps backward; end-cap (sign = +1) sweeps forward.\n const sweep = atEnd ? -Math.PI : Math.PI;\n const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_CAP_STEP_RAD));\n const stepAngle = sweep / steps;\n\n let prevIdx = leftIdx;\n for (let i = 1; i < steps; i++) {\n const ang = startAngle + i * stepAngle;\n const fx = cx + Math.cos(ang) * half;\n const fy = cy + Math.sin(ang) * half;\n const newIdx = verts.length / 2;\n verts.push(fx, fy);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n if (atEnd) idx.push(prevIdx, newIdx, pivotIdx);\n else idx.push(prevIdx, pivotIdx, newIdx);\n prevIdx = newIdx;\n }\n if (atEnd) idx.push(prevIdx, rightIdx, pivotIdx);\n else idx.push(prevIdx, pivotIdx, rightIdx);\n }\n}\n\nfunction makeSeg(ax: number, ay: number, bx: number, by: number, halfA: number, halfB: number): Seg | null {\n const dx = bx - ax, dy = by - ay;\n const len = Math.hypot(dx, dy);\n if (len === 0) return null;\n return {\n ax, ay, bx, by,\n nxUnit: -dy / len, nyUnit: dx / len,\n halfA, halfB,\n len,\n };\n}\n\n/**\n * Miter limit for a stroke that does not set one. SVG's default, not\n * Canvas2D's 10, because the serializer omits the attribute when the field is\n * unset — so a kit stroke exported to SVG is read back by every other renderer\n * as 4, and a kit that used 10 would disagree with its own export. 10 also\n * lets an acute corner throw a spike four times the half-width, which is what\n * a glyph outline's sharpest vertices do.\n */\nconst DEFAULT_MITER_LIMIT = 4;\n/** Default `Stroke.varyingWidthJoinThreshold`. */\nconst DEFAULT_VARYING_WIDTH_JOIN_THRESHOLD = 1.5;\n\nfunction emitJoin(\n segs: Seg[], segBaseIdx: number[], j: number, join: Join,\n miterLimit: number,\n varyingThreshold: number,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n segSrcIdx: number[],\n plA: Uint32Array, plB: Uint32Array, plT: Float32Array,\n): void {\n const a = segs[j];\n const b = segs[(j + 1) % segs.length];\n const aBase = segBaseIdx[j];\n const bBase = segBaseIdx[(j + 1) % segs.length];\n\n const adx = a.bx - a.ax, ady = a.by - a.ay;\n const bdx = b.bx - b.ax, bdy = b.by - b.ay;\n const cross = adx * bdy - ady * bdx;\n if (cross === 0) return; // straight (collinear), no wedge\n const onPositive = cross > 0;\n\n const aOuterEnd = onPositive ? aBase + 3 : aBase + 2;\n const bOuterStart = onPositive ? bBase + 1 : bBase + 0;\n\n // The corner of join `j` is the start of segment `j+1` (which is the END of\n // segment `j` — they share the same polyline point). For the wraparound join\n // on a closed polyline, j+1 wraps to segment 0 whose start is the closer\n // segment's endpoint, which is polyline point 0.\n const nextSeg = (j + 1) % segs.length;\n // The corner anchor is the start of the next segment (shared endpoint).\n // For a closed path's final join, nextSeg wraps to 0, whose start is\n // polyline point 0 — correct.\n const cornerSrc = segSrcIdx[nextSeg];\n const cornerA = plA[cornerSrc];\n const cornerB = plB[cornerSrc];\n const cornerT = plT[cornerSrc];\n // The two adjoining half-widths agree at the shared corner (a.halfB ===\n // b.halfA for a single-contour polyline), so use either for miter-limit\n // sizing. Force bevel when either adjacent segment itself tapers by\n // more than `varyingThreshold` — the miter apex math computes against\n // outer edges parallel to the segment direction, an assumption that\n // breaks on tapered trapezoids (outer edges fan in/out).\n const halfAtCorner = a.halfB;\n const taperA = Math.max(a.halfA, a.halfB) / Math.max(1e-9, Math.min(a.halfA, a.halfB));\n const taperB = Math.max(b.halfA, b.halfB) / Math.max(1e-9, Math.min(b.halfA, b.halfB));\n const forceBevelForVarying = taperA > varyingThreshold || taperB > varyingThreshold;\n\n if (join === 'bevel' || forceBevelForVarying) {\n emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n\n if (join === 'miter') {\n // Compute apex: intersection of A's outer edge extended forward and\n // B's outer edge extended backward. If miter length > MITER_LIMIT * half,\n // fall back to bevel.\n const aOX = verts[aOuterEnd * 2], aOY = verts[aOuterEnd * 2 + 1];\n const bOX = verts[bOuterStart * 2], bOY = verts[bOuterStart * 2 + 1];\n const apex = lineLineIntersect(aOX, aOY, adx, ady, bOX, bOY, -bdx, -bdy);\n if (!apex) {\n emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n const miterLen = Math.hypot(apex[0] - a.bx, apex[1] - a.by);\n if (miterLen > miterLimit * halfAtCorner) {\n emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n // A miter join's outer face is a kite quadrilateral with vertices\n // (R1, apex, R0, J) — covered by TWO triangles. The bevel inner half\n // (R1, R0, J) fills the area between the joint corner and the diagonal\n // hypotenuse R0-R1; the outer extension (R1, apex, R0) fills from the\n // hypotenuse to the apex point. Without the bevel half, an \"inverted\n // triangle\" gap opens at every miter corner.\n const apexIdx = verts.length / 2;\n verts.push(apex[0], apex[1]);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n const jIdx = verts.length / 2;\n verts.push(a.bx, a.by);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n if (onPositive) {\n idx.push(aOuterEnd, apexIdx, bOuterStart);\n idx.push(aOuterEnd, bOuterStart, jIdx);\n } else {\n idx.push(aOuterEnd, bOuterStart, apexIdx);\n idx.push(aOuterEnd, jIdx, bOuterStart);\n }\n return;\n }\n\n if (join === 'round') {\n emitRoundJoin(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n}\n\nconst ROUND_STEP_RAD = (10 * Math.PI) / 180; // ~10° per fan triangle\n\nfunction emitRoundJoin(\n a: Seg, aOuterEnd: number, bOuterStart: number, onPositive: boolean,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n cornerA: number, cornerB: number, cornerT: number,\n): void {\n // Pivot = joint center; emit fresh vertex.\n const cx = a.bx, cy = a.by;\n const pivotIdx = verts.length / 2;\n verts.push(cx, cy);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n\n const startX = verts[aOuterEnd * 2] - cx;\n const startY = verts[aOuterEnd * 2 + 1] - cy;\n const endX = verts[bOuterStart * 2] - cx;\n const endY = verts[bOuterStart * 2 + 1] - cy;\n const r = Math.hypot(startX, startY);\n\n const startAngle = Math.atan2(startY, startX);\n const endAngle = Math.atan2(endY, endX);\n // Outer-side sweep: for CCW turns (cross > 0, onPositive true) outer is on\n // the -n side and the arc sweeps from R1 (south of joint) clockwise to R0\n // (east of joint) — i.e., negative sweep. For CW turns, sweep is positive.\n // Pick the SHORT arc that crosses the outer wedge. For onPositive=true\n // (CW turn in screen coords with y-down), the outer wedge sits where the\n // natural sweep is positive; for onPositive=false, where it is negative.\n // If the natural sweep has the wrong sign, wrap by ±2π.\n let sweep = endAngle - startAngle;\n if (onPositive && sweep < 0) sweep += 2 * Math.PI;\n else if (!onPositive && sweep > 0) sweep -= 2 * Math.PI;\n\n const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_STEP_RAD));\n const stepAngle = sweep / steps;\n\n let prevIdx = aOuterEnd;\n for (let i = 1; i < steps; i++) {\n const ang = startAngle + i * stepAngle;\n const fx = cx + Math.cos(ang) * r;\n const fy = cy + Math.sin(ang) * r;\n const newIdx = verts.length / 2;\n verts.push(fx, fy);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n if (onPositive) idx.push(prevIdx, pivotIdx, newIdx);\n else idx.push(prevIdx, newIdx, pivotIdx);\n prevIdx = newIdx;\n }\n if (onPositive) idx.push(prevIdx, pivotIdx, bOuterStart);\n else idx.push(prevIdx, bOuterStart, pivotIdx);\n}\n\nfunction emitBevel(\n a: Seg, aOuterEnd: number, bOuterStart: number, onPositive: boolean,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n cornerA: number, cornerB: number, cornerT: number,\n): void {\n const jIdx = verts.length / 2;\n verts.push(a.bx, a.by);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n if (onPositive) idx.push(aOuterEnd, jIdx, bOuterStart);\n else idx.push(aOuterEnd, bOuterStart, jIdx);\n}\n\n/**\n * Solve for the intersection of line A (point ap, direction ad) with line B\n * (point bp, direction bd). Returns null if parallel or near-parallel.\n */\nfunction lineLineIntersect(\n apx: number, apy: number, adx: number, ady: number,\n bpx: number, bpy: number, bdx: number, bdy: number,\n): [number, number] | null {\n const denom = adx * bdy - ady * bdx;\n if (Math.abs(denom) < 1e-9) return null;\n const t = ((bpx - apx) * bdy - (bpy - apy) * bdx) / denom;\n return [apx + t * adx, apy + t * ady];\n}\n","/**\n * Resolving a `MarkerRef` to the distance the ribbon must stop short.\n *\n * The tessellation layer takes these as plain numbers and knows nothing about\n * the registry — keeping that layer free of upward dependencies is deliberate.\n * The ribbon cache, the SVG serializer and `inkReach` all resolve through here,\n * so the ribbon, the export and the hit region cannot disagree about where the\n * line ends.\n */\n\nimport { resolveScreenLength, type MarkerRef, type Stroke } from '@weasel-js/paint';\nimport { getMarker } from './strokeMarkers';\n\n/** The size of one marker unit, in the same world units as `strokeWidth`.\n * `scale` is the view scale a `{ px }` size resolves against, as a `{ px }`\n * stroke width does. */\nexport function resolveMarkerSize(ref: MarkerRef, strokeWidth: number, scale = 1): number {\n if (typeof ref === 'string' || ref.size === undefined) return strokeWidth;\n return resolveScreenLength(ref.size, scale);\n}\n\n/** The registry key a `MarkerRef` names, whether given bare or with a size. */\nexport function markerKeyOf(ref: MarkerRef): string {\n return typeof ref === 'string' ? ref : ref.key;\n}\n\n/**\n * How far back the ribbon stops for `ref`, in world units. Zero for an absent\n * marker, an unregistered key, or an open head — never throws, because an\n * unknown key is a data problem and dropping the head is the graceful answer.\n */\nexport function markerInset(ref: MarkerRef | undefined, strokeWidth: number, scale = 1): number {\n if (ref === undefined) return 0;\n const entry = getMarker(markerKeyOf(ref));\n if (entry === undefined) return 0;\n return (entry.inset ?? 0) * resolveMarkerSize(ref, strokeWidth, scale);\n}\n\n/** The start and end insets a stroke asks for. `markerMid` never insets —\n * trimming at an interior vertex would cut the line in two. */\nexport function strokeInsets(stroke: Stroke, strokeWidth: number): { start: number; end: number } {\n return {\n start: markerInset(stroke.markerStart, strokeWidth),\n end: markerInset(stroke.markerEnd, strokeWidth),\n };\n}\n","/**\n * Where a stroke's markers sit and which way they point.\n *\n * Computed from the *untrimmed* polyline: trimming moves the endpoint, and a\n * marker anchors to where the line was authored to end, not to where the\n * ribbon was cut.\n */\n\nimport type { Polyline } from '@weasel-js/geom/tessellate';\n\n/** One marker placement, in the polyline's own coordinates. */\nexport interface MarkerSite {\n x: number;\n y: number;\n /** Radians. The direction the marker's +X axis should point — outward at a\n * start or end, along the bisector at an interior vertex. */\n angle: number;\n role: 'start' | 'mid' | 'end';\n}\n\n/** Which marker roles to place. `start` and `end` are ignored on a closed polyline. */\nexport interface MarkerSiteRequest {\n start: boolean;\n mid: boolean;\n end: boolean;\n}\n\nconst EPS = 1e-9;\n\n/** Unit direction from point `i` to point `j`, or null if they coincide. */\nfunction dir(pl: Polyline, i: number, j: number): { x: number; y: number } | null {\n const dx = pl.points[j * 2] - pl.points[i * 2];\n const dy = pl.points[j * 2 + 1] - pl.points[i * 2 + 1];\n const len = Math.hypot(dx, dy);\n if (len < EPS) return null;\n return { x: dx / len, y: dy / len };\n}\n\n/** The first index after `i` whose point differs from `i`'s. */\nfunction nextDistinct(pl: Polyline, i: number, n: number): number {\n for (let k = i + 1; k < n; k++) if (dir(pl, i, k)) return k;\n return -1;\n}\nfunction prevDistinct(pl: Polyline, i: number): number {\n for (let k = i - 1; k >= 0; k--) if (dir(pl, k, i)) return k;\n return -1;\n}\n\n/**\n * Where each requested marker sits on `pl` and the angle it points at.\n * Mid sites fall only on authored vertices, never on flattened curve samples,\n * and need the polyline to carry anchor data; without it no mid sites are returned.\n */\nexport function markerSites(pl: Polyline, want: MarkerSiteRequest): MarkerSite[] {\n const out: MarkerSite[] = [];\n const n = pl.points.length / 2;\n if (n < 2) return out;\n\n if (want.start && !pl.closed) {\n const j = nextDistinct(pl, 0, n);\n const d = j >= 0 ? dir(pl, 0, j) : null;\n if (d) {\n // Reversed, so a start head points away from the line body the way an\n // end head does. SVG spells this `auto-start-reverse`; here it is the\n // only behavior.\n out.push({ x: pl.points[0], y: pl.points[1], angle: Math.atan2(-d.y, -d.x), role: 'start' });\n }\n }\n\n if (want.mid) {\n const A = pl.anchorA, B = pl.anchorB, T = pl.anchorT;\n if (A && B && T) {\n for (let i = 1; i < n - 1; i++) {\n // An authored anchor, not a flattened curve sample.\n if (A[i] !== B[i] || T[i] !== 0) continue;\n const p = prevDistinct(pl, i);\n const q = nextDistinct(pl, i, n);\n if (p < 0 || q < 0) continue;\n const inDir = dir(pl, p, i)!;\n const outDir = dir(pl, i, q)!;\n let bx = inDir.x + outDir.x;\n let by = inDir.y + outDir.y;\n // A 180° reversal leaves no bisector; fall back to the arriving direction.\n if (Math.hypot(bx, by) < EPS) { bx = inDir.x; by = inDir.y; }\n out.push({ x: pl.points[i * 2], y: pl.points[i * 2 + 1], angle: Math.atan2(by, bx), role: 'mid' });\n }\n }\n }\n\n if (want.end && !pl.closed) {\n const last = n - 1;\n const p = prevDistinct(pl, last);\n const d = p >= 0 ? dir(pl, p, last) : null;\n if (d) {\n out.push({ x: pl.points[last * 2], y: pl.points[last * 2 + 1], angle: Math.atan2(d.y, d.x), role: 'end' });\n }\n }\n\n return out;\n}\n","/**\n * A stroke's marker heads as placed geometry, and how far they reach.\n */\n\nimport type { MarkerRef, Stroke } from '@weasel-js/paint';\nimport { type Path, type PolygonPath, boundsOfPath } from '@weasel-js/geom';\nimport { extractPolylines } from '@weasel-js/geom/tessellate';\nimport { getMarker, type MarkerEntry } from './strokeMarkers';\nimport { markerKeyOf, resolveMarkerSize } from './markerInset';\nimport { markerSites, type MarkerSite } from './markerSites';\nimport {\n coordsOutOfMetric, polylineIntoMetric, type ScreenSpace, type StrokeSpaces,\n} from './tessellate/metric';\n\n/** Rotate + translate a marker's geometry onto its site. */\nfunction placed(path: Path, site: MarkerSite): PolygonPath {\n const src = path as PolygonPath;\n const cos = Math.cos(site.angle);\n const sin = Math.sin(site.angle);\n const coords = new Float32Array(src.coords.length);\n for (let i = 0; i < src.coords.length; i += 2) {\n const x = src.coords[i], y = src.coords[i + 1];\n coords[i] = site.x + x * cos - y * sin;\n coords[i + 1] = site.y + x * sin + y * cos;\n }\n return { kind: 'polygon', commands: src.commands, coords, fillRule: src.fillRule };\n}\n\n/** One head's placed geometry, before any paint is applied. */\nexport interface MarkerHead {\n readonly entry: MarkerEntry;\n readonly path: PolygonPath;\n readonly size: number;\n /** Where it was built, when not in world — `size` is in this space's units. */\n readonly space?: ScreenSpace;\n}\n\n/**\n * Every marker head for `path` under `stroke`, placed but unpainted.\n * `strokeWidth` is the already width-resolved stroke width; `flattenTolerance`\n * matches what the ribbon used, so heads land on the same flattened vertices\n * the stroke did. A head `spaces` puts in a screen space is placed and sized\n * there and comes back in world units, so it meets the line it caps.\n */\nexport function markerHeads(\n path: Path,\n stroke: Stroke,\n strokeWidth: number,\n flattenTolerance: number | undefined,\n spaces: StrokeSpaces = {},\n): MarkerHead[] {\n const refs = { start: stroke.markerStart, mid: stroke.markerMid, end: stroke.markerEnd };\n if (refs.start === undefined && refs.mid === undefined && refs.end === undefined) return [];\n\n // Heads sharing a space share one pass over the polyline mapped into it.\n const groups = new Map<ScreenSpace | undefined, { start: boolean; mid: boolean; end: boolean }>();\n for (const role of ['start', 'mid', 'end'] as const) {\n if (refs[role] === undefined) continue;\n const space = spaces[role];\n let want = groups.get(space);\n if (want === undefined) groups.set(space, (want = { start: false, mid: false, end: false }));\n want[role] = true;\n }\n\n const out: MarkerHead[] = [];\n for (const pl of extractPolylines(path, { flattenTolerance })) {\n for (const [space, want] of groups) {\n const inSpace = space ? { ...pl, points: pl.points.slice() } : pl;\n if (space) polylineIntoMetric(inSpace, space.metric);\n for (const site of markerSites(inSpace, want)) {\n const ref: MarkerRef | undefined = refs[site.role];\n if (ref === undefined) continue;\n const entry = getMarker(markerKeyOf(ref));\n if (entry === undefined) continue;\n const size = resolveMarkerSize(ref, strokeWidth);\n const angle = entry.orient === undefined || entry.orient === 'auto' ? site.angle : entry.orient;\n const head = placed(entry.path({ size, stroke }), { ...site, angle });\n if (space) coordsOutOfMetric(head.coords, space.metric);\n out.push(space ? { entry, size, path: head, space } : { entry, size, path: head });\n }\n }\n }\n return out;\n}\n\n/**\n * A key for the stroke fields `entry`'s geometry reads, or `null` when the\n * entry does not say which it reads and only the stroke's identity can stand\n * in for them.\n */\nexport function markerReadsKey(entry: MarkerEntry, stroke: Stroke): string | null {\n if (entry.reads === undefined) return null;\n let key = '';\n for (const field of entry.reads) key += `${JSON.stringify(stroke[field]) ?? ''}|`;\n return key;\n}\n\n/** Distinct stroke readings kept per entry before its map is dropped. */\nconst READINGS_PER_ENTRY = 64;\n\n/** Each entry's farthest reach from its anchor at `size` 1, outline included,\n * per value of the fields it reads — or per stroke object, when it does not\n * say which. */\nconst REACH_BY_READING = new WeakMap<MarkerEntry, Map<string, number>>();\nconst REACH_BY_STROKE = new WeakMap<MarkerEntry, WeakMap<Stroke, number>>();\n\nfunction measureUnitReach(entry: MarkerEntry, stroke: Stroke): number {\n const b = boundsOfPath(entry.path({ size: 1, stroke }));\n return Math.max(Math.abs(b.x), Math.abs(b.x + b.width), Math.abs(b.y), Math.abs(b.y + b.height))\n + (entry.outline ? entry.outline.width / 2 : 0);\n}\n\nfunction unitReach(entry: MarkerEntry, stroke: Stroke): number {\n const key = markerReadsKey(entry, stroke);\n if (key === null) {\n let byStroke = REACH_BY_STROKE.get(entry);\n if (byStroke === undefined) REACH_BY_STROKE.set(entry, (byStroke = new WeakMap()));\n let reach = byStroke.get(stroke);\n if (reach === undefined) byStroke.set(stroke, (reach = measureUnitReach(entry, stroke)));\n return reach;\n }\n let byReading = REACH_BY_READING.get(entry);\n if (byReading === undefined) REACH_BY_READING.set(entry, (byReading = new Map()));\n let reach = byReading.get(key);\n if (reach === undefined) {\n if (byReading.size >= READINGS_PER_ENTRY) byReading.clear();\n byReading.set(key, (reach = measureUnitReach(entry, stroke)));\n }\n return reach;\n}\n\n/**\n * How far `stroke`'s markers can paint from the vertex each sits on, split by\n * where each is built: `world` in world units for a head with a world size,\n * `px` in screen pixels for one with a `{ px }` size. A head with no size\n * takes the stroke width, and with it the width's units. Culling and a path\n * node's grab reach both measure through here.\n */\nexport function markerReach(stroke: Stroke): { world: number; px: number } {\n const reach = { world: 0, px: 0 };\n const width = stroke.width ?? 1;\n for (const ref of [stroke.markerStart, stroke.markerMid, stroke.markerEnd]) {\n if (ref === undefined) continue;\n const entry = getMarker(markerKeyOf(ref));\n if (entry === undefined) continue;\n const size = typeof ref === 'string' || ref.size === undefined ? width : ref.size;\n const unit = unitReach(entry, stroke);\n if (typeof size === 'number') reach.world = Math.max(reach.world, unit * size);\n else reach.px = Math.max(reach.px, unit * size.px);\n }\n return reach;\n}\n","/**\n * A stroke as geometry: the region its ink covers, as a fillable path.\n *\n * The ribbon the renderer draws already has the joins, caps, dashes, and\n * marker trims; unioning its triangles gives the silhouette with every\n * self-overlap resolved, so the outline and the drawn stroke cannot disagree.\n */\nimport type { Stroke } from '@weasel-js/paint';\nimport type { Path, PolygonPath } from '@weasel-js/geom';\nimport { pathIntersect, pathSubtract, pathUnion, trianglesToPath } from '@weasel-js/geom/booleans';\nimport { strokeInsets } from './markerInset';\nimport { resolveStrokeWidth, tessellateStroke } from './tessellate/stroke';\nimport { markerHeads } from './markerHeads';\n\n/** Options for {@link strokeToPath}. */\nexport interface StrokeToPathOptions {\n /** Screen pixels per world unit, for a `{ px }` width or marker size.\n * Default 1. */\n scale?: number;\n /** Flatness tolerance for curves, in the path's units. */\n flattenTolerance?: number;\n}\n\nconst EMPTY: PolygonPath = {\n kind: 'polygon', commands: new Uint8Array(0), coords: new Float32Array(0), fillRule: 'nonzero',\n};\n\n/**\n * The region `stroke` covers when drawn along `path`, as a path to fill:\n * width, cap, join, miter limit, dash, alignment, per-vertex widths, and\n * marker heads all included. Curves are flattened, so the result holds only\n * M/L/Z. A stroke with no width answers an empty path.\n */\nexport function strokeToPath(path: Path, stroke: Stroke, opts: StrokeToPathOptions = {}): PolygonPath {\n const width = resolveStrokeWidth(stroke.width ?? 1, opts.scale ?? 1);\n if (!(width > 0)) return EMPTY;\n const tolerance = opts.flattenTolerance;\n const sized: Stroke = { ...stroke, width };\n const insets = strokeInsets(sized, width);\n const align = stroke.align ?? 'center';\n // A rect's aligned ribbon is built in place. Any other path gets a centered\n // ribbon twice as wide, cut to the side of the path it belongs on.\n const cut = align !== 'center' && path.kind !== 'rect';\n const ribbonStroke: Stroke = cut\n ? { ...sized, width: width * 2, align: 'center', vertexWidths: stroke.vertexWidths?.map((w) => w * 2) }\n : sized;\n const mesh = tessellateStroke(path, ribbonStroke, {\n flattenTolerance: tolerance, startInset: insets.start, endInset: insets.end,\n });\n let ribbon = trianglesToPath(mesh.vertices, mesh.indices);\n if (cut) ribbon = align === 'inner' ? pathIntersect(ribbon, path) : pathSubtract(ribbon, path);\n\n const heads: PolygonPath[] = [];\n for (const { entry, path: head, size } of markerHeads(path, sized, width, tolerance)) {\n if ((entry.fill ?? 'line') !== 'none') heads.push(head);\n if (entry.outline && (entry.outline.paint ?? 'line') !== 'none') {\n heads.push(strokeToPath(head, { width: entry.outline.width * size, cap: 'round', join: 'round' }, opts));\n }\n }\n return heads.length === 0 ? ribbon : pathUnion(ribbon, ...heads);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/tessellate/dash.ts","../src/tessellate/flattening.ts","../src/tessellate/vertexWidths.ts","../src/tessellate/metric.ts","../src/tessellate/insets.ts","../src/tessellate/stroke.ts","../src/markerInset.ts","../src/markerSites.ts","../src/markerHeads.ts","../src/strokeToPath.ts","../src/offsetPath.ts"],"names":["len","resolveScreenLength","extractPolylines","reach","pathUnion","pathSubtract"],"mappings":"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","file":"index.js","sourcesContent":["import type { Polyline } from '@weasel-js/geom/tessellate';\n\n/**\n * Split a polyline into open sub-polylines for the \"on\" portions of a dash\n * pattern. Each output sub-polyline gets caps from the stroke's `cap` setting.\n * The \"off\" portions become invisible gaps. Anchor params are carried through:\n * sub-polyline endpoints inherit their source polyline-point's anchor params;\n * dash boundaries that land mid-segment (between two polyline points) snap\n * their anchor params to whichever endpoint they're closer to when the\n * segment crosses a path-anchor boundary, otherwise interpolate `t` linearly.\n */\nexport function splitForDash(pl: Polyline, dash: number[]): Polyline[] {\n const out: Polyline[] = [];\n const plA = pl.anchorA ?? new Uint32Array(pl.points.length / 2);\n const plB = pl.anchorB ?? new Uint32Array(pl.points.length / 2);\n const plT = pl.anchorT ?? new Float32Array(pl.points.length / 2);\n\n let dashIdx = 0;\n let dashRemaining = dash[0];\n let onPhase = true;\n let curPts: number[] | null = onPhase ? [pl.points[0], pl.points[1]] : null;\n let curA: number[] | null = onPhase ? [plA[0]] : null;\n let curB: number[] | null = onPhase ? [plB[0]] : null;\n let curT: number[] | null = onPhase ? [plT[0]] : null;\n\n const flushAndAdvance = () => {\n if (curPts && curPts.length >= 4) {\n out.push({\n points: curPts,\n closed: false,\n anchorA: new Uint32Array(curA!),\n anchorB: new Uint32Array(curB!),\n anchorT: new Float32Array(curT!),\n });\n }\n curPts = null; curA = null; curB = null; curT = null;\n dashIdx = (dashIdx + 1) % dash.length;\n dashRemaining = dash[dashIdx];\n onPhase = !onPhase;\n };\n\n let prevX = pl.points[0], prevY = pl.points[1];\n const ptCount = pl.points.length / 2;\n const segCount = pl.closed ? ptCount : ptCount - 1;\n\n for (let i = 0; i < segCount; i++) {\n const nextIdx = (i + 1) % ptCount;\n const cx = pl.points[nextIdx * 2], cy = pl.points[nextIdx * 2 + 1];\n const startA = plA[i], startB = plB[i], startT = plT[i];\n const endA = plA[nextIdx], endB = plB[nextIdx], endT = plT[nextIdx];\n const segFullDx = cx - prevX, segFullDy = cy - prevY;\n const segFullLen = Math.hypot(segFullDx, segFullDy);\n let segDx = segFullDx, segDy = segFullDy;\n let segLen = segFullLen;\n let traveled = 0;\n\n while (segLen > 1e-9) {\n if (segLen <= dashRemaining) {\n if (onPhase && curPts) {\n curPts.push(cx, cy);\n curA!.push(endA); curB!.push(endB); curT!.push(endT);\n }\n dashRemaining -= segLen;\n prevX = cx; prevY = cy;\n traveled = segFullLen;\n segLen = 0;\n if (dashRemaining <= 1e-9) {\n flushAndAdvance();\n if (onPhase) {\n curPts = [prevX, prevY];\n curA = [endA]; curB = [endB]; curT = [endT];\n }\n }\n } else {\n const tConsume = dashRemaining / segLen;\n const ix = prevX + segDx * tConsume;\n const iy = prevY + segDy * tConsume;\n traveled += dashRemaining;\n const frac = traveled / segFullLen;\n let mA: number, mB: number, mT: number;\n if (startA === endA && startB === endB) {\n mA = startA; mB = startB;\n mT = startT + (endT - startT) * frac;\n } else {\n // Cross-anchor segment: pick the nearer endpoint's params.\n if (frac < 0.5) { mA = startA; mB = startB; mT = startT; }\n else { mA = endA; mB = endB; mT = endT; }\n }\n if (onPhase && curPts) {\n curPts.push(ix, iy);\n curA!.push(mA); curB!.push(mB); curT!.push(mT);\n }\n prevX = ix; prevY = iy;\n segDx = cx - prevX; segDy = cy - prevY;\n segLen = Math.hypot(segDx, segDy);\n flushAndAdvance();\n if (onPhase) {\n curPts = [prevX, prevY];\n curA = [mA]; curB = [mB]; curT = [mT];\n }\n }\n }\n }\n\n if (curPts && curPts.length >= 4) {\n const tail: Polyline = {\n points: curPts,\n closed: false,\n anchorA: new Uint32Array(curA!),\n anchorB: new Uint32Array(curB!),\n anchorT: new Float32Array(curT!),\n };\n // A closed subpath's walk ends at the vertex it started from, so the run\n // still open there and the run that started there are one dash. Pushed\n // separately they are two butt-capped ribbons meeting at the seam — the\n // visible artifact whenever the pattern doesn't divide the perimeter.\n const tx = curPts[curPts.length - 2], ty = curPts[curPts.length - 1];\n const meets = (x: number, y: number) => Math.hypot(tx - x, ty - y) <= 1e-9;\n if (pl.closed && out.length > 0 && meets(out[0].points[0], out[0].points[1])) {\n out[0] = joinAtSeam(tail, out[0]);\n } else if (pl.closed && out.length === 0 && meets(curPts[0], curPts[1])) {\n // Every gap fell outside the perimeter: the dash is the whole loop, and\n // a loop stroked as an open run seams at its own start vertex too.\n out.push({\n points: curPts.slice(0, -2),\n closed: true,\n anchorA: tail.anchorA!.slice(0, -1),\n anchorB: tail.anchorB!.slice(0, -1),\n anchorT: tail.anchorT!.slice(0, -1),\n });\n } else {\n out.push(tail);\n }\n }\n return out;\n}\n\n/** `tail` continued by `head`, which starts where `tail` ends — the shared\n * vertex is carried once. */\nfunction joinAtSeam(tail: Polyline, head: Polyline): Polyline {\n return {\n points: [...tail.points, ...head.points.slice(2)],\n closed: false,\n anchorA: Uint32Array.from([...tail.anchorA!, ...head.anchorA!.subarray(1)]),\n anchorB: Uint32Array.from([...tail.anchorB!, ...head.anchorB!.subarray(1)]),\n anchorT: Float32Array.from([...tail.anchorT!, ...head.anchorT!.subarray(1)]),\n };\n}\n","import { DEFAULT_FLATTEN_TOLERANCE } from '@weasel-js/geom';\nimport type { ExtractOptions } from '@weasel-js/geom/tessellate';\n\n/** Most a thick stroke's centerline turns between flattened vertices: 10°. */\nconst STROKE_MAX_TURN = Math.PI / 18;\n\n/**\n * How a stroke flattens its path. Every flattened vertex is a join on edges\n * half a width out, so a bend the distance tolerance passes in 40° steps reads\n * as facets once the stroke is thick. A stroke no wider than twice the\n * tolerance keeps the fill's vertices exactly: finer ones could leave a gap\n * between its inner edge and the fill's chords, which a wider one covers.\n */\nexport function strokeFlattening(\n flattenTolerance: number | undefined,\n width: number,\n vertexWidths?: readonly number[],\n): ExtractOptions {\n const tolerance = flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n let widest = width;\n if (vertexWidths) for (const w of vertexWidths) widest = Math.max(widest, w);\n return widest / 2 > tolerance ? { flattenTolerance, maxTurn: STROKE_MAX_TURN } : { flattenTolerance };\n}\n","import type { Polyline } from '@weasel-js/geom/tessellate';\n\n/** What one unit of a `vertexWidths` entry measures across the line at a\n * point whose unit tangent, in the polyline's own space, is `(tx, ty)`. */\nexport type WidthScale = (tx: number, ty: number) => number;\n\n/** Fill `pl.widths` by interpolating `vertexWidths` across each point's\n * (anchorA, anchorB, anchorT). Anchor-aligned points (A === B) read the\n * anchor's value directly. Out-of-range / non-finite anchor entries fall\n * back to `fallbackWidth`. Given `scale`, each entry is scaled at the point\n * that reads it, and the fallback is not. */\nexport function populatePolylineWidths(\n pl: Polyline,\n vertexWidths: number[],\n fallbackWidth: number,\n scale?: WidthScale,\n): void {\n const ptCount = pl.points.length / 2;\n if (ptCount === 0) return;\n const aA = pl.anchorA ?? new Uint32Array(ptCount);\n const aB = pl.anchorB ?? new Uint32Array(ptCount);\n const aT = pl.anchorT ?? new Float32Array(ptCount);\n const widths = new Float32Array(ptCount);\n let k = 1;\n const read = (i: number): number => {\n const v = vertexWidths[i];\n return typeof v === 'number' && isFinite(v) && v > 0 ? v * k : fallbackWidth;\n };\n for (let i = 0; i < ptCount; i++) {\n if (scale) k = scaleAt(pl, i, scale);\n const a = aA[i], b = aB[i], t = aT[i];\n if (a === b) {\n widths[i] = read(a);\n } else {\n const wa = read(a);\n const wb = read(b);\n widths[i] = wa + (wb - wa) * t;\n }\n }\n pl.widths = widths;\n}\n\n/** `scale` along the line's direction at point `i`: the bisector of the\n * segments either side, or the one segment at an open end. */\nfunction scaleAt(pl: Polyline, i: number, scale: WidthScale): number {\n const pts = pl.points;\n const n = pts.length / 2;\n let tx = 0, ty = 0;\n const add = (from: number, to: number) => {\n const dx = pts[to * 2] - pts[from * 2], dy = pts[to * 2 + 1] - pts[from * 2 + 1];\n const len = Math.hypot(dx, dy);\n if (len > 0) { tx += dx / len; ty += dy / len; }\n };\n if (i > 0) add(i - 1, i);\n else if (pl.closed && n > 1) add(n - 1, 0);\n if (i < n - 1) add(i, i + 1);\n else if (pl.closed && n > 1) add(n - 1, 0);\n const len = Math.hypot(tx, ty);\n return len > 0 ? scale(tx / len, ty / len) : 1;\n}\n","/**\n * The space a screen-pixel stroke is built in.\n *\n * A `{ px }` stroke is exact on screen only when its ribbon is offset in a\n * space that measures lengths the way the screen does. The transform's linear\n * part is `scale · R · P`: a uniform scale, a rotation (or reflection) that\n * moves no lengths, and `P`, the symmetric unit-determinant stretch left over.\n * Offsetting the ribbon after `P` and mapping it back through `P⁻¹` gives a\n * world-space mesh that the full transform turns into a ribbon of exactly\n * `width · scale` pixels in every direction — and keeps the mesh drawable by\n * every path that draws a world-space ribbon.\n *\n * `P` depends only on the lengths the transform induces (`LᵀL`), not on any\n * rotation applied after it, so a view that only pans or zooms uniformly keeps\n * the same metric and the ribbon cache keeps hitting.\n */\nimport type { Polyline } from '@weasel-js/geom/tessellate';\n\n/** `P` = [[p, q], [q, r]], with `pr − q² = 1`. */\nexport interface StrokeMetric {\n readonly p: number;\n readonly q: number;\n readonly r: number;\n}\n\n/** A space a screen-sized part of a stroke is built in: the metric, and how\n * many screen pixels one of its units is. */\nexport interface ScreenSpace {\n readonly metric: StrokeMetric;\n readonly pxPerUnit: number;\n}\n\n/**\n * Where each part of a stroke is built. An absent part is built in world:\n * everything is under a similarity, and otherwise a part whose size is a world\n * length. The ribbon is screen-sized for a `{ px }` width; a head for a\n * `{ px }` size, or for no size on a screen-sized ribbon, since it then takes\n * the stroke width.\n */\nexport interface StrokeSpaces {\n readonly ribbon?: ScreenSpace;\n readonly start?: ScreenSpace;\n readonly mid?: ScreenSpace;\n readonly end?: ScreenSpace;\n}\n\n/** A cache-key fragment naming `space`; empty for world. */\nexport function screenSpaceKey(space: ScreenSpace | undefined): string {\n return space === undefined ? '' : `${metricKey(space.metric)}@${space.pxPerUnit}`;\n}\n\n/** Below this, a stretch is a rounding error and the transform a similarity. */\nconst CONFORMAL_EPSILON = 1e-9;\n\n/**\n * Split the linear map `x' = a·x + c·y, y' = b·x + d·y` — a GL `mat3`'s\n * `m[0], m[1], m[3], m[4]` — into its geometric-mean scale and its stroke\n * metric. `metric` is `null` when the map is a similarity, where world space\n * already measures like the screen; `scale` is `0` for a singular map.\n */\nexport function strokeSpaceOf(\n a: number, b: number, c: number, d: number,\n): { scale: number; metric: StrokeMetric | null } {\n const det2 = Math.abs(a * d - b * c);\n const scale = Math.sqrt(det2);\n if (!(det2 > 0) || !Number.isFinite(det2)) return { scale: 0, metric: null };\n // G = LᵀL / det, whose determinant is 1, so √G = (G + I) / √(tr G + 2).\n const g11 = (a * a + b * b) / det2;\n const g12 = (a * c + b * d) / det2;\n const g22 = (c * c + d * d) / det2;\n const s = Math.sqrt(g11 + g22 + 2);\n const p = (g11 + 1) / s;\n const q = g12 / s;\n const r = (g22 + 1) / s;\n if (Math.abs(q) < CONFORMAL_EPSILON && Math.abs(p - r) < CONFORMAL_EPSILON) {\n return { scale, metric: null };\n }\n return { scale, metric: { p, q, r } };\n}\n\n/** A cache-key fragment naming `metric`; empty for none. */\nexport function metricKey(metric: StrokeMetric | undefined): string {\n return metric === undefined ? '' : `${metric.p},${metric.q},${metric.r}`;\n}\n\n/** Map `pl`'s points through `P`, in place. */\nexport function polylineIntoMetric(pl: Polyline, m: StrokeMetric): void {\n const pts = pl.points;\n for (let i = 0; i < pts.length; i += 2) {\n const x = pts[i], y = pts[i + 1];\n pts[i] = m.p * x + m.q * y;\n pts[i + 1] = m.q * x + m.r * y;\n }\n}\n\n/** Map `pl`'s points back out through `P⁻¹`, in place. */\nexport function polylineOutOfMetric(pl: Polyline, m: StrokeMetric): void {\n const pts = pl.points;\n for (let i = 0; i < pts.length; i += 2) {\n const x = pts[i], y = pts[i + 1];\n pts[i] = m.r * x - m.q * y;\n pts[i + 1] = m.p * y - m.q * x;\n }\n}\n\n/** Whether two spaces are the same — world being `null`. */\nexport function sameMetric(a: StrokeMetric | null, b: StrokeMetric | null): boolean {\n if (a === b) return true;\n return a !== null && b !== null && a.p === b.p && a.q === b.q && a.r === b.r;\n}\n\n/**\n * What one world unit of width, across a line running along the unit\n * direction `(tx, ty)` of the metric's own space, measures in that space.\n * `P` keeps areas, so a strip keeps its area while its length stretches by\n * `|P u|` (`u` the line's world direction): its width shrinks by the same,\n * and `1 / |P u|` is `|P⁻¹ t|`.\n */\nexport function worldWidthInMetric(m: StrokeMetric, tx: number, ty: number): number {\n return Math.hypot(m.r * tx - m.q * ty, m.p * ty - m.q * tx);\n}\n\n/** The same, for a line running along the unit world direction `(ux, uy)`. */\nexport function worldWidthInMetricAlongWorld(m: StrokeMetric, ux: number, uy: number): number {\n return 1 / Math.hypot(m.p * ux + m.q * uy, m.q * ux + m.r * uy);\n}\n\n/** Map interleaved x,y pairs back out through `P⁻¹` = [[r, −q], [−q, p]], in\n * place. */\nexport function coordsOutOfMetric(coords: Float32Array, m: StrokeMetric): void {\n for (let i = 0; i < coords.length; i += 2) {\n const x = coords[i], y = coords[i + 1];\n coords[i] = m.r * x - m.q * y;\n coords[i + 1] = m.p * y - m.q * x;\n }\n}\n\n/** Whether `P` takes an axis-aligned rect to another one. */\nexport function metricKeepsRects(m: StrokeMetric): boolean {\n return m.q === 0;\n}\n\n/** `rect` in the metric's space, while `P` keeps it axis-aligned; otherwise\n * `null`, and the rect has to be carried as a polygon. */\nexport function rectIntoMetric(\n rect: { x: number; y: number; width: number; height: number },\n m: StrokeMetric,\n): { kind: 'rect'; x: number; y: number; width: number; height: number } | null {\n if (!metricKeepsRects(m)) return null;\n return { kind: 'rect', x: m.p * rect.x, y: m.r * rect.y, width: m.p * rect.width, height: m.r * rect.height };\n}\n","/**\n * Trimming a stroke's ends where each inset is measured.\n *\n * A head stops the line by a length in the head's own space, which need not be\n * the ribbon's: a world-sized head on a `{ px }` stroke stops it a world\n * distance short, a `{ px }` head on a world-width stroke a screen distance.\n * Under a stretching view one length means different distances in the two\n * spaces depending on which way the line runs, so each end is trimmed in its\n * own space rather than converted.\n */\nimport { type Polyline, trimPolyline } from '@weasel-js/geom/tessellate';\nimport {\n type StrokeMetric, polylineIntoMetric, polylineOutOfMetric, sameMetric,\n} from './metric';\n\n/** A length along the line measured in `metric`'s space, or in world where\n * `metric` is `null`. */\nexport interface MeasuredLength {\n readonly length: number;\n readonly metric: StrokeMetric | null;\n}\n\n/** A plain number is a length in the ribbon's own space. */\nexport type InsetLength = number | MeasuredLength;\n\ninterface Trim {\n length: number;\n metric: StrokeMetric | null;\n}\n\nconst trimOf = (inset: InsetLength | undefined, ribbon: StrokeMetric | null): Trim =>\n inset === undefined ? { length: 0, metric: ribbon }\n : typeof inset === 'number' ? { length: inset, metric: ribbon }\n : inset;\n\n/**\n * `pl`, whose points are in `from`'s space, trimmed by `start` and `end` and\n * carried into `ribbon`'s — `null` for world in both. `pl` may be mapped in\n * place. Returns `null` when the insets consume the whole run.\n */\nexport function trimInSpace(\n pl: Polyline,\n from: StrokeMetric | null,\n ribbon: StrokeMetric | null,\n start: InsetLength | undefined,\n end: InsetLength | undefined,\n): Polyline | null {\n const s = trimOf(start, ribbon);\n const e = trimOf(end, ribbon);\n let cur: Polyline | null = pl;\n let space = from;\n const moveTo = (to: StrokeMetric | null) => {\n if (cur === null || sameMetric(space, to)) return;\n if (space !== null) polylineOutOfMetric(cur, space);\n if (to !== null) polylineIntoMetric(cur, to);\n space = to;\n };\n if (s.length > 0 || e.length > 0) {\n if (sameMetric(s.metric, e.metric)) {\n moveTo(s.metric);\n cur = trimPolyline(cur, s.length, e.length);\n } else {\n for (const [len, metric, atStart] of [[s.length, s.metric, true], [e.length, e.metric, false]] as const) {\n if (!(len > 0) || cur === null) continue;\n moveTo(metric);\n cur = trimPolyline(cur, atStart ? len : 0, atStart ? 0 : len);\n }\n }\n }\n moveTo(ribbon);\n return cur;\n}\n","import type { Path } from '@weasel-js/geom';\nimport type { ScreenLength, Stroke } from '@weasel-js/paint';\nimport { alignedStrokeRect, resolveScreenLength } from '@weasel-js/paint';\nimport { type Mesh, extractPolylines, type Polyline } from '@weasel-js/geom/tessellate';\nimport { splitForDash } from './dash';\nimport { strokeFlattening } from './flattening';\nimport { populatePolylineWidths, type WidthScale } from './vertexWidths';\nimport { type InsetLength, trimInSpace } from './insets';\nimport {\n type StrokeMetric, coordsOutOfMetric, rectIntoMetric, worldWidthInMetric, worldWidthInMetricAlongWorld,\n} from './metric';\n\n/** Options for stroke tessellation. */\nexport interface StrokeOptions {\n flattenTolerance?: number;\n /**\n * Shorten each open subpath by this much at its start / end: a length in\n * the ribbon's space, or one measured in a space of its own. Stroke markers\n * use this so a filled head is not speared by its own line; the caller\n * resolves the distance, because this layer knows nothing about the marker\n * registry.\n */\n startInset?: InsetLength;\n endInset?: InsetLength;\n /**\n * Build the ribbon in this metric's space and map it back out, so the\n * transform it was derived from draws it at an exact screen width — see\n * `./metric`. Width and dash are then lengths in that space; `vertexWidths`\n * stay world widths. The path is flattened in world first, so the ribbon\n * follows the same vertices its fill does.\n */\n metric?: StrokeMetric;\n}\n\nconst EMPTY_MESH: Mesh = {\n vertices: new Float32Array(0),\n indices: new Uint32Array(0),\n anchorA: new Uint32Array(0),\n anchorB: new Uint32Array(0),\n anchorT: new Float32Array(0),\n};\n\ntype Cap = 'butt' | 'round' | 'square';\ntype Join = 'miter' | 'round' | 'bevel';\n\n/** Per-segment data the join code needs. */\ninterface Seg {\n ax: number; ay: number;\n bx: number; by: number;\n /** Unit perpendicular (rotated 90° CCW from direction). */\n nxUnit: number; nyUnit: number;\n /** Half-width at the start (a) and end (b) endpoints. Equal for uniform\n * strokes; differ when the polyline carries per-point widths. */\n halfA: number; halfB: number;\n len: number;\n}\n\n/** Resolve a stroke width to world units. A number is already world units;\n * `{ px }` is screen pixels divided by the accumulated scale, so it holds its\n * on-screen thickness as the view zooms. */\nexport function resolveStrokeWidth(width: ScreenLength, scale: number): number {\n return resolveScreenLength(width, scale);\n}\n\n/**\n * Build a triangle-mesh ribbon from a stroked Path.\n *\n * Supports:\n * - cap: 'butt' | 'round' | 'square'\n * - join: 'miter' | 'round' | 'bevel'\n * - center alignment directly; RectPath inner/outer alignment via a\n * pre-shifted rect; PolygonPath inner/outer alignment via stencil at the\n * renderer level\n * - dash splitting\n */\nexport function tessellateStroke(\n path: Path,\n stroke: Stroke,\n opts: StrokeOptions = {},\n): Mesh {\n // The renderer resolves `{ px }` against the accumulated transform before it\n // gets here; a stroke that reaches the tessellator unresolved is read at\n // scale 1, matching what the ribbon cache keys it under.\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n if (width <= 0) return EMPTY_MESH;\n const join: Join = stroke.join ?? 'miter';\n const cap: Cap = stroke.cap ?? 'butt';\n const align = stroke.align ?? 'center';\n const miterLimit = stroke.miterLimit ?? DEFAULT_MITER_LIMIT;\n const varyingThreshold = stroke.varyingWidthJoinThreshold ?? DEFAULT_VARYING_WIDTH_JOIN_THRESHOLD;\n\n // RectPath fast path for inner/outer alignment: shift the rect by half-width\n // so the ribbon's center alignment lands the stroke on the desired side of\n // the original geometric edge. Arbitrary paths handle alignment via stencil\n // clipping at the renderer level (not here).\n const metric = opts.metric;\n const rectInMetric = metric && path.kind === 'rect' ? rectIntoMetric(path, metric) : null;\n let workingPath: Path = rectInMetric ?? path;\n if (workingPath.kind === 'rect' && align !== 'center') {\n workingPath = { kind: 'rect', ...alignedStrokeRect(workingPath, align, width) };\n }\n\n // Per-point widths come first, in the space the points are in, so a trim\n // interpolates them rather than re-reading an anchor's.\n const vertexWidths = stroke.vertexWidths && stroke.vertexWidths.length > 0 ? stroke.vertexWidths : null;\n const polylines = extractPolylines(workingPath, strokeFlattening(opts.flattenTolerance, width, vertexWidths ?? undefined));\n const scale: WidthScale | undefined = !metric ? undefined\n : rectInMetric ? (tx, ty) => worldWidthInMetric(metric, tx, ty)\n : (ux, uy) => worldWidthInMetricAlongWorld(metric, ux, uy);\n const dash = stroke.dash ?? [];\n const verts: number[] = [];\n const idx: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n\n // Trim before dashing, so the dash pattern fits the visible line rather than\n // running off under a marker head.\n const ribbonSpace = metric ?? null;\n for (const pl of polylines) {\n if (vertexWidths) populatePolylineWidths(pl, vertexWidths, width, scale);\n const trimmed = trimInSpace(pl, rectInMetric ? ribbonSpace : null, ribbonSpace, opts.startInset, opts.endInset);\n if (trimmed === null) continue;\n const subs = dash.length > 0 ? splitForDash(trimmed, dash) : [trimmed];\n for (const sub of subs) {\n expandPolyline(sub, width, join, cap, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT);\n }\n }\n\n const vertices = new Float32Array(verts);\n if (metric) coordsOutOfMetric(vertices, metric);\n return {\n vertices,\n indices: new Uint32Array(idx),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n\nfunction expandPolyline(\n pl: Polyline,\n width: number,\n join: Join,\n cap: Cap,\n miterLimit: number,\n varyingThreshold: number,\n verts: number[],\n idx: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): void {\n const half = width / 2;\n const pts = pl.points;\n const ptCount = pts.length / 2;\n const segCount = ptCount - 1;\n if (segCount < 1) return;\n\n // Anchor params per polyline point (set by extractPolylines; splitForDash\n // re-derives them on dash boundaries). Default to A=B=0,t=0 if missing.\n const plA = pl.anchorA ?? new Uint32Array(ptCount);\n const plB = pl.anchorB ?? new Uint32Array(ptCount);\n const plT = pl.anchorT ?? new Float32Array(ptCount);\n // Per-point half-widths: derived from pl.widths if present, else the\n // uniform half. Indexing matches `pts` (one entry per polyline point).\n const plHalf = pl.widths\n ? pl.widths.map((w) => w / 2)\n : null;\n\n const segs: Seg[] = [];\n const segSrcIdx: number[] = []; // For each seg, the polyline-point index of its start.\n for (let s = 0; s < segCount; s++) {\n const ha = plHalf ? plHalf[s] : half;\n const hb = plHalf ? plHalf[s + 1] : half;\n const seg = makeSeg(pts[s * 2], pts[s * 2 + 1], pts[(s + 1) * 2], pts[(s + 1) * 2 + 1], ha, hb);\n if (seg) {\n segs.push(seg);\n segSrcIdx.push(s);\n }\n }\n let closerSrcIdx = -1;\n if (pl.closed && segs.length >= 1) {\n const last = segs[segs.length - 1];\n const first = segs[0];\n // Closer: from last point back to point 0. Half-widths are the\n // already-resolved ones at those source indices.\n const haCloser = plHalf ? plHalf[ptCount - 1] : half;\n const hbCloser = plHalf ? plHalf[0] : half;\n const closer = makeSeg(last.bx, last.by, first.ax, first.ay, haCloser, hbCloser);\n if (closer) {\n segs.push(closer);\n closerSrcIdx = ptCount - 1; // start is the last polyline point.\n segSrcIdx.push(closerSrcIdx);\n }\n }\n if (segs.length === 0) return;\n\n // Emit ribbon quads. For each emitted vertex, record the (A, B, t) of the\n // source polyline point that the geometric vertex sits at. Per-end\n // half-widths produce trapezoidal segments when the stroke tapers.\n const segBaseIdx: number[] = [];\n for (let s = 0; s < segs.length; s++) {\n const seg = segs[s];\n const startSrc = segSrcIdx[s];\n // End-source index for the seg. For closer (closed-path wraparound), end is point 0.\n const endSrc = (s === segs.length - 1 && pl.closed && closerSrcIdx >= 0) ? 0 : startSrc + 1;\n const base = verts.length / 2;\n segBaseIdx.push(base);\n const nxA = seg.nxUnit * seg.halfA, nyA = seg.nyUnit * seg.halfA;\n const nxB = seg.nxUnit * seg.halfB, nyB = seg.nyUnit * seg.halfB;\n // L0, R0 — at seg.ax/ay with start half-width.\n verts.push(seg.ax + nxA, seg.ay + nyA);\n anchorA.push(plA[startSrc]); anchorB.push(plB[startSrc]); anchorT.push(plT[startSrc]);\n verts.push(seg.ax - nxA, seg.ay - nyA);\n anchorA.push(plA[startSrc]); anchorB.push(plB[startSrc]); anchorT.push(plT[startSrc]);\n // L1, R1 — at seg.bx/by with end half-width.\n verts.push(seg.bx + nxB, seg.by + nyB);\n anchorA.push(plA[endSrc]); anchorB.push(plB[endSrc]); anchorT.push(plT[endSrc]);\n verts.push(seg.bx - nxB, seg.by - nyB);\n anchorA.push(plA[endSrc]); anchorB.push(plB[endSrc]); anchorT.push(plT[endSrc]);\n idx.push(base, base + 1, base + 2, base + 1, base + 3, base + 2);\n }\n\n // Joins between consecutive segments.\n const joinCount = pl.closed ? segs.length : segs.length - 1;\n for (let j = 0; j < joinCount; j++) {\n emitJoin(segs, segBaseIdx, j, join, miterLimit, varyingThreshold, verts, idx, anchorA, anchorB, anchorT, segSrcIdx, plA, plB, plT);\n }\n\n // Caps. Use the local half-width at the cap end (seg.halfA at start, seg.halfB at end).\n if (!pl.closed && cap !== 'butt') {\n const first = segs[0];\n const firstBase = segBaseIdx[0];\n emitCap(first, firstBase + 0, firstBase + 1, false, first.halfA, cap, verts, idx, anchorA, anchorB, anchorT, plA[0], plB[0], plT[0]);\n\n const last = segs[segs.length - 1];\n const lastBase = segBaseIdx[segs.length - 1];\n const lastSrc = segSrcIdx[segs.length - 1] + 1;\n emitCap(last, lastBase + 2, lastBase + 3, true, last.halfB, cap, verts, idx, anchorA, anchorB, anchorT, plA[lastSrc], plB[lastSrc], plT[lastSrc]);\n }\n}\n\nconst ROUND_CAP_STEP_RAD = (10 * Math.PI) / 180;\n\n/**\n * Emit a cap at one end of a segment. `leftIdx`/`rightIdx` are the buffer\n * indices of the L (perpendicular +n) and R (perpendicular -n) vertices at\n * the segment endpoint where the cap attaches. `atEnd` chooses which end of\n * the segment to extend from (and which cap-direction sign to use).\n */\nfunction emitCap(\n seg: Seg, leftIdx: number, rightIdx: number, atEnd: boolean,\n half: number, cap: Cap,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n endA: number, endB: number, endT: number,\n): void {\n // Outward direction = forward at end, backward at start.\n const sign = atEnd ? 1 : -1;\n const dx = (seg.bx - seg.ax) / seg.len * sign;\n const dy = (seg.by - seg.ay) / seg.len * sign;\n const cx = atEnd ? seg.bx : seg.ax;\n const cy = atEnd ? seg.by : seg.ay;\n\n // Perpendicular offset at this cap end uses the local half-width\n // (varies along the polyline when vertexWidths is set).\n const nx = seg.nxUnit * half;\n const ny = seg.nyUnit * half;\n\n if (cap === 'square') {\n const ox = cx + dx * half;\n const oy = cy + dy * half;\n const lOut = verts.length / 2;\n verts.push(ox + nx, oy + ny);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n const rOut = verts.length / 2;\n verts.push(ox - nx, oy - ny);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n // Two triangles forming the cap rectangle. Wind so triangles are CCW\n // viewed from the front; orientation symmetric for start vs. end caps.\n if (atEnd) {\n idx.push(leftIdx, lOut, rOut, leftIdx, rOut, rightIdx);\n } else {\n idx.push(leftIdx, rOut, lOut, leftIdx, rightIdx, rOut);\n }\n return;\n }\n\n if (cap === 'round') {\n // Pivot vertex at the endpoint center; fan from L through the outward\n // 180° arc to R.\n const pivotIdx = verts.length / 2;\n verts.push(cx, cy);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n\n // Starting angle: direction from pivot to L (= +n direction).\n const startAngle = Math.atan2(ny, nx);\n // Sweep 180° toward the outward direction. The outward unit is (dx, dy);\n // we rotate from +n to -n the \"outward\" way. The dot product of (dx, dy)\n // with the perpendicular tells us which way around the arc to go.\n // A start-cap (sign = -1) sweeps backward; end-cap (sign = +1) sweeps forward.\n const sweep = atEnd ? -Math.PI : Math.PI;\n const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_CAP_STEP_RAD));\n const stepAngle = sweep / steps;\n\n let prevIdx = leftIdx;\n for (let i = 1; i < steps; i++) {\n const ang = startAngle + i * stepAngle;\n const fx = cx + Math.cos(ang) * half;\n const fy = cy + Math.sin(ang) * half;\n const newIdx = verts.length / 2;\n verts.push(fx, fy);\n anchorA.push(endA); anchorB.push(endB); anchorT.push(endT);\n if (atEnd) idx.push(prevIdx, newIdx, pivotIdx);\n else idx.push(prevIdx, pivotIdx, newIdx);\n prevIdx = newIdx;\n }\n if (atEnd) idx.push(prevIdx, rightIdx, pivotIdx);\n else idx.push(prevIdx, pivotIdx, rightIdx);\n }\n}\n\nfunction makeSeg(ax: number, ay: number, bx: number, by: number, halfA: number, halfB: number): Seg | null {\n const dx = bx - ax, dy = by - ay;\n const len = Math.hypot(dx, dy);\n if (len === 0) return null;\n return {\n ax, ay, bx, by,\n nxUnit: -dy / len, nyUnit: dx / len,\n halfA, halfB,\n len,\n };\n}\n\n/**\n * Miter limit for a stroke that does not set one. SVG's default, not\n * Canvas2D's 10, because the serializer omits the attribute when the field is\n * unset — so a kit stroke exported to SVG is read back by every other renderer\n * as 4, and a kit that used 10 would disagree with its own export. 10 also\n * lets an acute corner throw a spike four times the half-width, which is what\n * a glyph outline's sharpest vertices do.\n */\nconst DEFAULT_MITER_LIMIT = 4;\n/** Default `Stroke.varyingWidthJoinThreshold`. */\nconst DEFAULT_VARYING_WIDTH_JOIN_THRESHOLD = 1.5;\n\nfunction emitJoin(\n segs: Seg[], segBaseIdx: number[], j: number, join: Join,\n miterLimit: number,\n varyingThreshold: number,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n segSrcIdx: number[],\n plA: Uint32Array, plB: Uint32Array, plT: Float32Array,\n): void {\n const a = segs[j];\n const b = segs[(j + 1) % segs.length];\n const aBase = segBaseIdx[j];\n const bBase = segBaseIdx[(j + 1) % segs.length];\n\n const adx = a.bx - a.ax, ady = a.by - a.ay;\n const bdx = b.bx - b.ax, bdy = b.by - b.ay;\n const cross = adx * bdy - ady * bdx;\n if (cross === 0) return; // straight (collinear), no wedge\n const onPositive = cross > 0;\n\n const aOuterEnd = onPositive ? aBase + 3 : aBase + 2;\n const bOuterStart = onPositive ? bBase + 1 : bBase + 0;\n\n // The corner of join `j` is the start of segment `j+1` (which is the END of\n // segment `j` — they share the same polyline point). For the wraparound join\n // on a closed polyline, j+1 wraps to segment 0 whose start is the closer\n // segment's endpoint, which is polyline point 0.\n const nextSeg = (j + 1) % segs.length;\n // The corner anchor is the start of the next segment (shared endpoint).\n // For a closed path's final join, nextSeg wraps to 0, whose start is\n // polyline point 0 — correct.\n const cornerSrc = segSrcIdx[nextSeg];\n const cornerA = plA[cornerSrc];\n const cornerB = plB[cornerSrc];\n const cornerT = plT[cornerSrc];\n // The two adjoining half-widths agree at the shared corner (a.halfB ===\n // b.halfA for a single-contour polyline), so use either for miter-limit\n // sizing. Force bevel when either adjacent segment itself tapers by\n // more than `varyingThreshold` — the miter apex math computes against\n // outer edges parallel to the segment direction, an assumption that\n // breaks on tapered trapezoids (outer edges fan in/out).\n const halfAtCorner = a.halfB;\n const taperA = Math.max(a.halfA, a.halfB) / Math.max(1e-9, Math.min(a.halfA, a.halfB));\n const taperB = Math.max(b.halfA, b.halfB) / Math.max(1e-9, Math.min(b.halfA, b.halfB));\n const forceBevelForVarying = taperA > varyingThreshold || taperB > varyingThreshold;\n\n if (join === 'bevel' || forceBevelForVarying) {\n emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n\n if (join === 'miter') {\n // Compute apex: intersection of A's outer edge extended forward and\n // B's outer edge extended backward. If miter length > MITER_LIMIT * half,\n // fall back to bevel.\n const aOX = verts[aOuterEnd * 2], aOY = verts[aOuterEnd * 2 + 1];\n const bOX = verts[bOuterStart * 2], bOY = verts[bOuterStart * 2 + 1];\n const apex = lineLineIntersect(aOX, aOY, adx, ady, bOX, bOY, -bdx, -bdy);\n if (!apex) {\n emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n const miterLen = Math.hypot(apex[0] - a.bx, apex[1] - a.by);\n if (miterLen > miterLimit * halfAtCorner) {\n emitBevel(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n // A miter join's outer face is a kite quadrilateral with vertices\n // (R1, apex, R0, J) — covered by TWO triangles. The bevel inner half\n // (R1, R0, J) fills the area between the joint corner and the diagonal\n // hypotenuse R0-R1; the outer extension (R1, apex, R0) fills from the\n // hypotenuse to the apex point. Without the bevel half, an \"inverted\n // triangle\" gap opens at every miter corner.\n const apexIdx = verts.length / 2;\n verts.push(apex[0], apex[1]);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n const jIdx = verts.length / 2;\n verts.push(a.bx, a.by);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n if (onPositive) {\n idx.push(aOuterEnd, apexIdx, bOuterStart);\n idx.push(aOuterEnd, bOuterStart, jIdx);\n } else {\n idx.push(aOuterEnd, bOuterStart, apexIdx);\n idx.push(aOuterEnd, jIdx, bOuterStart);\n }\n return;\n }\n\n if (join === 'round') {\n emitRoundJoin(a, aOuterEnd, bOuterStart, onPositive, verts, idx, anchorA, anchorB, anchorT, cornerA, cornerB, cornerT);\n return;\n }\n}\n\nconst ROUND_STEP_RAD = (10 * Math.PI) / 180; // ~10° per fan triangle\n\nfunction emitRoundJoin(\n a: Seg, aOuterEnd: number, bOuterStart: number, onPositive: boolean,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n cornerA: number, cornerB: number, cornerT: number,\n): void {\n // Pivot = joint center; emit fresh vertex.\n const cx = a.bx, cy = a.by;\n const pivotIdx = verts.length / 2;\n verts.push(cx, cy);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n\n const startX = verts[aOuterEnd * 2] - cx;\n const startY = verts[aOuterEnd * 2 + 1] - cy;\n const endX = verts[bOuterStart * 2] - cx;\n const endY = verts[bOuterStart * 2 + 1] - cy;\n const r = Math.hypot(startX, startY);\n\n const startAngle = Math.atan2(startY, startX);\n const endAngle = Math.atan2(endY, endX);\n // Outer-side sweep: for CCW turns (cross > 0, onPositive true) outer is on\n // the -n side and the arc sweeps from R1 (south of joint) clockwise to R0\n // (east of joint) — i.e., negative sweep. For CW turns, sweep is positive.\n // Pick the SHORT arc that crosses the outer wedge. For onPositive=true\n // (CW turn in screen coords with y-down), the outer wedge sits where the\n // natural sweep is positive; for onPositive=false, where it is negative.\n // If the natural sweep has the wrong sign, wrap by ±2π.\n let sweep = endAngle - startAngle;\n if (onPositive && sweep < 0) sweep += 2 * Math.PI;\n else if (!onPositive && sweep > 0) sweep -= 2 * Math.PI;\n\n const steps = Math.max(1, Math.ceil(Math.abs(sweep) / ROUND_STEP_RAD));\n const stepAngle = sweep / steps;\n\n let prevIdx = aOuterEnd;\n for (let i = 1; i < steps; i++) {\n const ang = startAngle + i * stepAngle;\n const fx = cx + Math.cos(ang) * r;\n const fy = cy + Math.sin(ang) * r;\n const newIdx = verts.length / 2;\n verts.push(fx, fy);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n if (onPositive) idx.push(prevIdx, pivotIdx, newIdx);\n else idx.push(prevIdx, newIdx, pivotIdx);\n prevIdx = newIdx;\n }\n if (onPositive) idx.push(prevIdx, pivotIdx, bOuterStart);\n else idx.push(prevIdx, bOuterStart, pivotIdx);\n}\n\nfunction emitBevel(\n a: Seg, aOuterEnd: number, bOuterStart: number, onPositive: boolean,\n verts: number[], idx: number[],\n anchorA: number[], anchorB: number[], anchorT: number[],\n cornerA: number, cornerB: number, cornerT: number,\n): void {\n const jIdx = verts.length / 2;\n verts.push(a.bx, a.by);\n anchorA.push(cornerA); anchorB.push(cornerB); anchorT.push(cornerT);\n if (onPositive) idx.push(aOuterEnd, jIdx, bOuterStart);\n else idx.push(aOuterEnd, bOuterStart, jIdx);\n}\n\n/**\n * Solve for the intersection of line A (point ap, direction ad) with line B\n * (point bp, direction bd). Returns null if parallel or near-parallel.\n */\nfunction lineLineIntersect(\n apx: number, apy: number, adx: number, ady: number,\n bpx: number, bpy: number, bdx: number, bdy: number,\n): [number, number] | null {\n const denom = adx * bdy - ady * bdx;\n if (Math.abs(denom) < 1e-9) return null;\n const t = ((bpx - apx) * bdy - (bpy - apy) * bdx) / denom;\n return [apx + t * adx, apy + t * ady];\n}\n","/**\n * Resolving a `MarkerRef` to the distance the ribbon must stop short.\n *\n * The tessellation layer takes these as plain numbers and knows nothing about\n * the registry — keeping that layer free of upward dependencies is deliberate.\n * The ribbon cache, the SVG serializer and `inkReach` all resolve through here,\n * so the ribbon, the export and the hit region cannot disagree about where the\n * line ends.\n */\n\nimport { resolveScreenLength, type MarkerRef, type Stroke } from '@weasel-js/paint';\nimport { getMarker } from './strokeMarkers';\n\n/** The size of one marker unit, in the same world units as `strokeWidth`.\n * `scale` is the view scale a `{ px }` size resolves against, as a `{ px }`\n * stroke width does. */\nexport function resolveMarkerSize(ref: MarkerRef, strokeWidth: number, scale = 1): number {\n if (typeof ref === 'string' || ref.size === undefined) return strokeWidth;\n return resolveScreenLength(ref.size, scale);\n}\n\n/** The registry key a `MarkerRef` names, whether given bare or with a size. */\nexport function markerKeyOf(ref: MarkerRef): string {\n return typeof ref === 'string' ? ref : ref.key;\n}\n\n/**\n * How far back the ribbon stops for `ref`, in world units. Zero for an absent\n * marker, an unregistered key, or an open head — never throws, because an\n * unknown key is a data problem and dropping the head is the graceful answer.\n */\nexport function markerInset(ref: MarkerRef | undefined, strokeWidth: number, scale = 1): number {\n if (ref === undefined) return 0;\n const entry = getMarker(markerKeyOf(ref));\n if (entry === undefined) return 0;\n return (entry.inset ?? 0) * resolveMarkerSize(ref, strokeWidth, scale);\n}\n\n/** The start and end insets a stroke asks for. `markerMid` never insets —\n * trimming at an interior vertex would cut the line in two. */\nexport function strokeInsets(stroke: Stroke, strokeWidth: number): { start: number; end: number } {\n return {\n start: markerInset(stroke.markerStart, strokeWidth),\n end: markerInset(stroke.markerEnd, strokeWidth),\n };\n}\n","/**\n * Where a stroke's markers sit and which way they point.\n *\n * Computed from the *untrimmed* polyline: trimming moves the endpoint, and a\n * marker anchors to where the line was authored to end, not to where the\n * ribbon was cut.\n */\n\nimport type { Polyline } from '@weasel-js/geom/tessellate';\n\n/** One marker placement, in the polyline's own coordinates. */\nexport interface MarkerSite {\n x: number;\n y: number;\n /** Radians. The direction the marker's +X axis should point — outward at a\n * start or end, along the bisector at an interior vertex. */\n angle: number;\n role: 'start' | 'mid' | 'end';\n}\n\n/** Which marker roles to place. `start` and `end` are ignored on a closed polyline. */\nexport interface MarkerSiteRequest {\n start: boolean;\n mid: boolean;\n end: boolean;\n}\n\nconst EPS = 1e-9;\n\n/** Unit direction from point `i` to point `j`, or null if they coincide. */\nfunction dir(pl: Polyline, i: number, j: number): { x: number; y: number } | null {\n const dx = pl.points[j * 2] - pl.points[i * 2];\n const dy = pl.points[j * 2 + 1] - pl.points[i * 2 + 1];\n const len = Math.hypot(dx, dy);\n if (len < EPS) return null;\n return { x: dx / len, y: dy / len };\n}\n\n/** The first index after `i` whose point differs from `i`'s. */\nfunction nextDistinct(pl: Polyline, i: number, n: number): number {\n for (let k = i + 1; k < n; k++) if (dir(pl, i, k)) return k;\n return -1;\n}\nfunction prevDistinct(pl: Polyline, i: number): number {\n for (let k = i - 1; k >= 0; k--) if (dir(pl, k, i)) return k;\n return -1;\n}\n\n/**\n * Where each requested marker sits on `pl` and the angle it points at.\n * Mid sites fall only on authored vertices, never on flattened curve samples,\n * and need the polyline to carry anchor data; without it no mid sites are returned.\n */\nexport function markerSites(pl: Polyline, want: MarkerSiteRequest): MarkerSite[] {\n const out: MarkerSite[] = [];\n const n = pl.points.length / 2;\n if (n < 2) return out;\n\n if (want.start && !pl.closed) {\n const j = nextDistinct(pl, 0, n);\n const d = j >= 0 ? dir(pl, 0, j) : null;\n if (d) {\n // Reversed, so a start head points away from the line body the way an\n // end head does. SVG spells this `auto-start-reverse`; here it is the\n // only behavior.\n out.push({ x: pl.points[0], y: pl.points[1], angle: Math.atan2(-d.y, -d.x), role: 'start' });\n }\n }\n\n if (want.mid) {\n const A = pl.anchorA, B = pl.anchorB, T = pl.anchorT;\n if (A && B && T) {\n for (let i = 1; i < n - 1; i++) {\n // An authored anchor, not a flattened curve sample.\n if (A[i] !== B[i] || T[i] !== 0) continue;\n const p = prevDistinct(pl, i);\n const q = nextDistinct(pl, i, n);\n if (p < 0 || q < 0) continue;\n const inDir = dir(pl, p, i)!;\n const outDir = dir(pl, i, q)!;\n let bx = inDir.x + outDir.x;\n let by = inDir.y + outDir.y;\n // A 180° reversal leaves no bisector; fall back to the arriving direction.\n if (Math.hypot(bx, by) < EPS) { bx = inDir.x; by = inDir.y; }\n out.push({ x: pl.points[i * 2], y: pl.points[i * 2 + 1], angle: Math.atan2(by, bx), role: 'mid' });\n }\n }\n }\n\n if (want.end && !pl.closed) {\n const last = n - 1;\n const p = prevDistinct(pl, last);\n const d = p >= 0 ? dir(pl, p, last) : null;\n if (d) {\n out.push({ x: pl.points[last * 2], y: pl.points[last * 2 + 1], angle: Math.atan2(d.y, d.x), role: 'end' });\n }\n }\n\n return out;\n}\n","/**\n * A stroke's marker heads as placed geometry, and how far they reach.\n */\n\nimport type { MarkerRef, Stroke } from '@weasel-js/paint';\nimport { type Path, type PolygonPath, boundsOfPath } from '@weasel-js/geom';\nimport { extractPolylines } from '@weasel-js/geom/tessellate';\nimport { getMarker, type MarkerEntry } from './strokeMarkers';\nimport { markerKeyOf, resolveMarkerSize } from './markerInset';\nimport { markerSites, type MarkerSite } from './markerSites';\nimport { strokeFlattening } from './tessellate/flattening';\nimport {\n coordsOutOfMetric, polylineIntoMetric, type ScreenSpace, type StrokeSpaces,\n} from './tessellate/metric';\n\n/** Rotate + translate a marker's geometry onto its site. */\nfunction placed(path: Path, site: MarkerSite): PolygonPath {\n const src = path as PolygonPath;\n const cos = Math.cos(site.angle);\n const sin = Math.sin(site.angle);\n const coords = new Float32Array(src.coords.length);\n for (let i = 0; i < src.coords.length; i += 2) {\n const x = src.coords[i], y = src.coords[i + 1];\n coords[i] = site.x + x * cos - y * sin;\n coords[i + 1] = site.y + x * sin + y * cos;\n }\n return { ...src, coords };\n}\n\n/** One head's placed geometry, before any paint is applied. */\nexport interface MarkerHead {\n readonly entry: MarkerEntry;\n readonly path: PolygonPath;\n readonly size: number;\n /** Where it was built, when not in world — `size` is in this space's units. */\n readonly space?: ScreenSpace;\n}\n\n/**\n * Every marker head for `path` under `stroke`, placed but unpainted.\n * `strokeWidth` is the already width-resolved stroke width; `flattenTolerance`\n * matches what the ribbon used, so heads land on the same flattened vertices\n * the stroke did. A head `spaces` puts in a screen space is placed and sized\n * there and comes back in world units, so it meets the line it caps.\n */\nexport function markerHeads(\n path: Path,\n stroke: Stroke,\n strokeWidth: number,\n flattenTolerance: number | undefined,\n spaces: StrokeSpaces = {},\n): MarkerHead[] {\n const refs = { start: stroke.markerStart, mid: stroke.markerMid, end: stroke.markerEnd };\n if (refs.start === undefined && refs.mid === undefined && refs.end === undefined) return [];\n\n // Heads sharing a space share one pass over the polyline mapped into it.\n const groups = new Map<ScreenSpace | undefined, { start: boolean; mid: boolean; end: boolean }>();\n for (const role of ['start', 'mid', 'end'] as const) {\n if (refs[role] === undefined) continue;\n const space = spaces[role];\n let want = groups.get(space);\n if (want === undefined) groups.set(space, (want = { start: false, mid: false, end: false }));\n want[role] = true;\n }\n\n const out: MarkerHead[] = [];\n for (const pl of extractPolylines(path, strokeFlattening(flattenTolerance, strokeWidth, stroke.vertexWidths))) {\n for (const [space, want] of groups) {\n const inSpace = space ? { ...pl, points: pl.points.slice() } : pl;\n if (space) polylineIntoMetric(inSpace, space.metric);\n for (const site of markerSites(inSpace, want)) {\n const ref: MarkerRef | undefined = refs[site.role];\n if (ref === undefined) continue;\n const entry = getMarker(markerKeyOf(ref));\n if (entry === undefined) continue;\n const size = resolveMarkerSize(ref, strokeWidth);\n const angle = entry.orient === undefined || entry.orient === 'auto' ? site.angle : entry.orient;\n const head = placed(entry.path({ size, stroke }), { ...site, angle });\n if (space) coordsOutOfMetric(head.coords, space.metric);\n out.push(space ? { entry, size, path: head, space } : { entry, size, path: head });\n }\n }\n }\n return out;\n}\n\n/**\n * A key for the stroke fields `entry`'s geometry reads, or `null` when the\n * entry does not say which it reads and only the stroke's identity can stand\n * in for them.\n */\nexport function markerReadsKey(entry: MarkerEntry, stroke: Stroke): string | null {\n if (entry.reads === undefined) return null;\n let key = '';\n for (const field of entry.reads) key += `${JSON.stringify(stroke[field]) ?? ''}|`;\n return key;\n}\n\n/** Distinct stroke readings kept per entry before its map is dropped. */\nconst READINGS_PER_ENTRY = 64;\n\n/** Each entry's farthest reach from its anchor at `size` 1, outline included,\n * per value of the fields it reads — or per stroke object, when it does not\n * say which. */\nconst REACH_BY_READING = new WeakMap<MarkerEntry, Map<string, number>>();\nconst REACH_BY_STROKE = new WeakMap<MarkerEntry, WeakMap<Stroke, number>>();\n\nfunction measureUnitReach(entry: MarkerEntry, stroke: Stroke): number {\n const b = boundsOfPath(entry.path({ size: 1, stroke }));\n return Math.max(Math.abs(b.x), Math.abs(b.x + b.width), Math.abs(b.y), Math.abs(b.y + b.height))\n + (entry.outline ? entry.outline.width / 2 : 0);\n}\n\nfunction unitReach(entry: MarkerEntry, stroke: Stroke): number {\n const key = markerReadsKey(entry, stroke);\n if (key === null) {\n let byStroke = REACH_BY_STROKE.get(entry);\n if (byStroke === undefined) REACH_BY_STROKE.set(entry, (byStroke = new WeakMap()));\n let reach = byStroke.get(stroke);\n if (reach === undefined) byStroke.set(stroke, (reach = measureUnitReach(entry, stroke)));\n return reach;\n }\n let byReading = REACH_BY_READING.get(entry);\n if (byReading === undefined) REACH_BY_READING.set(entry, (byReading = new Map()));\n let reach = byReading.get(key);\n if (reach === undefined) {\n if (byReading.size >= READINGS_PER_ENTRY) byReading.clear();\n byReading.set(key, (reach = measureUnitReach(entry, stroke)));\n }\n return reach;\n}\n\n/**\n * How far `stroke`'s markers can paint from the vertex each sits on, split by\n * where each is built: `world` in world units for a head with a world size,\n * `px` in screen pixels for one with a `{ px }` size. A head with no size\n * takes the stroke width, and with it the width's units. Culling and a path\n * node's grab reach both measure through here.\n */\nexport function markerReach(stroke: Stroke): { world: number; px: number } {\n const reach = { world: 0, px: 0 };\n const width = stroke.width ?? 1;\n for (const ref of [stroke.markerStart, stroke.markerMid, stroke.markerEnd]) {\n if (ref === undefined) continue;\n const entry = getMarker(markerKeyOf(ref));\n if (entry === undefined) continue;\n const size = typeof ref === 'string' || ref.size === undefined ? width : ref.size;\n const unit = unitReach(entry, stroke);\n if (typeof size === 'number') reach.world = Math.max(reach.world, unit * size);\n else reach.px = Math.max(reach.px, unit * size.px);\n }\n return reach;\n}\n","/**\n * A stroke as geometry: the region its ink covers, as a fillable path.\n *\n * The ribbon the renderer draws already has the joins, caps, dashes, and\n * marker trims; unioning its triangles gives the silhouette with every\n * self-overlap resolved, so the outline and the drawn stroke cannot disagree.\n */\nimport type { Stroke } from '@weasel-js/paint';\nimport { invert, transformPath, type Affine, type Path, type PolygonPath } from '@weasel-js/geom';\nimport { pathIntersect, pathSubtract, pathUnion, trianglesToPath } from '@weasel-js/geom/booleans';\nimport { strokeInsets } from './markerInset';\nimport { resolveStrokeWidth, tessellateStroke } from './tessellate/stroke';\nimport { markerHeads } from './markerHeads';\n\n/** Options for {@link strokeToPath}. */\nexport interface StrokeToPathOptions {\n /** Screen pixels per world unit, for a `{ px }` width or marker size.\n * Default 1. */\n scale?: number;\n /** Flatness tolerance for curves, in the path's units. */\n flattenTolerance?: number;\n /**\n * The frame the stroke is drawn in, as the matrix taking that frame to the\n * path's coordinates: a node's `poseFrameOf`. A frame that skews or\n * stretches does the same to the stroke, as it does on the canvas. For a\n * `{ px }` width under a view that scales each axis apart, the frame is the\n * screen: the inverse of the view's scale, with `scale` left at 1.\n */\n frame?: Affine;\n}\n\nconst EMPTY: PolygonPath = {\n kind: 'polygon', commands: new Uint8Array(0), coords: new Float32Array(0), fillRule: 'nonzero',\n};\n\n/**\n * The region `stroke` covers when drawn along `path`, as a path to fill:\n * width, cap, join, miter limit, dash, alignment, per-vertex widths, and\n * marker heads all included. Curves are flattened, so the result holds only\n * M/L/Z. A stroke with no width answers an empty path, and so does one drawn\n * in a `frame` that flattens it.\n */\nexport function strokeToPath(path: Path, stroke: Stroke, opts: StrokeToPathOptions = {}): PolygonPath {\n const { frame, ...drawn } = opts;\n if (!frame) return outlineOf(path, stroke, drawn);\n const back = invert(frame);\n if (!back) return EMPTY;\n return transformPath(outlineOf(transformPath(path, back), stroke, drawn), frame) as PolygonPath;\n}\n\nfunction outlineOf(path: Path, stroke: Stroke, opts: StrokeToPathOptions): PolygonPath {\n const width = resolveStrokeWidth(stroke.width ?? 1, opts.scale ?? 1);\n if (!(width > 0)) return EMPTY;\n const tolerance = opts.flattenTolerance;\n const sized: Stroke = { ...stroke, width };\n const insets = strokeInsets(sized, width);\n const align = stroke.align ?? 'center';\n // A rect's aligned ribbon is built in place. Any other path gets a centered\n // ribbon twice as wide, cut to the side of the path it belongs on.\n const cut = align !== 'center' && path.kind !== 'rect';\n const ribbonStroke: Stroke = cut\n ? { ...sized, width: width * 2, align: 'center', vertexWidths: stroke.vertexWidths?.map((w) => w * 2) }\n : sized;\n const mesh = tessellateStroke(path, ribbonStroke, {\n flattenTolerance: tolerance, startInset: insets.start, endInset: insets.end,\n });\n let ribbon = trianglesToPath(mesh.vertices, mesh.indices);\n if (cut) ribbon = align === 'inner' ? pathIntersect(ribbon, path) : pathSubtract(ribbon, path);\n\n const heads: PolygonPath[] = [];\n for (const { entry, path: head, size } of markerHeads(path, sized, width, tolerance)) {\n if ((entry.fill ?? 'line') !== 'none') heads.push(head);\n if (entry.outline && (entry.outline.paint ?? 'line') !== 'none') {\n heads.push(strokeToPath(head, { width: entry.outline.width * size, cap: 'round', join: 'round' }, opts));\n }\n }\n return heads.length === 0 ? ribbon : pathUnion(ribbon, ...heads);\n}\n","import {\n anchorsToPath, pathToAnchors, simplifyPath, type Path, type PolygonPath,\n} from '@weasel-js/geom';\nimport { pathSubtract, pathUnion } from '@weasel-js/geom/booleans';\nimport { strokeToPath } from './strokeToPath';\n\n/** Options for {@link offsetPath}. */\nexport interface OffsetPathOptions {\n /** How the offset outline turns a corner. Default `'miter'`. */\n join?: 'miter' | 'round' | 'bevel';\n /** Past this ratio of miter length to distance a miter corner is beveled.\n * Default 4. */\n miterLimit?: number;\n /** How closely curves are followed, in the path's units. Default 0.1. */\n tolerance?: number;\n /** Refit the outline's flattened curves as cubics (`simplifyPath` at\n * `tolerance`). Default true; false leaves a polygon. */\n refit?: boolean;\n}\n\n/**\n * The outline of the region `path` fills, grown by `distance` (shrunk by a\n * negative one), as a path to fill. Every subpath counts as closed. The\n * outline is where a stroke of twice `distance` centered on the path has its\n * outer (or inner) edge, so it takes that stroke's joins; overlaps resolve\n * the way a union does, and a region shrunk past its own width is gone.\n * Returns an empty path when nothing is left.\n */\nexport function offsetPath(path: Path, distance: number, opts: OffsetPathOptions = {}): PolygonPath {\n const region = closedRegion(path);\n if (distance === 0) return region;\n const tolerance = opts.tolerance ?? 0.1;\n const band = strokeToPath(region, {\n width: Math.abs(distance) * 2,\n join: opts.join ?? 'miter',\n miterLimit: opts.miterLimit ?? 4,\n }, { flattenTolerance: tolerance });\n const grown = distance > 0 ? pathUnion(region, band) : pathSubtract(region, band);\n return opts.refit === false || grown.commands.length === 0 ? grown : simplifyPath(grown, tolerance);\n}\n\n/** `path` with every subpath closed. */\nfunction closedRegion(path: Path): PolygonPath {\n if (path.kind === 'rect') {\n const { x, y, width: w, height: h } = path;\n return anchorsToPath([[{ x, y }, { x: x + w, y }, { x: x + w, y: y + h }, { x, y: y + h }]], [true]);\n }\n const { anchors, closed } = pathToAnchors(path);\n if (closed.every(Boolean)) return path;\n return anchorsToPath(anchors, closed.map(() => true), path);\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MarkerKey, Stroke,
|
|
1
|
+
import { MarkerKey, Stroke, Paint } from '@weasel-js/paint';
|
|
2
2
|
import { Path } from '@weasel-js/geom';
|
|
3
3
|
import { Reflection } from '@weasel-js/registry';
|
|
4
4
|
|
|
@@ -25,7 +25,7 @@ interface MarkerCtx {
|
|
|
25
25
|
}
|
|
26
26
|
/** `'line'` means the stroke's own paint — SVG 2's `context-stroke`, as the
|
|
27
27
|
* default rather than an opt-in. */
|
|
28
|
-
type MarkerPaint =
|
|
28
|
+
type MarkerPaint = Paint | 'line' | 'none';
|
|
29
29
|
/** A stroke-marker registry entry: a terminator's geometry, paint and inset. */
|
|
30
30
|
interface MarkerEntry {
|
|
31
31
|
/** `'kit:'`-free for built-ins so the key matches the SVG attribute value;
|
package/dist/test-seams.d.ts
CHANGED
package/dist/test-seams.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/stroke",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "A stroke as geometry: the ribbon mesh with joins, caps, dashes and per-vertex widths, the marker registry and its placed heads, and a stroke's outline as a path. No scene graph, no React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"./package.json": "./package.json"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@weasel-js/geom": "1.
|
|
24
|
-
"@weasel-js/paint": "1.
|
|
25
|
-
"@weasel-js/registry": "1.
|
|
23
|
+
"@weasel-js/geom": "1.10.1",
|
|
24
|
+
"@weasel-js/paint": "1.10.1",
|
|
25
|
+
"@weasel-js/registry": "1.10.1"
|
|
26
26
|
},
|
|
27
27
|
"author": "orochi235",
|
|
28
28
|
"homepage": "https://orochi235.github.io/weasel/",
|