diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 2fad73f17..18094ce26 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -417,12 +417,18 @@ void apply_filter(Src & src, colorize_alpha const& op) double step = 1.0/(size-1); double offset = 0.0; - BOOST_FOREACH( mapnik::color const& c, op) + BOOST_FOREACH( mapnik::filter::color_stop const& stop, op) { - grad_lut.add_color(offset, agg::rgba(c.red()/256.0, - c.green()/256.0, - c.blue()/256.0, - c.alpha()/256.0)); + mapnik::color const& c = stop.color; + double stop_offset = stop.offset; + if (stop_offset == 0) + { + stop_offset = offset; + } + grad_lut.add_color(stop_offset, agg::rgba(c.red()/256.0, + c.green()/256.0, + c.blue()/256.0, + c.alpha()/256.0)); offset += step; } grad_lut.build_lut(); diff --git a/include/mapnik/image_filter_grammar.hpp b/include/mapnik/image_filter_grammar.hpp index 4c490f446..e2f194923 100644 --- a/include/mapnik/image_filter_grammar.hpp +++ b/include/mapnik/image_filter_grammar.hpp @@ -25,17 +25,40 @@ // boost #include +#include // mapnik #include #include // stl #include +BOOST_FUSION_ADAPT_STRUCT( + mapnik::filter::color_stop, + (mapnik::color, color ) + (double, offset) +) namespace mapnik { namespace qi = boost::spirit::qi; +struct percent_offset_impl +{ + template + struct result + { + typedef double type; + }; + + double operator() (double val) const + { + double result = std::abs(val/100.0); + if (result > 1.0) result = 1.0; + return result; + } +}; + + template struct image_filter_grammar : qi::grammar @@ -46,10 +69,12 @@ struct image_filter_grammar : qi::rule, void(ContType&), qi::ascii::space_type> agg_blur_filter; qi::rule, void(ContType&), qi::ascii::space_type> hsla_filter; - qi::rule, void(ContType&), qi::ascii::space_type> colorize_alpha_filter; + qi::rule, void(ContType&), qi::ascii::space_type> colorize_alpha_filter; qi::rule no_args; qi::uint_parser< unsigned, 10, 1, 3 > radius_; css_color_grammar css_color_; + qi::rule color_stop_offset; + phoenix::function percent_offset; }; } diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index b433e9dd5..dc5728b15 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -98,16 +98,18 @@ struct hsla double a1; }; -struct colorize_alpha : std::vector +struct color_stop +{ + color_stop() {} + color_stop(mapnik::color const& c, double val = 0.0) + : color(c),offset(val) {} + mapnik::color color; + double offset; +}; + +struct colorize_alpha : std::vector { colorize_alpha() {} - colorize_alpha(mapnik::color const& c0, mapnik::color const& c1) - { - this->push_back(c0); - this->push_back(c1); - // TODO: support multiple color-stops - // https://developer.mozilla.org/en-US/docs/CSS/linear-gradient - } }; typedef boost::variant::image_filter_grammar() using boost::spirit::ascii::string; using phoenix::push_back; using phoenix::construct; - + using phoenix::at_c; #if BOOST_VERSION >= 104700 using qi::no_skip; start = -(filter % no_skip[*char_(", ")]) @@ -111,11 +111,17 @@ image_filter_grammar::image_filter_grammar() colorize_alpha_filter = lit("colorize-alpha")[_a = construct()] >> lit('(') - >> css_color_[push_back(_a, _1)] - >> +(lit(',') >> css_color_[push_back(_a, _1)]) + >> (css_color_[at_c<0>(_b) = _1, at_c<1>(_b) = 0] + >> -color_stop_offset(_b)) [push_back(_a,_b)] + >> +(lit(',') >> css_color_[at_c<0>(_b) =_1,at_c<1>(_b) = 0] + >> -color_stop_offset(_b))[push_back(_a,_b)] >> lit(')') [push_back(_r1,_a)] ; + color_stop_offset = (double_ >> lit('%'))[at_c<1>(_r1) = percent_offset(_1)] + | + double_[at_c<1>(_r1) = _1] + ; no_args = -(lit('(') >> lit(')')); }