current_element().attributes.id = id;
}
+void SVGAnalyzer::set_point(std::pair<double, double> point) {
+ current_element().attributes.points.emplace_back(point.first, point.second);
+}
+
void SVGAnalyzer::set_text(std::string_view text) {
auto &element = current_element();
element.text = text;
void set_id(std::string_view id) override;
void set_class(std::string_view) override;
void set_stroke(std::string_view stroke) override;
+ void set_point(std::pair<double, double> point) override;
void set_text(std::string_view text) override;
void set_transform(double a, double b, double c, double d, double e,
double f) override;
virtual void set_fill(std::string_view fill) = 0;
virtual void set_height(double height) = 0;
virtual void set_id(std::string_view id) = 0;
+ virtual void set_point(std::pair<double, double> point) = 0;
virtual void set_stroke(std::string_view stroke) = 0;
virtual void set_text(std::string_view text) = 0;
virtual void set_transform(double a, double b, double c, double d, double e,
return fmt::format(R"(id="{}")", attributes.id);
}
+std::string SVG::SVGElement::points_attribute_to_string() const {
+ std::string points_attribute_str = R"|(points=")|";
+ const char *separator = "";
+ for (const auto &point : attributes.points) {
+ points_attribute_str += separator + fmt::format("{},{}", point.x, point.y);
+ separator = " ";
+ }
+ points_attribute_str += '"';
+
+ return points_attribute_str;
+}
+
std::string SVG::SVGElement::stroke_attribute_to_string() const {
if (attributes.stroke.empty()) {
return "";
case SVG::SVGElementType::Polygon:
append_attribute(attributes_str, fill_attribute_to_string());
append_attribute(attributes_str, stroke_attribute_to_string());
+ append_attribute(attributes_str, points_attribute_to_string());
break;
case SVG::SVGElementType::Polyline:
append_attribute(attributes_str, fill_attribute_to_string());
append_attribute(attributes_str, stroke_attribute_to_string());
+ append_attribute(attributes_str, points_attribute_to_string());
break;
case SVG::SVGElementType::Svg:
attributes_str += fmt::format(
namespace SVG {
+struct SVGPoint {
+ double x;
+ double y;
+};
+
struct SVGRect {
double x;
double y;
std::string fill;
double height;
std::string id;
+ std::vector<SVGPoint> points;
std::string stroke;
std::optional<SVGMatrix> transform;
SVGRect viewBox;
const std::string &attribute) const;
std::string id_attribute_to_string() const;
std::string fill_attribute_to_string() const;
+ std::string points_attribute_to_string() const;
std::string stroke_attribute_to_string() const;
std::string stroke_to_graphviz_color(const std::string &color) const;
void to_string_impl(std::string &output, std::size_t indent_size,
m_svgAnalyzer->set_viewBox(v1, v2, v3, v4);
}
-void SvgppContext::set_impl(svgpp::tag::attribute::points &points,
- const std::any &range) {
- (void)points;
- (void)range;
- // ignore for now
+void SvgppContext::set(svgpp::tag::attribute::points,
+ const SvgppContext::PointsRange &range) {
+ for (auto &it : range) {
+ m_svgAnalyzer->set_point(it);
+ }
}
void SvgppContext::set_text(boost::iterator_range<const char *> v) {
#pragma once
-#include <any>
#include <stdexcept>
+#include <boost/range/any_range.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <svgpp/svgpp.hpp>
void set(svgpp::tag::attribute::y1 y1, double v);
void set(svgpp::tag::attribute::x2 x2, double v);
void set(svgpp::tag::attribute::y2 y2, double v);
- template <typename Range>
- void set(svgpp::tag::attribute::points points, const Range &range) {
- set_impl(points, range);
- }
+ typedef boost::any_range<std::pair<double, double>,
+ boost::single_pass_traversal_tag,
+ const std::pair<double, double> &, std::ptrdiff_t>
+ PointsRange;
+ void set(svgpp::tag::attribute::points points, const PointsRange &range);
void set(svgpp::tag::attribute::x a, double v);
void set(svgpp::tag::attribute::y y, double v);
void set(svgpp::tag::attribute::width width, double v);
void set_text(boost::iterator_range<const char *> v);
private:
- void set_impl(svgpp::tag::attribute::points &points, const std::any &range);
-
ISVGAnalyzer *m_svgAnalyzer = nullptr;
};
svgpp::tag::attribute::fill, //
svgpp::tag::attribute::height, //
svgpp::tag::attribute::id, //
+ svgpp::tag::attribute::points, //
svgpp::tag::attribute::stroke, //
svgpp::tag::attribute::transform, //
svgpp::tag::attribute::viewBox, //
boost::split(recreated_svg_lines, recreated_svg, boost::is_any_of("\n"));
for (std::size_t i = 0; i < original_svg_lines.size(); i++) {
REQUIRE(i < recreated_svg_lines.size());
+ if (recreated_svg_lines[i].starts_with("<ellipse fill=\"")) {
+ // stop comparison here for ellipse based node shapes since we do not
+ // yet handle all attributes on the 'ellipse' element
+ break;
+ }
if (recreated_svg_lines[i] ==
- "<polygon fill=\"white\" stroke=\"none\"/>") {
- // stop comparison here since we do not yet handle all attributes on the
- // 'polygon' element
+ ("<path fill=\"none\" stroke=\"black\"/>")) {
+ // stop comparison here for the 'cylinder' node shape since we do not
+ // yet handle all attributes on the 'path' element
+ break;
+ }
+ if (recreated_svg_lines[i] == "<text>a</text>") {
+ // stop comparison here for polygon based shapes since we do not yet
+ // handle all attributes on the 'text' element
break;
}
REQUIRE(recreated_svg_lines[i] == original_svg_lines[i]);
CHECK(recreated_svg.find("<text>a</text>") != std::string::npos);
CHECK(recreated_svg.find("<text>b</text>") != std::string::npos);
}
- CHECK(recreated_svg.find("<polygon fill=\"white\" stroke=\"none\"/>") !=
- std::string::npos);
CHECK(recreated_svg.find("<path fill=\"none\" stroke=\"black\"/>") !=
std::string::npos);
CHECK(recreated_svg.find("<!-- a -->") != std::string::npos);