From a46af7621685de1fabd44b7b5a030bfec8988c2e Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 14 Jul 2015 19:45:50 +0200 Subject: [PATCH] initial commit - make parse and parse_from_string return boolean ,collect error messages --- include/mapnik/svg/svg_parser.hpp | 7 ++- include/mapnik/svg/svg_parser_exception.hpp | 54 ++++++++++++++++++++ src/marker_cache.cpp | 10 +++- src/svg/svg_parser.cpp | 56 +++++++++++++-------- 4 files changed, 103 insertions(+), 24 deletions(-) create mode 100644 include/mapnik/svg/svg_parser_exception.hpp diff --git a/include/mapnik/svg/svg_parser.hpp b/include/mapnik/svg/svg_parser.hpp index ef9eafc06..63caacd8b 100644 --- a/include/mapnik/svg/svg_parser.hpp +++ b/include/mapnik/svg/svg_parser.hpp @@ -38,15 +38,18 @@ namespace mapnik { namespace svg { class MAPNIK_DECL svg_parser : private util::noncopyable { + using error_message_container = std::vector ; public: explicit svg_parser(svg_converter_type & path); ~svg_parser(); - void parse(std::string const& filename); - void parse_from_string(std::string const& svg); + error_message_container const& error_messages() const; + bool parse(std::string const& filename); + bool parse_from_string(std::string const& svg); svg_converter_type & path_; bool is_defs_; std::map gradient_map_; std::pair temporary_gradient_; + error_message_container error_messages_; }; }} diff --git a/include/mapnik/svg/svg_parser_exception.hpp b/include/mapnik/svg/svg_parser_exception.hpp new file mode 100644 index 000000000..89139da88 --- /dev/null +++ b/include/mapnik/svg/svg_parser_exception.hpp @@ -0,0 +1,54 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_SVG_PARSER_EXCEPTION_HPP +#define MAPNIK_SVG_PARSER_EXCEPTION_HPP + +// mapnik +#include +#include + +// stl +#include + +namespace mapnik { namespace svg { + +class MAPNIK_DECL svg_parser_exception : public std::exception +{ +public: + svg_parser_exception(std::string const& message) + : message_(message) {} + + ~svg_parser_exception() throw() {} + + virtual const char* what() const throw() + { + return message_.c_str(); + } +private: + std::string message_; +}; + +}} + + +#endif // MAPNIK_SVG_PARSER_EXCEPTION_HPP diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 3f8f9396b..6dbd6f5cb 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -175,7 +175,15 @@ std::shared_ptr marker_cache::find(std::string const& uri, svg_path_adapter svg_path(stl_storage); svg_converter_type svg(svg_path, marker_path->attributes()); svg_parser p(svg); - p.parse_from_string(known_svg_string); + + if (!p.parse_from_string(known_svg_string)) + { + for (auto const& msg : p.error_messages()) + { + std::cerr << "SVG PARSING ERROR:\"" << msg << "\"" << std::endl; + } + return std::make_shared(mapnik::marker_null()); + } //svg.arrange_orientations(); double lox,loy,hix,hiy; svg.bounding_rect(&lox, &loy, &hix, &hiy); diff --git a/src/svg/svg_parser.cpp b/src/svg/svg_parser.cpp index 1ef103c3b..c1f6ad49a 100644 --- a/src/svg/svg_parser.cpp +++ b/src/svg/svg_parser.cpp @@ -26,7 +26,7 @@ #include #include #include - +#include #include "agg_ellipse.h" #include "agg_rounded_rect.h" #include "agg_span_gradient.h" @@ -99,7 +99,8 @@ struct key_value_sequence_ordered qi::rule key, value; }; -agg::rgba8 parse_color(const char* str) +template +agg::rgba8 parse_color(T & error_messages, const char* str) { mapnik::color c(100,100,100); try @@ -108,7 +109,7 @@ agg::rgba8 parse_color(const char* str) } catch (mapnik::config_error const& ex) { - MAPNIK_LOG_ERROR(svg_parser) << ex.what(); + error_messages.emplace_back(ex.what()); } return agg::rgba8(c.red(), c.green(), c.blue(), c.alpha()); } @@ -330,12 +331,14 @@ void parse_attr(svg_parser & parser, const xmlChar * name, const xmlChar * value } else { - MAPNIK_LOG_ERROR(svg_parser) << "Failed to find gradient fill: " << id; + std::stringstream ss; + ss << "Failed to find gradient fill: " << id; + parser.error_messages_.push_back(ss.str()); } } else { - parser.path_.fill(parse_color((const char*) value)); + parser.path_.fill(parse_color(parser.error_messages_, (const char*) value)); } } else if (xmlStrEqual(name, BAD_CAST "fill-opacity")) @@ -367,12 +370,14 @@ void parse_attr(svg_parser & parser, const xmlChar * name, const xmlChar * value } else { - MAPNIK_LOG_ERROR(svg_parser) << "Failed to find gradient fill: " << id; + std::stringstream ss; + ss << "Failed to find gradient fill: " << id; + parser.error_messages_.push_back(ss.str()); } } else { - parser.path_.stroke(parse_color((const char*) value)); + parser.path_.stroke(parse_color(parser.error_messages_, (const char*) value)); } } else if (xmlStrEqual(name, BAD_CAST "stroke-width")) @@ -519,7 +524,6 @@ void parse_path(svg_parser & parser, xmlTextReaderPtr reader) void parse_polygon(svg_parser & parser, xmlTextReaderPtr reader) { xmlChar *value; - value = xmlTextReaderGetAttribute(reader, BAD_CAST "points"); if (value) { @@ -815,7 +819,7 @@ void parse_gradient_stop(svg_parser & parser, xmlTextReaderPtr reader) } catch (mapnik::config_error const& ex) { - MAPNIK_LOG_ERROR(svg_parser) << ex.what(); + parser.error_messages_.emplace_back(ex.what()); } } else if (kv.first == "stop-opacity") @@ -835,7 +839,7 @@ void parse_gradient_stop(svg_parser & parser, xmlTextReaderPtr reader) } catch (mapnik::config_error const& ex) { - MAPNIK_LOG_ERROR(svg_parser) << ex.what(); + parser.error_messages_.emplace_back(ex.what()); } xmlFree(value); } @@ -893,7 +897,9 @@ bool parse_common_gradient(svg_parser & parser, xmlTextReaderPtr reader) } else { - MAPNIK_LOG_ERROR(svg_parser) << "Failed to find linked gradient " << linkid; + std::stringstream ss; + ss << "Failed to find linked gradient " << linkid; + parser.error_messages_.push_back(ss.str()); } } xmlFree(value); @@ -1062,32 +1068,40 @@ svg_parser::svg_parser(svg_converter(svg.size()),nullptr,nullptr, (XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING)); - if (reader == nullptr) + if (reader == nullptr ||!parse_reader(*this,reader)) { - MAPNIK_LOG_ERROR(svg_parser) << "Unable to parse '" << svg << "'"; - } - else if (!parse_reader(*this,reader)) - { - MAPNIK_LOG_ERROR(svg_parser) << "Unable to parse '" << svg << "'"; + std::stringstream ss; + ss << "Unable to parse '" << svg << "'"; + error_messages_.push_back(ss.str()); } + return error_messages_.empty() ? true : false; } +svg_parser::error_message_container const& svg_parser::error_messages() const +{ + return error_messages_; +} }}