mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-22 11:18:11 +02:00
A shape layer's path is its vector mask in Photoshop (Properties > Masks), with its own vector-mask density and feather. PhotoCraft's ShapeLayer had neither, so soft shapes could not be made, and stroked soft shapes from PSDs lost both on import. - doc: ShapeLayer gains `density` (0..1, default 1) and `feather` (px, default 0). - vector: the shape renderer applies them to the fill as a soft vector mask (fill shows beyond the path at 1 - density; the feather is the vector mask's Gaussian), so the shape's own pixels, the GPU (which samples them) and the stroke/fill split all follow. The stroke stays crisp. The feather blur moves from compose::masks to vector::feather and both share it and the feathered area, so a shape and an equal vector mask render the same pixels. - compose: soft shapes' bounds reach their fill, their layer effects follow the soft alpha, and the split cache key includes density and feather. - engine: `layer.vectorMask.edit` on a shape layer sets density/feather in one history step (path/enabled/linked/invert are refused there); density is now validated (finite 0..100) instead of clamped. `layer.vectorMask.info` reports a shape's values. - ui: Properties shows the Vector Mask Density and Feather sliders for a selected shape layer in both themes (live drag, one undo per gesture). - .pcraft: manifest and convert carry both with serde defaults (older files load at 100 % and 0 px). - PSD: export writes them as the vector density/feather mask parameters; import reads them into the shape (re-rendered, as the stored pixels lack the fill beyond the path). Soft unstroked solid/gradient shapes now import as shapes instead of fill layers with a vector mask; pattern-filled ones stay fill layers. Photoshop's 10 px feather on a 100 px black square, row 100, x = 30..72: ours is within 1 level of every measured value (8, 16 and 32 bits); density 50 % shows 127/128 beyond the path and 0 inside. Scorecard: TOOL-214-12 done. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>