diff --git a/include/mapnik/css_color_grammar.hpp b/include/mapnik/css_color_grammar.hpp index a15f0fa87..eea5d1f35 100644 --- a/include/mapnik/css_color_grammar.hpp +++ b/include/mapnik/css_color_grammar.hpp @@ -25,6 +25,7 @@ // mapnik #include +#include // spirit2 #include @@ -39,24 +40,6 @@ // stl #include -namespace mapnik { - -// http://www.w3.org/TR/css3-color/#hsl-color -inline double hue_to_rgb( double m1, double m2, double h) -{ - if (h < 0.0) h = h + 1.0; - else if (h > 1) h = h - 1.0; - - if (h * 6 < 1.0) - return m1 + (m2 - m1) * h * 6.0; - if (h * 2 < 1.0) - return m2; - if (h * 3 < 2.0) - return m1 + (m2 - m1)* (2.0/3.0 - h) * 6.0; - return m1; -} - -} // namespace mapnik // boost #include diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 4470a5b31..c9b6a654f 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -507,41 +507,46 @@ void apply_filter(Src & src, scale_hsla const& transform) uint8_t & g = get_color(src_it[x], green_t()); uint8_t & b = get_color(src_it[x], blue_t()); uint8_t & a = get_color(src_it[x], alpha_t()); + double r2 = static_cast(r)/255.0; + double g2 = static_cast(g)/255.0; + double b2 = static_cast(b)/255.0; double a2 = static_cast(a)/255.0; - double a1 = a2; - bool alpha_modified = false; - if (set_alpha && a2 > 0.01) + // demultiply + if (a2 <= 0.0) + { + r = g = b = 0; + continue; + } + else + { + r2 /= a2; + g2 /= a2; + b2 /= a2; + } + if (set_alpha) { a2 = transform.a0 + (a2 * (transform.a1 - transform.a0)); if (a2 <= 0) { - a = 0; + r = g = b = a = 0; + continue; + } + else if (a2 > 1) + { + a2 = 1; + a = 255; } else { - a = static_cast(std::floor((a2 * 255.0) +.5)); - if (a > 255) a = 255; + a = static_cast(std::floor((a2 * 255.0) +.5)); } - alpha_modified = true; } - if (tinting && a > 1) + if (tinting) { double h; double s; double l; - // demultiply - if (a1 <= 0.0) - { - r = g = b = 0; - continue; - } - else if (a1 < 1) - { - r /= a1; - g /= a1; - b /= a1; - } - rgb2hsl(r,g,b,h,s,l); + rgb2hsl(r2,g2,b2,h,s,l); double h2 = transform.h0 + (h * (transform.h1 - transform.h0)); double s2 = transform.s0 + (s * (transform.s1 - transform.s0)); double l2 = transform.l0 + (l * (transform.l1 - transform.l0)); @@ -551,35 +556,19 @@ void apply_filter(Src & src, scale_hsla const& transform) else if (s2 < 0) { s2 = 0; } if (l2 > 1) { l2 = 1; } else if (l2 < 0) { l2 = 0; } - hsl2rgb(h2,s2,l2,r,g,b); - // premultiply - // we only work with premultiplied source, - // thus all color values must be <= alpha - r *= a2; - g *= a2; - b *= a2; - } - else if (alpha_modified) - { - // demultiply - if (a1 <= 0.0) - { - r = g = b = 0; - continue; - } - else if (a1 < 1) - { - r /= a1; - g /= a1; - b /= a1; - } - // premultiply - // we only work with premultiplied source, - // thus all color values must be <= alpha - r *= a2; - g *= a2; - b *= a2; + hsl2rgb(h2,s2,l2,r2,g2,b2); } + // premultiply + r2 *= a2; + g2 *= a2; + b2 *= a2; + r = static_cast(std::floor((r2*255.0)+.5)); + g = static_cast(std::floor((g2*255.0)+.5)); + b = static_cast(std::floor((b2*255.0)+.5)); + // all color values must be <= alpha + if (r>a) r=a; + if (g>a) g=a; + if (b>a) b=a; } } } diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index e5f0b5db6..8457880c7 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -26,13 +26,17 @@ // mapnik #include #include +#include + // boost #include + // stl #include #include #include // for std::back_insert_iterator + namespace mapnik { namespace filter { struct blur {}; @@ -66,7 +70,19 @@ struct scale_hsla l0(_l0), l1(_l1), a0(_a0), - a1(_a1) {} + a1(_a1) { + if (h0 < 0 || h0 > 1 || + h1 < 0 || h1 > 1 || + s0 < 0 || s0 > 1 || + s1 < 0 || s1 > 1 || + l0 < 0 || l0 > 1 || + l1 < 0 || l1 > 1 || + a0 < 0 || a0 > 1 || + a1 < 0 || a1 > 1) + { + throw config_error("scale-hsla values must be between 0 and 1"); + } + } inline bool is_identity() const { return (h0 == 0 && h1 == 1 && diff --git a/include/mapnik/util/hsl.hpp b/include/mapnik/util/hsl.hpp index ff3fa3466..2c6bada5f 100644 --- a/include/mapnik/util/hsl.hpp +++ b/include/mapnik/util/hsl.hpp @@ -27,11 +27,8 @@ namespace mapnik { -static inline void rgb2hsl(unsigned char red, unsigned char green, unsigned char blue, - double & h, double & s, double & l) { - double r = red/255.0; - double g = green/255.0; - double b = blue/255.0; +inline void rgb2hsl(double r, double g, double b, + double & h, double & s, double & l) { double max = std::max(r,std::max(g,b)); double min = std::min(r,std::min(g,b)); double delta = max - min; @@ -46,25 +43,30 @@ static inline void rgb2hsl(unsigned char red, unsigned char green, unsigned char } } -static inline double hueToRGB(double m1, double m2, double h) { - if(h < 0) h += 1; - if(h > 1) h -= 1; - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - if (h * 2 < 1) return m2; - if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6; +// http://www.w3.org/TR/css3-color/#hsl-color +inline double hue_to_rgb(double m1, double m2, double h) +{ + if (h < 0.0) h = h + 1.0; + else if (h > 1.0) h = h - 1.0; + if (h * 6 < 1.0) + return m1 + (m2 - m1) * h * 6.0; + if (h * 2 < 1.0) + return m2; + if (h * 3 < 2.0) + return m1 + (m2 - m1)* (2.0/3.0 - h) * 6.0; return m1; } -static inline void hsl2rgb(double h, double s, double l, - unsigned char & r, unsigned char & g, unsigned char & b) { +inline void hsl2rgb(double h, double s, double l, + double & r, double & g, double & b) { if (!s) { - r = g = b = static_cast(std::floor((l * 255.0)+.5)); + r = g = b = l; } - double m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s; - double m1 = l * 2 - m2; - r = static_cast(std::floor((hueToRGB(m1, m2, h + 0.33333) * 255.0)+.5)); - g = static_cast(std::floor((hueToRGB(m1, m2, h) * 255.0)+.5)); - b = static_cast(std::floor((hueToRGB(m1, m2, h - 0.33333) * 255.0)+.5)); + double m2 = (l <= 0.5) ? l * (s + 1.0) : l + s - l * s; + double m1 = l * 2.0 - m2; + r = hue_to_rgb(m1, m2, h + 1.0/3.0); + g = hue_to_rgb(m1, m2, h); + b = hue_to_rgb(m1, m2, h - 1.0/3.0); } } diff --git a/tests/data/broken_maps/invalid-scale-hsla-filter.xml b/tests/data/broken_maps/invalid-scale-hsla-filter.xml new file mode 100644 index 000000000..fec9d9eb0 --- /dev/null +++ b/tests/data/broken_maps/invalid-scale-hsla-filter.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png index 0fe1cacfb..1aeb7a534 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png index f766c3a28..46e816dcb 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png index 7da16b1cd..24708b9fd 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png index cdc496257..6ea357ad0 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png index 2a65704af..4c32e4d49 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png index 22d92db8d..79861fc0c 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/styles/marker-with-background-image-and-hsla-transform.xml b/tests/visual_tests/styles/marker-with-background-image-and-hsla-transform.xml index 4d691fbaa..96a0756a3 100644 --- a/tests/visual_tests/styles/marker-with-background-image-and-hsla-transform.xml +++ b/tests/visual_tests/styles/marker-with-background-image-and-hsla-transform.xml @@ -1,7 +1,7 @@