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