fix crash when copy'ing latent plugins
[ardour.git] / libs / canvas / colors.cc
index 1ab3c6689b657e1ba3422469efc0a09bed41a85c..7a108e7f85a36bd4aad3380478df053f9a0228f3 100644 (file)
@@ -35,6 +35,12 @@ using namespace ArdourCanvas;
 using std::max;
 using std::min;
 
 using std::max;
 using std::min;
 
+ArdourCanvas::Color
+change_alpha (Color c, double a)
+{
+       return ((c & ~0xff) | (lrintf (a*255.0) & 0xff));
+}
+
 void
 ArdourCanvas::color_to_hsv (Color color, double& h, double& s, double& v)
 {
 void
 ArdourCanvas::color_to_hsv (Color color, double& h, double& s, double& v)
 {
@@ -49,9 +55,9 @@ ArdourCanvas::color_to_hsva (Color color, double& h, double& s, double& v, doubl
        double cmax;
        double cmin;
        double delta;
        double cmax;
        double cmin;
        double delta;
-       
+
        color_to_rgba (color, r, g, b, a);
        color_to_rgba (color, r, g, b, a);
-       
+
        if (r > g) {
                cmax = max (r, b);
        } else {
        if (r > g) {
                cmax = max (r, b);
        } else {
@@ -70,12 +76,12 @@ ArdourCanvas::color_to_hsva (Color color, double& h, double& s, double& v, doubl
 
        if (cmax == 0) {
                // r = g = b == 0 ... v is undefined, s = 0
 
        if (cmax == 0) {
                // r = g = b == 0 ... v is undefined, s = 0
-               s = 0.0;  
+               s = 0.0;
                h = 0.0;
                return;
        }
 
                h = 0.0;
                return;
        }
 
-       if (delta != 0.0) {     
+       if (delta != 0.0) {
                if (cmax == r) {
                        h = fmod ((g - b)/delta, 6.0);
                } else if (cmax == g) {
                if (cmax == r) {
                        h = fmod ((g - b)/delta, 6.0);
                } else if (cmax == g) {
@@ -83,9 +89,9 @@ ArdourCanvas::color_to_hsva (Color color, double& h, double& s, double& v, doubl
                } else {
                        h = ((r - g)/delta) + 4;
                }
                } else {
                        h = ((r - g)/delta) + 4;
                }
-               
+
                h *= 60.0;
                h *= 60.0;
-               
+
                if (h < 0.0) {
                        /* negative values are legal but confusing, because
                           they alias positive values.
                if (h < 0.0) {
                        /* negative values are legal but confusing, because
                           they alias positive values.
@@ -129,7 +135,7 @@ ArdourCanvas::hsva_to_color (double h, double s, double v, double a)
                return rgba_to_color (x + m, m, c + m, a);
         } else if (h >= 300.0 && h < 360.0) {
                return rgba_to_color (c + m, m, x + m, a);
                return rgba_to_color (x + m, m, c + m, a);
         } else if (h >= 300.0 && h < 360.0) {
                return rgba_to_color (c + m, m, x + m, a);
-        } 
+        }
        return rgba_to_color (m, m, m, a);
 }
 
        return rgba_to_color (m, m, m, a);
 }
 
@@ -166,8 +172,8 @@ ArdourCanvas::rgba_to_color (double r, double g, double b, double a)
 }
 
 // Inverse of sRGB "gamma" function.
 }
 
 // Inverse of sRGB "gamma" function.
-static inline double 
-inv_gam_sRGB (double c) 
+static inline double
+inv_gam_sRGB (double c)
 {
         if (c <= 0.04045) {
                 return c/12.92;
 {
         if (c <= 0.04045) {
                 return c/12.92;
@@ -177,8 +183,8 @@ inv_gam_sRGB (double c)
 }
 
 // sRGB "gamma" function
 }
 
 // sRGB "gamma" function
-static inline int 
-gam_sRGB(double v) 
+static inline int
+gam_sRGB(double v)
 {
         if (v <= 0.0031308) {
                 v *= 12.92;
 {
         if (v <= 0.0031308) {
                 v *= 12.92;
@@ -188,7 +194,7 @@ gam_sRGB(double v)
         return int (v*255+.5);
 }
 
         return int (v*255+.5);
 }
 
-static double 
+static double
 luminance (uint32_t c)
 {
         // sRGB luminance(Y) values
 luminance (uint32_t c)
 {
         // sRGB luminance(Y) values
@@ -199,9 +205,9 @@ luminance (uint32_t c)
         double r, g, b, a;
 
         ArdourCanvas::color_to_rgba (c, r, g, b, a);
         double r, g, b, a;
 
         ArdourCanvas::color_to_rgba (c, r, g, b, a);
-        
+
         return (gam_sRGB (rY*inv_gam_sRGB(r) + gY*inv_gam_sRGB(g) + bY*inv_gam_sRGB(b))) / 255.0;
         return (gam_sRGB (rY*inv_gam_sRGB(r) + gY*inv_gam_sRGB(g) + bY*inv_gam_sRGB(b))) / 255.0;
-}    
+}
 
 uint32_t
 ArdourCanvas::contrasting_text_color (uint32_t c)
 
 uint32_t
 ArdourCanvas::contrasting_text_color (uint32_t c)
@@ -220,7 +226,7 @@ HSV::HSV ()
        : h (0.0)
        , s (1.0)
        , v (1.0)
        : h (0.0)
        , s (1.0)
        , v (1.0)
-       , a (1.0) 
+       , a (1.0)
 {
 }
 
 {
 }
 
@@ -228,7 +234,7 @@ HSV::HSV (double hh, double ss, double vv, double aa)
        : h (hh)
        , s (ss)
        , v (vv)
        : h (hh)
        , s (ss)
        , v (vv)
-       , a (aa) 
+       , a (aa)
 {
        if (h < 0.0) {
                /* normalize negative hue values into positive range */
 {
        if (h < 0.0) {
                /* normalize negative hue values into positive range */
@@ -253,6 +259,7 @@ HSV::HSV (const std::string& str)
 string
 HSV::to_string () const
 {
 string
 HSV::to_string () const
 {
+       PBD::LocaleGuard lg;
        stringstream ss;
        ss << h << ' ';
        ss << s << ' ';
        stringstream ss;
        ss << h << ' ';
        ss << s << ' ';
@@ -335,12 +342,12 @@ HSV
 HSV::shade (double factor) const
 {
        HSV hsv (*this);
 HSV::shade (double factor) const
 {
        HSV hsv (*this);
-       
+
        /* algorithm derived from a google palette website
           and analysis of their color palettes.
 
        /* algorithm derived from a google palette website
           and analysis of their color palettes.
 
-          basic rule: to make a color darker, increase its saturation 
-          until it reaches 88%, but then additionally reduce value/lightness 
+          basic rule: to make a color darker, increase its saturation
+          until it reaches 88%, but then additionally reduce value/lightness
           by a larger amount.
 
           invert rule to make a color lighter.
           by a larger amount.
 
           invert rule to make a color lighter.
@@ -349,12 +356,12 @@ HSV::shade (double factor) const
        if (factor > 1.0) {
                if (s < 88) {
                        hsv.v += (hsv.v * (factor * 10.0));
        if (factor > 1.0) {
                if (s < 88) {
                        hsv.v += (hsv.v * (factor * 10.0));
-               } 
+               }
                hsv.s *= factor;
        } else {
                if (s < 88) {
                        hsv.v -= (hsv.v * (factor * 10.0));
                hsv.s *= factor;
        } else {
                if (s < 88) {
                        hsv.v -= (hsv.v * (factor * 10.0));
-               } 
+               }
                hsv.s *= factor;
        }
 
                hsv.s *= factor;
        }
 
@@ -414,13 +421,13 @@ HSV::distance (const HSV& other) const
        if (is_gray() && other.is_gray()) {
                /* human color perception of achromatics generates about 450
                   distinct colors. By contrast, CIE94 could give a maximal
        if (is_gray() && other.is_gray()) {
                /* human color perception of achromatics generates about 450
                   distinct colors. By contrast, CIE94 could give a maximal
-                  perceptual distance of sqrt ((360^2) + 1 + 1) = 360. The 450 
+                  perceptual distance of sqrt ((360^2) + 1 + 1) = 360. The 450
                   are not evenly spread (Webers Law), so lets use 360 as an
                   approximation of the number of distinct achromatics.
                   are not evenly spread (Webers Law), so lets use 360 as an
                   approximation of the number of distinct achromatics.
-                  
+
                   So, scale up the achromatic difference to give about
                   a maximal distance between v = 1.0 and v = 0.0 of 360.
                   So, scale up the achromatic difference to give about
                   a maximal distance between v = 1.0 and v = 0.0 of 360.
-                  
+
                   A difference of about 0.0055 will generate a return value of
                   2, which is roughly the limit of human perceptual
                   discrimination for chromatics.
                   A difference of about 0.0055 will generate a return value of
                   2, which is roughly the limit of human perceptual
                   discrimination for chromatics.
@@ -438,7 +445,7 @@ HSV::distance (const HSV& other) const
        double sL, sA, sB;
        double oL, oA, oB;
        double r, g, b, alpha;  // Careful, "a" is a field of this
        double sL, sA, sB;
        double oL, oA, oB;
        double r, g, b, alpha;  // Careful, "a" is a field of this
-       Color c; 
+       Color c;
 
        c = hsva_to_color (h, s, v, a);
        color_to_rgba (c, r, g, b, alpha);
 
        c = hsva_to_color (h, s, v, a);
        color_to_rgba (c, r, g, b, alpha);
@@ -452,7 +459,7 @@ HSV::distance (const HSV& other) const
 
        const double whtL = 1.0;
        const double whtC = 1.0;
 
        const double whtL = 1.0;
        const double whtC = 1.0;
-       const double whtH = 1.0;  
+       const double whtH = 1.0;
 
        const double xC1 = sqrt ((sA * sA) + (sB * oB));
        const double xC2 = sqrt ((oA * oA) + (oB * oB));
 
        const double xC1 = sqrt ((sA * sA) + (sB * oB));
        const double xC2 = sqrt ((oA * oA) + (oB * oB));
@@ -461,7 +468,7 @@ HSV::distance (const HSV& other) const
        const double xDE = sqrt (((sL - oL) * (sL - oL))
                                 + ((sA - oA) * (sA - oA))
                                 + ((sB - oB) * (sB - oB)));
        const double xDE = sqrt (((sL - oL) * (sL - oL))
                                 + ((sA - oA) * (sA - oA))
                                 + ((sB - oB) * (sB - oB)));
-       
+
        double xDH;
 
        if (sqrt (xDE) > (sqrt (abs (xDL)) + sqrt (abs (xDC)))) {
        double xDH;
 
        if (sqrt (xDE) > (sqrt (abs (xDL)) + sqrt (abs (xDC)))) {
@@ -476,7 +483,7 @@ HSV::distance (const HSV& other) const
        xDL /= whtL;
        xDC /= whtC * xSC;
        xDH /= whtH * xSH;
        xDL /= whtL;
        xDC /= whtC * xSC;
        xDH /= whtH * xSH;
-       
+
        return sqrt ((xDL * xDL) + (xDC * xDC) + (xDH * xDH));
 }
 
        return sqrt ((xDL * xDL) + (xDC * xDC) + (xDH * xDH));
 }
 
@@ -529,9 +536,9 @@ HSV::mod (SVAModifier const & svam)
 
 SVAModifier::SVAModifier (string const &str)
        : type (Add)
 
 SVAModifier::SVAModifier (string const &str)
        : type (Add)
-       , s (0)
-       , v (0)
-       , a (0)
+       , _s (0)
+       , _v (0)
+       , _a (0)
 {
        from_string (str);
 }
 {
        from_string (str);
 }
@@ -549,23 +556,23 @@ SVAModifier::from_string (string const & str)
        case '*':
                type = Multiply;
                /* no-op values for multiply */
        case '*':
                type = Multiply;
                /* no-op values for multiply */
-               s = 1.0;
-               v = 1.0;
-               a = 1.0;
+               _s = 1.0;
+               _v = 1.0;
+               _a = 1.0;
                break;
        case '+':
                type = Add;
                /* no-op values for add */
                break;
        case '+':
                type = Add;
                /* no-op values for add */
-               s = 0.0;
-               v = 0.0;
-               a = 0.0;
+               _s = 0.0;
+               _v = 0.0;
+               _a = 0.0;
                break;
        case '=':
                type = Assign;
                /* this will avoid assignment in operator() (see below) */
                break;
        case '=':
                type = Assign;
                /* this will avoid assignment in operator() (see below) */
-               s = -1.0;
-               v = -1.0;
-               a = -1.0;
+               _s = -1.0;
+               _v = -1.0;
+               _a = -1.0;
                break;
        default:
                throw failed_constructor ();
                break;
        default:
                throw failed_constructor ();
@@ -576,11 +583,11 @@ SVAModifier::from_string (string const & str)
        while (ss) {
                ss >> mod;
                if ((pos = mod.find ("alpha:")) != string::npos) {
        while (ss) {
                ss >> mod;
                if ((pos = mod.find ("alpha:")) != string::npos) {
-                       a = PBD::atof (mod.substr (pos+6));
+                       _a = PBD::atof (mod.substr (pos+6));
                } else if ((pos = mod.find ("saturate:")) != string::npos) {
                } else if ((pos = mod.find ("saturate:")) != string::npos) {
-                       s = PBD::atof (mod.substr (pos+9));
+                       _s = PBD::atof (mod.substr (pos+9));
                } else if ((pos = mod.find ("darkness:")) != string::npos) {
                } else if ((pos = mod.find ("darkness:")) != string::npos) {
-                       v = PBD::atof (mod.substr (pos+9));
+                       _v = PBD::atof (mod.substr (pos+9));
                } else {
                        throw failed_constructor ();
                }
                } else {
                        throw failed_constructor ();
                }
@@ -590,7 +597,7 @@ SVAModifier::from_string (string const & str)
 string
 SVAModifier::to_string () const
 {
 string
 SVAModifier::to_string () const
 {
-       PBD::LocaleGuard lg ("POSIX");
+       PBD::LocaleGuard lg;
        stringstream ss;
 
        switch (type) {
        stringstream ss;
 
        switch (type) {
@@ -605,16 +612,16 @@ SVAModifier::to_string () const
                break;
        }
 
                break;
        }
 
-       if (s > -1.0) {
-               ss << " saturate:" << s;
+       if (_s >= 0.0) {
+               ss << " saturate:" << _s;
        }
 
        }
 
-       if (v > -1.0) {
-               ss << " darker:" << v;
+       if (_v >= 0.0) {
+               ss << " darker:" << _v;
        }
 
        }
 
-       if (a > -1.0) {
-               ss << " alpha:" << a;
+       if (_a >= 0.0) {
+               ss << " alpha:" << _a;
        }
 
        return ss.str();
        }
 
        return ss.str();
@@ -624,27 +631,27 @@ HSV
 SVAModifier::operator () (HSV& hsv)  const
 {
        HSV r (hsv);
 SVAModifier::operator () (HSV& hsv)  const
 {
        HSV r (hsv);
-       
+
        switch (type) {
        case Add:
        switch (type) {
        case Add:
-               r.s += s;
-               r.v += v;
-               r.a += a;
+               r.s += _s;
+               r.v += _v;
+               r.a += _a;
                break;
        case Multiply:
                break;
        case Multiply:
-               r.s *= s;
-               r.v *= v;
-               r.a *= a;
+               r.s *= _s;
+               r.v *= _v;
+               r.a *= _a;
                break;
        case Assign:
                break;
        case Assign:
-               if (s > -1.0) {
-                       r.s = s;
+               if (_s >= 0.0) {
+                       r.s = _s;
                }
                }
-               if (v > -1.0) {
-                       r.v = v;
+               if (_v >= 0.) {
+                       r.v = _v;
                }
                }
-               if (a > -1.0) {
-                       r.a = a;
+               if (_a >= 0.0) {
+                       r.a = _a;
                }
                break;
        }
                }
                break;
        }
@@ -652,3 +659,10 @@ SVAModifier::operator () (HSV& hsv)  const
        return r;
 }
 
        return r;
 }
 
+ArdourCanvas::Color
+ArdourCanvas::color_at_alpha (ArdourCanvas::Color c, double a)
+{
+       double r, g, b, unused;
+       color_to_rgba (c, r, g, b, unused);
+       return rgba_to_color( r,g,b, a );
+}