From 6eb2c967a05a698b3da81168bcbcdc8c8368b490 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 25 Apr 2021 15:41:50 +0200 Subject: svg-flatten: Add support for patterned strokes on outline layers --- svg-flatten/src/svg_doc.cpp | 68 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/svg-flatten/src/svg_doc.cpp b/svg-flatten/src/svg_doc.cpp index 6d41aca..bd22058 100644 --- a/svg-flatten/src/svg_doc.cpp +++ b/svg-flatten/src/svg_doc.cpp @@ -306,7 +306,7 @@ void gerbolyze::SVGDocument::export_svg_path(xform2d &mat, const RenderSettings /* Special case: A closed path becomes a number of open paths when it is dashed. */ if (dasharray.empty()) { - if (rset.outline_mode) { + if (rset.outline_mode && stroke_color != GRB_PATTERN_FILL) { /* In outline mode, manually close polys */ poly.push_back(poly[0]); *polygon_sink << ApertureToken() << poly; @@ -321,7 +321,7 @@ void gerbolyze::SVGDocument::export_svg_path(xform2d &mat, const RenderSettings Paths out; dash_path(poly_copy, out, dasharray); - if (rset.outline_mode) { + if (rset.outline_mode && stroke_color != GRB_PATTERN_FILL) { *polygon_sink << ApertureToken(stroke_width) << out; } else { offx.AddPaths(out, join_type, end_type); @@ -333,50 +333,48 @@ void gerbolyze::SVGDocument::export_svg_path(xform2d &mat, const RenderSettings Paths out; dash_path(poly, out, dasharray); - if (rset.outline_mode) { + if (rset.outline_mode && stroke_color != GRB_PATTERN_FILL) { *polygon_sink << ApertureToken(stroke_width) << out; } else { offx.AddPaths(out, join_type, end_type); } } - if (!rset.outline_mode) { - /* Execute clipper offset operation to generate stroke outlines */ - offx.Execute(ptree, 0.5 * stroke_width * clipper_scale); - - /* Clip. Note that after the outline, all we have is closed paths as any open path's stroke outline is itself - * a closed path. */ - if (!clip_path.empty()) { - Clipper c; - - Paths outline_paths; - PolyTreeToPaths(ptree, outline_paths); - c.AddPaths(outline_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); - } + /* Execute clipper offset operation to generate stroke outlines */ + offx.Execute(ptree, 0.5 * stroke_width * clipper_scale); - /* Call out to pattern tiler for pattern strokes. The stroke's outline becomes the clip here. */ - if (stroke_color == GRB_PATTERN_FILL) { - string stroke_pattern_id = usvg_id_url(node.attribute("stroke").value()); - Pattern *pattern = lookup_pattern(stroke_pattern_id); - if (!pattern) { - cerr << "Warning: Fill pattern with id \"" << stroke_pattern_id << "\" not found." << endl; + /* Clip. Note that after the outline, all we have is closed paths as any open path's stroke outline is itself + * a closed path. */ + if (!clip_path.empty()) { + Clipper c; - } else { - Paths clip; - PolyTreeToPaths(ptree, clip); - pattern->tile(local_xf, rset, clip); - } + Paths outline_paths; + PolyTreeToPaths(ptree, outline_paths); + c.AddPaths(outline_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); + } - } else { - Paths s_polys; - dehole_polytree(ptree, s_polys); + /* Call out to pattern tiler for pattern strokes. The stroke's outline becomes the clip here. */ + if (stroke_color == GRB_PATTERN_FILL) { + string stroke_pattern_id = usvg_id_url(node.attribute("stroke").value()); + Pattern *pattern = lookup_pattern(stroke_pattern_id); + if (!pattern) { + cerr << "Warning: Fill pattern with id \"" << stroke_pattern_id << "\" not found." << endl; - *polygon_sink << ApertureToken() << (stroke_color == GRB_DARK ? GRB_POL_DARK : GRB_POL_CLEAR) << s_polys; + } else { + Paths clip; + PolyTreeToPaths(ptree, clip); + pattern->tile(local_xf, rset, clip); } + + } else if (!rset.outline_mode) { + Paths s_polys; + dehole_polytree(ptree, s_polys); + + *polygon_sink << ApertureToken() << (stroke_color == GRB_DARK ? GRB_POL_DARK : GRB_POL_CLEAR) << s_polys; } } *polygon_sink << ApertureToken(); -- cgit