From 95cc560167c6624939dfc6e805115a7d4afa1de9 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 23 Dec 2016 14:40:19 +0100 Subject: [PATCH] SVG points - implement using boost::spirit::x3 + refactor `parse_rule` instantiations into separate *.cpp --- include/mapnik/svg/svg_path_grammar_x3.hpp | 14 ++--- .../mapnik/svg/svg_path_grammar_x3_def.hpp | 17 +++++- .../mapnik/svg/svg_points_grammar_impl.hpp | 58 ------------------- src/build.py | 1 + .../svg/svg_path_grammar_x3.cpp | 32 ++++------ src/svg/svg_path_parser.cpp | 7 +-- src/svg/svg_points_parser.cpp | 27 +++++++-- 7 files changed, 57 insertions(+), 99 deletions(-) delete mode 100644 include/mapnik/svg/svg_points_grammar_impl.hpp rename include/mapnik/svg/svg_points_grammar.hpp => src/svg/svg_path_grammar_x3.cpp (58%) diff --git a/include/mapnik/svg/svg_path_grammar_x3.hpp b/include/mapnik/svg/svg_path_grammar_x3.hpp index 9ef050c96..80882fce1 100644 --- a/include/mapnik/svg/svg_path_grammar_x3.hpp +++ b/include/mapnik/svg/svg_path_grammar_x3.hpp @@ -23,26 +23,24 @@ #ifndef MAPNIK_SVG_PATH_GRAMMAR_X3_HPP #define MAPNIK_SVG_PATH_GRAMMAR_X3_HPP -#pragma GCC diagnostic push -#include -#include -#pragma GCC diagnostic pop +#include namespace mapnik { namespace svg { namespace grammar { namespace x3 = boost::spirit::x3; -class relative_tag; -class svg_path_tag; - using svg_path_grammar_type = x3::rule; +using svg_points_grammar_type = x3::rule; -BOOST_SPIRIT_DECLARE(svg_path_grammar_type); +BOOST_SPIRIT_DECLARE(svg_path_grammar_type, + svg_points_grammar_type); } grammar::svg_path_grammar_type const& svg_path_grammar(); +grammar::svg_points_grammar_type const& svg_points_grammar(); + }} #endif // MAPNIK_SVG_PATH_GRAMMAR_X3_HPP diff --git a/include/mapnik/svg/svg_path_grammar_x3_def.hpp b/include/mapnik/svg/svg_path_grammar_x3_def.hpp index 36a021913..d3d685ce7 100644 --- a/include/mapnik/svg/svg_path_grammar_x3_def.hpp +++ b/include/mapnik/svg/svg_path_grammar_x3_def.hpp @@ -23,6 +23,7 @@ #ifndef MAPNIK_SVG_PATH_GRAMMAR_X3_DEF_HPP #define MAPNIK_SVG_PATH_GRAMMAR_X3_DEF_HPP +// mapnik #include #include #include @@ -137,11 +138,15 @@ auto const absolute = [] (auto const& ctx) svg_path_grammar_type const svg_path = "SVG Path"; +svg_points_grammar_type const svg_points = "SVG_Points"; + auto const coord = x3::rule{} = double_ > -lit(',') > double_; +auto const svg_points_def = coord[move_to] // move_to + > *(-lit(',') >> coord[line_to]); // *line_to + auto const M = x3::rule {} = (lit('M')[absolute] | lit('m')[relative]) - > coord[move_to] // move_to - > *(-lit(',') >> coord[line_to]); // *line_to + > svg_points ; auto const H = x3::rule {} = (lit('H')[absolute] | lit('h')[relative]) > (double_[ hline_to] % -lit(',')) ; // +hline_to @@ -179,7 +184,8 @@ auto const svg_path_def = +cmd; #pragma GCC diagnostic push #include BOOST_SPIRIT_DEFINE( - svg_path + svg_path, + svg_points ); #pragma GCC diagnostic pop @@ -190,6 +196,11 @@ grammar::svg_path_grammar_type const& svg_path_grammar() return grammar::svg_path; } +grammar::svg_points_grammar_type const& svg_points_grammar() +{ + return grammar::svg_points; +} + }} #endif // MAPNIK_SVG_PATH_GRAMMAR_X3_HPP diff --git a/include/mapnik/svg/svg_points_grammar_impl.hpp b/include/mapnik/svg/svg_points_grammar_impl.hpp deleted file mode 100644 index f6f09583a..000000000 --- a/include/mapnik/svg/svg_points_grammar_impl.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2016 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 - * - *****************************************************************************/ - -// NOTE: This is an implementation header file and is only meant to be included -// from implementation files. It therefore doesn't have an include guard. -// mapnik -#include -#include - -#pragma GCC diagnostic push -#include -#include -#pragma GCC diagnostic pop - -namespace mapnik { namespace svg { - -using namespace boost::spirit; -using namespace boost::phoenix; - -template -svg_points_grammar::svg_points_grammar() - : svg_points_grammar::base_type(start) -{ - qi::_1_type _1; - qi::_r1_type _r1; - qi::lit_type lit; - qi::double_type double_; - // commands - function move_to_; - function line_to_; - function close_; - - start = coord[move_to_(_r1, _1, false)] // move_to - >> *(-lit(',') >> coord [ line_to_(_r1, _1,false) ] ); // *line_to - - coord = double_ >> -lit(',') >> double_; -} - -}} diff --git a/src/build.py b/src/build.py index 45ba882ee..a21583344 100644 --- a/src/build.py +++ b/src/build.py @@ -226,6 +226,7 @@ source = Split( svg/svg_path_parser.cpp svg/svg_points_parser.cpp svg/svg_transform_parser.cpp + svg/svg_path_grammar_x3.cpp warp.cpp css_color_grammar_x3.cpp vertex_cache.cpp diff --git a/include/mapnik/svg/svg_points_grammar.hpp b/src/svg/svg_path_grammar_x3.cpp similarity index 58% rename from include/mapnik/svg/svg_points_grammar.hpp rename to src/svg/svg_path_grammar_x3.cpp index 07c93cc08..b1b04434d 100644 --- a/include/mapnik/svg/svg_points_grammar.hpp +++ b/src/svg/svg_path_grammar_x3.cpp @@ -20,28 +20,18 @@ * *****************************************************************************/ -#ifndef SVG_POINTS_GRAMMAR_HPP -#define SVG_POINTS_GRAMMAR_HPP +#include -#pragma GCC diagnostic push -#include -#include -#pragma GCC diagnostic pop +namespace mapnik { namespace svg { namespace grammar { -namespace mapnik { namespace svg { +#define BOOST_SPIRIT_INSTANTIATE_UNUSED(rule_type, Iterator, Context) \ + template bool parse_rule( \ + rule_type rule_ \ + , Iterator& first, Iterator const& last \ + , Context const& context, boost::spirit::x3::unused_type const& ); \ + /***/ -using namespace boost::spirit; -using namespace boost::phoenix; +BOOST_SPIRIT_INSTANTIATE_UNUSED(svg_path_grammar_type, iterator_type, svg_parse_context_type); +BOOST_SPIRIT_INSTANTIATE_UNUSED(svg_points_grammar_type, iterator_type, svg_parse_context_type); -template -struct svg_points_grammar : qi::grammar -{ - // ctor - svg_points_grammar(); - // rules - qi::rule start; - qi::rule(), SkipType> coord; -}; -}} - -#endif // SVG_POINTS_GRAMMAR_HPP +}}} diff --git a/src/svg/svg_path_parser.cpp b/src/svg/svg_path_parser.cpp index 602a05115..53c3a94ee 100644 --- a/src/svg/svg_path_parser.cpp +++ b/src/svg/svg_path_parser.cpp @@ -23,7 +23,7 @@ // mapnik #include -#include +#include // stl #include #include @@ -36,18 +36,17 @@ bool parse_path(const char* wkt, PathType& p) { using namespace boost::spirit; using iterator_type = char const*; - using skip_type = x3::ascii::space_type; - skip_type space; iterator_type first = wkt; iterator_type last = wkt + std::strlen(wkt); bool relative = false; + using space_type = mapnik::svg::grammar::space_type; auto const grammar = x3::with(std::ref(p)) [ x3::with(std::ref(relative)) [mapnik::svg::svg_path_grammar()]]; try { - if (!x3::phrase_parse(first, last, grammar, space) + if (!x3::phrase_parse(first, last, grammar, space_type()) || first != last) { throw std::runtime_error("Failed to parse svg-path"); diff --git a/src/svg/svg_points_parser.cpp b/src/svg/svg_points_parser.cpp index 85e6663bb..9ede3b7de 100644 --- a/src/svg/svg_points_parser.cpp +++ b/src/svg/svg_points_parser.cpp @@ -22,7 +22,7 @@ // mapnik #include -#include +#include // stl #include #include @@ -34,12 +34,29 @@ template bool parse_points(const char* wkt, PathType& p) { using namespace boost::spirit; - using iterator_type = const char*; - using skip_type = ascii::space_type; - static const svg_points_grammar g; + using iterator_type = char const*; + using space_type = mapnik::svg::grammar::space_type; iterator_type first = wkt; iterator_type last = wkt + std::strlen(wkt); - return qi::phrase_parse(first, last, (g)(boost::phoenix::ref(p)), skip_type()); + bool relative = false; + + auto const grammar = x3::with(std::ref(p)) + [ x3::with(std::ref(relative)) + [mapnik::svg::svg_points_grammar()]]; + + try + { + if (!x3::phrase_parse(first, last, grammar, space_type()) + || first != last) + { + throw std::runtime_error("Failed to parse svg-path"); + } + } + catch (...) + { + return false; + } + return true; } template bool parse_points(const char*, svg_converter_type&);