diff --git a/include/mapnik/feature_type_style.hpp b/include/mapnik/feature_type_style.hpp index 151588459..e6876fa0c 100644 --- a/include/mapnik/feature_type_style.hpp +++ b/include/mapnik/feature_type_style.hpp @@ -55,6 +55,7 @@ private: filter_mode_e filter_mode_; // image_filters std::vector filters_; + std::vector direct_filters_; // comp-op boost::optional comp_op_; // The rule_ptrs vectors are only valid for the scale_denom_validity_. @@ -76,14 +77,16 @@ public: rule_ptrs const& get_else_rules(double scale_denom); rule_ptrs const& get_also_rules(double scale_denom); - rules &get_rules_nonconst(); - + rules& get_rules_nonconst(); + void set_filter_mode(filter_mode_e mode); filter_mode_e get_filter_mode() const; // filters std::vector const& image_filters() const; - std::vector & image_filters(); + std::vector & image_filters(); + std::vector const& direct_image_filters() const; + std::vector & direct_image_filters(); // compositing void set_comp_op(composite_mode_e comp_op); boost::optional comp_op() const; diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index d1a24b188..22ea43ccc 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -252,6 +252,14 @@ void agg_renderer::end_style_processing(feature_type_style const& st) { composite(pixmap_.data(),current_buffer_->data(), src_over,false,false); } + + // apply any 'direct' image filters + mapnik::filter::filter_visitor visitor(pixmap_); + BOOST_FOREACH(mapnik::filter::filter_type filter_tag, st.direct_image_filters()) + { + boost::apply_visitor(visitor, filter_tag); + } + #ifdef MAPNIK_DEBUG std::clog << "end style processing\n"; #endif diff --git a/src/feature_type_style.cpp b/src/feature_type_style.cpp index 540f7cc47..c14413e6e 100644 --- a/src/feature_type_style.cpp +++ b/src/feature_type_style.cpp @@ -37,12 +37,14 @@ IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings ) feature_type_style::feature_type_style() : filter_mode_(FILTER_ALL), filters_(), + direct_filters_(), scale_denom_validity_(-1) {} feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy) : filter_mode_(rhs.filter_mode_), filters_(rhs.filters_), + direct_filters_(rhs.direct_filters_), comp_op_(rhs.comp_op_), scale_denom_validity_(-1) { @@ -62,6 +64,7 @@ feature_type_style& feature_type_style::operator=(feature_type_style const& rhs) if (this == &rhs) return *this; rules_=rhs.rules_; filters_ = rhs.filters_; + direct_filters_ = rhs.direct_filters_; comp_op_ = rhs.comp_op_; scale_denom_validity_ = -1; return *this; @@ -78,7 +81,7 @@ rules const& feature_type_style::get_rules() const return rules_; } -rules &feature_type_style::get_rules_nonconst() +rules& feature_type_style::get_rules_nonconst() { return rules_; } @@ -103,6 +106,16 @@ std::vector const& feature_type_style::image_filters() con return filters_; } +std::vector& feature_type_style::direct_image_filters() +{ + return direct_filters_; +} + +std::vector const& feature_type_style::direct_image_filters() const +{ + return direct_filters_; +} + void feature_type_style::set_comp_op(composite_mode_e comp_op) { comp_op_ = comp_op; diff --git a/src/load_map.cpp b/src/load_map.cpp index a56c367c7..f94df3881 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -430,22 +430,45 @@ void map_parser::parse_style(Map & map, xml_node const& sty) } // image filters + + mapnik::image_filter_grammar > filter_grammar; + optional filters = sty.get_opt_attr("image-filters"); if (filters) { std::string filter_mode = *filters; - if (filter_mode.empty()) - { - throw config_error("failed to parse empty image-filter"); - } std::string::const_iterator itr = filter_mode.begin(); std::string::const_iterator end = filter_mode.end(); - mapnik::image_filter_grammar > g; + - bool result = boost::spirit::qi::phrase_parse(itr,end, g, boost::spirit::qi::ascii::space, style.image_filters()); + bool result = boost::spirit::qi::phrase_parse(itr,end, + filter_grammar, + boost::spirit::qi::ascii::space, + style.image_filters()); if (!result || itr!=end) { - throw config_error("failed to parse image-filter: '" + std::string(itr,end) + "'"); + throw config_error("failed to parse image-filters: '" + std::string(itr,end) + "'"); + } + } + + // direct image filters (applied directly on main image buffer + // TODO : consider creating a separate XML node e.g + // + // + optional direct_filters = sty.get_opt_attr("direct-image-filters"); + if (direct_filters) + { + std::string filter_mode = *direct_filters; + std::string::const_iterator itr = filter_mode.begin(); + std::string::const_iterator end = filter_mode.end(); + bool result = boost::spirit::qi::phrase_parse(itr,end, + filter_grammar, + boost::spirit::qi::ascii::space, + style.direct_image_filters()); + if (!result || itr!=end) + { + throw config_error("failed to parse direct-image-filters: '" + std::string(itr,end) + "'"); } }