initial commit - make parse and parse_from_string return boolean ,collect error messages

This commit is contained in:
artemp 2015-07-14 19:45:50 +02:00
parent 6d6cb15b45
commit a46af76216
4 changed files with 103 additions and 24 deletions

View file

@ -38,15 +38,18 @@ namespace mapnik { namespace svg {
class MAPNIK_DECL svg_parser : private util::noncopyable class MAPNIK_DECL svg_parser : private util::noncopyable
{ {
using error_message_container = std::vector<std::string> ;
public: public:
explicit svg_parser(svg_converter_type & path); explicit svg_parser(svg_converter_type & path);
~svg_parser(); ~svg_parser();
void parse(std::string const& filename); error_message_container const& error_messages() const;
void parse_from_string(std::string const& svg); bool parse(std::string const& filename);
bool parse_from_string(std::string const& svg);
svg_converter_type & path_; svg_converter_type & path_;
bool is_defs_; bool is_defs_;
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_;
}; };
}} }}

View file

@ -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 <mapnik/config.hpp>
#include <exception>
// stl
#include <map>
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

View file

@ -175,7 +175,15 @@ std::shared_ptr<mapnik::marker const> marker_cache::find(std::string const& uri,
svg_path_adapter svg_path(stl_storage); svg_path_adapter svg_path(stl_storage);
svg_converter_type svg(svg_path, marker_path->attributes()); svg_converter_type svg(svg_path, marker_path->attributes());
svg_parser p(svg); 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 const>(mapnik::marker_null());
}
//svg.arrange_orientations(); //svg.arrange_orientations();
double lox,loy,hix,hiy; double lox,loy,hix,hiy;
svg.bounding_rect(&lox, &loy, &hix, &hiy); svg.bounding_rect(&lox, &loy, &hix, &hiy);

View file

@ -26,7 +26,7 @@
#include <mapnik/svg/svg_path_parser.hpp> #include <mapnik/svg/svg_path_parser.hpp>
#include <mapnik/config_error.hpp> #include <mapnik/config_error.hpp>
#include <mapnik/safe_cast.hpp> #include <mapnik/safe_cast.hpp>
#include <mapnik/svg/svg_parser_exception.hpp>
#include "agg_ellipse.h" #include "agg_ellipse.h"
#include "agg_rounded_rect.h" #include "agg_rounded_rect.h"
#include "agg_span_gradient.h" #include "agg_span_gradient.h"
@ -99,7 +99,8 @@ struct key_value_sequence_ordered
qi::rule<Iterator, std::string(), SkipType> key, value; qi::rule<Iterator, std::string(), SkipType> key, value;
}; };
agg::rgba8 parse_color(const char* str) template <typename T>
agg::rgba8 parse_color(T & error_messages, const char* str)
{ {
mapnik::color c(100,100,100); mapnik::color c(100,100,100);
try try
@ -108,7 +109,7 @@ agg::rgba8 parse_color(const char* str)
} }
catch (mapnik::config_error const& ex) 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()); 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 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 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")) 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 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 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")) 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) void parse_polygon(svg_parser & parser, xmlTextReaderPtr reader)
{ {
xmlChar *value; xmlChar *value;
value = xmlTextReaderGetAttribute(reader, BAD_CAST "points"); value = xmlTextReaderGetAttribute(reader, BAD_CAST "points");
if (value) if (value)
{ {
@ -815,7 +819,7 @@ void parse_gradient_stop(svg_parser & parser, xmlTextReaderPtr reader)
} }
catch (mapnik::config_error const& ex) 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") 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) catch (mapnik::config_error const& ex)
{ {
MAPNIK_LOG_ERROR(svg_parser) << ex.what(); parser.error_messages_.emplace_back(ex.what());
} }
xmlFree(value); xmlFree(value);
} }
@ -893,7 +897,9 @@ bool parse_common_gradient(svg_parser & parser, xmlTextReaderPtr reader)
} }
else 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); xmlFree(value);
@ -1062,32 +1068,40 @@ svg_parser::svg_parser(svg_converter<svg_path_adapter,
svg_parser::~svg_parser() {} svg_parser::~svg_parser() {}
void svg_parser::parse(std::string const& filename) bool svg_parser::parse(std::string const& filename)
{ {
xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename.c_str()); xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename.c_str());
if (reader == nullptr) if (reader == nullptr)
{ {
MAPNIK_LOG_ERROR(svg_parser) << "Unable to open '" << filename << "'"; std::stringstream ss;
ss << "Unable to open '" << filename << "'";
error_messages_.push_back(ss.str());
} }
else if (!parse_reader(*this,reader)) else if (!parse_reader(*this,reader))
{ {
MAPNIK_LOG_ERROR(svg_parser) << "Unable to parse '" << filename << "'"; std::stringstream ss;
ss << "Unable to parse '" << filename << "'";
error_messages_.push_back(ss.str());
} }
return error_messages_.empty() ? true : false;
} }
void svg_parser::parse_from_string(std::string const& svg) bool svg_parser::parse_from_string(std::string const& svg)
{ {
xmlTextReaderPtr reader = xmlReaderForMemory(svg.c_str(),safe_cast<int>(svg.size()),nullptr,nullptr, xmlTextReaderPtr reader = xmlReaderForMemory(svg.c_str(),safe_cast<int>(svg.size()),nullptr,nullptr,
(XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING)); (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 << "'"; std::stringstream ss;
} ss << "Unable to parse '" << svg << "'";
else if (!parse_reader(*this,reader)) error_messages_.push_back(ss.str());
{
MAPNIK_LOG_ERROR(svg_parser) << "Unable to parse '" << svg << "'";
} }
return error_messages_.empty() ? true : false;
} }
svg_parser::error_message_container const& svg_parser::error_messages() const
{
return error_messages_;
}
}} }}