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