Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 // 00025 // Adaptation for high precision colors has been sponsored by 00026 // Liberty Technology Systems, Inc., visit http://lib-sys.com 00027 // 00028 // Liberty Technology Systems, Inc. is the provider of 00029 // PostScript and PDF technology for software developers. 00030 // 00031 //---------------------------------------------------------------------------- 00032 00033 #ifndef AGG_PIXFMT_GRAY_INCLUDED 00034 #define AGG_PIXFMT_GRAY_INCLUDED 00035 00036 #include <string.h> 00037 #include "agg_basics.h" 00038 #include "agg_color_gray.h" 00039 #include "agg_rendering_buffer.h" 00040 00041 namespace agg 00042 { 00043 00044 //============================================================blender_gray 00045 template<class ColorT> struct blender_gray 00046 { 00047 typedef ColorT color_type; 00048 typedef typename color_type::value_type value_type; 00049 typedef typename color_type::calc_type calc_type; 00050 enum base_scale_e { base_shift = color_type::base_shift }; 00051 00052 static AGG_INLINE void blend_pix(value_type* p, unsigned cv, 00053 unsigned alpha, unsigned cover=0) 00054 { 00055 *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift); 00056 } 00057 }; 00058 00059 00060 //======================================================blender_gray_pre 00061 template<class ColorT> struct blender_gray_pre 00062 { 00063 typedef ColorT color_type; 00064 typedef typename color_type::value_type value_type; 00065 typedef typename color_type::calc_type calc_type; 00066 enum base_scale_e { base_shift = color_type::base_shift }; 00067 00068 static AGG_INLINE void blend_pix(value_type* p, unsigned cv, 00069 unsigned alpha, unsigned cover) 00070 { 00071 alpha = color_type::base_mask - alpha; 00072 cover = (cover + 1) << (base_shift - 8); 00073 *p = (value_type)((*p * alpha + cv * cover) >> base_shift); 00074 } 00075 00076 static AGG_INLINE void blend_pix(value_type* p, unsigned cv, 00077 unsigned alpha) 00078 { 00079 *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv); 00080 } 00081 }; 00082 00083 00084 00085 //=====================================================apply_gamma_dir_gray 00086 template<class ColorT, class GammaLut> class apply_gamma_dir_gray 00087 { 00088 public: 00089 typedef typename ColorT::value_type value_type; 00090 00091 apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {} 00092 00093 AGG_INLINE void operator () (value_type* p) 00094 { 00095 *p = m_gamma.dir(*p); 00096 } 00097 00098 private: 00099 const GammaLut& m_gamma; 00100 }; 00101 00102 00103 00104 //=====================================================apply_gamma_inv_gray 00105 template<class ColorT, class GammaLut> class apply_gamma_inv_gray 00106 { 00107 public: 00108 typedef typename ColorT::value_type value_type; 00109 00110 apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {} 00111 00112 AGG_INLINE void operator () (value_type* p) 00113 { 00114 *p = m_gamma.inv(*p); 00115 } 00116 00117 private: 00118 const GammaLut& m_gamma; 00119 }; 00120 00121 00122 00123 //=================================================pixfmt_alpha_blend_gray 00124 template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0> 00125 class pixfmt_alpha_blend_gray 00126 { 00127 public: 00128 typedef RenBuf rbuf_type; 00129 typedef typename rbuf_type::row_data row_data; 00130 typedef Blender blender_type; 00131 typedef typename blender_type::color_type color_type; 00132 typedef int order_type; // A fake one 00133 typedef typename color_type::value_type value_type; 00134 typedef typename color_type::calc_type calc_type; 00135 enum base_scale_e 00136 { 00137 base_shift = color_type::base_shift, 00138 base_scale = color_type::base_scale, 00139 base_mask = color_type::base_mask, 00140 pix_width = sizeof(value_type), 00141 pix_step = Step, 00142 pix_offset = Offset 00143 }; 00144 00145 private: 00146 //-------------------------------------------------------------------- 00147 static AGG_INLINE void copy_or_blend_pix(value_type* p, 00148 const color_type& c, 00149 unsigned cover) 00150 { 00151 if (c.a) 00152 { 00153 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 00154 if(alpha == base_mask) 00155 { 00156 *p = c.v; 00157 } 00158 else 00159 { 00160 Blender::blend_pix(p, c.v, alpha, cover); 00161 } 00162 } 00163 } 00164 00165 00166 static AGG_INLINE void copy_or_blend_pix(value_type* p, 00167 const color_type& c) 00168 { 00169 if (c.a) 00170 { 00171 if(c.a == base_mask) 00172 { 00173 *p = c.v; 00174 } 00175 else 00176 { 00177 Blender::blend_pix(p, c.v, c.a); 00178 } 00179 } 00180 } 00181 00182 00183 public: 00184 //-------------------------------------------------------------------- 00185 explicit pixfmt_alpha_blend_gray(rbuf_type& rb) : 00186 m_rbuf(&rb) 00187 {} 00188 void attach(rbuf_type& rb) { m_rbuf = &rb; } 00189 //-------------------------------------------------------------------- 00190 00191 template<class PixFmt> 00192 bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) 00193 { 00194 rect_i r(x1, y1, x2, y2); 00195 if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) 00196 { 00197 int stride = pixf.stride(); 00198 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 00199 (r.x2 - r.x1) + 1, 00200 (r.y2 - r.y1) + 1, 00201 stride); 00202 return true; 00203 } 00204 return false; 00205 } 00206 00207 //-------------------------------------------------------------------- 00208 AGG_INLINE unsigned width() const { return m_rbuf->width(); } 00209 AGG_INLINE unsigned height() const { return m_rbuf->height(); } 00210 AGG_INLINE int stride() const { return m_rbuf->stride(); } 00211 00212 //-------------------------------------------------------------------- 00213 int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } 00214 const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } 00215 row_data row(int y) const { return m_rbuf->row(y); } 00216 00217 const int8u* pix_ptr(int x, int y) const 00218 { 00219 return m_rbuf->row_ptr(y) + x * Step + Offset; 00220 } 00221 00222 int8u* pix_ptr(int x, int y) 00223 { 00224 return m_rbuf->row_ptr(y) + x * Step + Offset; 00225 } 00226 00227 //-------------------------------------------------------------------- 00228 AGG_INLINE static void make_pix(int8u* p, const color_type& c) 00229 { 00230 *(value_type*)p = c.v; 00231 } 00232 00233 //-------------------------------------------------------------------- 00234 AGG_INLINE color_type pixel(int x, int y) const 00235 { 00236 value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset; 00237 return color_type(*p); 00238 } 00239 00240 //-------------------------------------------------------------------- 00241 AGG_INLINE void copy_pixel(int x, int y, const color_type& c) 00242 { 00243 *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v; 00244 } 00245 00246 //-------------------------------------------------------------------- 00247 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) 00248 { 00249 copy_or_blend_pix((value_type*) 00250 m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, 00251 c, 00252 cover); 00253 } 00254 00255 00256 //-------------------------------------------------------------------- 00257 AGG_INLINE void copy_hline(int x, int y, 00258 unsigned len, 00259 const color_type& c) 00260 { 00261 value_type* p = (value_type*) 00262 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 00263 00264 do 00265 { 00266 *p = c.v; 00267 p += Step; 00268 } 00269 while(--len); 00270 } 00271 00272 00273 //-------------------------------------------------------------------- 00274 AGG_INLINE void copy_vline(int x, int y, 00275 unsigned len, 00276 const color_type& c) 00277 { 00278 do 00279 { 00280 value_type* p = (value_type*) 00281 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00282 00283 *p = c.v; 00284 } 00285 while(--len); 00286 } 00287 00288 00289 //-------------------------------------------------------------------- 00290 void blend_hline(int x, int y, 00291 unsigned len, 00292 const color_type& c, 00293 int8u cover) 00294 { 00295 if (c.a) 00296 { 00297 value_type* p = (value_type*) 00298 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 00299 00300 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 00301 if(alpha == base_mask) 00302 { 00303 do 00304 { 00305 *p = c.v; 00306 p += Step; 00307 } 00308 while(--len); 00309 } 00310 else 00311 { 00312 do 00313 { 00314 Blender::blend_pix(p, c.v, alpha, cover); 00315 p += Step; 00316 } 00317 while(--len); 00318 } 00319 } 00320 } 00321 00322 00323 //-------------------------------------------------------------------- 00324 void blend_vline(int x, int y, 00325 unsigned len, 00326 const color_type& c, 00327 int8u cover) 00328 { 00329 if (c.a) 00330 { 00331 value_type* p; 00332 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 00333 if(alpha == base_mask) 00334 { 00335 do 00336 { 00337 p = (value_type*) 00338 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00339 00340 *p = c.v; 00341 } 00342 while(--len); 00343 } 00344 else 00345 { 00346 do 00347 { 00348 p = (value_type*) 00349 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00350 00351 Blender::blend_pix(p, c.v, alpha, cover); 00352 } 00353 while(--len); 00354 } 00355 } 00356 } 00357 00358 00359 //-------------------------------------------------------------------- 00360 void blend_solid_hspan(int x, int y, 00361 unsigned len, 00362 const color_type& c, 00363 const int8u* covers) 00364 { 00365 if (c.a) 00366 { 00367 value_type* p = (value_type*) 00368 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 00369 00370 do 00371 { 00372 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; 00373 if(alpha == base_mask) 00374 { 00375 *p = c.v; 00376 } 00377 else 00378 { 00379 Blender::blend_pix(p, c.v, alpha, *covers); 00380 } 00381 p += Step; 00382 ++covers; 00383 } 00384 while(--len); 00385 } 00386 } 00387 00388 00389 //-------------------------------------------------------------------- 00390 void blend_solid_vspan(int x, int y, 00391 unsigned len, 00392 const color_type& c, 00393 const int8u* covers) 00394 { 00395 if (c.a) 00396 { 00397 do 00398 { 00399 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; 00400 00401 value_type* p = (value_type*) 00402 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00403 00404 if(alpha == base_mask) 00405 { 00406 *p = c.v; 00407 } 00408 else 00409 { 00410 Blender::blend_pix(p, c.v, alpha, *covers); 00411 } 00412 ++covers; 00413 } 00414 while(--len); 00415 } 00416 } 00417 00418 00419 //-------------------------------------------------------------------- 00420 void copy_color_hspan(int x, int y, 00421 unsigned len, 00422 const color_type* colors) 00423 { 00424 value_type* p = (value_type*) 00425 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 00426 00427 do 00428 { 00429 *p = colors->v; 00430 p += Step; 00431 ++colors; 00432 } 00433 while(--len); 00434 } 00435 00436 00437 //-------------------------------------------------------------------- 00438 void copy_color_vspan(int x, int y, 00439 unsigned len, 00440 const color_type* colors) 00441 { 00442 do 00443 { 00444 value_type* p = (value_type*) 00445 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00446 *p = colors->v; 00447 ++colors; 00448 } 00449 while(--len); 00450 } 00451 00452 00453 //-------------------------------------------------------------------- 00454 void blend_color_hspan(int x, int y, 00455 unsigned len, 00456 const color_type* colors, 00457 const int8u* covers, 00458 int8u cover) 00459 { 00460 value_type* p = (value_type*) 00461 m_rbuf->row_ptr(x, y, len) + x * Step + Offset; 00462 00463 if(covers) 00464 { 00465 do 00466 { 00467 copy_or_blend_pix(p, *colors++, *covers++); 00468 p += Step; 00469 } 00470 while(--len); 00471 } 00472 else 00473 { 00474 if(cover == 255) 00475 { 00476 do 00477 { 00478 if(colors->a == base_mask) 00479 { 00480 *p = colors->v; 00481 } 00482 else 00483 { 00484 copy_or_blend_pix(p, *colors); 00485 } 00486 p += Step; 00487 ++colors; 00488 } 00489 while(--len); 00490 } 00491 else 00492 { 00493 do 00494 { 00495 copy_or_blend_pix(p, *colors++, cover); 00496 p += Step; 00497 } 00498 while(--len); 00499 } 00500 } 00501 } 00502 00503 00504 00505 //-------------------------------------------------------------------- 00506 void blend_color_vspan(int x, int y, 00507 unsigned len, 00508 const color_type* colors, 00509 const int8u* covers, 00510 int8u cover) 00511 { 00512 value_type* p; 00513 if(covers) 00514 { 00515 do 00516 { 00517 p = (value_type*) 00518 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00519 00520 copy_or_blend_pix(p, *colors++, *covers++); 00521 } 00522 while(--len); 00523 } 00524 else 00525 { 00526 if(cover == 255) 00527 { 00528 do 00529 { 00530 p = (value_type*) 00531 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00532 00533 if(colors->a == base_mask) 00534 { 00535 *p = colors->v; 00536 } 00537 else 00538 { 00539 copy_or_blend_pix(p, *colors); 00540 } 00541 ++colors; 00542 } 00543 while(--len); 00544 } 00545 else 00546 { 00547 do 00548 { 00549 p = (value_type*) 00550 m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; 00551 00552 copy_or_blend_pix(p, *colors++, cover); 00553 } 00554 while(--len); 00555 } 00556 } 00557 } 00558 00559 //-------------------------------------------------------------------- 00560 template<class Function> void for_each_pixel(Function f) 00561 { 00562 unsigned y; 00563 for(y = 0; y < height(); ++y) 00564 { 00565 row_data r = m_rbuf->row(y); 00566 if(r.ptr) 00567 { 00568 unsigned len = r.x2 - r.x1 + 1; 00569 00570 value_type* p = (value_type*) 00571 m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset; 00572 00573 do 00574 { 00575 f(p); 00576 p += Step; 00577 } 00578 while(--len); 00579 } 00580 } 00581 } 00582 00583 //-------------------------------------------------------------------- 00584 template<class GammaLut> void apply_gamma_dir(const GammaLut& g) 00585 { 00586 for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g)); 00587 } 00588 00589 //-------------------------------------------------------------------- 00590 template<class GammaLut> void apply_gamma_inv(const GammaLut& g) 00591 { 00592 for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g)); 00593 } 00594 00595 //-------------------------------------------------------------------- 00596 template<class RenBuf2> 00597 void copy_from(const RenBuf2& from, 00598 int xdst, int ydst, 00599 int xsrc, int ysrc, 00600 unsigned len) 00601 { 00602 const int8u* p = from.row_ptr(ysrc); 00603 if(p) 00604 { 00605 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 00606 p + xsrc * pix_width, 00607 len * pix_width); 00608 } 00609 } 00610 00611 //-------------------------------------------------------------------- 00612 template<class SrcPixelFormatRenderer> 00613 void blend_from_color(const SrcPixelFormatRenderer& from, 00614 const color_type& color, 00615 int xdst, int ydst, 00616 int xsrc, int ysrc, 00617 unsigned len, 00618 int8u cover) 00619 { 00620 typedef typename SrcPixelFormatRenderer::value_type src_value_type; 00621 const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); 00622 if(psrc) 00623 { 00624 value_type* pdst = 00625 (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; 00626 do 00627 { 00628 copy_or_blend_pix(pdst, 00629 color, 00630 (*psrc * cover + base_mask) >> base_shift); 00631 ++psrc; 00632 ++pdst; 00633 } 00634 while(--len); 00635 } 00636 } 00637 00638 //-------------------------------------------------------------------- 00639 template<class SrcPixelFormatRenderer> 00640 void blend_from_lut(const SrcPixelFormatRenderer& from, 00641 const color_type* color_lut, 00642 int xdst, int ydst, 00643 int xsrc, int ysrc, 00644 unsigned len, 00645 int8u cover) 00646 { 00647 typedef typename SrcPixelFormatRenderer::value_type src_value_type; 00648 const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); 00649 if(psrc) 00650 { 00651 value_type* pdst = 00652 (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; 00653 do 00654 { 00655 copy_or_blend_pix(pdst, color_lut[*psrc], cover); 00656 ++psrc; 00657 ++pdst; 00658 } 00659 while(--len); 00660 } 00661 } 00662 00663 private: 00664 rbuf_type* m_rbuf; 00665 }; 00666 00667 typedef blender_gray<gray8> blender_gray8; 00668 typedef blender_gray_pre<gray8> blender_gray8_pre; 00669 typedef blender_gray<gray16> blender_gray16; 00670 typedef blender_gray_pre<gray16> blender_gray16_pre; 00671 00672 typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8 00673 typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre 00674 typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16 00675 typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre 00676 } 00677 00678 #endif 00679