diff --git a/.travis.yml b/.travis.yml index 2dc9e93f2..ba6ace47a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,11 +15,11 @@ before_install: # grab more recent gdal/proj - sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable # more recent boost - - sudo add-apt-repository -y ppa:mapnik/boost + - sudo add-apt-repository -y ppa:boost-latest/ppa - sudo apt-get update -y # upgrade compilers - sudo apt-get install -y gcc-4.8 g++-4.8 - - sudo apt-get install -y make libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libboost-thread-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libcairo-dev python-cairo-dev libsqlite3-dev + - sudo apt-get install -y make boost1.55 libgdal-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libcairo-dev python-cairo-dev libsqlite3-dev - wget http://mapnik.s3.amazonaws.com/deps/harfbuzz-0.9.24.tar.bz2 - tar xf harfbuzz-0.9.24.tar.bz2 - cd harfbuzz-0.9.24 diff --git a/benchmark/data/roads.xml b/benchmark/data/roads.xml index eddc42d24..f6d4a2155 100644 --- a/benchmark/data/roads.xml +++ b/benchmark/data/roads.xml @@ -52,7 +52,7 @@ +#include void render(mapnik::geometry_type & geom, mapnik::box2d const& extent, diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py index 934bf5a64..f98f1b60c 100644 --- a/bindings/python/mapnik/__init__.py +++ b/bindings/python/mapnik/__init__.py @@ -267,15 +267,17 @@ class _Path(Path,_injector): class _Datasource(Datasource,_injector): - def all_features(self,fields=None): + def all_features(self,fields=None,variables={}): query = Query(self.envelope()) + query.set_variables(variables); attributes = fields or self.fields() for fld in attributes: query.add_property_name(fld) return self.features(query).features - def featureset(self,fields=None): + def featureset(self,fields=None,variables={}): query = Query(self.envelope()) + query.set_variables(variables); attributes = fields or self.fields() for fld in attributes: query.add_property_name(fld) diff --git a/bindings/python/mapnik_expression.cpp b/bindings/python/mapnik_expression.cpp index d27be9bb5..fe64e6cd6 100644 --- a/bindings/python/mapnik_expression.cpp +++ b/bindings/python/mapnik_expression.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include "boost_std_shared_shim.hpp" +#include "python_to_value.hpp" // boost #include @@ -53,15 +54,15 @@ std::string expression_to_string_(mapnik::expr_node const& expr) return mapnik::to_expression_string(expr); } -mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::feature_impl const& f) +mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::feature_impl const& f, boost::python::dict const& d) { // will be auto-converted to proper python type by `mapnik_value_to_python` - return boost::apply_visitor(mapnik::evaluate(f),expr); + return boost::apply_visitor(mapnik::evaluate(f,mapnik::dict2attr(d)),expr); } -bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::feature_impl const& f) +bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::feature_impl const& f, boost::python::dict const& d) { - return boost::apply_visitor(mapnik::evaluate(f),expr).to_bool(); + return boost::apply_visitor(mapnik::evaluate(f,mapnik::dict2attr(d)),expr).to_bool(); } // path expression @@ -86,8 +87,8 @@ void export_expression() class_("Expression", "TODO" "",no_init) - .def("evaluate", &expression_evaluate_) - .def("to_bool", &expression_evaluate_to_bool_) + .def("evaluate", &expression_evaluate_,(arg("feature"),arg("variables")=boost::python::dict())) + .def("to_bool", &expression_evaluate_to_bool_,(arg("feature"),arg("variables")=boost::python::dict())) .def("__str__",&expression_to_string_); ; diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp index d89cbf33f..f6d4f1645 100644 --- a/bindings/python/mapnik_python.cpp +++ b/bindings/python/mapnik_python.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include "boost_std_shared_shim.hpp" +#include "python_to_value.hpp" #include // for keywords, arg, etc #include #include // for def @@ -182,7 +183,18 @@ void render(mapnik::Map const& map, python_unblock_auto_block b; mapnik::agg_renderer ren(map,image,scale_factor,offset_x, offset_y); ren.apply(); +} +void render_with_vars(mapnik::Map const& map, + mapnik::image_32& image, + boost::python::dict const& d) +{ + mapnik::attributes vars = mapnik::dict2attr(d); + mapnik::request req(map.width(),map.height(),map.get_current_extent()); + req.set_buffer_size(map.buffer_size()); + python_unblock_auto_block b; + mapnik::agg_renderer ren(map,req,vars,image,1,0,0); + ren.apply(); } void render_with_detector( @@ -259,7 +271,6 @@ void render6(mapnik::Map const& map, PycairoContext* py_context) mapnik::cairo_renderer ren(map,context); ren.apply(); } - void render_with_detector2( mapnik::Map const& map, PycairoContext* py_context, @@ -647,6 +658,7 @@ BOOST_PYTHON_MODULE(_mapnik) "\n" ); + def("render_with_vars",&render_with_vars); def("render", &render, render_overloads( "\n" diff --git a/bindings/python/mapnik_query.cpp b/bindings/python/mapnik_query.cpp index 503b1e570..1384adc20 100644 --- a/bindings/python/mapnik_query.cpp +++ b/bindings/python/mapnik_query.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include "boost_std_shared_shim.hpp" +#include "python_to_value.hpp" // boost #include @@ -69,6 +70,15 @@ struct names_to_list } }; +namespace { + + void set_variables(mapnik::query & q, boost::python::dict const& d) + { + mapnik::attributes vars = mapnik::dict2attr(d); + q.set_variables(vars); + } +} + void export_query() { using namespace boost::python; @@ -85,5 +95,6 @@ void export_query() return_value_policy()) ) .add_property("property_names", make_function(&query::property_names, return_value_policy()) ) - .def("add_property_name", &query::add_property_name); + .def("add_property_name", &query::add_property_name) + .def("set_variables",&set_variables); } diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index 87e0360f9..1aebf931a 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -125,10 +125,10 @@ struct NodeWrap: formatting::node, wrapper } - void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { python_block_auto_unblock b; - this->get_override("apply")(ptr(&p), ptr(&feature), ptr(&output)); + this->get_override("apply")(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output)); } virtual void add_expressions(expression_set &output) const @@ -163,85 +163,85 @@ struct TextNodeWrap: formatting::text_node, wrapper } - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { if(override o = this->get_override("apply")) { python_block_auto_unblock b; - o(ptr(&p), ptr(&feature), ptr(&output)); + o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output)); } else { - formatting::text_node::apply(p, feature, output); + formatting::text_node::apply(p, feature, vars, output); } } - void default_apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + void default_apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { - formatting::text_node::apply(p, feature, output); + formatting::text_node::apply(p, feature, vars, output); } }; struct FormatNodeWrap: formatting::format_node, wrapper { - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { if(override o = this->get_override("apply")) { python_block_auto_unblock b; - o(ptr(&p), ptr(&feature), ptr(&output)); + o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output)); } else { - formatting::format_node::apply(p, feature, output); + formatting::format_node::apply(p, feature, vars ,output); } } - void default_apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + void default_apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { - formatting::format_node::apply(p, feature, output); + formatting::format_node::apply(p, feature, vars, output); } }; struct ExprFormatWrap: formatting::expression_format, wrapper { - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { if(override o = this->get_override("apply")) { python_block_auto_unblock b; - o(ptr(&p), ptr(&feature), ptr(&output)); + o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output)); } else { - formatting::expression_format::apply(p, feature, output); + formatting::expression_format::apply(p, feature, vars, output); } } - void default_apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + void default_apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { - formatting::expression_format::apply(p, feature, output); + formatting::expression_format::apply(p, feature, vars, output); } }; struct LayoutNodeWrap: formatting::layout_node, wrapper { - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { if(override o = this->get_override("apply")) { python_block_auto_unblock b; - o(ptr(&p), ptr(&feature), ptr(&output)); + o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output)); } else { - formatting::layout_node::apply(p, feature, output); + formatting::layout_node::apply(p, feature, vars, output); } } - void default_apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + void default_apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { - formatting::layout_node::apply(p, feature, output); + formatting::layout_node::apply(p, feature, vars, output); } }; @@ -266,22 +266,22 @@ struct ListNodeWrap: formatting::list_node, wrapper /* TODO: Add constructor taking variable number of arguments. http://wiki.python.org/moin/boost.python/HowTo#A.22Raw.22_function */ - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { if(override o = this->get_override("apply")) { python_block_auto_unblock b; - o(ptr(&p), ptr(&feature), ptr(&output)); + o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output)); } else { - formatting::list_node::apply(p, feature, output); + formatting::list_node::apply(p, feature, vars, output); } } - void default_apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const + void default_apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { - formatting::list_node::apply(p, feature, output); + formatting::list_node::apply(p, feature, vars, output); } inline void IndexError(){ diff --git a/bindings/python/python_to_value.hpp b/bindings/python/python_to_value.hpp new file mode 100644 index 000000000..fd2eb4da2 --- /dev/null +++ b/bindings/python/python_to_value.hpp @@ -0,0 +1,90 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_PYTHON_BINDING_PYTHON_TO_VALUE +#define MAPNIK_PYTHON_BINDING_PYTHON_TO_VALUE + +// boost +#include + +// mapnik +#include +#include + + +namespace mapnik { + + static mapnik::attributes dict2attr(boost::python::dict const& d) + { + using namespace boost::python; + mapnik::attributes vars; + mapnik::transcoder tr_("utf8"); + boost::python::list keys=d.keys(); + for (int i=0; i < len(keys); ++i) + { + std::string key = extract(keys[i]); + object obj = d[key]; + if (PyUnicode_Check(obj.ptr())) + { + PyObject* temp = PyUnicode_AsUTF8String(obj.ptr()); + if (temp) + { + #if PY_VERSION_HEX >= 0x03000000 + char* c_str = PyBytes_AsString(temp); + #else + char* c_str = PyString_AsString(temp); + #endif + vars[key] = tr_.transcode(c_str); + Py_DecRef(temp); + } + continue; + } + + extract ex0(obj); + if (ex0.check()) + { + vars[key] = tr_.transcode(ex0().c_str()); + continue; + } + extract ex2(obj); + if (ex2.check()) + { + vars[key] = ex2(); + continue; + } + extract ex3(obj); + if (ex3.check()) + { + vars[key] = ex3(); + continue; + } + extract ex1(obj); + if (ex1.check()) + { + vars[key] = ex1(); + continue; + } + } + return vars; + } +} + +#endif // MAPNIK_PYTHON_BINDING_PYTHON_TO_VALUE diff --git a/include/mapnik/agg_helpers.hpp b/include/mapnik/agg_helpers.hpp index 457ebd2e8..188bf404d 100644 --- a/include/mapnik/agg_helpers.hpp +++ b/include/mapnik/agg_helpers.hpp @@ -61,9 +61,9 @@ void set_gamma_method(T & ras_ptr, double gamma, gamma_method_enum method) } template -void set_join_caps(Symbolizer const& sym, PathType & stroke, Feature const& feature) +void set_join_caps(Symbolizer const& sym, PathType & stroke, Feature const& feature, attributes const& vars) { - line_join_enum join = get(sym, keys::stroke_linejoin, feature, MITER_JOIN); + line_join_enum join = get(sym, keys::stroke_linejoin, feature, vars, MITER_JOIN); switch (join) { case MITER_JOIN: @@ -79,7 +79,7 @@ void set_join_caps(Symbolizer const& sym, PathType & stroke, Feature const& feat stroke.generator().line_join(agg::bevel_join); } - line_cap_enum cap = get(sym, keys::stroke_linecap, feature, BUTT_CAP); + line_cap_enum cap = get(sym, keys::stroke_linecap, feature, vars, BUTT_CAP); switch (cap) { @@ -96,9 +96,9 @@ void set_join_caps(Symbolizer const& sym, PathType & stroke, Feature const& feat template -void set_join_caps_aa(Symbolizer const& sym, Rasterizer & ras, Feature & feature) +void set_join_caps_aa(Symbolizer const& sym, Rasterizer & ras, Feature & feature, attributes const& vars) { - line_join_enum join = get(sym, keys::stroke_linejoin, feature, MITER_JOIN); + line_join_enum join = get(sym, keys::stroke_linejoin, feature, vars, MITER_JOIN); switch (join) { case MITER_JOIN: @@ -114,7 +114,7 @@ void set_join_caps_aa(Symbolizer const& sym, Rasterizer & ras, Feature & feature ras.line_join(agg::outline_no_join); } - line_cap_enum cap = get(sym, keys::stroke_linecap, feature, BUTT_CAP); + line_cap_enum cap = get(sym, keys::stroke_linecap, feature, vars, BUTT_CAP); switch (cap) { diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 5e6e43dd9..b16053dd4 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -73,7 +73,7 @@ public: agg_renderer(Map const &m, buffer_type & pixmap, std::shared_ptr detector, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); // pass in mapnik::request object to provide the mutable things per render - agg_renderer(Map const& m, request const& req, buffer_type & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); + agg_renderer(Map const& m, request const& req, attributes const& vars, buffer_type & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); ~agg_renderer(); void start_map_processing(Map const& map); void end_map_processing(Map const& map); @@ -142,6 +142,11 @@ public: return common_.scale_factor_; } + inline attributes const& variables() const + { + return common_.vars_; + } + inline box2d clipping_extent() const { if (common_.t_.offset() > 0) diff --git a/include/mapnik/attribute.hpp b/include/mapnik/attribute.hpp index b403bc7db..e280f2502 100644 --- a/include/mapnik/attribute.hpp +++ b/include/mapnik/attribute.hpp @@ -26,9 +26,11 @@ // mapnik #include #include +#include // stl #include +#include namespace mapnik { @@ -78,6 +80,8 @@ struct global_attribute } }; +typedef std::unordered_map attributes; + } #endif // MAPNIK_ATTRIBUTE_HPP diff --git a/include/mapnik/cairo_renderer.hpp b/include/mapnik/cairo_renderer.hpp index 5b101de48..645fbff49 100644 --- a/include/mapnik/cairo_renderer.hpp +++ b/include/mapnik/cairo_renderer.hpp @@ -58,17 +58,20 @@ class MAPNIK_DECL cairo_renderer_base : private mapnik::noncopyable protected: cairo_renderer_base(Map const& m, cairo_ptr const& cairo, + attributes const& vars, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); cairo_renderer_base(Map const& m, request const& req, cairo_ptr const& cairo, + attributes const& vars, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); cairo_renderer_base(Map const& m, cairo_ptr const& cairo, + attributes const& vars, std::shared_ptr detector, double scale_factor=1.0, unsigned offset_x=0, @@ -138,6 +141,11 @@ public: return common_.scale_factor_; } + inline attributes const& variables() const + { + return common_.vars_; + } + void render_marker(pixel_position const& pos, marker const& marker, agg::trans_affine const& mtx, @@ -165,6 +173,7 @@ public: unsigned offset_y=0); cairo_renderer(Map const& m, request const& req, + attributes const& vars, T const& obj, double scale_factor=1.0, unsigned offset_x=0, diff --git a/include/mapnik/expression_evaluator.hpp b/include/mapnik/expression_evaluator.hpp index 7da728301..b306b1f40 100644 --- a/include/mapnik/expression_evaluator.hpp +++ b/include/mapnik/expression_evaluator.hpp @@ -39,14 +39,16 @@ namespace mapnik { -template +template struct evaluate : boost::static_visitor { typedef T0 feature_type; typedef T1 value_type; + typedef T2 variable_type; - explicit evaluate(feature_type const& f) - : feature_(f) {} + explicit evaluate(feature_type const& f, variable_type const& v) + : feature_(f), + vars_(v) {} value_integer operator() (value_integer val) const { @@ -80,7 +82,12 @@ struct evaluate : boost::static_visitor value_type operator() (global_attribute const& attr) const { - return value_type();// shouldn't get here + auto itr = vars_.find(attr.name); + if (itr != vars_.end()) + { + return itr->second; + } + return value_type();// throw? } value_type operator() (geometry_type_attribute const& geom) const @@ -144,6 +151,7 @@ struct evaluate : boost::static_visitor } feature_type const& feature_; + variable_type const& vars_; }; } diff --git a/include/mapnik/feature_style_processor_impl.hpp b/include/mapnik/feature_style_processor_impl.hpp index 33cb5354e..8ebdcf63f 100644 --- a/include/mapnik/feature_style_processor_impl.hpp +++ b/include/mapnik/feature_style_processor_impl.hpp @@ -471,6 +471,7 @@ void feature_style_processor::prepare_layer(layer_rendering_material height/qh); query q(layer_ext,res,scale_denom,extent); + q.set_variables(p.variables()); if (p.attribute_collection_policy() == COLLECT_ALL) { @@ -643,6 +644,7 @@ void feature_style_processor::render_style( p.end_style_processing(*style); return; } + mapnik::attributes vars = p.variables(); feature_ptr feature; bool was_painted = false; while ((feature = features->next())) @@ -652,7 +654,7 @@ void feature_style_processor::render_style( for (rule const* r : rc.get_if_rules() ) { expression_ptr const& expr = r->get_filter(); - value_type result = boost::apply_visitor(evaluate(*feature),*expr); + value_type result = boost::apply_visitor(evaluate(*feature,vars),*expr); if (result.to_bool()) { was_painted = true; diff --git a/include/mapnik/grid/grid_marker_helpers.hpp b/include/mapnik/grid/grid_marker_helpers.hpp index 1f75e7192..2022e2df3 100644 --- a/include/mapnik/grid/grid_marker_helpers.hpp +++ b/include/mapnik/grid/grid_marker_helpers.hpp @@ -55,6 +55,7 @@ struct raster_markers_rasterizer_dispatch_grid Detector & detector, double scale_factor, mapnik::feature_impl & feature, + attributes const& vars, PixMapType & pixmap) : buf_(render_buffer), pixf_(buf_), @@ -66,29 +67,19 @@ struct raster_markers_rasterizer_dispatch_grid detector_(detector), scale_factor_(scale_factor), feature_(feature), + vars_(vars), pixmap_(pixmap), placed_(false) - { - // TODO - support basic binary operators - //pixf_.comp_op(static_cast(sym_.comp_op())); - } - - raster_markers_rasterizer_dispatch_grid(raster_markers_rasterizer_dispatch_grid &&d) - : buf_(d.buf_), pixf_(d.pixf_), renb_(d.renb_), ras_(d.ras_), src_(d.src_), - marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_), - scale_factor_(d.scale_factor_), feature_(d.feature_), pixmap_(d.pixmap_), - placed_(d.placed_) { } template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, false); - bool allow_overlap = get(sym_, keys::allow_overlap, false); - double spacing = get(sym_, keys::spacing, 100.0); - double max_error = get(sym_, keys::max_error, 0.2); + agg::scanline_bin sl_; + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); box2d bbox_(0,0, src_.width(),src_.height()); if (placement_method != MARKER_LINE_PLACEMENT || @@ -99,17 +90,23 @@ struct raster_markers_rasterizer_dispatch_grid if (path.type() == geometry_type::types::LineString) { if (!label::middle_point(path, x, y)) + { return; + } } else if (placement_method == MARKER_INTERIOR_PLACEMENT) { if (!label::interior_position(path, x, y)) + { return; + } } else { if (!label::centroid(path, x, y)) + { return; + } } agg::trans_affine matrix = marker_trans_; matrix.translate(x,y); @@ -131,6 +128,8 @@ struct raster_markers_rasterizer_dispatch_grid } else { + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); markers_placement placement(path, bbox_, marker_trans_, detector_, spacing * scale_factor_, max_error, @@ -153,6 +152,7 @@ struct raster_markers_rasterizer_dispatch_grid void render_raster_marker(agg::trans_affine const& marker_tr) { + agg::scanline_bin sl_; double width = src_.width(); double height = src_.height(); double p[8]; @@ -174,7 +174,6 @@ struct raster_markers_rasterizer_dispatch_grid } private: - agg::scanline_bin sl_; BufferType & buf_; PixFmt pixf_; RendererBase renb_; @@ -185,6 +184,7 @@ private: Detector & detector_; double scale_factor_; mapnik::feature_impl & feature_; + attributes const& vars_; PixMapType & pixmap_; bool placed_; }; @@ -208,6 +208,7 @@ struct vector_markers_rasterizer_dispatch_grid Detector & detector, double scale_factor, mapnik::feature_impl & feature, + attributes const& vars, PixMapType & pixmap) : buf_(render_buffer), pixf_(buf_), @@ -220,30 +221,20 @@ struct vector_markers_rasterizer_dispatch_grid detector_(detector), scale_factor_(scale_factor), feature_(feature), + vars_(vars), pixmap_(pixmap), placed_(false) - { - // TODO - //pixf_.comp_op(static_cast(sym_.comp_op())); - } - - vector_markers_rasterizer_dispatch_grid(vector_markers_rasterizer_dispatch_grid &&d) - : buf_(d.buf_), pixf_(d.pixf_), svg_renderer_(std::move(d.svg_renderer_)), ras_(d.ras_), - bbox_(d.bbox_), marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_), - scale_factor_(d.scale_factor_), feature_(d.feature_), pixmap_(d.pixmap_), - placed_(d.placed_) { } template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, false); - double spacing = get(sym_, keys::spacing, 100.0); - double max_error = get(sym_, keys::max_error, 0.2); - double opacity = get(sym_,keys::opacity, 1.0); - bool allow_overlap = get(sym_, keys::allow_overlap, false); + agg::scanline_bin sl_; + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + double opacity = get(sym_,keys::opacity, feature_, vars_, 1.0); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); if (placement_method != MARKER_LINE_PLACEMENT || path.type() == geometry_type::types::Point) @@ -253,17 +244,23 @@ struct vector_markers_rasterizer_dispatch_grid if (path.type() == geometry_type::types::LineString) { if (!label::middle_point(path, x, y)) + { return; + } } else if (placement_method == MARKER_INTERIOR_PLACEMENT) { if (!label::interior_position(path, x, y)) + { return; + } } else { if (!label::centroid(path, x, y)) + { return; + } } agg::trans_affine matrix = marker_trans_; matrix.translate(x,y); @@ -285,6 +282,8 @@ struct vector_markers_rasterizer_dispatch_grid } else { + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); markers_placement placement(path, bbox_, marker_trans_, detector_, spacing * scale_factor_, max_error, @@ -305,7 +304,6 @@ struct vector_markers_rasterizer_dispatch_grid } } private: - agg::scanline_bin sl_; BufferType & buf_; pixfmt_type pixf_; renderer_base renb_; @@ -317,10 +315,10 @@ private: Detector & detector_; double scale_factor_; mapnik::feature_impl & feature_; + attributes const& vars_; PixMapType & pixmap_; bool placed_; }; - } #endif diff --git a/include/mapnik/grid/grid_renderer.hpp b/include/mapnik/grid/grid_renderer.hpp index fe9e3e0ee..debc69dbc 100644 --- a/include/mapnik/grid/grid_renderer.hpp +++ b/include/mapnik/grid/grid_renderer.hpp @@ -68,7 +68,7 @@ public: typedef T buffer_type; typedef grid_renderer processor_impl_type; grid_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); - grid_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); + grid_renderer(Map const& m, request const& req, attributes const& vars, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); ~grid_renderer(); void start_map_processing(Map const& map); void end_map_processing(Map const& map); @@ -131,6 +131,11 @@ public: return common_.scale_factor_; } + inline attributes const& variables() const + { + return common_.vars_; + } + private: buffer_type & pixmap_; const std::unique_ptr ras_ptr; diff --git a/include/mapnik/group/group_symbolizer_helper.hpp b/include/mapnik/group/group_symbolizer_helper.hpp index fb9619cfc..62d161236 100644 --- a/include/mapnik/group/group_symbolizer_helper.hpp +++ b/include/mapnik/group/group_symbolizer_helper.hpp @@ -55,6 +55,7 @@ public: group_symbolizer_helper(group_symbolizer const& sym, feature_impl const& feature, + attributes const& vars, proj_transform const& prj_trans, unsigned width, unsigned height, diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index 8241778d9..3c7c9fa9f 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -34,6 +34,7 @@ #include // for svg_storage_type #include #include +#include // agg #include "agg_ellipse.h" @@ -74,6 +75,8 @@ struct vector_markers_rasterizer_dispatch agg::trans_affine const& marker_trans, markers_symbolizer const& sym, Detector & detector, + feature_impl & feature, + attributes const& vars, double scale_factor, bool snap_to_pixels) : buf_(render_buffer), @@ -85,26 +88,22 @@ struct vector_markers_rasterizer_dispatch marker_trans_(marker_trans), sym_(sym), detector_(detector), + feature_(feature), + vars_(vars), scale_factor_(scale_factor), snap_to_pixels_(snap_to_pixels) { - pixf_.comp_op(get(sym_, keys::comp_op, agg::comp_op_src_over)); - } - - vector_markers_rasterizer_dispatch(vector_markers_rasterizer_dispatch &&d) - : buf_(d.buf_), pixf_(d.pixf_), svg_renderer_(std::move(d.svg_renderer_)), ras_(d.ras_), - bbox_(d.bbox_), marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_), - scale_factor_(d.scale_factor_), snap_to_pixels_(d.snap_to_pixels_) - { + pixf_.comp_op(get(sym_, keys::comp_op, feature_, vars_, agg::comp_op_src_over)); } template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, false); - bool allow_overlap = get(sym_, keys::allow_overlap, false); - double opacity = get(sym_,keys::opacity, 1.0); + agg::scanline_u8 sl_; + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + double opacity = get(sym_,keys::opacity, feature_, vars_, 1.0); if (placement_method != MARKER_LINE_PLACEMENT || path.type() == mapnik::geometry_type::types::Point) @@ -114,17 +113,23 @@ struct vector_markers_rasterizer_dispatch if (path.type() == mapnik::geometry_type::types::LineString) { if (!label::middle_point(path, x, y)) + { return; + } } else if (placement_method == MARKER_INTERIOR_PLACEMENT) { if (!label::interior_position(path, x, y)) + { return; + } } else { if (!label::centroid(path, x, y)) + { return; + } } agg::trans_affine matrix = marker_trans_; matrix.translate(x,y); @@ -149,8 +154,8 @@ struct vector_markers_rasterizer_dispatch } else { - double spacing = get(sym_, keys::spacing, 100.0); - double max_error = get(sym_, keys::max_error, 0.2); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); markers_placement placement(path, bbox_, marker_trans_, detector_, spacing * scale_factor_, max_error, @@ -168,7 +173,6 @@ struct vector_markers_rasterizer_dispatch } } private: - agg::scanline_u8 sl_; BufferType & buf_; pixfmt_type pixf_; renderer_base renb_; @@ -178,6 +182,8 @@ private: agg::trans_affine const& marker_trans_; markers_symbolizer const& sym_; Detector & detector_; + feature_impl & feature_; + attributes const& vars_; double scale_factor_; bool snap_to_pixels_; }; @@ -198,6 +204,8 @@ struct raster_markers_rasterizer_dispatch agg::trans_affine const& marker_trans, markers_symbolizer const& sym, Detector & detector, + feature_impl & feature, + attributes const& vars, double scale_factor, bool snap_to_pixels) : buf_(render_buffer), @@ -208,27 +216,22 @@ struct raster_markers_rasterizer_dispatch marker_trans_(marker_trans), sym_(sym), detector_(detector), + feature_(feature), + vars_(vars), scale_factor_(scale_factor), snap_to_pixels_(snap_to_pixels) { - pixf_.comp_op(get(sym_, keys::comp_op, agg::comp_op_src_over)); - } - - raster_markers_rasterizer_dispatch(raster_markers_rasterizer_dispatch &&d) - : buf_(d.buf_), pixf_(d.pixf_), renb_(d.renb_), ras_(d.ras_), src_(d.src_), - marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_), - scale_factor_(d.scale_factor_), snap_to_pixels_(d.snap_to_pixels_) - { + pixf_.comp_op(get(sym_, keys::comp_op, feature_, vars_, agg::comp_op_src_over)); } template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT); - bool allow_overlap = get(sym_, keys::allow_overlap, false); + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); box2d bbox_(0,0, src_.width(),src_.height()); - double opacity = get(sym_, keys::opacity, 1.0); - bool ignore_placement = get(sym_, keys::ignore_placement, false); + double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); if (placement_method != MARKER_LINE_PLACEMENT || path.type() == mapnik::geometry_type::types::Point) @@ -238,17 +241,23 @@ struct raster_markers_rasterizer_dispatch if (path.type() == mapnik::geometry_type::types::LineString) { if (!label::middle_point(path, x, y)) + { return; + } } else if (placement_method == MARKER_INTERIOR_PLACEMENT) { if (!label::interior_position(path, x, y)) + { return; + } } else { if (!label::centroid(path, x, y)) + { return; + } } agg::trans_affine matrix = marker_trans_; matrix.translate(x,y); @@ -266,8 +275,8 @@ struct raster_markers_rasterizer_dispatch } else { - double spacing = get(sym_, keys::spacing, 100.0); - double max_error = get(sym_, keys::max_error, 0.2); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); markers_placement placement(path, bbox_, marker_trans_, detector_, spacing * scale_factor_, max_error, @@ -287,6 +296,7 @@ struct raster_markers_rasterizer_dispatch double opacity) { typedef agg::pixfmt_rgba32_pre pixfmt_pre; + agg::scanline_u8 sl_; double width = src_.width(); double height = src_.height(); if (std::fabs(1.0 - scale_factor_) < 0.001 @@ -349,7 +359,6 @@ struct raster_markers_rasterizer_dispatch } private: - agg::scanline_u8 sl_; BufferType & buf_; pixfmt_comp_type pixf_; renderer_base renb_; @@ -358,13 +367,15 @@ private: agg::trans_affine const& marker_trans_; markers_symbolizer const& sym_; Detector & detector_; + feature_impl & feature_; + attributes const& vars_; double scale_factor_; bool snap_to_pixels_; }; template -void build_ellipse(T const& sym, mapnik::feature_impl const& feature, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path) +void build_ellipse(T const& sym, mapnik::feature_impl & feature, attributes const& vars, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path) { auto width_expr = get(sym, keys::width); auto height_expr = get(sym, keys::height); @@ -372,17 +383,17 @@ void build_ellipse(T const& sym, mapnik::feature_impl const& feature, svg_storag double height = 0; if (width_expr && height_expr) { - width = boost::apply_visitor(evaluate(feature), *width_expr).to_double(); - height = boost::apply_visitor(evaluate(feature), *height_expr).to_double(); + width = boost::apply_visitor(evaluate(feature,vars), *width_expr).to_double(); + height = boost::apply_visitor(evaluate(feature,vars), *height_expr).to_double(); } else if (width_expr) { - width = boost::apply_visitor(evaluate(feature), *width_expr).to_double(); + width = boost::apply_visitor(evaluate(feature,vars), *width_expr).to_double(); height = width; } else if (height_expr) { - height = boost::apply_visitor(evaluate(feature), *height_expr).to_double(); + height = boost::apply_visitor(evaluate(feature,vars), *height_expr).to_double(); width = height; } svg::svg_converter_type styled_svg(svg_path, marker_ellipse.attributes()); @@ -400,13 +411,16 @@ void build_ellipse(T const& sym, mapnik::feature_impl const& feature, svg_storag } template -bool push_explicit_style(Attr const& src, Attr & dst, markers_symbolizer const& sym) +bool push_explicit_style(Attr const& src, Attr & dst, + markers_symbolizer const& sym, + feature_impl & feature, + attributes const& vars) { - auto fill_color = get_optional(sym, keys::fill); - auto fill_opacity = get_optional(sym, keys::fill_opacity); - auto stroke_color = get_optional(sym, keys::stroke); - auto stroke_width = get_optional(sym, keys::stroke_width); - auto stroke_opacity = get_optional(sym, keys::stroke_opacity); + auto fill_color = get_optional(sym, keys::fill, feature, vars); + auto fill_opacity = get_optional(sym, keys::fill_opacity, feature, vars); + auto stroke_color = get_optional(sym, keys::stroke, feature, vars); + auto stroke_width = get_optional(sym, keys::stroke_width, feature, vars); + auto stroke_opacity = get_optional(sym, keys::stroke_opacity, feature, vars); if (fill_color || fill_opacity || stroke_color || @@ -463,7 +477,8 @@ template void setup_transform_scaling(agg::trans_affine & tr, double svg_width, double svg_height, - mapnik::feature_impl const& feature, + mapnik::feature_impl & feature, + attributes const& vars, T const& sym) { double width = 0; @@ -471,11 +486,11 @@ void setup_transform_scaling(agg::trans_affine & tr, expression_ptr width_expr = get(sym, keys::width); if (width_expr) - width = boost::apply_visitor(evaluate(feature), *width_expr).to_double(); + width = boost::apply_visitor(evaluate(feature,vars), *width_expr).to_double(); expression_ptr height_expr = get(sym, keys::height); if (height_expr) - height = boost::apply_visitor(evaluate(feature), *height_expr).to_double(); + height = boost::apply_visitor(evaluate(feature,vars), *height_expr).to_double(); if (width > 0 && height > 0) { @@ -497,7 +512,7 @@ void setup_transform_scaling(agg::trans_affine & tr, // Apply markers to a feature with multiple geometries template -void apply_markers_multi(feature_impl & feature, Converter& converter, markers_symbolizer const& sym) +void apply_markers_multi(feature_impl & feature, attributes const& vars, Converter& converter, markers_symbolizer const& sym) { std::size_t geom_count = feature.paths().size(); if (geom_count == 1) @@ -506,8 +521,8 @@ void apply_markers_multi(feature_impl & feature, Converter& converter, markers_s } else if (geom_count > 1) { - marker_multi_policy_enum multi_policy = get(sym, keys::markers_multipolicy, MARKER_EACH_MULTI); - marker_placement_enum placement = get(sym, keys::markers_placement_type, MARKER_POINT_PLACEMENT); + marker_multi_policy_enum multi_policy = get(sym, keys::markers_multipolicy, feature, vars, MARKER_EACH_MULTI); + marker_placement_enum placement = get(sym, keys::markers_placement_type, feature, vars, MARKER_POINT_PLACEMENT); if (placement == MARKER_POINT_PLACEMENT && multi_policy == MARKER_WHOLE_MULTI) { @@ -551,7 +566,7 @@ void apply_markers_multi(feature_impl & feature, Converter& converter, markers_s } for (geometry_type & path : feature.paths()) { - converter.apply(path); + converter.apply(path); } } } diff --git a/include/mapnik/query.hpp b/include/mapnik/query.hpp index 0b08be756..c903982cb 100644 --- a/include/mapnik/query.hpp +++ b/include/mapnik/query.hpp @@ -25,6 +25,7 @@ //mapnik #include +#include // boost #include @@ -49,7 +50,8 @@ public: scale_denominator_(scale_denominator), filter_factor_(1.0), unbuffered_bbox_(unbuffered_bbox), - names_() + names_(), + vars_() {} query(box2d const& bbox, @@ -60,7 +62,8 @@ public: scale_denominator_(scale_denominator), filter_factor_(1.0), unbuffered_bbox_(bbox), - names_() + names_(), + vars_() {} query(box2d const& bbox) @@ -69,7 +72,8 @@ public: scale_denominator_(1.0), filter_factor_(1.0), unbuffered_bbox_(bbox), - names_() + names_(), + vars_() {} query(query const& other) @@ -78,7 +82,8 @@ public: scale_denominator_(other.scale_denominator_), filter_factor_(other.filter_factor_), unbuffered_bbox_(other.unbuffered_bbox_), - names_(other.names_) + names_(other.names_), + vars_(other.vars_) {} query& operator=(query const& other) @@ -90,6 +95,7 @@ public: filter_factor_=other.filter_factor_; unbuffered_bbox_=other.unbuffered_bbox_; names_=other.names_; + vars_=other.vars_; return *this; } @@ -143,6 +149,16 @@ public: return names_; } + void set_variables(attributes const& vars) + { + vars_ = vars; + } + + attributes const& variables() const + { + return vars_; + } + private: box2d bbox_; resolution_type resolution_; @@ -150,6 +166,7 @@ private: double filter_factor_; box2d unbuffered_bbox_; std::set names_; + attributes vars_; }; } diff --git a/include/mapnik/renderer_common.hpp b/include/mapnik/renderer_common.hpp index 62faab3b7..1e0af87cc 100644 --- a/include/mapnik/renderer_common.hpp +++ b/include/mapnik/renderer_common.hpp @@ -27,30 +27,33 @@ #include // for face_manager, etc #include // for box2d #include // for CoordTransform +#include // fwd declarations to speed up compile namespace mapnik { class label_collision_detector4; class Map; class request; +// class attributes; } namespace mapnik { struct renderer_common { - renderer_common(Map const &m, unsigned offset_x, unsigned offset_y, + renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor); - renderer_common(Map const &m, unsigned offset_x, unsigned offset_y, + renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor, std::shared_ptr detector); - renderer_common(request const &req, unsigned offset_x, unsigned offset_y, + renderer_common(request const &req, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor); - renderer_common(const renderer_common &); + renderer_common(renderer_common const& other); unsigned width_; unsigned height_; double scale_factor_; + attributes vars_; // TODO: dirty hack for cairo renderer, figure out how to remove this std::shared_ptr shared_font_engine_; freetype_engine &font_engine_; @@ -61,7 +64,7 @@ struct renderer_common private: renderer_common(unsigned width, unsigned height, double scale_factor, - CoordTransform &&t, std::shared_ptr detector); + attributes const& vars, CoordTransform &&t, std::shared_ptr detector); }; } diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index ff6cf7663..68c378378 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -115,7 +115,8 @@ struct render_thunk_extractor : public boost::static_visitor<> { render_thunk_extractor(box2d &box, render_thunk_list &thunks, - mapnik::feature_impl &feature, + feature_impl &feature, + attributes const& vars, proj_transform const &prj_trans, renderer_common &common, box2d const &clipping_extent); @@ -137,7 +138,8 @@ private: box2d &box_; render_thunk_list &thunks_; - mapnik::feature_impl &feature_; + feature_impl & feature_; + attributes const& vars_; proj_transform const &prj_trans_; renderer_common &common_; box2d clipping_extent_; @@ -181,9 +183,10 @@ void render_offset_placements(placements_list const& placements, template void render_group_symbolizer(group_symbolizer const &sym, - mapnik::feature_impl &feature, - proj_transform const &prj_trans, - box2d const &clipping_extent, + feature_impl & feature, + attributes const& vars, + proj_transform const & prj_trans, + box2d const & clipping_extent, renderer_common &common, F render_thunks) { @@ -260,7 +263,7 @@ void render_group_symbolizer(group_symbolizer const &sym, // get the layout for this set of properties for (auto const& rule : props->get_rules()) { - if (boost::apply_visitor(evaluate(*sub_feature), + if (boost::apply_visitor(evaluate(*sub_feature,common.vars_), *(rule->get_filter())).to_bool()) { // add matched rule and feature to the list of things to draw @@ -269,7 +272,7 @@ void render_group_symbolizer(group_symbolizer const &sym, // construct a bounding box around all symbolizers for the matched rule bound_box bounds; render_thunk_list thunks; - render_thunk_extractor extractor(bounds, thunks, *sub_feature, prj_trans, + render_thunk_extractor extractor(bounds, thunks, *sub_feature, common.vars_, prj_trans, virtual_renderer, clipping_extent); for (auto const& sym : *rule) @@ -288,7 +291,7 @@ void render_group_symbolizer(group_symbolizer const &sym, } // create a symbolizer helper - group_symbolizer_helper helper(sym, feature, prj_trans, + group_symbolizer_helper helper(sym, feature, vars, prj_trans, common.width_, common.height_, common.scale_factor_, common.t_, *common.detector_, clipping_extent); @@ -316,7 +319,7 @@ void render_group_symbolizer(group_symbolizer const &sym, // evalute the repeat key with the matched sub feature if we have one if (rpt_key_expr) { - rpt_key_value = boost::apply_visitor(evaluate(*match_feature), *rpt_key_expr).to_unicode(); + rpt_key_value = boost::apply_visitor(evaluate(*match_feature,common.vars_), *rpt_key_expr).to_unicode(); } helper.add_box_element(layout_manager.offset_box_at(i), rpt_key_value); } diff --git a/include/mapnik/renderer_common/process_markers_symbolizer.hpp b/include/mapnik/renderer_common/process_markers_symbolizer.hpp index c6bf5a2c0..8b04eb1cc 100644 --- a/include/mapnik/renderer_common/process_markers_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_markers_symbolizer.hpp @@ -48,9 +48,9 @@ void render_markers_symbolizer(markers_symbolizer const &sym, typedef boost::mpl::vector conv_types; typedef agg::pod_bvector svg_attribute_type; - std::string filename = get(sym, keys::file, feature, "shape://ellipse"); - bool clip = get(sym, keys::clip, feature, false); - double smooth = get(sym, keys::smooth, feature, false); + std::string filename = get(sym, keys::file, feature, common.vars_, "shape://ellipse"); + bool clip = get(sym, keys::clip, feature, common.vars_, false); + double smooth = get(sym, keys::smooth, feature, common.vars_, false); // https://github.com/mapnik/mapnik/issues/1316 bool snap_pixels = !mapnik::marker_cache::instance().is_uri(filename); @@ -76,11 +76,11 @@ void render_markers_symbolizer(markers_symbolizer const &sym, svg_storage_type marker_ellipse; vertex_stl_adapter stl_storage(marker_ellipse.source()); svg_path_adapter svg_path(stl_storage); - build_ellipse(sym, feature, marker_ellipse, svg_path); + build_ellipse(sym, feature, common.vars_, marker_ellipse, svg_path); svg_attribute_type attributes; - bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym); + bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_); auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(tr, feature, *image_transform); + if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); box2d bbox = marker_ellipse.bounding_box(); auto rasterizer_dispatch = make_vector_dispatch( @@ -90,7 +90,7 @@ void render_markers_symbolizer(markers_symbolizer const &sym, vertex_converter, dispatch_type, markers_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.scale_factor_); + converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.vars_,common.scale_factor_); if (clip && feature.paths().size() > 0) // optional clip (default: true) { geometry_type::types type = feature.paths()[0].type(); @@ -103,18 +103,18 @@ void render_markers_symbolizer(markers_symbolizer const &sym, } converter.template set(); //always transform if (smooth > 0.0) converter.template set(); // optional smooth converter - apply_markers_multi(feature, converter, sym); + apply_markers_multi(feature, common.vars_, converter, sym); } else { box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); + setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, common.vars_, sym); auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(tr, feature, *image_transform); + if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); vertex_stl_adapter stl_storage((*stock_vector_marker)->source()); svg_path_adapter svg_path(stl_storage); svg_attribute_type attributes; - bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym); + bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_); auto rasterizer_dispatch = make_vector_dispatch( svg_path, result ? attributes : (*stock_vector_marker)->attributes(), **stock_vector_marker, bbox, tr, snap_pixels); @@ -122,7 +122,7 @@ void render_markers_symbolizer(markers_symbolizer const &sym, vertex_converter, dispatch_type, markers_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.scale_factor_); + converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.vars_,common.scale_factor_); if (clip && feature.paths().size() > 0) // optional clip (default: true) { geometry_type::types type = feature.paths()[0].type(); @@ -135,14 +135,14 @@ void render_markers_symbolizer(markers_symbolizer const &sym, } converter.template set(); //always transform if (smooth > 0.0) converter.template set(); // optional smooth converter - apply_markers_multi(feature, converter, sym); + apply_markers_multi(feature, common.vars_, converter, sym); } } else // raster markers { - setup_transform_scaling(tr, (*mark)->width(), (*mark)->height(), feature, sym); + setup_transform_scaling(tr, (*mark)->width(), (*mark)->height(), feature, common.vars_, sym); auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(tr, feature, *image_transform); + if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); box2d const& bbox = (*mark)->bounding_box(); boost::optional marker = (*mark)->get_bitmap_data(); @@ -151,7 +151,7 @@ void render_markers_symbolizer(markers_symbolizer const &sym, vertex_converter, dispatch_type, markers_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.scale_factor_); + converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.vars_,common.scale_factor_); if (clip && feature.paths().size() > 0) // optional clip (default: true) { @@ -165,7 +165,7 @@ void render_markers_symbolizer(markers_symbolizer const &sym, } converter.template set(); //always transform if (smooth > 0.0) converter.template set(); // optional smooth converter - apply_markers_multi(feature, converter, sym); + apply_markers_multi(feature, common.vars_, converter, sym); } } } diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index 0623730d9..e7cc3b5a7 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -36,9 +36,9 @@ void render_point_symbolizer(point_symbolizer const &sym, renderer_common &common, F render_marker) { - std::string filename = get(sym, keys::file, feature); + std::string filename = get(sym, keys::file, feature, common.vars_); boost::optional marker; - if ( !filename.empty() ) + if (!filename.empty()) { marker = marker_cache::instance().find(filename, true); } @@ -46,20 +46,19 @@ void render_point_symbolizer(point_symbolizer const &sym, { marker.reset(std::make_shared()); } - if (marker) { - double opacity = get(sym,keys::opacity,feature, 1.0); - bool allow_overlap = get(sym, keys::allow_overlap, feature, false); - bool ignore_placement = get(sym, keys::ignore_placement, feature, false); - point_placement_enum placement= get(sym, keys::point_placement_type, feature, CENTROID_POINT_PLACEMENT); + double opacity = get(sym,keys::opacity,feature, common.vars_, 1.0); + bool allow_overlap = get(sym, keys::allow_overlap, feature, common.vars_, false); + bool ignore_placement = get(sym, keys::ignore_placement, feature, common.vars_, false); + point_placement_enum placement= get(sym, keys::point_placement_type, feature, common.vars_, CENTROID_POINT_PLACEMENT); box2d const& bbox = (*marker)->bounding_box(); coord2d center = bbox.center(); agg::trans_affine tr; auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(tr, feature, *image_transform); + if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine recenter_tr = recenter * tr; diff --git a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp index c3756a7a0..b65224ce3 100644 --- a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp @@ -36,15 +36,15 @@ void render_polygon_symbolizer(polygon_symbolizer const &sym, { agg::trans_affine tr; auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, *transform, common.scale_factor_); + if (transform) evaluate_transform(tr, feature, common.vars_, *transform, common.scale_factor_); - bool clip = get(sym, keys::clip, feature, true); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, 0.0); - double opacity = get(sym,keys::fill_opacity,feature, 1.0); + bool clip = get(sym, keys::clip, feature, common.vars_, true); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common.vars_, 0.0); + double opacity = get(sym,keys::fill_opacity,feature,common.vars_, 1.0); vertex_converter_type converter(clip_box, ras, sym, common.t_, prj_trans, tr, - feature,common.scale_factor_); + feature,common.vars_,common.scale_factor_); if (prj_trans.equal() && clip) converter.template set(); //optional clip (default: true) converter.template set(); //always transform @@ -60,7 +60,7 @@ void render_polygon_symbolizer(polygon_symbolizer const &sym, } } - color const& fill = get(sym, keys::fill, feature, mapnik::color(128,128,128)); // gray + color const& fill = get(sym, keys::fill, feature, common.vars_, mapnik::color(128,128,128)); // gray fill_func(fill, opacity); } diff --git a/include/mapnik/renderer_common/process_raster_symbolizer.hpp b/include/mapnik/renderer_common/process_raster_symbolizer.hpp index dae91ecae..77798dcb8 100644 --- a/include/mapnik/renderer_common/process_raster_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_raster_symbolizer.hpp @@ -23,6 +23,9 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP +// mapnik +#include + // agg #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -55,13 +58,11 @@ void render_raster_symbolizer(raster_symbolizer const &sym, int raster_height = end_y - start_y; if (raster_width > 0 && raster_height > 0) { - raster target(target_ext, raster_width, raster_height, source->get_filter_factor()); - scaling_method_e scaling_method = get(sym, keys::scaling, feature, SCALING_NEAR); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); - - double opacity = get(sym,keys::opacity,feature, 1.0); + scaling_method_e scaling_method = get(sym, keys::scaling, feature, common.vars_, SCALING_NEAR); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common.vars_, src_over); + double opacity = get(sym,keys::opacity,feature, common.vars_, 1.0); bool premultiply_source = !source->premultiplied_alpha_; - auto is_premultiplied = get_optional(sym, keys::premultiplied); + auto is_premultiplied = get_optional(sym, keys::premultiplied, feature, common.vars_); if (is_premultiplied) { if (*is_premultiplied) premultiply_source = false; @@ -80,7 +81,8 @@ void render_raster_symbolizer(raster_symbolizer const &sym, { double offset_x = ext.minx() - start_x; double offset_y = ext.miny() - start_y; - unsigned mesh_size = static_cast(get(sym,keys::mesh_size,feature, 16)); + raster target(target_ext, raster_width, raster_height, source->get_filter_factor()); + unsigned mesh_size = static_cast(get(sym,keys::mesh_size,feature, common.vars_, 16)); reproject_and_scale_raster(target, *source, prj_trans, @@ -88,31 +90,46 @@ void render_raster_symbolizer(raster_symbolizer const &sym, offset_y, mesh_size, scaling_method); + composite(target.data_, comp_op, opacity, start_x, start_y); } else { - if (scaling_method == SCALING_BILINEAR8) + double image_ratio_x = ext.width() / source->data_.width(); + double image_ratio_y = ext.height() / source->data_.height(); + double eps = 1e-5; + if ( (std::fabs(image_ratio_x - 1) <= eps) && + (std::fabs(image_ratio_y - 1) <= eps) && + (std::fabs(start_x) <= eps) && + (std::fabs(start_y) <= eps) ) { - scale_image_bilinear8(target.data_, - source->data_, - 0.0, - 0.0); + composite(source->data_, comp_op, opacity, start_x, start_y); } else { - double image_ratio_x = ext.width() / source->data_.width(); - double image_ratio_y = ext.height() / source->data_.height(); - scale_image_agg(target.data_, - source->data_, - scaling_method, - image_ratio_x, - image_ratio_y, - 0.0, - 0.0, - source->get_filter_factor()); + raster target(target_ext, raster_width, raster_height, source->get_filter_factor()); + if (scaling_method == SCALING_BILINEAR8) + { + scale_image_bilinear8(target.data_, + source->data_, + 0.0, + 0.0); + } + else + { + double image_ratio_x = ext.width() / source->data_.width(); + double image_ratio_y = ext.height() / source->data_.height(); + scale_image_agg(target.data_, + source->data_, + scaling_method, + image_ratio_x, + image_ratio_y, + 0.0, + 0.0, + source->get_filter_factor()); + } + composite(target.data_, comp_op, opacity, start_x, start_y); } } - composite(target, comp_op, opacity, start_x, start_y); } } } diff --git a/include/mapnik/svg/output/svg_renderer.hpp b/include/mapnik/svg/output/svg_renderer.hpp index 575140853..171907c97 100644 --- a/include/mapnik/svg/output/svg_renderer.hpp +++ b/include/mapnik/svg/output/svg_renderer.hpp @@ -74,7 +74,7 @@ class MAPNIK_DECL svg_renderer : public feature_style_processor processor_impl_type; svg_renderer(Map const& m, OutputIterator& output_iterator, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); - svg_renderer(Map const& m, request const& req, OutputIterator& output_iterator, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); + svg_renderer(Map const& m, request const& req, attributes const& vars, OutputIterator& output_iterator, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); ~svg_renderer(); void start_map_processing(Map const& map); @@ -147,6 +147,11 @@ public: return common_.scale_factor_; } + inline attributes const& variables() const + { + return common_.vars_; + } + inline OutputIterator& get_output_iterator() { return output_iterator_; diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 8fed474f5..fd3d9e007 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,8 @@ #include #include #include +#include + // stl #include #include @@ -63,6 +66,7 @@ class feature_impl; MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature, + attributes const& vars, transform_type const& trans_expr, double scale_factor=1.0); @@ -245,10 +249,10 @@ struct evaluate_expression_wrapper { typedef T result_type; - template - result_type operator() (T1 const& expr, T2 const& feature) const + template + result_type operator() (T1 const& expr, T2 const& feature, T3 const& vars) const { - mapnik::value_type result = boost::apply_visitor(mapnik::evaluate(feature), expr); + mapnik::value_type result = boost::apply_visitor(mapnik::evaluate(feature,vars), expr); return detail::expression_result::value>::convert(result); } }; @@ -257,10 +261,10 @@ struct evaluate_expression_wrapper template <> struct evaluate_expression_wrapper { - template - mapnik::color operator() (T1 const& expr, T2 const& feature) const + template + mapnik::color operator() (T1 const& expr, T2 const& feature, T3 const& vars) const { - mapnik::value_type val = boost::apply_visitor(mapnik::evaluate(feature), expr); + mapnik::value_type val = boost::apply_visitor(mapnik::evaluate(feature,vars), expr); // FIXME - throw instead? if (val.is_null()) return mapnik::color(255,192,203); // pink return mapnik::color(val.to_string()); @@ -271,10 +275,10 @@ struct evaluate_expression_wrapper template <> struct evaluate_expression_wrapper { - template - mapnik::enumeration_wrapper operator() (T1 const& expr, T2 const& feature) const + template + mapnik::enumeration_wrapper operator() (T1 const& expr, T2 const& feature, T3 const& vars) const { - mapnik::value_type val = boost::apply_visitor(mapnik::evaluate(feature), expr); + mapnik::value_type val = boost::apply_visitor(mapnik::evaluate(feature,vars), expr); return mapnik::enumeration_wrapper(val.to_int()); } }; @@ -285,12 +289,14 @@ struct extract_value : public boost::static_visitor { typedef T result_type; - extract_value(mapnik::feature_impl const& feature) - : feature_(feature) {} + extract_value(mapnik::feature_impl const& feature, + mapnik::attributes const& v) + : feature_(feature), + vars_(v) {} auto operator() (mapnik::expression_ptr const& expr) const -> result_type { - return evaluate_expression_wrapper()(*expr,feature_); + return evaluate_expression_wrapper()(*expr,feature_,vars_); } auto operator() (mapnik::path_expression_ptr const& expr) const -> result_type @@ -308,13 +314,14 @@ struct extract_value : public boost::static_visitor return detail::enumeration_result::value>::convert(e); } - template - auto operator() (T1 const& val) const -> result_type + template + auto operator() (TVal const& val) const -> result_type { return result_type(); } mapnik::feature_impl const& feature_; + mapnik::attributes const& vars_; }; template @@ -353,25 +360,25 @@ bool has_key(symbolizer_base const& sym, keys key) } template -T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, T const& _default_value = T()) +T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars, T const& _default_value = T()) { typedef symbolizer_base::cont_type::const_iterator const_iterator; const_iterator itr = sym.properties.find(key); if (itr != sym.properties.end()) { - return boost::apply_visitor(extract_value(feature), itr->second); + return boost::apply_visitor(extract_value(feature,vars), itr->second); } return _default_value; } template -boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature) +boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars) { typedef symbolizer_base::cont_type::const_iterator const_iterator; const_iterator itr = sym.properties.find(key); if (itr != sym.properties.end()) { - return boost::apply_visitor(extract_value(feature), itr->second); + return boost::apply_visitor(extract_value(feature,vars), itr->second); } return boost::optional(); } diff --git a/include/mapnik/symbolizer_keys.hpp b/include/mapnik/symbolizer_keys.hpp index 034aa343c..a1d86f9a6 100644 --- a/include/mapnik/symbolizer_keys.hpp +++ b/include/mapnik/symbolizer_keys.hpp @@ -82,6 +82,8 @@ enum class keys : std::uint8_t start_column, repeat_key, group_properties, + largest_box_only, + minimum_path_length, MAX_SYMBOLIZER_KEY }; diff --git a/include/mapnik/text/formatting/base.hpp b/include/mapnik/text/formatting/base.hpp index 17704ecb9..766feb76d 100644 --- a/include/mapnik/text/formatting/base.hpp +++ b/include/mapnik/text/formatting/base.hpp @@ -46,7 +46,7 @@ public: virtual ~node() {} virtual void to_xml(boost::property_tree::ptree &xml) const; static node_ptr from_xml(xml_node const& xml); - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const = 0; + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const = 0; virtual void add_expressions(expression_set &output) const; }; } //ns formatting diff --git a/include/mapnik/text/formatting/expression_format.hpp b/include/mapnik/text/formatting/expression_format.hpp index 8acbd9e36..53cabff7a 100644 --- a/include/mapnik/text/formatting/expression_format.hpp +++ b/include/mapnik/text/formatting/expression_format.hpp @@ -40,7 +40,7 @@ class MAPNIK_DECL expression_format: public node { public: void to_xml(boost::property_tree::ptree &xml) const; static node_ptr from_xml(xml_node const& xml); - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const; + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const; virtual void add_expressions(expression_set &output) const; void set_child(node_ptr child); diff --git a/include/mapnik/text/formatting/format.hpp b/include/mapnik/text/formatting/format.hpp index b7aa862e3..ce8ec74c4 100644 --- a/include/mapnik/text/formatting/format.hpp +++ b/include/mapnik/text/formatting/format.hpp @@ -36,7 +36,7 @@ class MAPNIK_DECL format_node: public node { public: void to_xml(boost::property_tree::ptree &xml) const; static node_ptr from_xml(xml_node const& xml); - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const; + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const; virtual void add_expressions(expression_set &output) const; void set_child(node_ptr child); diff --git a/include/mapnik/text/formatting/layout.hpp b/include/mapnik/text/formatting/layout.hpp index fe94c1434..30397d4d3 100644 --- a/include/mapnik/text/formatting/layout.hpp +++ b/include/mapnik/text/formatting/layout.hpp @@ -34,7 +34,7 @@ class MAPNIK_DECL layout_node: public node { public: void to_xml(boost::property_tree::ptree &xml) const; static node_ptr from_xml(xml_node const& xml); - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const; + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const; virtual void add_expressions(expression_set &output) const; void set_child(node_ptr child); node_ptr get_child() const; diff --git a/include/mapnik/text/formatting/list.hpp b/include/mapnik/text/formatting/list.hpp index d74a77295..dc22daff8 100644 --- a/include/mapnik/text/formatting/list.hpp +++ b/include/mapnik/text/formatting/list.hpp @@ -35,7 +35,7 @@ class MAPNIK_DECL list_node: public node { public: list_node() : node(), children_() {} virtual void to_xml(boost::property_tree::ptree &xml) const; - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const; + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const; virtual void add_expressions(expression_set &output) const; void push_back(node_ptr n); diff --git a/include/mapnik/text/formatting/text.hpp b/include/mapnik/text/formatting/text.hpp index a868e5845..f7a48e44e 100644 --- a/include/mapnik/text/formatting/text.hpp +++ b/include/mapnik/text/formatting/text.hpp @@ -36,7 +36,7 @@ public: text_node(std::string text): node(), text_(parse_expression(text)) {} void to_xml(boost::property_tree::ptree &xml) const; static node_ptr from_xml(xml_node const& xml); - virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const; + virtual void apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const; virtual void add_expressions(expression_set &output) const; void set_text(expression_ptr text); diff --git a/include/mapnik/text/layout.hpp b/include/mapnik/text/layout.hpp index 916c3e4f2..0adec58dc 100644 --- a/include/mapnik/text/layout.hpp +++ b/include/mapnik/text/layout.hpp @@ -101,7 +101,7 @@ public: pixel_position alignment_offset() const; double jalign_offset(double line_width) const; - void init_orientation(feature_impl const& feature); + void init_orientation(feature_impl const& feature, attributes const& attr); private: void break_line(text_line & line, double wrap_width, unsigned text_ratio, bool wrap_before); diff --git a/include/mapnik/text/placement_finder.hpp b/include/mapnik/text/placement_finder.hpp index 9bb42f250..7fe4e552b 100644 --- a/include/mapnik/text/placement_finder.hpp +++ b/include/mapnik/text/placement_finder.hpp @@ -45,6 +45,7 @@ class placement_finder : mapnik::noncopyable { public: placement_finder(feature_impl const& feature, + attributes const& attr, DetectorType & detector, box2d const& extent, text_placement_info_ptr placement_info, @@ -79,6 +80,7 @@ private: text_upright_e simplify_upright(text_upright_e upright, double angle) const; box2d get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot); feature_impl const& feature_; + attributes const& attr_; DetectorType &detector_; box2d const& extent_; text_placement_info_ptr info_; diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index efa07b22f..7d5b2a187 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -38,6 +38,7 @@ class base_symbolizer_helper public: base_symbolizer_helper(symbolizer_base const& sym, feature_impl const& feature, + attributes const& vars, proj_transform const& prj_trans, unsigned width, unsigned height, @@ -52,6 +53,7 @@ protected: //Input symbolizer_base const& sym_; feature_impl const& feature_; + attributes const& vars_; proj_transform const& prj_trans_; CoordTransform const& t_; box2d dims_; @@ -84,6 +86,7 @@ public: template text_symbolizer_helper(text_symbolizer const& sym, feature_impl const& feature, + attributes const& vars, proj_transform const& prj_trans, unsigned width, unsigned height, @@ -96,6 +99,7 @@ public: template text_symbolizer_helper(shield_symbolizer const& sym, feature_impl const& feature, + attributes const& vars, proj_transform const& prj_trans, unsigned width, unsigned height, diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index 8138f8bf5..6ff783bf4 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -175,7 +175,7 @@ struct MAPNIK_DECL text_symbolizer_properties /** Takes a feature and produces formated text as output. * The output object has to be created by the caller and passed in for thread safety. */ - void process(text_layout &output, feature_impl const& feature) const; + void process(text_layout &output, feature_impl const& feature, attributes const& vars) const; /** Automatically create processing instructions for a single expression. */ void set_old_style_expression(expression_ptr expr); /** Sets new format tree. */ diff --git a/include/mapnik/transform_processor.hpp b/include/mapnik/transform_processor.hpp index fe394bf92..a2f54a2b2 100644 --- a/include/mapnik/transform_processor.hpp +++ b/include/mapnik/transform_processor.hpp @@ -46,10 +46,11 @@ class feature_impl; template struct expression_attributes; -template +template struct transform_processor { typedef T feature_type; + typedef T1 variable_type; typedef agg::trans_affine transform_type; template @@ -109,9 +110,11 @@ struct transform_processor { node_evaluator(transform_type& tr, feature_type const& feat, + variable_type const& v, double scale_factor) : transform_(tr), feature_(feat), + vars_(v), scale_factor_(scale_factor) {} void operator() (identity_node const& node) @@ -175,7 +178,7 @@ struct transform_processor double eval(expr_node const& x) const { - mapnik::evaluate e(feature_); + mapnik::evaluate e(feature_,vars_); return boost::apply_visitor(e, x).to_double(); } @@ -186,6 +189,7 @@ struct transform_processor transform_type& transform_; feature_type const& feature_; + variable_type const& vars_; double scale_factor_; }; @@ -201,10 +205,13 @@ struct transform_processor } } - static void evaluate(transform_type& tr, feature_type const& feat, - transform_list const& list, double scale_factor) + static void evaluate(transform_type& tr, + feature_type const& feat, + variable_type const& vars, + transform_list const& list, + double scale_factor) { - node_evaluator eval(tr, feat, scale_factor); + node_evaluator eval(tr, feat, vars, scale_factor); #ifdef MAPNIK_LOG MAPNIK_LOG_DEBUG(transform) << "transform: begin with " << to_string(matrix_node(tr)); @@ -235,7 +242,7 @@ struct transform_processor } }; -typedef mapnik::transform_processor transform_processor_type; +typedef mapnik::transform_processor transform_processor_type; } // namespace mapnik diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index e570a1710..08b2f696f 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -99,7 +99,8 @@ struct converter_traits { typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); auto const& feat = boost::fusion::at_c<6>(args); - geom.smooth_value(get(sym, keys::smooth, feat)); + auto const& vars = boost::fusion::at_c<7>(args); + geom.smooth_value(get(sym, keys::smooth, feat, vars)); } }; @@ -114,8 +115,9 @@ struct converter_traits { typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); auto const& feat = boost::fusion::at_c<6>(args); - geom.set_simplify_algorithm(static_cast(get(sym, keys::simplify_algorithm, feat))); - geom.set_simplify_tolerance(get(sym, keys::simplify_tolerance, feat)); + auto const& vars = boost::fusion::at_c<7>(args); + geom.set_simplify_algorithm(static_cast(get(sym, keys::simplify_algorithm, feat, vars))); + geom.set_simplify_tolerance(get(sym, keys::simplify_tolerance, feat, vars)); } }; @@ -143,7 +145,7 @@ struct converter_traits static void setup(geometry_type & geom, Args const& args) { typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); - double scale_factor = boost::fusion::at_c<7>(args); + double scale_factor = boost::fusion::at_c<8>(args); auto dash = get_optional(sym, keys::stroke_dasharray); if (dash) { @@ -167,11 +169,12 @@ struct converter_traits { typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); auto const& feat = boost::fusion::at_c<6>(args); - set_join_caps(sym, geom, feat); - double miterlimit = get(sym, keys::stroke_miterlimit, feat, 4.0); + auto const& vars = boost::fusion::at_c<7>(args); + set_join_caps(sym, geom, feat, vars); + double miterlimit = get(sym, keys::stroke_miterlimit, feat, vars, 4.0); geom.generator().miter_limit(miterlimit); - double scale_factor = boost::fusion::at_c<7>(args); - double width = get(sym, keys::stroke_width, feat, 1.0); + double scale_factor = boost::fusion::at_c<8>(args); + double width = get(sym, keys::stroke_width, feat, vars, 1.0); geom.generator().width(width * scale_factor); } }; @@ -248,8 +251,9 @@ struct converter_traits { typename boost::mpl::at >::type sym = boost::fusion::at_c<2>(args); auto const& feat = boost::fusion::at_c<6>(args); - double offset = get(sym, keys::offset, feat); - double scale_factor = boost::fusion::at_c<7>(args); + auto const& vars = boost::fusion::at_c<7>(args); + double offset = get(sym, keys::offset, feat, vars); + double scale_factor = boost::fusion::at_c<8>(args); geom.set_offset(offset * scale_factor); } }; @@ -351,6 +355,7 @@ struct vertex_converter : private mapnik::noncopyable proj_trans_type const&, affine_trans_type const&, feature_type const&, + attributes const&, double //scale-factor > args_type; @@ -361,6 +366,7 @@ struct vertex_converter : private mapnik::noncopyable proj_trans_type const& prj_trans, affine_trans_type const& affine_trans, feature_type const& feature, + attributes const& vars, double scale_factor) : disp_(args_type(boost::cref(b), boost::ref(ras), @@ -369,6 +375,7 @@ struct vertex_converter : private mapnik::noncopyable boost::cref(prj_trans), boost::cref(affine_trans), boost::cref(feature), + boost::cref(vars), scale_factor)) {} template diff --git a/include/mapnik/webp_io.hpp b/include/mapnik/webp_io.hpp index 89b1e552b..0344000eb 100644 --- a/include/mapnik/webp_io.hpp +++ b/include/mapnik/webp_io.hpp @@ -28,7 +28,10 @@ #include // webp +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" #include +#pragma clang diagnostic pop // stl #include diff --git a/plugins/input/postgis/build.py b/plugins/input/postgis/build.py index 4a011681f..b9251cd83 100644 --- a/plugins/input/postgis/build.py +++ b/plugins/input/postgis/build.py @@ -54,6 +54,7 @@ if env['PLUGIN_LINKING'] == 'shared': libraries.insert(0,'mapnik') libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) + libraries.append('boost_regex%s' % env['BOOST_APPEND']) TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, SHLIBPREFIX='', diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index a3086aa5f..41fddcd0b 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -38,6 +38,7 @@ // boost #include #include +#include // stl #include @@ -85,9 +86,11 @@ postgis_datasource::postgis_datasource(parameters const& params) extent_from_subquery_(*params.get("extent_from_subquery", false)), max_async_connections_(*params_.get("max_async_connection", 1)), asynchronous_request_(false), + // TODO - use for known tokens too: "(@\\w+|!\\w+!)" + pattern_(boost::regex("(@\\w+)",boost::regex::normal | boost::regbase::icase)), // params below are for testing purposes only and may be removed at any time - intersect_min_scale_(*params.get("intersect_min_scale", 0)), - intersect_max_scale_(*params.get("intersect_max_scale", 0)) + intersect_min_scale_(*params.get("intersect_min_scale", 0)), + intersect_max_scale_(*params.get("intersect_max_scale", 0)) { #ifdef MAPNIK_STATS mapnik::progress_timer __stats__(std::clog, "postgis_datasource::init"); @@ -520,22 +523,34 @@ std::string postgis_datasource::populate_tokens(std::string const& sql) const if (boost::algorithm::icontains(sql, pixel_width_token_)) { - std::ostringstream ss; - ss << 0; - boost::algorithm::replace_all(populated_sql, pixel_width_token_, ss.str()); + boost::algorithm::replace_all(populated_sql, pixel_width_token_, "0"); } if (boost::algorithm::icontains(sql, pixel_height_token_)) { - std::ostringstream ss; - ss << 0; - boost::algorithm::replace_all(populated_sql, pixel_height_token_, ss.str()); + boost::algorithm::replace_all(populated_sql, pixel_height_token_, "0"); } + std::string copy2 = populated_sql; + std::list l; + boost::regex_split(std::back_inserter(l), copy2, pattern_); + if (!l.empty()) + { + for (auto const & token: l) + { + boost::algorithm::replace_all(populated_sql, token, "null"); + } + } return populated_sql; } -std::string postgis_datasource::populate_tokens(std::string const& sql, double scale_denom, box2d const& env, double pixel_width, double pixel_height) const +std::string postgis_datasource::populate_tokens( + std::string const& sql, + double scale_denom, + box2d const& env, + double pixel_width, + double pixel_height, + mapnik::attributes const& vars) const { std::string populated_sql = sql; std::string box = sql_bbox(env); @@ -564,7 +579,6 @@ std::string postgis_datasource::populate_tokens(std::string const& sql, double s if (boost::algorithm::icontains(populated_sql, bbox_token_)) { boost::algorithm::replace_all(populated_sql, bbox_token_, box); - return populated_sql; } else { @@ -582,9 +596,27 @@ std::string postgis_datasource::populate_tokens(std::string const& sql, double s { s << " WHERE \"" << geometryColumn_ << "\" && " << box; } - - return populated_sql + s.str(); + populated_sql += s.str(); } + std::string copy2 = populated_sql; + std::list l; + boost::regex_split(std::back_inserter(l), copy2, pattern_); + if (!l.empty()) + { + for (auto const & token: l) + { + auto itr = vars.find(token.substr(1,std::string::npos)); + if (itr != vars.end()) + { + boost::algorithm::replace_all(populated_sql, token, itr->second.to_string()); + } + else + { + boost::algorithm::replace_all(populated_sql, token, "null"); + } + } + } + return populated_sql; } @@ -780,7 +812,7 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo } } - std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh); + std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh, q.variables()); s << " FROM " << table_with_bbox; @@ -863,7 +895,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double t } box2d box(pt.x - tol, pt.y - tol, pt.x + tol, pt.y + tol); - std::string table_with_bbox = populate_tokens(table_, FMAX, box, 0, 0); + std::string table_with_bbox = populate_tokens(table_, FMAX, box, 0, 0, mapnik::attributes()); s << " FROM " << table_with_bbox; diff --git a/plugins/input/postgis/postgis_datasource.hpp b/plugins/input/postgis/postgis_datasource.hpp index b60327eb9..649a4184d 100644 --- a/plugins/input/postgis/postgis_datasource.hpp +++ b/plugins/input/postgis/postgis_datasource.hpp @@ -33,9 +33,11 @@ #include #include #include +#include // boost #include +#include // stl #include @@ -77,7 +79,12 @@ public: private: std::string sql_bbox(box2d const& env) const; - std::string populate_tokens(std::string const& sql, double scale_denom, box2d const& env, double pixel_width, double pixel_height) const; + std::string populate_tokens(std::string const& sql, + double scale_denom, + box2d const& env, + double pixel_width, + double pixel_height, + mapnik::attributes const& vars) const; std::string populate_tokens(std::string const& sql) const; std::shared_ptr get_resultset(std::shared_ptr &conn, std::string const& sql, CnxPool_ptr const& pool, processor_context_ptr ctx= processor_context_ptr()) const; static const std::string GEOMETRY_COLUMNS; @@ -112,6 +119,7 @@ private: bool estimate_extent_; int max_async_connections_; bool asynchronous_request_; + boost::regex pattern_; int intersect_min_scale_; int intersect_max_scale_; }; diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index b1d0f9dee..fcb327471 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -72,13 +72,13 @@ agg_renderer::agg_renderer(Map const& m, T0 & pixmap, double scale_factor ras_ptr(new rasterizer), gamma_method_(GAMMA_POWER), gamma_(1.0), - common_(m, offset_x, offset_y, m.width(), m.height(), scale_factor) + common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor) { setup(m); } template -agg_renderer::agg_renderer(Map const& m, request const& req, T0 & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y) +agg_renderer::agg_renderer(Map const& m, request const& req, attributes const& vars, T0 & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m, scale_factor), pixmap_(pixmap), internal_buffer_(), @@ -87,7 +87,7 @@ agg_renderer::agg_renderer(Map const& m, request const& req, T0 & pixmap, ras_ptr(new rasterizer), gamma_method_(GAMMA_POWER), gamma_(1.0), - common_(req, offset_x, offset_y, req.width(), req.height(), scale_factor) + common_(req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor) { setup(m); } @@ -103,7 +103,7 @@ agg_renderer::agg_renderer(Map const& m, T0 & pixmap, std::shared_ptr ras_ptr(new rasterizer), gamma_method_(GAMMA_POWER), gamma_(1.0), - common_(m, offset_x, offset_y, m.width(), m.height(), scale_factor, detector) + common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor, detector) { setup(m); } diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index 7a67b600d..5b2c9e1c9 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -61,8 +61,8 @@ void agg_renderer::process(building_symbolizer const& sym, agg::pixfmt_rgba32_pre pixf(buf); ren_base renb(pixf); - double opacity = get(sym,keys::fill_opacity,feature, 1.0); - color const& fill = get(sym, keys::fill, feature); + double opacity = get(sym,keys::fill_opacity,feature, common_.vars_, 1.0); + color const& fill = get(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); unsigned r=fill.red(); unsigned g=fill.green(); unsigned b=fill.blue(); @@ -71,8 +71,8 @@ void agg_renderer::process(building_symbolizer const& sym, agg::scanline_u8 sl; ras_ptr->reset(); - double gamma = get(sym, keys::gamma, feature, 1.0); - gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, GAMMA_POWER); + double gamma = get(sym, keys::gamma, feature, common_.vars_, 1.0); + gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, common_.vars_, GAMMA_POWER); if (gamma != gamma_ || gamma_method != gamma_method_) { set_gamma_method(ras_ptr, gamma, gamma_method); @@ -80,7 +80,7 @@ void agg_renderer::process(building_symbolizer const& sym, gamma_ = gamma; } - double height = get(sym, keys::height,0.0) * common_.scale_factor_; + double height = get(sym, keys::height, feature, common_.vars_,0.0) * common_.scale_factor_; render_building_symbolizer( feature, height, diff --git a/src/agg/process_debug_symbolizer.cpp b/src/agg/process_debug_symbolizer.cpp index a95e5f4c4..834718334 100644 --- a/src/agg/process_debug_symbolizer.cpp +++ b/src/agg/process_debug_symbolizer.cpp @@ -53,7 +53,7 @@ void agg_renderer::process(debug_symbolizer const& sym, proj_transform const& prj_trans) { - debug_symbolizer_mode_enum mode = get(sym, keys::mode, DEBUG_SYM_MODE_COLLISION); + debug_symbolizer_mode_enum mode = get(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); if (mode == DEBUG_SYM_MODE_COLLISION) { diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index 9e67329b0..f04580f12 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -106,7 +106,7 @@ void agg_renderer::process(group_symbolizer const& sym, proj_transform const& prj_trans) { render_group_symbolizer( - sym, feature, prj_trans, clipping_extent(), common_, + sym, feature, common_.vars_, prj_trans, clipping_extent(), common_, [&](render_thunk_list const& thunks, pixel_position const& render_offset) { thunk_renderer ren(*this, current_buffer_, common_, render_offset); diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index 937a014d4..528196be5 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -100,9 +100,9 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, typedef agg::renderer_outline_image renderer_type; typedef agg::rasterizer_outline_aa rasterizer_type; - std::string filename = get(sym, keys::file, feature); - - boost::optional mark = marker_cache::instance().find(filename,true); + std::string filename = get(sym, keys::file, feature, common_.vars_); + if (filename.empty()) return; + boost::optional mark = marker_cache::instance().find(filename, true); if (!mark) return; if (!(*mark)->is_bitmap()) @@ -114,16 +114,15 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, boost::optional pat = (*mark)->get_bitmap_data(); if (!pat) return; - - bool clip = get(sym, keys::clip, feature); + bool clip = get(sym, keys::clip, feature, common_.vars_, true); //double opacity = get(sym,keys::stroke_opacity,feature, 1.0); TODO - double offset = get(sym, keys::offset, feature, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, false); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, false); agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(), current_buffer_->width() * 4); pixfmt_type pixf(buf); - pixf.comp_op(get(sym, keys::comp_op, feature, agg::comp_op_src_over)); + pixf.comp_op(get(sym, keys::comp_op, feature, common_.vars_, agg::comp_op_src_over)); renderer_base ren_base(pixf); agg::pattern_filter_bilinear_rgba8 filter; @@ -134,7 +133,7 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, agg::trans_affine tr; auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, *transform, common_.scale_factor_); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); box2d clip_box = clipping_extent(); if (clip) @@ -152,7 +151,7 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, typedef boost::mpl::vector conv_types; vertex_converter, rasterizer_type, line_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box,ras,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(clip_box,ras,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) converter.set(); //optional clip (default: true) converter.set(); //always transform diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index 1272bb385..2302b9f74 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -26,7 +26,6 @@ #include #include #include - #include #include @@ -59,14 +58,14 @@ void agg_renderer::process(line_symbolizer const& sym, proj_transform const& prj_trans) { - color const& col = get(sym, keys::stroke, feature, mapnik::color(0,0,0)); + color const& col = get(sym, keys::stroke, feature, common_.vars_, mapnik::color(0,0,0)); unsigned r=col.red(); unsigned g=col.green(); unsigned b=col.blue(); unsigned a=col.alpha(); - double gamma = get(sym, keys::stroke_gamma, feature, 1.0); - gamma_method_enum gamma_method = get(sym, keys::stroke_gamma_method, feature, GAMMA_POWER); + double gamma = get(sym, keys::stroke_gamma, feature, common_.vars_, 1.0); + gamma_method_enum gamma_method = get(sym, keys::stroke_gamma_method, feature, common_.vars_, GAMMA_POWER); ras_ptr->reset(); if (gamma != gamma_ || gamma_method != gamma_method_) @@ -90,22 +89,22 @@ void agg_renderer::process(line_symbolizer const& sym, dash_tag, stroke_tag> conv_types; pixfmt_comp_type pixf(buf); - pixf.comp_op(get(sym, keys::comp_op, feature, agg::comp_op_src_over)); + pixf.comp_op(get(sym, keys::comp_op, feature, common_.vars_, agg::comp_op_src_over)); renderer_base renb(pixf); agg::trans_affine tr; auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, *transform, common_.scale_factor_); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); box2d clip_box = clipping_extent(); - bool clip = get(sym, keys::clip, feature, true); - double width = get(sym, keys::stroke_width, feature, 1.0); - double opacity = get(sym,keys::stroke_opacity,feature, 1.0); - double offset = get(sym, keys::offset, feature, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, false); - line_rasterizer_enum rasterizer_e = get(sym, keys::line_rasterizer, feature, RASTERIZER_FULL); + bool clip = get(sym, keys::clip, feature, common_.vars_, true); + double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); + double opacity = get(sym,keys::stroke_opacity,feature, common_.vars_, 1.0); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, false); + line_rasterizer_enum rasterizer_e = get(sym, keys::line_rasterizer, feature, common_.vars_, RASTERIZER_FULL); if (clip) { double padding = static_cast(common_.query_extent_.width()/pixmap_.width()); @@ -135,11 +134,11 @@ void agg_renderer::process(line_symbolizer const& sym, renderer_type ren(renb, profile); ren.color(agg::rgba8_pre(r, g, b, int(a * opacity))); rasterizer_type ras(ren); - set_join_caps_aa(sym, ras, feature); + set_join_caps_aa(sym, ras, feature, common_.vars_); vertex_converter, rasterizer_type, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box,ras,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(clip_box,ras,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) converter.set(); // optional clip (default: true) converter.set(); // always transform if (std::fabs(offset) > 0.0) converter.set(); // parallel offset @@ -159,7 +158,7 @@ void agg_renderer::process(line_symbolizer const& sym, { vertex_converter, rasterizer, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(clip_box,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) converter.set(); // optional clip (default: true) converter.set(); // always transform diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 8ccd0c3cd..dafec0588 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -83,8 +82,8 @@ void agg_renderer::process(markers_symbolizer const& sym, detector_type > vector_dispatch_type; typedef raster_markers_rasterizer_dispatch raster_dispatch_type; - double gamma = get(sym, keys::gamma, feature, 1.0); - gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, GAMMA_POWER); + double gamma = get(sym, keys::gamma, feature, common_.vars_, 1.0); + gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, common_.vars_, GAMMA_POWER); if (gamma != gamma_ || gamma_method != gamma_method_) { set_gamma_method(ras_ptr, gamma, gamma_method); @@ -112,6 +111,7 @@ void agg_renderer::process(markers_symbolizer const& sym, marker_trans, sym, *common_.detector_, + feature, common_.vars_, common_.scale_factor_, snap_pixels); }, @@ -126,6 +126,7 @@ void agg_renderer::process(markers_symbolizer const& sym, marker_trans, sym, *common_.detector_, + feature, common_.vars_, common_.scale_factor_, true /*snap rasters no matter what*/); }); diff --git a/src/agg/process_point_symbolizer.cpp b/src/agg/process_point_symbolizer.cpp index 792c6d3eb..96d041068 100644 --- a/src/agg/process_point_symbolizer.cpp +++ b/src/agg/process_point_symbolizer.cpp @@ -25,7 +25,6 @@ #include #include #include - #include #include #include @@ -50,7 +49,7 @@ void agg_renderer::process(point_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); render_point_symbolizer( sym, feature, prj_trans, common_, diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index 8fe83c62e..0ed2d88c3 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -20,9 +20,6 @@ * *****************************************************************************/ -// boost - - // mapnik #include #include @@ -57,13 +54,27 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + std::string filename = get(sym, keys::file, feature, common_.vars_); + if (filename.empty()) return; + boost::optional marker = marker_cache::instance().find(filename, true); + if (!marker) return; + + if (!(*marker)->is_bitmap()) + { + MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; + return; + } + + boost::optional pat = (*marker)->get_bitmap_data(); + if (!pat) return; + typedef agg::conv_clip_polygon clipped_geometry_type; typedef coord_transform path_type; agg::rendering_buffer buf(current_buffer_->raw_data(), current_buffer_->width(), current_buffer_->height(), current_buffer_->width() * 4); ras_ptr->reset(); - double gamma = get(sym, keys::gamma, feature, 1.0); - gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, GAMMA_POWER); + double gamma = get(sym, keys::gamma, feature, common_.vars_, 1.0); + gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, common_.vars_, GAMMA_POWER); if (gamma != gamma_ || gamma_method != gamma_method_) { set_gamma_method(ras_ptr, gamma, gamma_method); @@ -71,34 +82,10 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, gamma_ = gamma; } - std::string filename = get(sym, keys::file, feature); - boost::optional marker; - if ( !filename.empty() ) - { - marker = marker_cache::instance().find(filename, true); - } - else - { - MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: File not found=" << filename; - } - - if (!marker) return; - - if (!(*marker)->is_bitmap()) - { - MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the polygon_pattern_symbolizer"; - - return; - } - - boost::optional pat = (*marker)->get_bitmap_data(); - - if (!pat) return; - - bool clip = get(sym, keys::clip, feature, false); - double opacity = get(sym,keys::stroke_opacity, 1.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, false); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double opacity = get(sym,keys::stroke_opacity, feature, common_.vars_, 1.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, false); box2d clip_box = clipping_extent(); @@ -121,7 +108,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, span_gen_type> renderer_type; pixfmt_type pixf(buf); - pixf.comp_op(get(sym, keys::comp_op, feature, agg::comp_op_src_over)); + pixf.comp_op(get(sym, keys::comp_op, feature, common_.vars_, agg::comp_op_src_over)); ren_base renb(pixf); unsigned w=(*pat)->width(); @@ -130,7 +117,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf); img_source_type img_src(pixf_pattern); - pattern_alignment_enum alignment = get(sym, keys::alignment, feature, LOCAL_ALIGNMENT); + pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, LOCAL_ALIGNMENT); unsigned offset_x=0; unsigned offset_y=0; @@ -156,12 +143,12 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, agg::trans_affine tr; auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, *transform, common_.scale_factor_); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); typedef boost::mpl::vector conv_types; vertex_converter, rasterizer, polygon_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(clip_box,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) converter.set(); //always transform diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 26198b05e..a53501a94 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -55,8 +55,8 @@ void agg_renderer::process(polygon_symbolizer const& sym, conv_types, feature_impl> vertex_converter_type; ras_ptr->reset(); - double gamma = get(sym, keys::gamma, feature, 1.0); - gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, GAMMA_POWER); + double gamma = get(sym, keys::gamma, feature, common_.vars_, 1.0); + gamma_method_enum gamma_method = get(sym, keys::gamma_method, feature, common_.vars_, GAMMA_POWER); if (gamma != gamma_ || gamma_method != gamma_method_) { set_gamma_method(ras_ptr, gamma, gamma_method); @@ -81,7 +81,7 @@ void agg_renderer::process(polygon_symbolizer const& sym, typedef agg::renderer_base renderer_base; typedef agg::renderer_scanline_aa_solid renderer_type; pixfmt_comp_type pixf(buf); - pixf.comp_op(get(sym, keys::comp_op, feature, agg::comp_op_src_over)); + pixf.comp_op(get(sym, keys::comp_op, feature, common_.vars_, agg::comp_op_src_over)); renderer_base renb(pixf); renderer_type ren(renb); ren.color(agg::rgba8_pre(r, g, b, int(a * opacity))); diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp index cd1023d71..e79664f3b 100644 --- a/src/agg/process_raster_symbolizer.cpp +++ b/src/agg/process_raster_symbolizer.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -53,11 +52,12 @@ void agg_renderer::process(raster_symbolizer const& sym, { render_raster_symbolizer( sym, feature, prj_trans, common_, - [&](raster &target, composite_mode_e comp_op, double opacity, + [&](image_data_32 & target, composite_mode_e comp_op, double opacity, int start_x, int start_y) { - composite(current_buffer_->data(), target.data_, + composite(current_buffer_->data(), target, comp_op, opacity, start_x, start_y, false); - }); + } + ); } template void agg_renderer::process(raster_symbolizer const&, diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index ba7d60436..2f4035045 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -38,21 +38,21 @@ void agg_renderer::process(shield_symbolizer const& sym, { box2d clip_box = clipping_extent(); text_symbolizer_helper helper( - sym, feature, prj_trans, + sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, clip_box); - halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, HALO_RASTERIZER_FULL); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, feature, common_.vars_, HALO_RASTERIZER_FULL); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); agg_text_renderer ren(*current_buffer_, halo_rasterizer, comp_op, common_.scale_factor_, common_.font_manager_.get_stroker()); - double opacity = get(sym,keys::opacity,feature, 1.0); + double opacity = get(sym,keys::opacity, feature, common_.vars_, 1.0); placements_list const& placements = helper.get(); for (glyph_positions_ptr glyphs : placements) diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index 01fadeef0..440123ea1 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -38,14 +38,14 @@ void agg_renderer::process(text_symbolizer const& sym, box2d clip_box = clipping_extent(); text_symbolizer_helper helper( - sym, feature, prj_trans, + sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, clip_box); - halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, HALO_RASTERIZER_FULL); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer,feature, common_.vars_, HALO_RASTERIZER_FULL); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); agg_text_renderer ren(*current_buffer_, halo_rasterizer, comp_op, @@ -56,7 +56,7 @@ void agg_renderer::process(text_symbolizer const& sym, auto transform = get_optional(sym, keys::halo_transform); if (transform) { - evaluate_transform(halo_transform, feature, *transform); + evaluate_transform(halo_transform, feature, common_.vars_, *transform); ren.set_halo_transform(halo_transform); } placements_list const& placements = helper.get(); diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index c236e3c71..33eb1db1e 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -58,6 +58,7 @@ #include #include #include +#include // mapnik symbolizer generics #include @@ -108,12 +109,13 @@ struct cairo_save_restore cairo_renderer_base::cairo_renderer_base(Map const& m, cairo_ptr const& cairo, + attributes const& vars, double scale_factor, unsigned offset_x, unsigned offset_y) : m_(m), context_(cairo), - common_(m, offset_x, offset_y, m.width(), m.height(), scale_factor), + common_(m, vars, offset_x, offset_y, m.width(), m.height(), scale_factor), face_manager_(common_.shared_font_engine_) { setup(m); @@ -122,12 +124,13 @@ cairo_renderer_base::cairo_renderer_base(Map const& m, cairo_renderer_base::cairo_renderer_base(Map const& m, request const& req, cairo_ptr const& cairo, + attributes const& vars, double scale_factor, unsigned offset_x, unsigned offset_y) : m_(m), context_(cairo), - common_(req, offset_x, offset_y, req.width(), req.height(), scale_factor), + common_(req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor), face_manager_(common_.shared_font_engine_) { setup(m); @@ -135,13 +138,14 @@ cairo_renderer_base::cairo_renderer_base(Map const& m, cairo_renderer_base::cairo_renderer_base(Map const& m, cairo_ptr const& cairo, + attributes const& vars, std::shared_ptr detector, double scale_factor, unsigned offset_x, unsigned offset_y) : m_(m), context_(cairo), - common_(m, offset_x, offset_y, m.width(), m.height(), scale_factor, detector), + common_(m, vars, offset_x, offset_y, m.width(), m.height(), scale_factor, detector), face_manager_(common_.shared_font_engine_) { MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << m.scale(); @@ -150,32 +154,32 @@ cairo_renderer_base::cairo_renderer_base(Map const& m, template <> cairo_renderer::cairo_renderer(Map const& m, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,cairo,scale_factor,offset_x,offset_y) {} + cairo_renderer_base(m,cairo,attributes(),scale_factor,offset_x,offset_y) {} template <> cairo_renderer::cairo_renderer(Map const& m, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,create_context(surface),scale_factor,offset_x,offset_y) {} + cairo_renderer_base(m,create_context(surface),attributes(),scale_factor,offset_x,offset_y) {} template <> -cairo_renderer::cairo_renderer(Map const& m, request const& req, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y) +cairo_renderer::cairo_renderer(Map const& m, request const& req, attributes const& vars, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,req,cairo,scale_factor,offset_x,offset_y) {} + cairo_renderer_base(m,req,cairo,vars,scale_factor,offset_x,offset_y) {} template <> -cairo_renderer::cairo_renderer(Map const& m, request const& req, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y) +cairo_renderer::cairo_renderer(Map const& m, request const& req, attributes const& vars, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,req, create_context(surface),scale_factor,offset_x,offset_y) {} + cairo_renderer_base(m,req,create_context(surface),attributes(),scale_factor,offset_x,offset_y) {} template <> cairo_renderer::cairo_renderer(Map const& m, cairo_ptr const& cairo, std::shared_ptr detector, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,cairo,detector,scale_factor,offset_x,offset_y) {} + cairo_renderer_base(m,cairo,attributes(),detector,scale_factor,offset_x,offset_y) {} template <> cairo_renderer::cairo_renderer(Map const& m, cairo_surface_ptr const& surface, std::shared_ptr detector, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,create_context(surface),detector,scale_factor,offset_x,offset_y) {} + cairo_renderer_base(m,create_context(surface),attributes(),detector,scale_factor,offset_x,offset_y) {} cairo_renderer_base::~cairo_renderer_base() {} @@ -279,7 +283,7 @@ void cairo_renderer_base::process(polygon_symbolizer const& sym, conv_types, feature_impl> vertex_converter_type; cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); context_.set_operator(comp_op); render_polygon_symbolizer( @@ -298,10 +302,10 @@ void cairo_renderer_base::process(building_symbolizer const& sym, { typedef coord_transform path_type; cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); - mapnik::color fill = get(sym, keys::fill, feature); - double opacity = get(sym, keys::fill_opacity, feature, 1.0); - double height = get(sym, keys::height, feature, 0.0); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + mapnik::color fill = get(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); + double opacity = get(sym, keys::fill_opacity, feature, common_.vars_, 1.0); + double height = get(sym, keys::height, feature, common_.vars_, 0.0); context_.set_operator(comp_op); @@ -340,21 +344,19 @@ void cairo_renderer_base::process(line_symbolizer const& sym, offset_transform_tag, dash_tag, stroke_tag> conv_types; cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); - auto geom_transform = get_optional(sym, keys::geometry_transform); - bool clip = get(sym, keys::clip, feature, true); - double offset = get(sym, keys::offset, feature, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, 0.0); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + bool clip = get(sym, keys::clip, feature, common_.vars_, true); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); - mapnik::color stroke = get(sym, keys::stroke, feature, mapnik::color(0,0,0)); - double stroke_opacity = get(sym, keys::stroke_opacity, feature, 1.0); - line_join_enum stroke_join = get(sym, keys::stroke_linejoin, MITER_JOIN); - line_cap_enum stroke_cap = get(sym, keys::stroke_linecap, BUTT_CAP); + mapnik::color stroke = get(sym, keys::stroke, feature, common_.vars_, mapnik::color(0,0,0)); + double stroke_opacity = get(sym, keys::stroke_opacity, feature, common_.vars_, 1.0); + line_join_enum stroke_join = get(sym, keys::stroke_linejoin, feature, common_.vars_, MITER_JOIN); + line_cap_enum stroke_cap = get(sym, keys::stroke_linecap, feature, common_.vars_, BUTT_CAP); auto dash = get_optional(sym, keys::stroke_dasharray); - double miterlimit = get(sym, keys::stroke_miterlimit, feature, 4.0); - double width = get(sym, keys::stroke_width, feature, 1.0); - + double miterlimit = get(sym, keys::stroke_miterlimit, feature, common_.vars_, 4.0); + double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); context_.set_operator(comp_op); context_.set_color(stroke, stroke_opacity); @@ -368,7 +370,8 @@ void cairo_renderer_base::process(line_symbolizer const& sym, } agg::trans_affine tr; - if (geom_transform) { evaluate_transform(tr, feature, *geom_transform, common_.scale_factor_); } + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } box2d clipping_extent = common_.query_extent_; if (clip) @@ -384,7 +387,7 @@ void cairo_renderer_base::process(line_symbolizer const& sym, } vertex_converter, cairo_context, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clipping_extent,context_,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(clipping_extent,context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) converter.set(); // optional clip (default: true) converter.set(); // always transform @@ -553,7 +556,7 @@ void cairo_renderer_base::process(point_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); cairo_save_restore guard(context_); context_.set_operator(comp_op); @@ -571,15 +574,15 @@ void cairo_renderer_base::process(shield_symbolizer const& sym, proj_transform const& prj_trans) { text_symbolizer_helper helper( - sym, feature, prj_trans, + sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, common_.query_extent_); cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); - double opacity = get(sym,keys::opacity,feature, 1.0); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + double opacity = get(sym,keys::opacity,feature, common_.vars_, 1.0); context_.set_operator(comp_op); @@ -605,8 +608,8 @@ void cairo_renderer_base::process(line_pattern_symbolizer const& sym, typedef agg::conv_clip_polyline clipped_geometry_type; typedef coord_transform path_type; - std::string filename = get(sym, keys::file, feature); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + std::string filename = get(sym, keys::file, feature, common_.vars_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); boost::optional marker; if ( !filename.empty() ) @@ -690,12 +693,11 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, //typedef coord_transform path_type; cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); - std::string filename = get(sym, keys::file, feature); - auto geom_transform = get_optional(sym, keys::geometry_transform); - bool clip = get(sym, keys::clip, feature, false); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, 0.0); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + std::string filename = get(sym, keys::file, feature, common_.vars_); + bool clip = get(sym, keys::clip, feature, common_.vars_, true); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); context_.set_operator(comp_op); @@ -728,12 +730,13 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, //} agg::trans_affine tr; - if (geom_transform) { evaluate_transform(tr, feature, *geom_transform, common_.scale_factor_); } + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } typedef boost::mpl::vector conv_types; vertex_converter, cairo_context, polygon_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(common_.query_extent_,context_,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(common_.query_extent_,context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) converter.set(); //always transform @@ -758,14 +761,14 @@ void cairo_renderer_base::process(raster_symbolizer const& sym, proj_transform const& prj_trans) { cairo_save_restore guard(context_); - render_raster_symbolizer( sym, feature, prj_trans, common_, - [&](raster &target, composite_mode_e comp_op, double opacity, + [&](image_data_32 &target, composite_mode_e comp_op, double opacity, int start_x, int start_y) { context_.set_operator(comp_op); - context_.add_image(start_x, start_y, target.data_, opacity); - }); + context_.add_image(start_x, start_y, target, opacity); + } + ); } namespace detail { @@ -780,6 +783,8 @@ struct markers_dispatch markers_symbolizer const& sym, box2d const& bbox, agg::trans_affine const& marker_trans, + feature_impl const& feature, + mapnik::attributes const& vars, double scale_factor) :ctx_(ctx), marker_(marker), @@ -788,19 +793,20 @@ struct markers_dispatch sym_(sym), bbox_(bbox), marker_trans_(marker_trans), + feature_(feature), + vars_(vars), scale_factor_(scale_factor) {} template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, false); - bool allow_overlap = get(sym_, keys::allow_overlap, false); - double opacity = get(sym_, keys::opacity, 1.0); - - double spacing = get(sym_, keys::spacing, 100.0); - double max_error = get(sym_, keys::max_error, 0.2); + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); if (placement_method != MARKER_LINE_PLACEMENT || path.type() == geometry_type::types::Point) @@ -864,6 +870,8 @@ struct markers_dispatch markers_symbolizer const& sym_; box2d const& bbox_; agg::trans_affine const& marker_trans_; + feature_impl const& feature_; + attributes const& vars_; double scale_factor_; }; @@ -876,6 +884,8 @@ struct markers_dispatch_2 markers_symbolizer const& sym, box2d const& bbox, agg::trans_affine const& marker_trans, + feature_impl const& feature, + mapnik::attributes const& vars, double scale_factor) :ctx_(ctx), marker_(marker), @@ -883,18 +893,20 @@ struct markers_dispatch_2 sym_(sym), bbox_(bbox), marker_trans_(marker_trans), + feature_(feature), + vars_(vars), scale_factor_(scale_factor) {} template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT); - double opacity = get(sym_, keys::opacity, 1.0); - double spacing = get(sym_, keys::spacing, 100.0); - double max_error = get(sym_, keys::max_error, 0.2); - bool allow_overlap = get(sym_, keys::allow_overlap, false); - bool ignore_placement = get(sym_, keys::ignore_placement, false); + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); if (placement_method != MARKER_LINE_PLACEMENT || path.type() == geometry_type::types::Point) @@ -958,6 +970,8 @@ struct markers_dispatch_2 markers_symbolizer const& sym_; box2d const& bbox_; agg::trans_affine const& marker_trans_; + feature_impl const& feature_; + attributes const& vars_; double scale_factor_; }; @@ -973,7 +987,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym, label_collision_detector4> vector_dispatch_type; cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); context_.set_operator(comp_op); box2d clip_box = common_.query_extent_; @@ -983,12 +997,12 @@ void cairo_renderer_base::process(markers_symbolizer const& sym, box2d const &bbox, agg::trans_affine const &marker_trans, bool) -> vector_dispatch_type { return vector_dispatch_type(context_, marker, attr, *common_.detector_, sym, bbox, - marker_trans, common_.scale_factor_); + marker_trans, feature, common_.vars_, common_.scale_factor_); }, [&](image_data_32 &marker, agg::trans_affine const &marker_trans, box2d const &bbox) -> raster_dispatch_type { return raster_dispatch_type(context_, marker, *common_.detector_, sym, bbox, - marker_trans, common_.scale_factor_); + marker_trans, feature, common_.vars_, common_.scale_factor_); }); } @@ -997,15 +1011,14 @@ void cairo_renderer_base::process(text_symbolizer const& sym, proj_transform const& prj_trans) { text_symbolizer_helper helper( - sym, feature, prj_trans, + sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, common_.query_extent_); cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); - + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); context_.set_operator(comp_op); placements_list const &placements = helper.get(); @@ -1085,7 +1098,7 @@ void cairo_renderer_base::process(group_symbolizer const& sym, proj_transform const& prj_trans) { render_group_symbolizer( - sym, feature, prj_trans, common_.query_extent_, common_, + sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, [&](render_thunk_list const& thunks, pixel_position const& render_offset) { thunk_renderer ren(*this, context_, face_manager_, common_, render_offset); @@ -1123,7 +1136,7 @@ void cairo_renderer_base::process(debug_symbolizer const& sym, typedef label_collision_detector4 detector_type; cairo_save_restore guard(context_); - debug_symbolizer_mode_enum mode = get(sym, keys::mode, DEBUG_SYM_MODE_COLLISION); + debug_symbolizer_mode_enum mode = get(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); context_.set_operator(src_over); context_.set_color(mapnik::color(255, 0, 0), 1.0); diff --git a/src/grid/grid_renderer.cpp b/src/grid/grid_renderer.cpp index 43f92642e..bb0c5ef5b 100644 --- a/src/grid/grid_renderer.cpp +++ b/src/grid/grid_renderer.cpp @@ -63,19 +63,19 @@ grid_renderer::grid_renderer(Map const& m, T & pixmap, double scale_factor, u ras_ptr(new grid_rasterizer), // NOTE: can change this to m dims instead of pixmap_ if render-time // resolution support is dropped from grid_renderer python interface - common_(m, offset_x, offset_y, pixmap_.width(), pixmap_.height(), scale_factor) + common_(m, attributes(), offset_x, offset_y, pixmap_.width(), pixmap_.height(), scale_factor) { setup(m); } template -grid_renderer::grid_renderer(Map const& m, request const& req, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y) +grid_renderer::grid_renderer(Map const& m, request const& req, attributes const& vars, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m, scale_factor), pixmap_(pixmap), ras_ptr(new grid_rasterizer), // NOTE: can change this to m dims instead of pixmap_ if render-time // resolution support is dropped from grid_renderer python interface - common_(req, offset_x, offset_y, pixmap_.width(), pixmap_.height(), scale_factor) + common_(req, vars, offset_x, offset_y, pixmap_.width(), pixmap_.height(), scale_factor) { setup(m); } diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp index e39b37784..3779a1c99 100644 --- a/src/grid/process_building_symbolizer.cpp +++ b/src/grid/process_building_symbolizer.cpp @@ -68,7 +68,7 @@ void grid_renderer::process(building_symbolizer const& sym, ras_ptr->reset(); - double height = get(sym, keys::height,feature, 0.0); + double height = get(sym, keys::height, feature, common_.vars_, 0.0); render_building_symbolizer( feature, height, diff --git a/src/grid/process_group_symbolizer.cpp b/src/grid/process_group_symbolizer.cpp index 45bc78c3a..fc75cf82b 100644 --- a/src/grid/process_group_symbolizer.cpp +++ b/src/grid/process_group_symbolizer.cpp @@ -117,7 +117,7 @@ void grid_renderer::process(group_symbolizer const& sym, proj_transform const& prj_trans) { render_group_symbolizer( - sym, feature, prj_trans, common_.query_extent_, common_, + sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, [&](render_thunk_list const& thunks, pixel_position const& render_offset) { thunk_renderer ren(*this, pixmap_, common_, feature, render_offset); diff --git a/src/grid/process_line_pattern_symbolizer.cpp b/src/grid/process_line_pattern_symbolizer.cpp index b7521aba4..5e80c2a97 100644 --- a/src/grid/process_line_pattern_symbolizer.cpp +++ b/src/grid/process_line_pattern_symbolizer.cpp @@ -50,9 +50,9 @@ void grid_renderer::process(line_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - std::string filename = get(sym, keys::file, feature); - - boost::optional mark = marker_cache::instance().find(filename,true); + std::string filename = get(sym, keys::file, feature, common_.vars_); + if (filename.empty()) return; + boost::optional mark = marker_cache::instance().find(filename, true); if (!mark) return; if (!(*mark)->is_bitmap()) @@ -64,10 +64,10 @@ void grid_renderer::process(line_pattern_symbolizer const& sym, boost::optional pat = (*mark)->get_bitmap_data(); if (!pat) return; - bool clip = get(sym, keys::clip, feature); - double offset = get(sym, keys::offset, feature, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, false); + bool clip = get(sym, keys::clip, feature, common_.vars_, true); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, false); typedef typename grid_renderer_base_type::pixfmt_type pixfmt_type; typedef typename grid_renderer_base_type::pixfmt_type::color_type color_type; @@ -89,7 +89,10 @@ void grid_renderer::process(line_pattern_symbolizer const& sym, agg::trans_affine tr; auto transform = get_optional(sym, keys::geometry_transform); - if (transform) { evaluate_transform(tr, feature, *transform, common_.scale_factor_); } + if (transform) + { + evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + } box2d clipping_extent = common_.query_extent_; if (clip) @@ -117,7 +120,7 @@ void grid_renderer::process(line_pattern_symbolizer const& sym, vertex_converter, grid_rasterizer, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clipping_extent,*ras_ptr,line,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(clipping_extent,*ras_ptr,line,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) converter.set(); // optional clip (default: true) converter.set(); // always transform if (std::fabs(offset) > 0.0) converter.set(); // parallel offset diff --git a/src/grid/process_line_symbolizer.cpp b/src/grid/process_line_symbolizer.cpp index 6a5b2b337..fa7f26610 100644 --- a/src/grid/process_line_symbolizer.cpp +++ b/src/grid/process_line_symbolizer.cpp @@ -65,15 +65,18 @@ void grid_renderer::process(line_symbolizer const& sym, agg::trans_affine tr; auto transform = get_optional(sym, keys::geometry_transform); - if (transform) { evaluate_transform(tr, feature, *transform, common_.scale_factor_); } + if (transform) + { + evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + } box2d clipping_extent = common_.query_extent_; - bool clip = get(sym, keys::clip, feature, true); - double width = get(sym, keys::stroke_width, feature, 1.0); - double offset = get(sym, keys::offset, feature, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, false); + bool clip = get(sym, keys::clip, feature, common_.vars_, true); + double width = get(sym, keys::stroke_width, feature, common_.vars_,1.0); + double offset = get(sym, keys::offset, feature, common_.vars_,0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_,0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_,false); bool has_dash = has_key(sym, keys::stroke_dasharray); if (clip) @@ -90,7 +93,7 @@ void grid_renderer::process(line_symbolizer const& sym, vertex_converter, grid_rasterizer, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clipping_extent,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(clipping_extent,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) converter.set(); // optional clip (default: true) converter.set(); // always transform if (std::fabs(offset) > 0.0) converter.set(); // parallel offset diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 191e4f005..0b3be19ee 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -129,6 +129,7 @@ void grid_renderer::process(markers_symbolizer const& sym, *common_.detector_, common_.scale_factor_, feature, + common_.vars_, pixmap_); }, [&](image_data_32 const &marker, agg::trans_affine const &tr, @@ -145,6 +146,7 @@ void grid_renderer::process(markers_symbolizer const& sym, *common_.detector_, common_.scale_factor_, feature, + common_.vars_, pixmap_); }); } diff --git a/src/grid/process_point_symbolizer.cpp b/src/grid/process_point_symbolizer.cpp index 1ef96d5b9..7606f8f71 100644 --- a/src/grid/process_point_symbolizer.cpp +++ b/src/grid/process_point_symbolizer.cpp @@ -52,7 +52,7 @@ void grid_renderer::process(point_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); render_point_symbolizer( sym, feature, prj_trans, common_, diff --git a/src/grid/process_polygon_pattern_symbolizer.cpp b/src/grid/process_polygon_pattern_symbolizer.cpp index 141cb8850..d3ab1dd67 100644 --- a/src/grid/process_polygon_pattern_symbolizer.cpp +++ b/src/grid/process_polygon_pattern_symbolizer.cpp @@ -52,9 +52,9 @@ void grid_renderer::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - std::string filename = get(sym, keys::file, feature); - - boost::optional mark = marker_cache::instance().find(filename,true); + std::string filename = get(sym, keys::file, feature, common_.vars_); + if (filename.empty()) return; + boost::optional mark = marker_cache::instance().find(filename, true); if (!mark) return; if (!(*mark)->is_bitmap()) @@ -68,18 +68,21 @@ void grid_renderer::process(polygon_pattern_symbolizer const& sym, ras_ptr->reset(); - bool clip = get(sym, keys::clip, feature, false); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, 0.0); - double smooth = get(sym, keys::smooth, feature, false); + bool clip = get(sym, keys::clip, feature, common_.vars_, true); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, false); agg::trans_affine tr; - auto geom_transform = get_optional(sym, keys::geometry_transform); - if (geom_transform) evaluate_transform(tr, feature, *geom_transform, common_.scale_factor_); + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) + { + evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + } typedef boost::mpl::vector conv_types; vertex_converter, grid_rasterizer, polygon_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(common_.query_extent_,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.scale_factor_); + converter(common_.query_extent_,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) converter.set(); //always transform diff --git a/src/grid/process_shield_symbolizer.cpp b/src/grid/process_shield_symbolizer.cpp index c2dcc69ce..28ce40acc 100644 --- a/src/grid/process_shield_symbolizer.cpp +++ b/src/grid/process_shield_symbolizer.cpp @@ -44,15 +44,15 @@ void grid_renderer::process(shield_symbolizer const& sym, proj_transform const& prj_trans) { text_symbolizer_helper helper( - sym, feature, prj_trans, + sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, common_.query_extent_); bool placement_found = false; - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); - double opacity = get(sym,keys::opacity,feature, 1.0); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + double opacity = get(sym, keys::opacity, feature, common_.vars_, 1.0); grid_text_renderer ren(pixmap_, comp_op, diff --git a/src/grid/process_text_symbolizer.cpp b/src/grid/process_text_symbolizer.cpp index 21755040c..27b3d9344 100644 --- a/src/grid/process_text_symbolizer.cpp +++ b/src/grid/process_text_symbolizer.cpp @@ -37,14 +37,14 @@ void grid_renderer::process(text_symbolizer const& sym, proj_transform const& prj_trans) { text_symbolizer_helper helper( - sym, feature, prj_trans, + sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_ * (1.0/pixmap_.get_resolution()), common_.t_, common_.font_manager_, *common_.detector_, common_.query_extent_); bool placement_found = false; - composite_mode_e comp_op = get(sym, keys::comp_op, feature, src_over); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); grid_text_renderer ren(pixmap_, comp_op, diff --git a/src/group/group_symbolizer_helper.cpp b/src/group/group_symbolizer_helper.cpp index f877df345..4c174b647 100644 --- a/src/group/group_symbolizer_helper.cpp +++ b/src/group/group_symbolizer_helper.cpp @@ -39,11 +39,12 @@ namespace mapnik { group_symbolizer_helper::group_symbolizer_helper( const group_symbolizer &sym, const feature_impl &feature, + attributes const& vars, const proj_transform &prj_trans, unsigned width, unsigned height, double scale_factor, const CoordTransform &t, DetectorType &detector, const box2d &query_extent) - : base_symbolizer_helper(sym, feature, prj_trans, width, height, scale_factor, t, query_extent), + : base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent), detector_(detector) {} diff --git a/src/renderer_common.cpp b/src/renderer_common.cpp index 10b875011..3d886baae 100644 --- a/src/renderer_common.cpp +++ b/src/renderer_common.cpp @@ -24,14 +24,18 @@ #include #include #include +#include namespace mapnik { renderer_common::renderer_common(unsigned width, unsigned height, double scale_factor, - CoordTransform &&t, std::shared_ptr detector) + attributes const& vars, + CoordTransform && t, + std::shared_ptr detector) : width_(width), height_(height), scale_factor_(scale_factor), + vars_(vars), shared_font_engine_(std::make_shared()), font_engine_(*shared_font_engine_), font_manager_(font_engine_), @@ -40,26 +44,29 @@ renderer_common::renderer_common(unsigned width, unsigned height, double scale_f detector_(detector) {} -renderer_common::renderer_common(Map const &m, unsigned offset_x, unsigned offset_y, +renderer_common::renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor) : renderer_common(width, height, scale_factor, + vars, CoordTransform(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y), std::make_shared( box2d(-m.buffer_size(), -m.buffer_size(), m.width() + m.buffer_size() ,m.height() + m.buffer_size()))) {} -renderer_common::renderer_common(Map const &m, unsigned offset_x, unsigned offset_y, +renderer_common::renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor, std::shared_ptr detector) : renderer_common(width, height, scale_factor, + vars, CoordTransform(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y), detector) {} -renderer_common::renderer_common(request const &req, unsigned offset_x, unsigned offset_y, +renderer_common::renderer_common(request const &req, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor) : renderer_common(width, height, scale_factor, + vars, CoordTransform(req.width(),req.height(),req.extent(),offset_x,offset_y), std::make_shared( box2d(-req.buffer_size(), -req.buffer_size(), @@ -70,6 +77,7 @@ renderer_common::renderer_common(renderer_common const &other) : width_(other.width_), height_(other.height_), scale_factor_(other.scale_factor_), + vars_(other.vars_), shared_font_engine_(other.shared_font_engine_), font_engine_(*shared_font_engine_), font_manager_(font_engine_), diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp index 9e0174f32..4223fd07b 100644 --- a/src/renderer_common/process_group_symbolizer.cpp +++ b/src/renderer_common/process_group_symbolizer.cpp @@ -72,17 +72,18 @@ text_render_thunk::text_render_thunk(placements_list const &placements, render_thunk_extractor::render_thunk_extractor(box2d &box, render_thunk_list &thunks, - mapnik::feature_impl &feature, + feature_impl &feature, + attributes const& vars, proj_transform const &prj_trans, renderer_common &common, box2d const &clipping_extent) - : box_(box), thunks_(thunks), feature_(feature), prj_trans_(prj_trans), + : box_(box), thunks_(thunks), feature_(feature), vars_(vars), prj_trans_(prj_trans), common_(common), clipping_extent_(clipping_extent) {} void render_thunk_extractor::operator()(point_symbolizer const &sym) const { - composite_mode_e comp_op = get(sym, keys::comp_op, feature_, src_over); + composite_mode_e comp_op = get(sym, keys::comp_op, feature_, common_.vars_, src_over); render_point_symbolizer( sym, feature_, prj_trans_, common_, @@ -99,7 +100,7 @@ void render_thunk_extractor::operator()(text_symbolizer const &sym) const { box2d clip_box = clipping_extent_; text_symbolizer_helper helper( - sym, feature_, prj_trans_, + sym, feature_, vars_, prj_trans_, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, @@ -112,7 +113,7 @@ void render_thunk_extractor::operator()(shield_symbolizer const &sym) const { box2d clip_box = clipping_extent_; text_symbolizer_helper helper( - sym, feature_, prj_trans_, + sym, feature_, vars_, prj_trans_, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, @@ -123,9 +124,9 @@ void render_thunk_extractor::operator()(shield_symbolizer const &sym) const void render_thunk_extractor::extract_text_thunk(text_symbolizer_helper &helper, text_symbolizer const &sym) const { - double opacity = get(sym, keys::opacity, feature_, 1.0); - composite_mode_e comp_op = get(sym, keys::comp_op, feature_, src_over); - halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, HALO_RASTERIZER_FULL); + double opacity = get(sym, keys::opacity, feature_, common_.vars_, 1.0); + composite_mode_e comp_op = get(sym, keys::comp_op, feature_, common_.vars_, src_over); + halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL); placements_list const& placements = helper.get(); text_render_thunk thunk(placements, opacity, comp_op, halo_rasterizer); diff --git a/src/svg/output/svg_renderer.cpp b/src/svg/output/svg_renderer.cpp index 5265a126b..68ba930dc 100644 --- a/src/svg/output/svg_renderer.cpp +++ b/src/svg/output/svg_renderer.cpp @@ -42,16 +42,16 @@ svg_renderer::svg_renderer(Map const& m, T & output_iterator, double scale_fa output_iterator_(output_iterator), generator_(output_iterator), painted_(false), - common_(m, offset_x, offset_y, m.width(), m.height(), scale_factor) + common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor) {} template -svg_renderer::svg_renderer(Map const& m, request const& req, T & output_iterator, double scale_factor, unsigned offset_x, unsigned offset_y) : +svg_renderer::svg_renderer(Map const& m, request const& req, attributes const& vars, T & output_iterator, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m, scale_factor), output_iterator_(output_iterator), generator_(output_iterator), painted_(false), - common_(req, offset_x, offset_y, req.width(), req.height(), scale_factor) + common_(req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor) {} template diff --git a/src/symbolizer.cpp b/src/symbolizer.cpp index 8852feecc..d92e42b6d 100644 --- a/src/symbolizer.cpp +++ b/src/symbolizer.cpp @@ -29,7 +29,9 @@ namespace mapnik { // START FIXME - move to its own compilation unit -void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature, +void evaluate_transform(agg::trans_affine& tr, + feature_impl const& feature, + attributes const& vars, transform_list_ptr const& trans_expr, double scale_factor) { if (trans_expr) @@ -38,7 +40,7 @@ void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature, MAPNIK_LOG_DEBUG(transform) << "transform: evaluate " << transform_processor_type::to_string(*trans_expr); #endif - transform_processor_type::evaluate(tr, feature, *trans_expr, scale_factor); + transform_processor_type::evaluate(tr, feature, vars, *trans_expr, scale_factor); } } // END FIXME diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index e488ff2bc..022a74f15 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -94,7 +94,9 @@ static const property_meta_type key_meta[to_integral(keys::MAX_SYMBOLIZER_KEY)] property_meta_type{ "num-columns", static_cast(0), nullptr, property_types::target_integer}, property_meta_type{ "start-column", static_cast(1), nullptr, property_types::target_integer}, property_meta_type{ "repeat-key", nullptr, nullptr, property_types::target_repeat_key}, - property_meta_type{ "symbolizer-properties", nullptr, nullptr, property_types::target_group_symbolizer_properties} + property_meta_type{ "symbolizer-properties", nullptr, nullptr, property_types::target_group_symbolizer_properties}, + property_meta_type{ "largest-box-only", false, nullptr, property_types::target_bool }, + property_meta_type{ "minimum-path-length", false, nullptr, property_types::target_double } }; property_meta_type const& get_meta(mapnik::keys key) diff --git a/src/text/formatting/expression.cpp b/src/text/formatting/expression.cpp index c351af700..899a44a79 100644 --- a/src/text/formatting/expression.cpp +++ b/src/text/formatting/expression.cpp @@ -32,10 +32,8 @@ #include //boost - #include - namespace mapnik { namespace formatting { @@ -82,31 +80,30 @@ expression_ptr expression_format::get_expression(xml_node const& xml, std::strin return expression_ptr(); } - -void expression_format::apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const +void expression_format::apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { char_properties_ptr new_properties = std::make_shared(*p); if (face_name) new_properties->face_name = - boost::apply_visitor(evaluate(feature), *face_name).to_string(); + boost::apply_visitor(evaluate(feature,vars), *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,vars), *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,vars), *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,vars), *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,vars), *text_opacity).to_double(); if (wrap_char) new_properties->wrap_char = - boost::apply_visitor(evaluate(feature), *character_spacing).to_unicode()[0]; + boost::apply_visitor(evaluate(feature,vars), *character_spacing).to_unicode()[0]; if (fill) new_properties->fill = parse_color( - boost::apply_visitor(evaluate(feature), *fill).to_string()); + boost::apply_visitor(evaluate(feature,vars), *fill).to_string()); if (halo_fill) new_properties->halo_fill = parse_color( - boost::apply_visitor(evaluate(feature), *halo_fill).to_string()); + boost::apply_visitor(evaluate(feature,vars), *halo_fill).to_string()); if (halo_radius) new_properties->halo_radius = - boost::apply_visitor(evaluate(feature), *halo_radius).to_double(); + boost::apply_visitor(evaluate(feature,vars), *halo_radius).to_double(); if (child_) { - child_->apply(new_properties, feature, output); + child_->apply(new_properties, feature, vars, output); } else { MAPNIK_LOG_WARN(expression) << "Useless format: No text to format"; } diff --git a/src/text/formatting/format.cpp b/src/text/formatting/format.cpp index 998b0f392..4faef5c6a 100644 --- a/src/text/formatting/format.cpp +++ b/src/text/formatting/format.cpp @@ -77,7 +77,7 @@ node_ptr format_node::from_xml(xml_node const& xml) } -void format_node::apply(char_properties_ptr p, const feature_impl &feature, text_layout &output) const +void format_node::apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { char_properties_ptr new_properties = std::make_shared(*p); if (face_name) new_properties->face_name = *face_name; @@ -92,7 +92,7 @@ void format_node::apply(char_properties_ptr p, const feature_impl &feature, text if (halo_radius) new_properties->halo_radius = *halo_radius; if (child_) { - child_->apply(new_properties, feature, output); + child_->apply(new_properties, feature, vars, output); } else { MAPNIK_LOG_WARN(format) << "Useless format: No text to format"; } diff --git a/src/text/formatting/layout.cpp b/src/text/formatting/layout.cpp index d21550d9f..71935b666 100644 --- a/src/text/formatting/layout.cpp +++ b/src/text/formatting/layout.cpp @@ -79,7 +79,7 @@ node_ptr layout_node::from_xml(xml_node const& xml) return n; } -void layout_node::apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const +void layout_node::apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { text_layout_properties_ptr new_properties = std::make_shared(*output.get_layout_properties()); if (dx) new_properties->displacement.x = *dx; @@ -95,11 +95,11 @@ void layout_node::apply(char_properties_ptr p, feature_impl const& feature, text // starting a new offset child with the new displacement value text_layout_ptr child_layout = std::make_shared(output.get_font_manager(), output.get_scale_factor(), new_properties); - child_layout->init_orientation(feature); + child_layout->init_orientation(feature,vars); // process contained format tree into the child node if (child_) { - child_->apply(p, feature, *child_layout); + child_->apply(p, feature, vars, *child_layout); } else { MAPNIK_LOG_WARN(format) << "Useless layout node: Contains no text"; } diff --git a/src/text/formatting/list.cpp b/src/text/formatting/list.cpp index 0aa39d30d..e6487d657 100644 --- a/src/text/formatting/list.cpp +++ b/src/text/formatting/list.cpp @@ -42,11 +42,11 @@ void list_node::to_xml(boost::property_tree::ptree & xml) const } -void list_node::apply(char_properties_ptr p, feature_impl const& feature, text_layout & output) const +void list_node::apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout & output) const { for (node_ptr const& node : children_) { - node->apply(p, feature, output); + node->apply(p, feature, vars, output); } } diff --git a/src/text/formatting/text.cpp b/src/text/formatting/text.cpp index 20a094e4d..568434c0e 100644 --- a/src/text/formatting/text.cpp +++ b/src/text/formatting/text.cpp @@ -28,13 +28,9 @@ #include #include -//boost - - // boost #include - namespace mapnik { namespace formatting @@ -54,9 +50,9 @@ node_ptr text_node::from_xml(xml_node const& xml) return std::make_shared(xml.get_value()); } -void text_node::apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const +void text_node::apply(char_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const { - mapnik::value_unicode_string text_str = boost::apply_visitor(evaluate(feature), *text_).to_unicode(); + mapnik::value_unicode_string text_str = boost::apply_visitor(evaluate(feature,vars), *text_).to_unicode(); if (p->text_transform == UPPERCASE) { text_str = text_str.toUpper(); diff --git a/src/text/layout.cpp b/src/text/layout.cpp index 770bea7e9..b1b59b2db 100644 --- a/src/text/layout.cpp +++ b/src/text/layout.cpp @@ -235,12 +235,12 @@ void text_layout::shape_text(text_line & line) shaper_type::shape_text(line, itemizer_, width_map_, font_manager_, scale_factor_); } -void text_layout::init_orientation(feature_impl const& feature) +void text_layout::init_orientation(feature_impl const& feature, attributes const& attr) { if (properties_->orientation) { // https://github.com/mapnik/mapnik/issues/1352 - mapnik::evaluate evaluator(feature); + mapnik::evaluate evaluator(feature,attr); orientation_.init( boost::apply_visitor( evaluator, diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index 1494580ec..31744619e 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -41,12 +41,14 @@ namespace mapnik { placement_finder::placement_finder(feature_impl const& feature, + attributes const& attr, DetectorType &detector, box2d const& extent, text_placement_info_ptr placement_info, face_manager_freetype & font_manager, double scale_factor) : feature_(feature), + attr_(attr), detector_(detector), extent_(extent), info_(placement_info), @@ -74,8 +76,8 @@ bool placement_finder::next_position() } text_layout_ptr layout = std::make_shared(font_manager_, scale_factor_, info_->properties.layout_defaults); - layout->init_orientation(feature_); - info_->properties.process(*layout, feature_); + layout->init_orientation(feature_, attr_); + info_->properties.process(*layout, feature_, attr_); layouts_.clear(); layouts_.add(layout); @@ -266,11 +268,11 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or for (auto const& line : layout) { - //Only subtract half the line height here and half at the end because text is automatically - //centered on the line + // Only subtract half the line height here and half at the end because text is automatically + // centered on the line offset -= sign * line.height()/2; vertex_cache & off_pp = pp.get_offseted(offset, sign*layout.width()); - vertex_cache::scoped_state off_state(off_pp); //TODO: Remove this when a clean implementation in vertex_cache::get_offseted was done + vertex_cache::scoped_state off_state(off_pp); // TODO: Remove this when a clean implementation in vertex_cache::get_offseted is done if (!off_pp.move(sign * layout.jalign_offset(line.width()) - align_offset.x)) return false; @@ -291,7 +293,7 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or } current_cluster = glyph.char_index; last_glyph_spacing = glyph.format->character_spacing * scale_factor_; - //Only calculate new angle at the start of each cluster! + // Only calculate new angle at the start of each cluster! angle = normalize_angle(off_pp.angle(sign * layout.cluster_width(current_cluster))); rot.init(angle); if ((info_->properties.max_char_angle_delta > 0) && (last_cluster_angle != 999) && @@ -306,7 +308,7 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or if (std::abs(angle) > M_PI/2) ++upside_down_glyph_count; pixel_position pos = off_pp.current_position() + cluster_offset; - //Center the text on the line + // Center the text on the line double char_height = line.max_char_height(); pos.y = -pos.y - char_height/2.0*rot.cos; pos.x = pos.x + char_height/2.0*rot.sin; @@ -319,20 +321,20 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or bboxes.push_back(std::move(bbox)); glyphs->push_back(glyph, pos, rot); } - //See comment above + // See comment above offset -= sign * line.height()/2; } } - if (upside_down_glyph_count > (layouts_.text().length() / 2)) + if (upside_down_glyph_count > static_cast(layouts_.text().length() / 2)) { if (orientation == UPRIGHT_AUTO) { - //Try again with oposite orientation + // Try again with opposite orientation begin.restore(); return single_line_placement(pp, real_orientation == UPRIGHT_RIGHT ? UPRIGHT_LEFT : UPRIGHT_RIGHT); } - //upright==left_only or right_only and more than 50% of characters upside down => no placement + // upright==left_only or right_only and more than 50% of characters upside down => no placement else if (orientation == UPRIGHT_LEFT_ONLY || orientation == UPRIGHT_RIGHT_ONLY) { return false; diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index f21ec5f15..345d50ded 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -41,19 +41,23 @@ namespace mapnik { base_symbolizer_helper::base_symbolizer_helper( - const symbolizer_base &sym, const feature_impl &feature, - const proj_transform &prj_trans, + symbolizer_base const& sym, + feature_impl const& feature, + attributes const& vars, + proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, - const CoordTransform &t, const box2d &query_extent) + CoordTransform const& t, + box2d const& query_extent) : sym_(sym), feature_(feature), + vars_(vars), prj_trans_(prj_trans), t_(t), dims_(0, 0, width, height), query_extent_(query_extent), scale_factor_(scale_factor), - clipped_(mapnik::get(sym_, keys::clip, feature_, true /*TODO*/)), - placement_(mapnik::get(sym_, keys::text_placements_)->get_placement_info(scale_factor)) + clipped_(get(sym_, keys::clip, feature_, vars, true)), + placement_(get(sym_, keys::text_placements_)->get_placement_info(scale_factor)) { initialize_geometries(); if (!geometries_to_process_.size()) return; @@ -74,8 +78,8 @@ struct largest_bbox_first void base_symbolizer_helper::initialize_geometries() { // FIXME - bool largest_box_only = false;//get(sym_, keys::largest_box_only); - double minimum_path_length = 0; // get(sym_, keys::minimum_path_length); + bool largest_box_only = get(sym_, keys::largest_box_only, feature_, vars_, false); + double minimum_path_length = get(sym_, keys::minimum_path_length, feature_, vars_, 0); for ( auto const& geom : feature_.paths()) { // don't bother with empty geometries @@ -172,13 +176,15 @@ void base_symbolizer_helper::initialize_points() template text_symbolizer_helper::text_symbolizer_helper( - const text_symbolizer &sym, const feature_impl &feature, - const proj_transform &prj_trans, + text_symbolizer const& sym, + feature_impl const& feature, + attributes const& vars, + proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, - const CoordTransform &t, FaceManagerT &font_manager, + CoordTransform const& t, FaceManagerT & font_manager, DetectorT &detector, const box2d &query_extent) - : base_symbolizer_helper(sym, feature, prj_trans, width, height, scale_factor, t, query_extent), - finder_(feature, detector, dims_, placement_, font_manager, scale_factor), + : base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent), + finder_(feature, vars, detector, dims_, placement_, font_manager, scale_factor), points_on_line_(false) { if (geometries_to_process_.size()) finder_.next_position(); @@ -267,13 +273,15 @@ bool text_symbolizer_helper::next_point_placement() template text_symbolizer_helper::text_symbolizer_helper( - const shield_symbolizer &sym, const feature_impl &feature, - const proj_transform &prj_trans, + shield_symbolizer const& sym, + feature_impl const& feature, + attributes const& vars, + proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, - const CoordTransform &t, FaceManagerT &font_manager, + CoordTransform const& t, FaceManagerT & font_manager, DetectorT &detector, const box2d &query_extent) - : base_symbolizer_helper(sym, feature, prj_trans, width, height, scale_factor, t, query_extent), - finder_(feature, detector, dims_, placement_, font_manager, scale_factor), + : base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent), + finder_(feature, vars, detector, dims_, placement_, font_manager, scale_factor), points_on_line_(true) { if (geometries_to_process_.size()) @@ -286,23 +294,17 @@ text_symbolizer_helper::text_symbolizer_helper( void text_symbolizer_helper::init_marker() { - //shield_symbolizer const& sym = static_cast(sym_); - std::string filename = mapnik::get(sym_, keys::file, feature_); + std::string filename = mapnik::get(sym_, keys::file, feature_, vars_); + if (filename.empty()) return; + boost::optional marker = marker_cache::instance().find(filename, true); + if (!marker) return; //FIXME - need to test this //std::string filename = path_processor_type::evaluate(filename_string, feature_); agg::trans_affine trans; auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(trans, feature_, *image_transform); - boost::optional opt_marker; //TODO: Why boost::optional? - if (!filename.empty()) - { - opt_marker = marker_cache::instance().find(filename, true); - } - marker_ptr m; - if (opt_marker) m = *opt_marker; - if (!m) return; - double width = m->width(); - double height = m->height(); + if (image_transform) evaluate_transform(trans, feature_, vars_, *image_transform); + double width = (*marker)->width(); + double height = (*marker)->height(); double px0 = - 0.5 * width; double py0 = - 0.5 * height; double px1 = 0.5 * width; @@ -318,35 +320,39 @@ void text_symbolizer_helper::init_marker() box2d bbox(px0, py0, px1, py1); bbox.expand_to_include(px2, py2); bbox.expand_to_include(px3, py3); - bool unlock_image = mapnik::get(sym_, keys::unlock_image, false); - double shield_dx = mapnik::get(sym_, keys::shield_dx, 0.0); - double shield_dy = mapnik::get(sym_, keys::shield_dy, 0.0); + bool unlock_image = mapnik::get(sym_, keys::unlock_image, feature_, vars_, false); + double shield_dx = mapnik::get(sym_, keys::shield_dx, feature_, vars_, 0.0); + double shield_dy = mapnik::get(sym_, keys::shield_dy, feature_, vars_, 0.0); pixel_position marker_displacement; marker_displacement.set(shield_dx,shield_dy); - finder_.set_marker(std::make_shared(m, trans), bbox, unlock_image, marker_displacement); + finder_.set_marker(std::make_shared(*marker, trans), bbox, unlock_image, marker_displacement); } /*****************************************************************************/ -template text_symbolizer_helper::text_symbolizer_helper(const text_symbolizer &sym, - const feature_impl &feature, - const proj_transform &prj_trans, +template text_symbolizer_helper::text_symbolizer_helper( + text_symbolizer const& sym, + feature_impl const& feature, + attributes const& vars, + proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, - const CoordTransform &t, + CoordTransform const& t, face_manager &font_manager, label_collision_detector4 &detector, - const box2d &query_extent); + box2d const& query_extent); -template text_symbolizer_helper::text_symbolizer_helper(const shield_symbolizer &sym, - const feature_impl &feature, - const proj_transform &prj_trans, +template text_symbolizer_helper::text_symbolizer_helper( + shield_symbolizer const& sym, + feature_impl const& feature, + attributes const& vars, + proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, - const CoordTransform &t, + CoordTransform const& t, face_manager &font_manager, label_collision_detector4 &detector, - const box2d &query_extent); + box2d const& query_extent); } //namespace diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index e8ebcd11c..f79886d29 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -118,11 +118,11 @@ text_symbolizer_properties::text_symbolizer_properties() : } -void text_symbolizer_properties::process(text_layout &output, feature_impl const& feature) const +void text_symbolizer_properties::process(text_layout &output, feature_impl const& feature, attributes const& vars) const { output.clear(); if (tree_) { - tree_->apply(format, feature, output); + tree_->apply(format, feature, vars, output); } else { MAPNIK_LOG_WARN(text_properties) << "text_symbolizer_properties can't produce text: No formatting tree!"; } diff --git a/tests/cpp_tests/geometry_converters_test.cpp b/tests/cpp_tests/geometry_converters_test.cpp index 21ff702d9..3f75ebad2 100644 --- a/tests/cpp_tests/geometry_converters_test.cpp +++ b/tests/cpp_tests/geometry_converters_test.cpp @@ -62,7 +62,7 @@ boost::optional linestring_bbox_clipping(mapnik::box2d bbox mapnik::feature_impl f(ctx,0); vertex_converter, output_geometry_backend, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(bbox, backend, sym, t, prj_trans, tr, f, 1.0); + converter(bbox, backend, sym, t, prj_trans, tr, f, attributes(), 1.0); converter.set(); @@ -104,7 +104,7 @@ boost::optional polygon_bbox_clipping(mapnik::box2d bbox, mapnik::feature_impl f(ctx,0); vertex_converter, output_geometry_backend, polygon_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(bbox, backend, sym, t, prj_trans, tr, f, 1.0); + converter(bbox, backend, sym, t, prj_trans, tr, f, attributes(), 1.0); converter.set(); diff --git a/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp b/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp index f9a378028..56295e39e 100644 --- a/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp +++ b/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp @@ -44,7 +44,7 @@ void prepare_map(Map & m) put(poly_sym, keys::fill, color(250, 190, 183)); r.append(std::move(poly_sym)); } - provpoly_style.add_rule(r); + provpoly_style.add_rule(std::move(r)); } { rule r; @@ -54,7 +54,7 @@ void prepare_map(Map & m) put(poly_sym, keys::fill, color(217, 235, 203)); r.append(std::move(poly_sym)); } - provpoly_style.add_rule(r); + provpoly_style.add_rule(std::move(r)); } m.insert_style("provinces",provpoly_style); @@ -73,7 +73,7 @@ void prepare_map(Map & m) put(line_sym,keys::stroke_dasharray,dash); r.append(std::move(line_sym)); } - provlines_style.add_rule(r); + provlines_style.add_rule(std::move(r)); } m.insert_style("provlines",provlines_style); @@ -87,7 +87,7 @@ void prepare_map(Map & m) put(poly_sym, keys::fill, color(153, 204, 255)); r.append(std::move(poly_sym)); } - qcdrain_style.add_rule(r); + qcdrain_style.add_rule(std::move(r)); } m.insert_style("drainage",qcdrain_style); @@ -104,7 +104,7 @@ void prepare_map(Map & m) put(line_sym,keys::stroke_linejoin,ROUND_JOIN); r.append(std::move(line_sym)); } - roads34_style.add_rule(r); + roads34_style.add_rule(std::move(r)); } m.insert_style("smallroads",roads34_style); @@ -121,7 +121,7 @@ void prepare_map(Map & m) put(line_sym,keys::stroke_linejoin,ROUND_JOIN); r.append(std::move(line_sym)); } - roads2_style_1.add_rule(r); + roads2_style_1.add_rule(std::move(r)); } m.insert_style("road-border", roads2_style_1); @@ -137,7 +137,7 @@ void prepare_map(Map & m) put(line_sym,keys::stroke_linejoin,ROUND_JOIN); r.append(std::move(line_sym)); } - roads2_style_2.add_rule(r); + roads2_style_2.add_rule(std::move(r)); } m.insert_style("road-fill", roads2_style_2); @@ -154,7 +154,7 @@ void prepare_map(Map & m) put(line_sym,keys::stroke_linejoin,ROUND_JOIN); r.append(std::move(line_sym)); } - roads1_style_1.add_rule(r); + roads1_style_1.add_rule(std::move(r)); } m.insert_style("highway-border", roads1_style_1); @@ -170,7 +170,7 @@ void prepare_map(Map & m) put(line_sym,keys::stroke_linejoin,ROUND_JOIN); r.append(std::move(line_sym)); } - roads1_style_2.add_rule(r); + roads1_style_2.add_rule(std::move(r)); } m.insert_style("highway-fill", roads1_style_2); @@ -190,7 +190,7 @@ void prepare_map(Map & m) put(text_sym, keys::text_placements_, placement_finder); r.append(std::move(text_sym)); } - popplaces_style.add_rule(r); + popplaces_style.add_rule(std::move(r)); } m.insert_style("popplaces",popplaces_style ); @@ -202,7 +202,6 @@ void prepare_map(Map & m) p["type"]="shape"; p["file"]="demo/data/boundaries"; p["encoding"]="latin1"; - layer lyr("Provinces"); lyr.set_datasource(datasource_cache::instance().create(p)); lyr.set_srs(srs_lcc); diff --git a/tests/data/json/feature_collection_level_properties.json b/tests/data/json/feature_collection_level_properties.json new file mode 100644 index 000000000..320cfc4eb --- /dev/null +++ b/tests/data/json/feature_collection_level_properties.json @@ -0,0 +1,18 @@ +{ + "type": "FeatureCollection", + "properties": { + "fc_name": "fc_value" + }, + "features": [ + { + "type": "Feature", + "properties": { + "feat_name": "feat_value" + }, + "geometry": { + "type": "Point", + "coordinates": [ -122, 48 ] + } + } + ] +} \ No newline at end of file diff --git a/tests/python_tests/geojson_plugin_test.py b/tests/python_tests/geojson_plugin_test.py index d6143b7b7..ea5ac5457 100644 --- a/tests/python_tests/geojson_plugin_test.py +++ b/tests/python_tests/geojson_plugin_test.py @@ -66,6 +66,14 @@ if 'geojson' in mapnik.DatasourceCache.plugin_names(): # query.add_property_name('bogus') # fs = ds.features(query) + def test_parsing_feature_collection_with_top_level_properties(): + ds = mapnik.Datasource(type='geojson',file='../data/json/feature_collection_level_properties.json') + f = ds.all_features()[0] + + desc = ds.describe() + eq_(desc['geometry_type'],mapnik.DataGeometryType.Point) + eq_(f['feat_name'], u'feat_value') + if __name__ == "__main__": setup() run_all(eval(x) for x in dir() if x.startswith("test_")) diff --git a/tests/python_tests/postgis_test.py b/tests/python_tests/postgis_test.py index 568b0f128..0e8f6398e 100644 --- a/tests/python_tests/postgis_test.py +++ b/tests/python_tests/postgis_test.py @@ -1011,6 +1011,15 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \ eq_(geoms[0].to_wkt(),'Polygon((0 0,1 1,2 2,0 0))') eq_(geoms[1].to_wkt(),'Polygon((0 0,1 1,2 2,0 0))') + def test_variable_in_subquery1(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table=''' + (select * from test where @zoom = 30 ) as tmp''', + geometry_field='geom', + autodetect_key_field=True) + fs = ds.featureset(variables={'zoom':30}) + for id in range(1,5): + eq_(fs.next().id(),id) + atexit.register(postgis_takedown)