diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index 858c53437..5ade76573 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -125,7 +125,7 @@ bool painted(mapnik::image_32 const& im) void set_pixel(mapnik::image_32 & im, unsigned x, unsigned y, mapnik::color const& c) { im.setPixel(x, y, c.rgba()); -} +} boost::shared_ptr open_from_file(std::string const& filename) { diff --git a/bindings/python/mapnik_polygon_symbolizer.cpp b/bindings/python/mapnik_polygon_symbolizer.cpp index 4b4fb1b1a..dd809ac5d 100644 --- a/bindings/python/mapnik_polygon_symbolizer.cpp +++ b/bindings/python/mapnik_polygon_symbolizer.cpp @@ -84,7 +84,11 @@ void export_polygon_symbolizer() .add_property("gamma_method", &polygon_symbolizer::get_gamma_method, &polygon_symbolizer::set_gamma_method, - "Set/get the gamma correction method of the polygon") + "gamma correction method") + .add_property("smooth", + &polygon_symbolizer::smooth, + &polygon_symbolizer::set_smooth, + "smooth value (0..1.0)") ; } diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index 12c8dfa55..c9f1ac4e5 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -40,15 +40,15 @@ using namespace mapnik; /* Notes: -Overriding functions in inherited classes: -boost.python documentation doesn't really tell you how to do it. -But this helps: -http://www.gamedev.net/topic/446225-inheritance-in-boostpython/ + Overriding functions in inherited classes: + boost.python documentation doesn't really tell you how to do it. + But this helps: + http://www.gamedev.net/topic/446225-inheritance-in-boostpython/ -register_ptr_to_python is required for wrapped classes, but not for unwrapped. + register_ptr_to_python is required for wrapped classes, but not for unwrapped. -Functions don't have to be members of the class, but can also be -normal functions taking a ref to the class as first parameter. + Functions don't have to be members of the class, but can also be + normal functions taking a ref to the class as first parameter. */ namespace { @@ -261,7 +261,7 @@ struct TextPlacementsWrap: text_placements, wrapper struct TextPlacementInfoWrap: text_placement_info, wrapper { TextPlacementInfoWrap(text_placements const* parent, - double scale_factor_) + double scale_factor_) : text_placement_info(parent, scale_factor_) { @@ -339,7 +339,7 @@ void export_text_placement() ; class_("TextSymbolizer", - init<>()) + init<>()) .def(init()) .add_property("placements", &text_symbolizer::get_placement_options, @@ -357,7 +357,7 @@ void export_text_placement() class_with_converter - ("TextSymbolizerProperties") + ("TextSymbolizerProperties") .def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement) .def_readwrite_convert("horizontal_alignment", &text_symbolizer_properties::halign) .def_readwrite_convert("justify_alignment", &text_symbolizer_properties::jalign) @@ -381,15 +381,15 @@ void export_text_placement() .add_property ("format_tree", &text_symbolizer_properties::format_tree, &text_symbolizer_properties::set_format_tree); - /* from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python. - add_expressions isn't useful in python either. The result is only needed by - attribute_collector (which isn't exposed in python) and - it just calls add_expressions of the associated formatting tree. - set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */ - ; + /* from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python. + add_expressions isn't useful in python either. The result is only needed by + attribute_collector (which isn't exposed in python) and + it just calls add_expressions of the associated formatting tree. + set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */ + ; class_ - ("CharProperties") + ("CharProperties") .def(init()) //Copy constructor .def_readwrite("face_name", &char_properties::face_name) .def_readwrite("fontset", &char_properties::fontset) @@ -407,9 +407,9 @@ void export_text_placement() ; class_, - boost::noncopyable> - ("TextPlacements") + boost::shared_ptr, + boost::noncopyable> + ("TextPlacements") .def_readwrite("defaults", &text_placements::defaults) .def("get_placement_info", pure_virtual(&text_placements::get_placement_info)) /* TODO: add_expressions() */ @@ -417,10 +417,10 @@ void export_text_placement() register_ptr_to_python >(); class_, - boost::noncopyable> - ("TextPlacementInfo", - init()) + boost::shared_ptr, + boost::noncopyable> + ("TextPlacementInfo", + init()) .def("next", pure_virtual(&text_placement_info::next)) .def("get_actual_label_spacing", &text_placement_info::get_actual_label_spacing) .def("get_actual_minimum_distance", &text_placement_info::get_actual_minimum_distance) @@ -432,27 +432,27 @@ void export_text_placement() class_, - boost::noncopyable> - ("ProcessedText", no_init) + boost::shared_ptr, + boost::noncopyable> + ("ProcessedText", no_init) .def("push_back", &processed_text::push_back) .def("clear", &processed_text::clear) ; class_, - boost::noncopyable> - ("ExpressionSet") + boost::shared_ptr, + boost::noncopyable> + ("ExpressionSet") .def("insert", &insert_expression); - ; + ; //TODO: Python namespace class_, - boost::noncopyable> - ("FormattingNode") + boost::shared_ptr, + boost::noncopyable> + ("FormattingNode") .def("apply", pure_virtual(&formatting::node::apply)) .def("add_expressions", &formatting::node::add_expressions, @@ -462,10 +462,10 @@ void export_text_placement() class_, - bases, - boost::noncopyable> - ("FormattingText", init()) + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingText", init()) .def(init()) .def("apply", &formatting::text_node::apply, &TextNodeWrap::default_apply) .add_property("text", @@ -476,10 +476,10 @@ void export_text_placement() class_with_converter, - bases, - boost::noncopyable> - ("FormattingFormat") + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingFormat") .def_readwrite_convert("text_size", &formatting::format_node::text_size) .def_readwrite_convert("face_name", &formatting::format_node::face_name) .def_readwrite_convert("character_spacing", &formatting::format_node::character_spacing) @@ -499,10 +499,10 @@ void export_text_placement() register_ptr_to_python >(); class_, - bases, - boost::noncopyable> - ("FormattingList", init<>()) + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingList", init<>()) .def(init()) .def("append", &formatting::list_node::push_back) .def("apply", &formatting::list_node::apply, &ListNodeWrap::default_apply) @@ -510,15 +510,15 @@ void export_text_placement() .def("__getitem__", &ListNodeWrap::get_item) .def("__setitem__", &ListNodeWrap::set_item) .def("append", &ListNodeWrap::append) - ; + ; register_ptr_to_python >(); class_, - bases, - boost::noncopyable> - ("FormattingExpressionFormat") + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingExpressionFormat") .def_readwrite("text_size", &formatting::expression_format::text_size) .def_readwrite("face_name", &formatting::expression_format::face_name) .def_readwrite("character_spacing", &formatting::expression_format::character_spacing) diff --git a/bindings/python/mapnik_threads.hpp b/bindings/python/mapnik_threads.hpp index b1ac3f4e6..85789ff61 100644 --- a/bindings/python/mapnik_threads.hpp +++ b/bindings/python/mapnik_threads.hpp @@ -29,8 +29,8 @@ namespace mapnik { class python_thread { /* Docs: - http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock - */ + http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock + */ public: static void unblock() { @@ -38,8 +38,8 @@ public: if (state.get()) { std::cerr << "ERROR: Python threads are already unblocked. " - "Unblocking again will loose the current state and " - "might crash later. Aborting!\n"; + "Unblocking again will loose the current state and " + "might crash later. Aborting!\n"; abort(); //This is a serious error and can't be handled in any other sane way } #endif @@ -59,9 +59,9 @@ public: if (thread_support && !state.get()) { std::cerr << "ERROR: Trying to restore python thread state, " - "but no state is saved. Can't continue and also " - "can't raise an exception because the python " - "interpreter might be non-function. Aborting!\n"; + "but no state is saved. Can't continue and also " + "can't raise an exception because the python " + "interpreter might be non-function. Aborting!\n"; abort(); } #endif diff --git a/bindings/python/python_optional.hpp b/bindings/python/python_optional.hpp index da3279f2f..7707f0053 100644 --- a/bindings/python/python_optional.hpp +++ b/bindings/python/python_optional.hpp @@ -102,8 +102,8 @@ struct python_optional : public boost::noncopyable /** This class works around a bug in boost python. - See http://osdir.com/ml/python.c++/2003-11/msg00158.html - */ + See http://osdir.com/ml/python.c++/2003-11/msg00158.html +*/ template class class_with_converter : public boost::python::class_ { @@ -131,8 +131,8 @@ public: self& def_readwrite_convert(char const* name, D const& d, char const* doc=0) { this->add_property(name, - boost::python::make_getter(d, boost::python::return_value_policy()), - boost::python::make_setter(d, boost::python::default_call_policies())); + boost::python::make_getter(d, boost::python::return_value_policy()), + boost::python::make_setter(d, boost::python::default_call_policies())); return *this; } }; diff --git a/demo/python/rundemo.py b/demo/python/rundemo.py index 8e5bf765e..ce44681ce 100644 --- a/demo/python/rundemo.py +++ b/demo/python/rundemo.py @@ -138,7 +138,9 @@ qcdrain_lyr.datasource_parameters = {"type":"shape","file":'../data/qcdrainage'} qcdrain_style = mapnik.Style() qcdrain_rule = mapnik.Rule() qcdrain_rule.filter = mapnik.Expression('[HYC] = 8') -qcdrain_rule.symbols.append(mapnik.PolygonSymbolizer(mapnik.Color(153, 204, 255))) +sym = mapnik.PolygonSymbolizer(mapnik.Color(153, 204, 255)) +sym.smooth = 1.0 # very smooth +qcdrain_rule.symbols.append(sym) qcdrain_style.rules.append(qcdrain_rule) m.append_style('drainage', qcdrain_style) diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp index dadaba84c..103b4d9cd 100644 --- a/demo/viewer/mapwidget.cpp +++ b/demo/viewer/mapwidget.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "mapwidget.hpp" #include "info_dialog.hpp" @@ -487,7 +488,7 @@ void MapWidget::updateMap() } catch (mapnik::config_error & ex) { - std::cerr << ex.what() << std::endl; + std::cerr << ex.what() << std::endl; } catch (...) { diff --git a/include/mapnik/agg_helpers.hpp b/include/mapnik/agg_helpers.hpp new file mode 100644 index 000000000..aa13729d4 --- /dev/null +++ b/include/mapnik/agg_helpers.hpp @@ -0,0 +1,91 @@ +/***************************************************************************** + * + * 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_AGG_HELPERS_HPP +#define MAPNIK_AGG_HELPERS_HPP + +#include "agg_gamma_functions.h" +#include "agg_math_stroke.h" + +namespace mapnik { + +template +void set_gamma_method(T0 const& obj, T1 & ras_ptr) +{ + switch (obj.get_gamma_method()) + { + case GAMMA_POWER: + ras_ptr->gamma(agg::gamma_power(obj.get_gamma())); + break; + case GAMMA_LINEAR: + ras_ptr->gamma(agg::gamma_linear(0.0, obj.get_gamma())); + break; + case GAMMA_NONE: + ras_ptr->gamma(agg::gamma_none()); + break; + case GAMMA_THRESHOLD: + ras_ptr->gamma(agg::gamma_threshold(obj.get_gamma())); + break; + case GAMMA_MULTIPLY: + ras_ptr->gamma(agg::gamma_multiply(obj.get_gamma())); + break; + default: + ras_ptr->gamma(agg::gamma_power(obj.get_gamma())); + } +} + +template +void set_join_caps(Stroke const& stroke_, PathType & stroke) +{ + line_join_e join=stroke_.get_line_join(); + switch (join) + { + case MITER_JOIN: + stroke.generator().line_join(agg::miter_join); + break; + case MITER_REVERT_JOIN: + stroke.generator().line_join(agg::miter_join); + break; + case ROUND_JOIN: + stroke.generator().line_join(agg::round_join); + break; + default: + stroke.generator().line_join(agg::bevel_join); + } + + line_cap_e cap=stroke_.get_line_cap(); + switch (cap) + { + case BUTT_CAP: + stroke.generator().line_cap(agg::butt_cap); + break; + case SQUARE_CAP: + stroke.generator().line_cap(agg::square_cap); + break; + default: + stroke.generator().line_cap(agg::round_cap); + } +} + +} + +#endif //MAPNIK_AGG_HELPERS_HPP diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 592105ef1..d7e09049a 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -66,7 +66,7 @@ public: void start_layer_processing(layer const& lay, box2d const& query_extent); void end_layer_processing(layer const& lay); void render_marker(pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity); - + void process(point_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans); diff --git a/include/mapnik/boolean.hpp b/include/mapnik/boolean.hpp new file mode 100644 index 000000000..77332f4ae --- /dev/null +++ b/include/mapnik/boolean.hpp @@ -0,0 +1,90 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 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_BOOLEAN_HPP +#define MAPNIK_BOOLEAN_HPP +#include + +namespace mapnik +{ +/** Helper for class bool */ +class boolean { +public: + boolean(): b_(false) {} + boolean(bool b) : b_(b) {} + boolean(boolean const& b) : b_(b.b_) {} + + operator bool() const + { + return b_; + } + boolean & operator = (boolean const& other) + { + b_ = other.b_; + return * this; + } + boolean & operator = (bool other) + { + b_ = other; + return * this; + } +private: + bool b_; +}; + +/** Special stream input operator for boolean values */ +template +std::basic_istream & +operator >> ( std::basic_istream & s, boolean & b ) +{ + std::string word; + s >> word; + if ( s ) + { + if ( word == "true" || word == "yes" || word == "on" || + word == "1") + { + b = true; + } + else if ( word == "false" || word == "no" || word == "off" || + word == "0") + { + b = false; + } + else + { + s.setstate( std::ios::failbit ); + } + } + return s; +} + +template +std::basic_ostream & +operator << ( std::basic_ostream & s, boolean const& b ) +{ + s << ( b ? "true" : "false" ); + return s; +} + +} + +#endif // MAPNIK_BOOLEAN_HPP diff --git a/include/mapnik/color.hpp b/include/mapnik/color.hpp index c7f2de610..ad9806276 100644 --- a/include/mapnik/color.hpp +++ b/include/mapnik/color.hpp @@ -137,6 +137,14 @@ public: std::string to_hex_string() const; }; +template +std::basic_ostream & +operator << ( std::basic_ostream & s, mapnik::color const& c ) +{ + std::string hex_string( c.to_string() ); + s << hex_string; + return s; +} } diff --git a/include/mapnik/color_factory.hpp b/include/mapnik/color_factory.hpp index 3d92cb193..418c244a0 100644 --- a/include/mapnik/color_factory.hpp +++ b/include/mapnik/color_factory.hpp @@ -25,134 +25,26 @@ // mapnik #include -#include -#include // boost #include -#include - -// boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane) -#if BOOST_VERSION >= 104500 -#include namespace mapnik { +class color; + +template struct css_color_grammar; class MAPNIK_DECL color_factory : boost::noncopyable { public: - static void init_from_string(color & c, std::string const& css_color) - { - typedef std::string::const_iterator iterator_type; - typedef mapnik::css_color_grammar css_color_grammar; - - css_color_grammar g; - iterator_type first = css_color.begin(); - iterator_type last = css_color.end(); - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - c); - if (!result) - { - throw config_error(std::string("Failed to parse color value: ") + - "Expected a CSS color, but got '" + css_color + "'"); - } - } + static void init_from_string(color & c, std::string const& css_color); static bool parse_from_string(color & c, std::string const& css_color, - mapnik::css_color_grammar const& g) - { - std::string::const_iterator first = css_color.begin(); - std::string::const_iterator last = css_color.end(); - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - c); - return result && (first == last); - } + mapnik::css_color_grammar const& g); - static color from_string(std::string const& css_color) - { - color c; - init_from_string(c,css_color); - return c; - } + static color from_string(std::string const& css_color); }; } -#else -#include - -namespace mapnik { - -class MAPNIK_DECL color_factory : boost::noncopyable -{ -public: - - static bool parse_from_string(color & c, std::string const& css_color, - mapnik::css_color_grammar const& g) - { - std::string::const_iterator first = css_color.begin(); - std::string::const_iterator last = css_color.end(); - mapnik::css css_; - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - css_); - if (result && (first == last)) - { - c.set_red(css_.r); - c.set_green(css_.g); - c.set_blue(css_.b); - c.set_alpha(css_.a); - return true; - } - return false; - } - - static void init_from_string(color & c, std::string const& css_color) - { - typedef std::string::const_iterator iterator_type; - typedef mapnik::css_color_grammar css_color_grammar; - - css_color_grammar g; - iterator_type first = css_color.begin(); - iterator_type last = css_color.end(); - mapnik::css css_; - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - css_); - if (!result) - { - throw config_error(std::string("Failed to parse color value: ") + - "Expected a CSS color, but got '" + css_color + "'"); - } - c.set_red(css_.r); - c.set_green(css_.g); - c.set_blue(css_.b); - c.set_alpha(css_.a); - } - - static color from_string(std::string const& css_color) - { - color c; - init_from_string(c,css_color); - return c; - } -}; -} - -#endif - #endif // MAPNIK_COLOR_FACTORY_HPP diff --git a/include/mapnik/config.hpp b/include/mapnik/config.hpp index d25d74f62..88399b19c 100644 --- a/include/mapnik/config.hpp +++ b/include/mapnik/config.hpp @@ -25,8 +25,6 @@ // Windows DLL support -#define MAPNIK_SUPPORTS_GRID_RENDERER - #ifdef _WINDOWS # define MAPNIK_EXP __declspec (dllexport) # define MAPNIK_IMP __declspec (dllimport) diff --git a/include/mapnik/config_error.hpp b/include/mapnik/config_error.hpp index ad06fba58..a889bc39e 100644 --- a/include/mapnik/config_error.hpp +++ b/include/mapnik/config_error.hpp @@ -28,31 +28,28 @@ namespace mapnik { +class xml_node; class config_error : public std::exception { public: - config_error(): - what_() {} - - config_error( std::string const& what ) : - what_( what ) - { - } + config_error(std::string const& what); + config_error(std::string const& what, xml_node const& node); + config_error(std::string const& what, unsigned line_number, std::string const& filename); virtual ~config_error() throw() {} - virtual const char * what() const throw() - { - return what_.c_str(); - } - - void append_context(std::string const& ctx) const - { - what_ += " " + ctx; - } + virtual const char * what() const throw(); + void append_context(const std::string & ctx) const; + void append_context(const std::string & ctx, xml_node const& node) const; + void append_context(xml_node const& node) const; protected: mutable std::string what_; + mutable unsigned line_number_; + mutable std::string file_; + mutable std::string node_name_; + mutable std::string msg_; }; + } #endif // MAPNIK_CONFIG_ERROR_HPP diff --git a/include/mapnik/expression.hpp b/include/mapnik/expression.hpp index 4192c2a81..8862aed76 100644 --- a/include/mapnik/expression.hpp +++ b/include/mapnik/expression.hpp @@ -26,7 +26,6 @@ // mapnik #include #include -#include // stl #include @@ -35,6 +34,7 @@ namespace mapnik { typedef boost::shared_ptr expression_ptr; +template struct expression_grammar; class expression_factory { diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp index b5d478c5e..702e18a9b 100644 --- a/include/mapnik/expression_grammar.hpp +++ b/include/mapnik/expression_grammar.hpp @@ -229,7 +229,7 @@ struct expression_grammar : qi::grammar ("\\r", '\r')("\\t", '\t')("\\v", '\v')("\\\\", '\\') ("\\\'", '\'')("\\\"", '\"') ; - + #if BOOST_VERSION > 104500 quote_char %= char_('\'') | char_('"'); ustring %= omit[quote_char[_a = _1]] @@ -237,7 +237,7 @@ struct expression_grammar : qi::grammar >> lit(_a); attr %= '[' >> no_skip[+~char_(']')] >> ']'; #else - ustring %= lit('\'') + ustring %= lit('\'') >> *(unesc_char | "\\x" >> hex | (char_ - lit('\''))) >> lit('\''); attr %= '[' >> lexeme[+(char_ - ']')] >> ']'; diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index 9b636824d..8a8d75bd5 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -99,11 +99,11 @@ public: feature_impl(context_ptr const& ctx, int id) : id_(id), - ctx_(ctx), - data_(ctx_->mapping_.size()), - geom_cont_(), - raster_() - {} + ctx_(ctx), + data_(ctx_->mapping_.size()), + geom_cont_(), + raster_() + {} inline int id() const { return id_;} @@ -163,25 +163,25 @@ public: { context_type::map_type::const_iterator itr = ctx_->mapping_.find(key); if (itr != ctx_->mapping_.end()) - return get(itr->second); - else - throw std::out_of_range(std::string("Key does not exist: '") + key + "'"); + return get(itr->second); + else + throw std::out_of_range(std::string("Key does not exist: '") + key + "'"); } - + value_type const& get(std::size_t index) const { if (index < data_.size()) return data_[index]; throw std::out_of_range("Index out of range"); } - + boost::optional get_optional(std::size_t index) const { if (index < data_.size()) return boost::optional(data_[index]); return boost::optional(); } - + std::size_t size() const { return data_.size(); @@ -273,7 +273,7 @@ public: if (index < data_.size()) { ss << " " << itr->first << ":" << data_[itr->second] << std::endl; - } + } } ss << ")" << std::endl; return ss.str(); diff --git a/include/mapnik/font_engine_freetype.hpp b/include/mapnik/font_engine_freetype.hpp index ab8cad809..ffb0950e5 100644 --- a/include/mapnik/font_engine_freetype.hpp +++ b/include/mapnik/font_engine_freetype.hpp @@ -153,7 +153,7 @@ class MAPNIK_DECL font_face_set : private boost::noncopyable public: font_face_set(void) : faces_(), - dimension_cache_() {} + dimension_cache_() {} void add(face_ptr face) { diff --git a/include/mapnik/formatting/base.hpp b/include/mapnik/formatting/base.hpp index 47efe70de..7c4f0a144 100644 --- a/include/mapnik/formatting/base.hpp +++ b/include/mapnik/formatting/base.hpp @@ -36,6 +36,7 @@ namespace mapnik { typedef std::set expression_set; class processed_text; +class xml_node; struct char_properties; namespace formatting { @@ -48,7 +49,7 @@ class node public: virtual ~node() {} virtual void to_xml(boost::property_tree::ptree &xml) const; - static node_ptr from_xml(boost::property_tree::ptree const& xml); + static node_ptr from_xml(xml_node const& xml); virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const = 0; virtual void add_expressions(expression_set &output) const; }; diff --git a/include/mapnik/formatting/expression.hpp b/include/mapnik/formatting/expression.hpp index e85b7d973..d3db09691 100644 --- a/include/mapnik/formatting/expression.hpp +++ b/include/mapnik/formatting/expression.hpp @@ -31,7 +31,7 @@ namespace formatting { class expression_format: public node { public: void to_xml(boost::property_tree::ptree &xml) const; - static node_ptr from_xml(boost::property_tree::ptree const& xml); + static node_ptr from_xml(xml_node const& xml); virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const; virtual void add_expressions(expression_set &output) const; @@ -51,7 +51,7 @@ public: private: node_ptr child_; - static expression_ptr get_expression(boost::property_tree::ptree const& xml, std::string name); + static expression_ptr get_expression(xml_node const& xml, std::string name); }; } //ns formatting } //ns mapnik diff --git a/include/mapnik/formatting/format.hpp b/include/mapnik/formatting/format.hpp index 53e09a47f..22bef2d8e 100644 --- a/include/mapnik/formatting/format.hpp +++ b/include/mapnik/formatting/format.hpp @@ -31,7 +31,7 @@ namespace formatting { class format_node: public node { public: void to_xml(boost::property_tree::ptree &xml) const; - static node_ptr from_xml(boost::property_tree::ptree const& xml); + static node_ptr from_xml(xml_node const& xml); virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const; virtual void add_expressions(expression_set &output) const; diff --git a/include/mapnik/formatting/registry.hpp b/include/mapnik/formatting/registry.hpp index 9c2c9df22..1c44e68dd 100644 --- a/include/mapnik/formatting/registry.hpp +++ b/include/mapnik/formatting/registry.hpp @@ -38,16 +38,16 @@ namespace mapnik namespace formatting { -typedef node_ptr (*from_xml_function_ptr)(boost::property_tree::ptree const& xml); +typedef node_ptr (*from_xml_function_ptr)(xml_node const& xml); class registry : public singleton, - private boost::noncopyable + private boost::noncopyable { public: registry(); ~registry() {} void register_name(std::string name, from_xml_function_ptr ptr, bool overwrite=false); - node_ptr from_xml(std::string name, boost::property_tree::ptree const& xml); + node_ptr from_xml(xml_node const& xml); private: std::map map_; }; diff --git a/include/mapnik/formatting/text.hpp b/include/mapnik/formatting/text.hpp index c216b4fc2..8fd1551d8 100644 --- a/include/mapnik/formatting/text.hpp +++ b/include/mapnik/formatting/text.hpp @@ -31,7 +31,7 @@ public: text_node(expression_ptr text): node(), text_(text) {} text_node(std::string text): node(), text_(parse_expression(text)) {} void to_xml(boost::property_tree::ptree &xml) const; - static node_ptr from_xml(boost::property_tree::ptree const& xml); + static node_ptr from_xml(xml_node const& xml); virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const; virtual void add_expressions(expression_set &output) const; diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index 16eb3c0cc..691bf5404 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -390,7 +390,7 @@ public: } return false; } - + }; typedef geometry geometry_type; diff --git a/include/mapnik/hextree.hpp b/include/mapnik/hextree.hpp index 36ab40857..50102a812 100644 --- a/include/mapnik/hextree.hpp +++ b/include/mapnik/hextree.hpp @@ -160,7 +160,7 @@ public: ~hextree() {} - + void setMaxColors(unsigned max_colors) { max_colors_ = max_colors; @@ -335,7 +335,7 @@ public: sorted_pal_.reserve(colors_); create_palette_rek(sorted_pal_, root_.get()); - + // sort palette for binary searching in quantization #if BOOST_VERSION >= 104600 boost::sort(sorted_pal_, rgba::mean_sort_cmp()); diff --git a/include/mapnik/internal/dump_xml.hpp b/include/mapnik/internal/dump_xml.hpp index 022591f7a..7bdf78f66 100644 --- a/include/mapnik/internal/dump_xml.hpp +++ b/include/mapnik/internal/dump_xml.hpp @@ -1,26 +1,34 @@ #ifndef DUMP_XML_HPP #define DUMP_XML_HPP -#include +#include /* Debug dump ptree XML representation. -*/ -void dump_xml(boost::property_tree::ptree const& xml, unsigned level=0) + */ +void dump_xml(xml_node const& xml, unsigned level=0) { std::string indent; - int i; + unsigned i; for (i=0; ifirst << ", " << aitr->second.value << ", " << aitr->second.processed << ")"; + } + std::cerr << "]" << "\n"; + if (xml.is_text()) std::cerr << indent << "text: '" << xml.text() << "'\n"; + xml_node::const_iterator itr = xml.begin(); + xml_node::const_iterator end = xml.end(); for (; itr!=end; itr++) { - std::cout << indent <<"[" << itr->first << "]" << "\n"; - dump_xml(itr->second, level+1); - std::cout << indent << "[/" << itr->first << "]" << "\n"; + dump_xml(*itr, level+1); } + std::cerr << indent << "[/" << xml.name() << "]" << "\n"; } diff --git a/include/mapnik/metawriter_factory.hpp b/include/mapnik/metawriter_factory.hpp index d5b8911fd..1af7ff5d7 100644 --- a/include/mapnik/metawriter_factory.hpp +++ b/include/mapnik/metawriter_factory.hpp @@ -30,6 +30,7 @@ #include namespace mapnik { +class xml_node; /** * Creates a metawriter with the properties specified in the property @@ -37,7 +38,7 @@ namespace mapnik { * metawriters, but should provide an easy point to make them a * proper factory method if this is wanted in the future. */ -metawriter_ptr metawriter_create(const boost::property_tree::ptree &pt); +metawriter_ptr metawriter_create(xml_node const& pt); /** * Writes properties into the given property tree representing the diff --git a/include/mapnik/palette.hpp b/include/mapnik/palette.hpp index de58bbe10..a0db170bf 100644 --- a/include/mapnik/palette.hpp +++ b/include/mapnik/palette.hpp @@ -26,7 +26,6 @@ // mapnik #include #include -#include // boost #include diff --git a/include/mapnik/placement_finder.hpp b/include/mapnik/placement_finder.hpp index 662078238..1ee636349 100644 --- a/include/mapnik/placement_finder.hpp +++ b/include/mapnik/placement_finder.hpp @@ -124,16 +124,16 @@ private: text_symbolizer_properties const& p; text_placement_info const& pi; /** Length of the longest line after linebreaks. - * Before find_line_breaks() this is the total length of the string. - */ + * Before find_line_breaks() this is the total length of the string. + */ double string_width_; /** Height of the string after linebreaks. - * Before find_line_breaks() this is the total length of the string. - */ + * Before find_line_breaks() this is the total length of the string. + */ double string_height_; /** Height of the tallest font in the first line not including line spacing. - * Used to determine the correct offset for the first line. - */ + * Used to determine the correct offset for the first line. + */ double first_line_space_; vertical_alignment_e valign_; horizontal_alignment_e halign_; diff --git a/include/mapnik/polygon_symbolizer.hpp b/include/mapnik/polygon_symbolizer.hpp index a4f8706d5..e7a2a85c7 100644 --- a/include/mapnik/polygon_symbolizer.hpp +++ b/include/mapnik/polygon_symbolizer.hpp @@ -35,7 +35,7 @@ namespace mapnik struct MAPNIK_DECL polygon_symbolizer : public symbolizer_base { polygon_symbolizer(); - polygon_symbolizer(color const& fill); + explicit polygon_symbolizer(color const& fill); color const& get_fill() const; void set_fill(color const& fill); void set_opacity(double opacity); @@ -44,12 +44,14 @@ struct MAPNIK_DECL polygon_symbolizer : public symbolizer_base double get_gamma() const; void set_gamma_method(gamma_method_e gamma_method); gamma_method_e get_gamma_method() const; - + void set_smooth(double smooth); + double smooth() const; private: color fill_; double opacity_; double gamma_; gamma_method_e gamma_method_; + double smooth_; }; } diff --git a/include/mapnik/ptree_helpers.hpp b/include/mapnik/ptree_helpers.hpp index 0c3e8bf63..64167b590 100644 --- a/include/mapnik/ptree_helpers.hpp +++ b/include/mapnik/ptree_helpers.hpp @@ -23,450 +23,17 @@ #ifndef MAPNIK_PTREE_HELPERS_HPP #define MAPNIK_PTREE_HELPERS_HPP -// mapnik -#include -#include -#include -#include // boost #include -#include -#include - -// stl -#include -#include namespace mapnik { -template -inline boost::optional fast_cast(std::string const& value); - -template -T get(boost::property_tree::ptree const& node, std::string const& name, bool is_attribute, - T const& default_value); -template -T get(boost::property_tree::ptree const& node, std::string const& name, bool is_attribute); -template -T get_value(boost::property_tree::ptree const& node, std::string const& name); -template -boost::optional get_optional(boost::property_tree::ptree const& node, std::string const& name, - bool is_attribute); - -template -boost::optional get_opt_attr( boost::property_tree::ptree const& node, - std::string const& name) -{ - return get_optional( node, name, true); -} - -template -boost::optional get_opt_child( boost::property_tree::ptree const& node, - std::string const& name) -{ - return get_optional( node, name, false); -} - -template -T get_attr( boost::property_tree::ptree const& node, std::string const& name, - T const& default_value ) -{ - return get( node, name, true, default_value); -} - -template -T get_attr( boost::property_tree::ptree const& node, std::string const& name ) -{ - return get( node, name, true ); -} - - -template -std::basic_ostream & -operator << ( std::basic_ostream & s, mapnik::color const& c ) -{ - std::string hex_string( c.to_string() ); - s << hex_string; - return s; -} - -/** Helper for class bool */ -class boolean { -public: - boolean() : b_(false) {} - boolean(bool b) : b_(b) {} - boolean(boolean const& b) : b_(b.b_) {} - - operator bool() const - { - return b_; - } - boolean & operator = (boolean const& other) - { - b_ = other.b_; - return * this; - } - boolean & operator = (bool other) - { - b_ = other; - return * this; - } -private: - bool b_; -}; - -/** Special stream input operator for boolean values */ -template -std::basic_istream & -operator >> ( std::basic_istream & s, boolean & b ) -{ - std::string word; - s >> word; - if ( s ) - { - if ( word == "true" || word == "yes" || word == "on" || - word == "1") - { - b = true; - } - else if ( word == "false" || word == "no" || word == "off" || - word == "0") - { - b = false; - } - else - { - s.setstate( std::ios::failbit ); - } - } - return s; -} - -template -std::basic_ostream & -operator << ( std::basic_ostream & s, boolean const& b ) -{ - s << ( b ? "true" : "false" ); - return s; -} - template void set_attr(boost::property_tree::ptree & pt, std::string const& name, T const& v) { pt.put("." + name, v); } - -class boolean; - -template -struct name_trait -{ - static std::string name() - { - return ""; - } - // missing name_trait for type ... - // if you get here you are probably using a new type - // in the XML file. Just add a name trait for the new - // type below. - BOOST_STATIC_ASSERT( sizeof(T) == 0 ); -}; - -#define DEFINE_NAME_TRAIT( type, type_name ) \ - template <> \ - struct name_trait \ - { \ - static std::string name() { return std::string("type ") + type_name; } \ - }; - - -DEFINE_NAME_TRAIT( double, "double") -DEFINE_NAME_TRAIT( float, "float") -DEFINE_NAME_TRAIT( unsigned, "unsigned") -DEFINE_NAME_TRAIT( boolean, "boolean") -DEFINE_NAME_TRAIT( int, "integer" ) -DEFINE_NAME_TRAIT( std::string, "string" ) -DEFINE_NAME_TRAIT( color, "color" ) - -template -struct name_trait< mapnik::enumeration > -{ - typedef enumeration Enum; - - static std::string name() - { - std::string value_list("one of ["); - for (unsigned i = 0; i < Enum::MAX; ++i) - { - value_list += Enum::get_string( i ); - if ( i + 1 < Enum::MAX ) value_list += ", "; - } - value_list += "]"; - - return value_list; - } -}; - -template -inline boost::optional fast_cast(std::string const& value) -{ - try - { - return boost::lexical_cast( value ); - } - catch (boost::bad_lexical_cast const& ex) - { - return boost::optional(); - } - -} - -template <> -inline boost::optional fast_cast(std::string const& value) -{ - int result; - if (mapnik::conversions::string2int(value,result)) - return boost::optional(result); - return boost::optional(); -} - -template <> -inline boost::optional fast_cast(std::string const& value) -{ - double result; - if (mapnik::conversions::string2double(value,result)) - return boost::optional(result); - return boost::optional(); -} - -template <> -inline boost::optional fast_cast(std::string const& value) -{ - float result; - if (mapnik::conversions::string2float(value,result)) - return boost::optional(result); - return boost::optional(); -} - -template -T get(boost::property_tree::ptree const& node, - std::string const& name, - bool is_attribute, - T const& default_value) -{ - boost::optional str; - if (is_attribute) - { - str = node.get_optional( std::string(".") + name ); - } - else - { - str = node.get_optional(name + "."); - } - - if ( str ) - { - boost::optional result = fast_cast(*str); - if (result) - { - return *result; - } - else - { - throw config_error(std::string("Failed to parse ") + - (is_attribute ? "attribute" : "child node") + " '" + - name + "'. Expected " + name_trait::name() + - " but got '" + *str + "'"); - } - } - else - { - return default_value; - } -} - -template <> -inline color get(boost::property_tree::ptree const& node, - std::string const& name, - bool is_attribute, - color const& default_value) -{ - boost::optional str; - if (is_attribute) - { - str = node.get_optional( std::string(".") + name ); - } - else - { - str = node.get_optional(name + "."); - } - - if ( str ) - { - try - { - return mapnik::color_factory::from_string((*str).c_str()); - } - catch (...) - { - throw config_error(std::string("Failed to parse ") + - (is_attribute ? "attribute" : "child node") + " '" + - name + "'. Expected " + name_trait::name() + - " but got '" + *str + "'"); - } - } - else - { - return default_value; - } -} - -template -T get(boost::property_tree::ptree const& node, std::string const& name, bool is_attribute) -{ - boost::optional str; - if (is_attribute) - { - str = node.get_optional( std::string(".") + name); - } - else - { - str = node.get_optional(name + "."); - } - - if ( ! str ) - { - throw config_error(std::string("Required ") + - (is_attribute ? "attribute " : "child node ") + - "'" + name + "' is missing"); - } - boost::optional result = fast_cast(*str); - if (result) - { - return *result; - } - else - { - throw config_error(std::string("Failed to parse ") + - (is_attribute ? "attribute" : "child node") + " '" + - name + "'. Expected " + name_trait::name() + - " but got '" + *str + "'"); - } -} - -template -T get_value(boost::property_tree::ptree const& node, std::string const& name) -{ - try - { - /* NOTE: get_child works as long as there is only one child with that name. - If this function is used this used this condition must always be satisfied. - */ - return node.get_child("").get_value(); - } - catch (boost::property_tree::ptree_bad_path) - { - /* If the XML parser did not find any non-empty data element the is no - node. But we don't want to fail here but simply return a - default constructed value of the requested type. - */ - return T(); - } - catch (...) - { - throw config_error(std::string("Failed to parse ") + - name + ". Expected " + name_trait::name() + - " but got '" + node.data() + "'"); - } -} - -template -boost::optional get_optional(boost::property_tree::ptree const& node, - std::string const& name, - bool is_attribute) -{ - boost::optional str; - if (is_attribute) - { - str = node.get_optional( std::string(".") + name); - } - else - { - str = node.get_optional(name + "."); - } - - boost::optional result; - if ( str ) - { - result = fast_cast(*str); - if (!result) - { - throw config_error(std::string("Failed to parse ") + - (is_attribute ? "attribute" : "child node") + " '" + - name + "'. Expected " + name_trait::name() + - " but got '" + *str + "'"); - } - } - - return result; -} - -template <> -inline boost::optional get_optional(boost::property_tree::ptree const& node, - std::string const& name, - bool is_attribute) -{ - if (is_attribute) - { - return node.get_optional( std::string(".") + name); - } - else - { - return node.get_optional(name + "."); - } -} - -template <> -inline boost::optional get_optional(boost::property_tree::ptree const& node, - std::string const& name, - bool is_attribute) -{ - boost::optional str; - if (is_attribute) - { - str = node.get_optional( std::string(".") + name); - } - else - { - str = node.get_optional(name + "."); - } - - boost::optional result; - if ( str ) - { - try - { - result = mapnik::color_factory::from_string((*str).c_str()); - } - catch (...) - { - throw config_error(std::string("Failed to parse ") + - (is_attribute ? "attribute" : "child node") + " '" + - name + "'. Expected " + name_trait::name() + - " but got '" + *str + "'"); - } - } - - return result; -} - -static inline bool has_child(boost::property_tree::ptree const& node, std::string const& name) -{ - boost::optional str = node.get_optional(name); - return str; -} - } // end of namespace mapnik #endif // MAPNIK_PTREE_HELPERS_HPP diff --git a/include/mapnik/raster_colorizer.hpp b/include/mapnik/raster_colorizer.hpp index 74fcf4853..8903d60f2 100644 --- a/include/mapnik/raster_colorizer.hpp +++ b/include/mapnik/raster_colorizer.hpp @@ -39,7 +39,6 @@ // mapnik #include -#include #include #include #include diff --git a/include/mapnik/symbolizer_helpers.hpp b/include/mapnik/symbolizer_helpers.hpp index 92c5b1b2f..58063b6ab 100644 --- a/include/mapnik/symbolizer_helpers.hpp +++ b/include/mapnik/symbolizer_helpers.hpp @@ -65,11 +65,11 @@ public: detector_(detector), writer_(sym.get_metawriter()), dims_(0, 0, width, height), + query_extent_(query_extent), text_(font_manager, scale_factor), angle_(0.0), placement_valid_(false), points_on_line_(false), - query_extent_(query_extent), finder_() { initialize_geometries(); diff --git a/include/mapnik/text_placements/list.hpp b/include/mapnik/text_placements/list.hpp index e6e0adaea..923df0c9d 100644 --- a/include/mapnik/text_placements/list.hpp +++ b/include/mapnik/text_placements/list.hpp @@ -38,7 +38,7 @@ public: text_symbolizer_properties & add(); text_symbolizer_properties & get(unsigned i); unsigned size() const; - static text_placements_ptr from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets); + static text_placements_ptr from_xml(xml_node const &xml, fontset_map const & fontsets); private: std::vector list_; friend class text_placement_info_list; diff --git a/include/mapnik/text_placements/registry.hpp b/include/mapnik/text_placements/registry.hpp index c171a5089..f3bd123bf 100644 --- a/include/mapnik/text_placements/registry.hpp +++ b/include/mapnik/text_placements/registry.hpp @@ -39,17 +39,17 @@ namespace placements { typedef text_placements_ptr (*from_xml_function_ptr)( - boost::property_tree::ptree const& xml, fontset_map const & fontsets); + xml_node const& xml, fontset_map const & fontsets); class registry : public singleton, - private boost::noncopyable + private boost::noncopyable { public: registry(); ~registry() {} void register_name(std::string name, from_xml_function_ptr ptr, bool overwrite=false); text_placements_ptr from_xml(std::string name, - boost::property_tree::ptree const& xml, + xml_node const& xml, fontset_map const & fontsets); private: std::map map_; diff --git a/include/mapnik/text_placements/simple.hpp b/include/mapnik/text_placements/simple.hpp index 4173ab87a..59c57d87e 100644 --- a/include/mapnik/text_placements/simple.hpp +++ b/include/mapnik/text_placements/simple.hpp @@ -52,7 +52,7 @@ public: text_placement_info_ptr get_placement_info(double scale_factor) const; void set_positions(std::string positions); std::string get_positions(); - static text_placements_ptr from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets); + static text_placements_ptr from_xml(xml_node const &xml, fontset_map const & fontsets); private: std::string positions_; std::vector direction_; diff --git a/include/mapnik/text_properties.hpp b/include/mapnik/text_properties.hpp index dbf21f8d7..9f12b3663 100644 --- a/include/mapnik/text_properties.hpp +++ b/include/mapnik/text_properties.hpp @@ -54,7 +54,7 @@ struct char_properties { char_properties(); /** Construct object from XML. */ - void from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets); + void from_xml(xml_node const &sym, fontset_map const & fontsets); /** Write object to XML ptree. */ void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, char_properties const& dfl=char_properties()) const; std::string face_name; @@ -124,7 +124,7 @@ struct text_symbolizer_properties { text_symbolizer_properties(); /** Load all values from XML ptree. */ - void from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets); + void from_xml(xml_node const &sym, fontset_map const & fontsets); /** Save all values to XML ptree (but does not create a new parent node!). */ void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, text_symbolizer_properties const &dfl=text_symbolizer_properties()) const; diff --git a/include/mapnik/util/conversions.hpp b/include/mapnik/util/conversions.hpp index 1b38dee3d..c4d4a321b 100644 --- a/include/mapnik/util/conversions.hpp +++ b/include/mapnik/util/conversions.hpp @@ -30,16 +30,16 @@ namespace mapnik { namespace conversions { -bool string2int(const char * value, int & result); -bool string2int(std::string const& value, int & result); - -bool string2double(std::string const& value, double & result); -bool string2double(const char * value, double & result); - -bool string2float(std::string const& value, float & result); -bool string2float(const char * value, float & result); + bool string2int(const char * value, int & result); + bool string2int(std::string const& value, int & result); -} + bool string2double(std::string const& value, double & result); + bool string2double(const char * value, double & result); + + bool string2float(std::string const& value, float & result); + bool string2float(const char * value, float & result); + + } } #endif // MAPNIK_CONVERSIONS_UTIL_HPP diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index d657d974c..a3cef23b4 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -26,7 +26,6 @@ // mapnik #include #include -#include // boost #include diff --git a/include/mapnik/vertex_vector.hpp b/include/mapnik/vertex_vector.hpp index e326aa284..85bcd8857 100644 --- a/include/mapnik/vertex_vector.hpp +++ b/include/mapnik/vertex_vector.hpp @@ -55,16 +55,16 @@ public: // required for iterators support typedef boost::tuple value_type; typedef std::size_t size_type; - + private: unsigned num_blocks_; unsigned max_blocks_; coord_type** vertices_; unsigned char** commands_; size_type pos_; - + public: - + vertex_vector() : num_blocks_(0), max_blocks_(0), @@ -114,7 +114,7 @@ public: *y = (*vertex); return commands_[block] [pos & block_mask]; } - + private: void allocate_block(unsigned block) { diff --git a/include/mapnik/libxml2_loader.hpp b/include/mapnik/xml_loader.hpp similarity index 82% rename from include/mapnik/libxml2_loader.hpp rename to include/mapnik/xml_loader.hpp index 105a5f8b2..b102b61eb 100644 --- a/include/mapnik/libxml2_loader.hpp +++ b/include/mapnik/xml_loader.hpp @@ -23,16 +23,14 @@ #ifndef MAPNIK_LIBXML2_LOADER_HPP #define MAPNIK_LIBXML2_LOADER_HPP -// boost -#include - // stl #include namespace mapnik { -void read_xml2( std::string const & filename, boost::property_tree::ptree & pt); -void read_xml2_string( std::string const & str, boost::property_tree::ptree & pt, std::string const & base_path=""); +class xml_node; +void read_xml(std::string const & filename, xml_node &node); +void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path=""); } #endif // MAPNIK_LIBXML2_LOADER_HPP diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp new file mode 100644 index 000000000..f0db516e1 --- /dev/null +++ b/include/mapnik/xml_node.hpp @@ -0,0 +1,137 @@ +/***************************************************************************** + * + * 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_XML_NODE_H +#define MAPNIK_XML_NODE_H + +//mapnik +#include + + +//boost +#include + +//stl +#include +#include +#include +#include + +namespace mapnik +{ +class xml_tree; + +class xml_attribute +{ +public: + xml_attribute(std::string const& value); + std::string value; + mutable bool processed; +}; + +class node_not_found: public std::exception +{ +public: + node_not_found(std::string node_name); + virtual const char* what() const throw(); + ~node_not_found() throw (); +private: + std::string node_name_; +}; + +class attribute_not_found: public std::exception +{ +public: + attribute_not_found(std::string const& node_name, std::string const& attribute_name); + virtual const char* what() const throw(); + ~attribute_not_found() throw (); +private: + std::string node_name_; + std::string attribute_name_; +}; + +class more_than_one_child: public std::exception +{ +public: + more_than_one_child(std::string const& node_name); + virtual const char* what() const throw(); + ~more_than_one_child() throw (); +private: + std::string node_name_; +}; + +class xml_node +{ +public: + typedef std::list::const_iterator const_iterator; + typedef std::map attribute_map; + xml_node(xml_tree &tree, std::string name, unsigned line=0, bool text_node = false); + + std::string const& name() const; + std::string const& text() const; + std::string const& filename() const; + bool is_text() const; + bool is(std::string const& name) const; + + xml_node &add_child(std::string const& name, unsigned line=0, bool text_node = false); + void add_attribute(std::string const& name, std::string const& value); + attribute_map const& get_attributes() const; + + bool processed() const; + void set_processed(bool processed) const; + + unsigned line() const; + + const_iterator begin() const; + const_iterator end() const; + + xml_node & get_child(std::string const& name); + xml_node const& get_child(std::string const& name) const; + xml_node const* get_opt_child(std::string const& name) const; + bool has_child(std::string const& name) const; + + template + boost::optional get_opt_attr(std::string const& name) const; + + template + T get_attr(std::string const& name, T const& default_value) const; + template + T get_attr(std::string const& name) const; + + std::string get_text() const; + + template + T get_value() const; +private: + xml_tree &tree_; + std::string name_; + std::list children_; + attribute_map attributes_; + bool text_node_; + unsigned line_; + mutable bool processed_; + static std::string xml_text; +}; + +} //ns mapnik + +#endif // MAPNIK_XML_NODE_H diff --git a/include/mapnik/xml_tree.hpp b/include/mapnik/xml_tree.hpp new file mode 100644 index 000000000..27893d262 --- /dev/null +++ b/include/mapnik/xml_tree.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_XML_TREE_H +#define MAPNIK_XML_TREE_H +//mapnik +#include +#include + +// boost +#include + +#if BOOST_VERSION >= 104500 +#include +#else +#include +#endif + +//stl +#include + + +namespace mapnik +{ +class xml_tree +{ +public: + xml_tree(std::string const& encoding="utf8"); + void set_filename(std::string fn); + std::string const& filename() const; + xml_node &root(); +private: + xml_node node_; + std::string file_; + transcoder tr_; +public: + mapnik::css_color_grammar color_grammar; + mapnik::expression_grammar expr_grammar; +}; + +} //ns mapnik + +#endif // MAPNIK_XML_TREE_H diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index 2fca63198..3bed41211 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -6,6 +6,7 @@ #include #include #include +#include // mapnik #include @@ -14,7 +15,7 @@ #include #include #include -#include // mapnik::boolean +#include // stl #include diff --git a/plugins/input/gdal/gdal_datasource.cpp b/plugins/input/gdal/gdal_datasource.cpp index 6d540f61a..e3155675d 100644 --- a/plugins/input/gdal/gdal_datasource.cpp +++ b/plugins/input/gdal/gdal_datasource.cpp @@ -25,7 +25,7 @@ #include "gdal_featureset.hpp" // mapnik -#include +#include #include #include diff --git a/plugins/input/geos/geos_datasource.cpp b/plugins/input/geos/geos_datasource.cpp index 26147fe15..6dae1ec3c 100644 --- a/plugins/input/geos/geos_datasource.cpp +++ b/plugins/input/geos/geos_datasource.cpp @@ -30,7 +30,7 @@ #include // mapnik -#include +#include #include // boost diff --git a/plugins/input/kismet/kismet_datasource.cpp b/plugins/input/kismet/kismet_datasource.cpp index 899690a3a..94fcb906e 100644 --- a/plugins/input/kismet/kismet_datasource.cpp +++ b/plugins/input/kismet/kismet_datasource.cpp @@ -33,7 +33,7 @@ #include // mapnik -#include +#include // boost #include diff --git a/plugins/input/occi/occi_datasource.cpp b/plugins/input/occi/occi_datasource.cpp index 0354f8f39..dc9a73fcb 100644 --- a/plugins/input/occi/occi_datasource.cpp +++ b/plugins/input/occi/occi_datasource.cpp @@ -25,7 +25,7 @@ #include "occi_featureset.hpp" // mapnik -#include +#include #include // boost diff --git a/plugins/input/occi/occi_featureset.cpp b/plugins/input/occi/occi_featureset.cpp index 1cf17a3aa..3a09200f3 100644 --- a/plugins/input/occi/occi_featureset.cpp +++ b/plugins/input/occi/occi_featureset.cpp @@ -373,7 +373,7 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature, if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE) { geometry_type* geom = new geometry_type(geom_type); - + for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3) { int next_offset = elem_info[i]; diff --git a/plugins/input/ogr/ogr_datasource.cpp b/plugins/input/ogr/ogr_datasource.cpp index 0028ca3c3..9a3f4900a 100644 --- a/plugins/input/ogr/ogr_datasource.cpp +++ b/plugins/input/ogr/ogr_datasource.cpp @@ -33,7 +33,7 @@ #include // mapnik -#include +#include #include // boost diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index d1e45c0a6..f25b2b05f 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -26,7 +26,7 @@ // mapnik #include -#include +#include #include #include @@ -664,22 +664,22 @@ box2d postgis_datasource::envelope() const shared_ptr rs = conn->executeQuery(s.str()); if (rs->next() && !rs->isNull(0)) { - double lox; - double loy; - double hix; - double hiy; - if (mapnik::conversions::string2double(rs->getValue(0),lox) && - mapnik::conversions::string2double(rs->getValue(1),loy) && - mapnik::conversions::string2double(rs->getValue(2),hix) && - mapnik::conversions::string2double(rs->getValue(3),hiy)) - { - extent_.init(lox,loy,hix,hiy); - extent_initialized_ = true; - } - else - { - std::clog << boost::format("Postgis Plugin: warning: could not determine extent from query: %s\n") % s.str() << std::endl; - } + double lox; + double loy; + double hix; + double hiy; + if (mapnik::conversions::string2double(rs->getValue(0),lox) && + mapnik::conversions::string2double(rs->getValue(1),loy) && + mapnik::conversions::string2double(rs->getValue(2),hix) && + mapnik::conversions::string2double(rs->getValue(3),hiy)) + { + extent_.init(lox,loy,hix,hiy); + extent_initialized_ = true; + } + else + { + std::clog << boost::format("Postgis Plugin: warning: could not determine extent from query: %s\n") % s.str() << std::endl; + } } rs->close(); } diff --git a/plugins/input/rasterlite/rasterlite_datasource.cpp b/plugins/input/rasterlite/rasterlite_datasource.cpp index 043b84b98..1f51974f6 100644 --- a/plugins/input/rasterlite/rasterlite_datasource.cpp +++ b/plugins/input/rasterlite/rasterlite_datasource.cpp @@ -29,7 +29,7 @@ #include // mapnik -#include +#include #include using mapnik::datasource; diff --git a/plugins/input/shape/dbfile.cpp b/plugins/input/shape/dbfile.cpp index 9e09a14f3..4af77c654 100644 --- a/plugins/input/shape/dbfile.cpp +++ b/plugins/input/shape/dbfile.cpp @@ -127,7 +127,7 @@ void dbf_file::add_attribute(int col, mapnik::transcoder const& tr, Feature & f) if (col>=0 && col::shape_index_featureset(filterT const& filter, std::string const& shape_name, int row_limit) : filter_(filter), + ctx_(boost::make_shared()), shape_(shape), tr_(new transcoder(encoding)), row_limit_(row_limit), count_(0) { - ctx_ = boost::make_shared(); shape_.shp().skip(100); setup_attributes(ctx_, attribute_names, shape_name, shape_,attr_ids_); - + boost::shared_ptr index = shape_.index(); if (index) { diff --git a/plugins/input/shape/shape_io.cpp b/plugins/input/shape/shape_io.cpp index 4ace58937..81677677b 100644 --- a/plugins/input/shape/shape_io.cpp +++ b/plugins/input/shape/shape_io.cpp @@ -103,12 +103,12 @@ void shape_io::read_polyline(mapnik::geometry_container & geom) { shape_file::record_type record(reclength_ * 2 - 36); shp_.read_record(record); - + int num_parts = record.read_ndr_integer(); int num_points = record.read_ndr_integer(); if (num_parts == 1) { - geometry_type* line = new geometry_type(mapnik::LineString); + geometry_type* line = new geometry_type(mapnik::LineString); record.skip(4); double x = record.read_double(); double y = record.read_double(); @@ -132,7 +132,7 @@ void shape_io::read_polyline(mapnik::geometry_container & geom) int start, end; for (int k = 0; k < num_parts; ++k) { - geometry_type* line = new geometry_type(mapnik::LineString); + geometry_type* line = new geometry_type(mapnik::LineString); start = parts[k]; if (k == num_parts - 1) { @@ -179,11 +179,11 @@ void shape_io::read_polygon(mapnik::geometry_container & geom) { shape_file::record_type record(reclength_ * 2 - 36); shp_.read_record(record); - + int num_parts = record.read_ndr_integer(); int num_points = record.read_ndr_integer(); std::vector parts(num_parts); - + for (int i = 0; i < num_parts; ++i) { parts[i] = record.read_ndr_integer(); diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index d2fce8583..22f9246ce 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -26,7 +26,7 @@ #include "sqlite_utils.hpp" // mapnik -#include +#include #include #include #include diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index cbb703639..9b4279114 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index e45226bf3..cc00d2f2e 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -23,6 +23,7 @@ // mapnik #include +#include #include #include @@ -63,7 +64,7 @@ void agg_renderer::process(line_symbolizer const& sym, agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); agg::pixfmt_rgba32_plain pixf(buf); - + box2d ext = query_extent_ * 1.1; if (sym.get_rasterizer() == RASTERIZER_FAST) { @@ -71,7 +72,6 @@ void agg_renderer::process(line_symbolizer const& sym, typedef agg::rasterizer_outline_aa rasterizer_type; agg::line_profile_aa profile; - //agg::line_profile_aa profile(stroke_.get_width() * scale_factor_, agg::gamma_none()); profile.width(stroke_.get_width() * scale_factor_); ren_base base_ren(pixf); renderer_type ren(base_ren, profile); @@ -102,26 +102,10 @@ void agg_renderer::process(line_symbolizer const& sym, ren_base renb(pixf); renderer ren(renb); ras_ptr->reset(); - switch (stroke_.get_gamma_method()) - { - case GAMMA_POWER: - ras_ptr->gamma(agg::gamma_power(stroke_.get_gamma())); - break; - case GAMMA_LINEAR: - ras_ptr->gamma(agg::gamma_linear(0.0, stroke_.get_gamma())); - break; - case GAMMA_NONE: - ras_ptr->gamma(agg::gamma_none()); - break; - case GAMMA_THRESHOLD: - ras_ptr->gamma(agg::gamma_threshold(stroke_.get_gamma())); - break; - case GAMMA_MULTIPLY: - ras_ptr->gamma(agg::gamma_multiply(stroke_.get_gamma())); - break; - default: - ras_ptr->gamma(agg::gamma_power(stroke_.get_gamma())); - } + + set_gamma_method(stroke_, ras_ptr); + + //metawriter_with_properties writer = sym.get_metawriter(); for (unsigned i=0;inum_geometries();++i) @@ -129,12 +113,12 @@ void agg_renderer::process(line_symbolizer const& sym, geometry_type & geom = feature->get_geometry(i); if (geom.num_points() > 1) { - clipped_geometry_type clipped(geom); - clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy()); - path_type path(t_,clipped,prj_trans); - if (stroke_.has_dash()) { + clipped_geometry_type clipped(geom); + clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy()); + path_type path(t_,clipped,prj_trans); + agg::conv_dash dash(path); dash_array const& d = stroke_.get_dash_array(); dash_array::const_iterator itr = d.begin(); @@ -144,27 +128,8 @@ void agg_renderer::process(line_symbolizer const& sym, dash.add_dash(itr->first * scale_factor_, itr->second * scale_factor_); } - agg::conv_stroke > stroke(dash); - - line_join_e join=stroke_.get_line_join(); - if ( join == MITER_JOIN) - stroke.generator().line_join(agg::miter_join); - else if( join == MITER_REVERT_JOIN) - stroke.generator().line_join(agg::miter_join); - else if( join == ROUND_JOIN) - stroke.generator().line_join(agg::round_join); - else - stroke.generator().line_join(agg::bevel_join); - - line_cap_e cap=stroke_.get_line_cap(); - if (cap == BUTT_CAP) - stroke.generator().line_cap(agg::butt_cap); - else if (cap == SQUARE_CAP) - stroke.generator().line_cap(agg::square_cap); - else - stroke.generator().line_cap(agg::round_cap); - + set_join_caps(stroke_,stroke); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); @@ -172,25 +137,11 @@ void agg_renderer::process(line_symbolizer const& sym, } else { - agg::conv_stroke stroke(path); - line_join_e join=stroke_.get_line_join(); - if ( join == MITER_JOIN) - stroke.generator().line_join(agg::miter_join); - else if( join == MITER_REVERT_JOIN) - stroke.generator().line_join(agg::miter_join); - else if( join == ROUND_JOIN) - stroke.generator().line_join(agg::round_join); - else - stroke.generator().line_join(agg::bevel_join); - - line_cap_e cap=stroke_.get_line_cap(); - if (cap == BUTT_CAP) - stroke.generator().line_cap(agg::butt_cap); - else if (cap == SQUARE_CAP) - stroke.generator().line_cap(agg::square_cap); - else - stroke.generator().line_cap(agg::round_cap); - + clipped_geometry_type clipped(geom); + clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy()); + path_type path(t_,clipped,prj_trans); + agg::conv_stroke stroke(path); + set_join_caps(stroke_,stroke); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 1637f9450..57a01448e 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -253,7 +253,7 @@ void agg_renderer::process(markers_symbolizer const& sym, if (marker_type == ARROW) marker.concat_path(arrow_); - + clipped_geometry_type clipped(geom); clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); path_type path(t_,clipped,prj_trans); diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index 7e0f92c94..1d6fbde1f 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -23,6 +23,7 @@ // mapnik #include +#include #include #include #include @@ -72,27 +73,8 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, agg::scanline_u8 sl; ras_ptr->reset(); - switch (sym.get_gamma_method()) - { - case GAMMA_POWER: - ras_ptr->gamma(agg::gamma_power(sym.get_gamma())); - break; - case GAMMA_LINEAR: - ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma())); - break; - case GAMMA_NONE: - ras_ptr->gamma(agg::gamma_none()); - break; - case GAMMA_THRESHOLD: - ras_ptr->gamma(agg::gamma_threshold(sym.get_gamma())); - break; - case GAMMA_MULTIPLY: - ras_ptr->gamma(agg::gamma_multiply(sym.get_gamma())); - break; - default: - ras_ptr->gamma(agg::gamma_power(sym.get_gamma())); - } - + set_gamma_method(sym,ras_ptr); + std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature); boost::optional marker; if ( !filename.empty() ) @@ -134,7 +116,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, if (align == LOCAL_ALIGNMENT) { double x0=0,y0=0; - if (num_geometries>0) // FIXME: hmm...? + if (num_geometries>0) // FIXME: hmm...? { clipped_geometry_type clipped(feature->get_geometry(0)); clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 4b1f64bb8..2b532fb9f 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -23,6 +23,7 @@ // mapnik #include +#include #include #include @@ -35,6 +36,7 @@ // for polygon_symbolizer #include "agg_renderer_scanline.h" #include "agg_conv_clip_polygon.h" +#include "agg_conv_smooth_poly1.h" // stl #include @@ -45,8 +47,6 @@ void agg_renderer::process(polygon_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef agg::conv_clip_polygon clipped_geometry_type; - typedef coord_transform2 path_type; typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_aa_solid renderer; @@ -63,39 +63,39 @@ void agg_renderer::process(polygon_symbolizer const& sym, unsigned a=fill_.alpha(); //renb.clip_box(0,0,width_,height_); renderer ren(renb); - - ras_ptr->reset(); - switch (sym.get_gamma_method()) - { - case GAMMA_POWER: - ras_ptr->gamma(agg::gamma_power(sym.get_gamma())); - break; - case GAMMA_LINEAR: - ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma())); - break; - case GAMMA_NONE: - ras_ptr->gamma(agg::gamma_none()); - break; - case GAMMA_THRESHOLD: - ras_ptr->gamma(agg::gamma_threshold(sym.get_gamma())); - break; - case GAMMA_MULTIPLY: - ras_ptr->gamma(agg::gamma_multiply(sym.get_gamma())); - break; - default: - ras_ptr->gamma(agg::gamma_power(sym.get_gamma())); - } + ras_ptr->reset(); + + set_gamma_method(sym,ras_ptr); + //metawriter_with_properties writer = sym.get_metawriter(); + box2d inflated_extent = query_extent_ * 1.1; for (unsigned i=0;inum_geometries();++i) { geometry_type & geom=feature->get_geometry(i); if (geom.num_points() > 2) { - clipped_geometry_type clipped(geom); - clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); - path_type path(t_,clipped,prj_trans); - ras_ptr->add_path(path); + if (sym.smooth() > 0.0) + { + typedef agg::conv_clip_polygon clipped_geometry_type; + typedef coord_transform2 path_type; + typedef agg::conv_smooth_poly1_curve smooth_type; + clipped_geometry_type clipped(geom); + clipped.clip_box(inflated_extent.minx(),inflated_extent.miny(),inflated_extent.maxx(),inflated_extent.maxy()); + path_type path(t_,clipped,prj_trans); + smooth_type smooth(path); + smooth.smooth_value(sym.smooth()); + ras_ptr->add_path(smooth); + } + else + { + typedef agg::conv_clip_polygon clipped_geometry_type; + typedef coord_transform2 path_type; + clipped_geometry_type clipped(geom); + clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); + path_type path(t_,clipped,prj_trans); + ras_ptr->add_path(path); + } //if (writer.first) writer.first->add_polygon(path, *feature, t_, writer.second); } } diff --git a/src/build.py b/src/build.py index c25bc2fb5..78df41b46 100644 --- a/src/build.py +++ b/src/build.py @@ -178,6 +178,8 @@ source = Split( text_placements/list.cpp text_placements/simple.cpp text_properties.cpp + xml_tree.cpp + config_error.cpp """ ) @@ -299,7 +301,7 @@ if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']: env2 = lib_env.Clone() env2.Append(CXXFLAGS = '-DHAVE_LIBXML2') libmapnik_cxxflags.append('-DHAVE_LIBXML2') - fixup = ['load_map.cpp','libxml2_loader.cpp'] + fixup = ['libxml2_loader.cpp'] for cpp in fixup: if cpp in source: source.remove(cpp) @@ -307,6 +309,12 @@ if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']: source.insert(0,env2.StaticObject(cpp)) else: source.insert(0,env2.SharedObject(cpp)) +else: + source += Split( + """ + rapidxml_loader.cpp + """ + ) if env['CUSTOM_LDFLAGS']: linkflags = '%s %s' % (env['CUSTOM_LDFLAGS'], mapnik_lib_link_flag) diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index e018de3e9..e15e8460a 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -54,6 +53,7 @@ // agg #include "agg_conv_clip_polyline.h" #include "agg_conv_clip_polygon.h" +#include "agg_conv_smooth_poly1.h" // stl #ifdef MAPNIK_DEBUG @@ -257,7 +257,7 @@ cairo_face_ptr cairo_face_manager::get_face(face_ptr face) entry = boost::make_shared(font_engine_, face); cache_.insert(std::make_pair(face, entry)); } - + return entry; } @@ -713,7 +713,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) } query_extent_ = query_extent; } - + void cairo_renderer_base::end_layer_processing(layer const&) { #ifdef MAPNIK_DEBUG @@ -726,27 +726,41 @@ void cairo_renderer_base::start_map_processing(Map const& map) proj_transform const& prj_trans) { - typedef agg::conv_clip_polygon clipped_geometry_type; - typedef coord_transform2 path_type; - cairo_context context(context_); - context.set_color(sym.get_fill(), sym.get_opacity()); - + box2d inflated_extent = query_extent_ * 1.1; for (unsigned i = 0; i < feature->num_geometries(); ++i) { geometry_type & geom = feature->get_geometry(i); if (geom.num_points() > 2) { - clipped_geometry_type clipped(geom); - clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); - path_type path(t_,clipped,prj_trans); - context.add_path(path); - context.fill(); + if (sym.smooth() > 0.0) + { + typedef agg::conv_clip_polygon clipped_geometry_type; + typedef coord_transform2 path_type; + typedef agg::conv_smooth_poly1_curve smooth_type; + clipped_geometry_type clipped(geom); + clipped.clip_box(inflated_extent.minx(),inflated_extent.miny(),inflated_extent.maxx(),inflated_extent.maxy()); + path_type path(t_,clipped,prj_trans); + smooth_type smooth(path); + smooth.smooth_value(sym.smooth()); + context.add_agg_path(smooth); + context.fill(); + } + else + { + typedef agg::conv_clip_polygon clipped_geometry_type; + typedef coord_transform2 path_type; + clipped_geometry_type clipped(geom); + clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); + path_type path(t_,clipped,prj_trans); + context.add_path(path); + context.fill(); + } } } } - + void cairo_renderer_base::process(building_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) @@ -863,7 +877,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) { typedef agg::conv_clip_polyline clipped_geometry_type; typedef coord_transform2 path_type; - + cairo_context context(context_); mapnik::stroke const& stroke_ = sym.get_stroke(); @@ -1067,7 +1081,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) t_, font_manager_, detector_, query_extent_); cairo_context context(context_); - + while (helper.next()) { placements_type &placements = helper.placements(); for (unsigned int ii = 0; ii < placements.size(); ++ii) @@ -1087,7 +1101,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) { typedef agg::conv_clip_polyline clipped_geometry_type; typedef coord_transform2 path_type; - + std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature); boost::optional marker = mapnik::marker_cache::instance()->find(filename,true); if (!marker && !(*marker)->is_bitmap()) return; @@ -1111,7 +1125,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) clipped_geometry_type clipped(geom); clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); path_type path(t_,clipped,prj_trans); - + double length(0); double x0(0), y0(0); double x, y; @@ -1160,7 +1174,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) { typedef agg::conv_clip_polygon clipped_geometry_type; typedef coord_transform2 path_type; - + cairo_context context(context_); std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature); boost::optional marker = mapnik::marker_cache::instance()->find(filename,true); @@ -1180,7 +1194,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) { clipped_geometry_type clipped(geom); clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); - path_type path(t_,clipped,prj_trans); + path_type path(t_,clipped,prj_trans); context.add_path(path); context.fill(); } @@ -1249,9 +1263,9 @@ void cairo_renderer_base::start_map_processing(Map const& map) if (geom.num_points() > 1) { - + path_type path(t_, geom, prj_trans); - + markers_placement placement(path, arrow_.extent(), detector_, sym.get_spacing(), sym.get_max_error(), sym.get_allow_overlap()); double x, y, angle; diff --git a/src/color.cpp b/src/color.cpp index c70e01f5e..80464ccbb 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -25,11 +25,23 @@ // mapnik #include #include +#include + // boost #include +#include + // stl #include +// boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane) +#if BOOST_VERSION >= 104500 +#include +#else +#include +#endif + + namespace mapnik { color::color( std::string const& css_string) @@ -81,5 +93,90 @@ std::string color::to_hex_string() const } } + +/****************************************************************************/ +void color_factory::init_from_string(color & c, std::string const& css_color) +{ + typedef std::string::const_iterator iterator_type; + typedef mapnik::css_color_grammar css_color_grammar; + + css_color_grammar g; + iterator_type first = css_color.begin(); + iterator_type last = css_color.end(); + // boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane) +#if BOOST_VERSION >= 104500 + bool result = + boost::spirit::qi::phrase_parse(first, + last, + g, + boost::spirit::ascii::space, + c); + if (!result) + { + throw config_error(std::string("Failed to parse color value: ") + + "Expected a CSS color, but got '" + css_color + "'"); + } +#else + mapnik::css css_; + bool result = + boost::spirit::qi::phrase_parse(first, + last, + g, + boost::spirit::ascii::space, + css_); + if (!result) + { + throw config_error(std::string("Failed to parse color value: ") + + "Expected a CSS color, but got '" + css_color + "'"); + } + c.set_red(css_.r); + c.set_green(css_.g); + c.set_blue(css_.b); + c.set_alpha(css_.a); +#endif +} + +bool color_factory::parse_from_string(color & c, std::string const& css_color, + mapnik::css_color_grammar const& g) +{ + std::string::const_iterator first = css_color.begin(); + std::string::const_iterator last = css_color.end(); + // boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane) +#if BOOST_VERSION >= 104500 + bool result = + boost::spirit::qi::phrase_parse(first, + last, + g, + boost::spirit::ascii::space, + c); + return result && (first == last); +#else + mapnik::css css_; + bool result = + boost::spirit::qi::phrase_parse(first, + last, + g, + boost::spirit::ascii::space, + css_); + if (result && (first == last)) + { + c.set_red(css_.r); + c.set_green(css_.g); + c.set_blue(css_.b); + c.set_alpha(css_.a); + return true; + } + return false; +#endif +} + + +color color_factory::from_string(std::string const& css_color) +{ + color c; + init_from_string(c, css_color); + return c; +} + } diff --git a/src/config_error.cpp b/src/config_error.cpp new file mode 100644 index 000000000..714f5a5e2 --- /dev/null +++ b/src/config_error.cpp @@ -0,0 +1,55 @@ +#include +#include + +namespace mapnik +{ + +config_error::config_error(std::string const& what) + : what_(what), line_number_(0), file_(), node_name_(), msg_() +{ +} + + +config_error::config_error(std::string const& what, xml_node const& node) + : what_(what), line_number_(node.line()), file_(node.filename()), node_name_(node.name()), msg_() +{ +} + + +config_error::config_error(std::string const& what, unsigned line_number, std::string const& filename) + : what_(what), line_number_(line_number), file_(filename), node_name_(), msg_() +{ + +} + +char const* config_error::what() const throw() +{ + std::stringstream s; + s << file_; + if (line_number_ > 0) s << " line " << line_number_; + if (!node_name_.empty()) s << " in node "<< node_name_; + if (line_number_ > 0 || !file_.empty()) s << ": "; + s << what_; + msg_ = s.str(); //Avoid returning pointer to dead object + return msg_.c_str(); +} + +void config_error::append_context(std::string const& ctx) const +{ + what_ += " " + ctx; +} + +void config_error::append_context(std::string const& ctx, xml_node const& node) const +{ + append_context(ctx); + append_context(node); +} + +void config_error::append_context(xml_node const& node) const +{ + if (!line_number_) line_number_ = node.line(); + if (node_name_.empty()) node_name_ = node.name(); + if (file_.empty()) file_ = node.filename(); +} + +} diff --git a/src/conversions.cpp b/src/conversions.cpp index 7debd7a6c..d19272162 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -23,21 +23,21 @@ // boost #include -#define BOOST_SPIRIT_AUTO(domain_, name, expr) \ - typedef boost::proto::result_of:: \ - deep_copy::type name##_expr_type; \ - BOOST_SPIRIT_ASSERT_MATCH( \ - boost::spirit::domain_::domain, name##_expr_type); \ - BOOST_AUTO(name, boost::proto::deep_copy(expr)); \ +#define BOOST_SPIRIT_AUTO(domain_, name, expr) \ + typedef boost::proto::result_of:: \ + deep_copy::type name##_expr_type; \ + BOOST_SPIRIT_ASSERT_MATCH( \ + boost::spirit::domain_::domain, name##_expr_type); \ + BOOST_AUTO(name, boost::proto::deep_copy(expr)); \ namespace mapnik { namespace conversions { using namespace boost::spirit; -BOOST_SPIRIT_AUTO(qi, INTEGER, qi::int_); -BOOST_SPIRIT_AUTO(qi, FLOAT, qi::float_); -BOOST_SPIRIT_AUTO(qi, DOUBLE, qi::double_); +BOOST_SPIRIT_AUTO(qi, INTEGER, qi::int_) +BOOST_SPIRIT_AUTO(qi, FLOAT, qi::float_) +BOOST_SPIRIT_AUTO(qi, DOUBLE, qi::double_) bool string2int(const char * value, int & result) { diff --git a/src/expression.cpp b/src/expression.cpp index 9223021bc..84cd6b0ec 100644 --- a/src/expression.cpp +++ b/src/expression.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // boost #include @@ -50,8 +51,8 @@ expression_ptr expression_factory::compile(std::string const& str,transcoder con } bool expression_factory::parse_from_string(expression_ptr const& expr, - std::string const& str, - mapnik::expression_grammar const& g) + std::string const& str, + mapnik::expression_grammar const& g) { std::string::const_iterator itr = str.begin(); std::string::const_iterator end = str.end(); diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index 660671d25..a4c2cdf3a 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -203,7 +203,7 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces return; } - + #if defined(RENDERING_STATS) progress_timer layer_timer(std::clog, "rendering total for layer: '" + lay.name() + "'"); @@ -271,7 +271,6 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces query q(layer_ext,res,scale_denom,unbuffered_extent); p.start_layer_processing(lay, query_ext); - std::vector active_styles; attribute_collector collector(names); double filt_factor = 1; diff --git a/src/formatting/base.cpp b/src/formatting/base.cpp index e9c1ff3e7..3b88d581c 100644 --- a/src/formatting/base.cpp +++ b/src/formatting/base.cpp @@ -23,6 +23,7 @@ #include #include #include +#include // boost #include @@ -38,18 +39,18 @@ void node::to_xml(boost::property_tree::ptree &xml) const #endif } -node_ptr node::from_xml(boost::property_tree::ptree const& xml) +node_ptr node::from_xml(xml_node const& xml) { list_node *list = new list_node(); node_ptr list_ptr(list); - boost::property_tree::ptree::const_iterator itr = xml.begin(); - boost::property_tree::ptree::const_iterator end = xml.end(); + xml_node::const_iterator itr = xml.begin(); + xml_node::const_iterator end = xml.end(); for (; itr != end; ++itr) { - if (itr->first == "" || itr->first == "" || itr->first == "Placement") + if (itr->name() == "Placement") { continue; } - node_ptr n = registry::instance()->from_xml(itr->first, itr->second); + node_ptr n = registry::instance()->from_xml(*itr); if (n) list->push_back(n); } if (list->get_children().size() == 1) { diff --git a/src/formatting/expression.cpp b/src/formatting/expression.cpp index 0ee7598bd..5dfff9972 100644 --- a/src/formatting/expression.cpp +++ b/src/formatting/expression.cpp @@ -27,6 +27,7 @@ #include #include #include +#include // boost @@ -37,7 +38,7 @@ namespace formatting using boost::property_tree::ptree; void expression_format::to_xml(boost::property_tree::ptree &xml) const { - ptree &new_node = xml.push_back(ptree::value_type("Format", ptree()))->second; + ptree &new_node = xml.push_back(ptree::value_type("ExpressionFormat", ptree()))->second; if (face_name) set_attr(new_node, "face-name", to_expression_string(*face_name)); if (text_size) set_attr(new_node, "size", to_expression_string(*text_size)); if (character_spacing) set_attr(new_node, "character-spacing", to_expression_string*character_spacing); @@ -51,7 +52,7 @@ void expression_format::to_xml(boost::property_tree::ptree &xml) const if (child_) child_->to_xml(new_node); } -node_ptr expression_format::from_xml(ptree const& xml) +node_ptr expression_format::from_xml(xml_node const& xml) { expression_format *n = new expression_format(); node_ptr np(n); @@ -72,9 +73,9 @@ node_ptr expression_format::from_xml(ptree const& xml) return np; } -expression_ptr expression_format::get_expression(ptree const& xml, std::string name) +expression_ptr expression_format::get_expression(xml_node const& xml, std::string name) { - boost::optional tmp = get_opt_attr(xml, name); + boost::optional tmp = xml.get_opt_attr(name); if (tmp) return parse_expression(*tmp); return expression_ptr(); } @@ -84,25 +85,25 @@ void expression_format::apply(char_properties const& p, const Feature &feature, { char_properties new_properties = p; if (face_name) new_properties.face_name = - boost::apply_visitor(evaluate(feature), *face_name).to_string(); + boost::apply_visitor(evaluate(feature), *face_name).to_string(); if (text_size) new_properties.text_size = - boost::apply_visitor(evaluate(feature), *text_size).to_double(); + boost::apply_visitor(evaluate(feature), *text_size).to_double(); if (character_spacing) new_properties.character_spacing = - boost::apply_visitor(evaluate(feature), *character_spacing).to_double(); + boost::apply_visitor(evaluate(feature), *character_spacing).to_double(); if (line_spacing) new_properties.line_spacing = - boost::apply_visitor(evaluate(feature), *line_spacing).to_double(); + boost::apply_visitor(evaluate(feature), *line_spacing).to_double(); if (text_opacity) new_properties.text_opacity = - boost::apply_visitor(evaluate(feature), *text_opacity).to_double(); + boost::apply_visitor(evaluate(feature), *text_opacity).to_double(); if (wrap_before) new_properties.wrap_before = - boost::apply_visitor(evaluate(feature), *wrap_before).to_bool(); + boost::apply_visitor(evaluate(feature), *wrap_before).to_bool(); if (wrap_char) new_properties.wrap_char = - boost::apply_visitor(evaluate(feature), *character_spacing).to_unicode()[0]; + boost::apply_visitor(evaluate(feature), *character_spacing).to_unicode()[0]; // if (fill) new_properties.fill = // boost::apply_visitor(evaluate(feature), *fill).to_color(); // if (halo_fill) new_properties.halo_fill = // boost::apply_visitor(evaluate(feature), *halo_fill).to_color(); if (halo_radius) new_properties.halo_radius = - boost::apply_visitor(evaluate(feature), *halo_radius).to_double(); + boost::apply_visitor(evaluate(feature), *halo_radius).to_double(); if (child_) { child_->apply(new_properties, feature, output); diff --git a/src/formatting/format.cpp b/src/formatting/format.cpp index 860896dce..f1fad9d3e 100644 --- a/src/formatting/format.cpp +++ b/src/formatting/format.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include #include +#include namespace mapnik { using boost::property_tree::ptree; @@ -44,7 +45,7 @@ void format_node::to_xml(ptree &xml) const } -node_ptr format_node::from_xml(ptree const& xml) +node_ptr format_node::from_xml(xml_node const& xml) { format_node *n = new format_node(); node_ptr np(n); @@ -52,19 +53,19 @@ node_ptr format_node::from_xml(ptree const& xml) node_ptr child = node::from_xml(xml); n->set_child(child); - n->face_name = get_opt_attr(xml, "face-name"); + n->face_name = xml.get_opt_attr("face-name"); /*TODO: Fontset is problematic. We don't have the fontsets pointer here... */ - n->text_size = get_opt_attr(xml, "size"); - n->character_spacing = get_opt_attr(xml, "character-spacing"); - n->line_spacing = get_opt_attr(xml, "line-spacing"); - n->text_opacity = get_opt_attr(xml, "opactity"); - boost::optional wrap = get_opt_attr(xml, "wrap-before"); + n->text_size = xml.get_opt_attr("size"); + n->character_spacing = xml.get_opt_attr("character-spacing"); + n->line_spacing = xml.get_opt_attr("line-spacing"); + n->text_opacity = xml.get_opt_attr("opactity"); + boost::optional wrap = xml.get_opt_attr("wrap-before"); if (wrap) n->wrap_before = *wrap; - n->wrap_char = get_opt_attr(xml, "wrap-character"); - n->text_transform = get_opt_attr(xml, "text-transform"); - n->fill = get_opt_attr(xml, "fill"); - n->halo_fill = get_opt_attr(xml, "halo-fill"); - n->halo_radius = get_opt_attr(xml, "halo-radius"); + n->wrap_char = xml.get_opt_attr("wrap-character"); + n->text_transform = xml.get_opt_attr("text-transform"); + n->fill = xml.get_opt_attr("fill"); + n->halo_fill = xml.get_opt_attr("halo-fill"); + n->halo_radius = xml.get_opt_attr("halo-radius"); return np; } diff --git a/src/formatting/registry.cpp b/src/formatting/registry.cpp index 2c3a29a4a..527c81d71 100644 --- a/src/formatting/registry.cpp +++ b/src/formatting/registry.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include namespace mapnik { @@ -46,10 +48,11 @@ void registry::register_name(std::string name, from_xml_function_ptr ptr, bool o } } -node_ptr registry::from_xml(std::string name, const boost::property_tree::ptree &xml) +node_ptr registry::from_xml(xml_node const& xml) { - std::map::const_iterator itr = map_.find(name); - if (itr == map_.end()) throw config_error("Unknown element '" + name + "'"); + std::map::const_iterator itr = map_.find(xml.name()); + if (itr == map_.end()) throw config_error("Unknown element '" + xml.name() + "'", xml); + xml.set_processed(true); return itr->second(xml); } } //ns formatting diff --git a/src/formatting/text.cpp b/src/formatting/text.cpp index 7b5b8ff92..3377c9e4b 100644 --- a/src/formatting/text.cpp +++ b/src/formatting/text.cpp @@ -26,10 +26,7 @@ #include #include #include - -// boost -#include -#include +#include namespace mapnik { @@ -46,10 +43,9 @@ void text_node::to_xml(ptree &xml) const } -node_ptr text_node::from_xml(boost::property_tree::ptree const& xml) +node_ptr text_node::from_xml(xml_node const& xml) { - std::string data = xml.data(); - boost::trim(data); + std::string data = xml.text(); if (data.empty()) return node_ptr(); //No text return boost::make_shared(parse_expression(data, "utf8")); } diff --git a/src/grid/grid_renderer.cpp b/src/grid/grid_renderer.cpp index 5a9a81448..067c23b55 100644 --- a/src/grid/grid_renderer.cpp +++ b/src/grid/grid_renderer.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/src/json/feature_collection_parser.cpp b/src/json/feature_collection_parser.cpp index fbf9c2b19..a7f2a418a 100644 --- a/src/json/feature_collection_parser.cpp +++ b/src/json/feature_collection_parser.cpp @@ -33,29 +33,29 @@ namespace mapnik { namespace json { #if BOOST_VERSION >= 104700 -template -feature_collection_parser::feature_collection_parser(mapnik::context_ptr const& ctx, mapnik::transcoder const& tr) - : grammar_(new feature_collection_grammar(ctx,tr)) {} + template + feature_collection_parser::feature_collection_parser(mapnik::context_ptr const& ctx, mapnik::transcoder const& tr) + : grammar_(new feature_collection_grammar(ctx,tr)) {} -template -feature_collection_parser::~feature_collection_parser() {} + template + feature_collection_parser::~feature_collection_parser() {} #endif -template -bool feature_collection_parser::parse(iterator_type first, iterator_type last, std::vector & features) -{ + template + bool feature_collection_parser::parse(iterator_type first, iterator_type last, std::vector & features) + { #if BOOST_VERSION >= 104700 - using namespace boost::spirit; - return qi::phrase_parse(first, last, *grammar_, standard_wide::space, features); + using namespace boost::spirit; + return qi::phrase_parse(first, last, *grammar_, standard_wide::space, features); #else - std::ostringstream s; - s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; - throw std::runtime_error("mapnik::feature_collection_parser::parse() requires at least boost 1.47 while your build was compiled against boost " + s.str()); - return false; + std::ostringstream s; + s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; + throw std::runtime_error("mapnik::feature_collection_parser::parse() requires at least boost 1.47 while your build was compiled against boost " + s.str()); + return false; #endif -} + } -template class feature_collection_parser ; -template class feature_collection_parser > >; -}} + template class feature_collection_parser ; + template class feature_collection_parser > >; + }} diff --git a/src/json/geojson_generator.cpp b/src/json/geojson_generator.cpp index c25440ded..750489690 100644 --- a/src/json/geojson_generator.cpp +++ b/src/json/geojson_generator.cpp @@ -32,30 +32,30 @@ namespace mapnik { namespace json { -feature_generator::feature_generator() - : grammar_(new feature_generator_grammar()) {} - -feature_generator::~feature_generator() {} + feature_generator::feature_generator() + : grammar_(new feature_generator_grammar()) {} -bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f) -{ - sink_type sink(geojson); - return karma::generate(sink, *grammar_,f); -} + feature_generator::~feature_generator() {} + + bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f) + { + sink_type sink(geojson); + return karma::generate(sink, *grammar_,f); + } -geometry_generator::geometry_generator() - : grammar_(new multi_geometry_generator_grammar()) {} + geometry_generator::geometry_generator() + : grammar_(new multi_geometry_generator_grammar()) {} -geometry_generator::~geometry_generator() {} + geometry_generator::~geometry_generator() {} -bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g) -{ - sink_type sink(geojson); - return karma::generate(sink, *grammar_,g); -} + bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g) + { + sink_type sink(geojson); + return karma::generate(sink, *grammar_,g); + } -}} + }} #else @@ -65,22 +65,22 @@ bool geometry_generator::generate(std::string & geojson, mapnik::geometry_contai namespace mapnik { namespace json { -bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f) -{ - std::ostringstream s; - s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; - throw std::runtime_error("feature_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str()); - return false; -} + bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f) + { + std::ostringstream s; + s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; + throw std::runtime_error("feature_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str()); + return false; + } -bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g) -{ - std::ostringstream s; - s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; - throw std::runtime_error("geometry_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str()); - return false; -} + bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g) + { + std::ostringstream s; + s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; + throw std::runtime_error("geometry_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str()); + return false; + } -}} + }} #endif diff --git a/src/layer.cpp b/src/layer.cpp index c3c32a7d3..2248e532c 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -27,6 +27,7 @@ #include #include +#include // stl #include diff --git a/src/libxml2_loader.cpp b/src/libxml2_loader.cpp index af9ff4de9..d95e145ca 100644 --- a/src/libxml2_loader.cpp +++ b/src/libxml2_loader.cpp @@ -22,26 +22,27 @@ #ifdef HAVE_LIBXML2 -#include - +// mapnik +#include +#include #include +// boost #include -#include #include #include +// libxml #include #include #include #include +// stl #include -using boost::property_tree::ptree; using namespace std; -//#define DEFAULT_OPTIONS (XML_PARSE_NOENT | XML_PARSE_NOBLANKS | XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA) #define DEFAULT_OPTIONS (XML_PARSE_NOERROR | XML_PARSE_NOENT | XML_PARSE_NOBLANKS | XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA) namespace mapnik @@ -50,14 +51,14 @@ class libxml2_loader : boost::noncopyable { public: libxml2_loader(const char *encoding = NULL, int options = DEFAULT_OPTIONS, const char *url = NULL) : - ctx_( 0 ), - encoding_( encoding ), - options_( options ), - url_( url ) + ctx_(0), + encoding_(encoding), + options_(options), + url_(url) { LIBXML_TEST_VERSION; ctx_ = xmlNewParserCtxt(); - if ( ! ctx_ ) + if (!ctx_) { throw std::runtime_error("Failed to create parser context."); } @@ -71,19 +72,19 @@ public: } } - void load( std::string const& filename, ptree & pt ) + void load(std::string const& filename, xml_node &node) { boost::filesystem::path path(filename); - if ( !boost::filesystem::exists( path ) ) { - throw config_error(string("Could not load map file '") + - filename + "': File does not exist"); + if (!boost::filesystem::exists(path)) + { + throw config_error(string("Could not load map file: File does not exist"), 0, filename); } xmlDocPtr doc = xmlCtxtReadFile(ctx_, filename.c_str(), encoding_, options_); - if ( !doc ) + if (!doc) { - xmlError * error = xmlCtxtGetLastError( ctx_ ); + xmlError * error = xmlCtxtGetLastError(ctx_); if (error) { std::ostringstream os; @@ -91,15 +92,7 @@ public: os << ": " << std::endl << error->message; // remove CR std::string msg = os.str().substr(0, os.str().size() - 1); - config_error ex( msg ); - - os.str(""); - os << "(encountered in file '" << error->file << "' at line " - << error->line << ")"; - - ex.append_context( os.str() ); - - throw ex; + throw config_error(msg, error->line, error->file); } } @@ -110,21 +103,21 @@ public: << std::endl; } */ - load(doc, pt); + load(doc, node); } - void load( const int fd, ptree & pt ) + void load(const int fd, xml_node &node) { xmlDocPtr doc = xmlCtxtReadFd(ctx_, fd, url_, encoding_, options_); - load(doc, pt); + load(doc, node); } - void load_string( std::string const& buffer, ptree & pt, std::string const & base_path ) + void load_string(std::string const& buffer, xml_node &node, std::string const & base_path) { if (!base_path.empty()) { boost::filesystem::path path(base_path); - if ( ! boost::filesystem::exists( path ) ) { + if (!boost::filesystem::exists(path)) { throw config_error(string("Could not locate base_path '") + base_path + "': file or directory does not exist"); } @@ -132,12 +125,12 @@ public: xmlDocPtr doc = xmlCtxtReadMemory(ctx_, buffer.data(), buffer.length(), base_path.c_str(), encoding_, options_); - load(doc, pt); + load(doc, node); } - void load( const xmlDocPtr doc, ptree & pt ) + void load(const xmlDocPtr doc, xml_node &node) { - if ( !doc ) + if (!doc) { xmlError * error = xmlCtxtGetLastError( ctx_ ); std::ostringstream os; @@ -146,10 +139,10 @@ public: { os << ": " << std::endl << error->message; } - throw config_error(os.str()); + throw config_error(os.str(), error->line, error->file); } - int iXIncludeReturn = xmlXIncludeProcessFlags( doc, options_ ); + int iXIncludeReturn = xmlXIncludeProcessFlags(doc, options_); if (iXIncludeReturn < 0) { @@ -157,64 +150,48 @@ public: throw config_error("XML XInclude error. One or more files failed to load."); } - xmlNode * root = xmlDocGetRootElement( doc ); - if ( ! root ) { + xmlNode * root = xmlDocGetRootElement(doc); + if (!root) { xmlFreeDoc(doc); throw config_error("XML document is empty."); } - populate_tree( root, pt ); + populate_tree(root, node); xmlFreeDoc(doc); } private: - void append_attributes( xmlAttr * attributes, ptree & pt) + void append_attributes(xmlAttr *attributes, xml_node &node) { - if (attributes) + for (; attributes; attributes = attributes->next ) { - ptree::iterator it = pt.push_back( ptree::value_type( "", ptree() )); - ptree & attr_list = it->second; - xmlAttr * cur_attr = attributes; - for (; cur_attr; cur_attr = cur_attr->next ) - { - ptree::iterator it = attr_list.push_back( - ptree::value_type( (char*)cur_attr->name, ptree() )); - it->second.put_value( (char*) cur_attr->children->content ); - } + node.add_attribute((char *)attributes->name, (char *)attributes->children->content); } } - void populate_tree( xmlNode * node, ptree & pt ) + void populate_tree(xmlNode *cur_node, xml_node &node) { - xmlNode * cur_node = node; - for (; cur_node; cur_node = cur_node->next ) { switch (cur_node->type) { case XML_ELEMENT_NODE: { - ptree::iterator it = pt.push_back( ptree::value_type( - (char*)cur_node->name, ptree() )); - append_attributes( cur_node->properties, it->second); - populate_tree( cur_node->children, it->second ); + + xml_node &new_node = node.add_child((char *)cur_node->name, cur_node->line, false); + append_attributes(cur_node->properties, new_node); + populate_tree(cur_node->children, new_node); } break; case XML_TEXT_NODE: { std::string trimmed = boost::algorithm::trim_copy(std::string((char*)cur_node->content)); - if (trimmed.empty()) break; - ptree::iterator it = pt.push_back(ptree::value_type("", ptree())); - it->second.put_value(trimmed); + if (trimmed.empty()) break; //Don't add empty text nodes + node.add_child(trimmed, cur_node->line, true); } break; case XML_COMMENT_NODE: - { - ptree::iterator it = pt.push_back( - ptree::value_type( "", ptree() )); - it->second.put_value( (char*) cur_node->content ); - } - break; + break; default: break; @@ -228,15 +205,15 @@ private: const char *url_; }; -void read_xml2( std::string const & filename, boost::property_tree::ptree & pt) +void read_xml(std::string const & filename, xml_node &node) { libxml2_loader loader; - loader.load( filename, pt ); + loader.load(filename, node); } -void read_xml2_string( std::string const & str, boost::property_tree::ptree & pt, std::string const & base_path) +void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path) { libxml2_loader loader; - loader.load_string( str, pt, base_path ); + loader.load_string(str, node, base_path); } } // end of namespace mapnik diff --git a/src/load_map.cpp b/src/load_map.cpp index 54ec44686..884413552 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include #include #include #include @@ -33,11 +34,7 @@ #include #include #include - -#include -#ifdef HAVE_LIBXML2 -#include -#endif +#include #include #include @@ -51,6 +48,7 @@ #include #include #include +#include // boost #include @@ -68,13 +66,12 @@ // stl #include +#include using boost::lexical_cast; using boost::bad_lexical_cast; using boost::tokenizer; -using boost::property_tree::ptree; -using std::cerr; using std::endl; namespace mapnik @@ -87,47 +84,44 @@ public: strict_( strict ), filename_( filename ), relative_to_xml_(true), - font_manager_(font_engine_), - color_grammar_(), - // TODO - use xml encoding? - tr_("utf8"), - expr_grammar_(tr_) - {} + font_manager_(font_engine_) + {} - void parse_map(Map & map, ptree const & sty, std::string const& base_path); + void parse_map(Map & map, xml_node const& sty, std::string const& base_path); private: - void parse_map_include( Map & map, ptree const & include); - void parse_style(Map & map, ptree const & sty); - void parse_layer(Map & map, ptree const & lay); - void parse_metawriter(Map & map, ptree const & lay); - void parse_metawriter_in_symbolizer(symbolizer_base &sym, ptree const &pt); + void parse_map_include( Map & map, xml_node const& include); + void parse_style(Map & map, xml_node const& sty); + void parse_layer(Map & map, xml_node const& lay); + void parse_metawriter(Map & map, xml_node const& lay); + void parse_metawriter_in_symbolizer(symbolizer_base &sym, xml_node const& pt); - void parse_fontset(Map & map, ptree const & fset); - void parse_font(font_set & fset, ptree const & f); + void parse_fontset(Map & map, xml_node const & fset); + void parse_font(font_set & fset, xml_node const& f); - void parse_rule(feature_type_style & style, ptree const & r); + void parse_rule(feature_type_style & style, xml_node const & r); - void parse_point_symbolizer(rule & rule, ptree const & sym); - void parse_line_pattern_symbolizer(rule & rule, ptree const & sym); - void parse_polygon_pattern_symbolizer(rule & rule, ptree const & sym); - void parse_text_symbolizer(rule & rule, ptree const & sym); - void parse_shield_symbolizer(rule & rule, ptree const & sym); - void parse_line_symbolizer(rule & rule, ptree const & sym); - void parse_polygon_symbolizer(rule & rule, ptree const & sym); - void parse_building_symbolizer(rule & rule, ptree const & sym ); - void parse_raster_symbolizer(rule & rule, ptree const & sym ); - void parse_markers_symbolizer(rule & rule, ptree const & sym ); + void parse_point_symbolizer(rule & rule, xml_node const& sym); + void parse_line_pattern_symbolizer(rule & rule, xml_node const& sym); + void parse_polygon_pattern_symbolizer(rule & rule, xml_node const& sym); + void parse_text_symbolizer(rule & rule, xml_node const& sym); + void parse_shield_symbolizer(rule & rule, xml_node const& sym); + void parse_line_symbolizer(rule & rule, xml_node const& sym); + void parse_polygon_symbolizer(rule & rule, xml_node const& sym); + void parse_building_symbolizer(rule & rule, xml_node const& sym ); + void parse_raster_symbolizer(rule & rule, xml_node const& sym ); + void parse_markers_symbolizer(rule & rule, xml_node const& sym ); - void parse_raster_colorizer(raster_colorizer_ptr const& rc, ptree const& node ); - void parse_stroke(stroke & strk, ptree const & sym); - expression_ptr parse_expr(std::string const& expr); + void parse_raster_colorizer(raster_colorizer_ptr const& rc, xml_node const& node); + void parse_stroke(stroke & strk, xml_node const & sym); - void ensure_font_face( std::string const& face_name ); + void ensure_font_face(std::string const& face_name); + void find_unused_nodes(xml_node const& root); + void find_unused_nodes_recursive(xml_node const& node, std::stringstream &error_text); - std::string ensure_relative_to_xml( boost::optional opt_path ); - void ensure_attrs( ptree const& sym, std::string name, std::string attrs); + + std::string ensure_relative_to_xml(boost::optional opt_path); boost::optional get_opt_color_attr(boost::property_tree::ptree const& node, - std::string const& name); + std::string const& name); bool strict_; std::string filename_; @@ -137,157 +131,59 @@ private: face_manager font_manager_; std::map file_sources_; std::map fontsets_; - mapnik::css_color_grammar color_grammar_; - mapnik::transcoder tr_; - mapnik::expression_grammar expr_grammar_; - }; -void remove_empty_text_nodes(ptree &pt) -{ - ptree::iterator itr = pt.begin(); - ptree::iterator end = pt.end(); - while (itr!=end) - { - if (itr->first == "") { - std::string trimmed = boost::algorithm::trim_copy(itr->second.data()); - if (trimmed.empty()) { - itr = pt.erase(itr); - } else { - itr++; - } - } else { - remove_empty_text_nodes(itr->second); - itr++; - } - } -} - -//#include +#include void load_map(Map & map, std::string const& filename, bool strict) { - ptree pt; -#ifdef HAVE_LIBXML2 - read_xml2(filename, pt); -#else - try - { - read_xml(filename, pt, boost::property_tree::xml_parser::no_concat_text|boost::property_tree::xml_parser::no_comments); - remove_empty_text_nodes(pt); - } - catch (const boost::property_tree::xml_parser_error & ex) - { - throw config_error( ex.what() ); - } + // TODO - use xml encoding? + xml_tree tree("utf8"); + tree.set_filename(filename); + read_xml(filename, tree.root()); + map_parser parser(strict, filename); + parser.parse_map(map, tree.root(), ""); +#ifdef MAPNIK_DEBUG + dump_xml(tree.root()); #endif - map_parser parser( strict, filename); - std::string base_path(""); - parser.parse_map(map, pt, base_path); } void load_map_string(Map & map, std::string const& str, bool strict, std::string base_path) { - if (str.empty()) - { - throw config_error( "Cannot load map, XML string is empty" ) ; - } - - ptree pt; -#ifdef HAVE_LIBXML2 + // TODO - use xml encoding? + xml_tree tree("utf8"); if (!base_path.empty()) - read_xml2_string(str, pt, base_path); // accept base_path passed into function + read_xml_string(str, tree.root(), base_path); // accept base_path passed into function else - read_xml2_string(str, pt, map.base_path()); // default to map base_path -#else - try - { - std::istringstream s(str); - // TODO - support base_path? - read_xml(s, pt, boost::property_tree::xml_parser::no_concat_text|boost::property_tree::xml_parser::no_comments); - remove_empty_text_nodes(pt); - } - catch (const boost::property_tree::xml_parser_error & ex) - { - throw config_error( ex.what() ) ; - } -#endif - - map_parser parser( strict, base_path); - parser.parse_map(map, pt, base_path); + read_xml_string(str, tree.root(), map.base_path()); // default to map base_path + map_parser parser(strict, base_path); + parser.parse_map(map, tree.root(), base_path); } -expression_ptr map_parser::parse_expr(std::string const& str) -{ - expression_ptr expr(boost::make_shared(true)); - if (!expression_factory::parse_from_string(expr,str,expr_grammar_)) - { - throw mapnik::config_error( "Failed to parse expression: '" + str + "'" ); - } - return expr; - -} - -boost::optional map_parser::get_opt_color_attr(boost::property_tree::ptree const& node, - std::string const& name) -{ - - boost::optional str = node.get_optional( std::string(".") + name); - boost::optional result; - if (str && !str->empty()) - { - mapnik::color c; - if (mapnik::color_factory::parse_from_string(c,*str,color_grammar_)) - { - result.reset(c); - } - else - { - throw config_error(std::string("Failed to parse attribute ") + - name + "'. Expected color" + - " but got '" + *str + "'"); - } - } - return result; -} - -void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base_path ) +void map_parser::parse_map(Map & map, xml_node const& pt, std::string const& base_path) { try { - ptree const & map_node = pt.get_child("Map"); - - std::ostringstream s(""); - s << "background-color," - << "background-image," - << "srs," - << "buffer-size," - << "paths-from-xml," - << "minimum-version," - << "font-directory," - << "maximum-extent," - << "base"; - ensure_attrs(map_node, "Map", s.str()); - + xml_node const& map_node = pt.get_child("Map"); try { parameters extra_attr; // Check if relative paths should be interpreted as relative to/from XML location // Default is true, and map_parser::ensure_relative_to_xml will be called to modify path - optional paths_from_xml = get_opt_attr(map_node, "paths-from-xml"); + optional paths_from_xml = map_node.get_opt_attr("paths-from-xml"); if (paths_from_xml) { relative_to_xml_ = *paths_from_xml; } - optional base_path_from_xml = get_opt_attr(map_node, "base"); + optional base_path_from_xml = map_node.get_opt_attr("base"); if (!base_path.empty()) { - map.set_base_path( base_path ); + map.set_base_path(base_path); } else if (base_path_from_xml) { - map.set_base_path( *base_path_from_xml ); + map.set_base_path(*base_path_from_xml); } else { @@ -299,30 +195,30 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base std::string base = xml_path.branch_path().string(); #endif - map.set_base_path( base ); + map.set_base_path(base); } - optional bgcolor = get_opt_color_attr(map_node, "background-color"); + optional bgcolor = map_node.get_opt_attr("background-color"); if (bgcolor) { - map.set_background( * bgcolor ); + map.set_background(*bgcolor); } - optional image_filename = get_opt_attr(map_node, "background-image"); + optional image_filename = map_node.get_opt_attr("background-image"); if (image_filename) { map.set_background_image(ensure_relative_to_xml(image_filename)); } - map.set_srs( get_attr(map_node, "srs", map.srs() )); + map.set_srs(map_node.get_attr("srs", map.srs())); - optional buffer_size = get_opt_attr(map_node,"buffer-size"); + optional buffer_size = map_node.get_opt_attr("buffer-size"); if (buffer_size) { map.set_buffer_size(*buffer_size); } - optional maximum_extent = get_opt_attr(map_node,"maximum-extent"); + optional maximum_extent = map_node.get_opt_attr("maximum-extent"); if (maximum_extent) { box2d box; @@ -333,33 +229,33 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base else { std::ostringstream s_err; - s << "failed to parse 'maximum-extent'"; - if ( strict_ ) + s_err << "failed to parse 'maximum-extent'"; + if (strict_) throw config_error(s_err.str()); else - std::clog << "### WARNING: " << s.str() << std::endl; + std::clog << "### WARNING: " << s_err.str() << std::endl; } } - optional font_directory = get_opt_attr(map_node,"font-directory"); + optional font_directory = map_node.get_opt_attr("font-directory"); if (font_directory) { extra_attr["font-directory"] = *font_directory; - freetype_engine::register_fonts( ensure_relative_to_xml(font_directory), false); + freetype_engine::register_fonts(ensure_relative_to_xml(font_directory), false); } - optional min_version_string = get_opt_attr(map_node, "minimum-version"); + optional min_version_string = map_node.get_opt_attr("minimum-version"); if (min_version_string) { extra_attr["minimum-version"] = *min_version_string; boost::char_separator sep("."); - boost::tokenizer > tokens(*min_version_string,sep); + boost::tokenizer > tokens(*min_version_string, sep); unsigned i = 0; bool success = false; int n[3]; - for (boost::tokenizer >::iterator beg=tokens.begin(); - beg!=tokens.end();++beg) + for (boost::tokenizer >::iterator beg = tokens.begin(); + beg != tokens.end(); ++beg) { try { @@ -393,229 +289,177 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base } catch (const config_error & ex) { - ex.append_context("(in node Map)"); + ex.append_context(map_node); throw; } - parse_map_include( map, map_node ); + parse_map_include(map, map_node); } - catch (const boost::property_tree::ptree_bad_path &) + catch (node_not_found const&) { throw config_error("Not a map file. Node 'Map' not found."); } + find_unused_nodes(pt); } -void map_parser::parse_map_include( Map & map, ptree const & include ) +void map_parser::parse_map_include(Map & map, xml_node const& include) { - ptree::const_iterator itr = include.begin(); - ptree::const_iterator end = include.end(); - - for (; itr != end; ++itr) + try { - ptree::value_type const& v = *itr; + xml_node::const_iterator itr = include.begin(); + xml_node::const_iterator end = include.end(); - if (v.first == "Include") + for (; itr != end; ++itr) { - parse_map_include( map, v.second ); - } - else if (v.first == "Style") - { - parse_style( map, v.second ); - } - else if (v.first == "Layer") - { - parse_layer(map, v.second ); - } - else if (v.first == "FontSet") - { - parse_fontset(map, v.second); - } - else if (v.first == "MetaWriter") - { - parse_metawriter(map, v.second); - } - else if (v.first == "FileSource") - { - std::string name = get_attr( v.second, "name"); - std::string value = get_value( v.second, ""); - file_sources_[name] = value; - } - else if (v.first == "Datasource") - { - std::string name = get_attr(v.second, "name", std::string("Unnamed")); - parameters params; - ptree::const_iterator paramIter = v.second.begin(); - ptree::const_iterator endParam = v.second.end(); - for (; paramIter != endParam; ++paramIter) + if (itr->is_text()) continue; + if (itr->is("Include")) { - ptree const& param = paramIter->second; - - if (paramIter->first == "Parameter") - { - std::string name = get_attr(param, "name"); - std::string value = get_value( param, - "datasource parameter"); - params[name] = value; - } - else if( paramIter->first != "" && - paramIter->first != "") - { - throw config_error(std::string("Unknown child node in ") + - "'Datasource'. Expected 'Parameter' but got '" + - paramIter->first + "'"); - } + parse_map_include(map, *itr); } - datasource_templates_[name] = params; - } - else if (v.first == "Parameters") - { - std::string name = get_attr(v.second, "name", std::string("Unnamed")); - parameters & params = map.get_extra_parameters(); - ptree::const_iterator paramIter = v.second.begin(); - ptree::const_iterator endParam = v.second.end(); - for (; paramIter != endParam; ++paramIter) + else if (itr->is("Style")) { - ptree const& param = paramIter->second; - - if (paramIter->first == "Parameter") + parse_style(map, *itr); + } + else if (itr->is("Layer")) + { + parse_layer(map, *itr); + } + else if (itr->is("FontSet")) + { + parse_fontset(map, *itr); + } + else if (itr->is("MetaWriter")) + { + parse_metawriter(map, *itr); + } + else if (itr->is("FileSource")) + { + std::string name = itr->get_attr("name"); + std::string value = itr->get_text(); + file_sources_[name] = value; + } + else if (itr->is("Datasource")) + { + std::string name = itr->get_attr("name", std::string("Unnamed")); + parameters params; + xml_node::const_iterator paramIter = itr->begin(); + xml_node::const_iterator endParam = itr->end(); + for (; paramIter != endParam; ++paramIter) { - std::string name = get_attr(param, "name"); - bool is_string = true; - boost::optional type = get_opt_attr(param, "type"); - if (type) + if (paramIter->is("Parameter")) { - if (*type == "int") - { - is_string = false; - int value = get_value( param,"parameter"); - params[name] = value; - } - else if (*type == "float") - { - is_string = false; - double value = get_value( param,"parameter"); - params[name] = value; - } - } - - if (is_string) - { - std::string value = get_value( param, - "parameter"); + std::string name = paramIter->get_attr("name"); + std::string value = paramIter->get_text(); params[name] = value; } } - else if( paramIter->first != "" && - paramIter->first != "" ) + datasource_templates_[name] = params; + } + else if (itr->is("Parameters")) + { + std::string name = itr->get_attr("name", std::string("Unnamed")); + parameters & params = map.get_extra_parameters(); + xml_node::const_iterator paramIter = itr->begin(); + xml_node::const_iterator endParam = itr->end(); + for (; paramIter != endParam; ++paramIter) { - throw config_error(std::string("Unknown child node in ") + - "'Parameters'. Expected 'Parameter' but got '" + - paramIter->first + "'"); + if (paramIter->is("Parameter")) + { + std::string name = paramIter->get_attr("name"); + bool is_string = true; + boost::optional type = paramIter->get_opt_attr("type"); + if (type) + { + if (*type == "int") + { + is_string = false; + int value = paramIter->get_value(); + params[name] = value; + } + else if (*type == "float") + { + is_string = false; + double value = paramIter->get_value(); + params[name] = value; + } + } + + if (is_string) + { + std::string value = paramIter->get_text(); + params[name] = value; + } + } } } } - else if (v.first != "" && - v.first != "") - { - throw config_error(std::string("Unknown child node in 'Map': '") + - v.first + "'"); - } + } catch (const config_error & ex) { + ex.append_context(include); + throw; } - map.init_metawriters(); } -void map_parser::parse_style( Map & map, ptree const & sty ) +void map_parser::parse_style(Map & map, xml_node const& sty) { - std::ostringstream s(""); - s << "name," - << "filter-mode"; - ensure_attrs(sty, "Style", s.str()); - std::string name(""); try { - name = get_attr(sty, "name"); + name = sty.get_attr("name"); feature_type_style style; - filter_mode_e filter_mode = get_attr(sty, "filter-mode", FILTER_ALL); + filter_mode_e filter_mode = sty.get_attr("filter-mode", FILTER_ALL); style.set_filter_mode(filter_mode); - ptree::const_iterator ruleIter = sty.begin(); - ptree::const_iterator endRule = sty.end(); + xml_node::const_iterator ruleIter = sty.begin(); + xml_node::const_iterator endRule = sty.end(); for (; ruleIter!=endRule; ++ruleIter) { - ptree::value_type const& rule_tag = *ruleIter; - if (rule_tag.first == "Rule") + if (ruleIter->is("Rule")) { - parse_rule( style, rule_tag.second ); - } - else if (rule_tag.first != "" && - rule_tag.first != "" ) - { - throw config_error(std::string("Unknown child node in 'Style'. ") + - "Expected 'Rule' but got '" + rule_tag.first + "'"); + parse_rule(style, *ruleIter); } } map.insert_style(name, style); - } catch (const config_error & ex) { - if ( ! name.empty() ) { - ex.append_context(std::string("in style '") + name + "'"); - } - ex.append_context(std::string("in map '") + filename_ + "'"); + ex.append_context(std::string("in style '") + name + "'", sty); throw; } } -void map_parser::parse_metawriter(Map & map, ptree const & pt) +void map_parser::parse_metawriter(Map & map, xml_node const& pt) { - ensure_attrs(pt, "MetaWriter", "name,type,file,default-output,output-empty,pixel-coordinates"); std::string name(""); metawriter_ptr writer; try { - name = get_attr(pt, "name"); + name = pt.get_attr("name"); writer = metawriter_create(pt); map.insert_metawriter(name, writer); - } catch (const config_error & ex) { - if (!name.empty()) { - ex.append_context(std::string("in meta writer '") + name + "'"); - } - ex.append_context(std::string("in map '") + filename_ + "'"); - throw; + ex.append_context(std::string("in meta writer '") + name + "'", pt); } } -void map_parser::parse_fontset( Map & map, ptree const & fset ) +void map_parser::parse_fontset(Map & map, xml_node const& fset) { - ensure_attrs(fset, "FontSet", "name,Font"); std::string name(""); try { - name = get_attr(fset, "name"); + name = fset.get_attr("name"); font_set fontset(name); - ptree::const_iterator itr = fset.begin(); - ptree::const_iterator end = fset.end(); + xml_node::const_iterator itr = fset.begin(); + xml_node::const_iterator end = fset.end(); for (; itr != end; ++itr) { - ptree::value_type const& font_tag = *itr; - - if (font_tag.first == "Font") + if (itr->is("Font")) { - parse_font(fontset, font_tag.second); - } - else if (font_tag.first != "" && - font_tag.first != "" ) - { - throw config_error(std::string("Unknown child node in 'FontSet'. ") + - "Expected 'Font' but got '" + font_tag.first + "'"); + parse_font(fontset, *itr); } } @@ -625,19 +469,14 @@ void map_parser::parse_fontset( Map & map, ptree const & fset ) // when it's parsed fontsets_.insert(pair(name, fontset)); } catch (const config_error & ex) { - if ( ! name.empty() ) { - ex.append_context(std::string("in FontSet '") + name + "'"); - } - ex.append_context(std::string("in map '") + filename_ + "'"); + ex.append_context(std::string("in FontSet '") + name + "'", fset); throw; } } -void map_parser::parse_font(font_set & fset, ptree const & f) +void map_parser::parse_font(font_set &fset, xml_node const& f) { - ensure_attrs(f, "Font", "face-name"); - - optional face_name = get_opt_attr(f, "face-name"); + optional face_name = f.get_opt_attr("face-name"); if (face_name) { if ( strict_ ) @@ -648,89 +487,77 @@ void map_parser::parse_font(font_set & fset, ptree const & f) } else { - throw config_error(std::string("Must have 'face-name' set")); + throw config_error("Must have 'face-name' set", f); } } -void map_parser::parse_layer( Map & map, ptree const & lay ) +void map_parser::parse_layer(Map & map, xml_node const& lay) { std::string name; - std::ostringstream s(""); - s << "name," - << "srs," - << "status," - << "minzoom," - << "maxzoom," - << "queryable," - << "clear-label-cache," - << "cache-features," - << "group-by"; - ensure_attrs(lay, "Layer", s.str()); try { - name = get_attr(lay, "name", std::string("Unnamed")); + name = lay.get_attr("name", std::string("Unnamed")); // XXX if no projection is given inherit from map? [DS] - std::string srs = get_attr(lay, "srs", map.srs()); + std::string srs = lay.get_attr("srs", map.srs()); layer lyr(name, srs); - optional status = get_opt_attr(lay, "status"); + optional status = lay.get_opt_attr("status"); if (status) { - lyr.set_active( * status ); + lyr.set_active(* status ); } - optional min_zoom = get_opt_attr(lay, "minzoom"); + optional min_zoom = lay.get_opt_attr("minzoom"); if (min_zoom) { lyr.set_min_zoom( * min_zoom ); } - optional max_zoom = get_opt_attr(lay, "maxzoom"); + + optional max_zoom = lay.get_opt_attr("maxzoom"); if (max_zoom) { lyr.set_max_zoom( * max_zoom ); } - optional queryable = get_opt_attr(lay, "queryable"); + optional queryable = lay.get_opt_attr("queryable"); if (queryable) { lyr.set_queryable( * queryable ); } optional clear_cache = - get_opt_attr(lay, "clear-label-cache"); + lay.get_opt_attr("clear-label-cache"); if (clear_cache) { lyr.set_clear_label_cache( * clear_cache ); } optional cache_features = - get_opt_attr(lay, "cache-features"); + lay.get_opt_attr("cache-features"); if (cache_features) { lyr.set_cache_features( * cache_features ); } optional group_by = - get_opt_attr(lay, "group-by"); + lay.get_opt_attr("group-by"); if (group_by) { lyr.set_group_by( * group_by ); } - ptree::const_iterator itr2 = lay.begin(); - ptree::const_iterator end2 = lay.end(); + xml_node::const_iterator child = lay.begin(); + xml_node::const_iterator end = lay.end(); - for(; itr2 != end2; ++itr2) + for(; child != end; ++child) { - ptree::value_type const& child = *itr2; - if (child.first == "StyleName") + if (child->is("StyleName")) { - ensure_attrs(child.second, "StyleName", "none"); - std::string style_name = get_value(child.second, "style name"); + std::string style_name = child->get_text(); if (style_name.empty()) { std::ostringstream ss; @@ -745,11 +572,10 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) lyr.add_style(style_name); } } - else if (child.first == "Datasource") + else if (child->is("Datasource")) { - ensure_attrs(child.second, "Datasource", "base"); parameters params; - optional base = get_opt_attr( child.second, "base" ); + optional base = child->get_opt_attr("base"); if( base ) { std::map::const_iterator base_itr = datasource_templates_.find(*base); @@ -757,27 +583,16 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) params = base_itr->second; } - ptree::const_iterator paramIter = child.second.begin(); - ptree::const_iterator endParam = child.second.end(); + xml_node::const_iterator paramIter = child->begin(); + xml_node::const_iterator endParam = child->end(); for (; paramIter != endParam; ++paramIter) { - ptree const& param = paramIter->second; - - if (paramIter->first == "Parameter") + if (paramIter->is("Parameter")) { - ensure_attrs(param, "Parameter", "name"); - std::string name = get_attr(param, "name"); - std::string value = get_value( param, - "datasource parameter"); + std::string name = paramIter->get_attr("name"); + std::string value = paramIter->get_text(); params[name] = value; } - else if( paramIter->first != "" && - paramIter->first != "" ) - { - throw config_error(std::string("Unknown child node in ") + - "'Datasource'. Expected 'Parameter' but got '" + - paramIter->first + "'"); - } } boost::optional base_param = params.get("base"); @@ -794,171 +609,153 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) lyr.set_datasource_parameters(params); } - else if (child.first != "" && - child.first != "") - { - throw config_error(std::string("Unknown child node in 'Layer'. ") + - "Expected 'StyleName' or 'Datasource' but got '" + - child.first + "'"); - } } - map.addLayer(lyr); - } catch (const config_error & ex) { - if ( ! name.empty() ) + if (!name.empty()) { - ex.append_context(std::string("(encountered during parsing of layer '") + name + "' in map '" + filename_ + "')"); + ex.append_context(std::string(" encountered during parsing of layer '") + name + "'", lay); } throw; } } -void map_parser::parse_rule( feature_type_style & style, ptree const & r ) +void map_parser::parse_rule(feature_type_style & style, xml_node const& r) { - ensure_attrs(r, "Rule", "name"); std::string name; try { - name = get_attr( r, "name", std::string()); + name = r.get_attr("name", std::string()); rule rule(name); - optional filter_expr = - get_opt_child( r, "Filter"); - if (filter_expr) + xml_node const* child = r.get_opt_child("Filter"); + if (child) { - rule.set_filter(parse_expr(*filter_expr)); + rule.set_filter(child->get_value()); } - if (has_child(r, "ElseFilter")) + if (r.has_child("ElseFilter")) { rule.set_else(true); } - if (has_child(r, "AlsoFilter")) + if (r.has_child("AlsoFilter")) { rule.set_also(true); } - optional min_scale = - get_opt_child(r, "MinScaleDenominator"); - if (min_scale) + child = r.get_opt_child("MinScaleDenominator"); + if (child) { - rule.set_min_scale(*min_scale); + rule.set_min_scale(child->get_value()); } - optional max_scale = - get_opt_child(r, "MaxScaleDenominator"); - if (max_scale) + child = r.get_opt_child("MaxScaleDenominator"); + if (child) { - rule.set_max_scale(*max_scale); + rule.set_max_scale(child->get_value()); } - ptree::const_iterator symIter = r.begin(); - ptree::const_iterator endSym = r.end(); + xml_node::const_iterator symIter = r.begin(); + xml_node::const_iterator endSym = r.end(); for( ;symIter != endSym; ++symIter) { - ptree::value_type const& sym = *symIter; - if ( sym.first == "PointSymbolizer") + if ( symIter->is("PointSymbolizer")) { - parse_point_symbolizer( rule, sym.second ); + parse_point_symbolizer(rule, *symIter); } - else if ( sym.first == "LinePatternSymbolizer") + else if (symIter->is("LinePatternSymbolizer")) { - parse_line_pattern_symbolizer( rule, sym.second ); + parse_line_pattern_symbolizer(rule, *symIter); } - else if ( sym.first == "PolygonPatternSymbolizer") + else if (symIter->is("PolygonPatternSymbolizer")) { - parse_polygon_pattern_symbolizer( rule, sym.second ); + parse_polygon_pattern_symbolizer(rule, *symIter); } - else if ( sym.first == "TextSymbolizer") + else if (symIter->is("TextSymbolizer")) { - parse_text_symbolizer( rule, sym.second ); + parse_text_symbolizer(rule, *symIter); } - else if ( sym.first == "ShieldSymbolizer") + else if (symIter->is("ShieldSymbolizer")) { - parse_shield_symbolizer( rule, sym.second ); + parse_shield_symbolizer(rule, *symIter); } - else if ( sym.first == "LineSymbolizer") + else if (symIter->is("LineSymbolizer")) { - parse_line_symbolizer( rule, sym.second ); + parse_line_symbolizer(rule, *symIter); } - else if ( sym.first == "PolygonSymbolizer") + else if (symIter->is("PolygonSymbolizer")) { - parse_polygon_symbolizer( rule, sym.second ); + parse_polygon_symbolizer(rule, *symIter); } - else if ( sym.first == "BuildingSymbolizer") + else if (symIter->is("BuildingSymbolizer")) { - parse_building_symbolizer( rule, sym.second ); + parse_building_symbolizer(rule, *symIter); } - else if ( sym.first == "RasterSymbolizer") + else if (symIter->is("RasterSymbolizer")) { - parse_raster_symbolizer( rule, sym.second ); + parse_raster_symbolizer( rule, *symIter); } - else if ( sym.first == "MarkersSymbolizer") + else if (symIter->is("MarkersSymbolizer")) { - parse_markers_symbolizer(rule, sym.second); - } - - else if ( sym.first != "MinScaleDenominator" && - sym.first != "MaxScaleDenominator" && - sym.first != "Filter" && - sym.first != "ElseFilter" && - sym.first != "AlsoFilter" && - sym.first != "" && - sym.first != "" ) - { - throw config_error(std::string("Unknown symbolizer '") + - sym.first + "'"); + parse_markers_symbolizer(rule, *symIter); } } - style.add_rule(rule); } catch (const config_error & ex) { - if ( ! name.empty() ) + if (!name.empty() ) { - ex.append_context(std::string("in rule '") + name + "' in map '" + filename_ + "')"); + ex.append_context(std::string("in rule '") + name + "'", r); } throw; } } -void map_parser::parse_metawriter_in_symbolizer(symbolizer_base &sym, ptree const &pt) +void map_parser::parse_metawriter_in_symbolizer(symbolizer_base &sym, xml_node const &pt) { - optional writer = get_opt_attr(pt, "meta-writer"); + optional writer = pt.get_opt_attr("meta-writer"); if (!writer) return; - optional output = get_opt_attr(pt, "meta-output"); + optional output = pt.get_opt_attr("meta-output"); sym.add_metawriter(*writer, output); } -void map_parser::parse_point_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym) { try { - std::stringstream s; - s << "file,base,allow-overlap,ignore-placement,opacity,placement,transform,meta-writer,meta-output"; + optional file = sym.get_opt_attr("file"); + optional base = sym.get_opt_attr("base"); + optional allow_overlap = sym.get_opt_attr("allow-overlap"); + optional ignore_placement = sym.get_opt_attr("ignore-placement"); + optional opacity = sym.get_opt_attr("opacity"); + optional transform_wkt = sym.get_opt_attr("transform"); - optional file = get_opt_attr(sym, "file"); - optional base = get_opt_attr(sym, "base"); - optional allow_overlap = - get_opt_attr(sym, "allow-overlap"); - optional ignore_placement = - get_opt_attr(sym, "ignore-placement"); - optional opacity = - get_opt_attr(sym, "opacity"); - - optional transform_wkt = get_opt_attr(sym, "transform"); + point_symbolizer symbol; + if (allow_overlap) + { + symbol.set_allow_overlap( * allow_overlap ); + } + if (opacity) + { + symbol.set_opacity( * opacity ); + } + if (ignore_placement) + { + symbol.set_ignore_placement( * ignore_placement ); + } + point_placement_e placement = + sym.get_attr("placement", CENTROID_POINT_PLACEMENT); + symbol.set_point_placement( placement ); if (file) { - ensure_attrs(sym, "PointSymbolizer", s.str()); try { if( base ) @@ -972,23 +769,7 @@ void map_parser::parse_point_symbolizer( rule & rule, ptree const & sym ) *file = ensure_relative_to_xml(file); - point_symbolizer symbol(parse_path(*file)); - - if (allow_overlap) - { - symbol.set_allow_overlap( * allow_overlap ); - } - if (opacity) - { - symbol.set_opacity( * opacity ); - } - if (ignore_placement) - { - symbol.set_ignore_placement( * ignore_placement ); - } - point_placement_e placement = - get_attr(sym, "placement", CENTROID_POINT_PLACEMENT); - symbol.set_point_placement( placement ); + symbol.set_filename(parse_path(*file)); if (transform_wkt) { @@ -1007,9 +788,6 @@ void map_parser::parse_point_symbolizer( rule & rule, ptree const & sym ) tr.store_to(&matrix[0]); symbol.set_transform(matrix); } - - parse_metawriter_in_symbolizer(symbol, sym); - rule.append(symbol); } catch (image_reader_exception const & ex ) { @@ -1024,65 +802,29 @@ void map_parser::parse_point_symbolizer( rule & rule, ptree const & sym ) std::clog << "### WARNING: " << msg << endl; } } - - } - else - { - ensure_attrs(sym, "PointSymbolizer", s.str()); - point_symbolizer symbol; - - if (allow_overlap) - { - symbol.set_allow_overlap( * allow_overlap ); - } - if (opacity) - { - symbol.set_opacity( * opacity ); - } - if (ignore_placement) - { - symbol.set_ignore_placement( * ignore_placement ); - } - point_placement_e placement = - get_attr(sym, "placement", CENTROID_POINT_PLACEMENT); - symbol.set_point_placement( placement ); - - parse_metawriter_in_symbolizer(symbol, sym); - rule.append(symbol); } + parse_metawriter_in_symbolizer(symbol, sym); + rule.append(symbol); } catch (const config_error & ex) { - ex.append_context("in PointSymbolizer"); + ex.append_context("in PointSymbolizer", sym); throw; } } -void map_parser::parse_markers_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& sym) { try { std::string filename(""); - optional file = get_opt_attr(sym, "file"); - optional base = get_opt_attr(sym, "base"); - optional transform_wkt = get_opt_attr(sym, "transform"); - - std::stringstream s; - //s << "file,opacity,spacing,max-error,allow-overlap,placement,"; - s << "file,base,transform,fill,opacity," - << "spacing,max-error,allow-overlap," - << "width,height,placement,marker-type," - << "stroke,stroke-width,stroke-opacity,stroke-linejoin," - << "stroke-linecap,stroke-dashoffset,stroke-dasharray," - // note: stroke-gamma intentionally left off here as markers do not support them - << "meta-writer,meta-output"; - ensure_attrs(sym, "MarkersSymbolizer", s.str()); + optional file = sym.get_opt_attr("file"); + optional base = sym.get_opt_attr("base"); + optional transform_wkt = sym.get_opt_attr("transform"); if (file) { - //s << "base,transform"; - //ensure_attrs(sym, "MarkersSymbolizer", s.str()); try { if (base) @@ -1109,14 +851,9 @@ void map_parser::parse_markers_symbolizer( rule & rule, ptree const & sym ) } } } - /*else - { - //s << "fill,marker-type,width,height"; - //ensure_attrs(sym, "MarkersSymbolizer", s.str()); - }*/ markers_symbolizer symbol(parse_path(filename)); - optional opacity = get_opt_attr(sym, "opacity"); + optional opacity = sym.get_opt_attr("opacity"); if (opacity) symbol.set_opacity( *opacity ); if (transform_wkt) @@ -1137,17 +874,17 @@ void map_parser::parse_markers_symbolizer( rule & rule, ptree const & sym ) symbol.set_transform(matrix); } - optional c = get_opt_color_attr(sym, "fill"); + optional c = sym.get_opt_attr("fill"); if (c) symbol.set_fill(*c); - optional spacing = get_opt_attr(sym, "spacing"); + optional spacing = sym.get_opt_attr("spacing"); if (spacing) symbol.set_spacing(*spacing); - optional max_error = get_opt_attr(sym, "max-error"); + optional max_error = sym.get_opt_attr("max-error"); if (max_error) symbol.set_max_error(*max_error); - optional allow_overlap = get_opt_attr(sym, "allow-overlap"); + optional allow_overlap = sym.get_opt_attr("allow-overlap"); if (allow_overlap) symbol.set_allow_overlap(*allow_overlap); - optional w = get_opt_attr(sym, "width"); - optional h = get_opt_attr(sym, "height"); + optional w = sym.get_opt_attr("width"); + optional h = sym.get_opt_attr("height"); if (w && h) { symbol.set_width(*w); @@ -1169,7 +906,7 @@ void map_parser::parse_markers_symbolizer( rule & rule, ptree const & sym ) parse_stroke(strk,sym); symbol.set_stroke(strk); - marker_placement_e placement = get_attr(sym, "placement", MARKER_LINE_PLACEMENT); + marker_placement_e placement = sym.get_attr("placement", MARKER_LINE_PLACEMENT); symbol.set_marker_placement( placement ); marker_type_e dfl_marker_type = ARROW; @@ -1177,7 +914,7 @@ void map_parser::parse_markers_symbolizer( rule & rule, ptree const & sym ) if (placement == MARKER_POINT_PLACEMENT) dfl_marker_type = ELLIPSE; - marker_type_e marker_type = get_attr(sym, "marker-type", dfl_marker_type); + marker_type_e marker_type = sym.get_attr("marker-type", dfl_marker_type); symbol.set_marker_type( marker_type ); parse_metawriter_in_symbolizer(symbol, sym); @@ -1185,18 +922,17 @@ void map_parser::parse_markers_symbolizer( rule & rule, ptree const & sym ) } catch (const config_error & ex) { - ex.append_context("in MarkersSymbolizer"); + ex.append_context("in MarkersSymbolizer", sym); throw; } } -void map_parser::parse_line_pattern_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_line_pattern_symbolizer( rule & rule, xml_node const & sym ) { - ensure_attrs(sym, "LinePatternSymbolizer", "file,base,meta-writer,meta-output"); try { - std::string file = get_attr(sym, "file"); - optional base = get_opt_attr(sym, "base"); + std::string file = sym.get_attr("file"); + optional base = sym.get_opt_attr("base"); try { @@ -1232,19 +968,18 @@ void map_parser::parse_line_pattern_symbolizer( rule & rule, ptree const & sym ) } catch (const config_error & ex) { - ex.append_context("in LinePatternSymbolizer"); + ex.append_context("in LinePatternSymbolizer", sym); throw; } } void map_parser::parse_polygon_pattern_symbolizer( rule & rule, - ptree const & sym ) + xml_node const & sym ) { - ensure_attrs(sym, "PolygonPatternSymbolizer", "file,base,alignment,gamma,meta-writer,meta-output"); try { - std::string file = get_attr(sym, "file"); - optional base = get_opt_attr(sym, "base"); + std::string file = sym.get_attr("file"); + optional base = sym.get_opt_attr("base"); try { @@ -1262,15 +997,15 @@ void map_parser::parse_polygon_pattern_symbolizer( rule & rule, polygon_pattern_symbolizer symbol(parse_path(file)); // pattern alignment - pattern_alignment_e p_alignment = get_attr(sym, "alignment",LOCAL_ALIGNMENT); + pattern_alignment_e p_alignment = sym.get_attr("alignment",LOCAL_ALIGNMENT); symbol.set_alignment(p_alignment); // gamma - optional gamma = get_opt_attr(sym, "gamma"); + optional gamma = sym.get_opt_attr("gamma"); if (gamma) symbol.set_gamma(*gamma); // gamma method - optional gamma_method = get_opt_attr(sym, "gamma-method"); + optional gamma_method = sym.get_opt_attr("gamma-method"); if (gamma_method) symbol.set_gamma_method(*gamma_method); parse_metawriter_in_symbolizer(symbol, sym); @@ -1292,40 +1027,25 @@ void map_parser::parse_polygon_pattern_symbolizer( rule & rule, } catch (const config_error & ex) { - ex.append_context("in PolygonPatternSymbolizer"); + ex.append_context("in PolygonPatternSymbolizer", sym); throw; } } -void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_text_symbolizer( rule & rule, xml_node const& sym ) { - std::stringstream s_common; - s_common << "name,face-name,fontset-name,size,fill,orientation," - << "dx,dy,placement,vertical-alignment,halo-fill," - << "halo-radius,text-ratio,wrap-width,wrap-before," - << "wrap-character,text-transform,line-spacing," - << "label-position-tolerance,character-spacing," - << "spacing,minimum-distance,minimum-padding,minimum-path-length," - << "avoid-edges,allow-overlap,opacity,max-char-angle-delta," - << "horizontal-alignment,justify-alignment"; - - std::stringstream s_symbolizer; - s_symbolizer << s_common.str() << ",placements,placement-type," - << "meta-writer,meta-output"; - - ensure_attrs(sym, "TextSymbolizer", s_symbolizer.str()); try { text_placements_ptr placement_finder; - optional placement_type = get_opt_attr(sym, "placement-type"); + optional placement_type = sym.get_opt_attr("placement-type"); if (placement_type) { placement_finder = placements::registry::instance()->from_xml(*placement_type, sym, fontsets_); } else { - placement_finder = text_placements_ptr(boost::make_shared()); + placement_finder = boost::make_shared(); placement_finder->defaults.from_xml(sym, fontsets_); } if (strict_ && - !placement_finder->defaults.format.fontset.size()) + !placement_finder->defaults.format.fontset.size()) ensure_font_face(placement_finder->defaults.format.face_name); text_symbolizer text_symbol = text_symbolizer(placement_finder); @@ -1334,46 +1054,30 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym ) } catch (const config_error & ex) { - ex.append_context("in TextSymbolizer"); + ex.append_context("in TextSymbolizer", sym); throw; } } -void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& sym ) { - std::string s_common( - "name,face-name,fontset-name,size,fill,orientation," - "dx,dy,placement,vertical-alignment,halo-fill," - "halo-radius,text-ratio,wrap-width,wrap-before," - "wrap-character,text-transform,line-spacing," - "label-position-tolerance,character-spacing," - "spacing,minimum-distance,minimum-padding,minimum-path-length," - "avoid-edges,allow-overlap,opacity,max-char-angle-delta," - "horizontal-alignment,justify-alignment"); - - std::string s_symbolizer(s_common + ",file,base," - "transform,shield-dx,shield-dy,text-opacity," - "unlock-image" - "placements,placement-type,meta-writer,meta-output"); - - ensure_attrs(sym, "ShieldSymbolizer", s_symbolizer); try { text_placements_ptr placement_finder; - optional placement_type = get_opt_attr(sym, "placement-type"); + optional placement_type = sym.get_opt_attr("placement-type"); if (placement_type) { placement_finder = placements::registry::instance()->from_xml(*placement_type, sym, fontsets_); } else { - placement_finder = text_placements_ptr(boost::make_shared()); + placement_finder = boost::make_shared(); } placement_finder->defaults.from_xml(sym, fontsets_); if (strict_ && - !placement_finder->defaults.format.fontset.size()) + !placement_finder->defaults.format.fontset.size()) ensure_font_face(placement_finder->defaults.format.face_name); shield_symbolizer shield_symbol = shield_symbolizer(placement_finder); /* Symbolizer specific attributes. */ - optional transform_wkt = get_opt_attr(sym, "transform"); + optional transform_wkt = sym.get_opt_attr("transform"); if (transform_wkt) { agg::trans_affine tr; @@ -1391,12 +1095,12 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym ) shield_symbol.set_transform(matrix); } // shield displacement - double shield_dx = get_attr(sym, "shield-dx", 0.0); - double shield_dy = get_attr(sym, "shield-dy", 0.0); + double shield_dx = sym.get_attr("shield-dx", 0.0); + double shield_dy = sym.get_attr("shield-dy", 0.0); shield_symbol.set_shield_displacement(shield_dx,shield_dy); // opacity - optional opacity = get_opt_attr(sym, "opacity"); + optional opacity = sym.get_opt_attr("opacity"); if (opacity) { shield_symbol.set_opacity(*opacity); @@ -1405,7 +1109,7 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym ) // text-opacity // TODO: Could be problematic because it is named opacity in TextSymbolizer but opacity has a diffrent meaning here. optional text_opacity = - get_opt_attr(sym, "text-opacity"); + sym.get_opt_attr("text-opacity"); if (text_opacity) { shield_symbol.set_text_opacity( * text_opacity ); @@ -1413,7 +1117,7 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym ) // unlock_image optional unlock_image = - get_opt_attr(sym, "unlock-image"); + sym.get_opt_attr("unlock-image"); if (unlock_image) { shield_symbol.set_unlock_image( * unlock_image ); @@ -1421,8 +1125,8 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym ) parse_metawriter_in_symbolizer(shield_symbol, sym); - std::string image_file = get_attr(sym, "file"); - optional base = get_opt_attr(sym, "base"); + std::string image_file = sym.get_attr("file"); + optional base = sym.get_opt_attr("base"); try { @@ -1455,47 +1159,47 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym ) } catch (const config_error & ex) { - ex.append_context("in ShieldSymbolizer"); + ex.append_context("in ShieldSymbolizer", sym); throw; } } -void map_parser::parse_stroke(stroke & strk, ptree const & sym) +void map_parser::parse_stroke(stroke & strk, xml_node const & sym) { // stroke color - optional c = get_opt_color_attr(sym, "stroke"); + optional c = sym.get_opt_attr("stroke"); if (c) strk.set_color(*c); // stroke-width - optional width = get_opt_attr(sym, "stroke-width"); + optional width = sym.get_opt_attr("stroke-width"); if (width) strk.set_width(*width); // stroke-opacity - optional opacity = get_opt_attr(sym, "stroke-opacity"); + optional opacity = sym.get_opt_attr("stroke-opacity"); if (opacity) strk.set_opacity(*opacity); // stroke-linejoin - optional line_join = get_opt_attr(sym, "stroke-linejoin"); + optional line_join = sym.get_opt_attr("stroke-linejoin"); if (line_join) strk.set_line_join(*line_join); // stroke-linecap - optional line_cap = get_opt_attr(sym, "stroke-linecap"); + optional line_cap = sym.get_opt_attr("stroke-linecap"); if (line_cap) strk.set_line_cap(*line_cap); // stroke-gamma - optional gamma = get_opt_attr(sym, "stroke-gamma"); + optional gamma = sym.get_opt_attr("stroke-gamma"); if (gamma) strk.set_gamma(*gamma); // stroke-gamma-method - optional gamma_method = get_opt_attr(sym, "stroke-gamma-method"); + optional gamma_method = sym.get_opt_attr("stroke-gamma-method"); if (gamma_method) strk.set_gamma_method(*gamma_method); // stroke-dashoffset - optional dash_offset = get_opt_attr(sym, "stroke-dashoffset"); + optional dash_offset = sym.get_opt_attr("stroke-dashoffset"); if (dash_offset) strk.set_dash_offset(*dash_offset); // stroke-dasharray - optional str = get_opt_attr(sym,"stroke-dasharray"); + optional str = sym.get_opt_attr("stroke-dasharray"); if (str) { tokenizer<> tok (*str); @@ -1535,15 +1239,8 @@ void map_parser::parse_stroke(stroke & strk, ptree const & sym) } } -void map_parser::parse_line_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_line_symbolizer( rule & rule, xml_node const & sym ) { - std::stringstream s; - s << "stroke,stroke-width,stroke-opacity,stroke-linejoin," - << "stroke-linecap,stroke-gamma,stroke-dash-offset,stroke-dasharray," - << "rasterizer," - << "meta-writer,meta-output"; - - ensure_attrs(sym, "LineSymbolizer", s.str()); try { stroke strk; @@ -1551,8 +1248,8 @@ void map_parser::parse_line_symbolizer( rule & rule, ptree const & sym ) line_symbolizer symbol = line_symbolizer(strk); // rasterizer method - line_rasterizer_e rasterizer = get_attr(sym, "rasterizer", RASTERIZER_FULL); - //optional rasterizer_method = get_opt_attr(sym, "full"); + line_rasterizer_e rasterizer = sym.get_attr("rasterizer", RASTERIZER_FULL); + //optional rasterizer_method = sym.get_opt_attr("full"); symbol.set_rasterizer(rasterizer); parse_metawriter_in_symbolizer(symbol, sym); @@ -1560,116 +1257,107 @@ void map_parser::parse_line_symbolizer( rule & rule, ptree const & sym ) } catch (const config_error & ex) { - ex.append_context("in LineSymbolizer"); + ex.append_context("in LineSymbolizer", sym); throw; } } -void map_parser::parse_polygon_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_polygon_symbolizer( rule & rule, xml_node const & sym ) { - ensure_attrs(sym, "PolygonSymbolizer", "fill,fill-opacity,gamma,gamma-method,meta-writer,meta-output"); try { polygon_symbolizer poly_sym; // fill - optional fill = get_opt_color_attr(sym, "fill"); + optional fill = sym.get_opt_attr("fill"); if (fill) poly_sym.set_fill(*fill); // fill-opacity - optional opacity = get_opt_attr(sym, "fill-opacity"); + optional opacity = sym.get_opt_attr("fill-opacity"); if (opacity) poly_sym.set_opacity(*opacity); // gamma - optional gamma = get_opt_attr(sym, "gamma"); + optional gamma = sym.get_opt_attr("gamma"); if (gamma) poly_sym.set_gamma(*gamma); // gamma method - optional gamma_method = get_opt_attr(sym, "gamma-method"); + optional gamma_method = sym.get_opt_attr("gamma-method"); if (gamma_method) poly_sym.set_gamma_method(*gamma_method); - + // smooth value + optional smooth = sym.get_opt_attr("smooth"); + if (smooth) poly_sym.set_smooth(*smooth); + parse_metawriter_in_symbolizer(poly_sym, sym); rule.append(poly_sym); } catch (const config_error & ex) { - ex.append_context("in PolygonSymbolizer"); + ex.append_context("in PolygonSymbolizer", sym); throw; } } -void map_parser::parse_building_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_building_symbolizer( rule & rule, xml_node const & sym ) { - ensure_attrs(sym, "PolygonSymbolizer", "fill,fill-opacity,height,meta-writer,meta-output"); try { building_symbolizer building_sym; // fill - optional fill = get_opt_color_attr(sym, "fill"); + optional fill = sym.get_opt_attr("fill"); if (fill) building_sym.set_fill(*fill); // fill-opacity - optional opacity = get_opt_attr(sym, "fill-opacity"); + optional opacity = sym.get_opt_attr("fill-opacity"); if (opacity) building_sym.set_opacity(*opacity); // height - optional height = get_opt_attr(sym, "height"); - if (height) building_sym.set_height(parse_expr(*height)); + optional height = sym.get_opt_attr("height"); + if (height) building_sym.set_height(*height); parse_metawriter_in_symbolizer(building_sym, sym); rule.append(building_sym); } catch (const config_error & ex) { - ex.append_context("in BuildingSymbolizer"); + ex.append_context("in BuildingSymbolizer", sym); throw; } } -void map_parser::parse_raster_symbolizer( rule & rule, ptree const & sym ) +void map_parser::parse_raster_symbolizer( rule & rule, xml_node const & sym ) { - // no support for meta-writer,meta-output - ensure_attrs(sym, "RasterSymbolizer", "mode,scaling,opacity,filter-factor,mesh-size"); try { raster_symbolizer raster_sym; // mode - optional mode = get_opt_attr(sym, "mode"); + optional mode = sym.get_opt_attr("mode"); if (mode) raster_sym.set_mode(*mode); // scaling - optional scaling = get_opt_attr(sym, "scaling"); + optional scaling = sym.get_opt_attr("scaling"); if (scaling) raster_sym.set_scaling(*scaling); // opacity - optional opacity = get_opt_attr(sym, "opacity"); + optional opacity = sym.get_opt_attr("opacity"); if (opacity) raster_sym.set_opacity(*opacity); // filter factor - optional filter_factor = get_opt_attr(sym, "filter-factor"); + optional filter_factor = sym.get_opt_attr("filter-factor"); if (filter_factor) raster_sym.set_filter_factor(*filter_factor); // mesh-size - optional mesh_size = get_opt_attr(sym, "mesh-size"); + optional mesh_size = sym.get_opt_attr("mesh-size"); if (mesh_size) raster_sym.set_mesh_size(*mesh_size); - ptree::const_iterator cssIter = sym.begin(); - ptree::const_iterator endCss = sym.end(); + xml_node::const_iterator cssIter = sym.begin(); + xml_node::const_iterator endCss = sym.end(); for(; cssIter != endCss; ++cssIter) { - ptree::value_type const& css_tag = *cssIter; - - if (css_tag.first == "RasterColorizer") + if (cssIter->is("RasterColorizer")) { raster_colorizer_ptr colorizer = boost::make_shared(); raster_sym.set_colorizer(colorizer); - parse_raster_colorizer(colorizer, css_tag.second); - } - else if (css_tag.first != "" && - css_tag.first != "" ) - { - throw config_error(std::string("Unknown child node. ") + - "Expected 'RasterColorizer' but got '" + css_tag.first + "'"); + parse_raster_colorizer(colorizer, *cssIter); } } //Note: raster_symbolizer doesn't support metawriters @@ -1677,20 +1365,19 @@ void map_parser::parse_raster_symbolizer( rule & rule, ptree const & sym ) } catch (const config_error & ex) { - ex.append_context("in RasterSymbolizer"); + ex.append_context("in RasterSymbolizer", sym); throw; } } void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc, - ptree const& node ) + xml_node const& node) { try { - ensure_attrs(node, "RasterColorizer", "default-mode,default-color,epsilon"); // mode colorizer_mode default_mode = - get_attr(node, "default-mode", COLORIZER_LINEAR); + node.get_attr("default-mode", COLORIZER_LINEAR); if(default_mode == COLORIZER_INHERIT) { throw config_error("RasterColorizer mode must not be INHERIT. "); @@ -1698,7 +1385,7 @@ void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc, rc->set_default_mode( default_mode ); // default colour - optional default_color = get_opt_color_attr(node, "default-color"); + optional default_color = node.get_opt_attr("default-color"); if (default_color) { rc->set_default_color( *default_color ); @@ -1706,7 +1393,7 @@ void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc, // epsilon - optional eps = get_opt_attr(node, "epsilon"); + optional eps = node.get_opt_attr("epsilon"); if (eps) { if(*eps < 0) { @@ -1716,31 +1403,27 @@ void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc, } - ptree::const_iterator stopIter = node.begin(); - ptree::const_iterator endStop = node.end(); + xml_node::const_iterator stopIter = node.begin(); + xml_node::const_iterator endStop = node.end(); float maximumValue = -std::numeric_limits::max(); for(; stopIter != endStop; ++stopIter) { - ptree::value_type const& stop_tag = *stopIter; - ptree const & stop = stopIter->second; - - if (stop_tag.first == "stop") + if (stopIter->is("stop")) { - ensure_attrs(stop_tag.second, "stop", "color,mode,value,label"); // colour is optional. - optional stopcolor = get_opt_color_attr(stop, "color"); + optional stopcolor = stopIter->get_opt_attr("color"); if (!stopcolor) { *stopcolor = *default_color; } // mode default to INHERIT colorizer_mode mode = - get_attr(stop, "mode", COLORIZER_INHERIT); + stopIter->get_attr("mode", COLORIZER_INHERIT); // value is required, and it must be bigger than the previous optional value = - get_opt_attr(stop, "value"); + stopIter->get_opt_attr("value"); if(!value) { throw config_error("stop tag missing value"); @@ -1752,7 +1435,7 @@ void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc, maximumValue = *value; optional label = - get_opt_attr(stop, "label"); + stopIter->get_opt_attr("label"); //append the stop colorizer_stop tmpStop; @@ -1764,17 +1447,11 @@ void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc, rc->add_stop(tmpStop); } - else if (stop_tag.first != "" && - stop_tag.first != "" ) - { - throw config_error(std::string("Unknown child node. ") + - "Expected 'stop' but got '" + stop_tag.first + "'"); - } } } catch (const config_error & ex) { - ex.append_context("in RasterColorizer"); + ex.append_context("in RasterColorizer", node); throw; } } @@ -1814,44 +1491,45 @@ std::string map_parser::ensure_relative_to_xml( boost::optional opt return *opt_path; } -void map_parser::ensure_attrs(ptree const& sym, std::string name, std::string attrs) +void map_parser::find_unused_nodes(xml_node const& root) { - typedef ptree::key_type::value_type Ch; - optional attribs = sym.get_child_optional( boost::property_tree::xml_parser::xmlattr() ); - if (attribs) + std::stringstream error_message; + find_unused_nodes_recursive(root, error_message); + if (!error_message.str().empty()) { - std::set attr_set; - boost::split(attr_set, attrs, boost::is_any_of(",")); - std::ostringstream s(""); - s << "### " << name << " properties warning: "; - int missing = 0; - for (ptree::const_iterator it = attribs.get().begin(); it != attribs.get().end(); ++it) + throw config_error("The following nodes or attributes were not processed while parsing the xml file:" + error_message.str()); + } +} + +void map_parser::find_unused_nodes_recursive(xml_node const& node, std::stringstream &error_message) +{ + if (!node.processed()) + { + if (node.is_text()) { + error_message << "\n* text '" << node.text() << "'"; + } else { + error_message << "\n* node '" << node.name() << "' in line " << node.line(); + } + return; //All attributes and children are automatically unprocessed, too. + } + xml_node::attribute_map const& attr = node.get_attributes(); + xml_node::attribute_map::const_iterator aitr = attr.begin(); + xml_node::attribute_map::const_iterator aend = attr.end(); + for (;aitr!=aend; aitr++) + { + if (!aitr->second.processed) { - std::string name = it->first; - bool found = (attr_set.find(name) != attr_set.end()); - if (!found) - { - if (missing) - { - s << ","; - } - s << "'" << name << "'"; - ++missing; - } - } - if (missing) { - if (missing > 1) - { - s << " are"; - } - else - { - s << " is"; - } - s << " invalid, acceptable values are:\n'" << attrs << "'\n"; - std::clog << s.str(); + error_message << "\n* attribute '" << aitr->first << + "' with value '" << aitr->second.value << + "' in line " << node.line(); } } + xml_node::const_iterator itr = node.begin(); + xml_node::const_iterator end = node.end(); + for (; itr!=end; itr++) + { + find_unused_nodes_recursive(*itr, error_message); + } } } // end of namespace mapnik diff --git a/src/map.cpp b/src/map.cpp index 5af404a62..661c5c819 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -588,7 +588,7 @@ featureset_ptr Map::query_point(unsigned index, double x, double y) const featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y)); if (fs) return boost::make_shared >(fs, - hit_test_filter(x,y,tol)); + hit_test_filter(x,y,tol)); } } catch (...) @@ -634,7 +634,7 @@ featureset_ptr Map::query_map_point(unsigned index, double x, double y) const featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y)); if (fs) return boost::make_shared >(fs, - hit_test_filter(x,y,tol)); + hit_test_filter(x,y,tol)); } } catch (...) diff --git a/src/metawriter_factory.cpp b/src/metawriter_factory.cpp index 3157171b9..2c2a5973b 100644 --- a/src/metawriter_factory.cpp +++ b/src/metawriter_factory.cpp @@ -22,15 +22,15 @@ //$Id$ #include -#include - #include #include +#include +#include +#include #include #include -using boost::property_tree::ptree; using boost::optional; using std::string; @@ -38,20 +38,21 @@ namespace mapnik { metawriter_ptr -metawriter_create(const boost::property_tree::ptree &pt) { +metawriter_create(xml_node const& pt) +{ metawriter_ptr writer; - string type = get_attr(pt, "type"); + string type = pt.get_attr("type"); - optional properties = get_opt_attr(pt, "default-output"); + optional properties = pt.get_opt_attr("default-output"); if (type == "json") { - string file = get_attr(pt, "file"); + string file = pt.get_attr("file"); metawriter_json_ptr json = boost::make_shared(properties, parse_path(file)); - optional output_empty = get_opt_attr(pt, "output-empty"); + optional output_empty = pt.get_opt_attr("output-empty"); if (output_empty) { json->set_output_empty(*output_empty); } - optional pixel_coordinates = get_opt_attr(pt, "pixel-coordinates"); + optional pixel_coordinates = pt.get_opt_attr("pixel-coordinates"); if (pixel_coordinates) { json->set_pixel_coordinates(*pixel_coordinates); } @@ -61,14 +62,16 @@ metawriter_create(const boost::property_tree::ptree &pt) { metawriter_inmem_ptr inmem = boost::make_shared(properties); writer = inmem; } else { - throw config_error(string("Unknown type '") + type + "'"); + throw config_error(string("Unknown type '") + type + "'", pt); } return writer; } void -metawriter_save(const metawriter_ptr &metawriter, ptree &metawriter_node, bool explicit_defaults) { +metawriter_save(const metawriter_ptr &metawriter, + boost::property_tree::ptree &metawriter_node, bool explicit_defaults) +{ metawriter_json *json = dynamic_cast(metawriter.get()); if (json) { diff --git a/src/palette.cpp b/src/palette.cpp index 29d4120d4..6125d8808 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include +#include namespace mapnik { diff --git a/src/placement_finder.cpp b/src/placement_finder.cpp index f68597edb..387323323 100644 --- a/src/placement_finder.cpp +++ b/src/placement_finder.cpp @@ -269,9 +269,9 @@ void placement_finder::find_line_breaks() // wrap text at first wrap_char after (default) the wrap width or immediately before the current word if ((c == '\n') || (line_width > 0 && - ((line_width > wrap_at && !ci.format->wrap_before) || + ((line_width > wrap_at && !ci.format->wrap_before) || ((line_width + last_wrap_char_width + word_width) > wrap_at && ci.format->wrap_before)) ) - ) + ) { add_line(line_width, line_height, first_line); line_breaks_.push_back(last_wrap_char_pos); @@ -440,8 +440,8 @@ void placement_finder::find_point_placement(double label_x, if (!detector_.extent().intersects(e) || (!p.allow_overlap && - !detector_.has_point_placement(e, pi.get_actual_minimum_distance()))) - { + !detector_.has_point_placement(e, pi.get_actual_minimum_distance()))) + { return; } @@ -675,10 +675,10 @@ void placement_finder::find_line_placements(PathT & shape_path) template std::auto_ptr placement_finder::get_placement_offset(std::vector const& path_positions, - std::vector const& path_distances, - int & orientation, - unsigned index, - double distance) + std::vector const& path_distances, + int & orientation, + unsigned index, + double distance) { //Check that the given distance is on the given index and find the correct index and distance if not while (distance < 0 && index > 1) @@ -718,10 +718,10 @@ std::auto_ptr placement_finder::get_placement_offset(std:: } std::auto_ptr current_placement( - new text_path((old_x + dx*distance/segment_length), - (old_y + dy*distance/segment_length) - ) - ); + new text_path((old_x + dx*distance/segment_length), + (old_y + dy*distance/segment_length) + ) + ); double angle = atan2(-dy, dx); @@ -830,7 +830,7 @@ std::auto_ptr placement_finder::get_placement_offset(std:: render_angle += M_PI; } current_placement->add_node(&ci, - render_x - current_placement->center.x, + render_x - current_placement->center.x, -render_y + current_placement->center.y, render_angle); @@ -870,7 +870,7 @@ std::auto_ptr placement_finder::get_placement_offset(std:: template bool placement_finder::test_placement(std::auto_ptr const& current_placement, - int orientation) + int orientation) { //Create and test envelopes bool status = true; @@ -909,8 +909,8 @@ bool placement_finder::test_placement(std::auto_ptr const& if (!detector_.extent().intersects(e) || (!p.allow_overlap && !detector_.has_placement(e, info_.get_string(), pi.get_actual_minimum_distance()) + ) ) - ) { //std::clog << "No Intersects:" << !dimensions_.intersects(e) << ": " << e << " @ " << dimensions_ << std::endl; //std::clog << "No Placements:" << !detector_.has_placement(e, info.get_string(), p.minimum_distance) << std::endl; diff --git a/src/polygon_symbolizer.cpp b/src/polygon_symbolizer.cpp index 7009e586c..7c783a12d 100644 --- a/src/polygon_symbolizer.cpp +++ b/src/polygon_symbolizer.cpp @@ -32,14 +32,16 @@ polygon_symbolizer::polygon_symbolizer() fill_(color(128,128,128)), opacity_(1.0), gamma_(1.0), - gamma_method_(GAMMA_POWER) {} + gamma_method_(GAMMA_POWER), + smooth_(0.0) {} polygon_symbolizer::polygon_symbolizer(color const& fill) : symbolizer_base(), fill_(fill), opacity_(1.0), gamma_(1.0), - gamma_method_(GAMMA_POWER) {} + gamma_method_(GAMMA_POWER), + smooth_(0.0) {} color const& polygon_symbolizer::get_fill() const { @@ -81,4 +83,14 @@ gamma_method_e polygon_symbolizer::get_gamma_method() const return gamma_method_; } +void polygon_symbolizer::set_smooth(double smooth) +{ + smooth_ = smooth; +} + +double polygon_symbolizer::smooth() const +{ + return smooth_; +} + } diff --git a/src/processed_text.cpp b/src/processed_text.cpp index 3a6949487..921e528c6 100644 --- a/src/processed_text.cpp +++ b/src/processed_text.cpp @@ -1,4 +1,28 @@ +/***************************************************************************** + * + * 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 + * + *****************************************************************************/ + #include +#include + namespace mapnik { @@ -43,7 +67,7 @@ string_info &processed_text::get_string_info() { if (!p.fontset.get_name().empty()) { - throw config_error("Unable to find specified font set '" + p.face_name + "'"); + throw config_error("Unable to find specified font set '" + p.fontset.get_name() + "'"); } else if (!p.face_name.empty()) { throw config_error("Unable to find specified font face '" + p.face_name + "'"); } else { diff --git a/src/rapidxml_loader.cpp b/src/rapidxml_loader.cpp new file mode 100644 index 000000000..4a9293f54 --- /dev/null +++ b/src/rapidxml_loader.cpp @@ -0,0 +1,171 @@ + + +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 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 + * + *****************************************************************************/ + +#ifdef HAVE_LIBXML2 +#error HAVE_LIBXML2 defined but compiling rapidxml_loader.cpp! +#endif + +// mapnik +#include +#include +#include +#include + +// boost +#include +#include + +// stl +#include +#include + +using namespace std; +namespace rapidxml = boost::property_tree::detail::rapidxml; +namespace mapnik +{ +class rapidxml_loader : boost::noncopyable +{ +public: + rapidxml_loader(const char *encoding = NULL) : + filename_() + { + + } + + ~rapidxml_loader() + { + } + + void load(const std::string & filename, xml_node &node) + { + filename_ = filename; + std::basic_ifstream stream(filename.c_str()); + if (!stream) + { + throw config_error("Could not load map file", 0, filename); + } +// TODO: stream.imbue(loc); + load(stream, node); + } + + void load(std::basic_istream &stream, xml_node &node) + { + stream.unsetf(std::ios::skipws); + std::vector v(std::istreambuf_iterator(stream.rdbuf()), + std::istreambuf_iterator()); + if (!stream.good()) + { + throw config_error("Could not load map file", 0, filename_); + } + v.push_back(0); // zero-terminate + try + { + // Parse using appropriate flags + const int f_tws = rapidxml::parse_normalize_whitespace + | rapidxml::parse_trim_whitespace; + rapidxml::xml_document<> doc; + doc.parse(&v.front()); + + for (rapidxml::xml_node *child = doc.first_node(); + child; child = child->next_sibling()) + { + populate_tree(child, node); + } + } + catch (rapidxml::parse_error &e) + { + long line = static_cast( + std::count(&v.front(), e.where(), '\n') + 1); + throw config_error(e.what(), line, filename_); + } + } + + void load_string(const std::string & buffer, xml_node &node, std::string const & base_path ) + { + +// if (!base_path.empty()) +// { +// boost::filesystem::path path(base_path); +// if (!boost::filesystem::exists(path)) { +// throw config_error(string("Could not locate base_path '") + +// base_path + "': file or directory does not exist"); +// } +// } + + + load(buffer, node); + } +private: + void populate_tree(rapidxml::xml_node *cur_node, xml_node &node) + { + switch (cur_node->type()) + { + case rapidxml::node_element: + { + xml_node &new_node = node.add_child((char *)cur_node->name(), 0, false); + // Copy attributes + for (rapidxml::xml_attribute *attr = cur_node->first_attribute(); + attr; attr = attr->next_attribute()) + { + new_node.add_attribute(attr->name(), attr->value()); + } + + // Copy children + for (rapidxml::xml_node *child = cur_node->first_node(); + child; child = child->next_sibling()) + { + populate_tree(child, new_node); + } + } + break; + + // Data nodes + case rapidxml::node_data: + case rapidxml::node_cdata: + { + std::string trimmed = boost::algorithm::trim_copy(std::string(cur_node->value())); + if (trimmed.empty()) break; //Don't add empty text nodes + node.add_child(trimmed, 0, true); + } + break; + default: + break; + } + } +private: + std::string filename_; +}; + +void read_xml(std::string const & filename, xml_node &node) +{ + rapidxml_loader loader; + loader.load(filename, node); +} +void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path) +{ + rapidxml_loader loader; + loader.load_string(str, node, base_path); +} + +} // end of namespace mapnik diff --git a/src/save_map.cpp b/src/save_map.cpp index 286038cf8..ab02e587c 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -125,6 +125,10 @@ public: { set_attr( sym_node, "gamma-method", sym.get_gamma_method() ); } + if ( sym.smooth() != dfl.smooth() || explicit_defaults_ ) + { + set_attr( sym_node, "smooth", sym.smooth() ); + } add_metawriter_attributes(sym_node, sym); } diff --git a/src/svg_parser.cpp b/src/svg_parser.cpp index 2107aa646..4d4d30a98 100644 --- a/src/svg_parser.cpp +++ b/src/svg_parser.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "agg_ellipse.h" #include "agg_rounded_rect.h" diff --git a/src/symbolizer_helpers.cpp b/src/symbolizer_helpers.cpp index 8c59ff272..cfcc83902 100644 --- a/src/symbolizer_helpers.cpp +++ b/src/symbolizer_helpers.cpp @@ -51,7 +51,7 @@ bool text_symbolizer_helper::next_line_placement() geo_itr_ = geometries_to_process_.begin(); continue; //Reexecute size check } - + typedef agg::conv_clip_polyline clipped_geometry_type; typedef coord_transform2 path_type; clipped_geometry_type clipped(**geo_itr_); diff --git a/src/text_placements/dummy.cpp b/src/text_placements/dummy.cpp index 36c74597a..989fb542b 100644 --- a/src/text_placements/dummy.cpp +++ b/src/text_placements/dummy.cpp @@ -35,8 +35,7 @@ bool text_placement_info_dummy::next() text_placement_info_ptr text_placements_dummy::get_placement_info( double scale_factor) const { - return text_placement_info_ptr(boost::make_shared( - this, scale_factor)); + return boost::make_shared(this, scale_factor); } } //ns mapnik diff --git a/src/text_placements/list.cpp b/src/text_placements/list.cpp index a9bc7aa83..7aea6812d 100644 --- a/src/text_placements/list.cpp +++ b/src/text_placements/list.cpp @@ -20,9 +20,14 @@ * *****************************************************************************/ +//mapnik #include +#include + +//boost #include + namespace mapnik { @@ -58,8 +63,7 @@ text_symbolizer_properties & text_placements_list::get(unsigned i) text_placement_info_ptr text_placements_list::get_placement_info(double scale_factor) const { - return text_placement_info_ptr( - boost::make_shared(this, scale_factor)); + return boost::make_shared(this, scale_factor); } text_placements_list::text_placements_list() : text_placements(), list_(0) @@ -83,20 +87,19 @@ unsigned text_placements_list::size() const return list_.size(); } -text_placements_ptr text_placements_list::from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets) +text_placements_ptr text_placements_list::from_xml(xml_node const &xml, fontset_map const & fontsets) { using boost::property_tree::ptree; text_placements_list *list = new text_placements_list; text_placements_ptr ptr = text_placements_ptr(list); list->defaults.from_xml(xml, fontsets); - ptree::const_iterator itr = xml.begin(); - ptree::const_iterator end = xml.end(); + xml_node::const_iterator itr = xml.begin(); + xml_node::const_iterator end = xml.end(); for( ;itr != end; ++itr) { - if ((itr->first.find('<') != std::string::npos) || (itr->first != "Placement")) continue; -//TODO: ensure_attrs(symIter->second, "TextSymbolizer/Placement", s_common.str()); + if (itr->is_text() || !itr->is("Placement")) continue; text_symbolizer_properties &p = list->add(); - p.from_xml(itr->second, fontsets); + p.from_xml(*itr, fontsets); //TODO: if (strict_ && // !p.format.fontset.size()) // ensure_font_face(p.format.face_name); diff --git a/src/text_placements/registry.cpp b/src/text_placements/registry.cpp index 621c161b3..cf12b6213 100644 --- a/src/text_placements/registry.cpp +++ b/src/text_placements/registry.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace mapnik { @@ -46,10 +47,10 @@ void registry::register_name(std::string name, from_xml_function_ptr ptr, bool o } } -text_placements_ptr registry::from_xml(std::string name, const boost::property_tree::ptree &xml, fontset_map const& fontsets) +text_placements_ptr registry::from_xml(std::string name, xml_node const& xml, fontset_map const& fontsets) { std::map::const_iterator itr = map_.find(name); - if (itr == map_.end()) throw config_error("Unknown placement-type '" + name + "'"); + if (itr == map_.end()) throw config_error("Unknown placement-type '" + name + "'", xml); return itr->second(xml, fontsets); } } //ns formatting diff --git a/src/text_placements/simple.cpp b/src/text_placements/simple.cpp index 598082e55..cefa199fa 100644 --- a/src/text_placements/simple.cpp +++ b/src/text_placements/simple.cpp @@ -23,6 +23,7 @@ // mapnik #include #include +#include // boost #include @@ -102,8 +103,7 @@ bool text_placement_info_simple::next_position_only() text_placement_info_ptr text_placements_simple::get_placement_info( double scale_factor) const { - return text_placement_info_ptr( - boost::make_shared(this, scale_factor)); + return boost::make_shared(this, scale_factor); } /** Position string: [POS][SIZE] @@ -144,10 +144,12 @@ void text_placements_simple::set_positions(std::string positions) (direction_name[push_back(phoenix::ref(direction_), _1)] % ',') >> *(',' >> qi::float_[push_back(phoenix::ref(text_sizes_), _1)]), space ); - if (first != last) { + if (first != last) + { std::cerr << "WARNING: Could not parse text_placement_simple placement string ('" << positions << "').\n"; } - if (direction_.size() == 0) { + if (direction_.size() == 0) + { std::cerr << "WARNING: text_placements_simple with no valid placements! ('"<< positions<<"')\n"; } } @@ -167,10 +169,10 @@ std::string text_placements_simple::get_positions() return positions_; //TODO: Build string from data in direction_ and text_sizes_ } -text_placements_ptr text_placements_simple::from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets) +text_placements_ptr text_placements_simple::from_xml(xml_node const &xml, fontset_map const & fontsets) { - text_placements_ptr ptr = text_placements_ptr(boost::make_shared( - get_attr(xml, "placements", "X"))); + text_placements_ptr ptr = boost::make_shared( + xml.get_attr("placements", "X")); ptr->defaults.from_xml(xml, fontsets); return ptr; } diff --git a/src/text_properties.cpp b/src/text_properties.cpp index 4b1ebfbd2..4587cb5e4 100644 --- a/src/text_properties.cpp +++ b/src/text_properties.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include // boost #include @@ -79,45 +81,45 @@ formatting::node_ptr text_symbolizer_properties::format_tree() const return tree_; } -void text_symbolizer_properties::from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets) +void text_symbolizer_properties::from_xml(xml_node const &sym, fontset_map const & fontsets) { - optional placement_ = get_opt_attr(sym, "placement"); + optional placement_ = sym.get_opt_attr("placement"); if (placement_) label_placement = *placement_; - optional valign_ = get_opt_attr(sym, "vertical-alignment"); + optional valign_ = sym.get_opt_attr("vertical-alignment"); if (valign_) valign = *valign_; - optional text_ratio_ = get_opt_attr(sym, "text-ratio"); + optional text_ratio_ = sym.get_opt_attr("text-ratio"); if (text_ratio_) text_ratio = *text_ratio_; - optional wrap_width_ = get_opt_attr(sym, "wrap-width"); + optional wrap_width_ = sym.get_opt_attr("wrap-width"); if (wrap_width_) wrap_width = *wrap_width_; - optional label_position_tolerance_ = get_opt_attr(sym, "label-position-tolerance"); + optional label_position_tolerance_ = sym.get_opt_attr("label-position-tolerance"); if (label_position_tolerance_) label_position_tolerance = *label_position_tolerance_; - optional spacing_ = get_opt_attr(sym, "spacing"); + optional spacing_ = sym.get_opt_attr("spacing"); if (spacing_) label_spacing = *spacing_; - optional minimum_distance_ = get_opt_attr(sym, "minimum-distance"); + optional minimum_distance_ = sym.get_opt_attr("minimum-distance"); if (minimum_distance_) minimum_distance = *minimum_distance_; - optional min_padding_ = get_opt_attr(sym, "minimum-padding"); + optional min_padding_ = sym.get_opt_attr("minimum-padding"); if (min_padding_) minimum_padding = *min_padding_; - optional min_path_length_ = get_opt_attr(sym, "minimum-path-length"); + optional min_path_length_ = sym.get_opt_attr("minimum-path-length"); if (min_path_length_) minimum_path_length = *min_path_length_; - optional avoid_edges_ = get_opt_attr(sym, "avoid-edges"); + optional avoid_edges_ = sym.get_opt_attr("avoid-edges"); if (avoid_edges_) avoid_edges = *avoid_edges_; - optional allow_overlap_ = get_opt_attr(sym, "allow-overlap"); + optional allow_overlap_ = sym.get_opt_attr("allow-overlap"); if (allow_overlap_) allow_overlap = *allow_overlap_; - optional halign_ = get_opt_attr(sym, "horizontal-alignment"); + optional halign_ = sym.get_opt_attr("horizontal-alignment"); if (halign_) halign = *halign_; - optional jalign_ = get_opt_attr(sym, "justify-alignment"); + optional jalign_ = sym.get_opt_attr("justify-alignment"); if (jalign_) jalign = *jalign_; /* Attributes needing special care */ - optional orientation_ = get_opt_attr(sym, "orientation"); + optional orientation_ = sym.get_opt_attr("orientation"); if (orientation_) orientation = parse_expression(*orientation_, "utf8"); - optional dx = get_opt_attr(sym, "dx"); + optional dx = sym.get_opt_attr("dx"); if (dx) displacement.first = *dx; - optional dy = get_opt_attr(sym, "dy"); + optional dy = sym.get_opt_attr("dy"); if (dy) displacement.second = *dy; - optional max_char_angle_delta_ = get_opt_attr(sym, "max-char-angle-delta"); + optional max_char_angle_delta_ = sym.get_opt_attr("max-char-angle-delta"); if (max_char_angle_delta_) max_char_angle_delta=(*max_char_angle_delta_)*(M_PI/180); - optional name_ = get_opt_attr(sym, "name"); + optional name_ = sym.get_opt_attr("name"); if (name_) { std::clog << "### WARNING: Using 'name' in TextSymbolizer/ShieldSymbolizer is deprecated!\n"; set_old_style_expression(parse_expression(*name_, "utf8")); @@ -241,34 +243,34 @@ char_properties::char_properties() : } -void char_properties::from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets) +void char_properties::from_xml(xml_node const& sym, fontset_map const& fontsets) { - optional text_size_ = get_opt_attr(sym, "size"); + optional text_size_ = sym.get_opt_attr("size"); if (text_size_) text_size = *text_size_; - optional character_spacing_ = get_opt_attr(sym, "character-spacing"); + optional character_spacing_ = sym.get_opt_attr("character-spacing"); if (character_spacing_) character_spacing = *character_spacing_; - optional fill_ = get_opt_attr(sym, "fill"); + optional fill_ = sym.get_opt_attr("fill"); if (fill_) fill = *fill_; - optional halo_fill_ = get_opt_attr(sym, "halo-fill"); + optional halo_fill_ = sym.get_opt_attr("halo-fill"); if (halo_fill_) halo_fill = *halo_fill_; - optional halo_radius_ = get_opt_attr(sym, "halo-radius"); + optional halo_radius_ = sym.get_opt_attr("halo-radius"); if (halo_radius_) halo_radius = *halo_radius_; - optional wrap_before_ = get_opt_attr(sym, "wrap-before"); + optional wrap_before_ = sym.get_opt_attr("wrap-before"); if (wrap_before_) wrap_before = *wrap_before_; - optional tconvert_ = get_opt_attr(sym, "text-transform"); + optional tconvert_ = sym.get_opt_attr("text-transform"); if (tconvert_) text_transform = *tconvert_; - optional line_spacing_ = get_opt_attr(sym, "line-spacing"); + optional line_spacing_ = sym.get_opt_attr("line-spacing"); if (line_spacing_) line_spacing = *line_spacing_; - optional opacity_ = get_opt_attr(sym, "opacity"); + optional opacity_ = sym.get_opt_attr("opacity"); if (opacity_) text_opacity = *opacity_; - optional wrap_char_ = get_opt_attr(sym, "wrap-character"); + optional wrap_char_ = sym.get_opt_attr("wrap-character"); if (wrap_char_ && (*wrap_char_).size() > 0) wrap_char = ((*wrap_char_)[0]); - optional face_name_ = get_opt_attr(sym, "face-name"); + optional face_name_ = sym.get_opt_attr("face-name"); if (face_name_) { face_name = *face_name_; } - optional fontset_name_ = get_opt_attr(sym, "fontset-name"); + optional fontset_name_ = sym.get_opt_attr("fontset-name"); if (fontset_name_) { std::map::const_iterator itr = fontsets.find(*fontset_name_); if (itr != fontsets.end()) @@ -277,16 +279,16 @@ void char_properties::from_xml(boost::property_tree::ptree const &sym, fontset_m } else { - throw config_error("Unable to find any fontset named '" + *fontset_name_ + "'"); + throw config_error("Unable to find any fontset named '" + *fontset_name_ + "'", sym); } } if (!face_name.empty() && !fontset.get_name().empty()) { - throw config_error(std::string("Can't have both face-name and fontset-name")); + throw config_error("Can't have both face-name and fontset-name", sym); } if (face_name.empty() && fontset.get_name().empty()) { - throw config_error(std::string("Must have face-name or fontset-name")); + throw config_error("Must have face-name or fontset-name", sym); } } diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp new file mode 100644 index 000000000..ef61e9258 --- /dev/null +++ b/src/xml_tree.cpp @@ -0,0 +1,483 @@ +/***************************************************************************** + * + * 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 + * + *****************************************************************************/ + +//mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//boost +#include + +namespace mapnik +{ + +template +inline boost::optional fast_cast(xml_tree const& tree, std::string const& value) +{ + try + { + return boost::lexical_cast(value); + } + catch (boost::bad_lexical_cast const& ex) + { + return boost::optional(); + } +} + +template <> +inline boost::optional fast_cast(xml_tree const& tree, std::string const& value) +{ + int result; + if (mapnik::conversions::string2int(value, result)) + return boost::optional(result); + return boost::optional(); +} + +template <> +inline boost::optional fast_cast(xml_tree const& tree, std::string const& value) +{ + double result; + if (mapnik::conversions::string2double(value, result)) + return boost::optional(result); + return boost::optional(); +} + +template <> +inline boost::optional fast_cast(xml_tree const& tree, std::string const& value) +{ + float result; + if (mapnik::conversions::string2float(value, result)) + return boost::optional(result); + return boost::optional(); +} + +template <> +inline boost::optional fast_cast(xml_tree const& tree, std::string const& value) +{ + return value; +} + +template <> +inline boost::optional fast_cast(xml_tree const& tree, std::string const& value) +{ + mapnik::color c; + if (mapnik::color_factory::parse_from_string(c, value, tree.color_grammar)) + { + return c; + } + else + { + throw config_error("Failed to parse color '"+value+"'"); + } +} + +template <> +inline boost::optional fast_cast(xml_tree const& tree, std::string const& value) +{ + expression_ptr expr(boost::make_shared(true)); + if (expression_factory::parse_from_string(expr, value, tree.expr_grammar)) + { + return expr; + } else + { + throw mapnik::config_error("Failed to parse expression '" + value + "'"); + } +} + +/****************************************************************************/ + +class boolean; +template +struct name_trait +{ + static std::string name() + { + return ""; + } + // missing name_trait for type ... + // if you get here you are probably using a new type + // in the XML file. Just add a name trait for the new + // type below. + BOOST_STATIC_ASSERT( sizeof(T) == 0 ); +}; + +#define DEFINE_NAME_TRAIT( type, type_name ) \ + template <> \ + struct name_trait \ + { \ + static std::string name() { return std::string("type ") + type_name; } \ + }; + + +DEFINE_NAME_TRAIT( double, "double") +DEFINE_NAME_TRAIT( float, "float") +DEFINE_NAME_TRAIT( unsigned, "unsigned") +DEFINE_NAME_TRAIT( boolean, "boolean") +DEFINE_NAME_TRAIT( int, "integer" ) +DEFINE_NAME_TRAIT( std::string, "string" ) +DEFINE_NAME_TRAIT( color, "color" ) +DEFINE_NAME_TRAIT(expression_ptr, "expression_ptr" ) + +template +struct name_trait< mapnik::enumeration > +{ + typedef enumeration Enum; + + static std::string name() + { + std::string value_list("one of ["); + for (unsigned i = 0; i < Enum::MAX; ++i) + { + value_list += Enum::get_string( i ); + if ( i + 1 < Enum::MAX ) value_list += ", "; + } + value_list += "]"; + + return value_list; + } +}; + +/****************************************************************************/ + +xml_tree::xml_tree(std::string const& encoding) + : node_(*this, ""), + file_(), + tr_(encoding), + color_grammar(), + expr_grammar(tr_) +{ + node_.set_processed(true); //root node is always processed +} + +void xml_tree::set_filename(std::string fn) +{ + file_ = fn; +} + +std::string const& xml_tree::filename() const +{ + return file_; +} + +xml_node &xml_tree::root() +{ + return node_; +} + +/****************************************************************************/ +xml_attribute::xml_attribute(std::string const& value_) + : value(value_), processed(false) +{ + +} + +/****************************************************************************/ + +node_not_found::node_not_found(std::string node_name) + : node_name_(node_name) +{ + +} + +const char* node_not_found::what() const throw() +{ + return ("Node "+node_name_+ "not found").c_str(); +} + +node_not_found::~node_not_found() throw() +{ + +} + + +attribute_not_found::attribute_not_found( + std::string const& node_name, + std::string const& attribute_name) + : + node_name_(node_name), + attribute_name_(attribute_name) +{ + +} + +const char* attribute_not_found::what() const throw() +{ + return ("Attribute '" + attribute_name_ +"' not found in node '"+node_name_+ "'").c_str(); +} + +attribute_not_found::~attribute_not_found() throw() +{ + +} + +more_than_one_child::more_than_one_child(std::string const& node_name) + : node_name_(node_name) +{ + +} + +const char* more_than_one_child::what() const throw() +{ + return ("More than one child node in node '" + node_name_ +"'").c_str(); +} + +more_than_one_child::~more_than_one_child() throw() +{ + +} + +/****************************************************************************/ + +xml_node::xml_node(xml_tree &tree, std::string name, unsigned line, bool text_node) + : tree_(tree), + name_(name), + text_node_(text_node), + line_(line), + processed_(false) +{ + +} + +std::string xml_node::xml_text = ""; + +std::string const& xml_node::name() const +{ + if (!text_node_) + return name_; + else + return xml_text; +} + +std::string const& xml_node::text() const +{ + if (text_node_) + { + processed_ = true; + return name_; + } else + { + throw config_error("text() called on non-text node", *this); + } +} + +std::string const& xml_node::filename() const +{ + return tree_.filename(); +} + +bool xml_node::is_text() const +{ + return text_node_; +} + +bool xml_node::is(std::string const& name) const +{ + if (name_ == name) + { + processed_ = true; + return true; + } + return false; +} + +xml_node &xml_node::add_child(std::string const& name, unsigned line, bool text_node) +{ + children_.push_back(xml_node(tree_, name, line, text_node)); + return children_.back(); +} + +void xml_node::add_attribute(std::string const& name, std::string const& value) +{ + attributes_.insert(std::make_pair(name,xml_attribute(value))); +} + +xml_node::attribute_map const& xml_node::get_attributes() const +{ + return attributes_; +} + +void xml_node::set_processed(bool processed) const +{ + processed_ = processed; +} + +bool xml_node::processed() const +{ + return processed_; +} + +xml_node::const_iterator xml_node::begin() const +{ + return children_.begin(); +} + +xml_node::const_iterator xml_node::end() const +{ + return children_.end(); +} + +xml_node & xml_node::get_child(std::string const& name) +{ + std::list::iterator itr = children_.begin(); + std::list::iterator end = children_.end(); + for (; itr != end; itr++) + { + if (!(itr->text_node_) && itr->name_ == name) + { + itr->set_processed(true); + return *itr; + } + } + throw node_not_found(name); +} + +xml_node const& xml_node::get_child(std::string const& name) const +{ + xml_node const* node = get_opt_child(name); + if (!node) throw node_not_found(name); + return *node; +} + +xml_node const* xml_node::get_opt_child(std::string const& name) const +{ + const_iterator itr = children_.begin(); + const_iterator end = children_.end(); + for (; itr != end; itr++) + { + if (!(itr->text_node_) && itr->name_ == name) + { + itr->set_processed(true); + return &(*itr); + } + } + return 0; +} + +bool xml_node::has_child(std::string const& name) const +{ + return get_opt_child(name) != 0; +} + +template +boost::optional xml_node::get_opt_attr(std::string const& name) const +{ + std::map::const_iterator itr = attributes_.find(name); + if (itr == attributes_.end()) return boost::optional(); + itr->second.processed = true; + boost::optional result = fast_cast(tree_, itr->second.value); + if (!result) + { + throw config_error(std::string("Failed to parse attribute '") + + name + "'. Expected " + name_trait::name() + + " but got '" + itr->second.value + "'", *this); + } + return result; +} + +template +T xml_node::get_attr(std::string const& name, T const& default_value) const +{ + boost::optional value = get_opt_attr(name); + if (value) return *value; + return default_value; +} + +template +T xml_node::get_attr(std::string const& name) const +{ + boost::optional value = get_opt_attr(name); + if (value) return *value; + throw attribute_not_found(name_, name); +} + +std::string xml_node::get_text() const +{ + if (children_.size() == 0) + { + return ""; + } + if (children_.size() == 1) + { + return children_.front().text(); + } + throw more_than_one_child(name_); +} + + +template +T xml_node::get_value() const +{ + boost::optional result = fast_cast(tree_, get_text()); + if (!result) + { + throw config_error(std::string("Failed to parse value. Expected ") + + name_trait::name() + + " but got '" + get_text() + "'", *this); + } + return *result; +} + +unsigned xml_node::line() const +{ + return line_; +} + +#define compile_get_opt_attr(T) template boost::optional xml_node::get_opt_attr(std::string const&) const +#define compile_get_attr(T) template T xml_node::get_attr(std::string const&) const; template T xml_node::get_attr(std::string const&, T const&) const +#define compile_get_value(T) template T xml_node::get_value() const + +compile_get_opt_attr(boolean); +compile_get_opt_attr(std::string); +compile_get_opt_attr(unsigned); +compile_get_opt_attr(float); +compile_get_opt_attr(double); +compile_get_opt_attr(color); +compile_get_opt_attr(gamma_method_e); +compile_get_opt_attr(line_rasterizer_e); +compile_get_opt_attr(line_join_e); +compile_get_opt_attr(line_cap_e); +compile_get_opt_attr(text_transform_e); +compile_get_opt_attr(label_placement_e); +compile_get_opt_attr(vertical_alignment_e); +compile_get_opt_attr(horizontal_alignment_e); +compile_get_opt_attr(justify_alignment_e); +compile_get_opt_attr(expression_ptr); +compile_get_attr(std::string); +compile_get_attr(filter_mode_e); +compile_get_attr(point_placement_e); +compile_get_attr(marker_placement_e); +compile_get_attr(marker_type_e); +compile_get_attr(pattern_alignment_e); +compile_get_attr(line_rasterizer_e); +compile_get_attr(colorizer_mode); +compile_get_attr(double); +compile_get_value(int); +compile_get_value(double); +compile_get_value(expression_ptr); +} //ns mapnik diff --git a/tests/python_tests/object_test.py b/tests/python_tests/object_test.py index 2b08ac479..9c9787f4b 100644 --- a/tests/python_tests/object_test.py +++ b/tests/python_tests/object_test.py @@ -230,13 +230,8 @@ def test_map_init_from_string(): map_string = ''' diff --git a/tests/visual_tests/compare.py b/tests/visual_tests/compare.py index 21a627d99..414f49979 100644 --- a/tests/visual_tests/compare.py +++ b/tests/visual_tests/compare.py @@ -1,4 +1,4 @@ -import math, operator +#import math, operator import Image import sys @@ -27,6 +27,10 @@ def compare(fn1, fn2): return -1 diff = 0 pixels = im1.size[0] * im1.size[1] + delta_pixels = im2.size[0] * im2.size[1] - pixels + if delta_pixels != 0: + errors.append((fn1, delta_pixels)) + return delta_pixels im1 = im1.getdata() im2 = im2.getdata() for i in range(3, pixels - 1, 3): diff --git a/tests/visual_tests/shieldsymbolizer-1.xml b/tests/visual_tests/shieldsymbolizer-1.xml index 6f780d888..69ec6f2f5 100644 --- a/tests/visual_tests/shieldsymbolizer-1.xml +++ b/tests/visual_tests/shieldsymbolizer-1.xml @@ -1,6 +1,6 @@ - + My Style diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 67dc0d468..f899da1ea 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -50,7 +50,7 @@ def render(filename, width, height=100): return m if len(sys.argv) == 2: - files = [(sys.argv[1], 500)] + files = [(sys.argv[1], (500, 500))] elif len(sys.argv) > 2: files = [sys.argv[1:]]