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// color types gray8, gray16 25// 26//---------------------------------------------------------------------------- 27 28#ifndef AGG_COLOR_GRAY_INCLUDED 29#define AGG_COLOR_GRAY_INCLUDED 30 31#include "agg_basics.h" 32#include "agg_color_rgba.h" 33 34namespace agg 35{ 36 37 //===================================================================gray8 38 struct gray8 39 { 40 typedef int8u value_type; 41 typedef int32u calc_type; 42 typedef int32 long_type; 43 enum base_scale_e 44 { 45 base_shift = 8, 46 base_scale = 1 << base_shift, 47 base_mask = base_scale - 1 48 }; 49 typedef gray8 self_type; 50 51 value_type v; 52 value_type a; 53 54 //-------------------------------------------------------------------- 55 gray8() {} 56 57 //-------------------------------------------------------------------- 58 explicit gray8(unsigned v_, unsigned a_=base_mask) : 59 v(int8u(v_)), a(int8u(a_)) {} 60 61 //-------------------------------------------------------------------- 62 gray8(const self_type& c, unsigned a_) : 63 v(c.v), a(value_type(a_)) {} 64 65 //-------------------------------------------------------------------- 66 gray8(const rgba& c) : 67 v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), 68 a((value_type)uround(c.a * double(base_mask))) {} 69 70 //-------------------------------------------------------------------- 71 gray8(const rgba& c, double a_) : 72 v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), 73 a((value_type)uround(a_ * double(base_mask))) {} 74 75 //-------------------------------------------------------------------- 76 gray8(const rgba8& c) : 77 v((c.r*77 + c.g*150 + c.b*29) >> 8), 78 a(c.a) {} 79 80 //-------------------------------------------------------------------- 81 gray8(const rgba8& c, unsigned a_) : 82 v((c.r*77 + c.g*150 + c.b*29) >> 8), 83 a(a_) {} 84 85 //-------------------------------------------------------------------- 86 void clear() 87 { 88 v = a = 0; 89 } 90 91 //-------------------------------------------------------------------- 92 const self_type& transparent() 93 { 94 a = 0; 95 return *this; 96 } 97 98 //-------------------------------------------------------------------- 99 void opacity(double a_) 100 { 101 if(a_ < 0.0) a_ = 0.0; 102 if(a_ > 1.0) a_ = 1.0; 103 a = (value_type)uround(a_ * double(base_mask)); 104 } 105 106 //-------------------------------------------------------------------- 107 double opacity() const 108 { 109 return double(a) / double(base_mask); 110 } 111 112 113 //-------------------------------------------------------------------- 114 const self_type& premultiply() 115 { 116 if(a == base_mask) return *this; 117 if(a == 0) 118 { 119 v = 0; 120 return *this; 121 } 122 v = value_type((calc_type(v) * a) >> base_shift); 123 return *this; 124 } 125 126 //-------------------------------------------------------------------- 127 const self_type& premultiply(unsigned a_) 128 { 129 if(a == base_mask && a_ >= base_mask) return *this; 130 if(a == 0 || a_ == 0) 131 { 132 v = a = 0; 133 return *this; 134 } 135 calc_type v_ = (calc_type(v) * a_) / a; 136 v = value_type((v_ > a_) ? a_ : v_); 137 a = value_type(a_); 138 return *this; 139 } 140 141 //-------------------------------------------------------------------- 142 const self_type& demultiply() 143 { 144 if(a == base_mask) return *this; 145 if(a == 0) 146 { 147 v = 0; 148 return *this; 149 } 150 calc_type v_ = (calc_type(v) * base_mask) / a; 151 v = value_type((v_ > base_mask) ? base_mask : v_); 152 return *this; 153 } 154 155 //-------------------------------------------------------------------- 156 self_type gradient(self_type c, double k) const 157 { 158 self_type ret; 159 calc_type ik = uround(k * base_scale); 160 ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); 161 ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); 162 return ret; 163 } 164 165 //-------------------------------------------------------------------- 166 AGG_INLINE void add(const self_type& c, unsigned cover) 167 { 168 calc_type cv, ca; 169 if(cover == cover_mask) 170 { 171 if(c.a == base_mask) 172 { 173 *this = c; 174 } 175 else 176 { 177 cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; 178 ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 179 } 180 } 181 else 182 { 183 cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); 184 ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); 185 v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; 186 a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 187 } 188 } 189 190 //-------------------------------------------------------------------- 191 static self_type no_color() { return self_type(0,0); } 192 }; 193 194 195 //-------------------------------------------------------------gray8_pre 196 inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask) 197 { 198 return gray8(v,a).premultiply(); 199 } 200 inline gray8 gray8_pre(const gray8& c, unsigned a) 201 { 202 return gray8(c,a).premultiply(); 203 } 204 inline gray8 gray8_pre(const rgba& c) 205 { 206 return gray8(c).premultiply(); 207 } 208 inline gray8 gray8_pre(const rgba& c, double a) 209 { 210 return gray8(c,a).premultiply(); 211 } 212 inline gray8 gray8_pre(const rgba8& c) 213 { 214 return gray8(c).premultiply(); 215 } 216 inline gray8 gray8_pre(const rgba8& c, unsigned a) 217 { 218 return gray8(c,a).premultiply(); 219 } 220 221 222 223 224 //==================================================================gray16 225 struct gray16 226 { 227 typedef int16u value_type; 228 typedef int32u calc_type; 229 typedef int64 long_type; 230 enum base_scale_e 231 { 232 base_shift = 16, 233 base_scale = 1 << base_shift, 234 base_mask = base_scale - 1 235 }; 236 typedef gray16 self_type; 237 238 value_type v; 239 value_type a; 240 241 //-------------------------------------------------------------------- 242 gray16() {} 243 244 //-------------------------------------------------------------------- 245 explicit gray16(unsigned v_, unsigned a_=base_mask) : 246 v(int16u(v_)), a(int16u(a_)) {} 247 248 //-------------------------------------------------------------------- 249 gray16(const self_type& c, unsigned a_) : 250 v(c.v), a(value_type(a_)) {} 251 252 //-------------------------------------------------------------------- 253 gray16(const rgba& c) : 254 v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), 255 a((value_type)uround(c.a * double(base_mask))) {} 256 257 //-------------------------------------------------------------------- 258 gray16(const rgba& c, double a_) : 259 v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), 260 a((value_type)uround(a_ * double(base_mask))) {} 261 262 //-------------------------------------------------------------------- 263 gray16(const rgba8& c) : 264 v(c.r*77 + c.g*150 + c.b*29), 265 a((value_type(c.a) << 8) | c.a) {} 266 267 //-------------------------------------------------------------------- 268 gray16(const rgba8& c, unsigned a_) : 269 v(c.r*77 + c.g*150 + c.b*29), 270 a((value_type(a_) << 8) | c.a) {} 271 272 //-------------------------------------------------------------------- 273 void clear() 274 { 275 v = a = 0; 276 } 277 278 //-------------------------------------------------------------------- 279 const self_type& transparent() 280 { 281 a = 0; 282 return *this; 283 } 284 285 //-------------------------------------------------------------------- 286 void opacity(double a_) 287 { 288 if(a_ < 0.0) a_ = 0.0; 289 if(a_ > 1.0) a_ = 1.0; 290 a = (value_type)uround(a_ * double(base_mask)); 291 } 292 293 //-------------------------------------------------------------------- 294 double opacity() const 295 { 296 return double(a) / double(base_mask); 297 } 298 299 300 //-------------------------------------------------------------------- 301 const self_type& premultiply() 302 { 303 if(a == base_mask) return *this; 304 if(a == 0) 305 { 306 v = 0; 307 return *this; 308 } 309 v = value_type((calc_type(v) * a) >> base_shift); 310 return *this; 311 } 312 313 //-------------------------------------------------------------------- 314 const self_type& premultiply(unsigned a_) 315 { 316 if(a == base_mask && a_ >= base_mask) return *this; 317 if(a == 0 || a_ == 0) 318 { 319 v = a = 0; 320 return *this; 321 } 322 calc_type v_ = (calc_type(v) * a_) / a; 323 v = value_type((v_ > a_) ? a_ : v_); 324 a = value_type(a_); 325 return *this; 326 } 327 328 //-------------------------------------------------------------------- 329 const self_type& demultiply() 330 { 331 if(a == base_mask) return *this; 332 if(a == 0) 333 { 334 v = 0; 335 return *this; 336 } 337 calc_type v_ = (calc_type(v) * base_mask) / a; 338 v = value_type((v_ > base_mask) ? base_mask : v_); 339 return *this; 340 } 341 342 //-------------------------------------------------------------------- 343 self_type gradient(self_type c, double k) const 344 { 345 self_type ret; 346 calc_type ik = uround(k * base_scale); 347 ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); 348 ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); 349 return ret; 350 } 351 352 //-------------------------------------------------------------------- 353 AGG_INLINE void add(const self_type& c, unsigned cover) 354 { 355 calc_type cv, ca; 356 if(cover == cover_mask) 357 { 358 if(c.a == base_mask) 359 { 360 *this = c; 361 } 362 else 363 { 364 cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; 365 ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 366 } 367 } 368 else 369 { 370 cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); 371 ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); 372 v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; 373 a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; 374 } 375 } 376 377 //-------------------------------------------------------------------- 378 static self_type no_color() { return self_type(0,0); } 379 }; 380 381 382 //------------------------------------------------------------gray16_pre 383 inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask) 384 { 385 return gray16(v,a).premultiply(); 386 } 387 inline gray16 gray16_pre(const gray16& c, unsigned a) 388 { 389 return gray16(c,a).premultiply(); 390 } 391 inline gray16 gray16_pre(const rgba& c) 392 { 393 return gray16(c).premultiply(); 394 } 395 inline gray16 gray16_pre(const rgba& c, double a) 396 { 397 return gray16(c,a).premultiply(); 398 } 399 inline gray16 gray16_pre(const rgba8& c) 400 { 401 return gray16(c).premultiply(); 402 } 403 inline gray16 gray16_pre(const rgba8& c, unsigned a) 404 { 405 return gray16(c,a).premultiply(); 406 } 407 408 409} 410 411 412 413 414#endif 415