aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp23
-rw-r--r--src/svg_doc.cpp29
2 files changed, 45 insertions, 7 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 773b1a4..889fe6a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -38,6 +38,13 @@ int main(int argc, char **argv) {
{"flatten", {"--flatten"},
"Flatten output so it only consists of non-overlapping white polygons. This perform composition at the vector level. Potentially slow.",
0},
+ {"only_groups", {"-g", "--only-groups"},
+ "Comma-separated list of group IDs to export.",
+ 1},
+ {"exclude_groups", {"-e", "--exclude-groups"},
+ "Comma-separated list of group IDs to exclude from export. Takes precedence over --only-groups.",
+ 1},
+
}};
@@ -143,7 +150,21 @@ int main(int argc, char **argv) {
flattener = new Flattener(*sink);
}
- doc.render(flattener ? *flattener : *sink);
+ /* Because the C++ stdlib is bullshit */
+ auto id_match = [](string in, vector<string> &out) {
+ stringstream ss(in);
+ while (getline(ss, out.emplace_back(), ',')) {
+ }
+ out.pop_back();
+ };
+
+ ElementSelector sel;
+ if (args["only_groups"])
+ id_match(args["only_groups"], sel.include);
+ if (args["exclude_groups"])
+ id_match(args["exclude_groups"], sel.exclude);
+
+ doc.render(flattener ? *flattener : *sink, &sel);
return EXIT_SUCCESS;
}
diff --git a/src/svg_doc.cpp b/src/svg_doc.cpp
index 518e7ed..196cf60 100644
--- a/src/svg_doc.cpp
+++ b/src/svg_doc.cpp
@@ -116,8 +116,22 @@ double gerbolyze::SVGDocument::doc_units_to_mm(double px) const {
return px / (vb_w / page_w_mm);
}
+bool ElementSelector::match(const pugi::xml_node &node, bool included) const {
+ if (include.empty() && exclude.empty())
+ return true;
+
+ bool include_match = std::find(include.begin(), include.end(), node.attribute("id").value()) != include.end();
+ bool exclude_match = std::find(exclude.begin(), exclude.end(), node.attribute("id").value()) != exclude.end();
+
+ if (exclude_match || (!included && !include_match)) {
+ return false;
+ }
+
+ return true;
+}
+
/* Recursively export all SVG elements in the given group. */
-void gerbolyze::SVGDocument::export_svg_group(const pugi::xml_node &group, Paths &parent_clip_path) {
+void gerbolyze::SVGDocument::export_svg_group(const pugi::xml_node &group, Paths &parent_clip_path, const ElementSelector *sel, bool included) {
/* Enter the group's coordinate system */
cairo_save(cr);
apply_cairo_transform_from_svg(cr, group.attribute("transform").value());
@@ -147,9 +161,12 @@ void gerbolyze::SVGDocument::export_svg_group(const pugi::xml_node &group, Paths
/* Iterate over the group's children, exporting them one by one. */
for (const auto &node : group.children()) {
+ if (sel && !sel->match(node, included))
+ continue;
+
string name(node.name());
if (name == "g") {
- export_svg_group(node, clip_path);
+ export_svg_group(node, clip_path, sel, true);
} else if (name == "path") {
export_svg_path(node, clip_path);
@@ -342,7 +359,7 @@ void gerbolyze::SVGDocument::export_svg_path(const pugi::xml_node &node, Paths &
}
}
-void gerbolyze::SVGDocument::render(PolygonSink &sink) {
+void gerbolyze::SVGDocument::render(PolygonSink &sink, const ElementSelector *sel) {
assert(_valid);
/* Export the actual SVG document to both SVG for debuggin and to gerber. We do this as we go, i.e. we immediately
* process each element to gerber as we encounter it instead of first rendering everything to a giant list of gerber
@@ -354,15 +371,15 @@ void gerbolyze::SVGDocument::render(PolygonSink &sink) {
c.AddPaths(vb_paths, ptSubject, /* closed */ true);
ClipperLib::IntRect bbox = c.GetBounds();
cerr << "document viewbox clip: bbox={" << bbox.left << ", " << bbox.top << "} - {" << bbox.right << ", " << bbox.bottom << "}" << endl;
- export_svg_group(root_elem, vb_paths);
+ export_svg_group(root_elem, vb_paths, sel, false);
sink.footer();
}
-void gerbolyze::SVGDocument::render_to_list(vector<pair<Polygon, GerberPolarityToken>> &out) {
+void gerbolyze::SVGDocument::render_to_list(vector<pair<Polygon, GerberPolarityToken>> &out, const ElementSelector *sel) {
LambdaPolygonSink sink([&out](const Polygon &poly, GerberPolarityToken pol) {
out.emplace_back(pair<Polygon, GerberPolarityToken>{poly, pol});
});
- render(sink);
+ render(sink, sel);
}
void gerbolyze::SVGDocument::setup_debug_output(string filename) {