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