synfig-core  1.0.3
cairocolor.h
Go to the documentation of this file.
1 /* === S Y N F I G ========================================================= */
24 /* ========================================================================= */
25 
26 #ifndef __SYNFIG_COLOR_CAIROCOLOR_H
27 #define __SYNFIG_COLOR_CAIROCOLOR_H
28 
29 #include <synfig/color/common.h>
30 
31 namespace synfig {
32 
33 class CairoColorAccumulator;
34 
53 {
54 public:
56 
57 private:
58  value_type pixel;
59 
60 public:
61  static const unsigned char ceil=255;
62  static const unsigned char floor=0;
63  static const float range;
64  static const value_type amask=0xFF<<24;
65  static const value_type rmask=0xFF<<16;
66  static const value_type gmask=0xFF<<8;
67  static const value_type bmask=0xFF;
68 
69  // Operators
70 public:
71  inline unsigned char ceil_clamp(int x)
72  {
73  if(x>ceil) return ceil;
74  else return (unsigned char)(x);
75  }
76  inline unsigned char floor_clamp(int x)
77  {
78  if(x<floor) return floor;
79  else return (unsigned char)(x);
80  }
81  inline unsigned char clamp(int x)
82  {
83  if(x > ceil) return ceil;
84  else if (x < floor) return floor;
85  else return (unsigned char)(x);
86  }
87  inline unsigned char clamp(float x)
88  {
89  return clamp((int) (x));
90  }
91 
92  CairoColor&
93  operator+=(const CairoColor &rhs)
94  {
95  set_r(ceil_clamp((int)(get_r()) + rhs.get_r()));
96  set_g(ceil_clamp((int)(get_g()) + rhs.get_g()));
97  set_b(ceil_clamp((int)(get_b()) + rhs.get_b()));
98  set_a(ceil_clamp((int)(get_a()) + rhs.get_a()));
99  return *this;
100  }
101 
102  CairoColor&
103  operator-=(const CairoColor &rhs)
104  {
105  set_r(floor_clamp((int)(get_r()) - rhs.get_r()));
106  set_g(floor_clamp((int)(get_g()) - rhs.get_g()));
107  set_b(floor_clamp((int)(get_b()) - rhs.get_b()));
108  set_a(floor_clamp((int)(get_a()) - rhs.get_a()));
109  return *this;
110  }
111 
112  CairoColor &
113  operator*=(const float &rhs)
114  {
115  set_r(clamp(get_r()*rhs));
116  set_g(clamp(get_g()*rhs));
117  set_b(clamp(get_b()*rhs));
118  set_a(clamp(get_a()*rhs));
119  return *this;
120  }
121 
122  CairoColor &
123  operator/=(const float &rhs)
124  {
125  const float temp(1.0f/rhs);
126  set_r(clamp(get_r()*temp));
127  set_g(clamp(get_g()*temp));
128  set_b(clamp(get_b()*temp));
129  set_a(clamp(get_a()*temp));
130  return *this;
131  }
132 
133  CairoColor
134  operator+(const CairoColor &rhs)const
135  { return CairoColor(*this)+=rhs; }
136 
137  CairoColor
138  operator-(const CairoColor &rhs)const
139  { return CairoColor(*this)-=rhs; }
140 
141  CairoColor
142  operator*(const float &rhs)const
143  { return CairoColor(*this)*=rhs; }
144 
145  CairoColor
146  operator/(const float &rhs)const
147  { return CairoColor(*this)/=rhs; }
148 
149  bool
150  operator==(const CairoColor &rhs)const
151  { return get_r()==rhs.get_r()
152  && get_g()==rhs.get_g()
153  && get_b()==rhs.get_b()
154  && get_a()==rhs.get_a(); }
155 
156  bool
157  operator!=(const CairoColor &rhs)const
158  { return get_r()!=rhs.get_r()
159  || get_g()!=rhs.get_g()
160  || get_b()!=rhs.get_b()
161  || get_a()!=rhs.get_a(); }
162 
163 // Not suitable for CairoColor
164 // operator-()const
165 // { return CairoColor(-r_,-g_,-b_,-a_); }
166 
167  CairoColor
168  operator~()const
169  { return CairoColor((unsigned char)(ceil-get_r()),(unsigned char)(ceil-get_g()),(unsigned char)(ceil-get_b()),get_a()); }
170 
171  bool is_valid()const
172  { return true; }
173 
174 
176  {
177  const float a(get_a()/range);
178  return CairoColor (get_r()*a, get_g()*a, get_b()*a, get_a());
179  }
180 
182  {
183  if(get_a())
184  {
185  const float inva = range/get_a();
186  return CairoColor (get_r()*inva, get_g()*inva, get_b()*inva, get_a());
187  }else return alpha();
188  }
189 
190  // Constructors
191 public:
192  CairoColor() :pixel(0x0) { }
193  CairoColor(const unsigned char u): pixel((u<<24)|(u<<16)|(u<<8)|(u)) { }
194  //CairoColor(int f) :a_(f),r_(f), g_(f), b_(f) { }
195  CairoColor(const unsigned char R, const unsigned char G, const unsigned char B, const unsigned char A=ceil):
196  pixel((A<<24)|(R<<16)|(G<<8)|(B)) { }
197  CairoColor(const CairoColor& c, const unsigned char A):
198  pixel(c.get_pixel()) { set_a(A); }
199  CairoColor(const CairoColor& c): pixel(c.get_pixel()) { }
200  // Conversor constructor
201  CairoColor(const Color& c)
202  {
207  }
208  // From CairoColorAccumulator
209  friend class CairoColorAccumulator;
210  inline CairoColor(const CairoColorAccumulator& c);
211  CairoColor(int r, int g, int b, int a);
212 
213  value_type get_pixel()const {return pixel; }
214  unsigned char get_a()const { return pixel>>24; }
215  unsigned char get_r()const { return pixel>>16; }
216  unsigned char get_g()const { return pixel>>8; }
217  unsigned char get_b()const { return pixel; }
218  unsigned char get_alpha()const { return get_a(); }
219 
220  const String get_string(void)const;
221 
222  static const String char2hex(unsigned char c);
223  static unsigned char hex2char(String s);
224 
225  void set_hex( String& str);
226  const String get_hex()const { return String(char2hex(get_r())+char2hex(get_g())+char2hex(get_b())); }
227 
228  CairoColor& set_r(const unsigned char x) {pixel &= ~rmask; pixel |=(x<<16); return *this; }
229  CairoColor& set_g(const unsigned char x) {pixel &= ~gmask; pixel |=(x<<8 ); return *this; }
230  CairoColor& set_b(const unsigned char x) {pixel &= ~bmask; pixel |=(x ); return *this; }
231  CairoColor& set_a(const unsigned char x) {pixel &= ~amask; pixel |=(x<<24); return *this; }
232  CairoColor& set_alpha(const unsigned char x) { return set_a(x); }
233 
234  float
235  get_y() const
236  {
237  return(
238  (float)get_r()*EncodeYUV[0][0]+
239  (float)get_g()*EncodeYUV[0][1]+
240  (float)get_b()*EncodeYUV[0][2]
242  }
243 
244  float
245  get_u() const
246  {
247  return(
248  (float)get_r()*EncodeYUV[1][0]+
249  (float)get_g()*EncodeYUV[1][1]+
250  (float)get_b()*EncodeYUV[1][2]
252  }
253 
254  float
255  get_v() const
256  {
257  return(
258  (float)get_r()*EncodeYUV[2][0]+
259  (float)get_g()*EncodeYUV[2][1]+
260  (float)get_b()*EncodeYUV[2][2]
262  }
263 
264  float
265  get_s() const
266  {
267  const float u(get_u()), v(get_v());
268  return sqrt(u*u+v*v);
269  }
270 
271  CairoColor&
272  set_yuv(const float &y, const float &u, const float &v)
273  {
274  Color c(*this);
275  c.set_r(y*DecodeYUV[0][0]+u*DecodeYUV[0][1]+v*DecodeYUV[0][2]);
276  c.set_g(y*DecodeYUV[1][0]+u*DecodeYUV[1][1]+v*DecodeYUV[1][2]);
277  c.set_b(y*DecodeYUV[2][0]+u*DecodeYUV[2][1]+v*DecodeYUV[2][2]);
278  (*this)=CairoColor(c);
279  return *this;
280  }
281 
282  CairoColor& set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
283 
284  CairoColor& set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
285 
286  CairoColor& set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
287 
288  CairoColor& set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
289 
290  CairoColor& set_s(const float &x)
291  {
292  float u(get_u()), v(get_v());
293  const float s(sqrt(u*u+v*v));
294  if(s)
295  {
296  u=(u/s)*x;
297  v=(v/s)*x;
298  return set_uv(u,v);
299  }
300  return *this;
301  }
302 
303  static CairoColor YUV(const float& y, const float& u, const float& v, const unsigned char a=ceil)
304  { return CairoColor().set_yuv(y,u,v).set_a(a); }
305 
306  Angle get_hue() const { return Angle::tan(get_u(),get_v()); }
307 
308  Angle get_uv_angle() const { return get_hue(); }
309 
310  CairoColor& set_hue(const Angle& theta)
311  {
312  const float s(get_s());
313  const float
314  u(s*(float)Angle::sin(theta).get()),
315  v(s*(float)Angle::cos(theta).get());
316  return set_uv(u,v);
317  }
318 
319  CairoColor& set_uv_angle(const Angle& theta) { return set_hue(theta); }
320 
321  CairoColor& rotate_uv(const Angle& theta)
322  {
323  const float a(Angle::sin(theta).get()), b(Angle::cos(theta).get());
324  const float u(get_u()), v(get_v());
325  return set_uv(b*u-a*v,a*u+b*v);
326  }
327 
328  CairoColor& set_yuv(const float& y, const float& s, const Angle& theta)
329  {
330  return
331  set_yuv(
332  y,
333  s*(float)Angle::sin(theta).get(),
334  s*(float)Angle::cos(theta).get()
335  );
336  }
337 
338  static CairoColor YUV(const float& y, const float& s, const Angle& theta, const unsigned char a=ceil)
339  { return CairoColor().set_yuv(y,s,theta).set_a(a); }
340 
341  static inline CairoColor alpha() { return CairoColor(floor,floor,floor,floor); }
342  static inline CairoColor black() { return CairoColor(floor,floor,floor); }
343  static inline CairoColor white() { return CairoColor(ceil,ceil,ceil); }
344  static inline CairoColor gray() { return CairoColor(ceil/2,ceil/2,ceil/2); }
345  static inline CairoColor magenta() { return CairoColor(ceil,floor,ceil); }
346  static inline CairoColor red() { return CairoColor(ceil,floor, floor); }
347  static inline CairoColor green() { return CairoColor(floor, ceil,floor); }
348  static inline CairoColor blue() { return CairoColor(floor,floor,ceil); }
349  static inline CairoColor cyan() { return CairoColor(floor,ceil,ceil); }
350  static inline CairoColor yellow() { return CairoColor(ceil,ceil,floor); }
351 
352  // Use Color::BlenMethods for the enum value
354 
356  {
357  return Color::is_onto(x);
358  }
359 
361  {
362  return Color::is_straight(x);
363  }
364 
365 }; // End of CairoColor class
366 
367 
368 inline CairoColor::CairoColor(int r, int g, int b, int a)
369 {
374 }
375 
376 
377 
378 } // synfig namespace
379 
380 #endif // __SYNFIG_COLOR_CAIROCOLOR_H
381