Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_pixfmt_rgba.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 //
00025 // Adaptation for high precision colors has been sponsored by 
00026 // Liberty Technology Systems, Inc., visit http://lib-sys.com
00027 //
00028 // Liberty Technology Systems, Inc. is the provider of
00029 // PostScript and PDF technology for software developers.
00030 // 
00031 //----------------------------------------------------------------------------
00032 
00033 #ifndef AGG_PIXFMT_RGBA_INCLUDED
00034 #define AGG_PIXFMT_RGBA_INCLUDED
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 #include "agg_basics.h"
00039 #include "agg_color_rgba.h"
00040 #include "agg_rendering_buffer.h"
00041 
00042 namespace agg
00043 {
00044 
00045     //=========================================================multiplier_rgba
00046     template<class ColorT, class Order> struct multiplier_rgba
00047     {
00048         typedef typename ColorT::value_type value_type;
00049         typedef typename ColorT::calc_type calc_type;
00050 
00051         //--------------------------------------------------------------------
00052         static AGG_INLINE void premultiply(value_type* p)
00053         {
00054             calc_type a = p[Order::A];
00055             if(a < ColorT::base_mask)
00056             {
00057                 if(a == 0)
00058                 {
00059                     p[Order::R] = p[Order::G] = p[Order::B] = 0;
00060                     return;
00061                 }
00062                 p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift);
00063                 p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift);
00064                 p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift);
00065             }
00066         }
00067 
00068 
00069         //--------------------------------------------------------------------
00070         static AGG_INLINE void demultiply(value_type* p)
00071         {
00072             calc_type a = p[Order::A];
00073             if(a < ColorT::base_mask)
00074             {
00075                 if(a == 0)
00076                 {
00077                     p[Order::R] = p[Order::G] = p[Order::B] = 0;
00078                     return;
00079                 }
00080                 calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a;
00081                 calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a;
00082                 calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a;
00083                 p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r);
00084                 p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g);
00085                 p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b);
00086             }
00087         }
00088     };
00089 
00090     //=====================================================apply_gamma_dir_rgba
00091     template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba
00092     {
00093     public:
00094         typedef typename ColorT::value_type value_type;
00095 
00096         apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
00097 
00098         AGG_INLINE void operator () (value_type* p)
00099         {
00100             p[Order::R] = m_gamma.dir(p[Order::R]);
00101             p[Order::G] = m_gamma.dir(p[Order::G]);
00102             p[Order::B] = m_gamma.dir(p[Order::B]);
00103         }
00104 
00105     private:
00106         const GammaLut& m_gamma;
00107     };
00108 
00109     //=====================================================apply_gamma_inv_rgba
00110     template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba
00111     {
00112     public:
00113         typedef typename ColorT::value_type value_type;
00114 
00115         apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
00116 
00117         AGG_INLINE void operator () (value_type* p)
00118         {
00119             p[Order::R] = m_gamma.inv(p[Order::R]);
00120             p[Order::G] = m_gamma.inv(p[Order::G]);
00121             p[Order::B] = m_gamma.inv(p[Order::B]);
00122         }
00123 
00124     private:
00125         const GammaLut& m_gamma;
00126     };
00127 
00128 
00129     
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137     //=============================================================blender_rgba
00138     template<class ColorT, class Order> struct blender_rgba
00139     {
00140         typedef ColorT color_type;
00141         typedef Order order_type;
00142         typedef typename color_type::value_type value_type;
00143         typedef typename color_type::calc_type calc_type;
00144         enum base_scale_e 
00145         { 
00146             base_shift = color_type::base_shift,
00147             base_mask  = color_type::base_mask
00148         };
00149 
00150         //--------------------------------------------------------------------
00151         static AGG_INLINE void blend_pix(value_type* p, 
00152                                          unsigned cr, unsigned cg, unsigned cb,
00153                                          unsigned alpha, 
00154                                          unsigned cover=0)
00155         {
00156             calc_type r = p[Order::R];
00157             calc_type g = p[Order::G];
00158             calc_type b = p[Order::B];
00159             calc_type a = p[Order::A];
00160             p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift);
00161             p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift);
00162             p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift);
00163             p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift));
00164         }
00165     };
00166 
00167     //=========================================================blender_rgba_pre
00168     template<class ColorT, class Order> struct blender_rgba_pre
00169     {
00170         typedef ColorT color_type;
00171         typedef Order order_type;
00172         typedef typename color_type::value_type value_type;
00173         typedef typename color_type::calc_type calc_type;
00174         enum base_scale_e
00175         { 
00176             base_shift = color_type::base_shift,
00177             base_mask  = color_type::base_mask
00178         };
00179 
00180         //--------------------------------------------------------------------
00181         static AGG_INLINE void blend_pix(value_type* p, 
00182                                          unsigned cr, unsigned cg, unsigned cb,
00183                                          unsigned alpha,
00184                                          unsigned cover)
00185         {
00186             alpha = color_type::base_mask - alpha;
00187             cover = (cover + 1) << (base_shift - 8);
00188             p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
00189             p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
00190             p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
00191             p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift));
00192         }
00193 
00194         //--------------------------------------------------------------------
00195         static AGG_INLINE void blend_pix(value_type* p, 
00196                                          unsigned cr, unsigned cg, unsigned cb,
00197                                          unsigned alpha)
00198         {
00199             alpha = color_type::base_mask - alpha;
00200             p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
00201             p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
00202             p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
00203             p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift));
00204         }
00205     };
00206 
00207     //======================================================blender_rgba_plain
00208     template<class ColorT, class Order> struct blender_rgba_plain
00209     {
00210         typedef ColorT color_type;
00211         typedef Order order_type;
00212         typedef typename color_type::value_type value_type;
00213         typedef typename color_type::calc_type calc_type;
00214         enum base_scale_e { base_shift = color_type::base_shift };
00215 
00216         //--------------------------------------------------------------------
00217         static AGG_INLINE void blend_pix(value_type* p, 
00218                                          unsigned cr, unsigned cg, unsigned cb,
00219                                          unsigned alpha,
00220                                          unsigned cover=0)
00221         {
00222             if(alpha == 0) return;
00223             calc_type a = p[Order::A];
00224             calc_type r = p[Order::R] * a;
00225             calc_type g = p[Order::G] * a;
00226             calc_type b = p[Order::B] * a;
00227             a = ((alpha + a) << base_shift) - alpha * a;
00228             p[Order::A] = (value_type)(a >> base_shift);
00229             p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a);
00230             p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a);
00231             p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a);
00232         }
00233     };
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245     //=========================================================comp_op_rgba_clear
00246     template<class ColorT, class Order> struct comp_op_rgba_clear
00247     {
00248         typedef ColorT color_type;
00249         typedef Order order_type;
00250         typedef typename color_type::value_type value_type;
00251         enum base_scale_e
00252         { 
00253             base_shift = color_type::base_shift,
00254             base_mask  = color_type::base_mask
00255         };
00256 
00257         static AGG_INLINE void blend_pix(value_type* p, 
00258                                          unsigned, unsigned, unsigned, unsigned,
00259                                          unsigned cover)
00260         {
00261             if(cover < 255)
00262             {
00263                 cover = 255 - cover;
00264                 p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8);
00265                 p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8);
00266                 p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8);
00267                 p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8);
00268             }
00269             else
00270             {
00271                 p[0] = p[1] = p[2] = p[3] = 0; 
00272             }
00273         }
00274     };
00275 
00276     //===========================================================comp_op_rgba_src
00277     template<class ColorT, class Order> struct comp_op_rgba_src
00278     {
00279         typedef ColorT color_type;
00280         typedef Order order_type;
00281         typedef typename color_type::value_type value_type;
00282 
00283         static AGG_INLINE void blend_pix(value_type* p, 
00284                                          unsigned sr, unsigned sg, unsigned sb, 
00285                                          unsigned sa, unsigned cover)
00286         {
00287             if(cover < 255)
00288             {
00289                 unsigned alpha = 255 - cover;
00290                 p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8));
00291                 p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8));
00292                 p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8));
00293                 p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8));
00294             }
00295             else
00296             {
00297                 p[Order::R] = sr;
00298                 p[Order::G] = sg;
00299                 p[Order::B] = sb;
00300                 p[Order::A] = sa;
00301             }
00302         }
00303     };
00304 
00305     //===========================================================comp_op_rgba_dst
00306     template<class ColorT, class Order> struct comp_op_rgba_dst
00307     {
00308         typedef ColorT color_type;
00309         typedef Order order_type;
00310         typedef typename color_type::value_type value_type;
00311 
00312         static AGG_INLINE void blend_pix(value_type*, 
00313                                          unsigned, unsigned, unsigned, 
00314                                          unsigned, unsigned)
00315         {
00316         }
00317     };
00318 
00319     //======================================================comp_op_rgba_src_over
00320     template<class ColorT, class Order> struct comp_op_rgba_src_over
00321     {
00322         typedef ColorT color_type;
00323         typedef Order order_type;
00324         typedef typename color_type::value_type value_type;
00325         typedef typename color_type::calc_type calc_type;
00326         enum base_scale_e
00327         { 
00328             base_shift = color_type::base_shift,
00329             base_mask  = color_type::base_mask
00330         };
00331 
00332         //   Dca' = Sca + Dca.(1 - Sa)
00333         //   Da'  = Sa + Da - Sa.Da 
00334         static AGG_INLINE void blend_pix(value_type* p, 
00335                                          unsigned sr, unsigned sg, unsigned sb, 
00336                                          unsigned sa, unsigned cover)
00337         {
00338             if(cover < 255)
00339             {
00340                 sr = (sr * cover + 255) >> 8;
00341                 sg = (sg * cover + 255) >> 8;
00342                 sb = (sb * cover + 255) >> 8;
00343                 sa = (sa * cover + 255) >> 8;
00344             }
00345             calc_type s1a = base_mask - sa;
00346             p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift));
00347             p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift));
00348             p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift));
00349             p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
00350         }
00351     };
00352 
00353     //======================================================comp_op_rgba_dst_over
00354     template<class ColorT, class Order> struct comp_op_rgba_dst_over
00355     {
00356         typedef ColorT color_type;
00357         typedef Order order_type;
00358         typedef typename color_type::value_type value_type;
00359         typedef typename color_type::calc_type calc_type;
00360         enum base_scale_e
00361         { 
00362             base_shift = color_type::base_shift,
00363             base_mask  = color_type::base_mask
00364         };
00365 
00366         // Dca' = Dca + Sca.(1 - Da)
00367         // Da'  = Sa + Da - Sa.Da 
00368         static AGG_INLINE void blend_pix(value_type* p, 
00369                                          unsigned sr, unsigned sg, unsigned sb, 
00370                                          unsigned sa, unsigned cover)
00371         {
00372             if(cover < 255)
00373             {
00374                 sr = (sr * cover + 255) >> 8;
00375                 sg = (sg * cover + 255) >> 8;
00376                 sb = (sb * cover + 255) >> 8;
00377                 sa = (sa * cover + 255) >> 8;
00378             }
00379             calc_type d1a = base_mask - p[Order::A];
00380             p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift));
00381             p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift));
00382             p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift));
00383             p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
00384         }
00385     };
00386 
00387     //======================================================comp_op_rgba_src_in
00388     template<class ColorT, class Order> struct comp_op_rgba_src_in
00389     {
00390         typedef ColorT color_type;
00391         typedef Order order_type;
00392         typedef typename color_type::value_type value_type;
00393         typedef typename color_type::calc_type calc_type;
00394         enum base_scale_e
00395         { 
00396             base_shift = color_type::base_shift,
00397             base_mask  = color_type::base_mask
00398         };
00399 
00400         // Dca' = Sca.Da
00401         // Da'  = Sa.Da 
00402         static AGG_INLINE void blend_pix(value_type* p, 
00403                                          unsigned sr, unsigned sg, unsigned sb, 
00404                                          unsigned sa, unsigned cover)
00405         {
00406             calc_type da = p[Order::A];
00407             if(cover < 255)
00408             {
00409                 unsigned alpha = 255 - cover;
00410                 p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8));
00411                 p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8));
00412                 p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8));
00413                 p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8));
00414             }
00415             else
00416             {
00417                 p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift);
00418                 p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift);
00419                 p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift);
00420                 p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift);
00421             }
00422         }
00423     };
00424 
00425     //======================================================comp_op_rgba_dst_in
00426     template<class ColorT, class Order> struct comp_op_rgba_dst_in
00427     {
00428         typedef ColorT color_type;
00429         typedef Order order_type;
00430         typedef typename color_type::value_type value_type;
00431         typedef typename color_type::calc_type calc_type;
00432         enum base_scale_e
00433         { 
00434             base_shift = color_type::base_shift,
00435             base_mask  = color_type::base_mask
00436         };
00437 
00438         // Dca' = Dca.Sa
00439         // Da'  = Sa.Da 
00440         static AGG_INLINE void blend_pix(value_type* p, 
00441                                          unsigned, unsigned, unsigned, 
00442                                          unsigned sa, unsigned cover)
00443         {
00444             if(cover < 255)
00445             {
00446                 sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8);
00447             }
00448             p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift);
00449             p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift);
00450             p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift);
00451             p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift);
00452         }
00453     };
00454 
00455     //======================================================comp_op_rgba_src_out
00456     template<class ColorT, class Order> struct comp_op_rgba_src_out
00457     {
00458         typedef ColorT color_type;
00459         typedef Order order_type;
00460         typedef typename color_type::value_type value_type;
00461         typedef typename color_type::calc_type calc_type;
00462         enum base_scale_e
00463         { 
00464             base_shift = color_type::base_shift,
00465             base_mask  = color_type::base_mask
00466         };
00467 
00468         // Dca' = Sca.(1 - Da)
00469         // Da'  = Sa.(1 - Da) 
00470         static AGG_INLINE void blend_pix(value_type* p, 
00471                                          unsigned sr, unsigned sg, unsigned sb, 
00472                                          unsigned sa, unsigned cover)
00473         {
00474             calc_type da = base_mask - p[Order::A];
00475             if(cover < 255)
00476             {
00477                 unsigned alpha = 255 - cover;
00478                 p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8));
00479                 p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8));
00480                 p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8));
00481                 p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8));
00482             }
00483             else
00484             {
00485                 p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift);
00486                 p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift);
00487                 p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift);
00488                 p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift);
00489             }
00490         }
00491     };
00492 
00493     //======================================================comp_op_rgba_dst_out
00494     template<class ColorT, class Order> struct comp_op_rgba_dst_out
00495     {
00496         typedef ColorT color_type;
00497         typedef Order order_type;
00498         typedef typename color_type::value_type value_type;
00499         typedef typename color_type::calc_type calc_type;
00500         enum base_scale_e
00501         { 
00502             base_shift = color_type::base_shift,
00503             base_mask  = color_type::base_mask
00504         };
00505 
00506         // Dca' = Dca.(1 - Sa) 
00507         // Da'  = Da.(1 - Sa) 
00508         static AGG_INLINE void blend_pix(value_type* p, 
00509                                          unsigned, unsigned, unsigned, 
00510                                          unsigned sa, unsigned cover)
00511         {
00512             if(cover < 255)
00513             {
00514                 sa = (sa * cover + 255) >> 8;
00515             }
00516             sa = base_mask - sa;
00517             p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift);
00518             p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift);
00519             p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift);
00520             p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift);
00521         }
00522     };
00523 
00524     //=====================================================comp_op_rgba_src_atop
00525     template<class ColorT, class Order> struct comp_op_rgba_src_atop
00526     {
00527         typedef ColorT color_type;
00528         typedef Order order_type;
00529         typedef typename color_type::value_type value_type;
00530         typedef typename color_type::calc_type calc_type;
00531         enum base_scale_e
00532         { 
00533             base_shift = color_type::base_shift,
00534             base_mask  = color_type::base_mask
00535         };
00536 
00537         // Dca' = Sca.Da + Dca.(1 - Sa)
00538         // Da'  = Da
00539         static AGG_INLINE void blend_pix(value_type* p, 
00540                                          unsigned sr, unsigned sg, unsigned sb, 
00541                                          unsigned sa, unsigned cover)
00542         {
00543             if(cover < 255)
00544             {
00545                 sr = (sr * cover + 255) >> 8;
00546                 sg = (sg * cover + 255) >> 8;
00547                 sb = (sb * cover + 255) >> 8;
00548                 sa = (sa * cover + 255) >> 8;
00549             }
00550             calc_type da = p[Order::A];
00551             sa = base_mask - sa;
00552             p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift);
00553             p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift);
00554             p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift);
00555         }
00556     };
00557 
00558     //=====================================================comp_op_rgba_dst_atop
00559     template<class ColorT, class Order> struct comp_op_rgba_dst_atop
00560     {
00561         typedef ColorT color_type;
00562         typedef Order order_type;
00563         typedef typename color_type::value_type value_type;
00564         typedef typename color_type::calc_type calc_type;
00565         enum base_scale_e
00566         { 
00567             base_shift = color_type::base_shift,
00568             base_mask  = color_type::base_mask
00569         };
00570 
00571         // Dca' = Dca.Sa + Sca.(1 - Da)
00572         // Da'  = Sa 
00573         static AGG_INLINE void blend_pix(value_type* p, 
00574                                          unsigned sr, unsigned sg, unsigned sb, 
00575                                          unsigned sa, unsigned cover)
00576         {
00577             calc_type da = base_mask - p[Order::A];
00578             if(cover < 255)
00579             {
00580                 unsigned alpha = 255 - cover;
00581                 sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift;
00582                 sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift;
00583                 sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift;
00584                 p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8));
00585                 p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8));
00586                 p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8));
00587                 p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8));
00588 
00589             }
00590             else
00591             {
00592                 p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift);
00593                 p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift);
00594                 p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift);
00595                 p[Order::A] = (value_type)sa;
00596             }
00597         }
00598     };
00599 
00600     //=========================================================comp_op_rgba_xor
00601     template<class ColorT, class Order> struct comp_op_rgba_xor
00602     {
00603         typedef ColorT color_type;
00604         typedef Order order_type;
00605         typedef typename color_type::value_type value_type;
00606         typedef typename color_type::calc_type calc_type;
00607         enum base_scale_e
00608         { 
00609             base_shift = color_type::base_shift,
00610             base_mask  = color_type::base_mask
00611         };
00612 
00613         // Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
00614         // Da'  = Sa + Da - 2.Sa.Da 
00615         static AGG_INLINE void blend_pix(value_type* p, 
00616                                          unsigned sr, unsigned sg, unsigned sb, 
00617                                          unsigned sa, unsigned cover)
00618         {
00619             if(cover < 255)
00620             {
00621                 sr = (sr * cover + 255) >> 8;
00622                 sg = (sg * cover + 255) >> 8;
00623                 sb = (sb * cover + 255) >> 8;
00624                 sa = (sa * cover + 255) >> 8;
00625             }
00626             if(sa)
00627             {
00628                 calc_type s1a = base_mask - sa;
00629                 calc_type d1a = base_mask - p[Order::A];
00630                 p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift);
00631                 p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift);
00632                 p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift);
00633                 p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1)));
00634             }
00635         }
00636     };
00637 
00638     //=========================================================comp_op_rgba_plus
00639     template<class ColorT, class Order> struct comp_op_rgba_plus
00640     {
00641         typedef ColorT color_type;
00642         typedef Order order_type;
00643         typedef typename color_type::value_type value_type;
00644         typedef typename color_type::calc_type calc_type;
00645         enum base_scale_e
00646         { 
00647             base_shift = color_type::base_shift,
00648             base_mask  = color_type::base_mask
00649         };
00650 
00651         // Dca' = Sca + Dca
00652         // Da'  = Sa + Da 
00653         static AGG_INLINE void blend_pix(value_type* p, 
00654                                          unsigned sr, unsigned sg, unsigned sb, 
00655                                          unsigned sa, unsigned cover)
00656         {
00657             if(cover < 255)
00658             {
00659                 sr = (sr * cover + 255) >> 8;
00660                 sg = (sg * cover + 255) >> 8;
00661                 sb = (sb * cover + 255) >> 8;
00662                 sa = (sa * cover + 255) >> 8;
00663             }
00664             if(sa)
00665             {
00666                 calc_type dr = p[Order::R] + sr;
00667                 calc_type dg = p[Order::G] + sg;
00668                 calc_type db = p[Order::B] + sb;
00669                 calc_type da = p[Order::A] + sa;
00670                 p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr;
00671                 p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg;
00672                 p[Order::B] = (db > base_mask) ? (value_type)base_mask : db;
00673                 p[Order::A] = (da > base_mask) ? (value_type)base_mask : da;
00674             }
00675         }
00676     };
00677 
00678     //========================================================comp_op_rgba_minus
00679     template<class ColorT, class Order> struct comp_op_rgba_minus
00680     {
00681         typedef ColorT color_type;
00682         typedef Order order_type;
00683         typedef typename color_type::value_type value_type;
00684         typedef typename color_type::calc_type calc_type;
00685         enum base_scale_e
00686         { 
00687             base_shift = color_type::base_shift,
00688             base_mask  = color_type::base_mask
00689         };
00690 
00691         // Dca' = Dca - Sca
00692         // Da' = 1 - (1 - Sa).(1 - Da)
00693         static AGG_INLINE void blend_pix(value_type* p, 
00694                                          unsigned sr, unsigned sg, unsigned sb, 
00695                                          unsigned sa, unsigned cover)
00696         {
00697             if(cover < 255)
00698             {
00699                 sr = (sr * cover + 255) >> 8;
00700                 sg = (sg * cover + 255) >> 8;
00701                 sb = (sb * cover + 255) >> 8;
00702                 sa = (sa * cover + 255) >> 8;
00703             }
00704             if(sa)
00705             {
00706                 calc_type dr = p[Order::R] - sr;
00707                 calc_type dg = p[Order::G] - sg;
00708                 calc_type db = p[Order::B] - sb;
00709                 p[Order::R] = (dr > base_mask) ? 0 : dr;
00710                 p[Order::G] = (dg > base_mask) ? 0 : dg;
00711                 p[Order::B] = (db > base_mask) ? 0 : db;
00712                 p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
00713                 //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift));
00714             }
00715         }
00716     };
00717 
00718     //=====================================================comp_op_rgba_multiply
00719     template<class ColorT, class Order> struct comp_op_rgba_multiply
00720     {
00721         typedef ColorT color_type;
00722         typedef Order order_type;
00723         typedef typename color_type::value_type value_type;
00724         typedef typename color_type::calc_type calc_type;
00725         enum base_scale_e
00726         { 
00727             base_shift = color_type::base_shift,
00728             base_mask  = color_type::base_mask
00729         };
00730 
00731         // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
00732         // Da'  = Sa + Da - Sa.Da 
00733         static AGG_INLINE void blend_pix(value_type* p, 
00734                                          unsigned sr, unsigned sg, unsigned sb, 
00735                                          unsigned sa, unsigned cover)
00736         {
00737             if(cover < 255)
00738             {
00739                 sr = (sr * cover + 255) >> 8;
00740                 sg = (sg * cover + 255) >> 8;
00741                 sb = (sb * cover + 255) >> 8;
00742                 sa = (sa * cover + 255) >> 8;
00743             }
00744             if(sa)
00745             {
00746                 calc_type s1a = base_mask - sa;
00747                 calc_type d1a = base_mask - p[Order::A];
00748                 calc_type dr = p[Order::R];
00749                 calc_type dg = p[Order::G];
00750                 calc_type db = p[Order::B];
00751                 p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift);
00752                 p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift);
00753                 p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift);
00754                 p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
00755             }
00756         }
00757     };
00758 
00759     //=====================================================comp_op_rgba_screen
00760     template<class ColorT, class Order> struct comp_op_rgba_screen
00761     {
00762         typedef ColorT color_type;
00763         typedef Order order_type;
00764         typedef typename color_type::value_type value_type;
00765         typedef typename color_type::calc_type calc_type;
00766         enum base_scale_e
00767         { 
00768             base_shift = color_type::base_shift,
00769             base_mask  = color_type::base_mask
00770         };
00771 
00772         // Dca' = Sca + Dca - Sca.Dca
00773         // Da'  = Sa + Da - Sa.Da 
00774         static AGG_INLINE void blend_pix(value_type* p, 
00775                                          unsigned sr, unsigned sg, unsigned sb, 
00776                                          unsigned sa, unsigned cover)
00777         {
00778             if(cover < 255)
00779             {
00780                 sr = (sr * cover + 255) >> 8;
00781                 sg = (sg * cover + 255) >> 8;
00782                 sb = (sb * cover + 255) >> 8;
00783                 sa = (sa * cover + 255) >> 8;
00784             }
00785             if(sa)
00786             {
00787                 calc_type dr = p[Order::R];
00788                 calc_type dg = p[Order::G];
00789                 calc_type db = p[Order::B];
00790                 calc_type da = p[Order::A];
00791                 p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift));
00792                 p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift));
00793                 p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift));
00794                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
00795             }
00796         }
00797     };
00798 
00799     //=====================================================comp_op_rgba_overlay
00800     template<class ColorT, class Order> struct comp_op_rgba_overlay
00801     {
00802         typedef ColorT color_type;
00803         typedef Order order_type;
00804         typedef typename color_type::value_type value_type;
00805         typedef typename color_type::calc_type calc_type;
00806         enum base_scale_e
00807         { 
00808             base_shift = color_type::base_shift,
00809             base_mask  = color_type::base_mask
00810         };
00811 
00812         // if 2.Dca < Da
00813         //   Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
00814         // otherwise
00815         //   Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
00816         // 
00817         // Da' = Sa + Da - Sa.Da
00818         static AGG_INLINE void blend_pix(value_type* p, 
00819                                          unsigned sr, unsigned sg, unsigned sb, 
00820                                          unsigned sa, unsigned cover)
00821         {
00822             if(cover < 255)
00823             {
00824                 sr = (sr * cover + 255) >> 8;
00825                 sg = (sg * cover + 255) >> 8;
00826                 sb = (sb * cover + 255) >> 8;
00827                 sa = (sa * cover + 255) >> 8;
00828             }
00829             if(sa)
00830             {
00831                 calc_type d1a  = base_mask - p[Order::A];
00832                 calc_type s1a  = base_mask - sa;
00833                 calc_type dr   = p[Order::R];
00834                 calc_type dg   = p[Order::G];
00835                 calc_type db   = p[Order::B];
00836                 calc_type da   = p[Order::A];
00837                 calc_type sada = sa * p[Order::A];
00838 
00839                 p[Order::R] = (value_type)(((2*dr < da) ? 
00840                     2*sr*dr + sr*d1a + dr*s1a : 
00841                     sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
00842 
00843                 p[Order::G] = (value_type)(((2*dg < da) ? 
00844                     2*sg*dg + sg*d1a + dg*s1a : 
00845                     sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
00846 
00847                 p[Order::B] = (value_type)(((2*db < da) ? 
00848                     2*sb*db + sb*d1a + db*s1a : 
00849                     sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
00850 
00851                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
00852             }
00853         }
00854     };
00855 
00856 
00857     template<class T> inline T sd_min(T a, T b) { return (a < b) ? a : b; }
00858     template<class T> inline T sd_max(T a, T b) { return (a > b) ? a : b; }
00859 
00860     //=====================================================comp_op_rgba_darken
00861     template<class ColorT, class Order> struct comp_op_rgba_darken
00862     {
00863         typedef ColorT color_type;
00864         typedef Order order_type;
00865         typedef typename color_type::value_type value_type;
00866         typedef typename color_type::calc_type calc_type;
00867         enum base_scale_e
00868         { 
00869             base_shift = color_type::base_shift,
00870             base_mask  = color_type::base_mask
00871         };
00872 
00873         // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
00874         // Da'  = Sa + Da - Sa.Da 
00875         static AGG_INLINE void blend_pix(value_type* p, 
00876                                          unsigned sr, unsigned sg, unsigned sb, 
00877                                          unsigned sa, unsigned cover)
00878         {
00879             if(cover < 255)
00880             {
00881                 sr = (sr * cover + 255) >> 8;
00882                 sg = (sg * cover + 255) >> 8;
00883                 sb = (sb * cover + 255) >> 8;
00884                 sa = (sa * cover + 255) >> 8;
00885             }
00886             if(sa)
00887             {
00888                 calc_type d1a = base_mask - p[Order::A];
00889                 calc_type s1a = base_mask - sa;
00890                 calc_type dr  = p[Order::R];
00891                 calc_type dg  = p[Order::G];
00892                 calc_type db  = p[Order::B];
00893                 calc_type da  = p[Order::A];
00894 
00895                 p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
00896                 p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
00897                 p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
00898                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
00899             }
00900         }
00901     };
00902 
00903     //=====================================================comp_op_rgba_lighten
00904     template<class ColorT, class Order> struct comp_op_rgba_lighten
00905     {
00906         typedef ColorT color_type;
00907         typedef Order order_type;
00908         typedef typename color_type::value_type value_type;
00909         typedef typename color_type::calc_type calc_type;
00910         enum base_scale_e
00911         { 
00912             base_shift = color_type::base_shift,
00913             base_mask  = color_type::base_mask
00914         };
00915 
00916         // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
00917         // Da'  = Sa + Da - Sa.Da 
00918         static AGG_INLINE void blend_pix(value_type* p, 
00919                                          unsigned sr, unsigned sg, unsigned sb, 
00920                                          unsigned sa, unsigned cover)
00921         {
00922             if(cover < 255)
00923             {
00924                 sr = (sr * cover + 255) >> 8;
00925                 sg = (sg * cover + 255) >> 8;
00926                 sb = (sb * cover + 255) >> 8;
00927                 sa = (sa * cover + 255) >> 8;
00928             }
00929             if(sa)
00930             {
00931                 calc_type d1a = base_mask - p[Order::A];
00932                 calc_type s1a = base_mask - sa;
00933                 calc_type dr  = p[Order::R];
00934                 calc_type dg  = p[Order::G];
00935                 calc_type db  = p[Order::B];
00936                 calc_type da  = p[Order::A];
00937 
00938                 p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
00939                 p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
00940                 p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
00941                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
00942             }
00943         }
00944     };
00945 
00946     //=====================================================comp_op_rgba_color_dodge
00947     template<class ColorT, class Order> struct comp_op_rgba_color_dodge
00948     {
00949         typedef ColorT color_type;
00950         typedef Order order_type;
00951         typedef typename color_type::value_type value_type;
00952         typedef typename color_type::calc_type calc_type;
00953         typedef typename color_type::long_type long_type;
00954         enum base_scale_e
00955         { 
00956             base_shift = color_type::base_shift,
00957             base_mask  = color_type::base_mask
00958         };
00959 
00960         // if Sca.Da + Dca.Sa >= Sa.Da
00961         //   Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
00962         // otherwise
00963         //   Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
00964         //
00965         // Da'  = Sa + Da - Sa.Da 
00966         static AGG_INLINE void blend_pix(value_type* p, 
00967                                          unsigned sr, unsigned sg, unsigned sb, 
00968                                          unsigned sa, unsigned cover)
00969         {
00970             if(cover < 255)
00971             {
00972                 sr = (sr * cover + 255) >> 8;
00973                 sg = (sg * cover + 255) >> 8;
00974                 sb = (sb * cover + 255) >> 8;
00975                 sa = (sa * cover + 255) >> 8;
00976             }
00977             if(sa)
00978             {
00979                 calc_type d1a  = base_mask - p[Order::A];
00980                 calc_type s1a  = base_mask - sa;
00981                 calc_type dr   = p[Order::R];
00982                 calc_type dg   = p[Order::G];
00983                 calc_type db   = p[Order::B];
00984                 calc_type da   = p[Order::A];
00985                 long_type drsa = dr * sa;
00986                 long_type dgsa = dg * sa;
00987                 long_type dbsa = db * sa;
00988                 long_type srda = sr * da;
00989                 long_type sgda = sg * da;
00990                 long_type sbda = sb * da;
00991                 long_type sada = sa * da;
00992 
00993                 p[Order::R] = (value_type)((srda + drsa >= sada) ? 
00994                     (sada + sr * d1a + dr * s1a + base_mask) >> base_shift :
00995                     drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift));
00996 
00997                 p[Order::G] = (value_type)((sgda + dgsa >= sada) ? 
00998                     (sada + sg * d1a + dg * s1a + base_mask) >> base_shift :
00999                     dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift));
01000 
01001                 p[Order::B] = (value_type)((sbda + dbsa >= sada) ? 
01002                     (sada + sb * d1a + db * s1a + base_mask) >> base_shift :
01003                     dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift));
01004 
01005                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
01006             }
01007         }
01008     };
01009 
01010     //=====================================================comp_op_rgba_color_burn
01011     template<class ColorT, class Order> struct comp_op_rgba_color_burn
01012     {
01013         typedef ColorT color_type;
01014         typedef Order order_type;
01015         typedef typename color_type::value_type value_type;
01016         typedef typename color_type::calc_type calc_type;
01017         typedef typename color_type::long_type long_type;
01018         enum base_scale_e
01019         { 
01020             base_shift = color_type::base_shift,
01021             base_mask  = color_type::base_mask
01022         };
01023 
01024         // if Sca.Da + Dca.Sa <= Sa.Da
01025         //   Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
01026         // otherwise
01027         //   Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
01028         // 
01029         // Da'  = Sa + Da - Sa.Da 
01030         static AGG_INLINE void blend_pix(value_type* p, 
01031                                          unsigned sr, unsigned sg, unsigned sb, 
01032                                          unsigned sa, unsigned cover)
01033         {
01034             if(cover < 255)
01035             {
01036                 sr = (sr * cover + 255) >> 8;
01037                 sg = (sg * cover + 255) >> 8;
01038                 sb = (sb * cover + 255) >> 8;
01039                 sa = (sa * cover + 255) >> 8;
01040             }
01041             if(sa)
01042             {
01043                 calc_type d1a  = base_mask - p[Order::A];
01044                 calc_type s1a  = base_mask - sa;
01045                 calc_type dr   = p[Order::R];
01046                 calc_type dg   = p[Order::G];
01047                 calc_type db   = p[Order::B];
01048                 calc_type da   = p[Order::A];
01049                 long_type drsa = dr * sa;
01050                 long_type dgsa = dg * sa;
01051                 long_type dbsa = db * sa;
01052                 long_type srda = sr * da;
01053                 long_type sgda = sg * da;
01054                 long_type sbda = sb * da;
01055                 long_type sada = sa * da;
01056 
01057                 p[Order::R] = (value_type)(((srda + drsa <= sada) ? 
01058                     sr * d1a + dr * s1a :
01059                     sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift);
01060 
01061                 p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? 
01062                     sg * d1a + dg * s1a :
01063                     sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift);
01064 
01065                 p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? 
01066                     sb * d1a + db * s1a :
01067                     sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift);
01068 
01069                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
01070             }
01071         }
01072     };
01073 
01074     //=====================================================comp_op_rgba_hard_light
01075     template<class ColorT, class Order> struct comp_op_rgba_hard_light
01076     {
01077         typedef ColorT color_type;
01078         typedef Order order_type;
01079         typedef typename color_type::value_type value_type;
01080         typedef typename color_type::calc_type calc_type;
01081         typedef typename color_type::long_type long_type;
01082         enum base_scale_e
01083         { 
01084             base_shift = color_type::base_shift,
01085             base_mask  = color_type::base_mask
01086         };
01087 
01088         // if 2.Sca < Sa
01089         //    Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
01090         // otherwise
01091         //    Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
01092         // 
01093         // Da'  = Sa + Da - Sa.Da
01094         static AGG_INLINE void blend_pix(value_type* p, 
01095                                          unsigned sr, unsigned sg, unsigned sb, 
01096                                          unsigned sa, unsigned cover)
01097         {
01098             if(cover < 255)
01099             {
01100                 sr = (sr * cover + 255) >> 8;
01101                 sg = (sg * cover + 255) >> 8;
01102                 sb = (sb * cover + 255) >> 8;
01103                 sa = (sa * cover + 255) >> 8;
01104             }
01105             if(sa)
01106             {
01107                 calc_type d1a  = base_mask - p[Order::A];
01108                 calc_type s1a  = base_mask - sa;
01109                 calc_type dr   = p[Order::R];
01110                 calc_type dg   = p[Order::G];
01111                 calc_type db   = p[Order::B];
01112                 calc_type da   = p[Order::A];
01113                 calc_type sada = sa * da;
01114 
01115                 p[Order::R] = (value_type)(((2*sr < sa) ? 
01116                     2*sr*dr + sr*d1a + dr*s1a : 
01117                     sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
01118 
01119                 p[Order::G] = (value_type)(((2*sg < sa) ? 
01120                     2*sg*dg + sg*d1a + dg*s1a : 
01121                     sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
01122 
01123                 p[Order::B] = (value_type)(((2*sb < sa) ? 
01124                     2*sb*db + sb*d1a + db*s1a : 
01125                     sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
01126 
01127                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
01128             }
01129         }
01130     };
01131 
01132     //=====================================================comp_op_rgba_soft_light
01133     template<class ColorT, class Order> struct comp_op_rgba_soft_light
01134     {
01135         typedef ColorT color_type;
01136         typedef Order order_type;
01137         typedef typename color_type::value_type value_type;
01138         typedef typename color_type::calc_type calc_type;
01139         typedef typename color_type::long_type long_type;
01140         enum base_scale_e
01141         { 
01142             base_shift = color_type::base_shift,
01143             base_mask  = color_type::base_mask
01144         };
01145 
01146         // if 2.Sca < Sa
01147         //   Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
01148         // otherwise if 8.Dca <= Da
01149         //   Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
01150         // otherwise
01151         //   Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
01152         // 
01153         // Da'  = Sa + Da - Sa.Da 
01154 
01155         static AGG_INLINE void blend_pix(value_type* p, 
01156                                          unsigned r, unsigned g, unsigned b, 
01157                                          unsigned a, unsigned cover)
01158         {
01159             double sr = double(r * cover) / (base_mask * 255);
01160             double sg = double(g * cover) / (base_mask * 255);
01161             double sb = double(b * cover) / (base_mask * 255);
01162             double sa = double(a * cover) / (base_mask * 255);
01163             if(sa > 0)
01164             {
01165                 double dr = double(p[Order::R]) / base_mask;
01166                 double dg = double(p[Order::G]) / base_mask;
01167                 double db = double(p[Order::B]) / base_mask;
01168                 double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask;
01169                 if(cover < 255)
01170                 {
01171                     a = (a * cover + 255) >> 8;
01172                 }
01173 
01174                 if(2*sr < sa)       dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa);
01175                 else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa);
01176                 else                dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa);
01177 
01178                 if(2*sg < sa)       dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa);
01179                 else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa);
01180                 else                dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa);
01181 
01182                 if(2*sb < sa)       db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa);
01183                 else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa);
01184                 else                db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa);
01185 
01186                 p[Order::R] = (value_type)uround(dr * base_mask);
01187                 p[Order::G] = (value_type)uround(dg * base_mask);
01188                 p[Order::B] = (value_type)uround(db * base_mask);
01189                 p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift));
01190             }
01191         }
01192     };
01193 
01194     //=====================================================comp_op_rgba_difference
01195     template<class ColorT, class Order> struct comp_op_rgba_difference
01196     {
01197         typedef ColorT color_type;
01198         typedef Order order_type;
01199         typedef typename color_type::value_type value_type;
01200         typedef typename color_type::calc_type calc_type;
01201         typedef typename color_type::long_type long_type;
01202         enum base_scale_e
01203         { 
01204             base_shift = color_type::base_shift,
01205             base_scale = color_type::base_scale,
01206             base_mask  = color_type::base_mask
01207         };
01208 
01209         // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
01210         // Da'  = Sa + Da - Sa.Da 
01211         static AGG_INLINE void blend_pix(value_type* p, 
01212                                          unsigned sr, unsigned sg, unsigned sb, 
01213                                          unsigned sa, unsigned cover)
01214         {
01215             if(cover < 255)
01216             {
01217                 sr = (sr * cover + 255) >> 8;
01218                 sg = (sg * cover + 255) >> 8;
01219                 sb = (sb * cover + 255) >> 8;
01220                 sa = (sa * cover + 255) >> 8;
01221             }
01222             if(sa)
01223             {
01224                 calc_type dr = p[Order::R];
01225                 calc_type dg = p[Order::G];
01226                 calc_type db = p[Order::B];
01227                 calc_type da = p[Order::A];
01228                 p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift));
01229                 p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift));
01230                 p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift));
01231                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
01232             }
01233         }
01234     };
01235 
01236     //=====================================================comp_op_rgba_exclusion
01237     template<class ColorT, class Order> struct comp_op_rgba_exclusion
01238     {
01239         typedef ColorT color_type;
01240         typedef Order order_type;
01241         typedef typename color_type::value_type value_type;
01242         typedef typename color_type::calc_type calc_type;
01243         typedef typename color_type::long_type long_type;
01244         enum base_scale_e
01245         { 
01246             base_shift = color_type::base_shift,
01247             base_mask  = color_type::base_mask
01248         };
01249 
01250         // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
01251         // Da'  = Sa + Da - Sa.Da 
01252         static AGG_INLINE void blend_pix(value_type* p, 
01253                                          unsigned sr, unsigned sg, unsigned sb, 
01254                                          unsigned sa, unsigned cover)
01255         {
01256             if(cover < 255)
01257             {
01258                 sr = (sr * cover + 255) >> 8;
01259                 sg = (sg * cover + 255) >> 8;
01260                 sb = (sb * cover + 255) >> 8;
01261                 sa = (sa * cover + 255) >> 8;
01262             }
01263             if(sa)
01264             {
01265                 calc_type d1a = base_mask - p[Order::A];
01266                 calc_type s1a = base_mask - sa;
01267                 calc_type dr = p[Order::R];
01268                 calc_type dg = p[Order::G];
01269                 calc_type db = p[Order::B];
01270                 calc_type da = p[Order::A];
01271                 p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift);
01272                 p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift);
01273                 p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift);
01274                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
01275             }
01276         }
01277     };
01278 
01279     //=====================================================comp_op_rgba_contrast
01280     template<class ColorT, class Order> struct comp_op_rgba_contrast
01281     {
01282         typedef ColorT color_type;
01283         typedef Order order_type;
01284         typedef typename color_type::value_type value_type;
01285         typedef typename color_type::calc_type calc_type;
01286         typedef typename color_type::long_type long_type;
01287         enum base_scale_e
01288         { 
01289             base_shift = color_type::base_shift,
01290             base_mask  = color_type::base_mask
01291         };
01292 
01293 
01294         static AGG_INLINE void blend_pix(value_type* p, 
01295                                          unsigned sr, unsigned sg, unsigned sb, 
01296                                          unsigned sa, unsigned cover)
01297         {
01298             if(cover < 255)
01299             {
01300                 sr = (sr * cover + 255) >> 8;
01301                 sg = (sg * cover + 255) >> 8;
01302                 sb = (sb * cover + 255) >> 8;
01303                 sa = (sa * cover + 255) >> 8;
01304             }
01305             long_type dr = p[Order::R];
01306             long_type dg = p[Order::G];
01307             long_type db = p[Order::B];
01308             int       da = p[Order::A];
01309             long_type d2a = da >> 1;
01310             unsigned s2a = sa >> 1;
01311 
01312             int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); 
01313             int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); 
01314             int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); 
01315 
01316             r = (r < 0) ? 0 : r;
01317             g = (g < 0) ? 0 : g;
01318             b = (b < 0) ? 0 : b;
01319 
01320             p[Order::R] = (value_type)((r > da) ? da : r);
01321             p[Order::G] = (value_type)((g > da) ? da : g);
01322             p[Order::B] = (value_type)((b > da) ? da : b);
01323         }
01324     };
01325 
01326     //=====================================================comp_op_rgba_invert
01327     template<class ColorT, class Order> struct comp_op_rgba_invert
01328     {
01329         typedef ColorT color_type;
01330         typedef Order order_type;
01331         typedef typename color_type::value_type value_type;
01332         typedef typename color_type::calc_type calc_type;
01333         typedef typename color_type::long_type long_type;
01334         enum base_scale_e
01335         { 
01336             base_shift = color_type::base_shift,
01337             base_mask  = color_type::base_mask
01338         };
01339 
01340         // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa)
01341         // Da'  = Sa + Da - Sa.Da 
01342         static AGG_INLINE void blend_pix(value_type* p, 
01343                                          unsigned sr, unsigned sg, unsigned sb, 
01344                                          unsigned sa, unsigned cover)
01345         {
01346             sa = (sa * cover + 255) >> 8;
01347             if(sa)
01348             {
01349                 calc_type da = p[Order::A];
01350                 calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift;
01351                 calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift;
01352                 calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift;
01353                 calc_type s1a = base_mask - sa;
01354                 p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
01355                 p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
01356                 p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
01357                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
01358             }
01359         }
01360     };
01361 
01362     //=================================================comp_op_rgba_invert_rgb
01363     template<class ColorT, class Order> struct comp_op_rgba_invert_rgb
01364     {
01365         typedef ColorT color_type;
01366         typedef Order order_type;
01367         typedef typename color_type::value_type value_type;
01368         typedef typename color_type::calc_type calc_type;
01369         typedef typename color_type::long_type long_type;
01370         enum base_scale_e
01371         { 
01372             base_shift = color_type::base_shift,
01373             base_mask  = color_type::base_mask
01374         };
01375 
01376         // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa)
01377         // Da'  = Sa + Da - Sa.Da 
01378         static AGG_INLINE void blend_pix(value_type* p, 
01379                                          unsigned sr, unsigned sg, unsigned sb, 
01380                                          unsigned sa, unsigned cover)
01381         {
01382             if(cover < 255)
01383             {
01384                 sr = (sr * cover + 255) >> 8;
01385                 sg = (sg * cover + 255) >> 8;
01386                 sb = (sb * cover + 255) >> 8;
01387                 sa = (sa * cover + 255) >> 8;
01388             }
01389             if(sa)
01390             {
01391                 calc_type da = p[Order::A];
01392                 calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift;
01393                 calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift;
01394                 calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift;
01395                 calc_type s1a = base_mask - sa;
01396                 p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
01397                 p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
01398                 p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
01399                 p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
01400             }
01401         }
01402     };
01403 
01404 
01405 
01406 
01407 
01408     //======================================================comp_op_table_rgba
01409     template<class ColorT, class Order> struct comp_op_table_rgba
01410     {
01411         typedef typename ColorT::value_type value_type;
01412         typedef void (*comp_op_func_type)(value_type* p, 
01413                                           unsigned cr, 
01414                                           unsigned cg, 
01415                                           unsigned cb,
01416                                           unsigned ca,
01417                                           unsigned cover);
01418         static comp_op_func_type g_comp_op_func[];
01419     };
01420 
01421     //==========================================================g_comp_op_func
01422     template<class ColorT, class Order> 
01423     typename comp_op_table_rgba<ColorT, Order>::comp_op_func_type
01424     comp_op_table_rgba<ColorT, Order>::g_comp_op_func[] = 
01425     {
01426         comp_op_rgba_clear      <ColorT,Order>::blend_pix,
01427         comp_op_rgba_src        <ColorT,Order>::blend_pix,
01428         comp_op_rgba_dst        <ColorT,Order>::blend_pix,
01429         comp_op_rgba_src_over   <ColorT,Order>::blend_pix,
01430         comp_op_rgba_dst_over   <ColorT,Order>::blend_pix,
01431         comp_op_rgba_src_in     <ColorT,Order>::blend_pix,
01432         comp_op_rgba_dst_in     <ColorT,Order>::blend_pix,
01433         comp_op_rgba_src_out    <ColorT,Order>::blend_pix,
01434         comp_op_rgba_dst_out    <ColorT,Order>::blend_pix,
01435         comp_op_rgba_src_atop   <ColorT,Order>::blend_pix,
01436         comp_op_rgba_dst_atop   <ColorT,Order>::blend_pix,
01437         comp_op_rgba_xor        <ColorT,Order>::blend_pix,
01438         comp_op_rgba_plus       <ColorT,Order>::blend_pix,
01439         comp_op_rgba_minus      <ColorT,Order>::blend_pix,
01440         comp_op_rgba_multiply   <ColorT,Order>::blend_pix,
01441         comp_op_rgba_screen     <ColorT,Order>::blend_pix,
01442         comp_op_rgba_overlay    <ColorT,Order>::blend_pix,
01443         comp_op_rgba_darken     <ColorT,Order>::blend_pix,
01444         comp_op_rgba_lighten    <ColorT,Order>::blend_pix,
01445         comp_op_rgba_color_dodge<ColorT,Order>::blend_pix,
01446         comp_op_rgba_color_burn <ColorT,Order>::blend_pix,
01447         comp_op_rgba_hard_light <ColorT,Order>::blend_pix,
01448         comp_op_rgba_soft_light <ColorT,Order>::blend_pix,
01449         comp_op_rgba_difference <ColorT,Order>::blend_pix,
01450         comp_op_rgba_exclusion  <ColorT,Order>::blend_pix,
01451         comp_op_rgba_contrast   <ColorT,Order>::blend_pix,
01452         comp_op_rgba_invert     <ColorT,Order>::blend_pix,
01453         comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix,
01454         0
01455     };
01456 
01457 
01458     //==============================================================comp_op_e
01459     enum comp_op_e
01460     {
01461         comp_op_clear,         //----comp_op_clear
01462         comp_op_src,           //----comp_op_src
01463         comp_op_dst,           //----comp_op_dst
01464         comp_op_src_over,      //----comp_op_src_over
01465         comp_op_dst_over,      //----comp_op_dst_over
01466         comp_op_src_in,        //----comp_op_src_in
01467         comp_op_dst_in,        //----comp_op_dst_in
01468         comp_op_src_out,       //----comp_op_src_out
01469         comp_op_dst_out,       //----comp_op_dst_out
01470         comp_op_src_atop,      //----comp_op_src_atop
01471         comp_op_dst_atop,      //----comp_op_dst_atop
01472         comp_op_xor,           //----comp_op_xor
01473         comp_op_plus,          //----comp_op_plus
01474         comp_op_minus,         //----comp_op_minus
01475         comp_op_multiply,      //----comp_op_multiply
01476         comp_op_screen,        //----comp_op_screen
01477         comp_op_overlay,       //----comp_op_overlay
01478         comp_op_darken,        //----comp_op_darken
01479         comp_op_lighten,       //----comp_op_lighten
01480         comp_op_color_dodge,   //----comp_op_color_dodge
01481         comp_op_color_burn,    //----comp_op_color_burn
01482         comp_op_hard_light,    //----comp_op_hard_light
01483         comp_op_soft_light,    //----comp_op_soft_light
01484         comp_op_difference,    //----comp_op_difference
01485         comp_op_exclusion,     //----comp_op_exclusion
01486         comp_op_contrast,      //----comp_op_contrast
01487         comp_op_invert,        //----comp_op_invert
01488         comp_op_invert_rgb,    //----comp_op_invert_rgb
01489 
01490         end_of_comp_op_e
01491     };
01492 
01493 
01494 
01495 
01496 
01497 
01498 
01499     //====================================================comp_op_adaptor_rgba
01500     template<class ColorT, class Order> struct comp_op_adaptor_rgba
01501     {
01502         typedef Order  order_type;
01503         typedef ColorT color_type;
01504         typedef typename color_type::value_type value_type;
01505         enum base_scale_e
01506         {  
01507             base_shift = color_type::base_shift,
01508             base_mask  = color_type::base_mask 
01509         };
01510 
01511         static AGG_INLINE void blend_pix(unsigned op, value_type* p, 
01512                                          unsigned cr, unsigned cg, unsigned cb,
01513                                          unsigned ca,
01514                                          unsigned cover)
01515         {
01516             comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
01517                 (p, (cr * ca + base_mask) >> base_shift, 
01518                     (cg * ca + base_mask) >> base_shift,
01519                     (cb * ca + base_mask) >> base_shift,
01520                      ca, cover);
01521         }
01522     };
01523 
01524     //=========================================comp_op_adaptor_clip_to_dst_rgba
01525     template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba
01526     {
01527         typedef Order  order_type;
01528         typedef ColorT color_type;
01529         typedef typename color_type::value_type value_type;
01530         enum base_scale_e
01531         {  
01532             base_shift = color_type::base_shift,
01533             base_mask  = color_type::base_mask 
01534         };
01535 
01536         static AGG_INLINE void blend_pix(unsigned op, value_type* p, 
01537                                          unsigned cr, unsigned cg, unsigned cb,
01538                                          unsigned ca,
01539                                          unsigned cover)
01540         {
01541             cr = (cr * ca + base_mask) >> base_shift;
01542             cg = (cg * ca + base_mask) >> base_shift;
01543             cb = (cb * ca + base_mask) >> base_shift;
01544             unsigned da = p[Order::A];
01545             comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
01546                 (p, (cr * da + base_mask) >> base_shift, 
01547                     (cg * da + base_mask) >> base_shift, 
01548                     (cb * da + base_mask) >> base_shift, 
01549                     (ca * da + base_mask) >> base_shift, 
01550                     cover);
01551         }
01552     };
01553 
01554     //================================================comp_op_adaptor_rgba_pre
01555     template<class ColorT, class Order> struct comp_op_adaptor_rgba_pre
01556     {
01557         typedef Order  order_type;
01558         typedef ColorT color_type;
01559         typedef typename color_type::value_type value_type;
01560         enum base_scale_e
01561         {  
01562             base_shift = color_type::base_shift,
01563             base_mask  = color_type::base_mask 
01564         };
01565 
01566         static AGG_INLINE void blend_pix(unsigned op, value_type* p, 
01567                                          unsigned cr, unsigned cg, unsigned cb,
01568                                          unsigned ca,
01569                                          unsigned cover)
01570         {
01571             comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p, cr, cg, cb, ca, cover);
01572         }
01573     };
01574 
01575     //=====================================comp_op_adaptor_clip_to_dst_rgba_pre
01576     template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba_pre
01577     {
01578         typedef Order  order_type;
01579         typedef ColorT color_type;
01580         typedef typename color_type::value_type value_type;
01581         enum base_scale_e
01582         {  
01583             base_shift = color_type::base_shift,
01584             base_mask  = color_type::base_mask 
01585         };
01586 
01587         static AGG_INLINE void blend_pix(unsigned op, value_type* p, 
01588                                          unsigned cr, unsigned cg, unsigned cb,
01589                                          unsigned ca,
01590                                          unsigned cover)
01591         {
01592             unsigned da = p[Order::A];
01593             comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
01594                 (p, (cr * da + base_mask) >> base_shift, 
01595                     (cg * da + base_mask) >> base_shift, 
01596                     (cb * da + base_mask) >> base_shift, 
01597                     (ca * da + base_mask) >> base_shift, 
01598                     cover);
01599         }
01600     };
01601 
01602     //=======================================================comp_adaptor_rgba
01603     template<class BlenderPre> struct comp_adaptor_rgba
01604     {
01605         typedef typename BlenderPre::order_type order_type;
01606         typedef typename BlenderPre::color_type color_type;
01607         typedef typename color_type::value_type value_type;
01608         enum base_scale_e
01609         {  
01610             base_shift = color_type::base_shift,
01611             base_mask  = color_type::base_mask 
01612         };
01613 
01614         static AGG_INLINE void blend_pix(unsigned op, value_type* p, 
01615                                          unsigned cr, unsigned cg, unsigned cb,
01616                                          unsigned ca,
01617                                          unsigned cover)
01618         {
01619             BlenderPre::blend_pix(p, 
01620                                   (cr * ca + base_mask) >> base_shift, 
01621                                   (cg * ca + base_mask) >> base_shift,
01622                                   (cb * ca + base_mask) >> base_shift,
01623                                   ca, cover);
01624         }
01625     };
01626 
01627     //==========================================comp_adaptor_clip_to_dst_rgba
01628     template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba
01629     {
01630         typedef typename BlenderPre::order_type order_type;
01631         typedef typename BlenderPre::color_type color_type;
01632         typedef typename color_type::value_type value_type;
01633         enum base_scale_e
01634         {  
01635             base_shift = color_type::base_shift,
01636             base_mask  = color_type::base_mask 
01637         };
01638 
01639         static AGG_INLINE void blend_pix(unsigned op, value_type* p, 
01640                                          unsigned cr, unsigned cg, unsigned cb,
01641                                          unsigned ca,
01642                                          unsigned cover)
01643         {
01644             cr = (cr * ca + base_mask) >> base_shift;
01645             cg = (cg * ca + base_mask) >> base_shift;
01646             cb = (cb * ca + base_mask) >> base_shift;
01647             unsigned da = p[order_type::A];
01648             BlenderPre::blend_pix(p, 
01649                                   (cr * da + base_mask) >> base_shift, 
01650                                   (cg * da + base_mask) >> base_shift, 
01651                                   (cb * da + base_mask) >> base_shift, 
01652                                   (ca * da + base_mask) >> base_shift, 
01653                                   cover);
01654         }
01655     };
01656 
01657     //======================================comp_adaptor_clip_to_dst_rgba_pre
01658     template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba_pre
01659     {
01660         typedef typename BlenderPre::order_type order_type;
01661         typedef typename BlenderPre::color_type color_type;
01662         typedef typename color_type::value_type value_type;
01663         enum base_scale_e
01664         {  
01665             base_shift = color_type::base_shift,
01666             base_mask  = color_type::base_mask 
01667         };
01668 
01669         static AGG_INLINE void blend_pix(unsigned op, value_type* p, 
01670                                          unsigned cr, unsigned cg, unsigned cb,
01671                                          unsigned ca,
01672                                          unsigned cover)
01673         {
01674             unsigned da = p[order_type::A];
01675             BlenderPre::blend_pix(p, 
01676                                   (cr * da + base_mask) >> base_shift, 
01677                                   (cg * da + base_mask) >> base_shift, 
01678                                   (cb * da + base_mask) >> base_shift, 
01679                                   (ca * da + base_mask) >> base_shift, 
01680                                   cover);
01681         }
01682     };
01683 
01684 
01685 
01686 
01687 
01688 
01689     //===============================================copy_or_blend_rgba_wrapper
01690     template<class Blender> struct copy_or_blend_rgba_wrapper
01691     {
01692         typedef typename Blender::color_type color_type;
01693         typedef typename Blender::order_type order_type;
01694         typedef typename color_type::value_type value_type;
01695         typedef typename color_type::calc_type calc_type;
01696         enum base_scale_e
01697         {
01698             base_shift = color_type::base_shift,
01699             base_scale = color_type::base_scale,
01700             base_mask  = color_type::base_mask
01701         };
01702 
01703         //--------------------------------------------------------------------
01704         static AGG_INLINE void copy_or_blend_pix(value_type* p, 
01705                                                  unsigned cr, unsigned cg, unsigned cb,
01706                                                  unsigned alpha)
01707         {
01708             if(alpha)
01709             {
01710                 if(alpha == base_mask)
01711                 {
01712                     p[order_type::R] = cr;
01713                     p[order_type::G] = cg;
01714                     p[order_type::B] = cb;
01715                     p[order_type::A] = base_mask;
01716                 }
01717                 else
01718                 {
01719                     Blender::blend_pix(p, cr, cg, cb, alpha);
01720                 }
01721             }
01722         }
01723 
01724         //--------------------------------------------------------------------
01725         static AGG_INLINE void copy_or_blend_pix(value_type* p, 
01726                                                  unsigned cr, unsigned cg, unsigned cb,
01727                                                  unsigned alpha,
01728                                                  unsigned cover)
01729         {
01730             if(cover == 255)
01731             {
01732                 copy_or_blend_pix(p, cr, cg, cb, alpha);
01733             }
01734             else
01735             {
01736                 if(alpha)
01737                 {
01738                     alpha = (alpha * (cover + 1)) >> 8;
01739                     if(alpha == base_mask)
01740                     {
01741                         p[order_type::R] = cr;
01742                         p[order_type::G] = cg;
01743                         p[order_type::B] = cb;
01744                         p[order_type::A] = base_mask;
01745                     }
01746                     else
01747                     {
01748                         Blender::blend_pix(p, cr, cg, cb, alpha, cover);
01749                     }
01750                 }
01751             }
01752         }
01753     };
01754 
01755 
01756 
01757 
01758 
01759     
01760     //=================================================pixfmt_alpha_blend_rgba
01761     template<class Blender, class RenBuf, class PixelT = int32u> 
01762     class pixfmt_alpha_blend_rgba
01763     {
01764     public:
01765         typedef RenBuf   rbuf_type;
01766         typedef typename rbuf_type::row_data row_data;
01767         typedef PixelT   pixel_type;
01768         typedef Blender  blender_type;
01769         typedef typename blender_type::color_type color_type;
01770         typedef typename blender_type::order_type order_type;
01771         typedef typename color_type::value_type value_type;
01772         typedef typename color_type::calc_type calc_type;
01773         typedef copy_or_blend_rgba_wrapper<blender_type> cob_type;
01774         enum base_scale_e
01775         {
01776             base_shift = color_type::base_shift,
01777             base_scale = color_type::base_scale,
01778             base_mask  = color_type::base_mask,
01779             pix_width  = sizeof(pixel_type)
01780         };
01781 
01782         //--------------------------------------------------------------------
01783         pixfmt_alpha_blend_rgba() : m_rbuf(0) {}
01784         explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
01785         void attach(rbuf_type& rb) { m_rbuf = &rb; }
01786 
01787         //--------------------------------------------------------------------
01788         template<class PixFmt>
01789         bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
01790         {
01791             rect_i r(x1, y1, x2, y2);
01792             if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
01793             {
01794                 int stride = pixf.stride();
01795                 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 
01796                                (r.x2 - r.x1) + 1,
01797                                (r.y2 - r.y1) + 1,
01798                                stride);
01799                 return true;
01800             }
01801             return false;
01802         }
01803 
01804         //--------------------------------------------------------------------
01805         AGG_INLINE unsigned width()  const { return m_rbuf->width();  }
01806         AGG_INLINE unsigned height() const { return m_rbuf->height(); }
01807         AGG_INLINE int      stride() const { return m_rbuf->stride(); }
01808 
01809         //--------------------------------------------------------------------
01810         AGG_INLINE       int8u* row_ptr(int y)       { return m_rbuf->row_ptr(y); }
01811         AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
01812         AGG_INLINE row_data     row(int y)     const { return m_rbuf->row(y); }
01813 
01814         //--------------------------------------------------------------------
01815         AGG_INLINE int8u* pix_ptr(int x, int y)
01816         {
01817             return m_rbuf->row_ptr(y) + x * pix_width;
01818         }
01819 
01820         AGG_INLINE const int8u* pix_ptr(int x, int y) const
01821         {
01822             return m_rbuf->row_ptr(y) + x * pix_width;
01823         }
01824 
01825 
01826         //--------------------------------------------------------------------
01827         AGG_INLINE static void make_pix(int8u* p, const color_type& c)
01828         {
01829             ((value_type*)p)[order_type::R] = c.r;
01830             ((value_type*)p)[order_type::G] = c.g;
01831             ((value_type*)p)[order_type::B] = c.b;
01832             ((value_type*)p)[order_type::A] = c.a;
01833         }
01834 
01835         //--------------------------------------------------------------------
01836         AGG_INLINE color_type pixel(int x, int y) const
01837         {
01838             const value_type* p = (const value_type*)m_rbuf->row_ptr(y);
01839             if(p)
01840             {
01841                 p += x << 2;
01842                 return color_type(p[order_type::R], 
01843                                   p[order_type::G], 
01844                                   p[order_type::B], 
01845                                   p[order_type::A]);
01846             }
01847             return color_type::no_color();
01848         }
01849 
01850         //--------------------------------------------------------------------
01851         AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
01852         {
01853             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2);
01854             p[order_type::R] = c.r;
01855             p[order_type::G] = c.g;
01856             p[order_type::B] = c.b;
01857             p[order_type::A] = c.a;
01858         }
01859 
01860         //--------------------------------------------------------------------
01861         AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
01862         {
01863             cob_type::copy_or_blend_pix(
01864                 (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), 
01865                 c.r, c.g, c.b, c.a, 
01866                 cover);
01867         }
01868 
01869 
01870         //--------------------------------------------------------------------
01871         AGG_INLINE void copy_hline(int x, int y, 
01872                                    unsigned len, 
01873                                    const color_type& c)
01874         {
01875             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
01876             pixel_type v;
01877             ((value_type*)&v)[order_type::R] = c.r;
01878             ((value_type*)&v)[order_type::G] = c.g;
01879             ((value_type*)&v)[order_type::B] = c.b;
01880             ((value_type*)&v)[order_type::A] = c.a;
01881             do
01882             {
01883                 *(pixel_type*)p = v;
01884                 p += 4;
01885             }
01886             while(--len);
01887         }
01888 
01889 
01890         //--------------------------------------------------------------------
01891         AGG_INLINE void copy_vline(int x, int y,
01892                                    unsigned len, 
01893                                    const color_type& c)
01894         {
01895             pixel_type v;
01896             ((value_type*)&v)[order_type::R] = c.r;
01897             ((value_type*)&v)[order_type::G] = c.g;
01898             ((value_type*)&v)[order_type::B] = c.b;
01899             ((value_type*)&v)[order_type::A] = c.a;
01900             do
01901             {
01902                 value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
01903                 *(pixel_type*)p = v;
01904             }
01905             while(--len);
01906         }
01907 
01908 
01909         //--------------------------------------------------------------------
01910         void blend_hline(int x, int y,
01911                          unsigned len, 
01912                          const color_type& c,
01913                          int8u cover)
01914         {
01915             if (c.a)
01916             {
01917                 value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
01918                 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
01919                 if(alpha == base_mask)
01920                 {
01921                     pixel_type v;
01922                     ((value_type*)&v)[order_type::R] = c.r;
01923                     ((value_type*)&v)[order_type::G] = c.g;
01924                     ((value_type*)&v)[order_type::B] = c.b;
01925                     ((value_type*)&v)[order_type::A] = c.a;
01926                     do
01927                     {
01928                         *(pixel_type*)p = v;
01929                         p += 4;
01930                     }
01931                     while(--len);
01932                 }
01933                 else
01934                 {
01935                     if(cover == 255)
01936                     {
01937                         do
01938                         {
01939                             blender_type::blend_pix(p, c.r, c.g, c.b, alpha);
01940                             p += 4;
01941                         }
01942                         while(--len);
01943                     }
01944                     else
01945                     {
01946                         do
01947                         {
01948                             blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
01949                             p += 4;
01950                         }
01951                         while(--len);
01952                     }
01953                 }
01954             }
01955         }
01956 
01957 
01958         //--------------------------------------------------------------------
01959         void blend_vline(int x, int y,
01960                          unsigned len, 
01961                          const color_type& c,
01962                          int8u cover)
01963         {
01964             if (c.a)
01965             {
01966                 value_type* p;
01967                 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
01968                 if(alpha == base_mask)
01969                 {
01970                     pixel_type v;
01971                     ((value_type*)&v)[order_type::R] = c.r;
01972                     ((value_type*)&v)[order_type::G] = c.g;
01973                     ((value_type*)&v)[order_type::B] = c.b;
01974                     ((value_type*)&v)[order_type::A] = c.a;
01975                     do
01976                     {
01977                         p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
01978                         *(pixel_type*)p = v;
01979                     }
01980                     while(--len);
01981                 }
01982                 else
01983                 {
01984                     if(cover == 255)
01985                     {
01986                         do
01987                         {
01988                             p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
01989                             blender_type::blend_pix(p, c.r, c.g, c.b, alpha);
01990                         }
01991                         while(--len);
01992                     }
01993                     else
01994                     {
01995                         do
01996                         {
01997                             p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
01998                             blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
01999                         }
02000                         while(--len);
02001                     }
02002                 }
02003             }
02004         }
02005 
02006 
02007         //--------------------------------------------------------------------
02008         void blend_solid_hspan(int x, int y,
02009                                unsigned len, 
02010                                const color_type& c,
02011                                const int8u* covers)
02012         {
02013             if (c.a)
02014             {
02015                 value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
02016                 do 
02017                 {
02018                     calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
02019                     if(alpha == base_mask)
02020                     {
02021                         p[order_type::R] = c.r;
02022                         p[order_type::G] = c.g;
02023                         p[order_type::B] = c.b;
02024                         p[order_type::A] = base_mask;
02025                     }
02026                     else
02027                     {
02028                         blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
02029                     }
02030                     p += 4;
02031                     ++covers;
02032                 }
02033                 while(--len);
02034             }
02035         }
02036 
02037 
02038         //--------------------------------------------------------------------
02039         void blend_solid_vspan(int x, int y,
02040                                unsigned len, 
02041                                const color_type& c,
02042                                const int8u* covers)
02043         {
02044             if (c.a)
02045             {
02046                 do 
02047                 {
02048                     value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
02049                     calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
02050                     if(alpha == base_mask)
02051                     {
02052                         p[order_type::R] = c.r;
02053                         p[order_type::G] = c.g;
02054                         p[order_type::B] = c.b;
02055                         p[order_type::A] = base_mask;
02056                     }
02057                     else
02058                     {
02059                         blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
02060                     }
02061                     ++covers;
02062                 }
02063                 while(--len);
02064             }
02065         }
02066 
02067 
02068         //--------------------------------------------------------------------
02069         void copy_color_hspan(int x, int y,
02070                               unsigned len, 
02071                               const color_type* colors)
02072         {
02073             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
02074             do 
02075             {
02076                 p[order_type::R] = colors->r;
02077                 p[order_type::G] = colors->g;
02078                 p[order_type::B] = colors->b;
02079                 p[order_type::A] = colors->a;
02080                 ++colors;
02081                 p += 4;
02082             }
02083             while(--len);
02084         }
02085 
02086 
02087         //--------------------------------------------------------------------
02088         void copy_color_vspan(int x, int y,
02089                               unsigned len, 
02090                               const color_type* colors)
02091         {
02092             do 
02093             {
02094                 value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
02095                 p[order_type::R] = colors->r;
02096                 p[order_type::G] = colors->g;
02097                 p[order_type::B] = colors->b;
02098                 p[order_type::A] = colors->a;
02099                 ++colors;
02100             }
02101             while(--len);
02102         }
02103 
02104 
02105         //--------------------------------------------------------------------
02106         void blend_color_hspan(int x, int y,
02107                                unsigned len, 
02108                                const color_type* colors,
02109                                const int8u* covers,
02110                                int8u cover)
02111         {
02112             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
02113             if(covers)
02114             {
02115                 do 
02116                 {
02117                     cob_type::copy_or_blend_pix(p, 
02118                                                 colors->r, 
02119                                                 colors->g, 
02120                                                 colors->b, 
02121                                                 colors->a, 
02122                                                 *covers++);
02123                     p += 4;
02124                     ++colors;
02125                 }
02126                 while(--len);
02127             }
02128             else
02129             {
02130                 if(cover == 255)
02131                 {
02132                     do 
02133                     {
02134                         cob_type::copy_or_blend_pix(p, 
02135                                                     colors->r, 
02136                                                     colors->g, 
02137                                                     colors->b, 
02138                                                     colors->a);
02139                         p += 4;
02140                         ++colors;
02141                     }
02142                     while(--len);
02143                 }
02144                 else
02145                 {
02146                     do 
02147                     {
02148                         cob_type::copy_or_blend_pix(p, 
02149                                                     colors->r, 
02150                                                     colors->g, 
02151                                                     colors->b, 
02152                                                     colors->a, 
02153                                                     cover);
02154                         p += 4;
02155                         ++colors;
02156                     }
02157                     while(--len);
02158                 }
02159             }
02160         }
02161 
02162 
02163 
02164         //--------------------------------------------------------------------
02165         void blend_color_vspan(int x, int y,
02166                                unsigned len, 
02167                                const color_type* colors,
02168                                const int8u* covers,
02169                                int8u cover)
02170         {
02171             value_type* p;
02172             if(covers)
02173             {
02174                 do 
02175                 {
02176                     p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
02177                     cob_type::copy_or_blend_pix(p, 
02178                                                 colors->r, 
02179                                                 colors->g, 
02180                                                 colors->b, 
02181                                                 colors->a,
02182                                                 *covers++);
02183                     ++colors;
02184                 }
02185                 while(--len);
02186             }
02187             else
02188             {
02189                 if(cover == 255)
02190                 {
02191                     do 
02192                     {
02193                         p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
02194                         cob_type::copy_or_blend_pix(p, 
02195                                                     colors->r, 
02196                                                     colors->g, 
02197                                                     colors->b, 
02198                                                     colors->a);
02199                         ++colors;
02200                     }
02201                     while(--len);
02202                 }
02203                 else
02204                 {
02205                     do 
02206                     {
02207                         p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
02208                         cob_type::copy_or_blend_pix(p, 
02209                                                     colors->r, 
02210                                                     colors->g, 
02211                                                     colors->b, 
02212                                                     colors->a, 
02213                                                     cover);
02214                         ++colors;
02215                     }
02216                     while(--len);
02217                 }
02218             }
02219         }
02220 
02221         //--------------------------------------------------------------------
02222         template<class Function> void for_each_pixel(Function f)
02223         {
02224             unsigned y;
02225             for(y = 0; y < height(); ++y)
02226             {
02227                 row_data r = m_rbuf->row(y);
02228                 if(r.ptr)
02229                 {
02230                     unsigned len = r.x2 - r.x1 + 1;
02231                     value_type* p = 
02232                         (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2);
02233                     do
02234                     {
02235                         f(p);
02236                         p += 4;
02237                     }
02238                     while(--len);
02239                 }
02240             }
02241         }
02242 
02243         //--------------------------------------------------------------------
02244         void premultiply()
02245         {
02246             for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
02247         }
02248 
02249         //--------------------------------------------------------------------
02250         void demultiply()
02251         {
02252             for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
02253         }
02254 
02255         //--------------------------------------------------------------------
02256         template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
02257         {
02258             for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
02259         }
02260 
02261         //--------------------------------------------------------------------
02262         template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
02263         {
02264             for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
02265         }
02266 
02267         //--------------------------------------------------------------------
02268         template<class RenBuf2> void copy_from(const RenBuf2& from, 
02269                                                int xdst, int ydst,
02270                                                int xsrc, int ysrc,
02271                                                unsigned len)
02272         {
02273             const int8u* p = from.row_ptr(ysrc);
02274             if(p)
02275             {
02276                 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 
02277                         p + xsrc * pix_width, 
02278                         len * pix_width);
02279             }
02280         }
02281 
02282         //--------------------------------------------------------------------
02283         template<class SrcPixelFormatRenderer>
02284         void blend_from(const SrcPixelFormatRenderer& from, 
02285                         int xdst, int ydst,
02286                         int xsrc, int ysrc,
02287                         unsigned len,
02288                         int8u cover)
02289         {
02290             typedef typename SrcPixelFormatRenderer::order_type src_order;
02291             const value_type* psrc = (value_type*)from.row_ptr(ysrc);
02292             if(psrc)
02293             {
02294                 psrc += xsrc << 2;
02295                 value_type* pdst = 
02296                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
02297                 int incp = 4;
02298                 if(xdst > xsrc)
02299                 {
02300                     psrc += (len-1) << 2;
02301                     pdst += (len-1) << 2;
02302                     incp = -4;
02303                 }
02304 
02305                 if(cover == 255)
02306                 {
02307                     do 
02308                     {
02309                         cob_type::copy_or_blend_pix(pdst, 
02310                                                     psrc[src_order::R],
02311                                                     psrc[src_order::G],
02312                                                     psrc[src_order::B],
02313                                                     psrc[src_order::A]);
02314                         psrc += incp;
02315                         pdst += incp;
02316                     }
02317                     while(--len);
02318                 }
02319                 else
02320                 {
02321                     do 
02322                     {
02323                         cob_type::copy_or_blend_pix(pdst, 
02324                                                     psrc[src_order::R],
02325                                                     psrc[src_order::G],
02326                                                     psrc[src_order::B],
02327                                                     psrc[src_order::A],
02328                                                     cover);
02329                         psrc += incp;
02330                         pdst += incp;
02331                     }
02332                     while(--len);
02333                 }
02334             }
02335         }
02336 
02337         //--------------------------------------------------------------------
02338         template<class SrcPixelFormatRenderer>
02339         void blend_from_color(const SrcPixelFormatRenderer& from, 
02340                               const color_type& color,
02341                               int xdst, int ydst,
02342                               int xsrc, int ysrc,
02343                               unsigned len,
02344                               int8u cover)
02345         {
02346             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
02347             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
02348             if(psrc)
02349             {
02350                 value_type* pdst = 
02351                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
02352                 do 
02353                 {
02354                     cob_type::copy_or_blend_pix(pdst, 
02355                                                 color.r, color.g, color.b, color.a,
02356                                                 (*psrc * cover + base_mask) >> base_shift);
02357                     ++psrc;
02358                     pdst += 4;
02359                 }
02360                 while(--len);
02361             }
02362         }
02363 
02364         //--------------------------------------------------------------------
02365         template<class SrcPixelFormatRenderer>
02366         void blend_from_lut(const SrcPixelFormatRenderer& from, 
02367                             const color_type* color_lut,
02368                             int xdst, int ydst,
02369                             int xsrc, int ysrc,
02370                             unsigned len,
02371                             int8u cover)
02372         {
02373             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
02374             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
02375             if(psrc)
02376             {
02377                 value_type* pdst = 
02378                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
02379 
02380                 if(cover == 255)
02381                 {
02382                     do 
02383                     {
02384                         const color_type& color = color_lut[*psrc];
02385                         cob_type::copy_or_blend_pix(pdst, 
02386                                                     color.r, color.g, color.b, color.a);
02387                         ++psrc;
02388                         pdst += 4;
02389                     }
02390                     while(--len);
02391                 }
02392                 else
02393                 {
02394                     do 
02395                     {
02396                         const color_type& color = color_lut[*psrc];
02397                         cob_type::copy_or_blend_pix(pdst, 
02398                                                     color.r, color.g, color.b, color.a,
02399                                                     cover);
02400                         ++psrc;
02401                         pdst += 4;
02402                     }
02403                     while(--len);
02404                 }
02405             }
02406         }
02407 
02408     private:
02409         rbuf_type* m_rbuf;
02410     };
02411 
02412 
02413 
02414 
02415     //================================================pixfmt_custom_blend_rgba
02416     template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba
02417     {
02418     public:
02419         typedef RenBuf   rbuf_type;
02420         typedef typename rbuf_type::row_data row_data;
02421         typedef Blender  blender_type;
02422         typedef typename blender_type::color_type color_type;
02423         typedef typename blender_type::order_type order_type;
02424         typedef typename color_type::value_type value_type;
02425         typedef typename color_type::calc_type calc_type;
02426         enum base_scale_e
02427         {
02428             base_shift = color_type::base_shift,
02429             base_scale = color_type::base_scale,
02430             base_mask  = color_type::base_mask,
02431             pix_width  = sizeof(value_type) * 4 
02432         };
02433 
02434 
02435         //--------------------------------------------------------------------
02436         pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {}
02437         explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : 
02438             m_rbuf(&rb),
02439             m_comp_op(comp_op)
02440         {}
02441         void attach(rbuf_type& rb) { m_rbuf = &rb; }
02442 
02443         //--------------------------------------------------------------------
02444         template<class PixFmt>
02445         bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
02446         {
02447             rect_i r(x1, y1, x2, y2);
02448             if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
02449             {
02450                 int stride = pixf.stride();
02451                 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 
02452                                (r.x2 - r.x1) + 1,
02453                                (r.y2 - r.y1) + 1,
02454                                stride);
02455                 return true;
02456             }
02457             return false;
02458         }
02459 
02460         //--------------------------------------------------------------------
02461         AGG_INLINE unsigned width()  const { return m_rbuf->width();  }
02462         AGG_INLINE unsigned height() const { return m_rbuf->height(); }
02463         AGG_INLINE int      stride() const { return m_rbuf->stride(); }
02464 
02465         //--------------------------------------------------------------------
02466         AGG_INLINE       int8u* row_ptr(int y)       { return m_rbuf->row_ptr(y); }
02467         AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
02468         AGG_INLINE row_data     row(int y)     const { return m_rbuf->row(y); }
02469 
02470         //--------------------------------------------------------------------
02471         AGG_INLINE int8u* pix_ptr(int x, int y)
02472         {
02473             return m_rbuf->row_ptr(y) + x * pix_width;
02474         }
02475 
02476         AGG_INLINE const int8u* pix_ptr(int x, int y) const
02477         {
02478             return m_rbuf->row_ptr(y) + x * pix_width;
02479         }
02480 
02481         //--------------------------------------------------------------------
02482         void comp_op(unsigned op) { m_comp_op = op; }
02483         unsigned comp_op() const  { return m_comp_op; }
02484 
02485         //--------------------------------------------------------------------
02486         AGG_INLINE static void make_pix(int8u* p, const color_type& c)
02487         {
02488             ((value_type*)p)[order_type::R] = c.r;
02489             ((value_type*)p)[order_type::G] = c.g;
02490             ((value_type*)p)[order_type::B] = c.b;
02491             ((value_type*)p)[order_type::A] = c.a;
02492         }
02493 
02494         //--------------------------------------------------------------------
02495         color_type pixel(int x, int y) const
02496         {
02497             const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2);
02498             return color_type(p[order_type::R], 
02499                               p[order_type::G], 
02500                               p[order_type::B], 
02501                               p[order_type::A]);
02502         }
02503 
02504         //--------------------------------------------------------------------
02505         void copy_pixel(int x, int y, const color_type& c)
02506         {
02507             blender_type::blend_pix(
02508                 m_comp_op, 
02509                 (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), 
02510                 c.r, c.g, c.b, c.a, 255);
02511         }
02512 
02513         //--------------------------------------------------------------------
02514         void blend_pixel(int x, int y, const color_type& c, int8u cover)
02515         {
02516             blender_type::blend_pix(
02517                 m_comp_op, 
02518                 (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2),
02519                 c.r, c.g, c.b, c.a, 
02520                 cover);
02521         }
02522 
02523         //--------------------------------------------------------------------
02524         void copy_hline(int x, int y, unsigned len, const color_type& c)
02525         {
02526             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);;
02527             do
02528             {
02529                 blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255);
02530                 p += 4;
02531             }
02532             while(--len);
02533         }
02534 
02535         //--------------------------------------------------------------------
02536         void copy_vline(int x, int y, unsigned len, const color_type& c)
02537         {
02538             do
02539             {
02540                 blender_type::blend_pix(
02541                     m_comp_op, 
02542                     (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
02543                     c.r, c.g, c.b, c.a, 255);
02544             }
02545             while(--len);
02546         }
02547 
02548         //--------------------------------------------------------------------
02549         void blend_hline(int x, int y, unsigned len, 
02550                          const color_type& c, int8u cover)
02551         {
02552 
02553             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
02554             do
02555             {
02556                 blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover);
02557                 p += 4;
02558             }
02559             while(--len);
02560         }
02561 
02562         //--------------------------------------------------------------------
02563         void blend_vline(int x, int y, unsigned len, 
02564                          const color_type& c, int8u cover)
02565         {
02566 
02567             do
02568             {
02569                 blender_type::blend_pix(
02570                     m_comp_op, 
02571                     (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), 
02572                     c.r, c.g, c.b, c.a, 
02573                     cover);
02574             }
02575             while(--len);
02576         }
02577 
02578         //--------------------------------------------------------------------
02579         void blend_solid_hspan(int x, int y, unsigned len, 
02580                                const color_type& c, const int8u* covers)
02581         {
02582             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
02583             do 
02584             {
02585                 blender_type::blend_pix(m_comp_op, 
02586                                         p, c.r, c.g, c.b, c.a, 
02587                                         *covers++);
02588                 p += 4;
02589             }
02590             while(--len);
02591         }
02592 
02593         //--------------------------------------------------------------------
02594         void blend_solid_vspan(int x, int y, unsigned len, 
02595                                const color_type& c, const int8u* covers)
02596         {
02597             do 
02598             {
02599                 blender_type::blend_pix(
02600                     m_comp_op, 
02601                     (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), 
02602                     c.r, c.g, c.b, c.a, 
02603                     *covers++);
02604             }
02605             while(--len);
02606         }
02607 
02608         //--------------------------------------------------------------------
02609         void copy_color_hspan(int x, int y,
02610                               unsigned len, 
02611                               const color_type* colors)
02612         {
02613 
02614             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
02615             do 
02616             {
02617                 p[order_type::R] = colors->r;
02618                 p[order_type::G] = colors->g;
02619                 p[order_type::B] = colors->b;
02620                 p[order_type::A] = colors->a;
02621                 ++colors;
02622                 p += 4;
02623             }
02624             while(--len);
02625         }
02626 
02627         //--------------------------------------------------------------------
02628         void copy_color_vspan(int x, int y,
02629                               unsigned len, 
02630                               const color_type* colors)
02631         {
02632             do 
02633             {
02634                 value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
02635                 p[order_type::R] = colors->r;
02636                 p[order_type::G] = colors->g;
02637                 p[order_type::B] = colors->b;
02638                 p[order_type::A] = colors->a;
02639                 ++colors;
02640             }
02641             while(--len);
02642         }
02643 
02644         //--------------------------------------------------------------------
02645         void blend_color_hspan(int x, int y, unsigned len, 
02646                                const color_type* colors, 
02647                                const int8u* covers,
02648                                int8u cover)
02649         {
02650             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
02651             do 
02652             {
02653                 blender_type::blend_pix(m_comp_op, 
02654                                         p, 
02655                                         colors->r, 
02656                                         colors->g, 
02657                                         colors->b, 
02658                                         colors->a, 
02659                                         covers ? *covers++ : cover);
02660                 p += 4;
02661                 ++colors;
02662             }
02663             while(--len);
02664         }
02665 
02666         //--------------------------------------------------------------------
02667         void blend_color_vspan(int x, int y, unsigned len, 
02668                                const color_type* colors, 
02669                                const int8u* covers,
02670                                int8u cover)
02671         {
02672             do 
02673             {
02674                 blender_type::blend_pix(
02675                     m_comp_op, 
02676                     (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), 
02677                     colors->r,
02678                     colors->g,
02679                     colors->b,
02680                     colors->a,
02681                     covers ? *covers++ : cover);
02682                 ++colors;
02683             }
02684             while(--len);
02685 
02686         }
02687 
02688         //--------------------------------------------------------------------
02689         template<class Function> void for_each_pixel(Function f)
02690         {
02691             unsigned y;
02692             for(y = 0; y < height(); ++y)
02693             {
02694                 row_data r = m_rbuf->row(y);
02695                 if(r.ptr)
02696                 {
02697                     unsigned len = r.x2 - r.x1 + 1;
02698                     value_type* p = 
02699                         (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2);
02700                     do
02701                     {
02702                         f(p);
02703                         p += 4;
02704                     }
02705                     while(--len);
02706                 }
02707             }
02708         }
02709 
02710         //--------------------------------------------------------------------
02711         void premultiply()
02712         {
02713             for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
02714         }
02715 
02716         //--------------------------------------------------------------------
02717         void demultiply()
02718         {
02719             for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
02720         }
02721 
02722         //--------------------------------------------------------------------
02723         template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
02724         {
02725             for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
02726         }
02727 
02728         //--------------------------------------------------------------------
02729         template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
02730         {
02731             for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
02732         }
02733 
02734         //--------------------------------------------------------------------
02735         template<class RenBuf2> void copy_from(const RenBuf2& from, 
02736                                                int xdst, int ydst,
02737                                                int xsrc, int ysrc,
02738                                                unsigned len)
02739         {
02740             const int8u* p = from.row_ptr(ysrc);
02741             if(p)
02742             {
02743                 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 
02744                         p + xsrc * pix_width, 
02745                         len * pix_width);
02746             }
02747         }
02748 
02749         //--------------------------------------------------------------------
02750         template<class SrcPixelFormatRenderer> 
02751         void blend_from(const SrcPixelFormatRenderer& from, 
02752                         int xdst, int ydst,
02753                         int xsrc, int ysrc,
02754                         unsigned len,
02755                         int8u cover)
02756         {
02757             typedef typename SrcPixelFormatRenderer::order_type src_order;
02758             const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
02759             if(psrc)
02760             {
02761                 psrc += xsrc << 2;
02762                 value_type* pdst = 
02763                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
02764 
02765                 int incp = 4;
02766                 if(xdst > xsrc)
02767                 {
02768                     psrc += (len-1) << 2;
02769                     pdst += (len-1) << 2;
02770                     incp = -4;
02771                 }
02772 
02773                 do 
02774                 {
02775                     blender_type::blend_pix(m_comp_op, 
02776                                             pdst, 
02777                                             psrc[src_order::R],
02778                                             psrc[src_order::G],
02779                                             psrc[src_order::B],
02780                                             psrc[src_order::A],
02781                                             cover);
02782                     psrc += incp;
02783                     pdst += incp;
02784                 }
02785                 while(--len);
02786             }
02787         }
02788 
02789         //--------------------------------------------------------------------
02790         template<class SrcPixelFormatRenderer>
02791         void blend_from_color(const SrcPixelFormatRenderer& from, 
02792                               const color_type& color,
02793                               int xdst, int ydst,
02794                               int xsrc, int ysrc,
02795                               unsigned len,
02796                               int8u cover)
02797         {
02798             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
02799             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
02800             if(psrc)
02801             {
02802                 value_type* pdst = 
02803                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
02804                 do 
02805                 {
02806                     blender_type::blend_pix(m_comp_op,
02807                                             pdst, 
02808                                             color.r, color.g, color.b, color.a,
02809                                             (*psrc * cover + base_mask) >> base_shift);
02810                     ++psrc;
02811                     pdst += 4;
02812                 }
02813                 while(--len);
02814             }
02815         }
02816 
02817         //--------------------------------------------------------------------
02818         template<class SrcPixelFormatRenderer>
02819         void blend_from_lut(const SrcPixelFormatRenderer& from, 
02820                             const color_type* color_lut,
02821                             int xdst, int ydst,
02822                             int xsrc, int ysrc,
02823                             unsigned len,
02824                             int8u cover)
02825         {
02826             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
02827             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
02828             if(psrc)
02829             {
02830                 value_type* pdst = 
02831                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
02832                 do 
02833                 {
02834                     const color_type& color = color_lut[*psrc];
02835                     blender_type::blend_pix(m_comp_op,
02836                                             pdst, 
02837                                             color.r, color.g, color.b, color.a,
02838                                             cover);
02839                     ++psrc;
02840                     pdst += 4;
02841                 }
02842                 while(--len);
02843             }
02844         }
02845 
02846     private:
02847         rbuf_type* m_rbuf;
02848         unsigned m_comp_op;
02849     };
02850 
02851 
02852 
02853 
02854     //-----------------------------------------------------------------------
02855     typedef blender_rgba<rgba8, order_rgba> blender_rgba32; //----blender_rgba32
02856     typedef blender_rgba<rgba8, order_argb> blender_argb32; //----blender_argb32
02857     typedef blender_rgba<rgba8, order_abgr> blender_abgr32; //----blender_abgr32
02858     typedef blender_rgba<rgba8, order_bgra> blender_bgra32; //----blender_bgra32
02859 
02860     typedef blender_rgba_pre<rgba8, order_rgba> blender_rgba32_pre; //----blender_rgba32_pre
02861     typedef blender_rgba_pre<rgba8, order_argb> blender_argb32_pre; //----blender_argb32_pre
02862     typedef blender_rgba_pre<rgba8, order_abgr> blender_abgr32_pre; //----blender_abgr32_pre
02863     typedef blender_rgba_pre<rgba8, order_bgra> blender_bgra32_pre; //----blender_bgra32_pre
02864 
02865     typedef blender_rgba_plain<rgba8, order_rgba> blender_rgba32_plain; //----blender_rgba32_plain
02866     typedef blender_rgba_plain<rgba8, order_argb> blender_argb32_plain; //----blender_argb32_plain
02867     typedef blender_rgba_plain<rgba8, order_abgr> blender_abgr32_plain; //----blender_abgr32_plain
02868     typedef blender_rgba_plain<rgba8, order_bgra> blender_bgra32_plain; //----blender_bgra32_plain
02869 
02870     typedef blender_rgba<rgba16, order_rgba> blender_rgba64; //----blender_rgba64
02871     typedef blender_rgba<rgba16, order_argb> blender_argb64; //----blender_argb64
02872     typedef blender_rgba<rgba16, order_abgr> blender_abgr64; //----blender_abgr64
02873     typedef blender_rgba<rgba16, order_bgra> blender_bgra64; //----blender_bgra64
02874 
02875     typedef blender_rgba_pre<rgba16, order_rgba> blender_rgba64_pre; //----blender_rgba64_pre
02876     typedef blender_rgba_pre<rgba16, order_argb> blender_argb64_pre; //----blender_argb64_pre
02877     typedef blender_rgba_pre<rgba16, order_abgr> blender_abgr64_pre; //----blender_abgr64_pre
02878     typedef blender_rgba_pre<rgba16, order_bgra> blender_bgra64_pre; //----blender_bgra64_pre
02879 
02880 
02881     //-----------------------------------------------------------------------
02882     typedef int32u pixel32_type;
02883     typedef pixfmt_alpha_blend_rgba<blender_rgba32, rendering_buffer, pixel32_type> pixfmt_rgba32; //----pixfmt_rgba32
02884     typedef pixfmt_alpha_blend_rgba<blender_argb32, rendering_buffer, pixel32_type> pixfmt_argb32; //----pixfmt_argb32
02885     typedef pixfmt_alpha_blend_rgba<blender_abgr32, rendering_buffer, pixel32_type> pixfmt_abgr32; //----pixfmt_abgr32
02886     typedef pixfmt_alpha_blend_rgba<blender_bgra32, rendering_buffer, pixel32_type> pixfmt_bgra32; //----pixfmt_bgra32
02887 
02888     typedef pixfmt_alpha_blend_rgba<blender_rgba32_pre, rendering_buffer, pixel32_type> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre
02889     typedef pixfmt_alpha_blend_rgba<blender_argb32_pre, rendering_buffer, pixel32_type> pixfmt_argb32_pre; //----pixfmt_argb32_pre
02890     typedef pixfmt_alpha_blend_rgba<blender_abgr32_pre, rendering_buffer, pixel32_type> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre
02891     typedef pixfmt_alpha_blend_rgba<blender_bgra32_pre, rendering_buffer, pixel32_type> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre
02892 
02893     typedef pixfmt_alpha_blend_rgba<blender_rgba32_plain, rendering_buffer, pixel32_type> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain
02894     typedef pixfmt_alpha_blend_rgba<blender_argb32_plain, rendering_buffer, pixel32_type> pixfmt_argb32_plain; //----pixfmt_argb32_plain
02895     typedef pixfmt_alpha_blend_rgba<blender_abgr32_plain, rendering_buffer, pixel32_type> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain
02896     typedef pixfmt_alpha_blend_rgba<blender_bgra32_plain, rendering_buffer, pixel32_type> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain
02897 
02898     struct  pixel64_type { int16u c[4]; };
02899     typedef pixfmt_alpha_blend_rgba<blender_rgba64, rendering_buffer, pixel64_type> pixfmt_rgba64; //----pixfmt_rgba64
02900     typedef pixfmt_alpha_blend_rgba<blender_argb64, rendering_buffer, pixel64_type> pixfmt_argb64; //----pixfmt_argb64
02901     typedef pixfmt_alpha_blend_rgba<blender_abgr64, rendering_buffer, pixel64_type> pixfmt_abgr64; //----pixfmt_abgr64
02902     typedef pixfmt_alpha_blend_rgba<blender_bgra64, rendering_buffer, pixel64_type> pixfmt_bgra64; //----pixfmt_bgra64
02903 
02904     typedef pixfmt_alpha_blend_rgba<blender_rgba64_pre, rendering_buffer, pixel64_type> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre
02905     typedef pixfmt_alpha_blend_rgba<blender_argb64_pre, rendering_buffer, pixel64_type> pixfmt_argb64_pre; //----pixfmt_argb64_pre
02906     typedef pixfmt_alpha_blend_rgba<blender_abgr64_pre, rendering_buffer, pixel64_type> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre
02907     typedef pixfmt_alpha_blend_rgba<blender_bgra64_pre, rendering_buffer, pixel64_type> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre
02908 }
02909 
02910 #endif
02911 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines