X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcolor.cpp;fp=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcolor.cpp;h=0000000000000000000000000000000000000000;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=1dcc314ebe049fe06add9eb84d6d7b953e96fc55;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/color.cpp b/synfig-core/trunk/src/synfig/color.cpp deleted file mode 100644 index 1dcc314..0000000 --- a/synfig-core/trunk/src/synfig/color.cpp +++ /dev/null @@ -1,599 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file color.cpp -** \brief Color Class -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** Copyright (c) 2007, 2008 Chris Moore -** -** 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. -** -** 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 ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include "color.h" -#include -#include -#include -#include - -#endif - -using namespace synfig; -using namespace etl; -using namespace std; - -/* === M A C R O S ========================================================= */ - -#define COLOR_EPSILON (0.000001f) - -/* === G L O B A L S ======================================================= */ - -/* === P R O C E D U R E S ================================================= */ - -/* === M E T H O D S ======================================================= */ - - - -ColorReal -Color::hex2real(String s) -{ - std::istringstream i(s); - int n; - i.fill('0'); - if (!(i >> hex >> n)) - throw String("bad conversion from hex string \"") + s + String("\""); - return n / 255.0f; -} - -const String -Color::real2hex(ColorReal c) -{ - std::ostringstream o; - o.width(2); - o.fill('0'); - if (c<0) c = 0; - if (c>1) c = 1; - o << hex << int(c*255.0f); - return o.str(); -} - -void -Color::set_hex(String& str) -{ - value_type r, g, b; - String hex; - - // use just the hex characters - for (String::const_iterator iter = str.begin(); iter != str.end(); iter++) - if (isxdigit(*iter)) - hex.push_back(*iter); - - try - { - if (hex.size() == 1) - { - r = hex2real(hex.substr(0,1)+hex.substr(0,1)); - r_ = g_ = b_ = r; - } - else if (hex.size() == 3) - { - r = hex2real(hex.substr(0,1)+hex.substr(0,1)); - g = hex2real(hex.substr(1,1)+hex.substr(1,1)); - b = hex2real(hex.substr(2,1)+hex.substr(2,1)); - r_ = r; g_ = g; b_ = b; - } - else if (hex.size() == 6) - { - r = hex2real(hex.substr(0,2)); - g = hex2real(hex.substr(2,2)); - b = hex2real(hex.substr(4,2)); - r_ = r; g_ = g; b_ = b; - } - } - catch (string s) - { - printf("caught <%s>\n", s.c_str()); - return; - } -} - -const String -Color::get_string(void)const -{ - std::ostringstream o; - o << std::fixed << std::setprecision(3) << "#" << get_hex() << " : " << std::setw(6) << a_; - return String(o.str().c_str()); -} - -#if 0 -Color& -Color::rotate_uv(const Angle& theta)const -{ -/*/ - Color ret(*this); - ret.set_hue(ret.get_hue()+theta); - return ret; -/*/ - 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); - //return YUV(get_y(),b*u-a*v,a*u+b*v,get_a()); -//*/ -} -#endif - -Color -Color::clamped_negative()const -{ - Color ret=*this; - - if(ret.a_==0) - return alpha(); - - if(ret.a_<0) - ret=-ret; - - if(ret.r_<0) - { - ret.g_-=ret.r_; - ret.b_-=ret.r_; - ret.r_=0.0f; - } - if(ret.g_<0) - { - ret.r_-=ret.g_; - ret.b_-=ret.g_; - ret.g_=0.0f; - } - if(ret.b_<0) - { - ret.r_-=ret.b_; - ret.g_-=ret.b_; - ret.b_=0.0f; - } - - if(ret.r_>1) ret.r_=1; - if(ret.g_>1) ret.g_=1; - if(ret.b_>1) ret.b_=1; - if(ret.a_>1) ret.a_=1; - - if(isnan(ret.get_r())) ret.r_=0.5; - if(isnan(ret.get_g())) ret.g_=0.5; - if(isnan(ret.get_b())) ret.b_=0.5; - if(isnan(ret.get_a())) ret.a_=1; - -/* - if(ret.r_>1) { ret.g_/=ret.r_; ret.b_/=ret.r_; ret.r_=1; } - if(ret.g_>1) { ret.r_/=ret.g_; ret.b_/=ret.g_; ret.g_=1; } - if(ret.b_>1) { ret.g_/=ret.b_; ret.r_/=ret.b_; ret.b_=1; } - if(ret.a_>1) ret.a_=1; -*/ - - return ret; -} - -Color -Color::clamped()const -{ - Color ret(*this); - if(ret.get_r()<0) - ret.set_r(0); - if(ret.get_g()<0) - ret.set_g(0); - if(ret.get_b()<0) - ret.set_b(0); - if(ret.get_a()<0) - ret.set_a(0); - - if(ret.r_>1) ret.r_=1; - if(ret.g_>1) ret.g_=1; - if(ret.b_>1) ret.b_=1; - if(ret.a_>1) ret.a_=1; - - if(isnan(ret.get_r())) ret.r_=0.5; - if(isnan(ret.get_g())) ret.g_=0.5; - if(isnan(ret.get_b())) ret.b_=0.5; - if(isnan(ret.get_a())) ret.a_=1; - - return(ret); -} - -typedef Color (*blendfunc)(Color &,Color &,float); - -static Color -blendfunc_COMPOSITE(Color &src,Color &dest,float amount) -{ - //c_dest'=c_src+(1.0-a_src)*c_dest - //a_dest'=a_src+(1.0-a_src)*a_dest - - float a_src=src.get_a()*amount; - float a_dest=dest.get_a(); - - // if a_arc==0.0 - //if(fabsf(a_src)COLOR_EPSILON) - { - dest/=a_dest; - dest.set_a(a_dest); - } - else - { - dest=Color::alpha(); - } - assert(dest.is_valid()); - return dest; -} - -static Color -blendfunc_STRAIGHT(Color &src,Color &bg,float amount) -{ - //a_out'=(a_src-a_bg)*amount+a_bg - //c_out'=(((c_src*a_src)-(c_bg*a_bg))*amount+(c_bg*a_bg))/a_out' - - // ie: if(amount==1.0) - //if(fabsf(amount-1.0f)COLOR_EPSILON) -// if(a_out>COLOR_EPSILON || a_out<-COLOR_EPSILON) - { - out=((src*src.get_a()-bg*bg.get_a())*amount+bg*bg.get_a())/a_out; - out.set_a(a_out); - } - else - out=Color::alpha(); - - assert(out.is_valid()); - return out; -} - -static Color -blendfunc_ONTO(Color &a,Color &b,float amount) -{ - float alpha(b.get_a()); - return blendfunc_COMPOSITE(a,b.set_a(1.0f),amount).set_a(alpha); -} - -static Color -blendfunc_STRAIGHT_ONTO(Color &a,Color &b,float amount) -{ - a.set_a(a.get_a()*b.get_a()); - return blendfunc_STRAIGHT(a,b,amount); -} - -static Color -blendfunc_BRIGHTEN(Color &a,Color &b,float amount) -{ - const float alpha(a.get_a()*amount); - - if(b.get_r()(a.get_r()-1.0f)*alpha+1.0f) - b.set_r((a.get_r()-1.0f)*alpha+1.0f); - - if(b.get_g()>(a.get_g()-1.0f)*alpha+1.0f) - b.set_g((a.get_g()-1.0f)*alpha+1.0f); - - if(b.get_b()>(a.get_b()-1.0f)*alpha+1.0f) - b.set_b((a.get_b()-1.0f)*alpha+1.0f); - - - return b; -} - -static Color -blendfunc_ADD(Color &a,Color &b,float amount) -{ - const float alpha(a.get_a()*amount); - - b.set_r(b.get_r()+a.get_r()*alpha); - b.set_g(b.get_g()+a.get_g()*alpha); - b.set_b(b.get_b()+a.get_b()*alpha); - - return b; -} - -static Color -blendfunc_SUBTRACT(Color &a,Color &b,float amount) -{ - const float alpha(a.get_a()*amount); - - b.set_r(b.get_r()-a.get_r()*alpha); - b.set_g(b.get_g()-a.get_g()*alpha); - b.set_b(b.get_b()-a.get_b()*alpha); - - return b; -} - -static Color -blendfunc_DIFFERENCE(Color &a,Color &b,float amount) -{ - const float alpha(a.get_a()*amount); - - b.set_r(abs(b.get_r()-a.get_r()*alpha)); - b.set_g(abs(b.get_g()-a.get_g()*alpha)); - b.set_b(abs(b.get_b()-a.get_b()*alpha)); - - return b; -} - -static Color -blendfunc_MULTIPLY(Color &a,Color &b,float amount) -{ - if(amount<0) a=~a, amount=-amount; - - amount*=a.get_a(); - b.set_r(((b.get_r()*a.get_r())-b.get_r())*(amount)+b.get_r()); - b.set_g(((b.get_g()*a.get_g())-b.get_g())*(amount)+b.get_g()); - b.set_b(((b.get_b()*a.get_b())-b.get_b())*(amount)+b.get_b()); - return b; -} - -static Color -blendfunc_DIVIDE(Color &a,Color &b,float amount) -{ - amount*=a.get_a(); - - // We add COLOR_EPSILON in order to avoid a divide-by-zero condition. - // This causes DIVIDE to bias toward positive values, but the effect is - // really negligible. There is a reason why we use COLOR_EPSILON--we - // want the change to be imperceptible. - - b.set_r(((b.get_r()/(a.get_r()+COLOR_EPSILON))-b.get_r())*(amount)+b.get_r()); - b.set_g(((b.get_g()/(a.get_g()+COLOR_EPSILON))-b.get_g())*(amount)+b.get_g()); - b.set_b(((b.get_b()/(a.get_b()+COLOR_EPSILON))-b.get_b())*(amount)+b.get_b()); - - return b; -} - -static Color -blendfunc_COLOR(Color &a,Color &b,float amount) -{ - Color temp(b); - temp.set_uv(a.get_u(),a.get_v()); - return (temp-b)*amount*a.get_a()+b; -} - -static Color -blendfunc_HUE(Color &a,Color &b,float amount) -{ - Color temp(b); - temp.set_hue(a.get_hue()); - return (temp-b)*amount*a.get_a()+b; -} - -static Color -blendfunc_SATURATION(Color &a,Color &b,float amount) -{ - Color temp(b); - temp.set_s(a.get_s()); - return (temp-b)*amount*a.get_a()+b; -} - -static Color -blendfunc_LUMINANCE(Color &a,Color &b,float amount) -{ - Color temp(b); - temp.set_y(a.get_y()); - return (temp-b)*amount*a.get_a()+b; -} - -static Color -blendfunc_BEHIND(Color &a,Color &b,float amount) -{ - if(a.get_a()==0)a.set_a(COLOR_EPSILON); //!< \todo this is a hack - a.set_a(a.get_a()*amount); - return blendfunc_COMPOSITE(b,a,1.0); -} - -static Color -blendfunc_ALPHA_BRIGHTEN(Color &a,Color &b,float amount) -{ - // \todo can this be right, multiplying amount by *b*'s alpha? - // compare with blendfunc_BRIGHTEN where it is multiplied by *a*'s - if(a.get_a() < b.get_a()*amount) - return a.set_a(a.get_a()*amount); - return b; -} - -static Color -blendfunc_ALPHA_DARKEN(Color &a,Color &b,float amount) -{ - if(a.get_a()*amount > b.get_a()) - return a.set_a(a.get_a()*amount); - return b; -} - -static Color -blendfunc_SCREEN(Color &a,Color &b,float amount) -{ - if(amount<0) a=~a, amount=-amount; - - a.set_r(1.0-(1.0f-a.get_r())*(1.0f-b.get_r())); - a.set_g(1.0-(1.0f-a.get_g())*(1.0f-b.get_g())); - a.set_b(1.0-(1.0f-a.get_b())*(1.0f-b.get_b())); - - return blendfunc_ONTO(a,b,amount); -} - -static Color -blendfunc_OVERLAY(Color &a,Color &b,float amount) -{ - if(amount<0) a=~a, amount=-amount; - - Color rm; - rm.set_r(b.get_r()*a.get_r()); - rm.set_g(b.get_g()*a.get_g()); - rm.set_b(b.get_b()*a.get_b()); - - Color rs; - rs.set_r(1.0-(1.0f-a.get_r())*(1.0f-b.get_r())); - rs.set_g(1.0-(1.0f-a.get_g())*(1.0f-b.get_g())); - rs.set_b(1.0-(1.0f-a.get_b())*(1.0f-b.get_b())); - - Color& ret(a); - - ret.set_r(a.get_r()*rs.get_r() + (1.0-a.get_r())*rm.get_r()); - ret.set_g(a.get_g()*rs.get_g() + (1.0-a.get_g())*rm.get_g()); - ret.set_b(a.get_b()*rs.get_b() + (1.0-a.get_b())*rm.get_b()); - - return blendfunc_ONTO(ret,b,amount); -} - -static Color -blendfunc_HARD_LIGHT(Color &a,Color &b,float amount) -{ - if(amount<0) a=~a, amount=-amount; - - if(a.get_r()>0.5f) a.set_r(1.0-(1.0f-(a.get_r()*2.0f-1.0f))*(1.0f-b.get_r())); - else a.set_r(b.get_r()*(a.get_r()*2.0f)); - if(a.get_g()>0.5f) a.set_g(1.0-(1.0f-(a.get_g()*2.0f-1.0f))*(1.0f-b.get_g())); - else a.set_g(b.get_g()*(a.get_g()*2.0f)); - if(a.get_b()>0.5f) a.set_b(1.0-(1.0f-(a.get_b()*2.0f-1.0f))*(1.0f-b.get_b())); - else a.set_b(b.get_b()*(a.get_b()*2.0f)); - - return blendfunc_ONTO(a,b,amount); -} - -static Color -blendfunc_ALPHA_OVER(Color &a,Color &b,float amount) -{ - Color rm(b); - - //multiply the inverse alpha channel with the one below us - rm.set_a((1-a.get_a())*b.get_a()); - - return blendfunc_STRAIGHT(rm,b,amount); -} - - -Color -Color::blend(Color a, Color b,float amount, Color::BlendMethod type) -{ -#if 0 - if(isnan(a.get_r()) || isnan(a.get_g()) || isnan(a.get_b())) - { -#ifdef _DEBUG - a=magenta().set_a(a.get_a()); -#else - a=black().set_a(a.get_a()); -#endif - } - - if(isnan(b.get_r()) || isnan(b.get_g()) || isnan(b.get_b())) - { -#ifdef _DEBUG - b=magenta().set_a(b.get_a()); -#else - b=black().set_a(b.get_a()); -#endif - } -#endif - -/* - if(!a.is_valid()&&b.is_valid()) - return b; - - if(a.is_valid()&&!b.is_valid()) - return a; - - if(!a.is_valid()||!b.is_valid()) - { -#ifdef _DEBUG - return magenta(); -#else - return black(); -#endif - } -*/ - - // No matter what blend method is being used, - // if the amount is equal to zero, then only B - // will shine through - if(fabsf(amount)<=COLOR_EPSILON)return b; - - assert(type