synfig-core  1.0.3
cairocolorblendingfunctions.h
Go to the documentation of this file.
1 /* === S Y N F I G ========================================================= */
24 /* ========================================================================= */
25 
26 #ifndef __SYNFIG_COLOR_CAIROCOLORBLENDINGFUNCTIONS_H
27 #define __SYNFIG_COLOR_CAIROCOLORBLENDINGFUNCTIONS_H
28 
29 #include "colorblendingfunctions.h"
30 
31 namespace synfig {
32 
34 
35 template <>
38 {
39  int ra, ga, ba, aa;
40  int rb, gb, bb, ab;
41  int rc, gc, bc;
42  float ac;
43 
44  float faa, fab, A, AA;
45 
46  ra=a.get_r();
47  ga=a.get_g();
48  ba=a.get_b();
49  aa=a.get_a();
50  aa=aa*amount;
51  A=aa/255.0;
52  AA=1.0-A;
53 
54  rb=b.get_r();
55  gb=b.get_g();
56  bb=b.get_b();
57  ab=b.get_a();
58 
59  ac=aa+ab*AA;
60  if(fabsf(ac)<COLOR_EPSILON)
61  return CairoColor::alpha();
62 
63  faa=aa/ac;
64  fab=ab*AA/ac;
65 
66  rc=ra*faa+rb*fab;
67  gc=ga*faa+gb*fab;
68  bc=ba*faa+bb*fab;
69 
70  return CairoColor(rc, gc, bc, ac);
71 
72 }
73 
74 template <>
75 CairoColor
77 {
78  int ra, ga, ba, aa; //src
79  int rb, gb, bb, ab; //bg
80  int rc, gc, bc;
81  float ac; //out
82 
83  ra=a.get_r();
84  ga=a.get_g();
85  ba=a.get_b();
86  aa=a.get_a();
87 
88  rb=b.get_r();
89  gb=b.get_g();
90  bb=b.get_b();
91  ab=b.get_a();
92 
93  ac=(aa-ab)*amount+ab;
94 
95  // if ac!=0.0
96  if(fabsf(ac)>COLOR_EPSILON)
97  {
98  rc= ((ra*aa-rb*ab)*amount + rb*ab)/ac;
99  gc= ((ga*aa-gb*ab)*amount + gb*ab)/ac;
100  bc= ((ba*aa-bb*ab)*amount + bb*ab)/ac;
101  return CairoColor(rc, gc, bc, ac);
102  }
103  else
104  return CairoColor::alpha();
105 }
106 
107 template <>
108 CairoColor
109 blendfunc_ONTO(CairoColor &a, CairoColor &b, float amount)
110 {
111  unsigned char alpha(b.get_a());
112  return blendfunc_COMPOSITE(a,b.set_a(255),amount).set_a(alpha);
113 }
114 
115 template <>
116 CairoColor
118 {
119  a.set_a(a.get_a()*b.get_a()/255.0);
120  return CairoColor::blend(a, b, amount, Color::BLEND_STRAIGHT);
121 }
122 
123 template <>
124 CairoColor
126 {
127  int ra, ga, ba, aa;
128  int rb, gb, bb, ab;
129  int rc, gc, bc, ac;
130 
131  ra=a.get_r();
132  ga=a.get_g();
133  ba=a.get_b();
134  aa=a.get_a();
135 
136  rb=b.get_r();
137  gb=b.get_g();
138  bb=b.get_b();
139  ab=b.get_a();
140 
141  const float alpha = aa*amount/255.0;
142  const int raab(ra*alpha);
143  const int gaab(ga*alpha);
144  const int baab(ba*alpha);
145 
146  if(rb<raab)
147  rc=raab;
148  else
149  rc=rb;
150 
151  if(gb<gaab)
152  gc=gaab;
153  else
154  gc=gb;
155 
156  if(bb<baab)
157  bc=baab;
158  else
159  bc=bb;
160 
161  ac=ab;
162 
163  return CairoColor(rc, gc, bc, ac);
164 }
165 
166 template <>
167 CairoColor
169 {
170  int ra, ga, ba, aa;
171  int rb, gb, bb, ab;
172  int rc, gc, bc, ac;
173 
174  ra=a.get_r();
175  ga=a.get_g();
176  ba=a.get_b();
177  aa=a.get_a();
178 
179  rb=b.get_r();
180  gb=b.get_g();
181  bb=b.get_b();
182  ab=b.get_a();
183 
184  const float alpha=aa*amount/255.0;
185 
186  int rcompare=(ra-255)*alpha+255;
187  if(rb > rcompare)
188  rc=rcompare;
189  else
190  rc=rb;
191 
192  int gcompare=(ga-255)*alpha+255;
193  if(gb > gcompare)
194  gc=gcompare;
195  else
196  gc=gb;
197 
198  int bcompare=(ba-255)*alpha+255;
199  if(bb > bcompare)
200  bc=bcompare;
201  else
202  bc=bb;
203 
204  ac=ab;
205 
206  return CairoColor(rc, gc, bc, ac);
207 }
208 
209 template <>
210 CairoColor
211 blendfunc_ADD(CairoColor &a, CairoColor &b, float amount)
212 {
213  int ra, ga, ba, aa;
214  int rb, gb, bb, ab;
215  int rc, gc, bc, ac;
216 
217  ra=a.get_r();
218  ga=a.get_g();
219  ba=a.get_b();
220  aa=a.get_a();
221 
222  rb=b.get_r();
223  gb=b.get_g();
224  bb=b.get_b();
225  ab=b.get_a();
226 
227  const float aaa=aa*amount/255.0;
228 
229  rc=rb+ra*aaa;
230  gc=gb+ga*aaa;
231  bc=bb+ba*aaa;
232  ac=ab;
233 
234  return CairoColor(rc, gc, bc, ac);
235 }
236 
237 //Specialization for CairoColor
238 template <>
239 CairoColor
241 {
242  int ra, ga, ba, aa;
243  int rb, gb, bb, ab;
244  int rc, gc, bc, ac;
245 
246  ra=a.get_r();
247  ga=a.get_g();
248  ba=a.get_b();
249  aa=a.get_a();
250 
251  rb=b.get_r();
252  gb=b.get_g();
253  bb=b.get_b();
254  ab=b.get_a();
255 
256  const float aaa=aa*amount/255.0;
257 
258  rc=rb-ra*aaa;
259  gc=gb-ga*aaa;
260  bc=bb-ba*aaa;
261  ac=ab;
262 
263  return CairoColor(rc, gc, bc, ac);
264 }
265 
266 template <>
267 CairoColor
269 {
270  int ra, ga, ba, aa;
271  int rb, gb, bb, ab;
272  int rc, gc, bc, ac;
273 
274  ra=a.get_r();
275  ga=a.get_g();
276  ba=a.get_b();
277  aa=a.get_a();
278 
279  rb=b.get_r();
280  gb=b.get_g();
281  bb=b.get_b();
282  ab=b.get_a();
283 
284  const float aaa=aa*amount/255.0;
285 
286  rc=std::abs(rb-ra*aaa);
287  gc=std::abs(gb-ga*aaa);
288  bc=std::abs(bb-ba*aaa);
289  ac=ab;
290 
291  return CairoColor(rc, gc, bc, ac);
292 }
293 
294 template <>
295 CairoColor
297 {
298  if(amount<0) a=~a, amount=-amount;
299  amount*=a.get_a()/255.0;
300  int ra, ga, ba;
301  int rb, gb, bb;
302 
303  ra=a.get_r();
304  ga=a.get_g();
305  ba=a.get_b();
306 
307  rb=b.get_r();
308  gb=b.get_g();
309  bb=b.get_b();
310 
311  b.set_r((rb*ra*amount/255.0)+rb*(1.0-amount));
312  b.set_g((gb*ga*amount/255.0)+gb*(1.0-amount));
313  b.set_b((bb*ba*amount/255.0)+bb*(1.0-amount));
314  return b;
315 }
316 
317 template <>
318 CairoColor
320 {
321  int ra, ga, ba, aa;
322  int rb, gb, bb, ab;
323  int rc, gc, bc, ac;
324 
325  ra=a.get_r();
326  ga=a.get_g();
327  ba=a.get_b();
328  aa=a.get_a();
329 
330  rb=b.get_r();
331  gb=b.get_g();
332  bb=b.get_b();
333  ab=b.get_a();
334 
335  const float alpha=amount*aa/255.0;
336  const float ahpla=1.0-alpha;
337 
338  if(alpha<COLOR_EPSILON)
339  return b;
340 
341  ac=ab;
342  if(ra==0)
343  rc=rb;
344  else
345  rc=rb*(alpha*255)/(ra) + ahpla*rb;
346 
347  if(ga==0)
348  gc=gb;
349  else
350  gc=gb*(alpha*255)/(ga) + ahpla*gb;
351 
352  if(ba==0)
353  bc=bb;
354  else
355  bc=bb*(alpha*255)/(ba) + ahpla*bb;
356 
357  return CairoColor(rc, gc, bc, ac);
358 }
359 
360 template <>
361 CairoColor
362 blendfunc_COLOR(CairoColor &a, CairoColor &b, float amount)
363 {
364  return CairoColor(Color::blend(Color(a), Color(b), amount, Color::BLEND_COLOR));
365 }
366 
367 template <>
368 CairoColor
369 blendfunc_HUE(CairoColor &a, CairoColor &b, float amount)
370 {
371  return CairoColor(Color::blend(Color(a), Color(b), amount, Color::BLEND_HUE));
372 }
373 
374 template <>
375 CairoColor
377 {
378  return CairoColor(Color::blend(Color(a), Color(b), amount, Color::BLEND_SATURATION));
379 }
380 
381 template <>
382 CairoColor
384 {
385  return CairoColor(Color::blend(Color(a), Color(b), amount, Color::BLEND_LUMINANCE));
386 }
387 
388 template <>
389 CairoColor
391 {
392  a.set_a(a.get_a()*amount);
393  return CairoColor::blend(b, a, 1.0, Color::BLEND_COMPOSITE);
394 }
395 
396 template <>
397 CairoColor
399 {
400  // \todo can this be right, multiplying amount by *b*'s alpha?
401  // compare with blendfunc_BRIGHTEN where it is multiplied by *a*'s
402  //if(a.get_a() < b.get_a()*amount)
403  // return a.set_a(a.get_a()*amount);
404  //return b;
405  unsigned char ra, ga, ba, aa;
406  unsigned char ab;
407  unsigned char rc, gc, bc, ac;
408 
409  ra=a.get_r();
410  ga=a.get_g();
411  ba=a.get_b();
412  aa=a.get_a();
413 
414  ab=b.get_a();
415 
416  ac=aa*amount;
417  if(aa < ab*amount)
418  {
419  float acaa=(aa*amount)/aa;
420  rc=ra*acaa;
421  gc=ga*acaa;
422  bc=ba*acaa;
423  return CairoColor(rc, gc, bc, ac);
424  }
425  else
426  return b;
427 }
428 
429 template <>
430 CairoColor
432 {
433  unsigned char ra, ga, ba, aa;
434  unsigned char ab;
435  unsigned char rc, gc, bc, ac;
436 
437  ra=a.get_r();
438  ga=a.get_g();
439  ba=a.get_b();
440  aa=a.get_a();
441 
442  ab=b.get_a();
443 
444  ac=aa*amount;
445  if(ac > ab)
446  {
447  float acaa=(aa*amount)/aa;
448  rc=ra*acaa;
449  gc=ga*acaa;
450  bc=ba*acaa;
451  return CairoColor(rc, gc, bc, ac);
452  }
453  else
454  return b;
455 }
456 
457 template <>
458 CairoColor
460 {
461  if(amount<0) a=~a, amount=-amount;
462 
463  a.set_r(255-(255-a.get_r())*(1.0-b.get_r()/255.0));
464  a.set_g(255-(255-a.get_g())*(1.0-b.get_g()/255.0));
465  a.set_b(255-(255-a.get_b())*(1.0-b.get_b()/255.0));
466 
467  return blendfunc_ONTO(a,b,amount);
468 }
469 
470 template <>
471 CairoColor
473 {
474  if(amount<0) a=~a, amount=-amount;
475 
476  int ra, ga, ba, aa, ras, gas, bas;
477  int rb, gb, bb, ab;
478 
479  ra=a.get_r();
480  ras=ra*ra;
481  ga=a.get_g();
482  gas=ga*ga;
483  ba=a.get_b();
484  bas=ba*ba;
485  aa=a.get_a();
486 
487  rb=b.get_r();
488  gb=b.get_g();
489  bb=b.get_b();
490  ab=b.get_a();
491 
492 
493  int rc, gc, bc, ac;
494 
495  if(aa==0 || ab==0) return CairoColor();
496 
497  rc=(2*rb*ra+ras-2*rb*ras/255.0)/255.0;
498  gc=(2*gb*ga+gas-2*gb*gas/255.0)/255.0;
499  bc=(2*bb*ba+bas-2*bb*bas/255.0)/255.0;
500  ac=aa;
501 
502  return CairoColor::blend(CairoColor(rc, gc, bc, ac), b, amount, Color::BLEND_ONTO);
503 }
504 
505 template <>
506 CairoColor
508 {
509  if(amount<0) a=~a, amount=-amount;
510 
511  int ra, ga, ba, aa;
512  int rb, gb, bb;
513  int rc, gc, bc;
514 
515  ra=a.get_r();
516  ga=a.get_g();
517  ba=a.get_b();
518  aa=a.get_a();
519 
520  rb=b.get_r();
521  gb=b.get_g();
522  bb=b.get_b();
523 
524  if(ra>127) rc =255 - (255-(ra*2-255)) * (255-rb)/255.0;
525  else rc= rb*(ra*2)/255.0;
526  if(ga>127) gc =255 - (255-(ga*2-255)) * (255-gb)/255.0;
527  else gc= gb*(ga*2)/255.0;
528  if(ba>127) bc =255 - (255-(ba*2-255)) * (255-bb)/255.0;
529  else bc= bb*(ba*2)/255.0;
530 
531  return CairoColor::blend(CairoColor(rc, gc, bc, aa),b,amount, Color::BLEND_ONTO);
532 //
533 // if(a.get_r()>half) a.set_r(one-(one-(a.get_r()*2*one-one))*(one-b.get_r()));
534 // else a.set_r(b.get_r()*(a.get_r()*2*one));
535 // if(a.get_g()>half) a.set_g(one-(one-(a.get_g()*2*one-one))*(one-b.get_g()));
536 // else a.set_g(b.get_g()*(a.get_g()*2*one));
537 // if(a.get_b()>half) a.set_b(one-(one-(a.get_b()*2*one-one))*(one-b.get_b()));
538 // else a.set_b(b.get_b()*(a.get_b()*2*one));
539 //
540 // return blendfunc_ONTO(a,b,amount);
541 }
542 
543 template <>
544 CairoColor
546 {
547  CairoColor rm(b);
548 
549  //multiply the inverse alpha channel with the one below us
550  rm.set_a((255-a.get_a())*b.get_a()/255.0);
551 
552  return CairoColor::blend(rm,b,amount, Color::BLEND_STRAIGHT);
553 }
554 
555 
556 } // synfig namespace
557 
558 
559 #endif // __SYNFIG_COLOR_CAIROCOLORBLENDINGFUNCTIONS_H
560