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_GRAY_INCLUDED 25 #define AGG_PIXFMT_GRAY_INCLUDED 26 27 #include <string.h> 28 #include "agg_basics.h" 29 #include "agg_color_gray.h" 30 #include "agg_rendering_buffer.h" 31 32 namespace agg 33 { 34 35 //============================================================blender_gray 36 template<class ColorT> struct blender_gray 37 { 38 typedef ColorT color_type; 39 typedef typename color_type::value_type value_type; 40 typedef typename color_type::calc_type calc_type; 41 enum base_scale_e { base_shift = color_type::base_shift }; 42 43 static AGG_INLINE void blend_pix(value_type* p, unsigned cv, 44 unsigned alpha, unsigned cover=0) 45 { 46 *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift); 47 } 48 }; 49 50 51 //======================================================blender_gray_pre 52 template<class ColorT> struct blender_gray_pre 53 { 54 typedef ColorT color_type; 55 typedef typename color_type::value_type value_type; 56 typedef typename color_type::calc_type calc_type; 57 enum base_scale_e { base_shift = color_type::base_shift }; 58 blend_pixblender_gray_pre59 static AGG_INLINE void blend_pix(value_type* p, unsigned cv, 60 unsigned alpha, unsigned cover) 61 { 62 alpha = color_type::base_mask - alpha; 63 cover = (cover + 1) << (base_shift - 8); 64 *p = (value_type)((*p * alpha + cv * cover) >> base_shift); 65 } 66 blend_pixblender_gray_pre67 static AGG_INLINE void blend_pix(value_type* p, unsigned cv, 68 unsigned alpha) 69 { 70 *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv); 71 } 72 }; 73 74 75 76 //=====================================================apply_gamma_dir_gray 77 template<class ColorT, class GammaLut> class apply_gamma_dir_gray 78 { 79 public: 80 typedef typename ColorT::value_type value_type; 81 apply_gamma_dir_gray(const GammaLut & gamma)82 apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {} 83 operator()84 AGG_INLINE void operator () (value_type* p) 85 { 86 *p = m_gamma.dir(*p); 87 } 88 89 private: 90 const GammaLut& m_gamma; 91 }; 92 93 94 95 //=====================================================apply_gamma_inv_gray 96 template<class ColorT, class GammaLut> class apply_gamma_inv_gray 97 { 98 public: 99 typedef typename ColorT::value_type value_type; 100 apply_gamma_inv_gray(const GammaLut & gamma)101 apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {} 102 operator()103 AGG_INLINE void operator () (value_type* p) 104 { 105 *p = m_gamma.inv(*p); 106 } 107 108 private: 109 const GammaLut& m_gamma; 110 }; 111 112 113 114 //=================================================pixfmt_alpha_blend_gray 115 template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0> 116 class pixfmt_alpha_blend_gray 117 { 118 public: 119 typedef RenBuf rbuf_type; 120 typedef typename rbuf_type::row_data row_data; 121 typedef Blender blender_type; 122 typedef typename blender_type::color_type color_type; 123 typedef int order_type; // A fake one 124 typedef typename color_type::value_type value_type; 125 typedef typename color_type::calc_type calc_type; 126 enum base_scale_e 127 { 128 base_shift = color_type::base_shift, 129 base_scale = color_type::base_scale, 130 base_mask = color_type::base_mask, 131 pix_width = sizeof(value_type), 132 pix_step = Step, 133 pix_offset = Offset 134 }; 135 136 private: 137 //-------------------------------------------------------------------- copy_or_blend_pix(value_type * p,const color_type & c,unsigned cover)138 static AGG_INLINE void copy_or_blend_pix(value_type* p, 139 const color_type& c, 140 unsigned cover) 141 { 142 if (c.a) 143 { 144 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 145 if(alpha == base_mask) 146 { 147 *p = c.v; 148 } 149 else 150 { 151 Blender::blend_pix(p, c.v, alpha, cover); 152 } 153 } 154 } 155 156 copy_or_blend_pix(value_type * p,const color_type & c)157 static AGG_INLINE void copy_or_blend_pix(value_type* p, 158 const color_type& c) 159 { 160 if (c.a) 161 { 162 if(c.a == base_mask) 163 { 164 *p = c.v; 165 } 166 else 167 { 168 Blender::blend_pix(p, c.v, c.a); 169 } 170 } 171 } 172 173 174 public: 175 //-------------------------------------------------------------------- pixfmt_alpha_blend_gray(rbuf_type & rb)176 pixfmt_alpha_blend_gray(rbuf_type& rb) : 177 m_rbuf(&rb) 178 {} attach(rbuf_type & rb)179 void attach(rbuf_type& rb) { m_rbuf = &rb; } 180 //-------------------------------------------------------------------- 181 182 template<class PixFmt> attach(PixFmt & pixf,int x1,int y1,int x2,int y2)183 bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) 184 { 185 rect_i r(x1, y1, x2, y2); 186 if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) 187 { 188 int stride = pixf.stride(); 189 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 190 (r.x2 - r.x1) + 1, 191 (r.y2 - r.y1) + 1, 192 stride); 193 return true; 194 } 195 return false; 196 } 197 198 //-------------------------------------------------------------------- width()199 AGG_INLINE unsigned width() const { return m_rbuf->width(); } height()200 AGG_INLINE unsigned height() const { return m_rbuf->height(); } stride()201 AGG_INLINE int stride() const { return m_rbuf->stride(); } 202 203 //-------------------------------------------------------------------- row_ptr(int y)204 int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } row_ptr(int y)205 const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } row(int y)206 row_data row(int y) const { return m_rbuf->row(y); } 207 pix_ptr(int x,int y)208 const int8u* pix_ptr(int x, int y) const 209 { 210 return m_rbuf->row_ptr(y) + x * Step + Offset; 211 } 212 pix_ptr(int x,int y)213 int8u* pix_ptr(int x, int y) 214 { 215 return m_rbuf->row_ptr(y) + x * Step + Offset; 216 } 217 218 //-------------------------------------------------------------------- make_pix(int8u * p,const color_type & c)219 AGG_INLINE static void make_pix(int8u* p, const color_type& c) 220 { 221 *(value_type*)p = c.v; 222 } 223 224 //-------------------------------------------------------------------- pixel(int x,int y)225 AGG_INLINE color_type pixel(int x, int y) const 226 { 227 value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset; 228 return color_type(*p); 229 } 230 231 //-------------------------------------------------------------------- copy_pixel(int x,int y,const color_type & c)232 AGG_INLINE void copy_pixel(int x, int y, const color_type& c) 233 { 234 *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v; 235 } 236 237 //-------------------------------------------------------------------- blend_pixel(int x,int y,const color_type & c,int8u cover)238 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) 239 { 240 copy_or_blend_pix((value_type*) 241 m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, 242 c, 243 cover); 244 } 245 246 247 //-------------------------------------------------------------------- copy_hline(int x,int y,unsigned len,const color_type & c)248 AGG_INLINE void copy_hline(int x, int y, 249 unsigned len, 250 const color_type& c) 251 { 252 value_type* p = (value_type*) 253 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 254 255 do 256 { 257 *p = c.v; 258 p += Step; 259 } 260 while(--len); 261 } 262 263 264 //-------------------------------------------------------------------- copy_vline(int x,int y,unsigned len,const color_type & c)265 AGG_INLINE void copy_vline(int x, int y, 266 unsigned len, 267 const color_type& c) 268 { 269 do 270 { 271 value_type* p = (value_type*) 272 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 273 274 *p = c.v; 275 } 276 while(--len); 277 } 278 279 280 //-------------------------------------------------------------------- blend_hline(int x,int y,unsigned len,const color_type & c,int8u cover)281 void blend_hline(int x, int y, 282 unsigned len, 283 const color_type& c, 284 int8u cover) 285 { 286 if (c.a) 287 { 288 value_type* p = (value_type*) 289 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 290 291 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 292 if(alpha == base_mask) 293 { 294 do 295 { 296 *p = c.v; 297 p += Step; 298 } 299 while(--len); 300 } 301 else 302 { 303 do 304 { 305 Blender::blend_pix(p, c.v, alpha, cover); 306 p += Step; 307 } 308 while(--len); 309 } 310 } 311 } 312 313 314 //-------------------------------------------------------------------- blend_vline(int x,int y,unsigned len,const color_type & c,int8u cover)315 void blend_vline(int x, int y, 316 unsigned len, 317 const color_type& c, 318 int8u cover) 319 { 320 if (c.a) 321 { 322 value_type* p; 323 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 324 if(alpha == base_mask) 325 { 326 do 327 { 328 p = (value_type*) 329 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 330 331 *p = c.v; 332 } 333 while(--len); 334 } 335 else 336 { 337 do 338 { 339 p = (value_type*) 340 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 341 342 Blender::blend_pix(p, c.v, alpha, cover); 343 } 344 while(--len); 345 } 346 } 347 } 348 349 350 //-------------------------------------------------------------------- blend_solid_hspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)351 void blend_solid_hspan(int x, int y, 352 unsigned len, 353 const color_type& c, 354 const int8u* covers) 355 { 356 if (c.a) 357 { 358 value_type* p = (value_type*) 359 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 360 361 do 362 { 363 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; 364 if(alpha == base_mask) 365 { 366 *p = c.v; 367 } 368 else 369 { 370 Blender::blend_pix(p, c.v, alpha, *covers); 371 } 372 p += Step; 373 ++covers; 374 } 375 while(--len); 376 } 377 } 378 379 380 //-------------------------------------------------------------------- blend_solid_vspan(int x,int y,unsigned len,const color_type & c,const int8u * covers)381 void blend_solid_vspan(int x, int y, 382 unsigned len, 383 const color_type& c, 384 const int8u* covers) 385 { 386 if (c.a) 387 { 388 do 389 { 390 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; 391 392 value_type* p = (value_type*) 393 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 394 395 if(alpha == base_mask) 396 { 397 *p = c.v; 398 } 399 else 400 { 401 Blender::blend_pix(p, c.v, alpha, *covers); 402 } 403 ++covers; 404 } 405 while(--len); 406 } 407 } 408 409 410 //-------------------------------------------------------------------- copy_color_hspan(int x,int y,unsigned len,const color_type * colors)411 void copy_color_hspan(int x, int y, 412 unsigned len, 413 const color_type* colors) 414 { 415 value_type* p = (value_type*) 416 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 417 418 do 419 { 420 *p = colors->v; 421 p += Step; 422 ++colors; 423 } 424 while(--len); 425 } 426 427 428 //-------------------------------------------------------------------- copy_color_vspan(int x,int y,unsigned len,const color_type * colors)429 void copy_color_vspan(int x, int y, 430 unsigned len, 431 const color_type* colors) 432 { 433 do 434 { 435 value_type* p = (value_type*) 436 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 437 *p = colors->v; 438 ++colors; 439 } 440 while(--len); 441 } 442 443 444 //-------------------------------------------------------------------- blend_color_hspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)445 void blend_color_hspan(int x, int y, 446 unsigned len, 447 const color_type* colors, 448 const int8u* covers, 449 int8u cover) 450 { 451 value_type* p = (value_type*) 452 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 453 454 if(covers) 455 { 456 do 457 { 458 copy_or_blend_pix(p, *colors++, *covers++); 459 p += Step; 460 } 461 while(--len); 462 } 463 else 464 { 465 if(cover == 255) 466 { 467 do 468 { 469 if(colors->a == base_mask) 470 { 471 *p = colors->v; 472 } 473 else 474 { 475 copy_or_blend_pix(p, *colors); 476 } 477 p += Step; 478 ++colors; 479 } 480 while(--len); 481 } 482 else 483 { 484 do 485 { 486 copy_or_blend_pix(p, *colors++, cover); 487 p += Step; 488 } 489 while(--len); 490 } 491 } 492 } 493 494 495 496 //-------------------------------------------------------------------- blend_color_vspan(int x,int y,unsigned len,const color_type * colors,const int8u * covers,int8u cover)497 void blend_color_vspan(int x, int y, 498 unsigned len, 499 const color_type* colors, 500 const int8u* covers, 501 int8u cover) 502 { 503 value_type* p; 504 if(covers) 505 { 506 do 507 { 508 p = (value_type*) 509 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 510 511 copy_or_blend_pix(p, *colors++, *covers++); 512 } 513 while(--len); 514 } 515 else 516 { 517 if(cover == 255) 518 { 519 do 520 { 521 p = (value_type*) 522 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 523 524 if(colors->a == base_mask) 525 { 526 *p = colors->v; 527 } 528 else 529 { 530 copy_or_blend_pix(p, *colors); 531 } 532 ++colors; 533 } 534 while(--len); 535 } 536 else 537 { 538 do 539 { 540 p = (value_type*) 541 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 542 543 copy_or_blend_pix(p, *colors++, cover); 544 } 545 while(--len); 546 } 547 } 548 } 549 550 //-------------------------------------------------------------------- for_each_pixel(Function f)551 template<class Function> void for_each_pixel(Function f) 552 { 553 unsigned y; 554 for(y = 0; y < height(); ++y) 555 { 556 row_data r = m_rbuf->row(y); 557 if(r.ptr) 558 { 559 unsigned len = r.x2 - r.x1 + 1; 560 561 value_type* p = (value_type*) 562 m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset; 563 564 do 565 { 566 f(p); 567 p += Step; 568 } 569 while(--len); 570 } 571 } 572 } 573 574 //-------------------------------------------------------------------- apply_gamma_dir(const GammaLut & g)575 template<class GammaLut> void apply_gamma_dir(const GammaLut& g) 576 { 577 for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g)); 578 } 579 580 //-------------------------------------------------------------------- apply_gamma_inv(const GammaLut & g)581 template<class GammaLut> void apply_gamma_inv(const GammaLut& g) 582 { 583 for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g)); 584 } 585 586 //-------------------------------------------------------------------- 587 template<class RenBuf2> copy_from(const RenBuf2 & from,int xdst,int ydst,int xsrc,int ysrc,unsigned len)588 void copy_from(const RenBuf2& from, 589 int xdst, int ydst, 590 int xsrc, int ysrc, 591 unsigned len) 592 { 593 const int8u* p = from.row_ptr(ysrc); 594 if(p) 595 { 596 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 597 p + xsrc * pix_width, 598 len * pix_width); 599 } 600 } 601 602 private: 603 rbuf_type* m_rbuf; 604 }; 605 606 typedef blender_gray<gray8> blender_gray8; 607 typedef blender_gray_pre<gray8> blender_gray8_pre; 608 typedef blender_gray<gray16> blender_gray16; 609 typedef blender_gray_pre<gray16> blender_gray16_pre; 610 611 typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8 612 typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre 613 typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16 614 typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre 615 } 616 617 #endif 618 619