diff --git a/include/mapnik/util/dasharray_parser.hpp b/include/mapnik/util/dasharray_parser.hpp new file mode 100644 index 000000000..e9a3753f2 --- /dev/null +++ b/include/mapnik/util/dasharray_parser.hpp @@ -0,0 +1,62 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 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_UTIL_DASHARRAY_PARSER_HPP +#define MAPNIK_UTIL_DASHARRAY_PARSER_HPP + +#include +#include +#include +#include + +namespace mapnik { namespace util { + +template +bool parse_dasharray(Iterator first, Iterator last, std::vector& dasharray) +{ + using qi::double_; + using qi::phrase_parse; + using qi::_1; + using qi::lit; + using ascii::space; + using phoenix::push_back; + // SVG + // dasharray ::= (length | percentage) (comma-wsp dasharray)? + // no support for 'percentage' as viewport is unknown at load_map + // + bool r = phrase_parse(first, last, + ( + lit("none") | (double_[push_back(phoenix::ref(dasharray), _1)] + >> *(',' >> double_[push_back(phoenix::ref(dasharray), _1)])) + ) + , + space); + + if (first != last) + return false; + + return r; +} + +}} + +#endif // MAPNIK_UTIL_DASHARRAY_PARSER_HPP diff --git a/src/load_map.cpp b/src/load_map.cpp index d27071c42..e30a72e3c 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -50,6 +50,7 @@ #include #include #include +#include // boost #include @@ -1229,39 +1230,29 @@ void map_parser::parse_stroke(stroke & strk, xml_node const & sym) optional str = sym.get_opt_attr("stroke-dasharray"); if (str) { - tokenizer<> tok (*str); std::vector dash_array; - tokenizer<>::iterator itr = tok.begin(); - for (; itr != tok.end(); ++itr) + if (util::parse_dasharray((*str).begin(),(*str).end(),dash_array)) { - try + if (!dash_array.empty()) { - double f = boost::lexical_cast(*itr); - dash_array.push_back(f); - } - catch (boost::bad_lexical_cast &) - { - throw config_error(std::string("Failed to parse dasharray ") + - "'. Expected a " + - "list of floats but got '" + (*str) + "'"); - } - } - if (dash_array.size()) - { - size_t size = dash_array.size(); - if (size % 2) - { - for (size_t i=0; i < size ;++i) + size_t size = dash_array.size(); + if (size % 2 == 1) + dash_array.insert(dash_array.end(),dash_array.begin(),dash_array.end()); + + std::vector::const_iterator pos = dash_array.begin(); + while (pos != dash_array.end()) { - dash_array.push_back(dash_array[i]); + if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0 + strk.add_dash(*pos,*(pos + 1)); + pos +=2; } - } - std::vector::const_iterator pos = dash_array.begin(); - while (pos != dash_array.end()) - { - strk.add_dash(*pos,*(pos + 1)); - pos +=2; - } + } + } + else + { + throw config_error(std::string("Failed to parse dasharray ") + + "'. Expected a " + + "list of floats or 'none' but got '" + (*str) + "'"); } } }