diff --git a/include/mapnik/marker_cache.hpp b/include/mapnik/marker_cache.hpp index bed847a2d..5ff46c171 100644 --- a/include/mapnik/marker_cache.hpp +++ b/include/mapnik/marker_cache.hpp @@ -56,6 +56,7 @@ public: bool is_svg_uri(std::string const& path); bool is_image_uri(std::string const& path); std::shared_ptr find(std::string const& key, bool update_cache = false, bool strict = false); + std::shared_ptr find(std::string const& key, double width, double height, bool update_cache = false, bool strict = false); void clear(); }; diff --git a/include/mapnik/svg/svg_parser.hpp b/include/mapnik/svg/svg_parser.hpp index 0a2c4be61..3a60fcc87 100644 --- a/include/mapnik/svg/svg_parser.hpp +++ b/include/mapnik/svg/svg_parser.hpp @@ -86,12 +86,14 @@ class MAPNIK_DECL svg_parser : private util::noncopyable { using error_handler = svg_parser_error_handler; public: - explicit svg_parser(svg_converter_type & path, bool strict = false); + explicit svg_parser(svg_converter_type & path, double width, double height, bool strict = false); ~svg_parser(); error_handler & err_handler(); void parse(std::string const& filename); void parse_from_string(std::string const& svg); svg_converter_type & path_; + double width_; + double height_; bool is_defs_; bool strict_; bool ignore_; diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index a69b11e72..0ce328e4b 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -144,6 +144,12 @@ struct visitor_create_marker std::shared_ptr marker_cache::find(std::string const& uri, bool update_cache, bool strict) +{ + return find(uri, 0, 0, update_cache, strict); +} + +std::shared_ptr marker_cache::find(std::string const& uri, double width, double height, + bool update_cache, bool strict) { if (uri.empty()) { @@ -176,7 +182,7 @@ std::shared_ptr marker_cache::find(std::string const& uri, vertex_stl_adapter stl_storage(marker_path->source()); svg_path_adapter svg_path(stl_storage); svg_converter_type svg(svg_path, marker_path->attributes()); - svg_parser p(svg, strict); + svg_parser p(svg, width, height, strict); p.parse_from_string(known_svg_string); if (!strict) @@ -216,7 +222,7 @@ std::shared_ptr marker_cache::find(std::string const& uri, vertex_stl_adapter stl_storage(marker_path->source()); svg_path_adapter svg_path(stl_storage); svg_converter_type svg(svg_path, marker_path->attributes()); - svg_parser p(svg, strict); + svg_parser p(svg, width, height, strict); p.parse(uri); if (!strict) diff --git a/src/svg/svg_parser.cpp b/src/svg/svg_parser.cpp index 8bae77323..3bd916376 100644 --- a/src/svg/svg_parser.cpp +++ b/src/svg/svg_parser.cpp @@ -878,16 +878,28 @@ void parse_dimensions(svg_parser & parser, rapidxml::xml_node const* node) viewbox vbox = {0, 0, 0, 0}; bool has_percent_height = true; bool has_percent_width = true; - + bool overwrite_dimensions = false; auto const* width_attr = node->first_attribute("width"); - if (width_attr) - { - width = parse_svg_value(parser, width_attr->value(), has_percent_width); - } auto const* height_attr = node->first_attribute("height"); - if (height_attr) + + if (parser.width_ > 0 && parser.height_ > 0) // overwrite SVG document dimensions { - height = parse_svg_value(parser, height_attr->value(), has_percent_height); + has_percent_height = false; + has_percent_width = false; + overwrite_dimensions = true; + width = parser.width_; + height = parser.height_; + } + else + { + if (width_attr) + { + width = parse_svg_value(parser, width_attr->value(), has_percent_width); + } + if (height_attr) + { + height = parse_svg_value(parser, height_attr->value(), has_percent_height); + } } parser.vbox_ = viewbox{0, 0, width, height} ; auto const* viewbox_attr = node->first_attribute("viewBox"); @@ -896,12 +908,13 @@ void parse_dimensions(svg_parser & parser, rapidxml::xml_node const* node) agg::trans_affine t{}; parser.vbox_ = vbox; parser.normalized_diagonal_ = std::sqrt(vbox.width * vbox.width + vbox.height * vbox.height)/std::sqrt(2.0); - - if (has_percent_width) width = vbox.width * width; - else if (!width_attr || width == 0) width = vbox.width; - if (has_percent_height) height = vbox.height * height; - else if (!height_attr || height == 0) height = vbox.height; - + if (!overwrite_dimensions) + { + if (has_percent_width) width = vbox.width * width; + else if (!width_attr || width == 0) width = vbox.width; + if (has_percent_height) height = vbox.height * height; + else if (!height_attr || height == 0) height = vbox.height; + } if (width > 0 && height > 0 && vbox.width > 0 && vbox.height > 0) { std::pair preserve_aspect_ratio {xMidYMid, true}; @@ -1583,8 +1596,10 @@ void parse_linear_gradient(svg_parser & parser, rapidxml::xml_node const* } -svg_parser::svg_parser(svg_converter_type & path, bool strict) +svg_parser::svg_parser(svg_converter_type & path, double width, double height, bool strict) : path_(path), + width_(width), + height_(height), is_defs_(false), ignore_(false), css_style_(false), diff --git a/test/unit/svg/svg_parser_test.cpp b/test/unit/svg/svg_parser_test.cpp index e8a5f1249..1dfed9eae 100644 --- a/test/unit/svg/svg_parser_test.cpp +++ b/test/unit/svg/svg_parser_test.cpp @@ -48,7 +48,7 @@ namespace // internal : stl_storage(path.source()) , svg_path(stl_storage) , svg(svg_path, path.attributes()) - , p(svg, strict) + , p(svg, 0, 0, strict) {} mapnik::svg::svg_parser* operator->() diff --git a/utils/svg2png/svg2png.cpp b/utils/svg2png/svg2png.cpp index b4cbf6858..85cee042b 100644 --- a/utils/svg2png/svg2png.cpp +++ b/utils/svg2png/svg2png.cpp @@ -152,7 +152,7 @@ struct main_marker_visitor private: std::string svg_name_; - double scale_factor_ = 1.0; + double scale_factor_; bool verbose_; bool auto_open_; }; @@ -167,6 +167,8 @@ int main (int argc,char** argv) int status = 0; std::vector svg_files; mapnik::logger::instance().set_severity(mapnik::logger::error); + double target_width = 0.0; + double target_height = 0.0; double scale_factor = 1.0; std::string usage = "Usage: svg2png [options] "; try @@ -179,6 +181,8 @@ int main (int argc,char** argv) ("open,o","automatically open the file after rendering (os x only)") ("strict,s","enables strict SVG parsing") ("scale-factor", po::value(), "provide scaling factor (default: 1.0)") + ("width", po::value(), "width of the SVG document") + ("height", po::value(), "height of the SVG document") ("svg",po::value >(),"svg file to read") ; @@ -219,6 +223,14 @@ int main (int argc,char** argv) { scale_factor = vm["scale-factor"].as(); } + if (vm.count("width")) + { + target_width = vm["width"].as(); + } + if (vm.count("height")) + { + target_height = vm["height"].as(); + } if (vm.count("svg")) { svg_files=vm["svg"].as< std::vector >(); @@ -242,7 +254,8 @@ int main (int argc,char** argv) { std::clog << "found: " << svg_name << "\n"; } - std::shared_ptr marker = mapnik::marker_cache::instance().find(svg_name, false, strict); + std::shared_ptr marker = + mapnik::marker_cache::instance().find(svg_name, target_width, target_height, false, strict); main_marker_visitor visitor(svg_name, scale_factor, verbose, auto_open); status = mapnik::util::apply_visitor(visitor, *marker); }