SVG - add experimental "target" width and height which overwrite SVG's outermost "width" and "height" attributes [WIP]
This commit is contained in:
parent
21fd41b9a9
commit
792519e66a
6 changed files with 57 additions and 20 deletions
|
@ -56,6 +56,7 @@ public:
|
|||
bool is_svg_uri(std::string const& path);
|
||||
bool is_image_uri(std::string const& path);
|
||||
std::shared_ptr<marker const> find(std::string const& key, bool update_cache = false, bool strict = false);
|
||||
std::shared_ptr<marker const> find(std::string const& key, double width, double height, bool update_cache = false, bool strict = false);
|
||||
void clear();
|
||||
};
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -144,6 +144,12 @@ struct visitor_create_marker
|
|||
|
||||
std::shared_ptr<mapnik::marker const> marker_cache::find(std::string const& uri,
|
||||
bool update_cache, bool strict)
|
||||
{
|
||||
return find(uri, 0, 0, update_cache, strict);
|
||||
}
|
||||
|
||||
std::shared_ptr<mapnik::marker const> 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<mapnik::marker const> marker_cache::find(std::string const& uri,
|
|||
vertex_stl_adapter<svg_path_storage> 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<mapnik::marker const> marker_cache::find(std::string const& uri,
|
|||
vertex_stl_adapter<svg_path_storage> 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)
|
||||
|
|
|
@ -878,17 +878,29 @@ void parse_dimensions(svg_parser & parser, rapidxml::xml_node<char> 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");
|
||||
auto const* height_attr = node->first_attribute("height");
|
||||
|
||||
if (parser.width_ > 0 && parser.height_ > 0) // overwrite SVG document dimensions
|
||||
{
|
||||
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);
|
||||
}
|
||||
auto const* height_attr = node->first_attribute("height");
|
||||
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");
|
||||
if (viewbox_attr && parse_viewbox(parser.err_handler(), viewbox_attr->value(), vbox))
|
||||
|
@ -896,12 +908,13 @@ void parse_dimensions(svg_parser & parser, rapidxml::xml_node<char> 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 (!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<unsigned,bool> preserve_aspect_ratio {xMidYMid, true};
|
||||
|
@ -1583,8 +1596,10 @@ void parse_linear_gradient(svg_parser & parser, rapidxml::xml_node<char> 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),
|
||||
|
|
|
@ -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->()
|
||||
|
|
|
@ -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<std::string> 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] <svg-file(s)>";
|
||||
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<double>(), "provide scaling factor (default: 1.0)")
|
||||
("width", po::value<double>(), "width of the SVG document")
|
||||
("height", po::value<double>(), "height of the SVG document")
|
||||
("svg",po::value<std::vector<std::string> >(),"svg file to read")
|
||||
;
|
||||
|
||||
|
@ -219,6 +223,14 @@ int main (int argc,char** argv)
|
|||
{
|
||||
scale_factor = vm["scale-factor"].as<double>();
|
||||
}
|
||||
if (vm.count("width"))
|
||||
{
|
||||
target_width = vm["width"].as<double>();
|
||||
}
|
||||
if (vm.count("height"))
|
||||
{
|
||||
target_height = vm["height"].as<double>();
|
||||
}
|
||||
if (vm.count("svg"))
|
||||
{
|
||||
svg_files=vm["svg"].as< std::vector<std::string> >();
|
||||
|
@ -242,7 +254,8 @@ int main (int argc,char** argv)
|
|||
{
|
||||
std::clog << "found: " << svg_name << "\n";
|
||||
}
|
||||
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false, strict);
|
||||
std::shared_ptr<mapnik::marker const> 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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue