diff --git a/.gitmodules b/.gitmodules
index deedaea..b3b249b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -22,3 +22,6 @@
[submodule "upstream/stb"]
path = upstream/stb
url = https://github.com/nothings/stb
+[submodule "upstream/filesystem"]
+ path = upstream/filesystem
+ url = https://github.com/gulrak/filesystem
diff --git a/svg-flatten/Makefile b/svg-flatten/Makefile
index a980c05..2c9ff6c 100644
--- a/svg-flatten/Makefile
+++ b/svg-flatten/Makefile
@@ -1,5 +1,5 @@
-CXX := clang++
+CXX ?= clang++
LD ?= ld
INSTALL := install
PKG_CONFIG ?= pkg-config
@@ -45,7 +45,7 @@ SOURCES += $(CLIPPER_SOURCES)
INCLUDES := -Iinclude -Isrc $(CLIPPER_INCLUDES) $(VORONOI_INCLUDES) $(POISSON_INCLUDES) $(BASE64_INCLUDES) $(ARGAGG_INCLUDES) $(CAVC_INCLUDES) $(SUBPROCESS_INCLUDES) $(MINUNIT_INCLUDES) $(STB_INCLUDES)
CXXFLAGS := -std=c++2a -g -Wall -Wextra -O0
-LDFLAGS := -lm -lc -lstdc++
+LDFLAGS := -lm
PKG_CONFIG_DEPS :=
ifdef USE_SYSTEM_PUGIXML
@@ -71,19 +71,16 @@ $(BUILDDIR)/%.o: %.cpp
$(BUILDDIR)/$(TARGET): $(SOURCES:%.cpp=$(BUILDDIR)/%.o)
@mkdir -p $(dir $@)
- if [ $$(uname -s) = "Darwin" ]; then \
- $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^; \
- else \
- $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ -Wl,--start-group $^ -lstdc++fs -Wl,--end-group; \
- fi
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^
-$(BUILDDIR)/nopencv-tests: src/nopencv_test.cpp src/nopencv.cpp
+$(BUILDDIR)/nopencv-test: src/test/nopencv_test.cpp src/nopencv.cpp
@mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) $(INCLUDES) $(LDFLAGS) -o $@ $^
.PHONY: tests
-tests: $(BUILDDIR)/nopencv-tests
+tests: $(BUILDDIR)/nopencv-test
+ $(BUILDDIR)/nopencv-test
.PHONY: install
install:
diff --git a/svg-flatten/src/nopencv_test.cpp b/svg-flatten/src/test/nopencv_test.cpp
similarity index 99%
rename from svg-flatten/src/nopencv_test.cpp
rename to svg-flatten/src/test/nopencv_test.cpp
index 17ba71e..2f358b2 100644
--- a/svg-flatten/src/nopencv_test.cpp
+++ b/svg-flatten/src/test/nopencv_test.cpp
@@ -15,7 +15,7 @@
using namespace gerbolyze;
using namespace gerbolyze::nopencv;
-char msg[1024];
+char msg[512];
class TempfileHack {
public:
diff --git a/svg-flatten/src/test/svg_tests.py b/svg-flatten/src/test/svg_tests.py
new file mode 100644
index 0000000..a5139ec
--- /dev/null
+++ b/svg-flatten/src/test/svg_tests.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+
+import tempfile
+import unittest
+from pathlib import Path
+import subprocess
+import os
+
+from PIL import Image
+import numpy as np
+
+def run_svg_flatten(input_file, output_file, **kwargs):
+ if 'SVG_FLATTEN' in os.environ:
+ svg_flatten = os.environ.get('SVG_FLATTEN')
+ elif (Path(__file__) / '../../build/svg-flatten').is_file():
+ svg_flatten = '../../build/svg-flatten'
+ elif Path('./build/svg-flatten').is_file():
+ svg_flatten = './build/svg-flatten'
+ else:
+ svg_flatten = 'svg-flatten'
+
+ args = [ svg_flatten,
+ *(arg for (key, value) in kwargs.items() for arg in (f'--{key.replace("_", "-")}', value)),
+ str(input_file), str(output_file) ]
+
+ try:
+ proc = subprocess.run(args, capture_output=True, check=True)
+ except:
+ print('Subprocess stdout:')
+ print(proc.stdout)
+ print('Subprocess stderr:')
+ print(proc.stderr)
+ raise
+
+class SVGRoundTripTests(unittest.TestCase):
+
+ def compare_images(self, reference, output, test_name, mean=0.01):
+ ref = np.array(Image.open(reference))
+ out = np.array(Image.open(output))
+ delta = np.abs(out - ref).astype(float) / 255
+
+ #print(f'{test_name}: mean={delta.mean():.5g}')
+
+ self.assertTrue(delta.mean() < mean,
+ f'Expected mean pixel difference between images to be <{mean}, was {delta.mean():.5g}')
+
+ def run_svg_round_trip_test(self, test_in_svg):
+ with tempfile.NamedTemporaryFile(suffix='.svg') as tmp_out_svg,\
+ tempfile.NamedTemporaryFile(suffix='.png') as tmp_out_png,\
+ tempfile.NamedTemporaryFile(suffix='.png') as tmp_in_png:
+
+ run_svg_flatten(test_in_svg, tmp_out_svg.name, format='svg')
+
+ subprocess.run(['resvg', tmp_out_svg.name, tmp_out_png.name], check=True, stdout=subprocess.DEVNULL)
+ subprocess.run(['resvg', test_in_svg, tmp_in_png.name], check=True, stdout=subprocess.DEVNULL)
+
+ try:
+ self.compare_images(tmp_in_png, tmp_out_png, test_in_svg.stem)
+ except AssertionError as e:
+ import shutil
+ shutil.copyfile(tmp_in_png.name, f'/tmp/gerbolyze-fail-{test_in_svg.stem}-in.png')
+ shutil.copyfile(tmp_out_png.name, f'/tmp/gerbolyze-fail-{test_in_svg.stem}-out.png')
+ foo = list(e.args)
+ foo[0] += '\nFailing test renderings copied to:\n'
+ foo[0] += f' /tmp/gerbolyze-fail-{test_in_svg.stem}-{{in|out}}.png\n'
+ e.args = tuple(foo)
+ raise e
+
+for test_in_svg in Path('testdata/svg').glob('*.svg'):
+ # We need to make sure we capture the loop variable's current value here.
+ gen = lambda testcase: lambda self: self.run_svg_round_trip_test(testcase)
+ setattr(SVGRoundTripTests, f'test_{test_in_svg.stem}', gen(test_in_svg))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/svg-flatten/testdata/svg/circles.svg b/svg-flatten/testdata/svg/circles.svg
new file mode 100644
index 0000000..9be474e
--- /dev/null
+++ b/svg-flatten/testdata/svg/circles.svg
@@ -0,0 +1,78 @@
+
+
diff --git a/svg-flatten/testdata/svg/compound_xform.svg b/svg-flatten/testdata/svg/compound_xform.svg
new file mode 100644
index 0000000..229e05d
--- /dev/null
+++ b/svg-flatten/testdata/svg/compound_xform.svg
@@ -0,0 +1,102 @@
+
+
diff --git a/svg-flatten/testdata/svg/empty.svg b/svg-flatten/testdata/svg/empty.svg
new file mode 100644
index 0000000..d2cdc52
--- /dev/null
+++ b/svg-flatten/testdata/svg/empty.svg
@@ -0,0 +1,11 @@
+
+
diff --git a/svg-flatten/testdata/svg/empty_inkscape.svg b/svg-flatten/testdata/svg/empty_inkscape.svg
new file mode 100644
index 0000000..716379f
--- /dev/null
+++ b/svg-flatten/testdata/svg/empty_inkscape.svg
@@ -0,0 +1,54 @@
+
+
diff --git a/svg-flatten/testdata/svg/groups.svg b/svg-flatten/testdata/svg/groups.svg
new file mode 100644
index 0000000..d94dad0
--- /dev/null
+++ b/svg-flatten/testdata/svg/groups.svg
@@ -0,0 +1,96 @@
+
+
diff --git a/svg-flatten/testdata/svg/pattern_fill.svg b/svg-flatten/testdata/svg/pattern_fill.svg
new file mode 100644
index 0000000..21789e6
--- /dev/null
+++ b/svg-flatten/testdata/svg/pattern_fill.svg
@@ -0,0 +1,135 @@
+
+
diff --git a/svg-flatten/testdata/svg/pattern_stroke.svg b/svg-flatten/testdata/svg/pattern_stroke.svg
new file mode 100644
index 0000000..5564df0
--- /dev/null
+++ b/svg-flatten/testdata/svg/pattern_stroke.svg
@@ -0,0 +1,89 @@
+
+
diff --git a/svg-flatten/testdata/svg/pattern_stroke_dashed.svg b/svg-flatten/testdata/svg/pattern_stroke_dashed.svg
new file mode 100644
index 0000000..3d8145e
--- /dev/null
+++ b/svg-flatten/testdata/svg/pattern_stroke_dashed.svg
@@ -0,0 +1,89 @@
+
+
diff --git a/svg-flatten/testdata/svg/rect.svg b/svg-flatten/testdata/svg/rect.svg
new file mode 100644
index 0000000..297ff7e
--- /dev/null
+++ b/svg-flatten/testdata/svg/rect.svg
@@ -0,0 +1,65 @@
+
+
diff --git a/svg-flatten/testdata/svg/rect_occlusion.svg b/svg-flatten/testdata/svg/rect_occlusion.svg
new file mode 100644
index 0000000..ce0e531
--- /dev/null
+++ b/svg-flatten/testdata/svg/rect_occlusion.svg
@@ -0,0 +1,79 @@
+
+
diff --git a/svg-flatten/testdata/svg/rotation.svg b/svg-flatten/testdata/svg/rotation.svg
new file mode 100644
index 0000000..961ef0f
--- /dev/null
+++ b/svg-flatten/testdata/svg/rotation.svg
@@ -0,0 +1,66 @@
+
+
diff --git a/svg-flatten/testdata/svg/rotation_90.svg b/svg-flatten/testdata/svg/rotation_90.svg
new file mode 100644
index 0000000..dcca867
--- /dev/null
+++ b/svg-flatten/testdata/svg/rotation_90.svg
@@ -0,0 +1,66 @@
+
+
diff --git a/svg-flatten/testdata/svg/scale.svg b/svg-flatten/testdata/svg/scale.svg
new file mode 100644
index 0000000..91b28d6
--- /dev/null
+++ b/svg-flatten/testdata/svg/scale.svg
@@ -0,0 +1,91 @@
+
+
diff --git a/svg-flatten/testdata/svg/shear.svg b/svg-flatten/testdata/svg/shear.svg
new file mode 100644
index 0000000..ec7875f
--- /dev/null
+++ b/svg-flatten/testdata/svg/shear.svg
@@ -0,0 +1,59 @@
+
+
diff --git a/svg-flatten/testdata/svg/stroke.svg b/svg-flatten/testdata/svg/stroke.svg
new file mode 100644
index 0000000..6a4b334
--- /dev/null
+++ b/svg-flatten/testdata/svg/stroke.svg
@@ -0,0 +1,67 @@
+
+
diff --git a/svg-flatten/testdata/svg/stroke_caps.svg b/svg-flatten/testdata/svg/stroke_caps.svg
new file mode 100644
index 0000000..6b89a34
--- /dev/null
+++ b/svg-flatten/testdata/svg/stroke_caps.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/svg-flatten/testdata/svg/stroke_dashes.svg b/svg-flatten/testdata/svg/stroke_dashes.svg
new file mode 100644
index 0000000..c1d6f5c
--- /dev/null
+++ b/svg-flatten/testdata/svg/stroke_dashes.svg
@@ -0,0 +1,75 @@
+
+
diff --git a/svg-flatten/testdata/svg/stroke_joins.svg b/svg-flatten/testdata/svg/stroke_joins.svg
new file mode 100644
index 0000000..ee3e1ac
--- /dev/null
+++ b/svg-flatten/testdata/svg/stroke_joins.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/svg-flatten/testdata/svg/text.svg b/svg-flatten/testdata/svg/text.svg
new file mode 100644
index 0000000..bd8c390
--- /dev/null
+++ b/svg-flatten/testdata/svg/text.svg
@@ -0,0 +1,108 @@
+
+
diff --git a/upstream/filesystem b/upstream/filesystem
new file mode 160000
index 0000000..4e21ab3
--- /dev/null
+++ b/upstream/filesystem
@@ -0,0 +1 @@
+Subproject commit 4e21ab305794f5309a1454b4ae82ab9a0f5e0d25