Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-core / trunk / src / synfig / color.h
index 868420b..d54b0e9 100644 (file)
@@ -2,19 +2,21 @@
 /*!    \file color.h
 **     \brief Color Class Implementation
 **
-**     $Id: color.h,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $
+**     $Id$
 **
 **     \legal
-**     Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
 **
-**     This software and associated documentation
-**     are CONFIDENTIAL and PROPRIETARY property of
-**     the above-mentioned copyright holder.
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
 **
-**     You may not copy, print, publish, or in any
-**     other way distribute this software without
-**     a prior written agreement with
-**     the copyright holder.
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
 **     \endlegal
 */
 /* ========================================================================= */
 
 /* === H E A D E R S ======================================================= */
 
-#ifndef SYNFIG_NO_ANGLE
-# include "angle.h"
-#endif
 
 //#include <cmath>
 #include <math.h>
 #include <cassert>
 #include "gamma.h"
-#include <string.h>
+#include <synfig/string.h>
 
 #ifdef USE_HALF_TYPE
 #include <OpenEXR/half.h>
 #endif
 
+#ifndef SYNFIG_NO_ANGLE
+# include "angle.h"
+#endif
+
 /* === M A C R O S ========================================================= */
 
-#ifndef isnan
+#define use_colorspace_gamma() App::use_colorspace_gamma
+#define colorspace_gamma()             (2.2f)
+#define gamma_in(x)                            ((x>=0) ? pow((float)x,1.0f/colorspace_gamma()) : -pow((float)-x,1.0f/colorspace_gamma()))
+#define gamma_out(x)                   ((x>=0) ? pow((float)x,     colorspace_gamma()) : -pow((float)-x,     colorspace_gamma()))
 
 #ifdef WIN32
 #include <float.h>
@@ -52,10 +58,15 @@ extern "C" { int _isnan(double x); }
 #endif
 #endif
 
-#ifdef __APPLE__
-#define isnan __isnanf
+// For some reason isnan() isn't working on macosx any more.
+// This is a quick fix.
+#if defined(__APPLE__) && !defined(SYNFIG_ISNAN_FIX)
+#ifdef isnan
+#undef isnan
 #endif
