Anti-Grain Geometry Tutorial
agg_pixfmt_rgba.h
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // Adaptation for high precision colors has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
18 //
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
21 //
22 //----------------------------------------------------------------------------
23 
24 #ifndef AGG_PIXFMT_RGBA_INCLUDED
25 #define AGG_PIXFMT_RGBA_INCLUDED
26 
27 #include <cstring>
28 #include <cmath>
29 #include "agg_pixfmt_base.h"
30 #include "agg_rendering_buffer.h"
31 
32 namespace agg
33 {
34  template<class T> inline T sd_min(T a, T b) { return (a < b) ? a : b; }
35  template<class T> inline T sd_max(T a, T b) { return (a > b) ? a : b; }
36 
37  inline rgba & clip(rgba & c)
38  {
39  if (c.a > 1) c.a = 1; else if (c.a < 0) c.a = 0;
40  if (c.r > c.a) c.r = c.a; else if (c.r < 0) c.r = 0;
41  if (c.g > c.a) c.g = c.a; else if (c.g < 0) c.g = 0;
42  if (c.b > c.a) c.b = c.a; else if (c.b < 0) c.b = 0;
43  return c;
44  }
45 
46  //=========================================================multiplier_rgba
47  template<class ColorT, class Order>
49  {
50  typedef ColorT color_type;
51  typedef typename color_type::value_type value_type;
52 
53  //--------------------------------------------------------------------
54  static AGG_INLINE void premultiply(value_type* p)
55  {
56  value_type a = p[Order::A];
57  p[Order::R] = color_type::multiply(p[Order::R], a);
58  p[Order::G] = color_type::multiply(p[Order::G], a);
59  p[Order::B] = color_type::multiply(p[Order::B], a);
60  }
61 
62 
63  //--------------------------------------------------------------------
64  static AGG_INLINE void demultiply(value_type* p)
65  {
66  value_type a = p[Order::A];
67  p[Order::R] = color_type::demultiply(p[Order::R], a);
68  p[Order::G] = color_type::demultiply(p[Order::G], a);
69  p[Order::B] = color_type::demultiply(p[Order::B], a);
70  }
71  };
72 
73  //=====================================================apply_gamma_dir_rgba
74  template<class ColorT, class Order, class GammaLut>
76  {
77  public:
78  typedef ColorT color_type;
79  typedef typename color_type::value_type value_type;
80 
81  apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
82 
83  AGG_INLINE void operator () (value_type* p)
84  {
85  p[Order::R] = m_gamma.dir(p[Order::R]);
86  p[Order::G] = m_gamma.dir(p[Order::G]);
87  p[Order::B] = m_gamma.dir(p[Order::B]);
88  }
89 
90  private:
91  const GammaLut& m_gamma;
92  };
93 
94  //=====================================================apply_gamma_inv_rgba
95  template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba
96  {
97  public:
98  typedef ColorT color_type;
99  typedef typename color_type::value_type value_type;
100 
101  apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
102 
103  AGG_INLINE void operator () (value_type* p)
104  {
105  p[Order::R] = m_gamma.inv(p[Order::R]);
106  p[Order::G] = m_gamma.inv(p[Order::G]);
107  p[Order::B] = m_gamma.inv(p[Order::B]);
108  }
109 
110  private:
111  const GammaLut& m_gamma;
112  };
113 
114 
115  template<class ColorT, class Order>
117  {
118  typedef ColorT color_type;
119  typedef Order order_type;
120  typedef typename color_type::value_type value_type;
121 
122  //--------------------------------------------------------------------
123  static AGG_INLINE void set_plain_color(value_type* p, color_type c)
124  {
125  c.premultiply();
126  p[Order::R] = c.r;
127  p[Order::G] = c.g;
128  p[Order::B] = c.b;
129  p[Order::A] = c.a;
130  }
131 
132  //--------------------------------------------------------------------
133  static AGG_INLINE color_type get_plain_color(const value_type* p)
134  {
135  return color_type(
136  p[Order::R],
137  p[Order::G],
138  p[Order::B],
139  p[Order::A]).demultiply();
140  }
141  };
142 
143  template<class ColorT, class Order>
145  {
146  typedef ColorT color_type;
147  typedef Order order_type;
148  typedef typename color_type::value_type value_type;
149 
150  //--------------------------------------------------------------------
151  static AGG_INLINE void set_plain_color(value_type* p, color_type c)
152  {
153  p[Order::R] = c.r;
154  p[Order::G] = c.g;
155  p[Order::B] = c.b;
156  p[Order::A] = c.a;
157  }
158 
159  //--------------------------------------------------------------------
160  static AGG_INLINE color_type get_plain_color(const value_type* p)
161  {
162  return color_type(
163  p[Order::R],
164  p[Order::G],
165  p[Order::B],
166  p[Order::A]);
167  }
168  };
169 
170  //=============================================================blender_rgba
171  // Blends "plain" (i.e. non-premultiplied) colors into a premultiplied buffer.
172  template<class ColorT, class Order>
173  struct blender_rgba : conv_rgba_pre<ColorT, Order>
174  {
175  typedef ColorT color_type;
176  typedef Order order_type;
177  typedef typename color_type::value_type value_type;
178  typedef typename color_type::calc_type calc_type;
179  typedef typename color_type::long_type long_type;
180 
181  // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
182  // compositing function. Since the render buffer is in fact premultiplied
183  // we omit the initial premultiplication and final demultiplication.
184 
185  //--------------------------------------------------------------------
186  static AGG_INLINE void blend_pix(value_type* p,
187  value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
188  {
189  blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
190  }
191 
192  //--------------------------------------------------------------------
193  static AGG_INLINE void blend_pix(value_type* p,
194  value_type cr, value_type cg, value_type cb, value_type alpha)
195  {
196  p[Order::R] = color_type::lerp(p[Order::R], cr, alpha);
197  p[Order::G] = color_type::lerp(p[Order::G], cg, alpha);
198  p[Order::B] = color_type::lerp(p[Order::B], cb, alpha);
199  p[Order::A] = color_type::prelerp(p[Order::A], alpha, alpha);
200  }
201  };
202 
203 
204  //========================================================blender_rgba_pre
205  // Blends premultiplied colors into a premultiplied buffer.
206  template<class ColorT, class Order>
207  struct blender_rgba_pre : conv_rgba_pre<ColorT, Order>
208  {
209  typedef ColorT color_type;
210  typedef Order order_type;
211  typedef typename color_type::value_type value_type;
212  typedef typename color_type::calc_type calc_type;
213  typedef typename color_type::long_type long_type;
214 
215  // Blend pixels using the premultiplied form of Alvy-Ray Smith's
216  // compositing function.
217 
218  //--------------------------------------------------------------------
219  static AGG_INLINE void blend_pix(value_type* p,
220  value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
221  {
222  blend_pix(p,
223  color_type::mult_cover(cr, cover),
224  color_type::mult_cover(cg, cover),
225  color_type::mult_cover(cb, cover),
226  color_type::mult_cover(alpha, cover));
227  }
228 
229  //--------------------------------------------------------------------
230  static AGG_INLINE void blend_pix(value_type* p,
231  value_type cr, value_type cg, value_type cb, value_type alpha)
232  {
233  p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha);
234  p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha);
235  p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha);
236  p[Order::A] = color_type::prelerp(p[Order::A], alpha, alpha);
237  }
238  };
239 
240  //======================================================blender_rgba_plain
241  // Blends "plain" (non-premultiplied) colors into a plain (non-premultiplied) buffer.
242  template<class ColorT, class Order>
243  struct blender_rgba_plain : conv_rgba_plain<ColorT, Order>
244  {
245  typedef ColorT color_type;
246  typedef Order order_type;
247  typedef typename color_type::value_type value_type;
248  typedef typename color_type::calc_type calc_type;
249  typedef typename color_type::long_type long_type;
250 
251  // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
252  // compositing function.
253 
254  //--------------------------------------------------------------------
255  static AGG_INLINE void blend_pix(value_type* p,
256  value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
257  {
258  blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
259  }
260 
261  //--------------------------------------------------------------------
262  static AGG_INLINE void blend_pix(value_type* p,
263  value_type cr, value_type cg, value_type cb, value_type alpha)
264  {
265  if (alpha > color_type::empty_value())
266  {
267  calc_type a = p[Order::A];
268  calc_type r = color_type::multiply(p[Order::R], a);
269  calc_type g = color_type::multiply(p[Order::G], a);
270  calc_type b = color_type::multiply(p[Order::B], a);
271  p[Order::R] = color_type::lerp(r, cr, alpha);
272  p[Order::G] = color_type::lerp(g, cg, alpha);
273  p[Order::B] = color_type::lerp(b, cb, alpha);
274  p[Order::A] = color_type::prelerp(a, alpha, alpha);
276  }
277  }
278  };
279 
280  // SVG compositing operations.
281  // For specifications, see http://www.w3.org/TR/SVGCompositing/
282 
283  //=========================================================comp_op_rgba_clear
284  template<class ColorT, class Order>
285  struct comp_op_rgba_clear : blender_base<ColorT, Order>
286  {
287  typedef ColorT color_type;
288  typedef typename color_type::value_type value_type;
291 
292  // Dca' = 0
293  // Da' = 0
294  static AGG_INLINE void blend_pix(value_type* p,
295  value_type, value_type, value_type, value_type, cover_type cover)
296  {
297  if (cover >= cover_full)
298  {
299  p[0] = p[1] = p[2] = p[3] = color_type::empty_value();
300  }
301  else if (cover > cover_none)
302  {
303  set(p, get(p, cover_full - cover));
304  }
305  }
306  };
307 
308  //===========================================================comp_op_rgba_src
309  template<class ColorT, class Order>
310  struct comp_op_rgba_src : blender_base<ColorT, Order>
311  {
312  typedef ColorT color_type;
313  typedef typename color_type::value_type value_type;
316 
317  // Dca' = Sca
318  // Da' = Sa
319  static AGG_INLINE void blend_pix(value_type* p,
320  value_type r, value_type g, value_type b, value_type a, cover_type cover)
321  {
322  if (cover >= cover_full)
323  {
324  set(p, r, g, b, a);
325  }
326  else
327  {
328  rgba s = get(r, g, b, a, cover);
329  rgba d = get(p, cover_full - cover);
330  d.r += s.r;
331  d.g += s.g;
332  d.b += s.b;
333  d.a += s.a;
334  set(p, d);
335  }
336  }
337  };
338 
339  //===========================================================comp_op_rgba_dst
340  template<class ColorT, class Order>
341  struct comp_op_rgba_dst : blender_base<ColorT, Order>
342  {
343  typedef ColorT color_type;
344  typedef typename color_type::value_type value_type;
345 
346  // Dca' = Dca.Sa + Dca.(1 - Sa) = Dca
347  // Da' = Da.Sa + Da.(1 - Sa) = Da
348  static AGG_INLINE void blend_pix(value_type*,
349  value_type, value_type, value_type, value_type, cover_type)
350  {
351  // Well, that was easy!
352  }
353  };
354 
355  //======================================================comp_op_rgba_src_over
356  template<class ColorT, class Order>
357  struct comp_op_rgba_src_over : blender_base<ColorT, Order>
358  {
359  typedef ColorT color_type;
360  typedef typename color_type::value_type value_type;
363 
364  // Dca' = Sca + Dca.(1 - Sa) = Dca + Sca - Dca.Sa
365  // Da' = Sa + Da - Sa.Da
366  static AGG_INLINE void blend_pix(value_type* p,
367  value_type r, value_type g, value_type b, value_type a, cover_type cover)
368  {
369 #if 1
370  blender_rgba_pre<ColorT, Order>::blend_pix(p, r, g, b, a, cover);
371 #else
372  rgba s = get(r, g, b, a, cover);
373  rgba d = get(p);
374  d.r += s.r - d.r * s.a;
375  d.g += s.g - d.g * s.a;
376  d.b += s.b - d.b * s.a;
377  d.a += s.a - d.a * s.a;
378  set(p, d);
379 #endif
380  }
381  };
382 
383  //======================================================comp_op_rgba_dst_over
384  template<class ColorT, class Order>
385  struct comp_op_rgba_dst_over : blender_base<ColorT, Order>
386  {
387  typedef ColorT color_type;
388  typedef typename color_type::value_type value_type;
391 
392  // Dca' = Dca + Sca.(1 - Da)
393  // Da' = Sa + Da - Sa.Da = Da + Sa.(1 - Da)
394  static AGG_INLINE void blend_pix(value_type* p,
395  value_type r, value_type g, value_type b, value_type a, cover_type cover)
396  {
397  rgba s = get(r, g, b, a, cover);
398  rgba d = get(p);
399  double d1a = 1 - d.a;
400  d.r += s.r * d1a;
401  d.g += s.g * d1a;
402  d.b += s.b * d1a;
403  d.a += s.a * d1a;
404  set(p, d);
405  }
406  };
407 
408  //======================================================comp_op_rgba_src_in
409  template<class ColorT, class Order>
410  struct comp_op_rgba_src_in : blender_base<ColorT, Order>
411  {
412  typedef ColorT color_type;
413  typedef typename color_type::value_type value_type;
416 
417  // Dca' = Sca.Da
418  // Da' = Sa.Da
419  static AGG_INLINE void blend_pix(value_type* p,
420  value_type r, value_type g, value_type b, value_type a, cover_type cover)
421  {
422  double da = ColorT::to_double(p[Order::A]);
423  if (da > 0)
424  {
425  rgba s = get(r, g, b, a, cover);
426  rgba d = get(p, cover_full - cover);
427  d.r += s.r * da;
428  d.g += s.g * da;
429  d.b += s.b * da;
430  d.a += s.a * da;
431  set(p, d);
432  }
433  }
434  };
435 
436  //======================================================comp_op_rgba_dst_in
437  template<class ColorT, class Order>
438  struct comp_op_rgba_dst_in : blender_base<ColorT, Order>
439  {
440  typedef ColorT color_type;
441  typedef typename color_type::value_type value_type;
444 
445  // Dca' = Dca.Sa
446  // Da' = Sa.Da
447  static AGG_INLINE void blend_pix(value_type* p,
448  value_type, value_type, value_type, value_type a, cover_type cover)
449  {
450  double sa = ColorT::to_double(a);
451  rgba d = get(p, cover_full - cover);
452  rgba d2 = get(p, cover);
453  d.r += d2.r * sa;
454  d.g += d2.g * sa;
455  d.b += d2.b * sa;
456  d.a += d2.a * sa;
457  set(p, d);
458  }
459  };
460 
461  //======================================================comp_op_rgba_src_out
462  template<class ColorT, class Order>
463  struct comp_op_rgba_src_out : blender_base<ColorT, Order>
464  {
465  typedef ColorT color_type;
466  typedef typename color_type::value_type value_type;
469 
470  // Dca' = Sca.(1 - Da)
471  // Da' = Sa.(1 - Da)
472  static AGG_INLINE void blend_pix(value_type* p,
473  value_type r, value_type g, value_type b, value_type a, cover_type cover)
474  {
475  rgba s = get(r, g, b, a, cover);
476  rgba d = get(p, cover_full - cover);
477  double d1a = 1 - ColorT::to_double(p[Order::A]);
478  d.r += s.r * d1a;
479  d.g += s.g * d1a;
480  d.b += s.b * d1a;
481  d.a += s.a * d1a;
482  set(p, d);
483  }
484  };
485 
486  //======================================================comp_op_rgba_dst_out
487  template<class ColorT, class Order>
488  struct comp_op_rgba_dst_out : blender_base<ColorT, Order>
489  {
490  typedef ColorT color_type;
491  typedef typename color_type::value_type value_type;
494 
495  // Dca' = Dca.(1 - Sa)
496  // Da' = Da.(1 - Sa)
497  static AGG_INLINE void blend_pix(value_type* p,
498  value_type, value_type, value_type, value_type a, cover_type cover)
499  {
500  rgba d = get(p, cover_full - cover);
501  rgba dc = get(p, cover);
502  double s1a = 1 - ColorT::to_double(a);
503  d.r += dc.r * s1a;
504  d.g += dc.g * s1a;
505  d.b += dc.b * s1a;
506  d.a += dc.a * s1a;
507  set(p, d);
508  }
509  };
510 
511  //=====================================================comp_op_rgba_src_atop
512  template<class ColorT, class Order>
513  struct comp_op_rgba_src_atop : blender_base<ColorT, Order>
514  {
515  typedef ColorT color_type;
516  typedef typename color_type::value_type value_type;
519 
520  // Dca' = Sca.Da + Dca.(1 - Sa)
521  // Da' = Da
522  static AGG_INLINE void blend_pix(value_type* p,
523  value_type r, value_type g, value_type b, value_type a, cover_type cover)
524  {
525  rgba s = get(r, g, b, a, cover);
526  rgba d = get(p);
527  double s1a = 1 - s.a;
528  d.r = s.r * d.a + d.r * s1a;
529  d.g = s.g * d.a + d.g * s1a;
530  d.b = s.b * d.a + d.g * s1a;
531  set(p, d);
532  }
533  };
534 
535  //=====================================================comp_op_rgba_dst_atop
536  template<class ColorT, class Order>
537  struct comp_op_rgba_dst_atop : blender_base<ColorT, Order>
538  {
539  typedef ColorT color_type;
540  typedef typename color_type::value_type value_type;
543 
544  // Dca' = Dca.Sa + Sca.(1 - Da)
545  // Da' = Sa
546  static AGG_INLINE void blend_pix(value_type* p,
547  value_type r, value_type g, value_type b, value_type a, cover_type cover)
548  {
549  rgba sc = get(r, g, b, a, cover);
550  rgba dc = get(p, cover);
551  rgba d = get(p, cover_full - cover);
552  double sa = ColorT::to_double(a);
553  double d1a = 1 - ColorT::to_double(p[Order::A]);
554  d.r += dc.r * sa + sc.r * d1a;
555  d.g += dc.g * sa + sc.g * d1a;
556  d.b += dc.b * sa + sc.b * d1a;
557  d.a += sc.a;
558  set(p, d);
559  }
560  };
561 
562  //=========================================================comp_op_rgba_xor
563  template<class ColorT, class Order>
564  struct comp_op_rgba_xor : blender_base<ColorT, Order>
565  {
566  typedef ColorT color_type;
567  typedef typename color_type::value_type value_type;
570 
571  // Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
572  // Da' = Sa + Da - 2.Sa.Da
573  static AGG_INLINE void blend_pix(value_type* p,
574  value_type r, value_type g, value_type b, value_type a, cover_type cover)
575  {
576  rgba s = get(r, g, b, a, cover);
577  rgba d = get(p);
578  double s1a = 1 - s.a;
579  double d1a = 1 - ColorT::to_double(p[Order::A]);
580  d.r = s.r * d1a + d.r * s1a;
581  d.g = s.g * d1a + d.g * s1a;
582  d.b = s.b * d1a + d.b * s1a;
583  d.a = s.a + d.a - 2 * s.a * d.a;
584  set(p, d);
585  }
586  };
587 
588  //=========================================================comp_op_rgba_plus
589  template<class ColorT, class Order>
590  struct comp_op_rgba_plus : blender_base<ColorT, Order>
591  {
592  typedef ColorT color_type;
593  typedef typename color_type::value_type value_type;
596 
597  // Dca' = Sca + Dca
598  // Da' = Sa + Da
599  static AGG_INLINE void blend_pix(value_type* p,
600  value_type r, value_type g, value_type b, value_type a, cover_type cover)
601  {
602  rgba s = get(r, g, b, a, cover);
603  if (s.a > 0)
604  {
605  rgba d = get(p);
606  d.a = sd_min(d.a + s.a, 1.0);
607  d.r = sd_min(d.r + s.r, d.a);
608  d.g = sd_min(d.g + s.g, d.a);
609  d.b = sd_min(d.b + s.b, d.a);
610  set(p, clip(d));
611  }
612  }
613  };
614 
615  //========================================================comp_op_rgba_minus
616  // Note: not included in SVG spec.
617  template<class ColorT, class Order>
618  struct comp_op_rgba_minus : blender_base<ColorT, Order>
619  {
620  typedef ColorT color_type;
621  typedef typename color_type::value_type value_type;
624 
625  // Dca' = Dca - Sca
626  // Da' = 1 - (1 - Sa).(1 - Da) = Da + Sa - Sa.Da
627  static AGG_INLINE void blend_pix(value_type* p,
628  value_type r, value_type g, value_type b, value_type a, cover_type cover)
629  {
630  rgba s = get(r, g, b, a, cover);
631  if (s.a > 0)
632  {
633  rgba d = get(p);
634  d.a += s.a - s.a * d.a;
635  d.r = sd_max(d.r - s.r, 0.0);
636  d.g = sd_max(d.g - s.g, 0.0);
637  d.b = sd_max(d.b - s.b, 0.0);
638  set(p, clip(d));
639  }
640  }
641  };
642 
643  //=====================================================comp_op_rgba_multiply
644  template<class ColorT, class Order>
645  struct comp_op_rgba_multiply : blender_base<ColorT, Order>
646  {
647  typedef ColorT color_type;
648  typedef typename color_type::value_type value_type;
651 
652  // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
653  // Da' = Sa + Da - Sa.Da
654  static AGG_INLINE void blend_pix(value_type* p,
655  value_type r, value_type g, value_type b, value_type a, cover_type cover)
656  {
657  rgba s = get(r, g, b, a, cover);
658  if (s.a > 0)
659  {
660  rgba d = get(p);
661  double s1a = 1 - s.a;
662  double d1a = 1 - d.a;
663  d.r = s.r * d.r + s.r * d1a + d.r * s1a;
664  d.g = s.g * d.g + s.g * d1a + d.g * s1a;
665  d.b = s.b * d.b + s.b * d1a + d.b * s1a;
666  d.a += s.a - s.a * d.a;
667  set(p, clip(d));
668  }
669  }
670  };
671 
672  //=====================================================comp_op_rgba_screen
673  template<class ColorT, class Order>
674  struct comp_op_rgba_screen : blender_base<ColorT, Order>
675  {
676  typedef ColorT color_type;
677  typedef typename color_type::value_type value_type;
680 
681  // Dca' = Sca + Dca - Sca.Dca
682  // Da' = Sa + Da - Sa.Da
683  static AGG_INLINE void blend_pix(value_type* p,
684  value_type r, value_type g, value_type b, value_type a, cover_type cover)
685  {
686  rgba s = get(r, g, b, a, cover);
687  if (s.a > 0)
688  {
689  rgba d = get(p);
690  d.r += s.r - s.r * d.r;
691  d.g += s.g - s.g * d.g;
692  d.b += s.b - s.b * d.b;
693  d.a += s.a - s.a * d.a;
694  set(p, clip(d));
695  }
696  }
697  };
698 
699  //=====================================================comp_op_rgba_overlay
700  template<class ColorT, class Order>
701  struct comp_op_rgba_overlay : blender_base<ColorT, Order>
702  {
703  typedef ColorT color_type;
704  typedef typename color_type::value_type value_type;
707 
708  // if 2.Dca <= Da
709  // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
710  // otherwise
711  // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
712  //
713  // Da' = Sa + Da - Sa.Da
714  static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a)
715  {
716  return (2 * dca <= da) ?
717  2 * sca * dca + sca * d1a + dca * s1a :
718  sada - 2 * (da - dca) * (sa - sca) + sca * d1a + dca * s1a;
719  }
720 
721  static AGG_INLINE void blend_pix(value_type* p,
722  value_type r, value_type g, value_type b, value_type a, cover_type cover)
723  {
724  rgba s = get(r, g, b, a, cover);
725  if (s.a > 0)
726  {
727  rgba d = get(p);
728  double d1a = 1 - d.a;
729  double s1a = 1 - s.a;
730  double sada = s.a * d.a;
731  d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a);
732  d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a);
733  d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a);
734  d.a += s.a - s.a * d.a;
735  set(p, clip(d));
736  }
737  }
738  };
739 
740  //=====================================================comp_op_rgba_darken
741  template<class ColorT, class Order>
742  struct comp_op_rgba_darken : blender_base<ColorT, Order>
743  {
744  typedef ColorT color_type;
745  typedef typename color_type::value_type value_type;
748 
749  // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
750  // Da' = Sa + Da - Sa.Da
751  static AGG_INLINE void blend_pix(value_type* p,
752  value_type r, value_type g, value_type b, value_type a, cover_type cover)
753  {
754  rgba s = get(r, g, b, a, cover);
755  if (s.a > 0)
756  {
757  rgba d = get(p);
758  double d1a = 1 - d.a;
759  double s1a = 1 - s.a;
760  d.r = sd_min(s.r * d.a, d.r * s.a) + s.r * d1a + d.r * s1a;
761  d.g = sd_min(s.g * d.a, d.g * s.a) + s.g * d1a + d.g * s1a;
762  d.b = sd_min(s.b * d.a, d.b * s.a) + s.b * d1a + d.b * s1a;
763  d.a += s.a - s.a * d.a;
764  set(p, clip(d));
765  }
766  }
767  };
768 
769  //=====================================================comp_op_rgba_lighten
770  template<class ColorT, class Order>
771  struct comp_op_rgba_lighten : blender_base<ColorT, Order>
772  {
773  typedef ColorT color_type;
774  typedef typename color_type::value_type value_type;
777 
778  // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
779  // Da' = Sa + Da - Sa.Da
780  static AGG_INLINE void blend_pix(value_type* p,
781  value_type r, value_type g, value_type b, value_type a, cover_type cover)
782  {
783  rgba s = get(r, g, b, a, cover);
784  if (s.a > 0)
785  {
786  rgba d = get(p);
787  double d1a = 1 - d.a;
788  double s1a = 1 - s.a;
789  d.r = sd_max(s.r * d.a, d.r * s.a) + s.r * d1a + d.r * s1a;
790  d.g = sd_max(s.g * d.a, d.g * s.a) + s.g * d1a + d.g * s1a;
791  d.b = sd_max(s.b * d.a, d.b * s.a) + s.b * d1a + d.b * s1a;
792  d.a += s.a - s.a * d.a;
793  set(p, clip(d));
794  }
795  }
796  };
797 
798  //=====================================================comp_op_rgba_color_dodge
799  template<class ColorT, class Order>
800  struct comp_op_rgba_color_dodge : blender_base<ColorT, Order>
801  {
802  typedef ColorT color_type;
803  typedef typename color_type::value_type value_type;
806 
807  // if Sca == Sa and Dca == 0
808  // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) = Sca.(1 - Da)
809  // otherwise if Sca == Sa
810  // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
811  // otherwise if Sca < Sa
812  // Dca' = Sa.Da.min(1, Dca/Da.Sa/(Sa - Sca)) + Sca.(1 - Da) + Dca.(1 - Sa)
813  //
814  // Da' = Sa + Da - Sa.Da
815  static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a)
816  {
817  if (sca < sa) return sada * sd_min(1.0, (dca / da) * sa / (sa - sca)) + sca * d1a + dca * s1a;
818  if (dca > 0) return sada + sca * d1a + dca * s1a;
819  return sca * d1a;
820  }
821 
822  static AGG_INLINE void blend_pix(value_type* p,
823  value_type r, value_type g, value_type b, value_type a, cover_type cover)
824  {
825  rgba s = get(r, g, b, a, cover);
826  if (s.a > 0)
827  {
828  rgba d = get(p);
829  if (d.a > 0)
830  {
831  double sada = s.a * d.a;
832  double s1a = 1 - s.a;
833  double d1a = 1 - d.a;
834  d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a);
835  d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a);
836  d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a);
837  d.a += s.a - s.a * d.a;
838  set(p, clip(d));
839  }
840  else set(p, s);
841  }
842  }
843  };
844 
845  //=====================================================comp_op_rgba_color_burn
846  template<class ColorT, class Order>
847  struct comp_op_rgba_color_burn : blender_base<ColorT, Order>
848  {
849  typedef ColorT color_type;
850  typedef typename color_type::value_type value_type;
853 
854  // if Sca == 0 and Dca == Da
855  // Dca' = Sa.Da + Dca.(1 - Sa)
856  // otherwise if Sca == 0
857  // Dca' = Dca.(1 - Sa)
858  // otherwise if Sca > 0
859  // Dca' = Sa.Da.(1 - min(1, (1 - Dca/Da).Sa/Sca)) + Sca.(1 - Da) + Dca.(1 - Sa)
860  static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a)
861  {
862  if (sca > 0) return sada * (1 - sd_min(1.0, (1 - dca / da) * sa / sca)) + sca * d1a + dca * s1a;
863  if (dca > da) return sada + dca * s1a;
864  return dca * s1a;
865  }
866 
867  static AGG_INLINE void blend_pix(value_type* p,
868  value_type r, value_type g, value_type b, value_type a, cover_type cover)
869  {
870  rgba s = get(r, g, b, a, cover);
871  if (s.a > 0)
872  {
873  rgba d = get(p);
874  if (d.a > 0)
875  {
876  double sada = s.a * d.a;
877  double s1a = 1 - s.a;
878  double d1a = 1 - d.a;
879  d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a);
880  d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a);
881  d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a);
882  d.a += s.a - sada;
883  set(p, clip(d));
884  }
885  else set(p, s);
886  }
887  }
888  };
889 
890  //=====================================================comp_op_rgba_hard_light
891  template<class ColorT, class Order>
892  struct comp_op_rgba_hard_light : blender_base<ColorT, Order>
893  {
894  typedef ColorT color_type;
895  typedef typename color_type::value_type value_type;
898 
899  // if 2.Sca < Sa
900  // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
901  // otherwise
902  // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
903  //
904  // Da' = Sa + Da - Sa.Da
905  static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a)
906  {
907  return (2 * sca < sa) ?
908  2 * sca * dca + sca * d1a + dca * s1a :
909  sada - 2 * (da - dca) * (sa - sca) + sca * d1a + dca * s1a;
910  }
911 
912  static AGG_INLINE void blend_pix(value_type* p,
913  value_type r, value_type g, value_type b, value_type a, cover_type cover)
914  {
915  rgba s = get(r, g, b, a, cover);
916  if (s.a > 0)
917  {
918  rgba d = get(p);
919  double d1a = 1 - d.a;
920  double s1a = 1 - s.a;
921  double sada = s.a * d.a;
922  d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a);
923  d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a);
924  d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a);
925  d.a += s.a - sada;
926  set(p, clip(d));
927  }
928  }
929  };
930 
931  //=====================================================comp_op_rgba_soft_light
932  template<class ColorT, class Order>
933  struct comp_op_rgba_soft_light : blender_base<ColorT, Order>
934  {
935  typedef ColorT color_type;
936  typedef typename color_type::value_type value_type;
939 
940  // if 2.Sca <= Sa
941  // Dca' = Dca.Sa - (Sa.Da - 2.Sca.Da).Dca.Sa.(Sa.Da - Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
942  // otherwise if 2.Sca > Sa and 4.Dca <= Da
943  // Dca' = Dca.Sa + (2.Sca.Da - Sa.Da).((((16.Dsa.Sa - 12).Dsa.Sa + 4).Dsa.Da) - Dsa.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
944  // otherwise if 2.Sca > Sa and 4.Dca > Da
945  // Dca' = Dca.Sa + (2.Sca.Da - Sa.Da).((Dca.Sa)^0.5 - Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
946  //
947  // Da' = Sa + Da - Sa.Da
948  static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a)
949  {
950  double dcasa = dca * sa;
951  if (2 * sca <= sa) return dcasa - (sada - 2 * sca * da) * dcasa * (sada - dcasa) + sca * d1a + dca * s1a;
952  if (4 * dca <= da) return dcasa + (2 * sca * da - sada) * ((((16 * dcasa - 12) * dcasa + 4) * dca * da) - dca * da) + sca * d1a + dca * s1a;
953  return dcasa + (2 * sca * da - sada) * (std::sqrt(dcasa) - dcasa) + sca * d1a + dca * s1a;
954  }
955 
956  static AGG_INLINE void blend_pix(value_type* p,
957  value_type r, value_type g, value_type b, value_type a, cover_type cover)
958  {
959  rgba s = get(r, g, b, a, cover);
960  if (s.a > 0)
961  {
962  rgba d = get(p);
963  if (d.a > 0)
964  {
965  double sada = s.a * d.a;
966  double s1a = 1 - s.a;
967  double d1a = 1 - d.a;
968  d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a);
969  d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a);
970  d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a);
971  d.a += s.a - sada;
972  set(p, clip(d));
973  }
974  else set(p, s);
975  }
976  }
977  };
978 
979  //=====================================================comp_op_rgba_difference
980  template<class ColorT, class Order>
981  struct comp_op_rgba_difference : blender_base<ColorT, Order>
982  {
983  typedef ColorT color_type;
984  typedef typename color_type::value_type value_type;
987 
988  // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
989  // Da' = Sa + Da - Sa.Da
990  static AGG_INLINE void blend_pix(value_type* p,
991  value_type r, value_type g, value_type b, value_type a, cover_type cover)
992  {
993  rgba s = get(r, g, b, a, cover);
994  if (s.a > 0)
995  {
996  rgba d = get(p);
997  d.r += s.r - 2 * sd_min(s.r * d.a, d.r * s.a);
998  d.g += s.g - 2 * sd_min(s.g * d.a, d.g * s.a);
999  d.b += s.b - 2 * sd_min(s.b * d.a, d.b * s.a);
1000  d.a += s.a - s.a * d.a;
1001  set(p, clip(d));
1002  }
1003  }
1004  };
1005 
1006  //=====================================================comp_op_rgba_exclusion
1007  template<class ColorT, class Order>
1008  struct comp_op_rgba_exclusion : blender_base<ColorT, Order>
1009  {
1010  typedef ColorT color_type;
1011  typedef typename color_type::value_type value_type;
1014 
1015  // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
1016  // Da' = Sa + Da - Sa.Da
1017  static AGG_INLINE void blend_pix(value_type* p,
1018  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1019  {
1020  rgba s = get(r, g, b, a, cover);
1021  if (s.a > 0)
1022  {
1023  rgba d = get(p);
1024  double d1a = 1 - d.a;
1025  double s1a = 1 - s.a;
1026  d.r = (s.r * d.a + d.r * s.a - 2 * s.r * d.r) + s.r * d1a + d.r * s1a;
1027  d.g = (s.g * d.a + d.g * s.a - 2 * s.g * d.g) + s.g * d1a + d.g * s1a;
1028  d.b = (s.b * d.a + d.b * s.a - 2 * s.b * d.b) + s.b * d1a + d.b * s1a;
1029  d.a += s.a - s.a * d.a;
1030  set(p, clip(d));
1031  }
1032  }
1033  };
1034 
1035 #if 0
1036  //=====================================================comp_op_rgba_contrast
1037  template<class ColorT, class Order> struct comp_op_rgba_contrast
1038  {
1039  typedef ColorT color_type;
1040  typedef Order order_type;
1041  typedef typename color_type::value_type value_type;
1042  typedef typename color_type::calc_type calc_type;
1043  typedef typename color_type::long_type long_type;
1044  enum base_scale_e
1045  {
1046  base_shift = color_type::base_shift,
1047  base_mask = color_type::base_mask
1048  };
1049 
1050 
1051  static AGG_INLINE void blend_pix(value_type* p,
1052  unsigned sr, unsigned sg, unsigned sb,
1053  unsigned sa, unsigned cover)
1054  {
1055  if (cover < 255)
1056  {
1057  sr = (sr * cover + 255) >> 8;
1058  sg = (sg * cover + 255) >> 8;
1059  sb = (sb * cover + 255) >> 8;
1060  sa = (sa * cover + 255) >> 8;
1061  }
1062  long_type dr = p[Order::R];
1063  long_type dg = p[Order::G];
1064  long_type db = p[Order::B];
1065  int da = p[Order::A];
1066  long_type d2a = da >> 1;
1067  unsigned s2a = sa >> 1;
1068 
1069  int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a);
1070  int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a);
1071  int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a);
1072 
1073  r = (r < 0) ? 0 : r;
1074  g = (g < 0) ? 0 : g;
1075  b = (b < 0) ? 0 : b;
1076 
1077  p[Order::R] = (value_type)((r > da) ? da : r);
1078  p[Order::G] = (value_type)((g > da) ? da : g);
1079  p[Order::B] = (value_type)((b > da) ? da : b);
1080  }
1081  };
1082 
1083  //=====================================================comp_op_rgba_invert
1084  template<class ColorT, class Order> struct comp_op_rgba_invert
1085  {
1086  typedef ColorT color_type;
1087  typedef Order order_type;
1088  typedef typename color_type::value_type value_type;
1089  typedef typename color_type::calc_type calc_type;
1090  typedef typename color_type::long_type long_type;
1091  enum base_scale_e
1092  {
1093  base_shift = color_type::base_shift,
1094  base_mask = color_type::base_mask
1095  };
1096 
1097  // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa)
1098  // Da' = Sa + Da - Sa.Da
1099  static AGG_INLINE void blend_pix(value_type* p,
1100  unsigned sr, unsigned sg, unsigned sb,
1101  unsigned sa, unsigned cover)
1102  {
1103  sa = (sa * cover + 255) >> 8;
1104  if (sa)
1105  {
1106  calc_type da = p[Order::A];
1107  calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift;
1108  calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift;
1109  calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift;
1110  calc_type s1a = base_mask - sa;
1111  p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
1112  p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
1113  p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
1114  p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
1115  }
1116  }
1117  };
1118 
1119  //=================================================comp_op_rgba_invert_rgb
1120  template<class ColorT, class Order> struct comp_op_rgba_invert_rgb
1121  {
1122  typedef ColorT color_type;
1123  typedef Order order_type;
1124  typedef typename color_type::value_type value_type;
1125  typedef typename color_type::calc_type calc_type;
1126  typedef typename color_type::long_type long_type;
1127  enum base_scale_e
1128  {
1129  base_shift = color_type::base_shift,
1130  base_mask = color_type::base_mask
1131  };
1132 
1133  // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa)
1134  // Da' = Sa + Da - Sa.Da
1135  static AGG_INLINE void blend_pix(value_type* p,
1136  unsigned sr, unsigned sg, unsigned sb,
1137  unsigned sa, unsigned cover)
1138  {
1139  if (cover < 255)
1140  {
1141  sr = (sr * cover + 255) >> 8;
1142  sg = (sg * cover + 255) >> 8;
1143  sb = (sb * cover + 255) >> 8;
1144  sa = (sa * cover + 255) >> 8;
1145  }
1146  if (sa)
1147  {
1148  calc_type da = p[Order::A];
1149  calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift;
1150  calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift;
1151  calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift;
1152  calc_type s1a = base_mask - sa;
1153  p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
1154  p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
1155  p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
1156  p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
1157  }
1158  }
1159  };
1160 #endif
1161 
1162 
1163  //======================================================comp_op_table_rgba
1164  template<class ColorT, class Order> struct comp_op_table_rgba
1165  {
1166  typedef typename ColorT::value_type value_type;
1167  typedef typename ColorT::calc_type calc_type;
1168  typedef void (*comp_op_func_type)(value_type* p,
1169  value_type cr,
1170  value_type cg,
1171  value_type cb,
1172  value_type ca,
1173  cover_type cover);
1174  static comp_op_func_type g_comp_op_func[];
1175  };
1176 
1177  //==========================================================g_comp_op_func
1178  template<class ColorT, class Order>
1181  {
1195  //comp_op_rgba_minus <ColorT,Order>::blend_pix,
1207  //comp_op_rgba_contrast <ColorT,Order>::blend_pix,
1208  //comp_op_rgba_invert <ColorT,Order>::blend_pix,
1209  //comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix,
1210  0
1211  };
1212 
1213 
1214  //==============================================================comp_op_e
1215  enum comp_op_e
1216  {
1217  comp_op_clear, //----comp_op_clear
1218  comp_op_src, //----comp_op_src
1219  comp_op_dst, //----comp_op_dst
1220  comp_op_src_over, //----comp_op_src_over
1221  comp_op_dst_over, //----comp_op_dst_over
1222  comp_op_src_in, //----comp_op_src_in
1223  comp_op_dst_in, //----comp_op_dst_in
1224  comp_op_src_out, //----comp_op_src_out
1225  comp_op_dst_out, //----comp_op_dst_out
1226  comp_op_src_atop, //----comp_op_src_atop
1227  comp_op_dst_atop, //----comp_op_dst_atop
1228  comp_op_xor, //----comp_op_xor
1229  comp_op_plus, //----comp_op_plus
1230  //comp_op_minus, //----comp_op_minus
1231  comp_op_multiply, //----comp_op_multiply
1232  comp_op_screen, //----comp_op_screen
1233  comp_op_overlay, //----comp_op_overlay
1234  comp_op_darken, //----comp_op_darken
1235  comp_op_lighten, //----comp_op_lighten
1236  comp_op_color_dodge, //----comp_op_color_dodge
1237  comp_op_color_burn, //----comp_op_color_burn
1238  comp_op_hard_light, //----comp_op_hard_light
1239  comp_op_soft_light, //----comp_op_soft_light
1240  comp_op_difference, //----comp_op_difference
1241  comp_op_exclusion, //----comp_op_exclusion
1242  //comp_op_contrast, //----comp_op_contrast
1243  //comp_op_invert, //----comp_op_invert
1244  //comp_op_invert_rgb, //----comp_op_invert_rgb
1245 
1246  end_of_comp_op_e
1247  };
1248 
1249 
1250 
1251 
1252 
1253 
1254 
1255  //====================================================comp_op_adaptor_rgba
1256  template<class ColorT, class Order>
1258  {
1259  typedef ColorT color_type;
1260  typedef Order order_type;
1261  typedef typename color_type::value_type value_type;
1262  typedef typename color_type::calc_type calc_type;
1263  typedef typename color_type::long_type long_type;
1264 
1265  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1266  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1267  {
1268  comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p,
1269  color_type::multiply(r, a),
1270  color_type::multiply(g, a),
1271  color_type::multiply(b, a),
1272  a, cover);
1273  }
1274  };
1275 
1276  //=========================================comp_op_adaptor_clip_to_dst_rgba
1277  template<class ColorT, class Order>
1279  {
1280  typedef ColorT color_type;
1281  typedef Order order_type;
1282  typedef typename color_type::value_type value_type;
1283  typedef typename color_type::calc_type calc_type;
1284  typedef typename color_type::long_type long_type;
1285 
1286  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1287  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1288  {
1289  r = color_type::multiply(r, a);
1290  g = color_type::multiply(g, a);
1291  b = color_type::multiply(b, a);
1292  value_type da = p[Order::A];
1293  comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p,
1294  color_type::multiply(r, da),
1295  color_type::multiply(g, da),
1296  color_type::multiply(b, da),
1297  color_type::multiply(a, da), cover);
1298  }
1299  };
1300 
1301  //================================================comp_op_adaptor_rgba_pre
1302  template<class ColorT, class Order>
1304  {
1305  typedef ColorT color_type;
1306  typedef Order order_type;
1307  typedef typename color_type::value_type value_type;
1308  typedef typename color_type::calc_type calc_type;
1309  typedef typename color_type::long_type long_type;
1310 
1311  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1312  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1313  {
1314  comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p, r, g, b, a, cover);
1315  }
1316  };
1317 
1318  //=====================================comp_op_adaptor_clip_to_dst_rgba_pre
1319  template<class ColorT, class Order>
1321  {
1322  typedef ColorT color_type;
1323  typedef Order order_type;
1324  typedef typename color_type::value_type value_type;
1325  typedef typename color_type::calc_type calc_type;
1326  typedef typename color_type::long_type long_type;
1327 
1328  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1329  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1330  {
1331  value_type da = p[Order::A];
1332  comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p,
1333  color_type::multiply(r, da),
1334  color_type::multiply(g, da),
1335  color_type::multiply(b, da),
1336  color_type::multiply(a, da), cover);
1337  }
1338  };
1339 
1340  //====================================================comp_op_adaptor_rgba_plain
1341  template<class ColorT, class Order>
1343  {
1344  typedef ColorT color_type;
1345  typedef Order order_type;
1346  typedef typename color_type::value_type value_type;
1347  typedef typename color_type::calc_type calc_type;
1348  typedef typename color_type::long_type long_type;
1349 
1350  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1351  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1352  {
1354  comp_op_adaptor_rgba<ColorT, Order>::blend_pix(op, p, r, g, b, a, cover);
1356  }
1357  };
1358 
1359  //=========================================comp_op_adaptor_clip_to_dst_rgba_plain
1360  template<class ColorT, class Order>
1362  {
1363  typedef ColorT color_type;
1364  typedef Order order_type;
1365  typedef typename color_type::value_type value_type;
1366  typedef typename color_type::calc_type calc_type;
1367  typedef typename color_type::long_type long_type;
1368 
1369  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1370  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1371  {
1375  }
1376  };
1377 
1378  //=======================================================comp_adaptor_rgba
1379  template<class BlenderPre>
1381  {
1382  typedef typename BlenderPre::color_type color_type;
1383  typedef typename BlenderPre::order_type order_type;
1384  typedef typename color_type::value_type value_type;
1385  typedef typename color_type::calc_type calc_type;
1386  typedef typename color_type::long_type long_type;
1387 
1388  static AGG_INLINE void blend_pix(unsigned, value_type* p,
1389  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1390  {
1391  BlenderPre::blend_pix(p,
1392  color_type::multiply(r, a),
1393  color_type::multiply(g, a),
1394  color_type::multiply(b, a),
1395  a, cover);
1396  }
1397  };
1398 
1399  //==========================================comp_adaptor_clip_to_dst_rgba
1400  template<class BlenderPre>
1402  {
1403  typedef typename BlenderPre::color_type color_type;
1404  typedef typename BlenderPre::order_type order_type;
1405  typedef typename color_type::value_type value_type;
1406  typedef typename color_type::calc_type calc_type;
1407  typedef typename color_type::long_type long_type;
1408 
1409  static AGG_INLINE void blend_pix(unsigned, value_type* p,
1410  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1411  {
1412  r = color_type::multiply(r, a);
1413  g = color_type::multiply(g, a);
1414  b = color_type::multiply(b, a);
1415  value_type da = p[order_type::A];
1416  BlenderPre::blend_pix(p,
1417  color_type::multiply(r, da),
1418  color_type::multiply(g, da),
1419  color_type::multiply(b, da),
1420  color_type::multiply(a, da), cover);
1421  }
1422  };
1423 
1424  //=======================================================comp_adaptor_rgba_pre
1425  template<class BlenderPre>
1427  {
1428  typedef typename BlenderPre::color_type color_type;
1429  typedef typename BlenderPre::order_type order_type;
1430  typedef typename color_type::value_type value_type;
1431  typedef typename color_type::calc_type calc_type;
1432  typedef typename color_type::long_type long_type;
1433 
1434  static AGG_INLINE void blend_pix(unsigned, value_type* p,
1435  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1436  {
1437  BlenderPre::blend_pix(p, r, g, b, a, cover);
1438  }
1439  };
1440 
1441  //======================================comp_adaptor_clip_to_dst_rgba_pre
1442  template<class BlenderPre>
1444  {
1445  typedef typename BlenderPre::color_type color_type;
1446  typedef typename BlenderPre::order_type order_type;
1447  typedef typename color_type::value_type value_type;
1448  typedef typename color_type::calc_type calc_type;
1449  typedef typename color_type::long_type long_type;
1450 
1451  static AGG_INLINE void blend_pix(unsigned, value_type* p,
1452  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1453  {
1454  unsigned da = p[order_type::A];
1455  BlenderPre::blend_pix(p,
1456  color_type::multiply(r, da),
1457  color_type::multiply(g, da),
1458  color_type::multiply(b, da),
1459  color_type::multiply(a, da),
1460  cover);
1461  }
1462  };
1463 
1464  //=======================================================comp_adaptor_rgba_plain
1465  template<class BlenderPre>
1467  {
1468  typedef typename BlenderPre::color_type color_type;
1469  typedef typename BlenderPre::order_type order_type;
1470  typedef typename color_type::value_type value_type;
1471  typedef typename color_type::calc_type calc_type;
1472  typedef typename color_type::long_type long_type;
1473 
1474  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1475  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1476  {
1478  comp_adaptor_rgba<BlenderPre>::blend_pix(op, p, r, g, b, a, cover);
1480  }
1481  };
1482 
1483  //==========================================comp_adaptor_clip_to_dst_rgba_plain
1484  template<class BlenderPre>
1486  {
1487  typedef typename BlenderPre::color_type color_type;
1488  typedef typename BlenderPre::order_type order_type;
1489  typedef typename color_type::value_type value_type;
1490  typedef typename color_type::calc_type calc_type;
1491  typedef typename color_type::long_type long_type;
1492 
1493  static AGG_INLINE void blend_pix(unsigned op, value_type* p,
1494  value_type r, value_type g, value_type b, value_type a, cover_type cover)
1495  {
1497  comp_adaptor_clip_to_dst_rgba<BlenderPre>::blend_pix(op, p, r, g, b, a, cover);
1499  }
1500  };
1501 
1502 
1503  //=================================================pixfmt_alpha_blend_rgba
1504  template<class Blender, class RenBuf>
1506  {
1507  public:
1509  typedef RenBuf rbuf_type;
1510  typedef typename rbuf_type::row_data row_data;
1511  typedef Blender blender_type;
1512  typedef typename blender_type::color_type color_type;
1513  typedef typename blender_type::order_type order_type;
1514  typedef typename color_type::value_type value_type;
1515  typedef typename color_type::calc_type calc_type;
1516  enum
1517  {
1518  num_components = 4,
1519  pix_step = 4,
1520  pix_width = sizeof(value_type) * pix_step,
1521  };
1522  struct pixel_type
1523  {
1524  value_type c[num_components];
1525 
1526  void set(value_type r, value_type g, value_type b, value_type a)
1527  {
1528  c[order_type::R] = r;
1529  c[order_type::G] = g;
1530  c[order_type::B] = b;
1531  c[order_type::A] = a;
1532  }
1533 
1534  void set(const color_type& color)
1535  {
1536  set(color.r, color.g, color.b, color.a);
1537  }
1538 
1539  void get(value_type& r, value_type& g, value_type& b, value_type& a) const
1540  {
1541  r = c[order_type::R];
1542  g = c[order_type::G];
1543  b = c[order_type::B];
1544  a = c[order_type::A];
1545  }
1546 
1547  color_type get() const
1548  {
1549  return color_type(
1550  c[order_type::R],
1551  c[order_type::G],
1552  c[order_type::B],
1553  c[order_type::A]);
1554  }
1555 
1556  pixel_type* next()
1557  {
1558  return (pixel_type*)(c + pix_step);
1559  }
1560 
1561  const pixel_type* next() const
1562  {
1563  return (const pixel_type*)(c + pix_step);
1564  }
1565 
1566  pixel_type* advance(int n)
1567  {
1568  return (pixel_type*)(c + n * pix_step);
1569  }
1570 
1571  const pixel_type* advance(int n) const
1572  {
1573  return (const pixel_type*)(c + n * pix_step);
1574  }
1575  };
1576 
1577  private:
1578  //--------------------------------------------------------------------
1579  AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
1580  {
1581  m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover);
1582  }
1583 
1584  //--------------------------------------------------------------------
1585  AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
1586  {
1587  m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a);
1588  }
1589 
1590  //--------------------------------------------------------------------
1591  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
1592  {
1593  if (!c.is_transparent())
1594  {
1595  if (c.is_opaque() && cover == cover_mask)
1596  {
1597  p->set(c.r, c.g, c.b, c.a);
1598  }
1599  else
1600  {
1601  m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover);
1602  }
1603  }
1604  }
1605 
1606  //--------------------------------------------------------------------
1607  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
1608  {
1609  if (!c.is_transparent())
1610  {
1611  if (c.is_opaque())
1612  {
1613  p->set(c.r, c.g, c.b, c.a);
1614  }
1615  else
1616  {
1617  m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a);
1618  }
1619  }
1620  }
1621 
1622  public:
1623  //--------------------------------------------------------------------
1624  pixfmt_alpha_blend_rgba() : m_rbuf(0) {}
1625  explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
1626  void attach(rbuf_type& rb) { m_rbuf = &rb; }
1627 
1628  //--------------------------------------------------------------------
1629  template<class PixFmt>
1630  bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
1631  {
1632  rect_i r(x1, y1, x2, y2);
1633  if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
1634  {
1635  int stride = pixf.stride();
1636  m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
1637  (r.x2 - r.x1) + 1,
1638  (r.y2 - r.y1) + 1,
1639  stride);
1640  return true;
1641  }
1642  return false;
1643  }
1644 
1645  //--------------------------------------------------------------------
1646  AGG_INLINE unsigned width() const { return m_rbuf->width(); }
1647  AGG_INLINE unsigned height() const { return m_rbuf->height(); }
1648  AGG_INLINE int stride() const { return m_rbuf->stride(); }
1649 
1650  //--------------------------------------------------------------------
1651  AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
1652  AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
1653  AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
1654 
1655  //--------------------------------------------------------------------
1656  AGG_INLINE int8u* pix_ptr(int x, int y)
1657  {
1658  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step);
1659  }
1660 
1661  AGG_INLINE const int8u* pix_ptr(int x, int y) const
1662  {
1663  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step);
1664  }
1665 
1666  // Return pointer to pixel value, forcing row to be allocated.
1667  AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
1668  {
1669  return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step));
1670  }
1671 
1672  // Return pointer to pixel value, or null if row not allocated.
1673  AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
1674  {
1675  int8u* p = m_rbuf->row_ptr(y);
1676  return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step)) : 0;
1677  }
1678 
1679  // Get pixel pointer from raw buffer pointer.
1680  AGG_INLINE static pixel_type* pix_value_ptr(void* p)
1681  {
1682  return (pixel_type*)p;
1683  }
1684 
1685  // Get pixel pointer from raw buffer pointer.
1686  AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
1687  {
1688  return (const pixel_type*)p;
1689  }
1690 
1691  //--------------------------------------------------------------------
1692  AGG_INLINE static void write_plain_color(void* p, color_type c)
1693  {
1694  blender_type::set_plain_color(pix_value_ptr(p)->c, c);
1695  }
1696 
1697  //--------------------------------------------------------------------
1698  AGG_INLINE static color_type read_plain_color(const void* p)
1699  {
1700  return blender_type::get_plain_color(pix_value_ptr(p)->c);
1701  }
1702 
1703  //--------------------------------------------------------------------
1704  AGG_INLINE static void make_pix(int8u* p, const color_type& c)
1705  {
1706  ((pixel_type*)p)->set(c);
1707  }
1708 
1709  //--------------------------------------------------------------------
1710  AGG_INLINE color_type pixel(int x, int y) const
1711  {
1712  if (const pixel_type* p = pix_value_ptr(x, y))
1713  {
1714  return p->get();
1715  }
1716  return color_type::no_color();
1717  }
1718 
1719  //--------------------------------------------------------------------
1720  AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
1721  {
1722  pix_value_ptr(x, y, 1)->set(c);
1723  }
1724 
1725  //--------------------------------------------------------------------
1726  AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
1727  {
1728  copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
1729  }
1730 
1731  //--------------------------------------------------------------------
1732  AGG_INLINE void copy_hline(int x, int y,
1733  unsigned len,
1734  const color_type& c)
1735  {
1736  pixel_type v;
1737  v.set(c);
1738  pixel_type* p = pix_value_ptr(x, y, len);
1739  do
1740  {
1741  *p = v;
1742  p = p->next();
1743  }
1744  while (--len);
1745  }
1746 
1747 
1748  //--------------------------------------------------------------------
1749  AGG_INLINE void copy_vline(int x, int y,
1750  unsigned len,
1751  const color_type& c)
1752  {
1753  pixel_type v;
1754  v.set(c);
1755  do
1756  {
1757  *pix_value_ptr(x, y++, 1) = v;
1758  }
1759  while (--len);
1760  }
1761 
1762  //--------------------------------------------------------------------
1763  void blend_hline(int x, int y,
1764  unsigned len,
1765  const color_type& c,
1766  int8u cover)
1767  {
1768  if (!c.is_transparent())
1769  {
1770  pixel_type* p = pix_value_ptr(x, y, len);
1771  if (c.is_opaque() && cover == cover_mask)
1772  {
1773  pixel_type v;
1774  v.set(c);
1775  do
1776  {
1777  *p = v;
1778  p = p->next();
1779  }
1780  while (--len);
1781  }
1782  else
1783  {
1784  if (cover == cover_mask)
1785  {
1786  do
1787  {
1788  blend_pix(p, c);
1789  p = p->next();
1790  }
1791  while (--len);
1792  }
1793  else
1794  {
1795  do
1796  {
1797  blend_pix(p, c, cover);
1798  p = p->next();
1799  }
1800  while (--len);
1801  }
1802  }
1803  }
1804  }
1805 
1806 
1807  //--------------------------------------------------------------------
1808  void blend_vline(int x, int y,
1809  unsigned len,
1810  const color_type& c,
1811  int8u cover)
1812  {
1813  if (!c.is_transparent())
1814  {
1815  if (c.is_opaque() && cover == cover_mask)
1816  {
1817  pixel_type v;
1818  v.set(c);
1819  do
1820  {
1821  *pix_value_ptr(x, y++, 1) = v;
1822  }
1823  while (--len);
1824  }
1825  else
1826  {
1827  if (cover == cover_mask)
1828  {
1829  do
1830  {
1831  blend_pix(pix_value_ptr(x, y++, 1), c, c.a);
1832  }
1833  while (--len);
1834  }
1835  else
1836  {
1837  do
1838  {
1839  blend_pix(pix_value_ptr(x, y++, 1), c, cover);
1840  }
1841  while (--len);
1842  }
1843  }
1844  }
1845  }
1846 
1847 
1848  //--------------------------------------------------------------------
1849  void blend_solid_hspan(int x, int y,
1850  unsigned len,
1851  const color_type& c,
1852  const int8u* covers)
1853  {
1854  if (!c.is_transparent())
1855  {
1856  pixel_type* p = pix_value_ptr(x, y, len);
1857  do
1858  {
1859  if (c.is_opaque() && *covers == cover_mask)
1860  {
1861  p->set(c);
1862  }
1863  else
1864  {
1865  blend_pix(p, c, *covers);
1866  }
1867  p = p->next();
1868  ++covers;
1869  }
1870  while (--len);
1871  }
1872  }
1873 
1874 
1875  //--------------------------------------------------------------------
1876  void blend_solid_vspan(int x, int y,
1877  unsigned len,
1878  const color_type& c,
1879  const int8u* covers)
1880  {
1881  if (!c.is_transparent())
1882  {
1883  do
1884  {
1885  pixel_type* p = pix_value_ptr(x, y++, 1);
1886  if (c.is_opaque() && *covers == cover_mask)
1887  {
1888  p->set(c);
1889  }
1890  else
1891  {
1892  blend_pix(p, c, *covers);
1893  }
1894  ++covers;
1895  }
1896  while (--len);
1897  }
1898  }
1899 
1900  //--------------------------------------------------------------------
1901  void copy_color_hspan(int x, int y,
1902  unsigned len,
1903  const color_type* colors)
1904  {
1905  pixel_type* p = pix_value_ptr(x, y, len);
1906  do
1907  {
1908  p->set(*colors++);
1909  p = p->next();
1910  }
1911  while (--len);
1912  }
1913 
1914 
1915  //--------------------------------------------------------------------
1916  void copy_color_vspan(int x, int y,
1917  unsigned len,
1918  const color_type* colors)
1919  {
1920  do
1921  {
1922  pix_value_ptr(x, y++, 1)->set(*colors++);
1923  }
1924  while (--len);
1925  }
1926 
1927  //--------------------------------------------------------------------
1928  void blend_color_hspan(int x, int y,
1929  unsigned len,
1930  const color_type* colors,
1931  const int8u* covers,
1932  int8u cover)
1933  {
1934  pixel_type* p = pix_value_ptr(x, y, len);
1935  if (covers)
1936  {
1937  do
1938  {
1939  copy_or_blend_pix(p, *colors++, *covers++);
1940  p = p->next();
1941  }
1942  while (--len);
1943  }
1944  else
1945  {
1946  if (cover == cover_mask)
1947  {
1948  do
1949  {
1950  copy_or_blend_pix(p, *colors++);
1951  p = p->next();
1952  }
1953  while (--len);
1954  }
1955  else
1956  {
1957  do
1958  {
1959  copy_or_blend_pix(p, *colors++, cover);
1960  p = p->next();
1961  }
1962  while (--len);
1963  }
1964  }
1965  }
1966 
1967  //--------------------------------------------------------------------
1968  void blend_color_vspan(int x, int y,
1969  unsigned len,
1970  const color_type* colors,
1971  const int8u* covers,
1972  int8u cover)
1973  {
1974  if (covers)
1975  {
1976  do
1977  {
1978  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
1979  }
1980  while (--len);
1981  }
1982  else
1983  {
1984  if (cover == cover_mask)
1985  {
1986  do
1987  {
1988  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
1989  }
1990  while (--len);
1991  }
1992  else
1993  {
1994  do
1995  {
1996  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
1997  }
1998  while (--len);
1999  }
2000  }
2001  }
2002 
2003  //--------------------------------------------------------------------
2004  template<class Function> void for_each_pixel(Function f)
2005  {
2006  for (unsigned y = 0; y < height(); ++y)
2007  {
2008  row_data r = m_rbuf->row(y);
2009  if (r.ptr)
2010  {
2011  unsigned len = r.x2 - r.x1 + 1;
2012  pixel_type* p = pix_value_ptr(r.x1, y, len);
2013  do
2014  {
2015  f(p->c);
2016  p = p->next();
2017  }
2018  while (--len);
2019  }
2020  }
2021  }
2022 
2023  //--------------------------------------------------------------------
2024  void premultiply()
2025  {
2027  }
2028 
2029  //--------------------------------------------------------------------
2030  void demultiply()
2031  {
2033  }
2034 
2035  //--------------------------------------------------------------------
2036  template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
2037  {
2039  }
2040 
2041  //--------------------------------------------------------------------
2042  template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
2043  {
2045  }
2046 
2047  //--------------------------------------------------------------------
2048  template<class RenBuf2> void copy_from(const RenBuf2& from,
2049  int xdst, int ydst,
2050  int xsrc, int ysrc,
2051  unsigned len)
2052  {
2053  if (const int8u* p = from.row_ptr(ysrc))
2054  {
2055  std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
2056  p + xsrc * pix_width,
2057  len * pix_width);
2058  }
2059  }
2060 
2061  //--------------------------------------------------------------------
2062  // Blend from another RGBA surface.
2063  template<class SrcPixelFormatRenderer>
2064  void blend_from(const SrcPixelFormatRenderer& from,
2065  int xdst, int ydst,
2066  int xsrc, int ysrc,
2067  unsigned len,
2068  int8u cover)
2069  {
2070  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
2071 
2072  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
2073  {
2074  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
2075  int srcinc = 1;
2076  int dstinc = 1;
2077 
2078  if (xdst > xsrc)
2079  {
2080  psrc = psrc->advance(len - 1);
2081  pdst = pdst->advance(len - 1);
2082  srcinc = -1;
2083  dstinc = -1;
2084  }
2085 
2086  if (cover == cover_mask)
2087  {
2088  do
2089  {
2090  copy_or_blend_pix(pdst, psrc->get());
2091  psrc = psrc->advance(srcinc);
2092  pdst = pdst->advance(dstinc);
2093  }
2094  while (--len);
2095  }
2096  else
2097  {
2098  do
2099  {
2100  copy_or_blend_pix(pdst, psrc->get(), cover);
2101  psrc = psrc->advance(srcinc);
2102  pdst = pdst->advance(dstinc);
2103  }
2104  while (--len);
2105  }
2106  }
2107  }
2108 
2109  //--------------------------------------------------------------------
2110  // Combine single color with grayscale surface and blend.
2111  template<class SrcPixelFormatRenderer>
2112  void blend_from_color(const SrcPixelFormatRenderer& from,
2113  const color_type& color,
2114  int xdst, int ydst,
2115  int xsrc, int ysrc,
2116  unsigned len,
2117  int8u cover)
2118  {
2119  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
2120  typedef typename SrcPixelFormatRenderer::color_type src_color_type;
2121 
2122  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
2123  {
2124  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
2125 
2126  do
2127  {
2128  copy_or_blend_pix(pdst, color,
2129  src_color_type::scale_cover(cover, psrc->c[0]));
2130  psrc = psrc->next();
2131  pdst = pdst->next();
2132  }
2133  while (--len);
2134  }
2135  }
2136 
2137  //--------------------------------------------------------------------
2138  // Blend from color table, using grayscale surface as indexes into table.
2139  // Obviously, this only works for integer value types.
2140  template<class SrcPixelFormatRenderer>
2141  void blend_from_lut(const SrcPixelFormatRenderer& from,
2142  const color_type* color_lut,
2143  int xdst, int ydst,
2144  int xsrc, int ysrc,
2145  unsigned len,
2146  int8u cover)
2147  {
2148  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
2149 
2150  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
2151  {
2152  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
2153 
2154  if (cover == cover_mask)
2155  {
2156  do
2157  {
2158  copy_or_blend_pix(pdst, color_lut[psrc->c[0]]);
2159  psrc = psrc->next();
2160  pdst = pdst->next();
2161  }
2162  while (--len);
2163  }
2164  else
2165  {
2166  do
2167  {
2168  copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
2169  psrc = psrc->next();
2170  pdst = pdst->next();
2171  }
2172  while (--len);
2173  }
2174  }
2175  }
2176 
2177  private:
2178  rbuf_type* m_rbuf;
2179  Blender m_blender;
2180  };
2181 
2182  //================================================pixfmt_custom_blend_rgba
2183  template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba
2184  {
2185  public:
2187  typedef RenBuf rbuf_type;
2188  typedef typename rbuf_type::row_data row_data;
2189  typedef Blender blender_type;
2190  typedef typename blender_type::color_type color_type;
2191  typedef typename blender_type::order_type order_type;
2192  typedef typename color_type::value_type value_type;
2193  typedef typename color_type::calc_type calc_type;
2194  enum
2195  {
2196  num_components = 4,
2197  pix_step = 4,
2198  pix_width = sizeof(value_type) * pix_step,
2199  };
2200  struct pixel_type
2201  {
2202  value_type c[num_components];
2203 
2204  void set(value_type r, value_type g, value_type b, value_type a)
2205  {
2206  c[order_type::R] = r;
2207  c[order_type::G] = g;
2208  c[order_type::B] = b;
2209  c[order_type::A] = a;
2210  }
2211 
2212  void set(const color_type& color)
2213  {
2214  set(color.r, color.g, color.b, color.a);
2215  }
2216 
2217  void get(value_type& r, value_type& g, value_type& b, value_type& a) const
2218  {
2219  r = c[order_type::R];
2220  g = c[order_type::G];
2221  b = c[order_type::B];
2222  a = c[order_type::A];
2223  }
2224 
2225  color_type get() const
2226  {
2227  return color_type(
2228  c[order_type::R],
2229  c[order_type::G],
2230  c[order_type::B],
2231  c[order_type::A]);
2232  }
2233 
2234  pixel_type* next()
2235  {
2236  return (pixel_type*)(c + pix_step);
2237  }
2238 
2239  const pixel_type* next() const
2240  {
2241  return (const pixel_type*)(c + pix_step);
2242  }
2243 
2244  pixel_type* advance(int n)
2245  {
2246  return (pixel_type*)(c + n * pix_step);
2247  }
2248 
2249  const pixel_type* advance(int n) const
2250  {
2251  return (const pixel_type*)(c + n * pix_step);
2252  }
2253  };
2254 
2255 
2256  private:
2257  //--------------------------------------------------------------------
2258  AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full)
2259  {
2260  m_blender.blend_pix(m_comp_op, p->c, c.r, c.g, c.b, c.a, cover);
2261  }
2262 
2263  //--------------------------------------------------------------------
2264  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full)
2265  {
2266  if (!c.is_transparent())
2267  {
2268  if (c.is_opaque() && cover == cover_mask)
2269  {
2270  p->set(c.r, c.g, c.b, c.a);
2271  }
2272  else
2273  {
2274  blend_pix(p, c, cover);
2275  }
2276  }
2277  }
2278 
2279  public:
2280  //--------------------------------------------------------------------
2281  pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {}
2282  explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) :
2283  m_rbuf(&rb),
2284  m_comp_op(comp_op)
2285  {}
2286  void attach(rbuf_type& rb) { m_rbuf = &rb; }
2287 
2288  //--------------------------------------------------------------------
2289  template<class PixFmt>
2290  bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
2291  {
2292  rect_i r(x1, y1, x2, y2);
2293  if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
2294  {
2295  int stride = pixf.stride();
2296  m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
2297  (r.x2 - r.x1) + 1,
2298  (r.y2 - r.y1) + 1,
2299  stride);
2300  return true;
2301  }
2302  return false;
2303  }
2304 
2305  //--------------------------------------------------------------------
2306  void comp_op(unsigned op) { m_comp_op = op; }
2307  unsigned comp_op() const { return m_comp_op; }
2308 
2309  //--------------------------------------------------------------------
2310  AGG_INLINE unsigned width() const { return m_rbuf->width(); }
2311  AGG_INLINE unsigned height() const { return m_rbuf->height(); }
2312  AGG_INLINE int stride() const { return m_rbuf->stride(); }
2313 
2314  //--------------------------------------------------------------------
2315  AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
2316  AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
2317  AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
2318 
2319  //--------------------------------------------------------------------
2320  AGG_INLINE int8u* pix_ptr(int x, int y)
2321  {
2322  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step);
2323  }
2324 
2325  AGG_INLINE const int8u* pix_ptr(int x, int y) const
2326  {
2327  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step);
2328  }
2329 
2330  // Return pointer to pixel value, forcing row to be allocated.
2331  AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
2332  {
2333  return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step));
2334  }
2335 
2336  // Return pointer to pixel value, or null if row not allocated.
2337  AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
2338  {
2339  int8u* p = m_rbuf->row_ptr(y);
2340  return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step)) : 0;
2341  }
2342 
2343  // Get pixel pointer from raw buffer pointer.
2344  AGG_INLINE static pixel_type* pix_value_ptr(void* p)
2345  {
2346  return (pixel_type*)p;
2347  }
2348 
2349  // Get pixel pointer from raw buffer pointer.
2350  AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
2351  {
2352  return (const pixel_type*)p;
2353  }
2354 
2355  //--------------------------------------------------------------------
2356  AGG_INLINE static void make_pix(int8u* p, const color_type& c)
2357  {
2358  ((pixel_type*)p)->set(c);
2359  }
2360 
2361  //--------------------------------------------------------------------
2362  AGG_INLINE color_type pixel(int x, int y) const
2363  {
2364  if (const pixel_type* p = pix_value_ptr(x, y))
2365  {
2366  return p->get();
2367  }
2368  return color_type::no_color();
2369  }
2370 
2371  //--------------------------------------------------------------------
2372  AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
2373  {
2374  make_pix(pix_value_ptr(x, y, 1), c);
2375  }
2376 
2377  //--------------------------------------------------------------------
2378  AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
2379  {
2380  blend_pix(pix_value_ptr(x, y, 1), c, cover);
2381  }
2382 
2383  //--------------------------------------------------------------------
2384  AGG_INLINE void copy_hline(int x, int y,
2385  unsigned len,
2386  const color_type& c)
2387  {
2388  pixel_type v;
2389  v.set(c);
2390  pixel_type* p = pix_value_ptr(x, y, len);
2391  do
2392  {
2393  *p = v;
2394  p = p->next();
2395  }
2396  while (--len);
2397  }
2398 
2399 
2400  //--------------------------------------------------------------------
2401  AGG_INLINE void copy_vline(int x, int y,
2402  unsigned len,
2403  const color_type& c)
2404  {
2405  pixel_type v;
2406  v.set(c);
2407  do
2408  {
2409  *pix_value_ptr(x, y++, 1) = v;
2410  }
2411  while (--len);
2412  }
2413 
2414  //--------------------------------------------------------------------
2415  void blend_hline(int x, int y, unsigned len,
2416  const color_type& c, int8u cover)
2417  {
2418 
2419  pixel_type* p = pix_value_ptr(x, y, len);
2420  do
2421  {
2422  blend_pix(p, c, cover);
2423  p = p->next();
2424  }
2425  while (--len);
2426  }
2427 
2428  //--------------------------------------------------------------------
2429  void blend_vline(int x, int y, unsigned len,
2430  const color_type& c, int8u cover)
2431  {
2432  do
2433  {
2434  blend_pix(pix_value_ptr(x, y++, 1), c, cover);
2435  }
2436  while (--len);
2437  }
2438 
2439  //--------------------------------------------------------------------
2440  void blend_solid_hspan(int x, int y, unsigned len,
2441  const color_type& c, const int8u* covers)
2442  {
2443  pixel_type* p = pix_value_ptr(x, y, len);
2444 
2445  do
2446  {
2447  blend_pix(p, c, *covers++);
2448  p = p->next();
2449  }
2450  while (--len);
2451  }
2452 
2453  //--------------------------------------------------------------------
2454  void blend_solid_vspan(int x, int y, unsigned len,
2455  const color_type& c, const int8u* covers)
2456  {
2457  do
2458  {
2459  blend_pix(pix_value_ptr(x, y++, 1), c, *covers++);
2460  }
2461  while (--len);
2462  }
2463 
2464  //--------------------------------------------------------------------
2465  void copy_color_hspan(int x, int y,
2466  unsigned len,
2467  const color_type* colors)
2468  {
2469  pixel_type* p = pix_value_ptr(x, y, len);
2470 
2471  do
2472  {
2473  p->set(*colors++);
2474  p = p->next();
2475  }
2476  while (--len);
2477  }
2478 
2479  //--------------------------------------------------------------------
2480  void copy_color_vspan(int x, int y,
2481  unsigned len,
2482  const color_type* colors)
2483  {
2484  do
2485  {
2486  pix_value_ptr(x, y++, 1)->set(*colors++);
2487  }
2488  while (--len);
2489  }
2490 
2491  //--------------------------------------------------------------------
2492  void blend_color_hspan(int x, int y, unsigned len,
2493  const color_type* colors,
2494  const int8u* covers,
2495  int8u cover)
2496  {
2497  pixel_type* p = pix_value_ptr(x, y, len);
2498 
2499  do
2500  {
2501  blend_pix(p, *colors++, covers ? *covers++ : cover);
2502  p = p->next();
2503  }
2504  while (--len);
2505  }
2506 
2507  //--------------------------------------------------------------------
2508  void blend_color_vspan(int x, int y, unsigned len,
2509  const color_type* colors,
2510  const int8u* covers,
2511  int8u cover)
2512  {
2513  do
2514  {
2515  blend_pix(pix_value_ptr(x, y++, 1), *colors++, covers ? *covers++ : cover);
2516  }
2517  while (--len);
2518 
2519  }
2520 
2521  //--------------------------------------------------------------------
2522  template<class Function> void for_each_pixel(Function f)
2523  {
2524  unsigned y;
2525  for (y = 0; y < height(); ++y)
2526  {
2527  row_data r = m_rbuf->row(y);
2528  if (r.ptr)
2529  {
2530  unsigned len = r.x2 - r.x1 + 1;
2531  pixel_type* p = pix_value_ptr(r.x1, y, len);
2532  do
2533  {
2534  f(p->c);
2535  p = p->next();
2536  }
2537  while (--len);
2538  }
2539  }
2540  }
2541 
2542  //--------------------------------------------------------------------
2543  void premultiply()
2544  {
2546  }
2547 
2548  //--------------------------------------------------------------------
2549  void demultiply()
2550  {
2552  }
2553 
2554  //--------------------------------------------------------------------
2555  template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
2556  {
2558  }
2559 
2560  //--------------------------------------------------------------------
2561  template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
2562  {
2564  }
2565 
2566  //--------------------------------------------------------------------
2567  template<class RenBuf2> void copy_from(const RenBuf2& from,
2568  int xdst, int ydst,
2569  int xsrc, int ysrc,
2570  unsigned len)
2571  {
2572  if (const int8u* p = from.row_ptr(ysrc))
2573  {
2574  std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
2575  p + xsrc * pix_width,
2576  len * pix_width);
2577  }
2578  }
2579 
2580  //--------------------------------------------------------------------
2581  // Blend from another RGBA surface.
2582  template<class SrcPixelFormatRenderer>
2583  void blend_from(const SrcPixelFormatRenderer& from,
2584  int xdst, int ydst,
2585  int xsrc, int ysrc,
2586  unsigned len,
2587  int8u cover)
2588  {
2589  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
2590 
2591  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
2592  {
2593  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
2594  int srcinc = 1;
2595  int dstinc = 1;
2596 
2597  if (xdst > xsrc)
2598  {
2599  psrc = psrc->advance(len - 1);
2600  pdst = pdst->advance(len - 1);
2601  srcinc = -1;
2602  dstinc = -1;
2603  }
2604 
2605  do
2606  {
2607  blend_pix(pdst, psrc->get(), cover);
2608  psrc = psrc->advance(srcinc);
2609  pdst = pdst->advance(dstinc);
2610  }
2611  while (--len);
2612  }
2613  }
2614 
2615  //--------------------------------------------------------------------
2616  // Blend from single color, using grayscale surface as alpha channel.
2617  template<class SrcPixelFormatRenderer>
2618  void blend_from_color(const SrcPixelFormatRenderer& from,
2619  const color_type& color,
2620  int xdst, int ydst,
2621  int xsrc, int ysrc,
2622  unsigned len,
2623  int8u cover)
2624  {
2625  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
2626  typedef typename SrcPixelFormatRenderer::color_type src_color_type;
2627 
2628  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
2629  {
2630  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
2631 
2632  do
2633  {
2634  blend_pix(pdst, color,
2635  src_color_type::scale_cover(cover, psrc->c[0]));
2636  psrc = psrc->next();
2637  pdst = pdst->next();
2638  }
2639  while (--len);
2640  }
2641  }
2642 
2643  //--------------------------------------------------------------------
2644  // Blend from color table, using grayscale surface as indexes into table.
2645  // Obviously, this only works for integer value types.
2646  template<class SrcPixelFormatRenderer>
2647  void blend_from_lut(const SrcPixelFormatRenderer& from,
2648  const color_type* color_lut,
2649  int xdst, int ydst,
2650  int xsrc, int ysrc,
2651  unsigned len,
2652  int8u cover)
2653  {
2654  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
2655 
2656  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
2657  {
2658  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
2659 
2660  do
2661  {
2662  blend_pix(pdst, color_lut[psrc->c[0]], cover);
2663  psrc = psrc->next();
2664  pdst = pdst->next();
2665  }
2666  while (--len);
2667  }
2668  }
2669 
2670  private:
2671  rbuf_type* m_rbuf;
2672  Blender m_blender;
2673  unsigned m_comp_op;
2674  };
2675 
2676 
2677  //-----------------------------------------------------------------------
2682 
2687 
2692 
2697 
2702 
2707 
2712 
2717 
2722 
2727 
2732 
2737 
2738 
2739  //-----------------------------------------------------------------------
2744 
2749 
2754 
2759 
2764 
2769 
2774 
2779 
2784 
2789 
2794 
2799 
2800 }
2801 
2802 #endif
2803 
Definition: agg_arc.cpp:24