m_elements_in_process.push_back(&element.children.back());
}
+void SVGAnalyzer::set_class(std::string_view class_) {
+ current_element().attributes.class_ = class_;
+}
+
void SVGAnalyzer::set_text(std::string_view text) {
auto &element = current_element();
element.text = text;
void on_enter_element_text() override;
void on_enter_element_title() override;
void on_exit_element() override;
+ void set_class(std::string_view) override;
void set_text(std::string_view text) override;
std::size_t num_svgs() const { return m_num_svgs; };
std::size_t num_groups() const { return m_num_groups; };
virtual void on_enter_element_text() = 0;
virtual void on_enter_element_title() = 0;
virtual void on_exit_element() = 0;
+ virtual void set_class(std::string_view) = 0;
virtual void set_text(std::string_view text) = 0;
};
+#include <stdexcept>
+
#include <fmt/format.h>
#include "svg_element.h"
output += "<";
output += tag(type);
+ std::string attributes_str{};
+ switch (type) {
+ case SVG::SVGElementType::Ellipse:
+ // ignore for now
+ break;
+ case SVG::SVGElementType::Group:
+ attributes_str += fmt::format(R"(class="{}")", attributes.class_);
+ break;
+ case SVG::SVGElementType::Path:
+ // ignore for now
+ break;
+ case SVG::SVGElementType::Polygon:
+ // ignore for now
+ break;
+ case SVG::SVGElementType::Polyline:
+ // ignore for now
+ break;
+ case SVG::SVGElementType::Svg:
+ // ignore for now
+ break;
+ case SVG::SVGElementType::Text:
+ // ignore for now
+ break;
+ case SVG::SVGElementType::Title:
+ // Graphviz doesn't generate attributes on 'title' elements
+ break;
+ default:
+ throw std::runtime_error{fmt::format(
+ "Attributes on '{}' elements are not yet implemented", tag(type))};
+ }
+ if (!attributes_str.empty()) {
+ output += " ";
+ }
+ output += attributes_str;
+
if (children.empty() && text.empty()) {
output += "/>\n";
} else {
std::string_view tag(SVG::SVGElementType type);
+struct SVGAttributes {
+ std::string class_;
+};
+
/**
* @brief The SVGElement class represents an SVG element
*/
std::string to_string(std::size_t indent_size) const;
+ SVGAttributes attributes;
/// The Graphviz build date
std::string graphviz_build_date;
std::vector<SVGElement> children;
(void)v;
}
+void SvgppContext::set(svgpp::tag::attribute::class_,
+ boost::iterator_range<const char *> v) {
+ m_svgAnalyzer->set_class({v.begin(), v.end()});
+}
+
void SvgppContext::set_impl(svgpp::tag::attribute::points &points,
const std::any &range) {
(void)points;
void set(svgpp::tag::attribute::y y, double v);
void set(svgpp::tag::attribute::width width, double v);
void set(svgpp::tag::attribute::height height, double v);
+ void set(svgpp::tag::attribute::class_ a,
+ boost::iterator_range<const char *> v);
void set_text(boost::iterator_range<const char *> v);
private:
svgpp::tag::element::rect, svgpp::tag::element::text,
svgpp::tag::element::title>::type;
+ using processed_attributes_t =
+ boost::mpl::set<svgpp::traits::shapes_attributes_by_element,
+ svgpp::tag::attribute::class_ //
+ >::type;
+
svgpp::document_traversal<
svgpp::processed_elements<processed_elements_t>,
- svgpp::processed_attributes<
- svgpp::traits::shapes_attributes_by_element>,
+ svgpp::processed_attributes<processed_attributes_t>,
svgpp::basic_shapes_policy<svgpp::policy::basic_shapes::raw>>::
load_document(xml_root_element, context);
}
// yet compare with the original SVG
CHECK(recreated_svg.find("<svg>") != std::string::npos);
CHECK(recreated_svg.find("</svg>") != std::string::npos);
- CHECK(recreated_svg.find("<g>") != std::string::npos);
+ CHECK(recreated_svg.find("<g class=\"graph\">") != std::string::npos);
+ CHECK(recreated_svg.find("<g class=\"node\">") != std::string::npos);
+ CHECK(recreated_svg.find("<g class=\"edge\">") != std::string::npos);
CHECK(recreated_svg.find("</g>") != std::string::npos);
CHECK(recreated_svg.find("<title>g1</title>") != std::string::npos);
CHECK(recreated_svg.find("<title>a</title>") != std::string::npos);