Skip to content

feat: optimized SVG export writer (fixes #236)#317

Merged
spe-ciellt merged 1 commit intogerbv:developfrom
SourceParts:fix/optimized-svg-export
Mar 5, 2026
Merged

feat: optimized SVG export writer (fixes #236)#317
spe-ciellt merged 1 commit intogerbv:developfrom
SourceParts:fix/optimized-svg-export

Conversation

@rampageservices
Copy link
Copy Markdown
Contributor

Summary

Adds a custom SVG writer (export-svg.c) that walks gerbv's data structures directly, bypassing Cairo's SVG surface entirely. This produces dramatically smaller SVG output files.

Root cause of #236: Cairo's SVG surface emits one <path> per Gerber primitive with repeated inline styles and 6-digit coordinate precision. A board with 112,000 primitives = 112,000 <path> elements with duplicate style attributes, producing ~30MB files.

Key optimizations

  • CSS class deduplication — Unique fill/stroke attribute sets emitted once in <style>, referenced via class="c0". A typical board has <20 unique styles vs 112k inline repetitions.
  • Reduced coordinate precision — 3 decimal places with trailing zero stripping (0.00035mm resolution at 72 DPI). Cairo uses 6.
  • SVG-native elements<circle>, <rect>, <line>, <polygon> instead of generic <path> where applicable.
  • <g> grouping — Nested groups for layer/netstate transforms carry shared attributes.

What's covered

  • All aperture types: circle, rectangle, oval, polygon
  • All aperture states: flash, stroke (linear + circular arc), off
  • Polygon area fills (PAREA_START/END)
  • All 8 macro primitive types (circle, outline, polygon, moire, thermal, line20/21/22)
  • Layer/netstate change handling (polarity, rotation, knockout, step-and-repeat)
  • Clear polarity workaround (background-color fill, matching existing vector export fix in draw.c)
  • Inkscape layer mode (--svg-layers)
  • Legacy fallback via --svg-cairo CLI flag or GUI checkbox

Measured results

Test file Cairo SVG Optimized SVG Reduction
hellboard.front.gbr 2.5 MB 1.4 MB 42%
6_vbat.gbr (polarity) 1.1 MB 345 KB 69%
example.gbr (simple) 2.8 KB 1.9 KB 32%

Larger boards with many repeated aperture flashes (the #236 scenario) will see the greatest reduction, potentially 85-93% as noted in the issue.

Files changed

File Change
src/export-svg.c New: custom SVG writer (~1100 lines)
src/export-svg.h New: header with internal types
src/export-image.c Route SVG export to new writer (Cairo fallback via flag)
src/gerbv.h Add use_cairo_svg flag to gerbv_project_t
src/main.c Add --svg-cairo CLI flag for legacy output
src/callbacks.c Add "Use Cairo SVG (legacy)" checkbox in export dialog
src/CMakeLists.txt Add export-svg.c to library sources

Test plan

  • Builds cleanly with zero warnings
  • Existing test suite passes (94/94 — 10 pre-existing failures unrelated to SVG)
  • --svg-cairo produces identical output to the previous code path
  • Single-layer SVG export works
  • Multi-layer Inkscape SVG export works (--svg-layers)
  • Polarity/clear operations render correctly
  • Visual comparison: rasterize both Cairo SVG and optimized SVG at 300 DPI, pixel-diff (requesting reviewer help)
  • Test with macro-heavy Gerber files
  • Test with large real-world boards (the 30MB scenario from Exported SVG way too big #236)
  • Test with step-and-repeat panels
  • Test with arcs > 180 degrees

Requesting feedback on the approach and testing with real-world files that exercise the edge cases.

Fixes #236

SVG export via Cairo's SVG surface produces bloated files because it
emits one <path> per Gerber primitive with repeated inline styles and
6-digit coordinate precision. A board with 112k primitives produces
a 30MB SVG that SVGO can reduce to 1.8MB.

Add a custom SVG writer (export-svg.c) that walks gerbv's data
structures directly, producing dramatically smaller output:

- CSS class deduplication: unique fill/stroke styles emitted once in
  <style>, referenced via class="c0". Typical board has <20 unique
  styles vs 112k inline repetitions.
- Reduced precision: 3 decimal places with trailing zero stripping
  (0.00035mm resolution at 72 DPI, well below visual threshold).
- SVG-native elements: <circle>, <rect>, <line>, <polygon> instead
  of generic <path> where applicable.
- <g> grouping with inherited styles for layer/netstate transforms.
- All 8 macro primitive types (circle, outline, polygon, moire,
  thermal, line20/21/22).
- Clear polarity workaround using background-color fill, matching
  the existing vector export fix in draw.c.
- Full support for Inkscape layer mode (--svg-layers).

The new writer is the default for SVG export. The previous Cairo-based
path is available via --svg-cairo CLI flag or the "Use Cairo SVG
(legacy)" checkbox in the GUI export dialog.

Measured size reduction: 42-69% on test files vs Cairo SVG output.
Larger boards with more repeated apertures will see greater reduction.

Fixes gerbv#236
@spe-ciellt spe-ciellt added enhancement New feature or request help wanted Extra attention is needed labels Mar 3, 2026
@spe-ciellt spe-ciellt merged commit d78cbed into gerbv:develop Mar 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request help wanted Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exported SVG way too big

2 participants