transform_expression - port parsing grammar to x3

This commit is contained in:
artemp 2015-12-04 15:55:01 +00:00
parent 8bf0cff8cb
commit 2acaa7f9f4
3 changed files with 154 additions and 8 deletions

View file

@ -231,9 +231,9 @@ bool is_null_node (T const& node)
} // namespace detail
using transform_node = detail::transform_node ;
using transform_list = std::vector<transform_node> ;
using transform_list_ptr = std::shared_ptr<transform_list> ;
using transform_node = detail::transform_node;
using transform_list = std::vector<transform_node>;
using transform_list_ptr = std::shared_ptr<transform_list>;
MAPNIK_DECL std::string to_expression_string(transform_node const& node);
MAPNIK_DECL std::string to_expression_string(transform_list const& list);

View file

@ -0,0 +1,140 @@
/*****************************************************************************
*
* 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_TRANSFORM_GRAMMAR_X3_DEF_HPP
#define MAPNIK_TRANSFORM_GRAMMAR_X3_DEF_HPP
#include <boost/spirit/home/x3.hpp>
#include <mapnik/transform_expression.hpp>
#include <mapnik/expression_grammar_x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
// adapt transform nodes
// martrix
BOOST_FUSION_ADAPT_STRUCT(mapnik::matrix_node,
(mapnik::expr_node, a_)
(mapnik::expr_node, b_)
(mapnik::expr_node, c_)
(mapnik::expr_node, d_)
(mapnik::expr_node, e_)
(mapnik::expr_node, f_))
// translate
BOOST_FUSION_ADAPT_STRUCT(mapnik::translate_node,
(mapnik::expr_node, tx_)
(mapnik::expr_node, ty_))
// scale
BOOST_FUSION_ADAPT_STRUCT(mapnik::scale_node,
(mapnik::expr_node, sx_)
(mapnik::expr_node, sy_))
// rotate
BOOST_FUSION_ADAPT_STRUCT(mapnik::rotate_node,
(mapnik::expr_node, angle_)
(mapnik::expr_node, cx_)
(mapnik::expr_node, cy_))
// skewX
BOOST_FUSION_ADAPT_STRUCT(mapnik::skewX_node,
(mapnik::expr_node, angle_))
// skewY
BOOST_FUSION_ADAPT_STRUCT(mapnik::skewY_node,
(mapnik::expr_node, angle_))
namespace mapnik { namespace grammar {
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
// [http://www.w3.org/TR/SVG/coords.html#TransformAttribute]
// The value of the transform attribute is a <transform-list>, which
// is defined as a list of transform definitions, which are applied in
// the order provided. The individual transform definitions are
// separated by whitespace and/or a comma.
using x3::double_;
using x3::no_skip;
using x3::no_case;
using x3::lit;
using x3::char_;
x3::rule<class transform_list_class, mapnik::transform_list> transform_list_rule("transform list");
x3::rule<class transform_node_class, mapnik::transform_node> transform_node_rule("transform node");
x3::rule<class matrix_node_class, mapnik::matrix_node> matrix("matrix node");
x3::rule<class translate_node_class, mapnik::translate_node> translate("translate node");
x3::rule<class scale_node_class, mapnik::scale_node> scale("scale node");
x3::rule<class rotate_node_class, mapnik::rotate_node> rotate("rotate node");
x3::rule<class skewX_node_class, mapnik::skewX_node> skewX("skew X node");
x3::rule<class skewY_node_class, mapnik::skewY_node> skewY("skew Y node");
// Import the expression rule
namespace { auto const& expr = expression_grammar(); }
auto const transform_list_rule_def = transform_node_rule % no_skip[char_(", ")];
auto const transform_node_rule_def = matrix | translate | scale | rotate | skewX | skewY ;
// matrix(<a> <b> <c> <d> <e> <f>)
auto const matrix_def = no_case[lit("matrix")]
> '(' > expr > ',' > expr > ',' > expr > ',' > expr > ',' > expr > ',' > expr > ')'
;
// translate(<tx> [<ty>])
auto const translate_def = no_case[lit("translate")]
> '(' > expr > -(',' > expr ) > ')'
;
// scale(<sx> [<sy>])
auto const scale_def = no_case[lit("scale")]
> '(' > expr > -(',' > expr ) > ')'
;
// rotate(<rotate-angle> [<cx> <cy>])
auto const rotate_def = no_case[lit("rotate")]
> '(' > expr > -(',' > expr > ',' > expr) > ')'
;
// skewX(<skew-angle>)
auto const skewX_def = no_case[lit("skewX")]
> '(' > expr > ')';
// skewY(<skew-angle>)
auto const skewY_def = no_case[lit("skewY")]
> '(' > expr > ')';
BOOST_SPIRIT_DEFINE (
transform_list_rule,
transform_node_rule,
matrix,
translate,
scale,
rotate,
skewX,
skewY
);
}} //
#endif // ns

View file

@ -21,7 +21,7 @@
*****************************************************************************/
#include <mapnik/parse_transform.hpp>
#include <mapnik/transform_expression_grammar.hpp>
#include <mapnik/transform_expression_grammar_x3_def.hpp>
// stl
#include <string>
@ -31,14 +31,20 @@ namespace mapnik {
transform_list_ptr parse_transform(std::string const& str, std::string const& encoding)
{
static const transform_expression_grammar<std::string::const_iterator> g;
transform_list_ptr tl = std::make_shared<transform_list>();
using boost::spirit::x3::ascii::space;
transform_list_ptr trans_list = std::make_shared<transform_list>();
std::string::const_iterator itr = str.begin();
std::string::const_iterator end = str.end();
bool r = qi::phrase_parse(itr, end, g, space_type(), *tl);
mapnik::transcoder const tr(encoding);
auto const parser = boost::spirit::x3::with<mapnik::grammar::transcoder_tag>(std::ref(tr))
[
mapnik::grammar::transform_list_rule
];
// FIXME : try/catch!
bool r = boost::spirit::x3::phrase_parse(itr, end, parser, space, *trans_list);
if (r && itr == end)
{
return tl;
return trans_list;
}
else
{