openpencil/packages/scene-graph/src
Danila Poyarkov fa3672c39c
fix(core): fill open subpaths of filled SVG paths (#876)
* fix(core): keep SVG icon stroke caps and joins after saving

Icons inserted from Iconify and vectors from import_svg set stroke-linecap
and stroke-linejoin only on the Stroke paint. .fig stores cap and join on
the node, and the reader rebuilds the paint's cap and join from it, so a
saved and reopened Lucide icon came back with NONE caps and MITER joins
and showed gaps where its strokes meet. Set strokeCap and strokeJoin on
the node as well.

* fix(core): fill open subpaths of filled SVG paths

SVG fills every subpath as if it were closed, but parseSVGPath put only
closed subpaths in the fill region. The renderer filled the open ones as
a separate path, so a hole formed by an open subpath and a closed one
under the path's fill rule was filled in, as in some Font Awesome icons.

Add an includeOpenRegions option to parseSVGPath, off by default, and set
it for filled paths without a stroke from Iconify icons and import_svg,
and for SVG clip paths. Stroked paths keep open subpaths out of the
region so their closing edges are not stroked. A filled polyline now
flattens with adjacent filled shapes like a polygon does.

* docs(changelog): state where open SVG subpaths are now filled

The app has no icon picker. The fix reaches Design JSX <Icon> and
inline <svg> through scalePathInfos, dropped and pasted SVG files and
clip paths through svgToVectorPaths, and makes filled polylines render
filled. Name the unstroked-path limit instead of an unqualified claim.

* test(core): import SceneGraph from its owning package

Scene Graph owns the graph type; the Core barrel only re-exports it for
compatibility. importVectors also returns the graph, matching the same
helper in #832 so the shared test files reconcile cleanly.

* docs(changelog): name every path that keeps SVG stroke caps

The app has no icon picker; the fix reaches Design JSX <Icon> and
inline <svg> through createIconFromPaths, and dropped or pasted SVG
files through the same vector placement as import_svg.

* test(core): import SceneGraph from its owning package

Scene Graph owns the graph type; the Core barrel only re-exports it
for compatibility.

* refactor(core): read the first SVG path stroke with at(0)

Array destructuring types the first stroke as always present, so the
type-aware no-unnecessary-condition lint rejected the guard that skips
vectors without strokes and failed bun run check.

---------

Co-authored-by: Jason Woltje <1139190+jetrich@users.noreply.github.com>
2026-10-04 13:25:23 +00:00
..
color fix(tools): judge describe text contrast by WCAG ratio (#758) 2026-09-30 11:32:34 +04:00
components fix(fig): read, render, and write Figma slots (#850) 2026-10-04 00:45:10 +04:00
fields feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
instances fix(scene-graph): leave a field a component property drives to its instance (#843) 2026-10-04 01:38:23 +04:00
scaling feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
transfer fix(fig): keep variable metadata, plugin data and default mode on save (#848) 2026-10-04 12:53:04 +04:00
variables feat: model variables as CSS design tokens (#852) 2026-10-04 10:50:46 +00:00
arrow-caps.ts feat(canvas): render arrow stroke caps on lines and open vectors 2026-08-31 21:25:38 +03:00
bindings.ts feat(editor): add shared style bindings 2026-07-17 20:28:22 +03:00
buffered-events.ts feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
checkpoint.ts fix(tools): guard checkpoint identities and share input schemas 2026-09-15 19:45:30 +03:00
constants.ts
coordinate.ts fix(figma-api): size groups and boolean operations to their contents (#775) 2026-09-30 05:23:59 +04:00
copy.ts feat(scene-graph)!: make a stroke a paint (#864) 2026-10-04 13:38:05 +04:00
events.ts
export-format.ts refactor(export): derive export format lists from the IO registry (#755) 2026-09-25 15:42:42 +04:00
export-scale.ts
font-style.ts fix(deps): patch collaboration websocket driver 2026-07-18 02:49:22 +03:00
geometry.ts fix(canvas): include arrow caps in bounds and controls 2026-08-31 21:25:38 +03:00
guides.ts feat(editor): add ruler guide authoring foundation 2026-08-19 18:08:48 +03:00
hit-test.ts perf(scene-graph): accelerate axis-aligned hit tests (#534) 2026-08-16 15:43:25 +03:00
images.ts fix(fig): use hex image hashes 2026-06-30 10:55:20 +03:00
index.ts feat: model variables as CSS design tokens (#852) 2026-10-04 10:50:46 +00:00
instance-overrides.ts feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
instances.ts fix(fig): read, render, and write Figma slots (#850) 2026-10-04 00:45:10 +04:00
layout-guides.ts fix(editor): harden snapping edge cases 2026-08-19 12:33:32 +03:00
matrix.ts
mutation-impact.ts fix(editor): preserve mutation parents and font layout 2026-09-02 08:27:52 +03:00
node-defaults.ts feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
parse-path.ts fix(core): fill open subpaths of filled SVG paths (#876) 2026-10-04 13:25:23 +00:00
preview.ts feat(editor): checkpoint live interaction improvements 2026-09-15 11:36:17 +03:00
primitives.ts refactor: standardize acronym casing 2026-08-10 15:48:16 +03:00
resize.ts feat(fig): support text on path 2026-08-17 12:00:01 +03:00
shared-styles.ts feat(text): deepen typography controls 2026-07-17 22:40:52 +03:00
snap.ts feat(editor): add configurable snapping and guides 2026-08-18 19:11:48 +03:00
source-metadata.ts refactor(fig): own raw metadata invalidation 2026-07-18 02:22:01 +03:00
text-direction.ts refactor!: move shared primitives below dom-css and core (#771) 2026-09-26 11:39:11 +04:00
text-picture.ts feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
types.ts feat: model variables as CSS design tokens (#852) 2026-10-04 10:50:46 +00:00
undo.ts fix(editor): close preview and history lifecycle gaps 2026-09-16 03:36:44 +03:00
variables.ts fix(fig): write bound fields resolved when exporting .fig (#859) 2026-10-04 08:59:42 +00:00
variant-name.ts
variant-properties.ts fix(figma-api): align variant combination behavior 2026-08-19 20:05:54 +03:00
vector-network.ts fix(figma-api): match Figma vector editing (#444) 2026-08-02 22:32:16 +03:00