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_RGB_INCLUDED 25 #define AGG_PIXFMT_RGB_INCLUDED 26 27 #include <string.h> 28 #include "agg_pixfmt_base.h" 29 #include "agg_rendering_buffer.h" 30 31 namespace agg 32 { 33 34 //=====================================================apply_gamma_dir_rgb 35 template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb 36 { 37 public: 38 typedef typename ColorT::value_type value_type; 39 apply_gamma_dir_rgb(const GammaLut & gamma)40 apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {} 41 operator()42 AGG_INLINE void operator () (value_type* p) 43 { 44 p[Order::R] = m_gamma.dir(p[Order::R]); 45 p[Order::G] = m_gamma.dir(p[Order::G]); 46 p[Order::B] = m_gamma.dir(p[Order::B]); 47 } 48 49 private: 50 const GammaLut& m_gamma; 51 }; 52 53 54 55 //=====================================================apply_gamma_inv_rgb 56 template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb 57 { 58 public: 59 typedef typename ColorT::value_type value_type; 60 apply_gamma_inv_rgb(const GammaLut & gamma)61 apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {} 62 operator()63 AGG_INLINE void operator () (value_type* p) 64 { 65 p[Order::R] = m_gamma.inv(p[Order::R]); 66 p[Order::G] = m_gamma.inv(p[Order::G]); 67 p[Order::B] = m_gamma.inv(p[Order::B]); 68 } 69 70 private: 71 const GammaLut& m_gamma; 72 }; 73 74 75 //=========================================================blender_rgb 76 template<class ColorT, class Order> 77 struct blender_rgb 78 { 79 typedef ColorT color_type; 80 typedef Order order_type; 81 typedef typename color_type::value_type value_type; 82 typedef typename color_type::calc_type calc_type; 83 typedef typename color_type::long_type long_type; 84 85 // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's 86 // compositing function. Since the render buffer is opaque we skip the 87 // initial premultiply and final demultiply. 88 89 //-------------------------------------------------------------------- blend_pixblender_rgb90 static AGG_INLINE void blend_pix(value_type* p, 91 value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) 92 { 93 blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); 94 } 95 96 //-------------------------------------------------------------------- blend_pixblender_rgb97 static AGG_INLINE void blend_pix(value_type* p, 98 value_type cr, value_type cg, value_type cb, value_type alpha) 99 { 100 p[Order::R] = color_type::lerp(p[Order::R], cr, alpha); 101 p[Order::G] = color_type::lerp(p[Order::G], cg, alpha); 102 p[Order::B] = color_type::lerp(p[Order::B], cb, alpha); 103 } 104 }; 105 106 //======================================================blender_rgb_pre 107 template<class ColorT, class Order> 108 struct blender_rgb_pre 109 { 110 typedef ColorT color_type; 111 typedef Order order_type; 112 typedef typename color_type::value_type value_type; 113 typedef typename color_type::calc_type calc_type; 114 typedef typename color_type::long_type long_type; 115 116 // Blend pixels using the premultiplied form of Alvy-Ray Smith's 117 // compositing function. 118 119 //-------------------------------------------------------------------- blend_pixblender_rgb_pre120 static AGG_INLINE void blend_pix(value_type* p, 121 value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) 122 { 123 blend_pix(p, 124 color_type::mult_cover(cr, cover), 125 color_type::mult_cover(cg, cover), 126 color_type::mult_cover(cb, cover), 127 color_type::mult_cover(alpha, cover)); 128 } 129 130 //-------------------------------------------------------------------- blend_pixblender_rgb_pre131 static AGG_INLINE void blend_pix(value_type* p, 132 value_type cr, value_type cg, value_type cb, value_type alpha) 133 { 134 p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha); 135 p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha); 136 p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha); 137 } 138 }; 139 140 //===================================================blender_rgb_gamma 141 template<class ColorT, class Order, class Gamma> 142 class blender_rgb_gamma : public blender_base<ColorT, Order> 143 { 144 public: 145 typedef ColorT color_type; 146 typedef Order order_type; 147 typedef Gamma gamma_type; 148 typedef typename color_type::value_type value_type; 149 typedef typename color_type::calc_type calc_type; 150 typedef typename color_type::long_type long_type; 151 152 //-------------------------------------------------------------------- blender_rgb_gamma()153 blender_rgb_gamma() : m_gamma(0) {} gamma(const gamma_type & g)154 void gamma(const gamma_type& g) { m_gamma = &g; } 155 156 //-------------------------------------------------------------------- blend_pix(value_type * p,value_type cr,value_type cg,value_type cb,value_type alpha,cover_type cover)157 AGG_INLINE void blend_pix(value_type* p, 158 value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) 159 { 160 blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); 161 } 162 163 //-------------------------------------------------------------------- blend_pix(value_type * p,value_type cr,value_type cg,value_type cb,value_type alpha)164 AGG_INLINE void blend_pix(value_type* p, 165 value_type cr, value_type cg, value_type cb, value_type alpha) 166 { 167 calc_type r = m_gamma->dir(p[Order::R]); 168 calc_type g = m_gamma->dir(p[Order::G]); 169 calc_type b = m_gamma->dir(p[Order::B]); 170 p[Order::R] = m_gamma->inv(color_type::downscale((m_gamma->dir(cr) - r) * alpha) + r); 171 p[Order::G] = m_gamma->inv(color_type::downscale((m_gamma->dir(cg) - g) * alpha) + g); 172 p[Order::B] = m_gamma->inv(color_type::downscale((m_gamma->dir(cb) - b) * alpha) + b); 173 } 174 175 private: 176 const gamma_type* m_gamma; 177 }; 178 179 180 //==================================================pixfmt_alpha_blend_rgb 181 template<class Blender, class RenBuf, unsigned Step, unsigned Offset = 0> 182 class pixfmt_alpha_blend_rgb 183 { 184 public: 185 typedef pixfmt_rgb_tag pixfmt_category; 186 typedef RenBuf rbuf_type; 187 typedef Blender blender_type; 188 typedef typename rbuf_type::row_data row_data; 189 typedef typename blender_type::color_type color_type; 190 typedef typename blender_type::order_type order_type; 191 typedef typename color_type::value_type value_type; 192 typedef typename color_type::calc_type calc_type; 193 enum 194 { 195 num_components = 3, 196 pix_step = Step, 197 pix_offset = Offset, 198 pix_width = sizeof(value_type) * pix_step 199 }; 200 struct pixel_type 201 { 202 value_type c[num_components]; 203 setpixel_type204 void set(value_type r, value_type g, value_type b) 205 { 206 c[order_type::R] = r; 207 c[order_type::G] = g; 208 c[order_type::B] = b; 209 } 210 setpixel_type211 void set(const color_type& color) 212 { 213 set(color.r, color.g, color.b); 214 } 215 getpixel_type216 void get(value_type& r, value_type& g, value_type& b) const 217 { 218 r = c[order_type::R]; 219 g = c[order_type::G]; 220 b = c[order_type::B]; 221 } 222 getpixel_type223 color_type get() const 224 { 225 return color_type( 226 c[order_type::R], 227 c[order_type::G], 228 c[order_type::B]); 229 } 230 nextpixel_type231 pixel_type* next() 232 { 233 return (pixel_type*)(c + pix_step); 234 } 235 nextpixel_type236 const pixel_type* next() const 237 { 238 return (const pixel_type*)(c + pix_step); 239 } 240 advancepixel_type241 pixel_type* advance(int n) 242 { 243 return (pixel_type*)(c + n * pix_step); 244 } 245 advancepixel_type246 const pixel_type* advance(int n) const 247 { 248 return (const pixel_type*)(c + n * pix_step); 249 } 250 }; 251 252 private: 253 //-------------------------------------------------------------------- blend_pix(pixel_type * p,value_type r,value_type g,value_type b,value_type a,unsigned cover)254 AGG_INLINE void blend_pix(pixel_type* p, 255 value_type r, value_type g, value_type b, value_type a, 256 unsigned cover) 257 { 258 m_blender.blend_pix(p->c, r, g, b, a, cover); 259 } 260 261 //-------------------------------------------------------------------- blend_pix(pixel_type * p,value_type r,value_type g,value_type b,value_type a)262 AGG_INLINE void blend_pix(pixel_type* p, 263 value_type r, value_type g, value_type b, value_type a) 264 { 265 m_blender.blend_pix(p->c, r, g, b, a); 266 } 267 268 //-------------------------------------------------------------------- blend_pix(pixel_type * p,const color_type & c,unsigned cover)269 AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) 270 { 271 m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); 272 } 273 274 //-------------------------------------------------------------------- blend_pix(pixel_type * p,const color_type & c)275 AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) 276 { 277 m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); 278 } 279 280 //-------------------------------------------------------------------- copy_or_blend_pix(pixel_type * p,const color_type & c,unsigned cover)281 AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) 282 { 283 if (!c.is_transparent()) 284 { 285 if (c.is_opaque() && cover == cover_mask) 286 { 287 p->set(c); 288 } 289 else 290 { 291 blend_pix(p, c, cover); 292 } 293 } 294 } 295 296 //-------------------------------------------------------------------- copy_or_blend_pix(pixel_type * p,const color_type & c)297 AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) 298 { 299 if (!c.is_transparent()) 300 { 301 if (c.is_opaque()) 302 { 303 p->set(c); 304 } 305 else 306 { 307 blend_pix(p, c); 308 } 309 } 310 } 311 312 public: 313 //-------------------------------------------------------------------- pixfmt_alpha_blend_rgb(rbuf_type & rb)314 explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) : 315 m_rbuf(&rb) 316 {} attach(rbuf_type & rb)317 void attach(rbuf_type& rb) { m_rbuf = &rb; } 318 319 //-------------------------------------------------------------------- 320 template<class PixFmt> attach(PixFmt & pixf,int x1,int y1,int x2,int y2)321 bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) 322 { 323 rect_i r(x1, y1, x2, y2); 324 if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) 325 { 326 int stride = pixf.stride(); 327 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 328 (r.x2 - r.x1) + 1, 329 (r.y2 - r.y1) + 1, 330 stride); 331 return true; 332 } 333 return false; 334 } 335 336 //-------------------------------------------------------------------- blender()337 Blender& blender() { return m_blender; } 338 339 //-------------------------------------------------------------------- width()340 AGG_INLINE unsigned width() const { return m_rbuf->width(); } height()341 AGG_INLINE unsigned height() const { return m_rbuf->height(); } stride()342 AGG_INLINE int stride() const { return m_rbuf->stride(); } 343 344 //-------------------------------------------------------------------- row_ptr(int y)345 AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } row_ptr(int y)346 AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } row(int y)347 AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } 348 349 //-------------------------------------------------------------------- pix_ptr(int x,int y)350 AGG_INLINE int8u* pix_ptr(int x, int y) 351 { 352 return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); 353 } 354 pix_ptr(int x,int y)355 AGG_INLINE const int8u* pix_ptr(int x, int y) const 356 { 357 return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); 358 } 359 360 // Return pointer to pixel value, forcing row to be allocated. pix_value_ptr(int x,int y,unsigned len)361 AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) 362 { 363 return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset)); 364 } 365 366 // Return pointer to pixel value, or null if row not allocated. pix_value_ptr(int x,int y)367 AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const 368 { 369 int8u* p = m_rbuf->row_ptr(y); 370 return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0; 371 } 372 373 // Get pixel pointer from raw buffer pointer. pix_value_ptr(void * p)374 AGG_INLINE static pixel_type* pix_value_ptr(void* p) 375 { 376 return (pixel_type*)((value_type*)p + pix_offset); 377 } 378 379 // Get pixel pointer from raw buffer pointer. pix_value_ptr(const void * p)380 AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) 381 { 382 return (const pixel_type*)((const value_type*)p + pix_offset); 383 } 384 385 //-------------------------------------------------------------------- write_plain_color(void * p,color_type c)386 AGG_INLINE static void write_plain_color(void* p, color_type c) 387 { 388 // RGB formats are implicitly premultiplied. 389 c.premultiply(); 390 pix_value_ptr(p)->set(c); 391 } 392 393 //-------------------------------------------------------------------- read_plain_color(const void * p)394 AGG_INLINE static color_type read_plain_color(const void* p) 395 { 396 return pix_value_ptr(p)->get(); 397 } 398 399 //-------------------------------------------------------------------- make_pix(int8u * p,const color_type & c)400 AGG_INLINE static void make_pix(int8u* p, const color_type& c) 401 { 402 ((pixel_type*)p)->set(c); 403 } 404 405 //-------------------------------------------------------------------- pixel(int x,int y)406 AGG_INLINE color_type pixel(int x, int y) const 407 { 408 if (const pixel_type* p = pix_value_ptr(x, y)) 409 { 410 return p->get(); 411 } 412 return color_type::no_color(); 413 } 414 415 //-------------------------------------------------------------------- copy_pixel(int x,int y,const color_type & c)416 AGG_INLINE void copy_pixel(int x, int y, const color_type& c) 417 { 418 pix_value_ptr(x, y, 1)->set(c); 419 } 420 421 //-------------------------------------------------------------------- blend_pixel(int x,int y,const color_type & c,int8u cover)422 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) 423 { 424 copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover); 425 } 426 427 //-------------------------------------------------------------------- copy_hline(int x,int y,unsigned len,const color_type & c)428 AGG_INLINE void copy_hline(int x, int y, 429 unsigned len, 430 const color_type& c) 431 { 432 pixel_type* p = pix_value_ptr(x, y, len); 433 do 434 { 435 p->set(c); 436 p = p->next(); 437 } 438 while(--len); 439 } 440 441 442 //-------------------------------------------------------------------- copy_vline(int x,int y,unsigned len,const color_type & c)443 AGG_INLINE void copy_vline(int x, int y, 444 unsigned len, 445 const color_type& c) 446 { 447 do 448 { 449 pix_value_ptr(x, y++, 1)->set(c); 450 } 451 while (--len); 452 } 453 454 //-------------------------------------------------------------------- blend_hline(int x,int y,unsigned len,const color_type & c,int8u cover)455 void blend_hline(int x, int y, 456 unsigned len, 457 const color_type& c, 458 int8u cover) 459 { 460 if (!c.is_transparent()) 461 { 462 pixel_type* p = pix_value_ptr(x, y, len); 463 464 if (c.is_opaque() && cover == cover_mask) 465 { 466 do 467 { 468 p->set(c); 469 p = p->next(); 470 } 471 while (--len); 472 } 473 else 474 { 475 do 476 { 477 blend_pix(p, c, cover); 478 p = p->next(); 479 } 480 while (--len); 481 } 482 } 483 } 484 485 486 //-------------------------------------------------------------------- blend_vline(int x,int y,unsigned len,const color_type & c,int8u cover)487 void blend_vline(int x, int y, 488 unsigned len, 489 const color_type& c, 490 int8u cover) 491 { 492 if (!c.is_transparent()) 493 { 494 if (c.is_opaque() && cover == cover_mask) 495 { 496 do 497 { 498 pix_value_ptr(x, y++, 1)->set(c); 499 } 500 while (--len); 501 } 502 else 503 { 504 do 505 { 506 blend_pix(pix_value_ptr(x, y++, 1), c, cover); 507 } 508 while (--len); 509 } 510 } 511 } 512 513 //-------------------------------------------------------------------- blend_solid_hspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)514 void blend_solid_hspan(int x, int y, 515 unsigned len, 516 const color_type& c, 517 const int8u* covers) 518 { 519 if (!c.is_transparent()) 520 { 521 pixel_type* p = pix_value_ptr(x, y, len); 522 523 do 524 { 525 if (c.is_opaque() && *covers == cover_mask) 526 { 527 p->set(c); 528 } 529 else 530 { 531 blend_pix(p, c, *covers); 532 } 533 p = p->next(); 534 ++covers; 535 } 536 while (--len); 537 } 538 } 539 540 541 //-------------------------------------------------------------------- blend_solid_vspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)542 void blend_solid_vspan(int x, int y, 543 unsigned len, 544 const color_type& c, 545 const int8u* covers) 546 { 547 if (!c.is_transparent()) 548 { 549 do 550 { 551 pixel_type* p = pix_value_ptr(x, y++, 1); 552 553 if (c.is_opaque() && *covers == cover_mask) 554 { 555 p->set(c); 556 } 557 else 558 { 559 blend_pix(p, c, *covers); 560 } 561 ++covers; 562 } 563 while (--len); 564 } 565 } 566 567 //-------------------------------------------------------------------- copy_color_hspan(int x,int y,unsigned len,const color_type * colors)568 void copy_color_hspan(int x, int y, 569 unsigned len, 570 const color_type* colors) 571 { 572 pixel_type* p = pix_value_ptr(x, y, len); 573 574 do 575 { 576 p->set(*colors++); 577 p = p->next(); 578 } 579 while (--len); 580 } 581 582 583 //-------------------------------------------------------------------- copy_color_vspan(int x,int y,unsigned len,const color_type * colors)584 void copy_color_vspan(int x, int y, 585 unsigned len, 586 const color_type* colors) 587 { 588 do 589 { 590 pix_value_ptr(x, y++, 1)->set(*colors++); 591 } 592 while (--len); 593 } 594 595 //-------------------------------------------------------------------- blend_color_hspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)596 void blend_color_hspan(int x, int y, 597 unsigned len, 598 const color_type* colors, 599 const int8u* covers, 600 int8u cover) 601 { 602 pixel_type* p = pix_value_ptr(x, y, len); 603 604 if (covers) 605 { 606 do 607 { 608 copy_or_blend_pix(p, *colors++, *covers++); 609 p = p->next(); 610 } 611 while (--len); 612 } 613 else 614 { 615 if (cover == cover_mask) 616 { 617 do 618 { 619 copy_or_blend_pix(p, *colors++); 620 p = p->next(); 621 } 622 while (--len); 623 } 624 else 625 { 626 do 627 { 628 copy_or_blend_pix(p, *colors++, cover); 629 p = p->next(); 630 } 631 while (--len); 632 } 633 } 634 } 635 636 //-------------------------------------------------------------------- blend_color_vspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)637 void blend_color_vspan(int x, int y, 638 unsigned len, 639 const color_type* colors, 640 const int8u* covers, 641 int8u cover) 642 { 643 if (covers) 644 { 645 do 646 { 647 copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); 648 } 649 while (--len); 650 } 651 else 652 { 653 if (cover == cover_mask) 654 { 655 do 656 { 657 copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); 658 } 659 while (--len); 660 } 661 else 662 { 663 do 664 { 665 copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); 666 } 667 while (--len); 668 } 669 } 670 } 671 672 //-------------------------------------------------------------------- for_each_pixel(Function f)673 template<class Function> void for_each_pixel(Function f) 674 { 675 for (unsigned y = 0; y < height(); ++y) 676 { 677 row_data r = m_rbuf->row(y); 678 if (r.ptr) 679 { 680 unsigned len = r.x2 - r.x1 + 1; 681 pixel_type* p = pix_value_ptr(r.x1, y, len); 682 do 683 { 684 f(p->c); 685 p = p->next(); 686 } 687 while (--len); 688 } 689 } 690 } 691 692 //-------------------------------------------------------------------- apply_gamma_dir(const GammaLut & g)693 template<class GammaLut> void apply_gamma_dir(const GammaLut& g) 694 { 695 for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g)); 696 } 697 698 //-------------------------------------------------------------------- apply_gamma_inv(const GammaLut & g)699 template<class GammaLut> void apply_gamma_inv(const GammaLut& g) 700 { 701 for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g)); 702 } 703 704 //-------------------------------------------------------------------- 705 template<class RenBuf2> copy_from(const RenBuf2 & from,int xdst,int ydst,int xsrc,int ysrc,unsigned len)706 void copy_from(const RenBuf2& from, 707 int xdst, int ydst, 708 int xsrc, int ysrc, 709 unsigned len) 710 { 711 if (const int8u* p = from.row_ptr(ysrc)) 712 { 713 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 714 p + xsrc * pix_width, 715 len * pix_width); 716 } 717 } 718 719 //-------------------------------------------------------------------- 720 // Blend from an RGBA surface. 721 template<class SrcPixelFormatRenderer> blend_from(const SrcPixelFormatRenderer & from,int xdst,int ydst,int xsrc,int ysrc,unsigned len,int8u cover)722 void blend_from(const SrcPixelFormatRenderer& from, 723 int xdst, int ydst, 724 int xsrc, int ysrc, 725 unsigned len, 726 int8u cover) 727 { 728 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 729 typedef typename SrcPixelFormatRenderer::order_type src_order; 730 731 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 732 { 733 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 734 735 if (cover == cover_mask) 736 { 737 do 738 { 739 value_type alpha = psrc->c[src_order::A]; 740 if (alpha <= color_type::empty_value()) 741 { 742 if (alpha >= color_type::full_value()) 743 { 744 pdst->c[order_type::R] = psrc->c[src_order::R]; 745 pdst->c[order_type::G] = psrc->c[src_order::G]; 746 pdst->c[order_type::B] = psrc->c[src_order::B]; 747 } 748 else 749 { 750 blend_pix(pdst, 751 psrc->c[src_order::R], 752 psrc->c[src_order::G], 753 psrc->c[src_order::B], 754 alpha); 755 } 756 } 757 psrc = psrc->next(); 758 pdst = pdst->next(); 759 } 760 while(--len); 761 } 762 else 763 { 764 do 765 { 766 copy_or_blend_pix(pdst, psrc->get(), cover); 767 psrc = psrc->next(); 768 pdst = pdst->next(); 769 } 770 while (--len); 771 } 772 } 773 } 774 775 //-------------------------------------------------------------------- 776 // Blend from single color, using grayscale surface as alpha channel. 777 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)778 void blend_from_color(const SrcPixelFormatRenderer& from, 779 const color_type& color, 780 int xdst, int ydst, 781 int xsrc, int ysrc, 782 unsigned len, 783 int8u cover) 784 { 785 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 786 typedef typename SrcPixelFormatRenderer::color_type src_color_type; 787 788 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 789 { 790 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 791 792 do 793 { 794 copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0])); 795 psrc = psrc->next(); 796 pdst = pdst->next(); 797 } 798 while (--len); 799 } 800 } 801 802 //-------------------------------------------------------------------- 803 // Blend from color table, using grayscale surface as indexes into table. 804 // Obviously, this only works for integer value types. 805 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)806 void blend_from_lut(const SrcPixelFormatRenderer& from, 807 const color_type* color_lut, 808 int xdst, int ydst, 809 int xsrc, int ysrc, 810 unsigned len, 811 int8u cover) 812 { 813 typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; 814 815 if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) 816 { 817 pixel_type* pdst = pix_value_ptr(xdst, ydst, len); 818 819 if (cover == cover_mask) 820 { 821 do 822 { 823 const color_type& color = color_lut[psrc->c[0]]; 824 blend_pix(pdst, color); 825 psrc = psrc->next(); 826 pdst = pdst->next(); 827 } 828 while(--len); 829 } 830 else 831 { 832 do 833 { 834 copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); 835 psrc = psrc->next(); 836 pdst = pdst->next(); 837 } 838 while(--len); 839 } 840 } 841 } 842 843 private: 844 rbuf_type* m_rbuf; 845 Blender m_blender; 846 }; 847 848 //----------------------------------------------------------------------- 849 typedef blender_rgb<rgba8, order_rgb> blender_rgb24; 850 typedef blender_rgb<rgba8, order_bgr> blender_bgr24; 851 typedef blender_rgb<srgba8, order_rgb> blender_srgb24; 852 typedef blender_rgb<srgba8, order_bgr> blender_sbgr24; 853 typedef blender_rgb<rgba16, order_rgb> blender_rgb48; 854 typedef blender_rgb<rgba16, order_bgr> blender_bgr48; 855 typedef blender_rgb<rgba32, order_rgb> blender_rgb96; 856 typedef blender_rgb<rgba32, order_bgr> blender_bgr96; 857 858 typedef blender_rgb_pre<rgba8, order_rgb> blender_rgb24_pre; 859 typedef blender_rgb_pre<rgba8, order_bgr> blender_bgr24_pre; 860 typedef blender_rgb_pre<srgba8, order_rgb> blender_srgb24_pre; 861 typedef blender_rgb_pre<srgba8, order_bgr> blender_sbgr24_pre; 862 typedef blender_rgb_pre<rgba16, order_rgb> blender_rgb48_pre; 863 typedef blender_rgb_pre<rgba16, order_bgr> blender_bgr48_pre; 864 typedef blender_rgb_pre<rgba32, order_rgb> blender_rgb96_pre; 865 typedef blender_rgb_pre<rgba32, order_bgr> blender_bgr96_pre; 866 867 typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 3> pixfmt_rgb24; 868 typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 3> pixfmt_bgr24; 869 typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 3> pixfmt_srgb24; 870 typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 3> pixfmt_sbgr24; 871 typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 3> pixfmt_rgb48; 872 typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 3> pixfmt_bgr48; 873 typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 3> pixfmt_rgb96; 874 typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 3> pixfmt_bgr96; 875 876 typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 3> pixfmt_rgb24_pre; 877 typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 3> pixfmt_bgr24_pre; 878 typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 3> pixfmt_srgb24_pre; 879 typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 3> pixfmt_sbgr24_pre; 880 typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 3> pixfmt_rgb48_pre; 881 typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 3> pixfmt_bgr48_pre; 882 typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 3> pixfmt_rgb96_pre; 883 typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 3> pixfmt_bgr96_pre; 884 885 typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 0> pixfmt_rgbx32; 886 typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 1> pixfmt_xrgb32; 887 typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 1> pixfmt_xbgr32; 888 typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 0> pixfmt_bgrx32; 889 typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 0> pixfmt_srgbx32; 890 typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 1> pixfmt_sxrgb32; 891 typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 1> pixfmt_sxbgr32; 892 typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 0> pixfmt_sbgrx32; 893 typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 0> pixfmt_rgbx64; 894 typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 1> pixfmt_xrgb64; 895 typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 1> pixfmt_xbgr64; 896 typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 0> pixfmt_bgrx64; 897 typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 0> pixfmt_rgbx128; 898 typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 1> pixfmt_xrgb128; 899 typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 1> pixfmt_xbgr128; 900 typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 0> pixfmt_bgrx128; 901 902 typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 0> pixfmt_rgbx32_pre; 903 typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 1> pixfmt_xrgb32_pre; 904 typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 1> pixfmt_xbgr32_pre; 905 typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 0> pixfmt_bgrx32_pre; 906 typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 0> pixfmt_srgbx32_pre; 907 typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 1> pixfmt_sxrgb32_pre; 908 typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 1> pixfmt_sxbgr32_pre; 909 typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 0> pixfmt_sbgrx32_pre; 910 typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 0> pixfmt_rgbx64_pre; 911 typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 1> pixfmt_xrgb64_pre; 912 typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 1> pixfmt_xbgr64_pre; 913 typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 0> pixfmt_bgrx64_pre; 914 typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 0> pixfmt_rgbx128_pre; 915 typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 1> pixfmt_xrgb128_pre; 916 typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 1> pixfmt_xbgr128_pre; 917 typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 0> pixfmt_bgrx128_pre; 918 919 920 //-----------------------------------------------------pixfmt_rgb24_gamma 921 template<class Gamma> class pixfmt_rgb24_gamma : 922 public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3> 923 { 924 public: pixfmt_rgb24_gamma(rendering_buffer & rb,const Gamma & g)925 pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : 926 pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb) 927 { 928 this->blender().gamma(g); 929 } 930 }; 931 932 //-----------------------------------------------------pixfmt_srgb24_gamma 933 template<class Gamma> class pixfmt_srgb24_gamma : 934 public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3> 935 { 936 public: pixfmt_srgb24_gamma(rendering_buffer & rb,const Gamma & g)937 pixfmt_srgb24_gamma(rendering_buffer& rb, const Gamma& g) : 938 pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb) 939 { 940 this->blender().gamma(g); 941 } 942 }; 943 944 //-----------------------------------------------------pixfmt_bgr24_gamma 945 template<class Gamma> class pixfmt_bgr24_gamma : 946 public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3> 947 { 948 public: pixfmt_bgr24_gamma(rendering_buffer & rb,const Gamma & g)949 pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : 950 pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb) 951 { 952 this->blender().gamma(g); 953 } 954 }; 955 956 //-----------------------------------------------------pixfmt_sbgr24_gamma 957 template<class Gamma> class pixfmt_sbgr24_gamma : 958 public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3> 959 { 960 public: pixfmt_sbgr24_gamma(rendering_buffer & rb,const Gamma & g)961 pixfmt_sbgr24_gamma(rendering_buffer& rb, const Gamma& g) : 962 pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb) 963 { 964 this->blender().gamma(g); 965 } 966 }; 967 968 //-----------------------------------------------------pixfmt_rgb48_gamma 969 template<class Gamma> class pixfmt_rgb48_gamma : 970 public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3> 971 { 972 public: pixfmt_rgb48_gamma(rendering_buffer & rb,const Gamma & g)973 pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) : 974 pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>(rb) 975 { 976 this->blender().gamma(g); 977 } 978 }; 979 980 //-----------------------------------------------------pixfmt_bgr48_gamma 981 template<class Gamma> class pixfmt_bgr48_gamma : 982 public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3> 983 { 984 public: pixfmt_bgr48_gamma(rendering_buffer & rb,const Gamma & g)985 pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) : 986 pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>(rb) 987 { 988 this->blender().gamma(g); 989 } 990 }; 991 992 } 993 994 #endif 995 996