//---------------------------------------------------------------------------- // Anti-Grain Geometry (AGG) - Version 2.5 // A high quality rendering engine for C++ // Copyright (C) 2002-2006 Maxim Shemanarev // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://antigrain.com // // AGG is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // AGG is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with AGG; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, // MA 02110-1301, USA. //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_RGBA_INCLUDED #define AGG_PIXFMT_RGBA_INCLUDED #include <string.h> #include <math.h> #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_rendering_buffer.h" namespace agg { //=========================================================multiplier_rgba template<class ColorT, class Order> struct multiplier_rgba { typedef typename ColorT::value_type value_type; typedef typename ColorT::calc_type calc_type; //-------------------------------------------------------------------- static AGG_INLINE void premultiply(value_type* p) { calc_type a = p[Order::A]; if(a < ColorT::base_mask) { if(a == 0) { p[Order::R] = p[Order::G] = p[Order::B] = 0; return; } p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); } } //-------------------------------------------------------------------- static AGG_INLINE void demultiply(value_type* p) { calc_type a = p[Order::A]; if(a < ColorT::base_mask) { if(a == 0) { p[Order::R] = p[Order::G] = p[Order::B] = 0; return; } calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); } } }; //=====================================================apply_gamma_dir_rgba template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba { public: typedef typename ColorT::value_type value_type; apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { p[Order::R] = m_gamma.dir(p[Order::R]); p[Order::G] = m_gamma.dir(p[Order::G]); p[Order::B] = m_gamma.dir(p[Order::B]); } private: const GammaLut& m_gamma; }; //=====================================================apply_gamma_inv_rgba template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba { public: typedef typename ColorT::value_type value_type; apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { p[Order::R] = m_gamma.inv(p[Order::R]); p[Order::G] = m_gamma.inv(p[Order::G]); p[Order::B] = m_gamma.inv(p[Order::B]); } private: const GammaLut& m_gamma; }; //=============================================================blender_rgba template<class ColorT, class Order> struct blender_rgba { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover=0) { calc_type r = p[Order::R]; calc_type g = p[Order::G]; calc_type b = p[Order::B]; calc_type a = p[Order::A]; p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); } }; //=========================================================blender_rgba_pre template<class ColorT, class Order> struct blender_rgba_pre { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (base_shift - 8); p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); } //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha) { alpha = color_type::base_mask - alpha; p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); } }; //======================================================blender_rgba_plain template<class ColorT, class Order> struct blender_rgba_plain { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover=0) { if(alpha == 0) return; calc_type a = p[Order::A]; calc_type r = p[Order::R] * a; calc_type g = p[Order::G] * a; calc_type b = p[Order::B] * a; a = ((alpha + a) << base_shift) - alpha * a; p[Order::A] = (value_type)(a >> base_shift); p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); } }; //=========================================================comp_op_rgba_clear template<class ColorT, class Order> struct comp_op_rgba_clear { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(value_type* p, unsigned, unsigned, unsigned, unsigned, unsigned cover) { if(cover < 255) { cover = 255 - cover; p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); } else { p[0] = p[1] = p[2] = p[3] = 0; } } }; //===========================================================comp_op_rgba_src template<class ColorT, class Order> struct comp_op_rgba_src { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { unsigned alpha = 255 - cover; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); } else { p[Order::R] = sr; p[Order::G] = sg; p[Order::B] = sb; p[Order::A] = sa; } } }; //===========================================================comp_op_rgba_dst template<class ColorT, class Order> struct comp_op_rgba_dst { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; static AGG_INLINE void blend_pix(value_type*, unsigned, unsigned, unsigned, unsigned, unsigned) { } }; //======================================================comp_op_rgba_src_over template<class ColorT, class Order> struct comp_op_rgba_src_over { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } calc_type s1a = base_mask - sa; p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); } }; //======================================================comp_op_rgba_dst_over template<class ColorT, class Order> struct comp_op_rgba_dst_over { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca + Sca.(1 - Da) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } calc_type d1a = base_mask - p[Order::A]; p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); } }; //======================================================comp_op_rgba_src_in template<class ColorT, class Order> struct comp_op_rgba_src_in { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.Da // Da' = Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { calc_type da = p[Order::A]; if(cover < 255) { unsigned alpha = 255 - cover; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); } else { p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); } } }; //======================================================comp_op_rgba_dst_in template<class ColorT, class Order> struct comp_op_rgba_dst_in { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca.Sa // Da' = Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned, unsigned, unsigned, unsigned sa, unsigned cover) { if(cover < 255) { sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); } p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); } }; //======================================================comp_op_rgba_src_out template<class ColorT, class Order> struct comp_op_rgba_src_out { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.(1 - Da) // Da' = Sa.(1 - Da) static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { calc_type da = base_mask - p[Order::A]; if(cover < 255) { unsigned alpha = 255 - cover; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); } else { p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); } } }; //======================================================comp_op_rgba_dst_out template<class ColorT, class Order> struct comp_op_rgba_dst_out { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca.(1 - Sa) // Da' = Da.(1 - Sa) static AGG_INLINE void blend_pix(value_type* p, unsigned, unsigned, unsigned, unsigned sa, unsigned cover) { if(cover < 255) { sa = (sa * cover + 255) >> 8; } sa = base_mask - sa; p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); } }; //=====================================================comp_op_rgba_src_atop template<class ColorT, class Order> struct comp_op_rgba_src_atop { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.Da + Dca.(1 - Sa) // Da' = Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } calc_type da = p[Order::A]; sa = base_mask - sa; p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); } }; //=====================================================comp_op_rgba_dst_atop template<class ColorT, class Order> struct comp_op_rgba_dst_atop { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca.Sa + Sca.(1 - Da) // Da' = Sa static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { calc_type da = base_mask - p[Order::A]; if(cover < 255) { unsigned alpha = 255 - cover; sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); } else { p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); p[Order::A] = (value_type)sa; } } }; //=========================================================comp_op_rgba_xor template<class ColorT, class Order> struct comp_op_rgba_xor { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) // Da' = Sa + Da - 2.Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type s1a = base_mask - sa; calc_type d1a = base_mask - p[Order::A]; p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); } } }; //=========================================================comp_op_rgba_plus template<class ColorT, class Order> struct comp_op_rgba_plus { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca + Dca // Da' = Sa + Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type dr = p[Order::R] + sr; calc_type dg = p[Order::G] + sg; calc_type db = p[Order::B] + sb; calc_type da = p[Order::A] + sa; p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; } } }; //========================================================comp_op_rgba_minus template<class ColorT, class Order> struct comp_op_rgba_minus { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca - Sca // Da' = 1 - (1 - Sa).(1 - Da) static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type dr = p[Order::R] - sr; calc_type dg = p[Order::G] - sg; calc_type db = p[Order::B] - sb; p[Order::R] = (dr > base_mask) ? 0 : dr; p[Order::G] = (dg > base_mask) ? 0 : dg; p[Order::B] = (db > base_mask) ? 0 : db; p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_multiply template<class ColorT, class Order> struct comp_op_rgba_multiply { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type s1a = base_mask - sa; calc_type d1a = base_mask - p[Order::A]; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_screen template<class ColorT, class Order> struct comp_op_rgba_screen { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca + Dca - Sca.Dca // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_overlay template<class ColorT, class Order> struct comp_op_rgba_overlay { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // if 2.Dca < Da // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) // otherwise // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) // // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da |