Merge branch 'master' into skia-renderer
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/color.hpp>
|
#include <mapnik/color.hpp>
|
||||||
|
#include <mapnik/util/hsl.hpp>
|
||||||
|
|
||||||
// spirit2
|
// spirit2
|
||||||
#include <boost/spirit/include/qi.hpp>
|
#include <boost/spirit/include/qi.hpp>
|
||||||
|
@ -39,24 +40,6 @@
|
||||||
// stl
|
// stl
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
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
|
// boost
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.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 & g = get_color(src_it[x], green_t());
|
||||||
uint8_t & b = get_color(src_it[x], blue_t());
|
uint8_t & b = get_color(src_it[x], blue_t());
|
||||||
uint8_t & a = get_color(src_it[x], alpha_t());
|
uint8_t & a = get_color(src_it[x], alpha_t());
|
||||||
|
double r2 = static_cast<double>(r)/255.0;
|
||||||
|
double g2 = static_cast<double>(g)/255.0;
|
||||||
|
double b2 = static_cast<double>(b)/255.0;
|
||||||
double a2 = static_cast<double>(a)/255.0;
|
double a2 = static_cast<double>(a)/255.0;
|
||||||
double a1 = a2;
|
// demultiply
|
||||||
bool alpha_modified = false;
|
if (a2 <= 0.0)
|
||||||
if (set_alpha && a2 > 0.01)
|
{
|
||||||
|
r = g = b = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r2 /= a2;
|
||||||
|
g2 /= a2;
|
||||||
|
b2 /= a2;
|
||||||
|
}
|
||||||
|
if (set_alpha)
|
||||||
{
|
{
|
||||||
a2 = transform.a0 + (a2 * (transform.a1 - transform.a0));
|
a2 = transform.a0 + (a2 * (transform.a1 - transform.a0));
|
||||||
if (a2 <= 0)
|
if (a2 <= 0)
|
||||||
{
|
{
|
||||||
a = 0;
|
r = g = b = a = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (a2 > 1)
|
||||||
|
{
|
||||||
|
a2 = 1;
|
||||||
|
a = 255;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a = static_cast<unsigned>(std::floor((a2 * 255.0) +.5));
|
a = static_cast<uint8_t>(std::floor((a2 * 255.0) +.5));
|
||||||
if (a > 255) a = 255;
|
|
||||||
}
|
}
|
||||||
alpha_modified = true;
|
|
||||||
}
|
}
|
||||||
if (tinting && a > 1)
|
if (tinting)
|
||||||
{
|
{
|
||||||
double h;
|
double h;
|
||||||
double s;
|
double s;
|
||||||
double l;
|
double l;
|
||||||
// demultiply
|
rgb2hsl(r2,g2,b2,h,s,l);
|
||||||
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);
|
|
||||||
double h2 = transform.h0 + (h * (transform.h1 - transform.h0));
|
double h2 = transform.h0 + (h * (transform.h1 - transform.h0));
|
||||||
double s2 = transform.s0 + (s * (transform.s1 - transform.s0));
|
double s2 = transform.s0 + (s * (transform.s1 - transform.s0));
|
||||||
double l2 = transform.l0 + (l * (transform.l1 - transform.l0));
|
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; }
|
else if (s2 < 0) { s2 = 0; }
|
||||||
if (l2 > 1) { l2 = 1; }
|
if (l2 > 1) { l2 = 1; }
|
||||||
else if (l2 < 0) { l2 = 0; }
|
else if (l2 < 0) { l2 = 0; }
|
||||||
hsl2rgb(h2,s2,l2,r,g,b);
|
hsl2rgb(h2,s2,l2,r2,g2,b2);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
// premultiply
|
||||||
|
r2 *= a2;
|
||||||
|
g2 *= a2;
|
||||||
|
b2 *= a2;
|
||||||
|
r = static_cast<uint8_t>(std::floor((r2*255.0)+.5));
|
||||||
|
g = static_cast<uint8_t>(std::floor((g2*255.0)+.5));
|
||||||
|
b = static_cast<uint8_t>(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,17 @@
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/config.hpp>
|
#include <mapnik/config.hpp>
|
||||||
#include <mapnik/color.hpp>
|
#include <mapnik/color.hpp>
|
||||||
|
#include <mapnik/config_error.hpp>
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
// stl
|
// stl
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <iterator> // for std::back_insert_iterator
|
#include <iterator> // for std::back_insert_iterator
|
||||||
|
|
||||||
|
|
||||||
namespace mapnik { namespace filter {
|
namespace mapnik { namespace filter {
|
||||||
|
|
||||||
struct blur {};
|
struct blur {};
|
||||||
|
@ -66,7 +70,19 @@ struct scale_hsla
|
||||||
l0(_l0),
|
l0(_l0),
|
||||||
l1(_l1),
|
l1(_l1),
|
||||||
a0(_a0),
|
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 {
|
inline bool is_identity() const {
|
||||||
return (h0 == 0 &&
|
return (h0 == 0 &&
|
||||||
h1 == 1 &&
|
h1 == 1 &&
|
||||||
|
|
|
@ -27,11 +27,8 @@
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
|
|
||||||
static inline void rgb2hsl(unsigned char red, unsigned char green, unsigned char blue,
|
inline void rgb2hsl(double r, double g, double b,
|
||||||
double & h, double & s, double & l) {
|
double & h, double & s, double & l) {
|
||||||
double r = red/255.0;
|
|
||||||
double g = green/255.0;
|
|
||||||
double b = blue/255.0;
|
|
||||||
double max = std::max(r,std::max(g,b));
|
double max = std::max(r,std::max(g,b));
|
||||||
double min = std::min(r,std::min(g,b));
|
double min = std::min(r,std::min(g,b));
|
||||||
double delta = max - min;
|
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) {
|
// http://www.w3.org/TR/css3-color/#hsl-color
|
||||||
if(h < 0) h += 1;
|
inline double hue_to_rgb(double m1, double m2, double h)
|
||||||
if(h > 1) h -= 1;
|
{
|
||||||
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
|
if (h < 0.0) h = h + 1.0;
|
||||||
if (h * 2 < 1) return m2;
|
else if (h > 1.0) h = h - 1.0;
|
||||||
if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
|
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;
|
return m1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void hsl2rgb(double h, double s, double l,
|
inline void hsl2rgb(double h, double s, double l,
|
||||||
unsigned char & r, unsigned char & g, unsigned char & b) {
|
double & r, double & g, double & b) {
|
||||||
if (!s) {
|
if (!s) {
|
||||||
r = g = b = static_cast<unsigned char>(std::floor((l * 255.0)+.5));
|
r = g = b = l;
|
||||||
}
|
}
|
||||||
double m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
|
double m2 = (l <= 0.5) ? l * (s + 1.0) : l + s - l * s;
|
||||||
double m1 = l * 2 - m2;
|
double m1 = l * 2.0 - m2;
|
||||||
r = static_cast<unsigned char>(std::floor((hueToRGB(m1, m2, h + 0.33333) * 255.0)+.5));
|
r = hue_to_rgb(m1, m2, h + 1.0/3.0);
|
||||||
g = static_cast<unsigned char>(std::floor((hueToRGB(m1, m2, h) * 255.0)+.5));
|
g = hue_to_rgb(m1, m2, h);
|
||||||
b = static_cast<unsigned char>(std::floor((hueToRGB(m1, m2, h - 0.33333) * 255.0)+.5));
|
b = hue_to_rgb(m1, m2, h - 1.0/3.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
4
tests/data/broken_maps/invalid-scale-hsla-filter.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<Map>
|
||||||
|
<Style name="style" image-filters="scale-hsla(-1,1.1,0,1,0,1,0,1)">
|
||||||
|
</Style>
|
||||||
|
</Map>
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 8 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
|
@ -1,7 +1,7 @@
|
||||||
<Map srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" background-image="../../data/images/checker.jpg">
|
<Map srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" background-image="../../data/images/checker.jpg">
|
||||||
|
|
||||||
<Style name="ellipse"
|
<Style name="ellipse"
|
||||||
direct-image-filters=" scale-hsla(0,1,0,1,0,1,0,.5)"
|
direct-image-filters="scale-hsla(0,1,0,1,0,1,0,.5)"
|
||||||
image-filters="scale-hsla(.1,.9,.5,1,.5,1,.2,1)"
|
image-filters="scale-hsla(.1,.9,.5,1,.5,1,.2,1)"
|
||||||
>
|
>
|
||||||
<Rule>
|
<Rule>
|
||||||
|
|