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 <cstring> 28 #include <cmath> 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, value_type, value_type, value_type, 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*, 349 value_type, value_type, value_type, value_type, cover_type) 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, value_type, value_type, 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, value_type, value_type, 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) * (std::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, 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, 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, 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, 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 num_components = 4, 1519 pix_step = 4, 1520 pix_width = sizeof(value_type) * pix_step, 1521 }; 1522 struct pixel_type 1523 { 1524 value_type c[num_components]; 1525 setpixel_type1526 void set(value_type r, value_type g, value_type b, value_type a) 1527 { 1528 c[order_type::R] = r; 1529 c[order_type::G] = g; 1530 c[order_type::B] = b; 1531 c[order_type::A] = a; 1532 } 1533 setpixel_type1534 void set(const color_type& color) 1535 { 1536 set(color.r, color.g, color.b, color.a); 1537 } 1538 getpixel_type1539 void get(value_type& r, value_type& g, value_type& b, value_type& a) const 1540 { 1541 r = c[order_type::R]; 1542 g = c[order_type::G]; 1543 b = c[order_type::B]; 1544 a = c[order_type::A]; 1545 } 1546 getpixel_type1547 color_type get() const 1548 { 1549 return color_type( 1550 c[order_type::R], 1551 c[order_type::G], 1552 c[order_type::B], 1553 c[order_type::A]); 1554 } 1555 nextpixel_type1556 pixel_type* next() 1557 { 1558 return (pixel_type*)(c + pix_step); 1559 } 1560 nextpixel_type1561 const pixel_type* next() const 1562 { 1563 return (const pixel_type*)(c + pix_step); 1564 } 1565 advancepixel_type1566 pixel_type* advance(int n) 1567 { 1568 return (pixel_type*)(c + n * pix_step); 1569 } 1570 advancepixel_type1571 const pixel_type* advance(int n) const 1572 { 1573 return (const pixel_type*)(c + n * pix_step); 1574 } 1575 }; 1576 1577 private: 1578 //-------------------------------------------------------------------- blend_pix(pixel_type * p,const color_type & c,unsigned cover)1579 AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) 1580 { 1581 m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); 1582 } 1583 1584 //-------------------------------------------------------------------- blend_pix(pixel_type * p,const color_type & c)1585 AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) 1586 { 1587 m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); 1588 } 1589 1590 //-------------------------------------------------------------------- copy_or_blend_pix(pixel_type * p,const color_type & c,unsigned cover)1591 AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) 1592 { 1593 if (!c.is_transparent()) 1594 { 1595 if (c.is_opaque() && cover == cover_mask) 1596 { 1597 p->set(c.r, c.g, c.b, c.a); 1598 } 1599 else 1600 { 1601 m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); 1602 } 1603 } 1604 } 1605 1606 //-------------------------------------------------------------------- copy_or_blend_pix(pixel_type * p,const color_type & c)1607 AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) 1608 { 1609 if (!c.is_transparent()) 1610 { 1611 if (c.is_opaque()) 1612 { 1613 p->set(c.r, c.g, c.b, c.a); 1614 } 1615 else 1616 { 1617 m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); 1618 } 1619 } 1620 } 1621 1622 public: 1623 //-------------------------------------------------------------------- pixfmt_alpha_blend_rgba()1624 pixfmt_alpha_blend_rgba() : m_rbuf(0) {} pixfmt_alpha_blend_rgba(rbuf_type & rb)1625 explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} attach(rbuf_type & rb)1626 void attach(rbuf_type& rb) { m_rbuf = &rb; } 1627 1628 //-------------------------------------------------------------------- 1629 template<class PixFmt> attach(PixFmt & pixf,int x1,int y1,int x2,int y2)1630 bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) 1631 { 1632 rect_i r(x1, y1, x2, y2); 1633 if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) 1634 { 1635 int stride = pixf.stride(); 1636 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 1637 (r.x2 - r.x1) + 1, 1638 (r.y2 - r.y1) + 1, 1639 stride); 1640 return true; 1641 } 1642 return false; 1643 } 1644 1645 //-------------------------------------------------------------------- width()1646 AGG_INLINE unsigned width() const { return m_rbuf->width(); } height()1647 AGG_INLINE unsigned height() const { return m_rbuf->height(); } stride()1648 AGG_INLINE int stride() const { return m_rbuf->stride(); } 1649 1650 //-------------------------------------------------------------------- row_ptr(int y)1651 AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } row_ptr(int y)1652 AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } row(int y)1653 AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } 1654 1655 //-------------------------------------------------------------------- pix_ptr(int x,int y)1656 AGG_INLINE int8u* pix_ptr(int x, int y) 1657 { 1658 return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); 1659 } 1660 pix_ptr(int x,int y)1661 AGG_INLINE const int8u* pix_ptr(int x, int y) const 1662 { 1663 return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); 1664 } 1665 1666 // Return pointer to pixel value, forcing row to be allocated. pix_value_ptr(int x,int y,unsigned len)1667 AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) 1668 { 1669 return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step)); 1670 } 1671 1672 // Return pointer to pixel value, or null if row not allocated. pix_value_ptr(int x,int y)1673 AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const 1674 { 1675 int8u* p = m_rbuf->row_ptr(y); 1676 return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step)) : 0; 1677 } 1678 1679 // Get pixel pointer from raw buffer pointer. pix_value_ptr(void * p)1680 AGG_INLINE static pixel_type* pix_value_ptr(void* p) 1681 { 1682 return (pixel_type*)p; 1683 } 1684 1685 // Get pixel pointer from raw buffer pointer. pix_value_ptr(const void * p)1686 AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) 1687 { 1688 return (const pixel_type*)p; 1689 } 1690 1691 //-------------------------------------------------------------------- write_plain_color(void * p,color_type c)1692 AGG_INLINE static void write_plain_color(void* p, color_type c) 1693 { 1694 blender_type::set_plain_color(pix_value_ptr(p)->c, c); 1695 } 1696 1697 //-------------------------------------------------------------------- read_plain_color(const void * p)1698 AGG_INLINE static color_type read_plain_color(const void* p) 1699 { 1700 return blender_type::get_plain_color(pix_value_ptr(p)->c); 1701 } 1702 1703 //-------------------------------------------------------------------- make_pix(int8u * p,const color_type & c)1704 AGG_INLINE static void make_pix(int8u* p, const color_type& c) 1705 { 1706 ((pixel_type*)p)->set(c); 1707 } 1708 1709 //-------------------------------------------------------------------- pixel(int x,int y)1710 AGG_INLINE color_type pixel(int x, int y) const 1711 { 1712 if (const pixel_type* p = pix_value_ptr(x, y)) 1713 { 1714 return p->get(); 1715 } 1716 return color_type::no_color(); 1717 } 1718 1719 //-------------------------------------------------------------------- copy_pixel(int x,int y,const color_type & c)1720 AGG_INLINE void copy_pixel(int x, int y, const color_type& c) 1721 { 1722 pix_value_ptr(x, y, 1)->set(c); 1723 } 1724 1725 //-------------------------------------------------------------------- blend_pixel(int x,int y,const color_type & c,int8u cover)1726 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) 1727 { 1728 copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover); 1729 } 1730 1731 //-------------------------------------------------------------------- copy_hline(int x,int y,unsigned len,const color_type & c)1732 AGG_INLINE void copy_hline(int x, int y, 1733 unsigned len, 1734 const color_type& c) 1735 { 1736 pixel_type v; 1737 v.set(c); 1738 pixel_type* p = pix_value_ptr(x, y, len); 1739 do 1740 { 1741 *p = v; 1742 p = p->next(); 1743 } 1744 while (--len); 1745 } 1746 1747 1748 //-------------------------------------------------------------------- copy_vline(int x,int y,unsigned len,const color_type & c)1749 AGG_INLINE void copy_vline(int x, int y, 1750 unsigned len, 1751 const color_type& c) 1752 { 1753 pixel_type v; 1754 v.set(c); 1755 do 1756 { 1757 *pix_value_ptr(x, y++, 1) = v; 1758 } 1759 while (--len); 1760 } 1761 1762 //-------------------------------------------------------------------- blend_hline(int x,int y,unsigned len,const color_type & c,int8u cover)1763 void blend_hline(int x, int y, 1764 unsigned len, 1765 const color_type& c, 1766 int8u cover) 1767 { 1768 if (!c.is_transparent()) 1769 { 1770 pixel_type* p = pix_value_ptr(x, y, len); 1771 if (c.is_opaque() && cover == cover_mask) 1772 { 1773 pixel_type v; 1774 v.set(c); 1775 do 1776 { 1777 *p = v; 1778 p = p->next(); 1779 } 1780 while (--len); 1781 } 1782 else 1783 { 1784 if (cover == cover_mask) 1785 { 1786 do 1787 { 1788 blend_pix(p, c); 1789 p = p->next(); 1790 } 1791 while (--len); 1792 } 1793 else 1794 { 1795 do 1796 { 1797 blend_pix(p, c, cover); 1798 p = p->next(); 1799 } 1800 while (--len); 1801 } 1802 } 1803 } 1804 } 1805 1806 1807 //-------------------------------------------------------------------- blend_vline(int x,int y,unsigned len,const color_type & c,int8u cover)1808 void blend_vline(int x, int y, 1809 unsigned len, 1810 const color_type& c, 1811 int8u cover) 1812 { 1813 if (!c.is_transparent()) 1814 { 1815 if (c.is_opaque() && cover == cover_mask) 1816 { 1817 pixel_type v; 1818 v.set(c); 1819 do 1820 { 1821 *pix_value_ptr(x, y++, 1) = v; 1822 } 1823 while (--len); 1824 } 1825 else 1826 { 1827 if (cover == cover_mask) 1828 { 1829 do 1830 { 1831 blend_pix(pix_value_ptr(x, y++, 1), c, c.a); 1832 } 1833 while (--len); 1834 } 1835 else 1836 { 1837 do 1838 { 1839 blend_pix(pix_value_ptr(x, y++, 1), c, cover); 1840 } 1841 while (--len); 1842 } 1843 } 1844 } 1845 } 1846 1847 1848 //-------------------------------------------------------------------- blend_solid_hspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)1849 void blend_solid_hspan(int x, int y, 1850 unsigned len, 1851 const color_type& c, 1852 const int8u* covers) 1853 { 1854 if (!c.is_transparent()) 1855 { 1856 pixel_type* p = pix_value_ptr(x, y, len); 1857 do 1858 { 1859 if (c.is_opaque() && *covers == cover_mask) 1860 { 1861 p->set(c); 1862 } 1863 else 1864 { 1865 blend_pix(p, c, *covers); 1866 } 1867 p = p->next(); 1868 ++covers; 1869 } 1870 while (--len); 1871 } 1872 } 1873 1874 1875 //-------------------------------------------------------------------- blend_solid_vspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)1876 void blend_solid_vspan(int x, int y, 1877 unsigned len, 1878 const color_type& c, 1879 const int8u* covers) 1880 { 1881 if (!c.is_transparent()) 1882 { 1883 do 1884 { 1885 pixel_type* p = pix_value_ptr(x, y++, 1); 1886 if (c.is_opaque() && *covers == cover_mask) 1887 { 1888 p->set(c); 1889 } 1890 else 1891 { 1892 blend_pix(p, c, *covers); 1893 } 1894 ++covers; 1895 } 1896 while (--len); 1897 } 1898 } 1899 1900 //-------------------------------------------------------------------- copy_color_hspan(int x,int y,unsigned len,const color_type * colors)1901 void copy_color_hspan(int x, int y, 1902 unsigned len, 1903 const color_type* colors) 1904 { 1905 pixel_type* p = pix_value_ptr(x, y, len); 1906 do 1907 { 1908 p->set(*colors++); 1909 p = p->next(); 1910 } 1911 while (--len); 1912 } 1913 1914 1915 //-------------------------------------------------------------------- copy_color_vspan(int x,int y,unsigned len,const color_type * colors)1916 void copy_color_vspan(int x, int y, 1917 unsigned len, 1918 const color_type* colors) 1919 { 1920 do 1921 { 1922 pix_value_ptr(x, y++, 1)->set(*colors++); 1923 } 1924 while (--len); 1925 } 1926 1927 //-------------------------------------------------------------------- blend_color_hspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)1928 void blend_color_hspan(int x, int y, 1929 unsigned len, 1930 const color_type* colors, 1931 const int8u* covers, 1932 int8u cover) 1933 { 1934 pixel_type* p = pix_value_ptr(x, y, len); 1935 if (covers) 1936 { 1937 do 1938 { 1939 copy_or_blend_pix(p, *colors++, *covers++); 1940 p = p->next(); 1941 } 1942 while (--len); 1943 } 1944 else 1945 { 1946 if (cover == cover_mask) 1947 { 1948 do 1949 { 1950 copy_or_blend_pix(p, *colors++); 1951 p = p->next(); 1952 } 1953 while (--len); 1954 } 1955 else 1956 { 1957 do 1958 { 1959 copy_or_blend_pix(p, *colors++, cover); 1960 p = p->next(); 1961 } 1962 while (--len); 1963 } 1964 } 1965 } 1966 1967 //-------------------------------------------------------------------- blend_color_vspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)1968 void blend_color_vspan(int x, int y, 1969 unsigned len, 1970 const color_type* colors, 1971 const int8u* covers, 1972 int8u cover) 1973 { 1974 if (covers) 1975 { 1976 do 1977 { 1978 copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); 1979 } 1980 while (--len); 1981 } 1982 else 1983 { 1984 if (cover == cover_mask) 1985 { 1986 do 1987 { 1988 copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); 1989 } 1990 while (--len); 1991 } 1992 else 1993 { 1994 do 1995 { 1996 copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); 1997 } 1998 while (--len); 1999 } 2000 } 2001 } 2002 2003 //-------------------------------------------------------------------- for_each_pixel(Function f)2004 template<class Function> void for_each_pixel(Function f) 2005 { 2006 for (unsigned y = 0; y < height(); ++y) 2007 { 2008 row_data r = m_rbuf->row(y); 2009 if (r.ptr) 2010 { 2011 unsigned len = r.x2 - r.x1 + 1; 2012 pixel_type* p = pix_value_ptr(r.x1, y, len); 2013 do 2014 { 2015 f(p->c); 2016 p = p->next(); 2017 } 2018 while (--len); 2019 } 2020 } 2021 } 2022 2023 //-------------------------------------------------------------------- premultiply()2024 void premultiply() 2025 { 2026 for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); 2027 } 2028 2029 //-------------------------------------------------------------------- demultiply()2030 void demultiply() 2031 { 2032 for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); 2033 } 2034 2035 //-------------------------------------------------------------------- apply_gamma_dir(const GammaLut & g)2036 template<class GammaLut> void apply_gamma_dir(const GammaLut& g) 2037 { 2038 for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); 2039 } 2040 2041 //-------------------------------------------------------------------- apply_gamma_inv(const GammaLut & g)2042 template<class GammaLut> void apply_gamma_inv(const GammaLut& g) 2043 { 2044 for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g)); 2045 } 2046 2047 //-------------------------------------------------------------------- copy_from(const RenBuf2 & from,int xdst,int ydst,int xsrc,int ysrc,unsigned len)2048 template<class RenBuf2> void copy_from(const RenBuf2& from, 2049 int xdst, int ydst, 2050 int xsrc, int ysrc, 2051 unsigned len) 2052 { 2053 if (const int8u* p = from.row_ptr(ysrc)) 2054 { 2055 std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 2056 p + xsrc * pix_width, 2057 len * pix_width); 2058 } 2059 } 2060 2061 //-------------------------------------------------------------------- 2062 // Blend from another RGBA surface. 2063 template<class SrcPixelFormatRenderer> blend_from(const SrcPixelFormatRenderer & from,int xdst,int ydst,int xsrc,int ysrc,unsigned len,int8u cover)2064 void blend_from(const SrcPixelFormatRenderer& from, 2065 int xdst, int ydst, 2066 int xsrc, int ysrc, 2067 unsigned len, 2068 int8u cover) 2069 { 2070 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 2071 2072 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 2073 { 2074 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 2075 int srcinc = 1; 2076 int dstinc = 1; 2077 2078 if (xdst > xsrc) 2079 { 2080 psrc = psrc->advance(len - 1); 2081 pdst = pdst->advance(len - 1); 2082 srcinc = -1; 2083 dstinc = -1; 2084 } 2085 2086 if (cover == cover_mask) 2087 { 2088 do 2089 { 2090 copy_or_blend_pix(pdst, psrc->get()); 2091 psrc = psrc->advance(srcinc); 2092 pdst = pdst->advance(dstinc); 2093 } 2094 while (--len); 2095 } 2096 else 2097 { 2098 do 2099 { 2100 copy_or_blend_pix(pdst, psrc->get(), cover); 2101 psrc = psrc->advance(srcinc); 2102 pdst = pdst->advance(dstinc); 2103 } 2104 while (--len); 2105 } 2106 } 2107 } 2108 2109 //-------------------------------------------------------------------- 2110 // Combine single color with grayscale surface and blend. 2111 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)2112 void blend_from_color(const SrcPixelFormatRenderer& from, 2113 const color_type& color, 2114 int xdst, int ydst, 2115 int xsrc, int ysrc, 2116 unsigned len, 2117 int8u cover) 2118 { 2119 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 2120 typedef typename SrcPixelFormatRenderer::color_type src_color_type; 2121 2122 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 2123 { 2124 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 2125 2126 do 2127 { 2128 copy_or_blend_pix(pdst, color, 2129 src_color_type::scale_cover(cover, psrc->c[0])); 2130 psrc = psrc->next(); 2131 pdst = pdst->next(); 2132 } 2133 while (--len); 2134 } 2135 } 2136 2137 //-------------------------------------------------------------------- 2138 // Blend from color table, using grayscale surface as indexes into table. 2139 // Obviously, this only works for integer value types. 2140 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)2141 void blend_from_lut(const SrcPixelFormatRenderer& from, 2142 const color_type* color_lut, 2143 int xdst, int ydst, 2144 int xsrc, int ysrc, 2145 unsigned len, 2146 int8u cover) 2147 { 2148 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 2149 2150 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 2151 { 2152 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 2153 2154 if (cover == cover_mask) 2155 { 2156 do 2157 { 2158 copy_or_blend_pix(pdst, color_lut[psrc->c[0]]); 2159 psrc = psrc->next(); 2160 pdst = pdst->next(); 2161 } 2162 while (--len); 2163 } 2164 else 2165 { 2166 do 2167 { 2168 copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); 2169 psrc = psrc->next(); 2170 pdst = pdst->next(); 2171 } 2172 while (--len); 2173 } 2174 } 2175 } 2176 2177 private: 2178 rbuf_type* m_rbuf; 2179 Blender m_blender; 2180 }; 2181 2182 //================================================pixfmt_custom_blend_rgba 2183 template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba 2184 { 2185 public: 2186 typedef pixfmt_rgba_tag pixfmt_category; 2187 typedef RenBuf rbuf_type; 2188 typedef typename rbuf_type::row_data row_data; 2189 typedef Blender blender_type; 2190 typedef typename blender_type::color_type color_type; 2191 typedef typename blender_type::order_type order_type; 2192 typedef typename color_type::value_type value_type; 2193 typedef typename color_type::calc_type calc_type; 2194 enum 2195 { 2196 num_components = 4, 2197 pix_step = 4, 2198 pix_width = sizeof(value_type) * pix_step, 2199 }; 2200 struct pixel_type 2201 { 2202 value_type c[num_components]; 2203 setpixel_type2204 void set(value_type r, value_type g, value_type b, value_type a) 2205 { 2206 c[order_type::R] = r; 2207 c[order_type::G] = g; 2208 c[order_type::B] = b; 2209 c[order_type::A] = a; 2210 } 2211 setpixel_type2212 void set(const color_type& color) 2213 { 2214 set(color.r, color.g, color.b, color.a); 2215 } 2216 getpixel_type2217 void get(value_type& r, value_type& g, value_type& b, value_type& a) const 2218 { 2219 r = c[order_type::R]; 2220 g = c[order_type::G]; 2221 b = c[order_type::B]; 2222 a = c[order_type::A]; 2223 } 2224 getpixel_type2225 color_type get() const 2226 { 2227 return color_type( 2228 c[order_type::R], 2229 c[order_type::G], 2230 c[order_type::B], 2231 c[order_type::A]); 2232 } 2233 nextpixel_type2234 pixel_type* next() 2235 { 2236 return (pixel_type*)(c + pix_step); 2237 } 2238 nextpixel_type2239 const pixel_type* next() const 2240 { 2241 return (const pixel_type*)(c + pix_step); 2242 } 2243 advancepixel_type2244 pixel_type* advance(int n) 2245 { 2246 return (pixel_type*)(c + n * pix_step); 2247 } 2248 advancepixel_type2249 const pixel_type* advance(int n) const 2250 { 2251 return (const pixel_type*)(c + n * pix_step); 2252 } 2253 }; 2254 2255 2256 private: 2257 //-------------------------------------------------------------------- 2258 AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full) 2259 { 2260 m_blender.blend_pix(m_comp_op, p->c, c.r, c.g, c.b, c.a, cover); 2261 } 2262 2263 //-------------------------------------------------------------------- 2264 AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full) 2265 { 2266 if (!c.is_transparent()) 2267 { 2268 if (c.is_opaque() && cover == cover_mask) 2269 { 2270 p->set(c.r, c.g, c.b, c.a); 2271 } 2272 else 2273 { 2274 blend_pix(p, c, cover); 2275 } 2276 } 2277 } 2278 2279 public: 2280 //-------------------------------------------------------------------- pixfmt_custom_blend_rgba()2281 pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} 2282 explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : 2283 m_rbuf(&rb), 2284 m_comp_op(comp_op) 2285 {} attach(rbuf_type & rb)2286 void attach(rbuf_type& rb) { m_rbuf = &rb; } 2287 2288 //-------------------------------------------------------------------- 2289 template<class PixFmt> attach(PixFmt & pixf,int x1,int y1,int x2,int y2)2290 bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) 2291 { 2292 rect_i r(x1, y1, x2, y2); 2293 if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) 2294 { 2295 int stride = pixf.stride(); 2296 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 2297 (r.x2 - r.x1) + 1, 2298 (r.y2 - r.y1) + 1, 2299 stride); 2300 return true; 2301 } 2302 return false; 2303 } 2304 2305 //-------------------------------------------------------------------- comp_op(unsigned op)2306 void comp_op(unsigned op) { m_comp_op = op; } comp_op()2307 unsigned comp_op() const { return m_comp_op; } 2308 2309 //-------------------------------------------------------------------- width()2310 AGG_INLINE unsigned width() const { return m_rbuf->width(); } height()2311 AGG_INLINE unsigned height() const { return m_rbuf->height(); } stride()2312 AGG_INLINE int stride() const { return m_rbuf->stride(); } 2313 2314 //-------------------------------------------------------------------- row_ptr(int y)2315 AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } row_ptr(int y)2316 AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } row(int y)2317 AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } 2318 2319 //-------------------------------------------------------------------- pix_ptr(int x,int y)2320 AGG_INLINE int8u* pix_ptr(int x, int y) 2321 { 2322 return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); 2323 } 2324 pix_ptr(int x,int y)2325 AGG_INLINE const int8u* pix_ptr(int x, int y) const 2326 { 2327 return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); 2328 } 2329 2330 // Return pointer to pixel value, forcing row to be allocated. pix_value_ptr(int x,int y,unsigned len)2331 AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) 2332 { 2333 return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step)); 2334 } 2335 2336 // Return pointer to pixel value, or null if row not allocated. pix_value_ptr(int x,int y)2337 AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const 2338 { 2339 int8u* p = m_rbuf->row_ptr(y); 2340 return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step)) : 0; 2341 } 2342 2343 // Get pixel pointer from raw buffer pointer. pix_value_ptr(void * p)2344 AGG_INLINE static pixel_type* pix_value_ptr(void* p) 2345 { 2346 return (pixel_type*)p; 2347 } 2348 2349 // Get pixel pointer from raw buffer pointer. pix_value_ptr(const void * p)2350 AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) 2351 { 2352 return (const pixel_type*)p; 2353 } 2354 2355 //-------------------------------------------------------------------- make_pix(int8u * p,const color_type & c)2356 AGG_INLINE static void make_pix(int8u* p, const color_type& c) 2357 { 2358 ((pixel_type*)p)->set(c); 2359 } 2360 2361 //-------------------------------------------------------------------- pixel(int x,int y)2362 AGG_INLINE color_type pixel(int x, int y) const 2363 { 2364 if (const pixel_type* p = pix_value_ptr(x, y)) 2365 { 2366 return p->get(); 2367 } 2368 return color_type::no_color(); 2369 } 2370 2371 //-------------------------------------------------------------------- copy_pixel(int x,int y,const color_type & c)2372 AGG_INLINE void copy_pixel(int x, int y, const color_type& c) 2373 { 2374 make_pix(pix_value_ptr(x, y, 1), c); 2375 } 2376 2377 //-------------------------------------------------------------------- blend_pixel(int x,int y,const color_type & c,int8u cover)2378 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) 2379 { 2380 blend_pix(pix_value_ptr(x, y, 1), c, cover); 2381 } 2382 2383 //-------------------------------------------------------------------- copy_hline(int x,int y,unsigned len,const color_type & c)2384 AGG_INLINE void copy_hline(int x, int y, 2385 unsigned len, 2386 const color_type& c) 2387 { 2388 pixel_type v; 2389 v.set(c); 2390 pixel_type* p = pix_value_ptr(x, y, len); 2391 do 2392 { 2393 *p = v; 2394 p = p->next(); 2395 } 2396 while (--len); 2397 } 2398 2399 2400 //-------------------------------------------------------------------- copy_vline(int x,int y,unsigned len,const color_type & c)2401 AGG_INLINE void copy_vline(int x, int y, 2402 unsigned len, 2403 const color_type& c) 2404 { 2405 pixel_type v; 2406 v.set(c); 2407 do 2408 { 2409 *pix_value_ptr(x, y++, 1) = v; 2410 } 2411 while (--len); 2412 } 2413 2414 //-------------------------------------------------------------------- blend_hline(int x,int y,unsigned len,const color_type & c,int8u cover)2415 void blend_hline(int x, int y, unsigned len, 2416 const color_type& c, int8u cover) 2417 { 2418 2419 pixel_type* p = pix_value_ptr(x, y, len); 2420 do 2421 { 2422 blend_pix(p, c, cover); 2423 p = p->next(); 2424 } 2425 while (--len); 2426 } 2427 2428 //-------------------------------------------------------------------- blend_vline(int x,int y,unsigned len,const color_type & c,int8u cover)2429 void blend_vline(int x, int y, unsigned len, 2430 const color_type& c, int8u cover) 2431 { 2432 do 2433 { 2434 blend_pix(pix_value_ptr(x, y++, 1), c, cover); 2435 } 2436 while (--len); 2437 } 2438 2439 //-------------------------------------------------------------------- blend_solid_hspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)2440 void blend_solid_hspan(int x, int y, unsigned len, 2441 const color_type& c, const int8u* covers) 2442 { 2443 pixel_type* p = pix_value_ptr(x, y, len); 2444 2445 do 2446 { 2447 blend_pix(p, c, *covers++); 2448 p = p->next(); 2449 } 2450 while (--len); 2451 } 2452 2453 //-------------------------------------------------------------------- blend_solid_vspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)2454 void blend_solid_vspan(int x, int y, unsigned len, 2455 const color_type& c, const int8u* covers) 2456 { 2457 do 2458 { 2459 blend_pix(pix_value_ptr(x, y++, 1), c, *covers++); 2460 } 2461 while (--len); 2462 } 2463 2464 //-------------------------------------------------------------------- copy_color_hspan(int x,int y,unsigned len,const color_type * colors)2465 void copy_color_hspan(int x, int y, 2466 unsigned len, 2467 const color_type* colors) 2468 { 2469 pixel_type* p = pix_value_ptr(x, y, len); 2470 2471 do 2472 { 2473 p->set(*colors++); 2474 p = p->next(); 2475 } 2476 while (--len); 2477 } 2478 2479 //-------------------------------------------------------------------- copy_color_vspan(int x,int y,unsigned len,const color_type * colors)2480 void copy_color_vspan(int x, int y, 2481 unsigned len, 2482 const color_type* colors) 2483 { 2484 do 2485 { 2486 pix_value_ptr(x, y++, 1)->set(*colors++); 2487 } 2488 while (--len); 2489 } 2490 2491 //-------------------------------------------------------------------- blend_color_hspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)2492 void blend_color_hspan(int x, int y, unsigned len, 2493 const color_type* colors, 2494 const int8u* covers, 2495 int8u cover) 2496 { 2497 pixel_type* p = pix_value_ptr(x, y, len); 2498 2499 do 2500 { 2501 blend_pix(p, *colors++, covers ? *covers++ : cover); 2502 p = p->next(); 2503 } 2504 while (--len); 2505 } 2506 2507 //-------------------------------------------------------------------- blend_color_vspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)2508 void blend_color_vspan(int x, int y, unsigned len, 2509 const color_type* colors, 2510 const int8u* covers, 2511 int8u cover) 2512 { 2513 do 2514 { 2515 blend_pix(pix_value_ptr(x, y++, 1), *colors++, covers ? *covers++ : cover); 2516 } 2517 while (--len); 2518 2519 } 2520 2521 //-------------------------------------------------------------------- for_each_pixel(Function f)2522 template<class Function> void for_each_pixel(Function f) 2523 { 2524 unsigned y; 2525 for (y = 0; y < height(); ++y) 2526 { 2527 row_data r = m_rbuf->row(y); 2528 if (r.ptr) 2529 { 2530 unsigned len = r.x2 - r.x1 + 1; 2531 pixel_type* p = pix_value_ptr(r.x1, y, len); 2532 do 2533 { 2534 f(p->c); 2535 p = p->next(); 2536 } 2537 while (--len); 2538 } 2539 } 2540 } 2541 2542 //-------------------------------------------------------------------- premultiply()2543 void premultiply() 2544 { 2545 for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); 2546 } 2547 2548 //-------------------------------------------------------------------- demultiply()2549 void demultiply() 2550 { 2551 for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); 2552 } 2553 2554 //-------------------------------------------------------------------- apply_gamma_dir(const GammaLut & g)2555 template<class GammaLut> void apply_gamma_dir(const GammaLut& g) 2556 { 2557 for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); 2558 } 2559 2560 //-------------------------------------------------------------------- apply_gamma_inv(const GammaLut & g)2561 template<class GammaLut> void apply_gamma_inv(const GammaLut& g) 2562 { 2563 for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g)); 2564 } 2565 2566 //-------------------------------------------------------------------- copy_from(const RenBuf2 & from,int xdst,int ydst,int xsrc,int ysrc,unsigned len)2567 template<class RenBuf2> void copy_from(const RenBuf2& from, 2568 int xdst, int ydst, 2569 int xsrc, int ysrc, 2570 unsigned len) 2571 { 2572 if (const int8u* p = from.row_ptr(ysrc)) 2573 { 2574 std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 2575 p + xsrc * pix_width, 2576 len * pix_width); 2577 } 2578 } 2579 2580 //-------------------------------------------------------------------- 2581 // Blend from another RGBA surface. 2582 template<class SrcPixelFormatRenderer> blend_from(const SrcPixelFormatRenderer & from,int xdst,int ydst,int xsrc,int ysrc,unsigned len,int8u cover)2583 void blend_from(const SrcPixelFormatRenderer& from, 2584 int xdst, int ydst, 2585 int xsrc, int ysrc, 2586 unsigned len, 2587 int8u cover) 2588 { 2589 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 2590 2591 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 2592 { 2593 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 2594 int srcinc = 1; 2595 int dstinc = 1; 2596 2597 if (xdst > xsrc) 2598 { 2599 psrc = psrc->advance(len - 1); 2600 pdst = pdst->advance(len - 1); 2601 srcinc = -1; 2602 dstinc = -1; 2603 } 2604 2605 do 2606 { 2607 blend_pix(pdst, psrc->get(), cover); 2608 psrc = psrc->advance(srcinc); 2609 pdst = pdst->advance(dstinc); 2610 } 2611 while (--len); 2612 } 2613 } 2614 2615 //-------------------------------------------------------------------- 2616 // Blend from single color, using grayscale surface as alpha channel. 2617 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)2618 void blend_from_color(const SrcPixelFormatRenderer& from, 2619 const color_type& color, 2620 int xdst, int ydst, 2621 int xsrc, int ysrc, 2622 unsigned len, 2623 int8u cover) 2624 { 2625 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 2626 typedef typename SrcPixelFormatRenderer::color_type src_color_type; 2627 2628 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 2629 { 2630 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 2631 2632 do 2633 { 2634 blend_pix(pdst, color, 2635 src_color_type::scale_cover(cover, psrc->c[0])); 2636 psrc = psrc->next(); 2637 pdst = pdst->next(); 2638 } 2639 while (--len); 2640 } 2641 } 2642 2643 //-------------------------------------------------------------------- 2644 // Blend from color table, using grayscale surface as indexes into table. 2645 // Obviously, this only works for integer value types. 2646 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)2647 void blend_from_lut(const SrcPixelFormatRenderer& from, 2648 const color_type* color_lut, 2649 int xdst, int ydst, 2650 int xsrc, int ysrc, 2651 unsigned len, 2652 int8u cover) 2653 { 2654 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 2655 2656 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 2657 { 2658 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 2659 2660 do 2661 { 2662 blend_pix(pdst, color_lut[psrc->c[0]], cover); 2663 psrc = psrc->next(); 2664 pdst = pdst->next(); 2665 } 2666 while (--len); 2667 } 2668 } 2669 2670 private: 2671 rbuf_type* m_rbuf; 2672 Blender m_blender; 2673 unsigned m_comp_op; 2674 }; 2675 2676 2677 //----------------------------------------------------------------------- 2678 typedef blender_rgba<rgba8, order_rgba> blender_rgba32; 2679 typedef blender_rgba<rgba8, order_argb> blender_argb32; 2680 typedef blender_rgba<rgba8, order_abgr> blender_abgr32; 2681 typedef blender_rgba<rgba8, order_bgra> blender_bgra32; 2682 2683 typedef blender_rgba<srgba8, order_rgba> blender_srgba32; 2684 typedef blender_rgba<srgba8, order_argb> blender_sargb32; 2685 typedef blender_rgba<srgba8, order_abgr> blender_sabgr32; 2686 typedef blender_rgba<srgba8, order_bgra> blender_sbgra32; 2687 2688 typedef blender_rgba_pre<rgba8, order_rgba> blender_rgba32_pre; 2689 typedef blender_rgba_pre<rgba8, order_argb> blender_argb32_pre; 2690 typedef blender_rgba_pre<rgba8, order_abgr> blender_abgr32_pre; 2691 typedef blender_rgba_pre<rgba8, order_bgra> blender_bgra32_pre; 2692 2693 typedef blender_rgba_pre<srgba8, order_rgba> blender_srgba32_pre; 2694 typedef blender_rgba_pre<srgba8, order_argb> blender_sargb32_pre; 2695 typedef blender_rgba_pre<srgba8, order_abgr> blender_sabgr32_pre; 2696 typedef blender_rgba_pre<srgba8, order_bgra> blender_sbgra32_pre; 2697 2698 typedef blender_rgba_plain<rgba8, order_rgba> blender_rgba32_plain; 2699 typedef blender_rgba_plain<rgba8, order_argb> blender_argb32_plain; 2700 typedef blender_rgba_plain<rgba8, order_abgr> blender_abgr32_plain; 2701 typedef blender_rgba_plain<rgba8, order_bgra> blender_bgra32_plain; 2702 2703 typedef blender_rgba_plain<srgba8, order_rgba> blender_srgba32_plain; 2704 typedef blender_rgba_plain<srgba8, order_argb> blender_sargb32_plain; 2705 typedef blender_rgba_plain<srgba8, order_abgr> blender_sabgr32_plain; 2706 typedef blender_rgba_plain<srgba8, order_bgra> blender_sbgra32_plain; 2707 2708 typedef blender_rgba<rgba16, order_rgba> blender_rgba64; 2709 typedef blender_rgba<rgba16, order_argb> blender_argb64; 2710 typedef blender_rgba<rgba16, order_abgr> blender_abgr64; 2711 typedef blender_rgba<rgba16, order_bgra> blender_bgra64; 2712 2713 typedef blender_rgba_pre<rgba16, order_rgba> blender_rgba64_pre; 2714 typedef blender_rgba_pre<rgba16, order_argb> blender_argb64_pre; 2715 typedef blender_rgba_pre<rgba16, order_abgr> blender_abgr64_pre; 2716 typedef blender_rgba_pre<rgba16, order_bgra> blender_bgra64_pre; 2717 2718 typedef blender_rgba_plain<rgba16, order_rgba> blender_rgba64_plain; 2719 typedef blender_rgba_plain<rgba16, order_argb> blender_argb64_plain; 2720 typedef blender_rgba_plain<rgba16, order_abgr> blender_abgr64_plain; 2721 typedef blender_rgba_plain<rgba16, order_bgra> blender_bgra64_plain; 2722 2723 typedef blender_rgba<rgba32, order_rgba> blender_rgba128; 2724 typedef blender_rgba<rgba32, order_argb> blender_argb128; 2725 typedef blender_rgba<rgba32, order_abgr> blender_abgr128; 2726 typedef blender_rgba<rgba32, order_bgra> blender_bgra128; 2727 2728 typedef blender_rgba_pre<rgba32, order_rgba> blender_rgba128_pre; 2729 typedef blender_rgba_pre<rgba32, order_argb> blender_argb128_pre; 2730 typedef blender_rgba_pre<rgba32, order_abgr> blender_abgr128_pre; 2731 typedef blender_rgba_pre<rgba32, order_bgra> blender_bgra128_pre; 2732 2733 typedef blender_rgba_plain<rgba32, order_rgba> blender_rgba128_plain; 2734 typedef blender_rgba_plain<rgba32, order_argb> blender_argb128_plain; 2735 typedef blender_rgba_plain<rgba32, order_abgr> blender_abgr128_plain; 2736 typedef blender_rgba_plain<rgba32, order_bgra> blender_bgra128_plain; 2737 2738 2739 //----------------------------------------------------------------------- 2740 typedef pixfmt_alpha_blend_rgba<blender_rgba32, rendering_buffer> pixfmt_rgba32; 2741 typedef pixfmt_alpha_blend_rgba<blender_argb32, rendering_buffer> pixfmt_argb32; 2742 typedef pixfmt_alpha_blend_rgba<blender_abgr32, rendering_buffer> pixfmt_abgr32; 2743 typedef pixfmt_alpha_blend_rgba<blender_bgra32, rendering_buffer> pixfmt_bgra32; 2744 2745 typedef pixfmt_alpha_blend_rgba<blender_srgba32, rendering_buffer> pixfmt_srgba32; 2746 typedef pixfmt_alpha_blend_rgba<blender_sargb32, rendering_buffer> pixfmt_sargb32; 2747 typedef pixfmt_alpha_blend_rgba<blender_sabgr32, rendering_buffer> pixfmt_sabgr32; 2748 typedef pixfmt_alpha_blend_rgba<blender_sbgra32, rendering_buffer> pixfmt_sbgra32; 2749 2750 typedef pixfmt_alpha_blend_rgba<blender_rgba32_pre, rendering_buffer> pixfmt_rgba32_pre; 2751 typedef pixfmt_alpha_blend_rgba<blender_argb32_pre, rendering_buffer> pixfmt_argb32_pre; 2752 typedef pixfmt_alpha_blend_rgba<blender_abgr32_pre, rendering_buffer> pixfmt_abgr32_pre; 2753 typedef pixfmt_alpha_blend_rgba<blender_bgra32_pre, rendering_buffer> pixfmt_bgra32_pre; 2754 2755 typedef pixfmt_alpha_blend_rgba<blender_srgba32_pre, rendering_buffer> pixfmt_srgba32_pre; 2756 typedef pixfmt_alpha_blend_rgba<blender_sargb32_pre, rendering_buffer> pixfmt_sargb32_pre; 2757 typedef pixfmt_alpha_blend_rgba<blender_sabgr32_pre, rendering_buffer> pixfmt_sabgr32_pre; 2758 typedef pixfmt_alpha_blend_rgba<blender_sbgra32_pre, rendering_buffer> pixfmt_sbgra32_pre; 2759 2760 typedef pixfmt_alpha_blend_rgba<blender_rgba32_plain, rendering_buffer> pixfmt_rgba32_plain; 2761 typedef pixfmt_alpha_blend_rgba<blender_argb32_plain, rendering_buffer> pixfmt_argb32_plain; 2762 typedef pixfmt_alpha_blend_rgba<blender_abgr32_plain, rendering_buffer> pixfmt_abgr32_plain; 2763 typedef pixfmt_alpha_blend_rgba<blender_bgra32_plain, rendering_buffer> pixfmt_bgra32_plain; 2764 2765 typedef pixfmt_alpha_blend_rgba<blender_srgba32_plain, rendering_buffer> pixfmt_srgba32_plain; 2766 typedef pixfmt_alpha_blend_rgba<blender_sargb32_plain, rendering_buffer> pixfmt_sargb32_plain; 2767 typedef pixfmt_alpha_blend_rgba<blender_sabgr32_plain, rendering_buffer> pixfmt_sabgr32_plain; 2768 typedef pixfmt_alpha_blend_rgba<blender_sbgra32_plain, rendering_buffer> pixfmt_sbgra32_plain; 2769 2770 typedef pixfmt_alpha_blend_rgba<blender_rgba64, rendering_buffer> pixfmt_rgba64; 2771 typedef pixfmt_alpha_blend_rgba<blender_argb64, rendering_buffer> pixfmt_argb64; 2772 typedef pixfmt_alpha_blend_rgba<blender_abgr64, rendering_buffer> pixfmt_abgr64; 2773 typedef pixfmt_alpha_blend_rgba<blender_bgra64, rendering_buffer> pixfmt_bgra64; 2774 2775 typedef pixfmt_alpha_blend_rgba<blender_rgba64_pre, rendering_buffer> pixfmt_rgba64_pre; 2776 typedef pixfmt_alpha_blend_rgba<blender_argb64_pre, rendering_buffer> pixfmt_argb64_pre; 2777 typedef pixfmt_alpha_blend_rgba<blender_abgr64_pre, rendering_buffer> pixfmt_abgr64_pre; 2778 typedef pixfmt_alpha_blend_rgba<blender_bgra64_pre, rendering_buffer> pixfmt_bgra64_pre; 2779 2780 typedef pixfmt_alpha_blend_rgba<blender_rgba64_plain, rendering_buffer> pixfmt_rgba64_plain; 2781 typedef pixfmt_alpha_blend_rgba<blender_argb64_plain, rendering_buffer> pixfmt_argb64_plain; 2782 typedef pixfmt_alpha_blend_rgba<blender_abgr64_plain, rendering_buffer> pixfmt_abgr64_plain; 2783 typedef pixfmt_alpha_blend_rgba<blender_bgra64_plain, rendering_buffer> pixfmt_bgra64_plain; 2784 2785 typedef pixfmt_alpha_blend_rgba<blender_rgba128, rendering_buffer> pixfmt_rgba128; 2786 typedef pixfmt_alpha_blend_rgba<blender_argb128, rendering_buffer> pixfmt_argb128; 2787 typedef pixfmt_alpha_blend_rgba<blender_abgr128, rendering_buffer> pixfmt_abgr128; 2788 typedef pixfmt_alpha_blend_rgba<blender_bgra128, rendering_buffer> pixfmt_bgra128; 2789 2790 typedef pixfmt_alpha_blend_rgba<blender_rgba128_pre, rendering_buffer> pixfmt_rgba128_pre; 2791 typedef pixfmt_alpha_blend_rgba<blender_argb128_pre, rendering_buffer> pixfmt_argb128_pre; 2792 typedef pixfmt_alpha_blend_rgba<blender_abgr128_pre, rendering_buffer> pixfmt_abgr128_pre; 2793 typedef pixfmt_alpha_blend_rgba<blender_bgra128_pre, rendering_buffer> pixfmt_bgra128_pre; 2794 2795 typedef pixfmt_alpha_blend_rgba<blender_rgba128_plain, rendering_buffer> pixfmt_rgba128_plain; 2796 typedef pixfmt_alpha_blend_rgba<blender_argb128_plain, rendering_buffer> pixfmt_argb128_plain; 2797 typedef pixfmt_alpha_blend_rgba<blender_abgr128_plain, rendering_buffer> pixfmt_abgr128_plain; 2798 typedef pixfmt_alpha_blend_rgba<blender_bgra128_plain, rendering_buffer> pixfmt_bgra128_plain; 2799 2800 } 2801 2802 #endif 2803 2804