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