-
+inline bool isnan(double x) { return x != x; }
+inline bool isnan(float x) { return x != x; }
+#define SYNFIG_ISNAN_FIX 1
 #endif
 
 namespace synfig {
@@ -105,6 +116,8 @@ private:
 
 public:
 
+       const String get_string(void)const;
+
        Color &
        operator+=(const Color &rhs)
        {
@@ -181,12 +194,12 @@ public:
 
        bool is_valid()const
        { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
-       
+
        Color premult_alpha() const
        {
                return Color (r_*a_, g_*a_, b_*a_, a_);
        }
-       
+
        Color demult_alpha() const
        {
                if(a_)
@@ -197,7 +210,11 @@ public:
        }
 
 public:
-       Color() /*:r_(0), g_(0), b_(0), a_(0)*/ { }
+       // ETL/trunk/ETL/_gaussian.h does:
+       //   SR1=SR2=SR3=typename T::value_type();
+       // and expects that to give it initialized colors
+       // Otherwise the 'gaussian' blur type is random.
+       Color() :a_(0), r_(0), g_(0), b_(0) { }
        Color(const value_type &f) :a_(f),r_(f), g_(f), b_(f) { }
        Color(int f) :a_(f),r_(f), g_(f), b_(f) { }
 
@@ -211,22 +228,22 @@ public:
                g_(G),
                b_(B) { }
 
-       /*!     \param C Source for color components
+       /*!     \param c Source for color components
        **      \param A Opacity(alpha) */
        Color(const Color& c, const value_type& A):
-               a_(c.a_),
+               a_(A),
                r_(c.r_),
                g_(c.g_),
                b_(c.b_) { }
 
-       
+
        //!     Copy constructor
        Color(const Color& c):
                a_(c.a_),
                r_(c.r_),
                g_(c.g_),
                b_(c.b_) { }
-       
+
 #ifdef USE_HALF_TYPE
        friend class ColorAccumulator;
        //!     Convert constructor
@@ -242,7 +259,7 @@ public:
                return *this;
        }*/
        //Color& operator=(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); return *this; }
-       
+
        //! Returns the RED component
        const value_type& get_r()const { return r_; }
 
@@ -254,10 +271,22 @@ public:
 
        //! Returns the amount of opacity (alpha)
        const value_type& get_a()const { return a_; }
-       
+
        //! Synonym for get_a(). \see get_a()
        const value_type& get_alpha()const { return get_a(); }
 
+       //! Converts a 2 character hex string \a s (00-ff) into a ColorReal (0.0-1.0)
+       static ColorReal hex2real(String s);
+
+       //! Converts a ColorReal \a c (0.0-1.0) into a 2 character hex string (00-ff)
+       static const String real2hex(ColorReal c);
+
+       //! Returns the color as a 6 character hex sting
+       const String get_hex()const { return String(real2hex(r_)+real2hex(g_)+real2hex(b_)); }
+
+       //! Sets the color's R, G, and B from a 3 or 6 character hex string
+       void set_hex(String& hex);
+
        //! Sets the RED component to \a x
        Color& set_r(const value_type& x) { r_ = x; return *this; }
 
@@ -269,7 +298,7 @@ public:
 
        //! Sets the opacity (alpha) to \a x
        Color& set_a(const value_type& x) { a_ = x; return *this; }
-       
+
        //! Synonym for set_a(). \see set_a()
        Color& set_alpha(const value_type& x) { return set_a(x); }
 
@@ -283,7 +312,7 @@ public:
                        (float)get_b()*EncodeYUV[0][2];
        }
 
-       
+
        //! Returns U component of chromanance
        float
        get_u() const
@@ -327,16 +356,16 @@ public:
 
        //! Sets color luminance
        Color& set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
-       
+
        //! Set U component of chromanance
        Color& set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
-       
+
        //! Set V component of chromanance
        Color& set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
-       
+
        //! Set the U and V components of chromanance
        Color& set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
-               
+
        //! Sets the color's saturation
        /*!     \see get_s() */
        Color&
@@ -344,7 +373,7 @@ public:
        {
                float u(get_u()), v(get_v());
                const float s(sqrt(u*u+v*v));
-               if(s)   
+               if(s)
                {
                        u=(u/s)*x;
                        v=(v/s)*x;
@@ -367,7 +396,7 @@ public:
 
        //! Synonym for get_hue(). \see get_hue()
        Angle get_uv_angle() const { return get_hue(); }
-       
+
        //! Sets the color's hue
        /*!     \see get_hue() */
        Color&
@@ -382,16 +411,16 @@ public:
 
        //! Synonym for set_hue(). \see set_hue()
        Color& set_uv_angle(const Angle& theta) { return set_hue(theta); }
-       
+
        //! Rotates the chromanance vector by amount specified by \a theta
        Color& rotate_uv(const Angle& theta)
        {
                const float     a(Angle::sin(theta).get()),     b(Angle::cos(theta).get());
                const float     u(get_u()),     v(get_v());
-               
+
                return set_uv(b*u-a*v,a*u+b*v);
        }
-               
+
        //! Sets the luminance (\a y) and chromanance (\a s and \a theta).
        /*!     \param y Luminance
        **      \param s Saturation
@@ -418,7 +447,7 @@ public:
 
        //! Clamps a color so that its values are in range. Ignores attempting to visualize negative colors.
        Color clamped()const;
-       
+
        //! Clamps a color so that its values are in range.
        Color clamped_negative()const;
 
@@ -441,41 +470,40 @@ public:
        static inline Color cyan() { return Color(0,1,1); }
        static inline Color yellow() { return Color(1,1,0); }
        //@}
-       
+
        //! \writeme
        enum BlendMethod
        {
-               BLEND_COMPOSITE=0,      //!< Color A is composited onto B (Taking into about A's alpha)
-               BLEND_STRAIGHT=1,       //!< Straight linear interpolation from A->B (Alpha ignored)
-               BLEND_BRIGHTEN=2,       //!< If composite is brighter than B, use composite. B otherwise.
-               BLEND_DARKEN=3,         //!< If composite is brighter than B, use composite. B otherwise.
-               BLEND_ADD=4,            //!< Simple A+B.
-               BLEND_SUBTRACT=5,       //!< Simple A-B.
-               BLEND_MULTIPLY=6,       //!< Simple A*B.
-               BLEND_DIVIDE=7,         //!< Simple B/A
-               BLEND_COLOR=8,          //!< Preserves the U and V channels of color A
-               BLEND_HUE=9,            //!< Preserves the angle of the UV vector of color A
-               BLEND_SATURATION=10,//!< Preserves the magnitude of the UV Vector of color A
-               BLEND_LUMINANCE=11,     //!< Preserves the Y channel of color A
-               BLEND_BEHIND=12,        //!< Similar to BLEND_COMPOSITE, except that B is composited onto A.
-               BLEND_ONTO=13,          //!< Similar to BLEND_COMPOSITE, except that B's alpha is maintained
-               BLEND_SCREEN=16,                //!< \writeme
-               BLEND_OVERLAY=20,               //!< \writeme
-               BLEND_DIFFERENCE=18,            //!< \writeme
+               BLEND_COMPOSITE=0,                      //!< Color A is composited onto B (Taking A's alpha into account)
+               BLEND_STRAIGHT=1,                       //!< Straight linear interpolation from A->B (Alpha ignored)
+               BLEND_ONTO=13,                          //!< Similar to BLEND_COMPOSITE, except that B's alpha is maintained
+               BLEND_STRAIGHT_ONTO=21,         //!< \deprecated \writeme
+               BLEND_BEHIND=12,                        //!< Similar to BLEND_COMPOSITE, except that B is composited onto A.
+               BLEND_SCREEN=16,                        //!< \writeme
+               BLEND_OVERLAY=20,                       //!< \writeme
                BLEND_HARD_LIGHT=17,            //!< \writeme
-               
-               //! Deprecated
-               BLEND_ALPHA_BRIGHTEN=14,        //!< If A is less opaque than B, use A
-               BLEND_ALPHA_DARKEN=15,          //!< If A is more opaque than B, use B
-               BLEND_ALPHA_OVER=19,//!< multiply alphas and then straight blends that using the amount
-               BLEND_STRAIGHT_ONTO=21,//!< \writeme
-               
-               BLEND_END=22                    //!< \internal
+               BLEND_MULTIPLY=6,                       //!< Simple A*B.
+               BLEND_DIVIDE=7,                         //!< Simple B/A
+               BLEND_ADD=4,                            //!< Simple A+B.
+               BLEND_SUBTRACT=5,                       //!< Simple A-B.
+               BLEND_DIFFERENCE=18,            //!< Simple |A-B|.
+               BLEND_BRIGHTEN=2,                       //!< If composite is brighter than B, use composite. B otherwise.
+               BLEND_DARKEN=3,                         //!< If composite is darker than B, use composite. B otherwise.
+               BLEND_COLOR=8,                          //!< Preserves the U and V channels of color A
+               BLEND_HUE=9,                            //!< Preserves the angle of the UV vector of color A
+               BLEND_SATURATION=10,            //!< Preserves the magnitude of the UV Vector of color A
+               BLEND_LUMINANCE=11,                     //!< Preserves the Y channel of color A
+
+               BLEND_ALPHA_BRIGHTEN=14,        //!< \deprecated If A is less opaque than B, use A
+               BLEND_ALPHA_DARKEN=15,          //!< \deprecated If A is more opaque than B, use B
+               BLEND_ALPHA_OVER=19,            //!< \deprecated multiply alphas and then straight blends using the amount
+
+               BLEND_END=22                            //!< \internal
        };
 
        /* Other */
        static Color blend(Color a, Color b,float amount,BlendMethod type=BLEND_COMPOSITE);
-       
+
        static bool is_onto(BlendMethod x)
        {
                return x==BLEND_BRIGHTEN
@@ -496,6 +524,15 @@ public:
                        || x==BLEND_HARD_LIGHT
                ;
        }
+
+       //! a blending method is considered 'straight' if transparent pixels in the upper layer can affect the result of the blend
+       static bool is_straight(BlendMethod x)
+       {
+               return x==BLEND_STRAIGHT
+                       || x==BLEND_STRAIGHT_ONTO
+                       || x==BLEND_ALPHA_BRIGHTEN
+               ;
+       }
 /*protected:
 
        value_type& operator[](const int i)
@@ -627,6 +664,9 @@ public:
                g_(c.g_),
                b_(c.b_) { }
 
+       //! Converter
+       ColorAccumulator(int c): a_(c),r_(c), g_(c), b_(c) { }
+
        //! Returns the RED component
        const value_type& get_r()const { return r_; }
 
@@ -638,7 +678,7 @@ public:
 
        //! Returns the amount of opacity (alpha)
        const value_type& get_a()const { return a_; }
-       
+
        //! Synonym for get_a(). \see get_a()
        const value_type& get_alpha()const { return get_a(); }
 
@@ -653,7 +693,7 @@ public:
 
        //! Sets the opacity (alpha) to \a x
        ColorAccumulator& set_a(const value_type& x) { a_ = x; return *this; }
-       
+
        //! Synonym for set_a(). \see set_a()
        ColorAccumulator& set_alpha(const value_type& x) { return set_a(x); }
 };
@@ -681,7 +721,7 @@ enum PixelFormat
 ** 3   Endian (BGR/RGB)
 ** 4   Alpha Location (Start/End)
 ** 5   ZDepth Location (Start/End)
-** 6   Alpha/ZDepth Arangement (ZA,AZ)
+** 6   Alpha/ZDepth Arrangement (ZA,AZ)
 ** 7   Alpha Range (Inverted,Normal)
 ** 8   Z Range (Inverted,Normal)
 */
@@ -692,16 +732,16 @@ enum PixelFormat
        PF_BGR=(1<<3),                  //!< If set, reverse the order of the RGB channels
        PF_A_START=(1<<4),              //!< If set, alpha channel is before the color data. If clear, it is after.
        PF_Z_START=(1<<5),              //!< If set, ZDepth channel is before the color data. If clear, it is after.
-       PF_ZA=(1<<6),                   //!< If set, the ZDepth channel will be infront of the alpha channel. If clear, they are reversed.
+       PF_ZA=(1<<6),                   //!< If set, the ZDepth channel will be in front of the alpha channel. If clear, they are reversed.
 
        PF_A_INV=(1<<7),                //!< If set, the alpha channel is stored as 1.0-a
        PF_Z_INV=(1<<8),                //!< If set, the ZDepth channel is stored as 1.0-z
-       PF_RAW_COLOR=(1<<9)+(1<<1)      //!< If set, the data represents a raw Color datastructure, and all other bits are ignored.
+       PF_RAW_COLOR=(1<<9)+(1<<1)      //!< If set, the data represents a raw Color data structure, and all other bits are ignored.
 };
 
 inline PixelFormat operator|(PixelFormat lhs, PixelFormat rhs)
        { return static_cast<PixelFormat>((int)lhs|(int)rhs); }
-       
+
 inline PixelFormat operator&(PixelFormat lhs, PixelFormat rhs)
        { return static_cast<PixelFormat>((int)lhs&(int)rhs); }
 #define FLAGS(x,y)             (((x)&(y))==(y))
@@ -721,7 +761,7 @@ channels(PixelFormat x)
                ++chan;
        if(FLAGS(x,PF_RAW_COLOR))
                chan=sizeof(Color);
-               
+
        return chan;
 }
 
@@ -739,7 +779,7 @@ Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out,
        int alpha=(int)((FLAGS(pf,PF_A_INV)?(-(float)color.get_a()+1):(float)color.get_a())*255);
        if(alpha<0)alpha=0;
        if(alpha>255)alpha=255;
-               
+
        if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
        {
                if(FLAGS(pf,PF_Z_START))
@@ -753,7 +793,7 @@ Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out,
                        *out++=static_cast<unsigned char>(alpha);
                if(FLAGS(pf,PF_Z_START))
                        *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
-               
+
        }
 
        if(FLAGS(pf,PF_GRAY))
@@ -773,7 +813,7 @@ Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out,
                        *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_b()));
                }
        }
-       
+
        if(FLAGS(pf,PF_ZA))
        {
                if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
@@ -834,7 +874,7 @@ PixelFormat2Color(Color &color, const PixelFormat &pf,const unsigned char *out)
                        color.set_b((float)*out++/255);
                }
        }
-       
+
        if(FLAGS(pf,PF_ZA))
        {
                if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))