PinePaper SVG Compatibility Guide
Reference for what survives an SVG ↔ PinePaper round-trip. Last verified against v0.5.0-beta.
TL;DR — round-trip score: 8/10
PinePaper imports SVG via Paper.js (project.importSVG) and exports via
project.exportSVG. Static geometry, fills, strokes, and transforms round-trip
reliably. Animations are emitted via the animated SVG (SMIL) export path,
which is a separate flow from import. The combination is “good enough” for
designers moving artwork between Illustrator/Inkscape/Figma and PinePaper.
Quick reference
| Feature class | Round-trip | Notes |
|---|---|---|
Path elements (<path>) |
✅ Solid | Bezier curves preserved exactly |
| Basic shapes (rect, circle, ellipse, line, polygon, polyline) | ✅ Solid | Expanded to paths on import |
Group elements (<g>) |
✅ Solid | Nested groups preserved |
| Fill colors (hex, rgb, rgba) | ✅ Solid | |
| Stroke colors, widths, line caps, joins | ✅ Solid | Dash patterns also preserved |
| Transforms (translate, scale, rotate, matrix) | ✅ Solid | Baked into geometry on import |
Opacity (opacity and fill-opacity) |
✅ Solid | |
Text elements (<text>) |
⚠️ Imports as PointText | Font fallback to system; complex <tspan> may flatten |
| viewBox | ⚠️ Read on import (v0.5+), not always re-emitted | Stored in item.data.svgViewBox for future use |
id attributes |
⚠️ Root id captured (v0.5+); child ids may drop | Stored in item.data.svgId |
Image elements (<image> with href) |
⚠️ Loads as raster | Cross-origin URLs may fail |
| Linear/radial gradients | ⚠️ Imported correctly, may flatten on re-export | Paper.js gradient support is incomplete |
Patterns (<pattern> fills) |
❌ Drop to solid | Not supported by Paper.js import |
CSS classes / inline <style> blocks |
❌ Drop | Class-based styling not parsed |
| Filters (blur, drop-shadow, etc.) | ❌ Drop | SVG filter primitives not imported |
Masks (<mask> and clip-path) |
⚠️ Partial | Simple cases work, complex masks fall through |
SMIL animations (<animate>, <animateTransform>, <animateMotion>) |
❌ Dropped on import | But PinePaper CAN emit them on export via animated SVG path |
Foreign objects (<foreignObject>) |
❌ Drop | HTML in SVG not supported |
Symbol / use elements (<symbol> + <use>) |
⚠️ May expand or drop | Depends on Paper.js handling |
What v0.5 added
The v0.5 SVG polish pass added metadata preservation to importSVG. When
you import an SVG, the following metadata is now stored on the imported item’s
data object:
item.data.svgId // The SVG root <svg id="..."> attribute
item.data.svgViewBox // The viewBox attribute, e.g. "0 0 200 100"
item.data.svgIntrinsicWidth // The width attribute (may be "100", "100px", "100%")
item.data.svgIntrinsicHeight // The height attribute
item.data.svgSource // The original SVG markup (if < 64KB)
This metadata is available for inspection but not yet used by the export path. The plan for v0.6 is to use it to round-trip imported SVGs back through the export with their original viewBox and id intact.
What works exceptionally well
Path geometry
SVG path data — M, L, C, Q, A, Z commands — round-trips with
exact bezier handle preservation. A complex illustration imported from
Illustrator and re-exported should be visually identical.
Group hierarchy
Nested <g> elements preserve their structure. A group containing groups
containing paths will have the same nesting after import.
Transforms
SVG transform attributes (translate(x, y), scale(s), rotate(deg, cx, cy),
matrix(a, b, c, d, e, f)) are baked into the geometry on import — Paper.js
applies the transform to the path coordinates so the resulting item is at the
final position with no transform left to apply. This is lossless for visual
geometry but loses the transform decomposition (you can’t separate the rotation
from the translation post-import).
Fills and strokes
Solid colors, opacities, line widths, line caps, line joins, and dash patterns all round-trip cleanly via Paper.js’s native style handling.
Known limitations
CSS-styled SVGs
SVGs that rely on a <style> block or external CSS for styling will lose
those styles on import. Workaround: use the SVG editor’s “convert styles to
attributes” or “inline styles” option before exporting.
SMIL-animated SVGs
PinePaper does NOT import SMIL animations from existing SVG files. If you
import an SVG that contains <animate> elements, the animations are dropped
and the static state is preserved. PinePaper CAN emit SMIL animations on
export (via app.exportEngine.exportAnimatedSVG()), but this is a one-way
flow.
SVG filters
<filter> primitives like Gaussian blur, drop shadow, color matrix, etc.
are not parsed. The visual filter effect is lost. Workaround: bake the
filter into a raster (export the SVG as PNG with the filter applied, then
import the PNG into PinePaper instead).
Patterns
SVG <pattern> fills (e.g. cross-hatching, repeating textures) drop to
solid colors. Use PinePaper’s GeneratorRegistry instead — it has 30+
pattern generators that produce native canvas geometry.
Text rendering
Text elements import as PinePaper PointText items, but font fallback is
naive — if the SVG references a font that’s not loaded in the browser, it
falls back to the system font. Complex <tspan> structures may flatten.
Cross-origin images
<image> elements with href="https://..." URLs may fail to load due to
CORS policy. Use data URIs (href="data:image/png;base64,...") or import
the image separately into PinePaper’s Add tab.
Migration notes
If you have an SVG that uses unsupported features and you want it to import cleanly into PinePaper:
-
In your SVG editor (Illustrator, Inkscape, Figma):
- Convert text to outlines if you don’t need editable text
- Bake filters and effects into raster images
- Replace pattern fills with solid colors or generated PNG textures
- Inline any external CSS styles
- Remove SMIL animations (PinePaper has its own animation system)
-
After importing into PinePaper:
- Manually re-add any features dropped during import using PinePaper’s native systems
- Use the GeneratorRegistry for patterns
- Use the FilterSystem for blur / glow / color effects
- Use the keyframe animation system for motion
File reference for developers
| File | Purpose |
|---|---|
js/PinePaper.js (importSVG method) |
Public SVG import entry point with metadata preservation |
js/ExportEngine.js (exportSVGWithCSS, animated SVG path) |
SVG export including animated SVG (SMIL) variant |
js/core/SMILExporter.js |
Animated SVG export — converts PinePaper keyframes to SMIL |
js/MapSystem.js (exportSVG method) |
Map-specific SVG export with optimized output |
Testing
For the SVG round-trip integration tests, see
__tests__/v05-svg-roundtrip.test.js. The test pins down which features
import correctly so future regressions are caught at commit time.
Last updated
2026-04-09 — round-trip audit pass for v0.5.0-beta release. Verified against:
- Inkscape 1.3 export samples
- Adobe Illustrator SVG export samples
- Hand-coded SVG fixtures