aboutsummaryrefslogtreecommitdiff
path: root/svg-flatten/src
diff options
context:
space:
mode:
authorjaseg <git@jaseg.de>2022-06-20 18:30:34 +0200
committerjaseg <git@jaseg.de>2022-06-20 18:30:34 +0200
commite4a0c1ba4a16c0e0f7c1013afd924ecb41b41f05 (patch)
tree5de4c8e20238b2c1a8c527cc62441315031bcd6f /svg-flatten/src
parent9e9cc2bc019f0e67720ad5da16315e7cd6781e78 (diff)
downloadgerbolyze-e4a0c1ba4a16c0e0f7c1013afd924ecb41b41f05.tar.gz
gerbolyze-e4a0c1ba4a16c0e0f7c1013afd924ecb41b41f05.tar.bz2
gerbolyze-e4a0c1ba4a16c0e0f7c1013afd924ecb41b41f05.zip
Fix outline mode clip & flash handling
Diffstat (limited to 'svg-flatten/src')
-rw-r--r--svg-flatten/src/out_dilater.cpp5
-rw-r--r--svg-flatten/src/out_flattener.cpp2
-rw-r--r--svg-flatten/src/out_gerber.cpp11
-rw-r--r--svg-flatten/src/out_scaler.cpp6
-rw-r--r--svg-flatten/src/out_sexp.cpp2
-rw-r--r--svg-flatten/src/out_svg.cpp2
-rw-r--r--svg-flatten/src/svg_doc.cpp91
7 files changed, 63 insertions, 56 deletions
diff --git a/svg-flatten/src/out_dilater.cpp b/svg-flatten/src/out_dilater.cpp
index a5b0619..4a259a9 100644
--- a/svg-flatten/src/out_dilater.cpp
+++ b/svg-flatten/src/out_dilater.cpp
@@ -88,3 +88,8 @@ Dilater &Dilater::operator<<(const ApertureToken &ap) {
m_sink << ApertureToken(ap.m_size + 2*m_dilation);
return *this;
}
+
+Dilater &Dilater::operator<<(const FlashToken &tok) {
+ m_sink << tok;
+ return *this;
+}
diff --git a/svg-flatten/src/out_flattener.cpp b/svg-flatten/src/out_flattener.cpp
index 600584b..398d055 100644
--- a/svg-flatten/src/out_flattener.cpp
+++ b/svg-flatten/src/out_flattener.cpp
@@ -152,7 +152,7 @@ Flattener &Flattener::operator<<(const LayerNameToken &layer_name) {
return *this;
}
-Flattener &Flattener::operator<<(const DrillToken &tok) {
+Flattener &Flattener::operator<<(const FlashToken &tok) {
m_sink << tok;
return *this;
}
diff --git a/svg-flatten/src/out_gerber.cpp b/svg-flatten/src/out_gerber.cpp
index 0b0a6bf..543d641 100644
--- a/svg-flatten/src/out_gerber.cpp
+++ b/svg-flatten/src/out_gerber.cpp
@@ -126,17 +126,6 @@ SimpleGerberOutput& SimpleGerberOutput::operator<<(const Polygon &poly) {
return *this;
}
-SimpleGerberOutput &SimpleGerberOutput::operator<<(const DrillToken &tok) {
- double x = round((tok.m_center[0] * m_scale + m_offset[0]) * m_gerber_scale);
- double y = round((m_height - tok.m_center[1] * m_scale + m_offset[1]) * m_gerber_scale);
-
- m_out << "X" << setw(m_digits_int + m_digits_frac) << setfill('0') << std::internal /* isn't C++ a marvel of engineering? */ << (long long int)x
- << "Y" << setw(m_digits_int + m_digits_frac) << setfill('0') << std::internal << (long long int)y
- << "D03*" << endl;
-
- return *this;
-}
-
void SimpleGerberOutput::footer_impl() {
m_out << "M02*" << endl;
}
diff --git a/svg-flatten/src/out_scaler.cpp b/svg-flatten/src/out_scaler.cpp
index fb54145..c6e624d 100644
--- a/svg-flatten/src/out_scaler.cpp
+++ b/svg-flatten/src/out_scaler.cpp
@@ -64,12 +64,6 @@ PolygonScaler &PolygonScaler::operator<<(const Polygon &poly) {
return *this;
}
-PolygonScaler &PolygonScaler::operator<<(const DrillToken &tok) {
- d2p new_center { tok.m_center[0] * m_scale, tok.m_center[1] * m_scale };
- m_sink << DrillToken(new_center);
- return *this;
-}
-
PolygonScaler &PolygonScaler::operator<<(const FlashToken &tok) {
d2p new_offset = { tok.m_offset[0] * m_scale, tok.m_offset[1] * m_scale};
m_sink << FlashToken(new_offset);
diff --git a/svg-flatten/src/out_sexp.cpp b/svg-flatten/src/out_sexp.cpp
index f872b90..6c9f5ae 100644
--- a/svg-flatten/src/out_sexp.cpp
+++ b/svg-flatten/src/out_sexp.cpp
@@ -135,7 +135,7 @@ KicadSexpOutput &KicadSexpOutput::operator<<(const Polygon &poly) {
return *this;
}
-KicadSexpOutput &KicadSexpOutput::operator<<(const DrillToken &) {
+KicadSexpOutput &KicadSexpOutput::operator<<(const FlashToken &) {
return *this;
}
diff --git a/svg-flatten/src/out_svg.cpp b/svg-flatten/src/out_svg.cpp
index 66f0c94..80a5bdd 100644
--- a/svg-flatten/src/out_svg.cpp
+++ b/svg-flatten/src/out_svg.cpp
@@ -77,7 +77,7 @@ SimpleSVGOutput &SimpleSVGOutput::operator<<(const Polygon &poly) {
return *this;
}
-SimpleSVGOutput &SimpleSVGOutput::operator<<(const DrillToken &) {
+SimpleSVGOutput &SimpleSVGOutput::operator<<(const FlashToken &) {
return *this;
}
diff --git a/svg-flatten/src/svg_doc.cpp b/svg-flatten/src/svg_doc.cpp
index 7716a2e..20e11b2 100644
--- a/svg-flatten/src/svg_doc.cpp
+++ b/svg-flatten/src/svg_doc.cpp
@@ -285,7 +285,7 @@ void gerbolyze::SVGDocument::export_svg_path(RenderContext &ctx, const pugi::xml
double diameter = sqrt(4*fabs(area)/M_PI) / clipper_scale;
diameter = ctx.mat().doc2phys_dist(diameter); /* FIXME is this correct w.r.t. PolygonScaler? */
diameter = round(diameter * 1000.0) / 1000.0; /* Round to micrometer precsion; FIXME: make configurable */
- ctx.sink() << ApertureToken(diameter) << DrillToken(centroid);
+ ctx.sink() << ApertureToken(diameter) << FlashToken(centroid);
}
}
return;
@@ -346,6 +346,10 @@ void gerbolyze::SVGDocument::export_svg_path(RenderContext &ctx, const pugi::xml
}
if (has_stroke) {
+ Clipper stroke_clip;
+ stroke_clip.StrictlySimple(true);
+ stroke_clip.AddPaths(ctx.clip(), ptClip, /* closed */ true);
+
ClipperOffset offx;
offx.ArcTolerance = 0.01 * clipper_scale; /* 10µm; TODO: Make this configurable */
offx.MiterLimit = stroke_miterlimit;
@@ -359,10 +363,8 @@ void gerbolyze::SVGDocument::export_svg_path(RenderContext &ctx, const pugi::xml
if (dasharray.empty()) {
if (ctx.settings().outline_mode && stroke_color != GRB_PATTERN_FILL) {
- /* In outline mode, manually close polys */
- poly.push_back(poly[0]);
- ctx.sink() << ApertureToken() << poly;
-
+ cerr << "add closed path of size " << poly.size() << endl;
+ stroke_clip.AddPath(poly, ptSubject, /* closed */ true);
} else {
offx.AddPath(poly, join_type, etClosedLine);
}
@@ -374,7 +376,8 @@ void gerbolyze::SVGDocument::export_svg_path(RenderContext &ctx, const pugi::xml
dash_path(poly_copy, out, dasharray, stroke_dashoffset);
if (ctx.settings().outline_mode && stroke_color != GRB_PATTERN_FILL) {
- ctx.sink() << ApertureToken(stroke_width) << out;
+ cerr << "add open path dashes of size " << out.size() << endl;
+ stroke_clip.AddPaths(out, ptSubject, /* closed */ false);
} else {
offx.AddPaths(out, join_type, end_type);
}
@@ -386,47 +389,63 @@ void gerbolyze::SVGDocument::export_svg_path(RenderContext &ctx, const pugi::xml
dash_path(poly, out, dasharray, stroke_dashoffset);
if (ctx.settings().outline_mode && stroke_color != GRB_PATTERN_FILL) {
- ctx.sink() << ApertureToken(stroke_width) << out;
+ cerr << "add open paths of size " << out.size() << endl;
+ stroke_clip.AddPaths(out, ptSubject, /* closed */ false);
} else {
offx.AddPaths(out, join_type, end_type);
}
}
- /* Execute clipper offset operation to generate stroke outlines */
- offx.Execute(ptree, 0.5 * stroke_width * clipper_scale);
+ if (ctx.settings().outline_mode && stroke_color != GRB_PATTERN_FILL) {
+ stroke_clip.Execute(ctIntersection, ptree, pftNonZero, pftNonZero);
+ Paths outline_paths;
+ ctx.sink() << ApertureToken(stroke_width);
+
+ ClosedPathsFromPolyTree(ptree, outline_paths);
+ for (auto &path : outline_paths) {
+ /* we have to connect the last and first point here */
+ if (path.empty())
+ continue;
+ path.push_back(path[0]);
+ ctx.sink() << path;
+ }
- /* 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 (!ctx.clip().empty()) {
- Clipper c;
+ OpenPathsFromPolyTree(ptree, outline_paths);
+ ctx.sink() << outline_paths;
- Paths outline_paths;
- PolyTreeToPaths(ptree, outline_paths);
- c.AddPaths(outline_paths, ptSubject, /* closed */ true);
- c.AddPaths(ctx.clip(), 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 {
+ /* Execute clipper offset operation to generate stroke outlines */
+ offx.Execute(ptree, 0.5 * stroke_width * clipper_scale);
+
+ /* Clip. Note that (outside of outline mode) after the clipper outline operation, all we have is closed paths as
+ * any open path's stroke outline is itself a closed path. */
+ if (!ctx.clip().empty()) {
+ Paths outline_paths;
+ PolyTreeToPaths(ptree, outline_paths);
+ stroke_clip.AddPaths(outline_paths, ptSubject, /* closed */ true);
+ /* fill rules are nonzero since both subject and clip have already been normalized by clipper. */
+ stroke_clip.Execute(ctIntersection, ptree, pftNonZero, pftNonZero);
+ }
- /* 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;
+ /* 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;
+
+ } else {
+ Paths clip;
+ PolyTreeToPaths(ptree, clip);
+ RenderContext local_ctx(ctx, xform2d(), clip, true);
+ pattern->tile(local_ctx);
+ }
} else {
- Paths clip;
- PolyTreeToPaths(ptree, clip);
- RenderContext local_ctx(ctx, xform2d(), clip, true);
- pattern->tile(local_ctx);
+ Paths s_polys;
+ dehole_polytree(ptree, s_polys);
+ ctx.sink() << (stroke_color == GRB_DARK ? GRB_POL_DARK : GRB_POL_CLEAR) << ApertureToken() << s_polys;
}
-
- } else if (!ctx.settings().outline_mode) {
- Paths s_polys;
- dehole_polytree(ptree, s_polys);
- ctx.sink() << (stroke_color == GRB_DARK ? GRB_POL_DARK : GRB_POL_CLEAR) << ApertureToken() << s_polys;
}
}
}