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 // Contact: mcseem@antigrain.com 00033 // mcseemagg@yahoo.com 00034 // http://www.antigrain.com 00035 //---------------------------------------------------------------------------- 00036 00037 #ifndef AGG_COLOR_RGBA_INCLUDED 00038 #define AGG_COLOR_RGBA_INCLUDED 00039 00040 #include <math.h> 00041 #include "agg_basics.h" 00042 00043 namespace agg 00044 { 00045 // Supported byte orders for RGB and RGBA pixel formats 00046 //======================================================================= 00047 struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb 00048 struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr 00049 struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba 00050 struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb 00051 struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr 00052 struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra 00053 00054 //====================================================================rgba 00055 struct rgba 00056 { 00057 typedef double value_type; 00058 00059 double r; 00060 double g; 00061 double b; 00062 double a; 00063 00064 //-------------------------------------------------------------------- 00065 rgba() {} 00066 00067 //-------------------------------------------------------------------- 00068 rgba(double r_, double g_, double b_, double a_=1.0) : 00069 r(r_), g(g_), b(b_), a(a_) {} 00070 00071 //-------------------------------------------------------------------- 00072 rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} 00073 00074 //-------------------------------------------------------------------- 00075 void clear() 00076 { 00077 r = g = b = a = 0; 00078 } 00079 00080 //-------------------------------------------------------------------- 00081 const rgba& transparent() 00082 { 00083 a = 0.0; 00084 return *this; 00085 } 00086 00087 //-------------------------------------------------------------------- 00088 const rgba& opacity(double a_) 00089 { 00090 if(a_ < 0.0) a_ = 0.0; 00091 if(a_ > 1.0) a_ = 1.0; 00092 a = a_; 00093 return *this; 00094 } 00095 00096 //-------------------------------------------------------------------- 00097 double opacity() const 00098 { 00099 return a; 00100 } 00101 00102 //-------------------------------------------------------------------- 00103 const rgba& premultiply() 00104 { 00105 r *= a; 00106 g *= a; 00107 b *= a; 00108 return *this; 00109 } 00110 00111 //-------------------------------------------------------------------- 00112 const rgba& premultiply(double a_) 00113 { 00114 if(a <= 0.0 || a_ <= 0.0) 00115 { 00116 r = g = b = a = 0.0; 00117 return *this; 00118 } 00119 a_ /= a; 00120 r *= a_; 00121 g *= a_; 00122 b *= a_; 00123 a = a_; 00124 return *this; 00125 } 00126 00127 //-------------------------------------------------------------------- 00128 const rgba& demultiply() 00129 { 00130 if(a == 0) 00131 { 00132 r = g = b = 0; 00133 return *this; 00134 } 00135 double a_ = 1.0 / a; 00136 r *= a_; 00137 g *= a_; 00138 b *= a_; 00139 return *this; 00140 } 00141 00142 00143 //-------------------------------------------------------------------- 00144 rgba gradient(rgba c, double k) const 00145 { 00146 rgba ret; 00147 ret.r = r + (c.r - r) * k; 00148 ret.g = g + (c.g - g) * k; 00149 ret.b = b + (c.b - b) * k; 00150 ret.a = a + (c.a - a) * k; 00151 return ret; 00152 } 00153 00154 //-------------------------------------------------------------------- 00155 static rgba no_color() { return rgba(0,0,0,0); } 00156 00157 //-------------------------------------------------------------------- 00158 static rgba from_wavelength(double wl, double gamma = 1.0); 00159 00160 //-------------------------------------------------------------------- 00161 explicit rgba(double wavelen, double gamma=1.0) 00162 { 00163 *this = from_wavelength(wavelen, gamma); 00164 } 00165 00166 }; 00167 00168 //----------------------------------------------------------------rgba_pre 00169 inline rgba rgba_pre(double r, double g, double b, double a=1.0) 00170 { 00171 return rgba(r, g, b, a).premultiply(); 00172 } 00173 inline rgba rgba_pre(const rgba& c) 00174 { 00175 return rgba(c).premultiply(); 00176 } 00177 inline rgba rgba_pre(const rgba& c, double a) 00178 { 00179 return rgba(c, a).premultiply(); 00180 } 00181 00182 //------------------------------------------------------------------------ 00183 inline rgba rgba::from_wavelength(double wl, double gamma) 00184 { 00185 rgba t(0.0, 0.0, 0.0); 00186 00187 if(wl >= 380.0 && wl <= 440.0) 00188 { 00189 t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); 00190 t.b = 1.0; 00191 } 00192 else 00193 if(wl >= 440.0 && wl <= 490.0) 00194 { 00195 t.g = (wl - 440.0) / (490.0 - 440.0); 00196 t.b = 1.0; 00197 } 00198 else 00199 if(wl >= 490.0 && wl <= 510.0) 00200 { 00201 t.g = 1.0; 00202 t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); 00203 } 00204 else 00205 if(wl >= 510.0 && wl <= 580.0) 00206 { 00207 t.r = (wl - 510.0) / (580.0 - 510.0); 00208 t.g = 1.0; 00209 } 00210 else 00211 if(wl >= 580.0 && wl <= 645.0) 00212 { 00213 t.r = 1.0; 00214 t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); 00215 } 00216 else 00217 if(wl >= 645.0 && wl <= 780.0) 00218 { 00219 t.r = 1.0; 00220 } 00221 00222 double s = 1.0; 00223 if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); 00224 else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); 00225 00226 t.r = pow(t.r * s, gamma); 00227 t.g = pow(t.g * s, gamma); 00228 t.b = pow(t.b * s, gamma); 00229 return t; 00230 } 00231 00232 00233 00234 00235 //===================================================================rgba8 00236 struct rgba8 00237 { 00238 typedef int8u value_type; 00239 typedef int32u calc_type; 00240 typedef int32 long_type; 00241 enum base_scale_e 00242 { 00243 base_shift = 8, 00244 base_scale = 1 << base_shift, 00245 base_mask = base_scale - 1 00246 }; 00247 typedef rgba8 self_type; 00248 00249 00250 value_type r; 00251 value_type g; 00252 value_type b; 00253 value_type a; 00254 00255 //-------------------------------------------------------------------- 00256 rgba8() {} 00257 00258 //-------------------------------------------------------------------- 00259 rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : 00260 r(value_type(r_)), 00261 g(value_type(g_)), 00262 b(value_type(b_)), 00263 a(value_type(a_)) {} 00264 00265 //-------------------------------------------------------------------- 00266 rgba8(const rgba& c, double a_) : 00267 r((value_type)uround(c.r * double(base_mask))), 00268 g((value_type)uround(c.g * double(base_mask))), 00269 b((value_type)uround(c.b * double(base_mask))), 00270 a((value_type)uround(a_ * double(base_mask))) {} 00271 00272 //-------------------------------------------------------------------- 00273 rgba8(const self_type& c, unsigned a_) : 00274 r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} 00275 00276 //-------------------------------------------------------------------- 00277 rgba8(const rgba& c) : 00278 r((value_type)uround(c.r * double(base_mask))), 00279 g((value_type)uround(c.g * double(base_mask))), 00280 b((value_type)uround(c.b * double(base_mask))), 00281 a((value_type)uround(c.a * double(base_mask))) {} 00282 00283 //-------------------------------------------------------------------- 00284 void clear() 00285 { 00286 r = g = b = a = 0; 00287 } 00288 00289 //-------------------------------------------------------------------- 00290 const self_type& transparent() 00291 { 00292 a = 0; 00293 return *this; 00294 } 00295 00296 //-------------------------------------------------------------------- 00297 const self_type& opacity(double a_) 00298 { 00299 if(a_ < 0.0) a_ = 0.0; 00300 if(a_ > 1.0) a_ = 1.0; 00301 a = (value_type)uround(a_ * double(base_mask)); 00302 return *this; 00303 } 00304 00305 //-------------------------------------------------------------------- 00306 double opacity() const 00307 { 00308 return double(a) / double(base_mask); 00309 } 00310 00311 //-------------------------------------------------------------------- 00312 AGG_INLINE const self_type& premultiply() 00313 { 00314 if(a == base_mask) return *this; 00315 if(a == 0) 00316 { 00317 r = g = b = 0; 00318 return *this; 00319 } 00320 r = value_type((calc_type(r) * a) >> base_shift); 00321 g = value_type((calc_type(g) * a) >> base_shift); 00322 b = value_type((calc_type(b) * a) >> base_shift); 00323 return *this; 00324 } 00325 00326 //-------------------------------------------------------------------- 00327 AGG_INLINE const self_type& premultiply(unsigned a_) 00328 { 00329 if(a == base_mask && a_ >= base_mask) return *this; 00330 if(a == 0 || a_ == 0) 00331 { 00332 r = g = b = a = 0; 00333 return *this; 00334 } 00335 calc_type r_ = (calc_type(r) * a_) / a; 00336 calc_type g_ = (calc_type(g) * a_) / a; 00337 calc_type b_ = (calc_type(b) * a_) / a; 00338 r = value_type((r_ > a_) ? a_ : r_); 00339 g = value_type((g_ > a_) ? a_ : g_); 00340 b = value_type((b_ > a_) ? a_ : b_); 00341 a = value_type(a_); 00342 return *this; 00343 } 00344 00345 //-------------------------------------------------------------------- 00346 AGG_INLINE const self_type& demultiply() 00347 { 00348 if(a == base_mask) return *this; 00349 if(a == 0) 00350 { 00351 r = g = b = 0; 00352 return *this; 00353 } 00354 calc_type r_ = (calc_type(r) * base_mask) / a; 00355 calc_type g_ = (calc_type(g) * base_mask) / a; 00356 calc_type b_ = (calc_type(b) * base_mask) / a; 00357 r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); 00358 g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); 00359 b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); 00360 return *this; 00361 } 00362 00363 //-------------------------------------------------------------------- 00364 AGG_INLINE self_type gradient(const self_type& c, double k) const 00365 { 00366 self_type ret; 00367 calc_type ik = uround(k * base_scale); 00368 ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); 00369 ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); 00370 ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); 00371 ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); 00372 return ret; 00373 } 00374 00375 //-------------------------------------------------------------------- 00376 AGG_INLINE void add(const self_type& c, unsigned cover) 00377 { 00378 calc_type cr, cg, cb, ca; 00379 if(cover == cover_mask) 00380 { 00381 if(c.a == base_mask) 00382 { 00383 *this = c; 00384 } 00385 else 00386 { 00387 cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; 00388 cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; 00389 cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; 00390 ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 00391 } 00392 } 00393 else 00394 { 00395 cr = r + ((c.r * cover + cover_mask/2) >> cover_shift); 00396 cg = g + ((c.g * cover + cover_mask/2) >> cover_shift); 00397 cb = b + ((c.b * cover + cover_mask/2) >> cover_shift); 00398 ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); 00399 r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; 00400 g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; 00401 b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; 00402 a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 00403 } 00404 } 00405 00406 //-------------------------------------------------------------------- 00407 template<class GammaLUT> 00408 AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) 00409 { 00410 r = gamma.dir(r); 00411 g = gamma.dir(g); 00412 b = gamma.dir(b); 00413 } 00414 00415 //-------------------------------------------------------------------- 00416 template<class GammaLUT> 00417 AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) 00418 { 00419 r = gamma.inv(r); 00420 g = gamma.inv(g); 00421 b = gamma.inv(b); 00422 } 00423 00424 //-------------------------------------------------------------------- 00425 static self_type no_color() { return self_type(0,0,0,0); } 00426 00427 //-------------------------------------------------------------------- 00428 static self_type from_wavelength(double wl, double gamma = 1.0) 00429 { 00430 return self_type(rgba::from_wavelength(wl, gamma)); 00431 } 00432 }; 00433 00434 00435 //-------------------------------------------------------------rgba8_pre 00436 inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, 00437 unsigned a = rgba8::base_mask) 00438 { 00439 return rgba8(r,g,b,a).premultiply(); 00440 } 00441 inline rgba8 rgba8_pre(const rgba8& c) 00442 { 00443 return rgba8(c).premultiply(); 00444 } 00445 inline rgba8 rgba8_pre(const rgba8& c, unsigned a) 00446 { 00447 return rgba8(c,a).premultiply(); 00448 } 00449 inline rgba8 rgba8_pre(const rgba& c) 00450 { 00451 return rgba8(c).premultiply(); 00452 } 00453 inline rgba8 rgba8_pre(const rgba& c, double a) 00454 { 00455 return rgba8(c,a).premultiply(); 00456 } 00457 00458 00459 //-------------------------------------------------------------rgb8_packed 00460 inline rgba8 rgb8_packed(unsigned v) 00461 { 00462 return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); 00463 } 00464 00465 //-------------------------------------------------------------bgr8_packed 00466 inline rgba8 bgr8_packed(unsigned v) 00467 { 00468 return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); 00469 } 00470 00471 //------------------------------------------------------------argb8_packed 00472 inline rgba8 argb8_packed(unsigned v) 00473 { 00474 return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); 00475 } 00476 00477 //---------------------------------------------------------rgba8_gamma_dir 00478 template<class GammaLUT> 00479 rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma) 00480 { 00481 return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); 00482 } 00483 00484 //---------------------------------------------------------rgba8_gamma_inv 00485 template<class GammaLUT> 00486 rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma) 00487 { 00488 return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); 00489 } 00490 00491 00492 00493 00494 00495 //==================================================================rgba16 00496 struct rgba16 00497 { 00498 typedef int16u value_type; 00499 typedef int32u calc_type; 00500 typedef int64 long_type; 00501 enum base_scale_e 00502 { 00503 base_shift = 16, 00504 base_scale = 1 << base_shift, 00505 base_mask = base_scale - 1 00506 }; 00507 typedef rgba16 self_type; 00508 00509 value_type r; 00510 value_type g; 00511 value_type b; 00512 value_type a; 00513 00514 //-------------------------------------------------------------------- 00515 rgba16() {} 00516 00517 //-------------------------------------------------------------------- 00518 rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : 00519 r(value_type(r_)), 00520 g(value_type(g_)), 00521 b(value_type(b_)), 00522 a(value_type(a_)) {} 00523 00524 //-------------------------------------------------------------------- 00525 rgba16(const self_type& c, unsigned a_) : 00526 r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} 00527 00528 //-------------------------------------------------------------------- 00529 rgba16(const rgba& c) : 00530 r((value_type)uround(c.r * double(base_mask))), 00531 g((value_type)uround(c.g * double(base_mask))), 00532 b((value_type)uround(c.b * double(base_mask))), 00533 a((value_type)uround(c.a * double(base_mask))) {} 00534 00535 //-------------------------------------------------------------------- 00536 rgba16(const rgba& c, double a_) : 00537 r((value_type)uround(c.r * double(base_mask))), 00538 g((value_type)uround(c.g * double(base_mask))), 00539 b((value_type)uround(c.b * double(base_mask))), 00540 a((value_type)uround(a_ * double(base_mask))) {} 00541 00542 //-------------------------------------------------------------------- 00543 rgba16(const rgba8& c) : 00544 r(value_type((value_type(c.r) << 8) | c.r)), 00545 g(value_type((value_type(c.g) << 8) | c.g)), 00546 b(value_type((value_type(c.b) << 8) | c.b)), 00547 a(value_type((value_type(c.a) << 8) | c.a)) {} 00548 00549 //-------------------------------------------------------------------- 00550 rgba16(const rgba8& c, unsigned a_) : 00551 r(value_type((value_type(c.r) << 8) | c.r)), 00552 g(value_type((value_type(c.g) << 8) | c.g)), 00553 b(value_type((value_type(c.b) << 8) | c.b)), 00554 a(value_type(( a_ << 8) | c.a)) {} 00555 00556 //-------------------------------------------------------------------- 00557 void clear() 00558 { 00559 r = g = b = a = 0; 00560 } 00561 00562 //-------------------------------------------------------------------- 00563 const self_type& transparent() 00564 { 00565 a = 0; 00566 return *this; 00567 } 00568 00569 //-------------------------------------------------------------------- 00570 AGG_INLINE const self_type& opacity(double a_) 00571 { 00572 if(a_ < 0.0) a_ = 0.0; 00573 if(a_ > 1.0) a_ = 1.0; 00574 a = (value_type)uround(a_ * double(base_mask)); 00575 return *this; 00576 } 00577 00578 //-------------------------------------------------------------------- 00579 double opacity() const 00580 { 00581 return double(a) / double(base_mask); 00582 } 00583 00584 //-------------------------------------------------------------------- 00585 AGG_INLINE const self_type& premultiply() 00586 { 00587 if(a == base_mask) return *this; 00588 if(a == 0) 00589 { 00590 r = g = b = 0; 00591 return *this; 00592 } 00593 r = value_type((calc_type(r) * a) >> base_shift); 00594 g = value_type((calc_type(g) * a) >> base_shift); 00595 b = value_type((calc_type(b) * a) >> base_shift); 00596 return *this; 00597 } 00598 00599 //-------------------------------------------------------------------- 00600 AGG_INLINE const self_type& premultiply(unsigned a_) 00601 { 00602 if(a == base_mask && a_ >= base_mask) return *this; 00603 if(a == 0 || a_ == 0) 00604 { 00605 r = g = b = a = 0; 00606 return *this; 00607 } 00608 calc_type r_ = (calc_type(r) * a_) / a; 00609 calc_type g_ = (calc_type(g) * a_) / a; 00610 calc_type b_ = (calc_type(b) * a_) / a; 00611 r = value_type((r_ > a_) ? a_ : r_); 00612 g = value_type((g_ > a_) ? a_ : g_); 00613 b = value_type((b_ > a_) ? a_ : b_); 00614 a = value_type(a_); 00615 return *this; 00616 } 00617 00618 //-------------------------------------------------------------------- 00619 AGG_INLINE const self_type& demultiply() 00620 { 00621 if(a == base_mask) return *this; 00622 if(a == 0) 00623 { 00624 r = g = b = 0; 00625 return *this; 00626 } 00627 calc_type r_ = (calc_type(r) * base_mask) / a; 00628 calc_type g_ = (calc_type(g) * base_mask) / a; 00629 calc_type b_ = (calc_type(b) * base_mask) / a; 00630 r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); 00631 g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); 00632 b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); 00633 return *this; 00634 } 00635 00636 //-------------------------------------------------------------------- 00637 AGG_INLINE self_type gradient(const self_type& c, double k) const 00638 { 00639 self_type ret; 00640 calc_type ik = uround(k * base_scale); 00641 ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); 00642 ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); 00643 ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); 00644 ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); 00645 return ret; 00646 } 00647 00648 //-------------------------------------------------------------------- 00649 AGG_INLINE void add(const self_type& c, unsigned cover) 00650 { 00651 calc_type cr, cg, cb, ca; 00652 if(cover == cover_mask) 00653 { 00654 if(c.a == base_mask) 00655 { 00656 *this = c; 00657 } 00658 else 00659 { 00660 cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; 00661 cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; 00662 cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; 00663 ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 00664 } 00665 } 00666 else 00667 { 00668 cr = r + ((c.r * cover + cover_mask) >> cover_shift); 00669 cg = g + ((c.g * cover + cover_mask) >> cover_shift); 00670 cb = b + ((c.b * cover + cover_mask) >> cover_shift); 00671 ca = a + ((c.a * cover + cover_mask) >> cover_shift); 00672 r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; 00673 g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; 00674 b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; 00675 a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 00676 } 00677 } 00678 00679 //-------------------------------------------------------------------- 00680 template<class GammaLUT> 00681 AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) 00682 { 00683 r = gamma.dir(r); 00684 g = gamma.dir(g); 00685 b = gamma.dir(b); 00686 } 00687 00688 //-------------------------------------------------------------------- 00689 template<class GammaLUT> 00690 AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) 00691 { 00692 r = gamma.inv(r); 00693 g = gamma.inv(g); 00694 b = gamma.inv(b); 00695 } 00696 00697 //-------------------------------------------------------------------- 00698 static self_type no_color() { return self_type(0,0,0,0); } 00699 00700 //-------------------------------------------------------------------- 00701 static self_type from_wavelength(double wl, double gamma = 1.0) 00702 { 00703 return self_type(rgba::from_wavelength(wl, gamma)); 00704 } 00705 }; 00706 00707 00708 00709 //--------------------------------------------------------------rgba16_pre 00710 inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b, 00711 unsigned a = rgba16::base_mask) 00712 { 00713 return rgba16(r,g,b,a).premultiply(); 00714 } 00715 inline rgba16 rgba16_pre(const rgba16& c, unsigned a) 00716 { 00717 return rgba16(c,a).premultiply(); 00718 } 00719 inline rgba16 rgba16_pre(const rgba& c) 00720 { 00721 return rgba16(c).premultiply(); 00722 } 00723 inline rgba16 rgba16_pre(const rgba& c, double a) 00724 { 00725 return rgba16(c,a).premultiply(); 00726 } 00727 inline rgba16 rgba16_pre(const rgba8& c) 00728 { 00729 return rgba16(c).premultiply(); 00730 } 00731 inline rgba16 rgba16_pre(const rgba8& c, unsigned a) 00732 { 00733 return rgba16(c,a).premultiply(); 00734 } 00735 00736 00737 //------------------------------------------------------rgba16_gamma_dir 00738 template<class GammaLUT> 00739 rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) 00740 { 00741 return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); 00742 } 00743 00744 //------------------------------------------------------rgba16_gamma_inv 00745 template<class GammaLUT> 00746 rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma) 00747 { 00748 return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); 00749 } 00750 00751 00752 } 00753 00754 00755 00756 #endif