svg-parser : handle parsing failures via error_handler
( throw in strict mode and log+continue when strict==false)
This commit is contained in:
parent
e56233833e
commit
ef6c2e71b8
4 changed files with 129 additions and 115 deletions
|
@ -36,13 +36,36 @@
|
||||||
|
|
||||||
namespace mapnik { namespace svg {
|
namespace mapnik { namespace svg {
|
||||||
|
|
||||||
class MAPNIK_DECL svg_parser : private util::noncopyable
|
class svg_parser_error_handler
|
||||||
{
|
{
|
||||||
using error_message_container = std::vector<std::string> ;
|
using error_message_container = std::vector<std::string> ;
|
||||||
public:
|
public:
|
||||||
|
explicit svg_parser_error_handler(bool strict = false)
|
||||||
|
: strict_(strict) {}
|
||||||
|
|
||||||
|
void on_error(std::string const& msg)
|
||||||
|
{
|
||||||
|
if (strict_) throw std::runtime_error(msg);
|
||||||
|
else error_messages_.push_back(msg);
|
||||||
|
}
|
||||||
|
error_message_container const& error_messages() const
|
||||||
|
{
|
||||||
|
return error_messages_;
|
||||||
|
}
|
||||||
|
bool strict() const { return strict_; }
|
||||||
|
private:
|
||||||
|
|
||||||
|
error_message_container error_messages_;
|
||||||
|
bool strict_;
|
||||||
|
};
|
||||||
|
|
||||||
|
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, bool strict = false);
|
||||||
~svg_parser();
|
~svg_parser();
|
||||||
error_message_container const& error_messages() const;
|
error_handler & err_handler();
|
||||||
bool parse(std::string const& filename);
|
bool parse(std::string const& filename);
|
||||||
bool parse_from_string(std::string const& svg);
|
bool parse_from_string(std::string const& svg);
|
||||||
svg_converter_type & path_;
|
svg_converter_type & path_;
|
||||||
|
@ -50,8 +73,9 @@ namespace mapnik { namespace svg {
|
||||||
bool strict_;
|
bool strict_;
|
||||||
std::map<std::string, gradient> gradient_map_;
|
std::map<std::string, gradient> gradient_map_;
|
||||||
std::pair<std::string, gradient> temporary_gradient_;
|
std::pair<std::string, gradient> temporary_gradient_;
|
||||||
error_message_container error_messages_;
|
error_handler err_handler_;
|
||||||
};
|
|
||||||
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ std::shared_ptr<mapnik::marker const> marker_cache::find(std::string const& uri,
|
||||||
|
|
||||||
if (!p.parse_from_string(known_svg_string) && !strict)
|
if (!p.parse_from_string(known_svg_string) && !strict)
|
||||||
{
|
{
|
||||||
for (auto const& msg : p.error_messages())
|
for (auto const& msg : p.err_handler().error_messages())
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "SVG PARSING ERROR:\"" << msg << "\"";
|
MAPNIK_LOG_ERROR(marker_cache) << "SVG PARSING ERROR:\"" << msg << "\"";
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ std::shared_ptr<mapnik::marker const> marker_cache::find(std::string const& uri,
|
||||||
|
|
||||||
if (!p.parse(uri) && !strict)
|
if (!p.parse(uri) && !strict)
|
||||||
{
|
{
|
||||||
for (auto const& msg : p.error_messages())
|
for (auto const& msg : p.err_handler().error_messages())
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "SVG PARSING ERROR:\"" << msg << "\"";
|
MAPNIK_LOG_ERROR(marker_cache) << "SVG PARSING ERROR:\"" << msg << "\"";
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,17 +115,8 @@ BOOST_SPIRIT_DEFINE(key, value, key_value, key_value_sequence_ordered);
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
namespace {
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void on_error(T & error_messages, std::string const& msg, bool strict)
|
mapnik::color parse_color(T & err_handler, const char* str)
|
||||||
{
|
|
||||||
if (strict) throw std::runtime_error(msg);
|
|
||||||
else error_messages.emplace_back(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
mapnik::color parse_color(T & error_messages, const char* str)
|
|
||||||
{
|
{
|
||||||
mapnik::color c(100,100,100);
|
mapnik::color c(100,100,100);
|
||||||
try
|
try
|
||||||
|
@ -134,33 +125,33 @@ mapnik::color parse_color(T & error_messages, const char* str)
|
||||||
}
|
}
|
||||||
catch (mapnik::config_error const& ex)
|
catch (mapnik::config_error const& ex)
|
||||||
{
|
{
|
||||||
on_error(error_messages, ex.what(), false);
|
err_handler.on_error(ex.what());
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
agg::rgba8 parse_color_agg(T & error_messages, const char* str)
|
agg::rgba8 parse_color_agg(T & err_handler, const char* str)
|
||||||
{
|
{
|
||||||
auto c = parse_color(error_messages, str);
|
auto c = parse_color(err_handler, str);
|
||||||
return agg::rgba8(c.red(), c.green(), c.blue(), c.alpha());
|
return agg::rgba8(c.red(), c.green(), c.blue(), c.alpha());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
double parse_double(T & error_messages, const char* str)
|
double parse_double(T & err_handler, const char* str)
|
||||||
{
|
{
|
||||||
using namespace boost::spirit::x3;
|
using namespace boost::spirit::x3;
|
||||||
double val = 0.0;
|
double val = 0.0;
|
||||||
if (!parse(str, str + std::strlen(str), double_, val))
|
if (!parse(str, str + std::strlen(str), double_, val))
|
||||||
{
|
{
|
||||||
on_error(error_messages,"Failed to parse double: \"" + std::string(str) + "\"", false);
|
err_handler.on_error("Failed to parse double: \"" + std::string(str) + "\"");
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/SVG/coords.html#Units
|
// https://www.w3.org/TR/SVG/coords.html#Units
|
||||||
template <typename T, int DPI = 90>
|
template <typename T, int DPI = 90>
|
||||||
double parse_svg_value(T & error_messages, const char* str, bool & is_percent)
|
double parse_svg_value(T & err_handler, const char* str, bool & is_percent)
|
||||||
{
|
{
|
||||||
namespace x3 = boost::spirit::x3;
|
namespace x3 = boost::spirit::x3;
|
||||||
double val = 0.0;
|
double val = 0.0;
|
||||||
|
@ -187,18 +178,18 @@ double parse_svg_value(T & error_messages, const char* str, bool & is_percent)
|
||||||
x3::lit('%')[apply_percent]),
|
x3::lit('%')[apply_percent]),
|
||||||
x3::space))
|
x3::space))
|
||||||
{
|
{
|
||||||
on_error(error_messages,"Failed to parse SVG value: '" + std::string(str) + "'", false);
|
err_handler.on_error("Failed to parse SVG value: '" + std::string(str) + "'");
|
||||||
}
|
}
|
||||||
else if (cur != end)
|
else if (cur != end)
|
||||||
{
|
{
|
||||||
on_error(error_messages,"Failed to parse SVG value: '" + std::string(str) +
|
err_handler.on_error("Failed to parse SVG value: '" + std::string(str) +
|
||||||
"', trailing garbage: '" + cur + "'", false);
|
"', trailing garbage: '" + cur + "'");
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename V>
|
template <typename T, typename V>
|
||||||
bool parse_viewbox(T & error_messages, const char* str, V & viewbox)
|
bool parse_viewbox(T & err_handler, const char* str, V & viewbox)
|
||||||
{
|
{
|
||||||
namespace x3 = boost::spirit::x3;
|
namespace x3 = boost::spirit::x3;
|
||||||
if ( !x3::phrase_parse(str, str + std::strlen(str),
|
if ( !x3::phrase_parse(str, str + std::strlen(str),
|
||||||
|
@ -207,7 +198,7 @@ bool parse_viewbox(T & error_messages, const char* str, V & viewbox)
|
||||||
x3::double_ > -x3::lit(',') >
|
x3::double_ > -x3::lit(',') >
|
||||||
x3::double_, x3::space, viewbox))
|
x3::double_, x3::space, viewbox))
|
||||||
{
|
{
|
||||||
on_error(error_messages,"failed to parse SVG viewbox from " + std::string(str), false);
|
err_handler.on_error("failed to parse SVG viewbox from " + std::string(str));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -307,8 +298,7 @@ bool traverse_tree(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//std::cerr << "unprocessed node <--[" << node->name() << "]\n";
|
//parser.err_handler().on_error(std::string("Unsupported element:\"") + node->name());
|
||||||
on_error(parser.error_messages_, std::string("Unsupported element:\"") + node->name(), parser.strict_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.path_.pop_attr();
|
parser.path_.pop_attr();
|
||||||
|
@ -397,17 +387,17 @@ void parse_attr(svg_parser & parser, char const* name, char const* value )
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Failed to find gradient fill: " << id;
|
ss << "Failed to find gradient fill: " << id;
|
||||||
on_error(parser.error_messages_, ss.str(), parser.strict_);
|
parser.err_handler().on_error(ss.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parser.path_.fill(parse_color_agg(parser.error_messages_, value));
|
parser.path_.fill(parse_color_agg(parser.err_handler(), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name,"fill-opacity") == 0)
|
else if (std::strcmp(name,"fill-opacity") == 0)
|
||||||
{
|
{
|
||||||
parser.path_.fill_opacity(parse_double(parser.error_messages_, value));
|
parser.path_.fill_opacity(parse_double(parser.err_handler(), value));
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "fill-rule") == 0)
|
else if (std::strcmp(name, "fill-rule") == 0)
|
||||||
{
|
{
|
||||||
|
@ -434,22 +424,22 @@ void parse_attr(svg_parser & parser, char const* name, char const* value )
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Failed to find gradient stroke: " << id;
|
ss << "Failed to find gradient stroke: " << id;
|
||||||
on_error(parser.error_messages_, ss.str(), parser.strict_);
|
parser.err_handler().on_error(ss.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parser.path_.stroke(parse_color_agg(parser.error_messages_, value));
|
parser.path_.stroke(parse_color_agg(parser.err_handler(), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "stroke-width") == 0)
|
else if (std::strcmp(name, "stroke-width") == 0)
|
||||||
{
|
{
|
||||||
bool percent;
|
bool percent;
|
||||||
parser.path_.stroke_width(parse_svg_value(parser.error_messages_, value, percent));
|
parser.path_.stroke_width(parse_svg_value(parser.err_handler(), value, percent));
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "stroke-opacity") == 0)
|
else if (std::strcmp(name, "stroke-opacity") == 0)
|
||||||
{
|
{
|
||||||
parser.path_.stroke_opacity(parse_double(parser.error_messages_, value));
|
parser.path_.stroke_opacity(parse_double(parser.err_handler(), value));
|
||||||
}
|
}
|
||||||
else if(std::strcmp(name, "stroke-linecap") == 0)
|
else if(std::strcmp(name, "stroke-linecap") == 0)
|
||||||
{
|
{
|
||||||
|
@ -471,7 +461,7 @@ void parse_attr(svg_parser & parser, char const* name, char const* value )
|
||||||
}
|
}
|
||||||
else if(std::strcmp(name, "stroke-miterlimit") == 0)
|
else if(std::strcmp(name, "stroke-miterlimit") == 0)
|
||||||
{
|
{
|
||||||
parser.path_.miter_limit(parse_double(parser.error_messages_,value));
|
parser.path_.miter_limit(parse_double(parser.err_handler(),value));
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name,"stroke-dasharray") == 0)
|
else if (std::strcmp(name,"stroke-dasharray") == 0)
|
||||||
{
|
{
|
||||||
|
@ -483,12 +473,12 @@ void parse_attr(svg_parser & parser, char const* name, char const* value )
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name,"stroke-dashoffset") == 0)
|
else if (std::strcmp(name,"stroke-dashoffset") == 0)
|
||||||
{
|
{
|
||||||
double offset = parse_double(parser.error_messages_, value);
|
double offset = parse_double(parser.err_handler(), value);
|
||||||
parser.path_.dash_offset(offset);
|
parser.path_.dash_offset(offset);
|
||||||
}
|
}
|
||||||
else if(std::strcmp(name, "opacity") == 0)
|
else if(std::strcmp(name, "opacity") == 0)
|
||||||
{
|
{
|
||||||
double opacity = parse_double(parser.error_messages_, value);
|
double opacity = parse_double(parser.err_handler(), value);
|
||||||
parser.path_.opacity(opacity);
|
parser.path_.opacity(opacity);
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "visibility") == 0)
|
else if (std::strcmp(name, "visibility") == 0)
|
||||||
|
@ -501,7 +491,7 @@ void parse_attr(svg_parser & parser, char const* name, char const* value )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
on_error(parser.error_messages_, std::string("Unsupported attribute:\"") + name, parser.strict_);
|
//parser.err_handler().on_error(std::string("Unsupported attribute:\"") + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +524,7 @@ void parse_dimensions(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
double width = 0;
|
double width = 0;
|
||||||
double height = 0;
|
double height = 0;
|
||||||
double aspect_ratio = 1;
|
double aspect_ratio = 1;
|
||||||
viewbox vbox = {0,0,0,0};
|
viewbox vbox = {0, 0, 0, 0};
|
||||||
bool has_viewbox = false;
|
bool has_viewbox = false;
|
||||||
bool has_percent_height = true;
|
bool has_percent_height = true;
|
||||||
bool has_percent_width = true;
|
bool has_percent_width = true;
|
||||||
|
@ -542,17 +532,17 @@ void parse_dimensions(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
auto const* width_attr = node->first_attribute("width");
|
auto const* width_attr = node->first_attribute("width");
|
||||||
if (width_attr)
|
if (width_attr)
|
||||||
{
|
{
|
||||||
width = parse_svg_value(parser.error_messages_, width_attr->value(), has_percent_width);
|
width = parse_svg_value(parser.err_handler(), width_attr->value(), has_percent_width);
|
||||||
}
|
}
|
||||||
auto const* height_attr = node->first_attribute("height");
|
auto const* height_attr = node->first_attribute("height");
|
||||||
if (height_attr)
|
if (height_attr)
|
||||||
{
|
{
|
||||||
height = parse_svg_value(parser.error_messages_, height_attr->value(), has_percent_height);
|
height = parse_svg_value(parser.err_handler(), height_attr->value(), has_percent_height);
|
||||||
}
|
}
|
||||||
auto const* viewbox_attr = node->first_attribute("viewBox");
|
auto const* viewbox_attr = node->first_attribute("viewBox");
|
||||||
if (viewbox_attr)
|
if (viewbox_attr)
|
||||||
{
|
{
|
||||||
has_viewbox = parse_viewbox(parser.error_messages_, viewbox_attr->value(), vbox);
|
has_viewbox = parse_viewbox(parser.err_handler(), viewbox_attr->value(), vbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_percent_width && !has_percent_height && has_viewbox)
|
if (has_percent_width && !has_percent_height && has_viewbox)
|
||||||
|
@ -590,12 +580,12 @@ void parse_path(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
if (id_attr == nullptr) id_attr = node->first_attribute("id");
|
if (id_attr == nullptr) id_attr = node->first_attribute("id");
|
||||||
if (id_attr)
|
if (id_attr)
|
||||||
{
|
{
|
||||||
on_error(parser.error_messages_, std::string("unable to parse invalid svg <path> with id '")
|
parser.err_handler().on_error(std::string("unable to parse invalid svg <path> with id '")
|
||||||
+ id_attr->value() + "'", parser.strict_);
|
+ id_attr->value() + "'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
on_error(parser.error_messages_, std::string("unable to parse invalid svg <path>"), parser.strict_);
|
parser.err_handler().on_error(std::string("unable to parse invalid svg <path>"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.path_.end_path();
|
parser.path_.end_path();
|
||||||
|
@ -611,7 +601,7 @@ void parse_polygon(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
parser.path_.begin_path();
|
parser.path_.begin_path();
|
||||||
if (!mapnik::svg::parse_points(attr->value(), parser.path_))
|
if (!mapnik::svg::parse_points(attr->value(), parser.path_))
|
||||||
{
|
{
|
||||||
on_error(parser.error_messages_, std::string("Failed to parse <polygon> 'points'"), parser.strict_);
|
parser.err_handler().on_error(std::string("Failed to parse <polygon> 'points'"));
|
||||||
}
|
}
|
||||||
parser.path_.close_subpath();
|
parser.path_.close_subpath();
|
||||||
parser.path_.end_path();
|
parser.path_.end_path();
|
||||||
|
@ -626,7 +616,7 @@ void parse_polyline(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
parser.path_.begin_path();
|
parser.path_.begin_path();
|
||||||
if (!mapnik::svg::parse_points(attr->value(), parser.path_))
|
if (!mapnik::svg::parse_points(attr->value(), parser.path_))
|
||||||
{
|
{
|
||||||
on_error(parser.error_messages_, std::string("Failed to parse <polyline> 'points'"), parser.strict_);
|
parser.err_handler().on_error(std::string("Failed to parse <polyline> 'points'"));
|
||||||
}
|
}
|
||||||
parser.path_.end_path();
|
parser.path_.end_path();
|
||||||
}
|
}
|
||||||
|
@ -640,16 +630,16 @@ void parse_line(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
double y2 = 0.0;
|
double y2 = 0.0;
|
||||||
bool percent;
|
bool percent;
|
||||||
auto const* x1_attr = node->first_attribute("x1");
|
auto const* x1_attr = node->first_attribute("x1");
|
||||||
if (x1_attr) x1 = parse_svg_value(parser.error_messages_, x1_attr->value(), percent);
|
if (x1_attr) x1 = parse_svg_value(parser.err_handler(), x1_attr->value(), percent);
|
||||||
|
|
||||||
auto const* y1_attr = node->first_attribute("y1");
|
auto const* y1_attr = node->first_attribute("y1");
|
||||||
if (y1_attr) y1 = parse_svg_value(parser.error_messages_, y1_attr->value(), percent);
|
if (y1_attr) y1 = parse_svg_value(parser.err_handler(), y1_attr->value(), percent);
|
||||||
|
|
||||||
auto const* x2_attr = node->first_attribute("x2");
|
auto const* x2_attr = node->first_attribute("x2");
|
||||||
if (x2_attr) x2 = parse_svg_value(parser.error_messages_, x2_attr->value(), percent);
|
if (x2_attr) x2 = parse_svg_value(parser.err_handler(), x2_attr->value(), percent);
|
||||||
|
|
||||||
auto const* y2_attr = node->first_attribute("y2");
|
auto const* y2_attr = node->first_attribute("y2");
|
||||||
if (y2_attr) y2 = parse_svg_value(parser.error_messages_, y2_attr->value(), percent);
|
if (y2_attr) y2 = parse_svg_value(parser.err_handler(), y2_attr->value(), percent);
|
||||||
|
|
||||||
parser.path_.begin_path();
|
parser.path_.begin_path();
|
||||||
parser.path_.move_to(x1, y1);
|
parser.path_.move_to(x1, y1);
|
||||||
|
@ -666,19 +656,19 @@ void parse_circle(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
auto * attr = node->first_attribute("cx");
|
auto * attr = node->first_attribute("cx");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
cx = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
cx = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("cy");
|
attr = node->first_attribute("cy");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
cy = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
cy = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("r");
|
attr = node->first_attribute("r");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
r = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
r = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.path_.begin_path();
|
parser.path_.begin_path();
|
||||||
|
@ -686,7 +676,7 @@ void parse_circle(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
{
|
{
|
||||||
if (r < 0.0)
|
if (r < 0.0)
|
||||||
{
|
{
|
||||||
parser.error_messages_.emplace_back("parse_circle: Invalid radius");
|
parser.err_handler().on_error("parse_circle: Invalid radius");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -707,25 +697,25 @@ void parse_ellipse(svg_parser & parser, rapidxml::xml_node<char> const * node)
|
||||||
auto * attr = node->first_attribute("cx");
|
auto * attr = node->first_attribute("cx");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
cx = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
cx = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("cy");
|
attr = node->first_attribute("cy");
|
||||||
if (attr)
|
if (attr)
|
||||||
{
|
{
|
||||||
cy = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
cy = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("rx");
|
attr = node->first_attribute("rx");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
rx = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
rx = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("ry");
|
attr = node->first_attribute("ry");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
ry = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
ry = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx != 0.0 && ry != 0.0)
|
if (rx != 0.0 && ry != 0.0)
|
||||||
|
@ -733,11 +723,11 @@ void parse_ellipse(svg_parser & parser, rapidxml::xml_node<char> const * node)
|
||||||
|
|
||||||
if (rx < 0.0)
|
if (rx < 0.0)
|
||||||
{
|
{
|
||||||
parser.error_messages_.emplace_back("parse_ellipse: Invalid rx");
|
parser.err_handler().on_error("parse_ellipse: Invalid rx");
|
||||||
}
|
}
|
||||||
else if (ry < 0.0)
|
else if (ry < 0.0)
|
||||||
{
|
{
|
||||||
parser.error_messages_.emplace_back("parse_ellipse: Invalid ry");
|
parser.err_handler().on_error("parse_ellipse: Invalid ry");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -762,31 +752,31 @@ void parse_rect(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
auto * attr = node->first_attribute("x");
|
auto * attr = node->first_attribute("x");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
x = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
x = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("y");
|
attr = node->first_attribute("y");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
y = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
y = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("width");
|
attr = node->first_attribute("width");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
w = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
w = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
attr = node->first_attribute("height");
|
attr = node->first_attribute("height");
|
||||||
if (attr)
|
if (attr)
|
||||||
{
|
{
|
||||||
h = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
h = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rounded = true;
|
bool rounded = true;
|
||||||
attr = node->first_attribute("rx");
|
attr = node->first_attribute("rx");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
rx = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
rx = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
if ( rx > 0.5 * w ) rx = 0.5 * w;
|
if ( rx > 0.5 * w ) rx = 0.5 * w;
|
||||||
}
|
}
|
||||||
else rounded = false;
|
else rounded = false;
|
||||||
|
@ -794,7 +784,7 @@ void parse_rect(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
attr = node->first_attribute("ry");
|
attr = node->first_attribute("ry");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
ry = parse_svg_value(parser.error_messages_, attr->value(), percent);
|
ry = parse_svg_value(parser.err_handler(), attr->value(), percent);
|
||||||
if ( ry > 0.5 * h ) ry = 0.5 * h;
|
if ( ry > 0.5 * h ) ry = 0.5 * h;
|
||||||
if (!rounded)
|
if (!rounded)
|
||||||
{
|
{
|
||||||
|
@ -811,19 +801,19 @@ void parse_rect(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
{
|
{
|
||||||
if(w < 0.0)
|
if(w < 0.0)
|
||||||
{
|
{
|
||||||
parser.error_messages_.emplace_back("parse_rect: Invalid width");
|
parser.err_handler().on_error("parse_rect: Invalid width");
|
||||||
}
|
}
|
||||||
else if(h < 0.0)
|
else if(h < 0.0)
|
||||||
{
|
{
|
||||||
parser.error_messages_.emplace_back("parse_rect: Invalid height");
|
parser.err_handler().on_error("parse_rect: Invalid height");
|
||||||
}
|
}
|
||||||
else if(rx < 0.0)
|
else if(rx < 0.0)
|
||||||
{
|
{
|
||||||
parser.error_messages_.emplace_back("parse_rect: Invalid rx");
|
parser.err_handler().on_error("parse_rect: Invalid rx");
|
||||||
}
|
}
|
||||||
else if(ry < 0.0)
|
else if(ry < 0.0)
|
||||||
{
|
{
|
||||||
parser.error_messages_.emplace_back("parse_rect: Invalid ry");
|
parser.err_handler().on_error("parse_rect: Invalid ry");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -858,7 +848,7 @@ void parse_gradient_stop(svg_parser & parser, rapidxml::xml_node<char> const* no
|
||||||
auto * attr = node->first_attribute("offset");
|
auto * attr = node->first_attribute("offset");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
offset = parse_double(parser.error_messages_,attr->value());
|
offset = parse_double(parser.err_handler(),attr->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("style");
|
attr = node->first_attribute("style");
|
||||||
|
@ -873,11 +863,11 @@ void parse_gradient_stop(svg_parser & parser, rapidxml::xml_node<char> const* no
|
||||||
{
|
{
|
||||||
if (kv.first == "stop-color")
|
if (kv.first == "stop-color")
|
||||||
{
|
{
|
||||||
stop_color = parse_color(parser.error_messages_, kv.second.c_str());
|
stop_color = parse_color(parser.err_handler(), kv.second.c_str());
|
||||||
}
|
}
|
||||||
else if (kv.first == "stop-opacity")
|
else if (kv.first == "stop-opacity")
|
||||||
{
|
{
|
||||||
opacity = parse_double(parser.error_messages_,kv.second.c_str());
|
opacity = parse_double(parser.err_handler(),kv.second.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -885,13 +875,13 @@ void parse_gradient_stop(svg_parser & parser, rapidxml::xml_node<char> const* no
|
||||||
attr = node->first_attribute("stop-color");
|
attr = node->first_attribute("stop-color");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
stop_color = parse_color(parser.error_messages_, attr->value());
|
stop_color = parse_color(parser.err_handler(), attr->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("stop-opacity");
|
attr = node->first_attribute("stop-opacity");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
opacity = parse_double(parser.error_messages_, attr->value());
|
opacity = parse_double(parser.err_handler(), attr->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_color.set_alpha(static_cast<uint8_t>(opacity * 255));
|
stop_color.set_alpha(static_cast<uint8_t>(opacity * 255));
|
||||||
|
@ -931,7 +921,7 @@ bool parse_common_gradient(svg_parser & parser, rapidxml::xml_node<char> const*
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Failed to find linked gradient " << linkid;
|
ss << "Failed to find linked gradient " << linkid;
|
||||||
on_error(parser.error_messages_, ss.str(), parser.strict_);
|
parser.err_handler().on_error(ss.str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -973,19 +963,19 @@ void parse_radial_gradient(svg_parser & parser, rapidxml::xml_node<char> const*
|
||||||
auto * attr = node->first_attribute("cx");
|
auto * attr = node->first_attribute("cx");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
cx = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
cx = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("cy");
|
attr = node->first_attribute("cy");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
cy = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
cy = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("fx");
|
attr = node->first_attribute("fx");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
fx = parse_svg_value(parser.error_messages_,attr->value(), has_percent);
|
fx = parse_svg_value(parser.err_handler(),attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fx = cx;
|
fx = cx;
|
||||||
|
@ -993,14 +983,14 @@ void parse_radial_gradient(svg_parser & parser, rapidxml::xml_node<char> const*
|
||||||
attr = node->first_attribute("fy");
|
attr = node->first_attribute("fy");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
fy = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
fy = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
else fy = cy;
|
else fy = cy;
|
||||||
|
|
||||||
attr = node->first_attribute("r");
|
attr = node->first_attribute("r");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
r = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
r = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
// this logic for detecting %'s will not support mixed coordinates.
|
// this logic for detecting %'s will not support mixed coordinates.
|
||||||
if (has_percent && parser.temporary_gradient_.second.get_units() == USER_SPACE_ON_USE)
|
if (has_percent && parser.temporary_gradient_.second.get_units() == USER_SPACE_ON_USE)
|
||||||
|
@ -1029,25 +1019,25 @@ void parse_linear_gradient(svg_parser & parser, rapidxml::xml_node<char> const*
|
||||||
auto * attr = node->first_attribute("x1");
|
auto * attr = node->first_attribute("x1");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
x1 = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
x1 = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("x2");
|
attr = node->first_attribute("x2");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
x2 = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
x2 = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("y1");
|
attr = node->first_attribute("y1");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
y1 = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
y1 = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = node->first_attribute("y2");
|
attr = node->first_attribute("y2");
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
{
|
{
|
||||||
y2 = parse_svg_value(parser.error_messages_, attr->value(), has_percent);
|
y2 = parse_svg_value(parser.err_handler(), attr->value(), has_percent);
|
||||||
}
|
}
|
||||||
// this logic for detecting %'s will not support mixed coordinates.
|
// this logic for detecting %'s will not support mixed coordinates.
|
||||||
if (has_percent && parser.temporary_gradient_.second.get_units() == USER_SPACE_ON_USE)
|
if (has_percent && parser.temporary_gradient_.second.get_units() == USER_SPACE_ON_USE)
|
||||||
|
@ -1065,7 +1055,7 @@ svg_parser::svg_parser(svg_converter<svg_path_adapter,
|
||||||
agg::pod_bvector<mapnik::svg::path_attributes> > & path, bool strict)
|
agg::pod_bvector<mapnik::svg::path_attributes> > & path, bool strict)
|
||||||
: path_(path),
|
: path_(path),
|
||||||
is_defs_(false),
|
is_defs_(false),
|
||||||
strict_(strict) {}
|
err_handler_(strict) {}
|
||||||
|
|
||||||
svg_parser::~svg_parser() {}
|
svg_parser::~svg_parser() {}
|
||||||
|
|
||||||
|
@ -1080,7 +1070,7 @@ bool svg_parser::parse(std::string const& filename)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Unable to open '" << filename << "'";
|
ss << "Unable to open '" << filename << "'";
|
||||||
error_messages_.push_back(ss.str());
|
err_handler_.on_error(ss.str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,7 +1089,7 @@ bool svg_parser::parse(std::string const& filename)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "svg_parser::parse - Unable to parse '" << filename << "'";
|
ss << "svg_parser::parse - Unable to parse '" << filename << "'";
|
||||||
error_messages_.push_back(ss.str());
|
err_handler_.on_error(ss.str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1108,7 +1098,7 @@ bool svg_parser::parse(std::string const& filename)
|
||||||
{
|
{
|
||||||
traverse_tree(*this, child);
|
traverse_tree(*this, child);
|
||||||
}
|
}
|
||||||
return error_messages_.empty() ? true : false;
|
return err_handler_.error_messages().empty() ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool svg_parser::parse_from_string(std::string const& svg)
|
bool svg_parser::parse_from_string(std::string const& svg)
|
||||||
|
@ -1125,7 +1115,7 @@ bool svg_parser::parse_from_string(std::string const& svg)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Unable to parse '" << svg << "'";
|
ss << "Unable to parse '" << svg << "'";
|
||||||
error_messages_.push_back(ss.str());
|
err_handler_.on_error(ss.str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (rapidxml::xml_node<char> const* child = doc.first_node();
|
for (rapidxml::xml_node<char> const* child = doc.first_node();
|
||||||
|
@ -1133,12 +1123,12 @@ bool svg_parser::parse_from_string(std::string const& svg)
|
||||||
{
|
{
|
||||||
traverse_tree(*this, child);
|
traverse_tree(*this, child);
|
||||||
}
|
}
|
||||||
return error_messages_.empty() ? true : false;
|
return err_handler_.error_messages().empty() ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg_parser::error_message_container const& svg_parser::error_messages() const
|
svg_parser::error_handler & svg_parser::err_handler()
|
||||||
{
|
{
|
||||||
return error_messages_;
|
return err_handler_;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -92,7 +92,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse(svg_name));
|
REQUIRE(!p->parse(svg_name));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG::parse_from_string syntax error")
|
SECTION("SVG::parse_from_string syntax error")
|
||||||
|
@ -109,7 +109,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse_from_string(svg_str));
|
REQUIRE(!p->parse_from_string(svg_str));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG::parse_from_string syntax error")
|
SECTION("SVG::parse_from_string syntax error")
|
||||||
|
@ -122,7 +122,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse(svg_name));
|
REQUIRE(!p->parse(svg_name));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG parser color <fail>")
|
SECTION("SVG parser color <fail>")
|
||||||
|
@ -142,7 +142,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse_from_string(svg_str));
|
REQUIRE(!p->parse_from_string(svg_str));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG - cope with erroneous geometries")
|
SECTION("SVG - cope with erroneous geometries")
|
||||||
|
@ -172,7 +172,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse_from_string(svg_str));
|
REQUIRE(!p->parse_from_string(svg_str));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG parser double % <fail>")
|
SECTION("SVG parser double % <fail>")
|
||||||
|
@ -190,7 +190,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse_from_string(svg_str));
|
REQUIRE(!p->parse_from_string(svg_str));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG parser display=none")
|
SECTION("SVG parser display=none")
|
||||||
|
@ -612,7 +612,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse(svg_name));
|
REQUIRE(!p->parse(svg_name));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG missing <gradient> id")
|
SECTION("SVG missing <gradient> id")
|
||||||
|
@ -630,7 +630,7 @@ TEST_CASE("SVG parser") {
|
||||||
|
|
||||||
test_parser p;
|
test_parser p;
|
||||||
REQUIRE(!p->parse_from_string(svg_str));
|
REQUIRE(!p->parse_from_string(svg_str));
|
||||||
REQUIRE(join(p->error_messages()) == join(expected_errors));
|
REQUIRE(join(p->err_handler().error_messages()) == join(expected_errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG missing <gradient> inheritance")
|
SECTION("SVG missing <gradient> inheritance")
|
||||||
|
|
Loading…
Reference in a new issue