diff --git a/include/mapnik/svg/svg_parser.hpp b/include/mapnik/svg/svg_parser.hpp index 909f58e1c..db0e2fe9c 100644 --- a/include/mapnik/svg/svg_parser.hpp +++ b/include/mapnik/svg/svg_parser.hpp @@ -111,7 +111,6 @@ class MAPNIK_DECL svg_parser : private util::noncopyable mapnik::css_data css_data_; boost::optional vbox_{}; double normalized_diagonal_ = 0.0; - agg::trans_affine viewbox_tr_{}; std::deque font_sizes_{}; error_handler err_handler_; }; diff --git a/include/mapnik/svg/svg_transform_grammar_x3_def.hpp b/include/mapnik/svg/svg_transform_grammar_x3_def.hpp index f9692c70c..96a0108a0 100644 --- a/include/mapnik/svg/svg_transform_grammar_x3_def.hpp +++ b/include/mapnik/svg/svg_transform_grammar_x3_def.hpp @@ -64,7 +64,7 @@ auto const matrix_action = [](auto const& ctx) { auto d = boost::fusion::at_c<3>(attr); auto e = boost::fusion::at_c<4>(attr); auto f = boost::fusion::at_c<5>(attr); - tr = agg::trans_affine(a, b, c, d, e, f) * tr; + tr.premultiply(agg::trans_affine(a, b, c, d, e, f)); }; auto const rotate_action = [](auto const& ctx) { @@ -75,14 +75,14 @@ auto const rotate_action = [](auto const& ctx) { auto cy = boost::fusion::at_c<2>(attr) ? *boost::fusion::at_c<2>(attr) : 0.0; if (cx == 0.0 && cy == 0.0) { - tr = agg::trans_affine_rotation(agg::deg2rad(a)) * tr; + tr.premultiply(agg::trans_affine_rotation(agg::deg2rad(a))); } else { agg::trans_affine t = agg::trans_affine_translation(-cx, -cy); t *= agg::trans_affine_rotation(agg::deg2rad(a)); t *= agg::trans_affine_translation(cx, cy); - tr = t * tr; + tr.premultiply(t); } }; @@ -92,9 +92,9 @@ auto const translate_action = [](auto const& ctx) { auto tx = boost::fusion::at_c<0>(attr); auto ty = boost::fusion::at_c<1>(attr); if (ty) - tr = agg::trans_affine_translation(tx, *ty) * tr; + tr.premultiply(agg::trans_affine_translation(tx, *ty)); else - tr = agg::trans_affine_translation(tx, 0.0) * tr; + tr.premultiply(agg::trans_affine_translation(tx, 0.0)); }; auto const scale_action = [](auto const& ctx) { @@ -103,21 +103,21 @@ auto const scale_action = [](auto const& ctx) { auto sx = boost::fusion::at_c<0>(attr); auto sy = boost::fusion::at_c<1>(attr); if (sy) - tr = agg::trans_affine_scaling(sx, *sy) * tr; + tr.premultiply(agg::trans_affine_scaling(sx, *sy)); else - tr = agg::trans_affine_scaling(sx, sx) * tr; + tr.premultiply(agg::trans_affine_scaling(sx, sx)); }; auto const skewX_action = [](auto const& ctx) { auto& tr = extract_transform(ctx); auto skew_x = _attr(ctx); - tr = agg::trans_affine_skewing(agg::deg2rad(skew_x), 0.0) * tr; + tr.premultiply(agg::trans_affine_skewing(agg::deg2rad(skew_x), 0.0)); }; auto const skewY_action = [](auto const& ctx) { auto& tr = extract_transform(ctx); auto skew_y = _attr(ctx); - tr = agg::trans_affine_skewing(0.0, agg::deg2rad(skew_y)) * tr; + tr.premultiply(agg::trans_affine_skewing(0.0, agg::deg2rad(skew_y))); }; // rules diff --git a/src/svg/svg_parser.cpp b/src/svg/svg_parser.cpp index 9e2f7c8a4..829dd326c 100644 --- a/src/svg/svg_parser.cpp +++ b/src/svg/svg_parser.cpp @@ -54,6 +54,8 @@ MAPNIK_DISABLE_WARNING_POP #include #include + + namespace mapnik { namespace svg { @@ -531,36 +533,45 @@ void traverse_tree(svg_parser& parser, rapidxml::xml_node const* node) { switch (name) { - case "g"_case: - if (node->first_node() != nullptr) - { - parser.path_.push_attr(); - parse_id(parser, node); - if (parser.css_style_) - process_css(parser, node); - parse_attr(parser, node); - } - break; - case "use"_case: + case "g"_case: + if (node->first_node() != nullptr) + { parser.path_.push_attr(); parse_id(parser, node); if (parser.css_style_) process_css(parser, node); parse_attr(parser, node); - parse_use(parser, node); - parser.path_.pop_attr(); - break; - default: + } + break; + case "svg"_case: + if (node->first_node() != nullptr) + { parser.path_.push_attr(); - parse_id(parser, node); - if (parser.css_style_) - process_css(parser, node); parse_attr(parser, node); - if (parser.path_.display()) - { - parse_element(parser, node->name(), node); - } - parser.path_.pop_attr(); + parse_dimensions(parser, node); + } + + break; + case "use"_case: + parser.path_.push_attr(); + parse_id(parser, node); + if (parser.css_style_) + process_css(parser, node); + parse_attr(parser, node); + parse_use(parser, node); + parser.path_.pop_attr(); + break; + default: + parser.path_.push_attr(); + parse_id(parser, node); + if (parser.css_style_) + process_css(parser, node); + parse_attr(parser, node); + if (parser.path_.display()) + { + parse_element(parser, node->name(), node); + } + parser.path_.pop_attr(); } } else @@ -642,38 +653,26 @@ void parse_element(svg_parser& parser, char const* name, rapidxml::xml_node const* node) viewbox vbox = {0, 0, 0, 0}; bool has_percent_height = true; bool has_percent_width = true; - auto const* width_attr = node->first_attribute("width"); if (width_attr) { @@ -933,58 +931,56 @@ void parse_dimensions(svg_parser& parser, rapidxml::xml_node const* node) double sx = width / vbox.width; double sy = height / vbox.height; double scale = preserve_aspect_ratio.second ? std::min(sx, sy) : std::max(sx, sy); + switch (preserve_aspect_ratio.first) { - case none: - t = agg::trans_affine_scaling(sx, sy) * t; - break; - case xMinYMin: - t = agg::trans_affine_scaling(scale, scale) * t; - break; - case xMinYMid: - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(0, -0.5 * (vbox.height - height / scale)) * t; - break; - case xMinYMax: - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(0, -1.0 * (vbox.height - height / scale)) * t; - break; - case xMidYMin: - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(-0.5 * (vbox.width - width / scale), 0.0) * t; - break; - case xMidYMid: // (the default) - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(-0.5 * (vbox.width - width / scale), - -0.5 * (vbox.height - height / scale)) * - t; - break; - case xMidYMax: - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(-0.5 * (vbox.width - width / scale), - -1.0 * (vbox.height - height / scale)) * - t; - break; - case xMaxYMin: - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(-1.0 * (vbox.width - width / scale), 0.0) * t; - break; - case xMaxYMid: - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(-1.0 * (vbox.width - width / scale), - -0.5 * (vbox.height - height / scale)) * - t; - break; - case xMaxYMax: - t = agg::trans_affine_scaling(scale, scale) * t; - t = agg::trans_affine_translation(-1.0 * (vbox.width - width / scale), - -1.0 * (vbox.height - height / scale)) * - t; + case none: + t.premultiply(agg::trans_affine_scaling(sx, sy)); + break; + case xMinYMin: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + break; + case xMinYMid: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(0, -0.5 * (vbox.height - height / scale))); + break; + case xMinYMax: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(0, -1.0 * (vbox.height - height / scale))); + break; + case xMidYMin: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(-0.5 * (vbox.width - width / scale), 0.0)); + break; + case xMidYMid: // (the default) + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(-0.5 * (vbox.width - width / scale), + -0.5 * (vbox.height - height / scale))); + break; + case xMidYMax: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(-0.5 * (vbox.width - width / scale), + -1.0 * (vbox.height - height / scale))); break; + case xMaxYMin: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(-1.0 * (vbox.width - width / scale), 0.0)); + break; + case xMaxYMid: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(-1.0 * (vbox.width - width / scale), + -0.5 * (vbox.height - height / scale))); + break; + case xMaxYMax: + t.premultiply(agg::trans_affine_scaling(scale, scale)); + t.premultiply(agg::trans_affine_translation(-1.0 * (vbox.width - width / scale), + -1.0 * (vbox.height - height / scale))); + break; }; + + t.premultiply(agg::trans_affine_translation(-vbox.x0, -vbox.y0)); + parser.path_.transform().premultiply(t); } - t = agg::trans_affine_translation(-vbox.x0, -vbox.y0) * t; - parser.viewbox_tr_ = t; } else if (width == 0 || height == 0 || has_percent_width || has_percent_height) {