From 5bb733e55948e9a4273ae0f7cee8e81e38c23206 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 25 Apr 2021 18:42:43 +0200 Subject: Fix pattern rendering and some xform bugs --- svg-flatten/include/geom2d.hpp | 6 +++--- svg-flatten/src/svg_doc.cpp | 7 ++++--- svg-flatten/src/svg_pattern.cpp | 23 +++++++++++++++-------- svg-flatten/src/vec_core.cpp | 2 +- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/svg-flatten/include/geom2d.hpp b/svg-flatten/include/geom2d.hpp index ac56628..80b47df 100644 --- a/svg-flatten/include/geom2d.hpp +++ b/svg-flatten/include/geom2d.hpp @@ -67,8 +67,8 @@ namespace gerbolyze { } xform2d &translate(double x, double y) { - x0 += x; - y0 += y; + x0 += x*xx + y*xy; + y0 += y*yy + x*yx; return *this; } @@ -109,7 +109,7 @@ namespace gerbolyze { d2p doc2phys(const d2p p) { return d2p { xx * p[0] + xy * p[1] + x0, - xy * p[1] + yy * p[1] + y0 + yx * p[0] + yy * p[1] + y0 }; } diff --git a/svg-flatten/src/svg_doc.cpp b/svg-flatten/src/svg_doc.cpp index bd22058..18b744b 100644 --- a/svg-flatten/src/svg_doc.cpp +++ b/svg-flatten/src/svg_doc.cpp @@ -152,8 +152,8 @@ void gerbolyze::SVGDocument::export_svg_group(xform2d &mat, const RenderSettings } else { clip_path = *lookup; + local_xf.transform_paths(clip_path); } - local_xf.transform_paths(clip_path); /* Clip against parent's clip path (both are now in document coordinates) */ if (!parent_clip_path.empty()) { @@ -251,9 +251,10 @@ void gerbolyze::SVGDocument::export_svg_path(xform2d &mat, const RenderSettings c.AddPaths(fill_paths, ptSubject, /* closed */ true); c.AddPaths(clip_path, ptClip, /* closed */ true); c.StrictlySimple(true); + /* fill rules are nonzero since both subject and clip have already been normalized by clipper. */ - c.Execute(ctIntersection, ptree, pftNonZero, pftNonZero); - PolyTreeToPaths(ptree, fill_paths); + c.Execute(ctIntersection, ptree_fill, pftNonZero, pftNonZero); + PolyTreeToPaths(ptree_fill, fill_paths); } /* Call out to pattern tiler for pattern fills. The path becomes the clip here. */ diff --git a/svg-flatten/src/svg_pattern.cpp b/svg-flatten/src/svg_pattern.cpp index a122975..cbdf4dd 100644 --- a/svg-flatten/src/svg_pattern.cpp +++ b/svg-flatten/src/svg_pattern.cpp @@ -59,10 +59,10 @@ void gerbolyze::Pattern::tile (xform2d &mat, const gerbolyze::RenderSettings &rs /* Transform x, y, w, h from pattern coordinate space into parent coordinates by applying the inverse * patternTransform. This is necessary so we iterate over the correct bounds when tiling below */ - d2p pos_xf = patternTransform_inv.doc2phys(d2p{x, y}); + d2p pos_xf = mat.doc2phys(d2p{x, y}); double inst_x = pos_xf[0], inst_y = pos_xf[1]; - double inst_w = patternTransform_inv.doc2phys_dist(w); - double inst_h = patternTransform_inv.doc2phys_dist(h); + double inst_w = mat.doc2phys_dist(w); + double inst_h = mat.doc2phys_dist(h); ClipperLib::IntRect clip_bounds = get_paths_bounds(clip); double bx = clip_bounds.left / clipper_scale; @@ -70,6 +70,14 @@ void gerbolyze::Pattern::tile (xform2d &mat, const gerbolyze::RenderSettings &rs double bw = (clip_bounds.right - clip_bounds.left) / clipper_scale; double bh = (clip_bounds.bottom - clip_bounds.top) / clipper_scale; + d2p clip_p0 = patternTransform_inv.doc2phys(d2p{bx, by}); + d2p clip_p1 = patternTransform_inv.doc2phys(d2p{bx+bw, by+bh}); + + bx = fmin(clip_p0[0], clip_p1[0]); + by = fmin(clip_p0[1], clip_p1[1]); + bw = fmax(clip_p0[0], clip_p1[0]) - bx; + bh = fmax(clip_p0[1], clip_p1[1]) - by; + if (patternUnits == SVG_ObjectBoundingBox) { inst_x *= bw; inst_y *= bh; @@ -79,16 +87,15 @@ void gerbolyze::Pattern::tile (xform2d &mat, const gerbolyze::RenderSettings &rs /* Switch to pattern coordinates */ xform2d local_xf(mat); - local_xf.translate(bx, by); local_xf.transform(patternTransform); /* Iterate over all pattern tiles in pattern coordinates */ - for (double inst_off_x = fmod(inst_x, inst_w) - inst_w; - inst_off_x < bw + inst_w; + for (double inst_off_x = fmod(inst_x, inst_w) - 2*inst_w; + inst_off_x < bw + 2*inst_w; inst_off_x += inst_w) { - for (double inst_off_y = fmod(inst_y, inst_h) - inst_h; - inst_off_y < bh + inst_h; + for (double inst_off_y = fmod(inst_y, inst_h) - 2*inst_h; + inst_off_y < bh + 2*inst_h; inst_off_y += inst_h) { xform2d elem_xf(local_xf); diff --git a/svg-flatten/src/vec_core.cpp b/svg-flatten/src/vec_core.cpp index 6951e4f..aa4a1cc 100644 --- a/svg-flatten/src/vec_core.cpp +++ b/svg-flatten/src/vec_core.cpp @@ -170,8 +170,8 @@ void gerbolyze::VoronoiVectorizer::vectorize_image(xform2d &mat, const pugi::xml /* Set up target transform using SVG transform and x/y attributes */ xform2d local_xf(mat); - local_xf.transform(xform2d(node.attribute("transform").value())); local_xf.translate(x, y); + local_xf.transform(xform2d(node.attribute("transform").value())); double orig_rows = img.rows; double orig_cols = img.cols; -- cgit