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