Anti-Grain Geometry - AGG (libagg)
2.5
|
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