Commit graph

7 commits

Author SHA1 Message Date
Danila Poyarkov 07674d1919 Restructure @open-pencil/core into domain modules
Move 30+ loose files at src/ root into domain directories:
- scene-graph/ — SceneGraph class, instances, hit-test, copy, snap, undo
- color/ — parse/format, color management, OkHCL
- text/ — text editor, style runs, direction, fonts
- vector/ — vector network encode/decode, bezier math
- figma-api/ — FigmaAPI class, FigmaNodeProxy
- icons/ — Iconify API client, icon rendering
- canvas/ — SkiaRenderer (was renderer/)
- design-jsx/ — JSX-to-design renderer (was render/)

Also:
- Move fig-compress.ts into io/formats/fig/compress.ts
- Delete re-export shims (headless-render.ts, svg-export/)
- Convert all self-referencing @open-pencil/core/* imports to relative
- Clean up package.json exports (26 subpaths, no internal leaks)
- Update AGENTS.md subpath table

Fixes #179
2026-04-06 14:39:53 +03:00
Danila Poyarkov f70338d18e Use child shape for drop shadows on transparent containers
When a frame/instance has no visible fills, Figma renders drop shadows
using the first child's shape instead of the node's own rectangle.
This makes shadows follow rounded children (e.g. pill-shaped badges
inside a rectangular wrapper).

Pass the first visible child as shadowShapeChild to renderEffects
when the container has no visible fills.
2026-03-14 12:25:51 +03:00
Danila Poyarkov e954fdabff Treat FOREGROUND_BLUR as layer blur wrapping children
Figma's kiwi format uses FOREGROUND_BLUR for what the Plugin API calls
LAYER_BLUR — a blur that applies to the entire layer including children.

Previously FOREGROUND_BLUR was handled in the per-effect 'front' pass via
applyClippedBlur, which only blurred the node's own fills (drawn before
children). For nodes with no fills but with children (like groups),
the blur had no visible effect.

Now FOREGROUND_BLUR is handled alongside LAYER_BLUR in renderNode,
using a saveLayer that wraps both the node content and its children.
This fixes gradient blobs that should appear soft/blurred (e.g. the
decorative gradients in gold-preview.fig's Preview Thumbnail).
2026-03-13 21:09:43 +03:00
Danila Poyarkov 9784544f1f Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests
- Strip tools/schema.ts from 1831 to 65 lines (remove duplicate tool defs)
- Fix tools/index.ts to export ALL_TOOLS from registry instead of schema
- Fix renderJsx → renderJSX typo in tools/create.ts and structure.ts
- Add geometry.ts with shared rotation/coordinate math utilities
- Add isArrayMixed() helper to use-multi-props.ts, deduplicate FillSection/StrokeSection/EffectsSection
- Fix broken test imports: use @open-pencil/core instead of relative paths into packages/core/src/
- Merge duplicate import statements across all test files
- Export profiler internals and style-run helpers from core index.ts
- Add 6 new test files: color, undo, snap, vector, style-runs, text-editor (98 new tests)
- Update renderer-effects test for renderer/ directory split
2026-03-06 22:33:10 +03:00
Danila Poyarkov 0047a25cae Fix effect ordering test, add contributors to release notes
Fix renderer-effects test: check drawStrokeWithAlign call site instead of
drawNodeStroke helper definition (stroke align refactor moved the method).

Add a step to build.yml that resolves git authors to GitHub usernames via
the compare API and appends a Contributors section to release notes.
2026-03-05 09:56:13 +03:00
Danila Poyarkov 8ced3201cf Cache effect ImageFilters and reuse layer paint
Eliminates per-frame WASM allocations for shadows and blurs:
- Reusable effectLayerPaint instead of new Paint() per effect
- ImageFilter cache keyed by params (drop shadow, blur, decal blur)
- Zero allocations during SkPicture recording for cached effects
2026-03-03 10:12:02 +03:00
Danila Poyarkov 8ab7148294
Fix effects rendering: shadows, blur, spread (#24)
* Fix shadow rendering, implement blur effects, add spread support

- Fix drop shadow rendering order: draw shadows before fills so they
  appear behind opaque shapes instead of on top (#23.1)
- Implement shadow spread: expand/contract shadow shape by spread value
  for both drop shadow and inner shadow (#23.2)
- Implement background blur: clip to node shape and apply blur filter
  to content behind the node (#23.3)
- Fix text shadows: use saveLayer with ColorFilter.MakeBlend to apply
  shadows to text glyphs instead of the bounding box (#23.4)
- Implement layer blur with actual saveLayer + blur filter instead of
  the no-op comment (#23.3)
- Implement foreground blur: clip to node shape and blur content in
  front (#23.7)
- Add inner shadow spread support with rounded rect handling
- Add makeRRectWithSpread and makeRRectWithOffset helpers

Closes #23

* Add Effects section to demo showcasing shadow and blur fixes

Drop shadows (subtle, medium, heavy, with spread), inner shadows
(inset, with spread, on ellipse, combined), text shadows on glyphs,
layer blur, and glassmorphism background blur card.

* Fix drop shadow, layer blur, and background blur rendering

Drop shadow: use MakeDropShadowOnly to produce shadow-only output
that doesn't bleed through opaque fills. The sigma is radius/2 to
match Figma's blur convention.

Layer blur: wrap entire node content in a saveLayer with blur filter
at the renderNode level instead of trying to blur after-the-fact
in renderEffects.

Background/foreground blur: extract clipNodeShape helper to reduce
duplication in blur effect rendering.

Update tests to match new rendering approach.

* Add visual regression tests for effects rendering

9 snapshot tests covering drop shadow, inner shadow, spread,
ellipse shapes, text glyphs, layer blur, and combined effects.

* Make Effects demo section background white

* Clean up renderer code and tests

- Extract applyClippedBlur to deduplicate background/foreground blur
- Remove comments that repeat what code does
- Format with oxfmt

* Add undo/redo support for effect property changes

ScrubInput controls (offset, radius, spread, opacity) now use
scrubEffect for live preview and commitEffect on release to create
a single undo entry per interaction.
2026-03-03 09:53:39 +03:00