mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-14 19:26:51 -04:00
* SVG opens as shape layers and places as a vector smart object (FILE-215-9, part of #215) crates/io/src/svg.rs: usvg parses (already in the tree through egui_extras); paths become ShapeLayer knots with the transform chain baked in, quadratics raised to cubics and every subpath after the first joining the component so the fill rule spans the path as SVG does; groups keep opacity and blend mode (transform-only and id-only wrapper groups vanish); text is shaped into outline shapes with the craft fonts plus the system's; gradients become the layer's gradient fill (stops and angle, with a warning). Clip paths, masks, filters, pattern paints and images are rasterised by resvg into pixel layers over their bounding box rather than dropped. Limits: 16384 px canvas, 2000 elements, 24 M px per raster, bounded recursion; malformed input is IoError::Svg. smart_cmds::render rasterises an SVG source at the placement's axis scale (1/16 steps, cached per scale) and divides the placement by it, affine and projective alike; place_bytes renders that cache up front. svg/svgz join the openable lists; book page; scorecard row done. Co-Authored-By: Claude Mythos 5.1 <[email protected]> * SVG import: never read local files from <image href> usvg's default image resolver reads any absolute or relative path in an <image href>, so opening an untrusted SVG could embed local files (/etc/..., ~/.ssh/...) into the document. Parse with a resolver that only accepts data: URLs (resources_dir None, string hrefs ignored). Embedded sub-SVGs already get no <image> resolution from usvg. The font database (and its system-font scan) is now only loaded when the drawing may contain text. Regression test: a PNG on disk referenced by absolute path, file:// URL and relative path is not loaded; a data: URL still is. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: leon <[email protected]> Co-authored-by: Claude Mythos 5.1 <[email protected]> Co-authored-by: Brandon Thomas <[email protected]>