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