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_PACKED_INCLUDED 25 #define AGG_PIXFMT_RGB_PACKED_INCLUDED 26 27 #include <string.h> 28 #include "agg_basics.h" 29 #include "agg_color_rgba.h" 30 #include "agg_rendering_buffer.h" 31 32 namespace agg 33 { 34 //=========================================================blender_rgb555 35 struct blender_rgb555 36 { 37 typedef rgba8 color_type; 38 typedef color_type::value_type value_type; 39 typedef color_type::calc_type calc_type; 40 typedef int16u pixel_type; 41 42 static AGG_INLINE void blend_pix(pixel_type* p, 43 unsigned cr, unsigned cg, unsigned cb, 44 unsigned alpha, 45 unsigned) 46 { 47 pixel_type rgb = *p; 48 calc_type r = (rgb >> 7) & 0xF8; 49 calc_type g = (rgb >> 2) & 0xF8; 50 calc_type b = (rgb << 3) & 0xF8; 51 *p = (pixel_type) 52 (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) | 53 ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | 54 (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000); 55 } 56 57 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 58 { 59 return (pixel_type)(((r & 0xF8) << 7) | 60 ((g & 0xF8) << 2) | 61 (b >> 3) | 0x8000); 62 } 63 64 static AGG_INLINE color_type make_color(pixel_type p) 65 { 66 return color_type((p >> 7) & 0xF8, 67 (p >> 2) & 0xF8, 68 (p << 3) & 0xF8); 69 } 70 }; 71 72 73 //=====================================================blender_rgb555_pre 74 struct blender_rgb555_pre 75 { 76 typedef rgba8 color_type; 77 typedef color_type::value_type value_type; 78 typedef color_type::calc_type calc_type; 79 typedef int16u pixel_type; 80 81 static AGG_INLINE void blend_pix(pixel_type* p, 82 unsigned cr, unsigned cg, unsigned cb, 83 unsigned alpha, 84 unsigned cover) 85 { 86 alpha = color_type::base_mask - alpha; 87 pixel_type rgb = *p; 88 calc_type r = (rgb >> 7) & 0xF8; 89 calc_type g = (rgb >> 2) & 0xF8; 90 calc_type b = (rgb << 3) & 0xF8; 91 *p = (pixel_type) 92 ((((r * alpha + cr * cover) >> 1) & 0x7C00) | 93 (((g * alpha + cg * cover) >> 6) & 0x03E0) | 94 ((b * alpha + cb * cover) >> 11) | 0x8000); 95 } 96 97 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 98 { 99 return (pixel_type)(((r & 0xF8) << 7) | 100 ((g & 0xF8) << 2) | 101 (b >> 3) | 0x8000); 102 } 103 104 static AGG_INLINE color_type make_color(pixel_type p) 105 { 106 return color_type((p >> 7) & 0xF8, 107 (p >> 2) & 0xF8, 108 (p << 3) & 0xF8); 109 } 110 }; 111 112 113 114 115 //=====================================================blender_rgb555_gamma 116 template<class Gamma> class blender_rgb555_gamma 117 { 118 public: 119 typedef rgba8 color_type; 120 typedef color_type::value_type value_type; 121 typedef color_type::calc_type calc_type; 122 typedef int16u pixel_type; 123 typedef Gamma gamma_type; 124 125 blender_rgb555_gamma() : m_gamma(0) {} 126 void gamma(const gamma_type& g) { m_gamma = &g; } 127 128 AGG_INLINE void blend_pix(pixel_type* p, 129 unsigned cr, unsigned cg, unsigned cb, 130 unsigned alpha, 131 unsigned) 132 { 133 pixel_type rgb = *p; 134 calc_type r = m_gamma->dir((rgb >> 7) & 0xF8); 135 calc_type g = m_gamma->dir((rgb >> 2) & 0xF8); 136 calc_type b = m_gamma->dir((rgb << 3) & 0xF8); 137 *p = (pixel_type) 138 (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) | 139 ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) | 140 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000); 141 } 142 143 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 144 { 145 return (pixel_type)(((r & 0xF8) << 7) | 146 ((g & 0xF8) << 2) | 147 (b >> 3) | 0x8000); 148 } 149 150 static AGG_INLINE color_type make_color(pixel_type p) 151 { 152 return color_type((p >> 7) & 0xF8, 153 (p >> 2) & 0xF8, 154 (p << 3) & 0xF8); 155 } 156 157 private: 158 const Gamma* m_gamma; 159 }; 160 161 162 163 164 165 //=========================================================blender_rgb565 166 struct blender_rgb565 167 { 168 typedef rgba8 color_type; 169 typedef color_type::value_type value_type; 170 typedef color_type::calc_type calc_type; 171 typedef int16u pixel_type; 172 173 static AGG_INLINE void blend_pix(pixel_type* p, 174 unsigned cr, unsigned cg, unsigned cb, 175 unsigned alpha, 176 unsigned) 177 { 178 pixel_type rgb = *p; 179 calc_type r = (rgb >> 8) & 0xF8; 180 calc_type g = (rgb >> 3) & 0xFC; 181 calc_type b = (rgb << 3) & 0xF8; 182 *p = (pixel_type) 183 (((((cr - r) * alpha + (r << 8)) ) & 0xF800) | 184 ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) | 185 (((cb - b) * alpha + (b << 8)) >> 11)); 186 } 187 188 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 189 { 190 return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); 191 } 192 193 static AGG_INLINE color_type make_color(pixel_type p) 194 { 195 return color_type((p >> 8) & 0xF8, 196 (p >> 3) & 0xFC, 197 (p << 3) & 0xF8); 198 } 199 }; 200 201 202 203 //=====================================================blender_rgb565_pre 204 struct blender_rgb565_pre 205 { 206 typedef rgba8 color_type; 207 typedef color_type::value_type value_type; 208 typedef color_type::calc_type calc_type; 209 typedef int16u pixel_type; 210 211 static AGG_INLINE void blend_pix(pixel_type* p, 212 unsigned cr, unsigned cg, unsigned cb, 213 unsigned alpha, 214 unsigned cover) 215 { 216 alpha = color_type::base_mask - alpha; 217 pixel_type rgb = *p; 218 calc_type r = (rgb >> 8) & 0xF8; 219 calc_type g = (rgb >> 3) & 0xFC; 220 calc_type b = (rgb << 3) & 0xF8; 221 *p = (pixel_type) 222 ((((r * alpha + cr * cover) ) & 0xF800) | 223 (((g * alpha + cg * cover) >> 5 ) & 0x07E0) | 224 ((b * alpha + cb * cover) >> 11)); 225 } 226 227 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 228 { 229 return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); 230 } 231 232 static AGG_INLINE color_type make_color(pixel_type p) 233 { 234 return color_type((p >> 8) & 0xF8, 235 (p >> 3) & 0xFC, 236 (p << 3) & 0xF8); 237 } 238 }; 239 240 241 242 //=====================================================blender_rgb565_gamma 243 template<class Gamma> class blender_rgb565_gamma 244 { 245 public: 246 typedef rgba8 color_type; 247 typedef color_type::value_type value_type; 248 typedef color_type::calc_type calc_type; 249 typedef int16u pixel_type; 250 typedef Gamma gamma_type; 251 252 blender_rgb565_gamma() : m_gamma(0) {} 253 void gamma(const gamma_type& g) { m_gamma = &g; } 254 255 AGG_INLINE void blend_pix(pixel_type* p, 256 unsigned cr, unsigned cg, unsigned cb, 257 unsigned alpha, 258 unsigned) 259 { 260 pixel_type rgb = *p; 261 calc_type r = m_gamma->dir((rgb >> 8) & 0xF8); 262 calc_type g = m_gamma->dir((rgb >> 3) & 0xFC); 263 calc_type b = m_gamma->dir((rgb << 3) & 0xF8); 264 *p = (pixel_type) 265 (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) | 266 ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) | 267 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3)); 268 } 269 270 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 271 { 272 return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); 273 } 274 275 static AGG_INLINE color_type make_color(pixel_type p) 276 { 277 return color_type((p >> 8) & 0xF8, 278 (p >> 3) & 0xFC, 279 (p << 3) & 0xF8); 280 } 281 282 private: 283 const Gamma* m_gamma; 284 }; 285 286 287 288 //=====================================================blender_rgbAAA 289 struct blender_rgbAAA 290 { 291 typedef rgba16 color_type; 292 typedef color_type::value_type value_type; 293 typedef color_type::calc_type calc_type; 294 typedef int32u pixel_type; 295 296 static AGG_INLINE void blend_pix(pixel_type* p, 297 unsigned cr, unsigned cg, unsigned cb, 298 unsigned alpha, 299 unsigned) 300 { 301 pixel_type rgb = *p; 302 calc_type r = (rgb >> 14) & 0xFFC0; 303 calc_type g = (rgb >> 4) & 0xFFC0; 304 calc_type b = (rgb << 6) & 0xFFC0; 305 *p = (pixel_type) 306 (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) | 307 ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | 308 (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000); 309 } 310 311 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 312 { 313 return (pixel_type)(((r & 0xFFC0) << 14) | 314 ((g & 0xFFC0) << 4) | 315 (b >> 6) | 0xC0000000); 316 } 317 318 static AGG_INLINE color_type make_color(pixel_type p) 319 { 320 return color_type((p >> 14) & 0xFFC0, 321 (p >> 4) & 0xFFC0, 322 (p << 6) & 0xFFC0); 323 } 324 }; 325 326 327 328 //==================================================blender_rgbAAA_pre 329 struct blender_rgbAAA_pre 330 { 331 typedef rgba16 color_type; 332 typedef color_type::value_type value_type; 333 typedef color_type::calc_type calc_type; 334 typedef int32u pixel_type; 335 336 static AGG_INLINE void blend_pix(pixel_type* p, 337 unsigned cr, unsigned cg, unsigned cb, 338 unsigned alpha, 339 unsigned cover) 340 { 341 alpha = color_type::base_mask - alpha; 342 cover = (cover + 1) << (color_type::base_shift - 8); 343 pixel_type rgb = *p; 344 calc_type r = (rgb >> 14) & 0xFFC0; 345 calc_type g = (rgb >> 4) & 0xFFC0; 346 calc_type b = (rgb << 6) & 0xFFC0; 347 *p = (pixel_type) 348 ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) | 349 (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | 350 ((b * alpha + cb * cover) >> 22) | 0xC0000000); 351 } 352 353 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 354 { 355 return (pixel_type)(((r & 0xFFC0) << 14) | 356 ((g & 0xFFC0) << 4) | 357 (b >> 6) | 0xC0000000); 358 } 359 360 static AGG_INLINE color_type make_color(pixel_type p) 361 { 362 return color_type((p >> 14) & 0xFFC0, 363 (p >> 4) & 0xFFC0, 364 (p << 6) & 0xFFC0); 365 } 366 }; 367 368 369 370 //=================================================blender_rgbAAA_gamma 371 template<class Gamma> class blender_rgbAAA_gamma 372 { 373 public: 374 typedef rgba16 color_type; 375 typedef color_type::value_type value_type; 376 typedef color_type::calc_type calc_type; 377 typedef int32u pixel_type; 378 typedef Gamma gamma_type; 379 380 blender_rgbAAA_gamma() : m_gamma(0) {} 381 void gamma(const gamma_type& g) { m_gamma = &g; } 382 383 AGG_INLINE void blend_pix(pixel_type* p, 384 unsigned cr, unsigned cg, unsigned cb, 385 unsigned alpha, 386 unsigned) 387 { 388 pixel_type rgb = *p; 389 calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0); 390 calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0); 391 calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); 392 *p = (pixel_type) 393 (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) | 394 ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | 395 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000); 396 } 397 398 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 399 { 400 return (pixel_type)(((r & 0xFFC0) << 14) | 401 ((g & 0xFFC0) << 4) | 402 (b >> 6) | 0xC0000000); 403 } 404 405 static AGG_INLINE color_type make_color(pixel_type p) 406 { 407 return color_type((p >> 14) & 0xFFC0, 408 (p >> 4) & 0xFFC0, 409 (p << 6) & 0xFFC0); 410 } 411 private: 412 const Gamma* m_gamma; 413 }; 414 415 416 //=====================================================blender_bgrAAA 417 struct blender_bgrAAA 418 { 419 typedef rgba16 color_type; 420 typedef color_type::value_type value_type; 421 typedef color_type::calc_type calc_type; 422 typedef int32u pixel_type; 423 424 static AGG_INLINE void blend_pix(pixel_type* p, 425 unsigned cr, unsigned cg, unsigned cb, 426 unsigned alpha, 427 unsigned) 428 { 429 pixel_type bgr = *p; 430 calc_type b = (bgr >> 14) & 0xFFC0; 431 calc_type g = (bgr >> 4) & 0xFFC0; 432 calc_type r = (bgr << 6) & 0xFFC0; 433 *p = (pixel_type) 434 (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) | 435 ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | 436 (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000); 437 } 438 439 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 440 { 441 return (pixel_type)(((b & 0xFFC0) << 14) | 442 ((g & 0xFFC0) << 4) | 443 (r >> 6) | 0xC0000000); 444 } 445 446 static AGG_INLINE color_type make_color(pixel_type p) 447 { 448 return color_type((p << 6) & 0xFFC0, 449 (p >> 4) & 0xFFC0, 450 (p >> 14) & 0xFFC0); 451 } 452 }; 453 454 455 456 //=================================================blender_bgrAAA_pre 457 struct blender_bgrAAA_pre 458 { 459 typedef rgba16 color_type; 460 typedef color_type::value_type value_type; 461 typedef color_type::calc_type calc_type; 462 typedef int32u pixel_type; 463 464 static AGG_INLINE void blend_pix(pixel_type* p, 465 unsigned cr, unsigned cg, unsigned cb, 466 unsigned alpha, 467 unsigned cover) 468 { 469 alpha = color_type::base_mask - alpha; 470 cover = (cover + 1) << (color_type::base_shift - 8); 471 pixel_type bgr = *p; 472 calc_type b = (bgr >> 14) & 0xFFC0; 473 calc_type g = (bgr >> 4) & 0xFFC0; 474 calc_type r = (bgr << 6) & 0xFFC0; 475 *p = (pixel_type) 476 ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) | 477 (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | 478 ((r * alpha + cr * cover) >> 22) | 0xC0000000); 479 } 480 481 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 482 { 483 return (pixel_type)(((b & 0xFFC0) << 14) | 484 ((g & 0xFFC0) << 4) | 485 (r >> 6) | 0xC0000000); 486 } 487 488 static AGG_INLINE color_type make_color(pixel_type p) 489 { 490 return color_type((p << 6) & 0xFFC0, 491 (p >> 4) & 0xFFC0, 492 (p >> 14) & 0xFFC0); 493 } 494 }; 495 496 497 498 //=================================================blender_bgrAAA_gamma 499 template<class Gamma> class blender_bgrAAA_gamma 500 { 501 public: 502 typedef rgba16 color_type; 503 typedef color_type::value_type value_type; 504 typedef color_type::calc_type calc_type; 505 typedef int32u pixel_type; 506 typedef Gamma gamma_type; 507 508 blender_bgrAAA_gamma() : m_gamma(0) {} 509 void gamma(const gamma_type& g) { m_gamma = &g; } 510 511 AGG_INLINE void blend_pix(pixel_type* p, 512 unsigned cr, unsigned cg, unsigned cb, 513 unsigned alpha, 514 unsigned) 515 { 516 pixel_type bgr = *p; 517 calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0); 518 calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0); 519 calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0); 520 *p = (pixel_type) 521 (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) | 522 ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | 523 (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000); 524 } 525 526 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 527 { 528 return (pixel_type)(((b & 0xFFC0) << 14) | 529 ((g & 0xFFC0) << 4) | 530 (r >> 6) | 0xC0000000); 531 } 532 533 static AGG_INLINE color_type make_color(pixel_type p) 534 { 535 return color_type((p << 6) & 0xFFC0, 536 (p >> 4) & 0xFFC0, 537 (p >> 14) & 0xFFC0); 538 } 539 540 private: 541 const Gamma* m_gamma; 542 }; 543 544 545 546 //=====================================================blender_rgbBBA 547 struct blender_rgbBBA 548 { 549 typedef rgba16 color_type; 550 typedef color_type::value_type value_type; 551 typedef color_type::calc_type calc_type; 552 typedef int32u pixel_type; 553 554 static AGG_INLINE void blend_pix(pixel_type* p, 555 unsigned cr, unsigned cg, unsigned cb, 556 unsigned alpha, 557 unsigned) 558 { 559 pixel_type rgb = *p; 560 calc_type r = (rgb >> 16) & 0xFFE0; 561 calc_type g = (rgb >> 5) & 0xFFE0; 562 calc_type b = (rgb << 6) & 0xFFC0; 563 *p = (pixel_type) 564 (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) | 565 ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) | 566 (((cb - b) * alpha + (b << 16)) >> 22)); 567 } 568 569 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 570 { 571 return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); 572 } 573 574 static AGG_INLINE color_type make_color(pixel_type p) 575 { 576 return color_type((p >> 16) & 0xFFE0, 577 (p >> 5) & 0xFFE0, 578 (p << 6) & 0xFFC0); 579 } 580 }; 581 582 583 //=================================================blender_rgbBBA_pre 584 struct blender_rgbBBA_pre 585 { 586 typedef rgba16 color_type; 587 typedef color_type::value_type value_type; 588 typedef color_type::calc_type calc_type; 589 typedef int32u pixel_type; 590 591 static AGG_INLINE void blend_pix(pixel_type* p, 592 unsigned cr, unsigned cg, unsigned cb, 593 unsigned alpha, 594 unsigned cover) 595 { 596 alpha = color_type::base_mask - alpha; 597 cover = (cover + 1) << (color_type::base_shift - 8); 598 pixel_type rgb = *p; 599 calc_type r = (rgb >> 16) & 0xFFE0; 600 calc_type g = (rgb >> 5) & 0xFFE0; 601 calc_type b = (rgb << 6) & 0xFFC0; 602 *p = (pixel_type) 603 ((((r * alpha + cr * cover) ) & 0xFFE00000) | 604 (((g * alpha + cg * cover) >> 11) & 0x001FFC00) | 605 ((b * alpha + cb * cover) >> 22)); 606 } 607 608 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 609 { 610 return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); 611 } 612 613 static AGG_INLINE color_type make_color(pixel_type p) 614 { 615 return color_type((p >> 16) & 0xFFE0, 616 (p >> 5) & 0xFFE0, 617 (p << 6) & 0xFFC0); 618 } 619 }; 620 621 622 623 //=================================================blender_rgbBBA_gamma 624 template<class Gamma> class blender_rgbBBA_gamma 625 { 626 public: 627 typedef rgba16 color_type; 628 typedef color_type::value_type value_type; 629 typedef color_type::calc_type calc_type; 630 typedef int32u pixel_type; 631 typedef Gamma gamma_type; 632 633 blender_rgbBBA_gamma() : m_gamma(0) {} 634 void gamma(const gamma_type& g) { m_gamma = &g; } 635 636 AGG_INLINE void blend_pix(pixel_type* p, 637 unsigned cr, unsigned cg, unsigned cb, 638 unsigned alpha, 639 unsigned) 640 { 641 pixel_type rgb = *p; 642 calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0); 643 calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0); 644 calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); 645 *p = (pixel_type) 646 (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) | 647 ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) | 648 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 )); 649 } 650 651 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 652 { 653 return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); 654 } 655 656 static AGG_INLINE color_type make_color(pixel_type p) 657 { 658 return color_type((p >> 16) & 0xFFE0, 659 (p >> 5) & 0xFFE0, 660 (p << 6) & 0xFFC0); 661 } 662 663 private: 664 const Gamma* m_gamma; 665 }; 666 667 668 //=====================================================blender_bgrABB 669 struct blender_bgrABB 670 { 671 typedef rgba16 color_type; 672 typedef color_type::value_type value_type; 673 typedef color_type::calc_type calc_type; 674 typedef int32u pixel_type; 675 676 static AGG_INLINE void blend_pix(pixel_type* p, 677 unsigned cr, unsigned cg, unsigned cb, 678 unsigned alpha, 679 unsigned) 680 { 681 pixel_type bgr = *p; 682 calc_type b = (bgr >> 16) & 0xFFC0; 683 calc_type g = (bgr >> 6) & 0xFFE0; 684 calc_type r = (bgr << 5) & 0xFFE0; 685 *p = (pixel_type) 686 (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) | 687 ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) | 688 (((cr - r) * alpha + (r << 16)) >> 21)); 689 } 690 691 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 692 { 693 return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); 694 } 695 696 static AGG_INLINE color_type make_color(pixel_type p) 697 { 698 return color_type((p << 5) & 0xFFE0, 699 (p >> 6) & 0xFFE0, 700 (p >> 16) & 0xFFC0); 701 } 702 }; 703 704 705 //=================================================blender_bgrABB_pre 706 struct blender_bgrABB_pre 707 { 708 typedef rgba16 color_type; 709 typedef color_type::value_type value_type; 710 typedef color_type::calc_type calc_type; 711 typedef int32u pixel_type; 712 713 static AGG_INLINE void blend_pix(pixel_type* p, 714 unsigned cr, unsigned cg, unsigned cb, 715 unsigned alpha, 716 unsigned cover) 717 { 718 alpha = color_type::base_mask - alpha; 719 cover = (cover + 1) << (color_type::base_shift - 8); 720 pixel_type bgr = *p; 721 calc_type b = (bgr >> 16) & 0xFFC0; 722 calc_type g = (bgr >> 6) & 0xFFE0; 723 calc_type r = (bgr << 5) & 0xFFE0; 724 *p = (pixel_type) 725 ((((b * alpha + cb * cover) ) & 0xFFC00000) | 726 (((g * alpha + cg * cover) >> 10) & 0x003FF800) | 727 ((r * alpha + cr * cover) >> 21)); 728 } 729 730 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 731 { 732 return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); 733 } 734 735 static AGG_INLINE color_type make_color(pixel_type p) 736 { 737 return color_type((p << 5) & 0xFFE0, 738 (p >> 6) & 0xFFE0, 739 (p >> 16) & 0xFFC0); 740 } 741 }; 742 743 744 745 //=================================================blender_bgrABB_gamma 746 template<class Gamma> class blender_bgrABB_gamma 747 { 748 public: 749 typedef rgba16 color_type; 750 typedef color_type::value_type value_type; 751 typedef color_type::calc_type calc_type; 752 typedef int32u pixel_type; 753 typedef Gamma gamma_type; 754 755 blender_bgrABB_gamma() : m_gamma(0) {} 756 void gamma(const gamma_type& g) { m_gamma = &g; } 757 758 AGG_INLINE void blend_pix(pixel_type* p, 759 unsigned cr, unsigned cg, unsigned cb, 760 unsigned alpha, 761 unsigned) 762 { 763 pixel_type bgr = *p; 764 calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0); 765 calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0); 766 calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0); 767 *p = (pixel_type) 768 (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) | 769 ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) | 770 (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 )); 771 } 772 773 static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) 774 { 775 return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); 776 } 777 778 static AGG_INLINE color_type make_color(pixel_type p) 779 { 780 return color_type((p << 5) & 0xFFE0, 781 (p >> 6) & 0xFFE0, 782 (p >> 16) & 0xFFC0); 783 } 784 785 private: 786 const Gamma* m_gamma; 787 }; 788 789 790 791 //===========================================pixfmt_alpha_blend_rgb_packed 792 template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_packed 793 { 794 public: 795 typedef RenBuf rbuf_type; 796 typedef typename rbuf_type::row_data row_data; 797 typedef Blender blender_type; 798 typedef typename blender_type::color_type color_type; 799 typedef typename blender_type::pixel_type pixel_type; 800 typedef int order_type; // A fake one 801 typedef typename color_type::value_type value_type; 802 typedef typename color_type::calc_type calc_type; 803 enum base_scale_e 804 { 805 base_shift = color_type::base_shift, 806 base_scale = color_type::base_scale, 807 base_mask = color_type::base_mask, 808 pix_width = sizeof(pixel_type) 809 }; 810 811 private: 812 //-------------------------------------------------------------------- 813 AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) 814 { 815 if (c.a) 816 { 817 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 818 if(alpha == base_mask) 819 { 820 *p = m_blender.make_pix(c.r, c.g, c.b); 821 } 822 else 823 { 824 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); 825 } 826 } 827 } 828 829 public: 830 //-------------------------------------------------------------------- 831 pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {} 832 void attach(rbuf_type& rb) { m_rbuf = &rb; } 833 834 //-------------------------------------------------------------------- 835 template<class PixFmt> 836 bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) 837 { 838 rect_i r(x1, y1, x2, y2); 839 if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) 840 { 841 int stride = pixf.stride(); 842 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 843 (r.x2 - r.x1) + 1, 844 (r.y2 - r.y1) + 1, 845 stride); 846 return true; 847 } 848 return false; 849 } 850 851 Blender& blender() { return m_blender; } 852 853 //-------------------------------------------------------------------- 854 AGG_INLINE unsigned width() const { return m_rbuf->width(); } 855 AGG_INLINE unsigned height() const { return m_rbuf->height(); } 856 AGG_INLINE int stride() const { return m_rbuf->stride(); } 857 858 //-------------------------------------------------------------------- 859 AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } 860 AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } 861 AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } 862 863 //-------------------------------------------------------------------- 864 AGG_INLINE int8u* pix_ptr(int x, int y) 865 { 866 return m_rbuf->row_ptr(y) + x * pix_width; 867 } 868 869 AGG_INLINE const int8u* pix_ptr(int x, int y) const 870 { 871 return m_rbuf->row_ptr(y) + x * pix_width; 872 } 873 874 //-------------------------------------------------------------------- 875 AGG_INLINE void make_pix(int8u* p, const color_type& c) 876 { 877 *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b); 878 } 879 880 //-------------------------------------------------------------------- 881 AGG_INLINE color_type pixel(int x, int y) const 882 { 883 return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]); 884 } 885 886 //-------------------------------------------------------------------- 887 AGG_INLINE void copy_pixel(int x, int y, const color_type& c) 888 { 889 ((pixel_type*) 890 m_rbuf->row_ptr(x, y, 1))[x] = 891 m_blender.make_pix(c.r, c.g, c.b); 892 } 893 894 //-------------------------------------------------------------------- 895 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) 896 { 897 copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover); 898 } 899 900 //-------------------------------------------------------------------- 901 AGG_INLINE void copy_hline(int x, int y, 902 unsigned len, 903 const color_type& c) 904 { 905 pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; 906 pixel_type v = m_blender.make_pix(c.r, c.g, c.b); 907 do 908 { 909 *p++ = v; 910 } 911 while(--len); 912 } 913 914 //-------------------------------------------------------------------- 915 AGG_INLINE void copy_vline(int x, int y, 916 unsigned len, 917 const color_type& c) 918 { 919 pixel_type v = m_blender.make_pix(c.r, c.g, c.b); 920 do 921 { 922 pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; 923 *p = v; 924 } 925 while(--len); 926 } 927 928 //-------------------------------------------------------------------- 929 void blend_hline(int x, int y, 930 unsigned len, 931 const color_type& c, 932 int8u cover) 933 { 934 if (c.a) 935 { 936 pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; 937 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 938 if(alpha == base_mask) 939 { 940 pixel_type v = m_blender.make_pix(c.r, c.g, c.b); 941 do 942 { 943 *p++ = v; 944 } 945 while(--len); 946 } 947 else 948 { 949 do 950 { 951 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); 952 ++p; 953 } 954 while(--len); 955 } 956 } 957 } 958 959 //-------------------------------------------------------------------- 960 void blend_vline(int x, int y, 961 unsigned len, 962 const color_type& c, 963 int8u cover) 964 { 965 if (c.a) 966 { 967 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; 968 if(alpha == base_mask) 969 { 970 pixel_type v = m_blender.make_pix(c.r, c.g, c.b); 971 do 972 { 973 ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v; 974 } 975 while(--len); 976 } 977 else 978 { 979 do 980 { 981 m_blender.blend_pix( 982 (pixel_type*)m_rbuf->row_ptr(x, y++, 1), 983 c.r, c.g, c.b, alpha, cover); 984 } 985 while(--len); 986 } 987 } 988 } 989 990 //-------------------------------------------------------------------- 991 void blend_solid_hspan(int x, int y, 992 unsigned len, 993 const color_type& c, 994 const int8u* covers) 995 { 996 pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; 997 do 998 { 999 copy_or_blend_pix(p, c, *covers++); 1000 ++p; 1001 } 1002 while(--len); 1003 } 1004 1005 //-------------------------------------------------------------------- 1006 void blend_solid_vspan(int x, int y, 1007 unsigned len, 1008 const color_type& c, 1009 const int8u* covers) 1010 { 1011 do 1012 { 1013 copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, 1014 c, *covers++); 1015 } 1016 while(--len); 1017 } 1018 1019 //-------------------------------------------------------------------- 1020 void copy_color_hspan(int x, int y, 1021 unsigned len, 1022 const color_type* colors) 1023 { 1024 pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; 1025 do 1026 { 1027 *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); 1028 ++colors; 1029 } 1030 while(--len); 1031 } 1032 1033 //-------------------------------------------------------------------- 1034 void copy_color_vspan(int x, int y, 1035 unsigned len, 1036 const color_type* colors) 1037 { 1038 do 1039 { 1040 pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; 1041 *p = m_blender.make_pix(colors->r, colors->g, colors->b); 1042 ++colors; 1043 } 1044 while(--len); 1045 } 1046 1047 //-------------------------------------------------------------------- 1048 void blend_color_hspan(int x, int y, 1049 unsigned len, 1050 const color_type* colors, 1051 const int8u* covers, 1052 int8u cover) 1053 { 1054 pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; 1055 do 1056 { 1057 copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); 1058 } 1059 while(--len); 1060 } 1061 1062 //-------------------------------------------------------------------- 1063 void blend_color_vspan(int x, int y, 1064 unsigned len, 1065 const color_type* colors, 1066 const int8u* covers, 1067 int8u cover) 1068 { 1069 do 1070 { 1071 copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, 1072 *colors++, covers ? *covers++ : cover); 1073 } 1074 while(--len); 1075 } 1076 1077 //-------------------------------------------------------------------- 1078 template<class RenBuf2> 1079 void copy_from(const RenBuf2& from, 1080 int xdst, int ydst, 1081 int xsrc, int ysrc, 1082 unsigned len) 1083 { 1084 const int8u* p = from.row_ptr(ysrc); 1085 if(p) 1086 { 1087 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 1088 p + xsrc * pix_width, 1089 len * pix_width); 1090 } 1091 } 1092 1093 //-------------------------------------------------------------------- 1094 template<class SrcPixelFormatRenderer> 1095 void blend_from(const SrcPixelFormatRenderer& from, 1096 int xdst, int ydst, 1097 int xsrc, int ysrc, 1098 unsigned len, 1099 int8u cover) 1100 { 1101 typedef typename SrcPixelFormatRenderer::order_type src_order; 1102 1103 const value_type* psrc = (const value_type*)from.row_ptr(ysrc); 1104 if(psrc) 1105 { 1106 psrc += xsrc * 4; 1107 pixel_type* pdst = 1108 (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; 1109 do 1110 { 1111 value_type alpha = psrc[src_order::A]; 1112 if(alpha) 1113 { 1114 if(alpha == base_mask && cover == 255) 1115 { 1116 *pdst = m_blender.make_pix(psrc[src_order::R], 1117 psrc[src_order::G], 1118 psrc[src_order::B]); 1119 } 1120 else 1121 { 1122 m_blender.blend_pix(pdst, 1123 psrc[src_order::R], 1124 psrc[src_order::G], 1125 psrc[src_order::B], 1126 alpha, 1127 cover); 1128 } 1129 } 1130 psrc += 4; 1131 ++pdst; 1132 } 1133 while(--len); 1134 } 1135 } 1136 1137 private: 1138 rbuf_type* m_rbuf; 1139 Blender m_blender; 1140 }; 1141 1142 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555, rendering_buffer> pixfmt_rgb555; //----pixfmt_rgb555 1143 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565, rendering_buffer> pixfmt_rgb565; //----pixfmt_rgb565 1144 1145 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555_pre, rendering_buffer> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre 1146 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565_pre, rendering_buffer> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre 1147 1148 typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA, rendering_buffer> pixfmt_rgbAAA; //----pixfmt_rgbAAA 1149 typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA, rendering_buffer> pixfmt_bgrAAA; //----pixfmt_bgrAAA 1150 typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA, rendering_buffer> pixfmt_rgbBBA; //----pixfmt_rgbBBA 1151 typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB, rendering_buffer> pixfmt_bgrABB; //----pixfmt_bgrABB 1152 1153 typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_pre, rendering_buffer> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre 1154 typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_pre, rendering_buffer> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre 1155 typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_pre, rendering_buffer> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre 1156 typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB_pre, rendering_buffer> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre 1157 1158 1159 //-----------------------------------------------------pixfmt_rgb555_gamma 1160 template<class Gamma> class pixfmt_rgb555_gamma : 1161 public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, 1162 rendering_buffer> 1163 { 1164 public: 1165 pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : 1166 pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, 1167 rendering_buffer>(rb) 1168 { 1169 this->blender().gamma(g); 1170 } 1171 }; 1172 1173 1174 //-----------------------------------------------------pixfmt_rgb565_gamma 1175 template<class Gamma> class pixfmt_rgb565_gamma : 1176 public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer> 1177 { 1178 public: 1179 pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : 1180 pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>(rb) 1181 { 1182 this->blender().gamma(g); 1183 } 1184 }; 1185 1186 1187 //-----------------------------------------------------pixfmt_rgbAAA_gamma 1188 template<class Gamma> class pixfmt_rgbAAA_gamma : 1189 public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, 1190 rendering_buffer> 1191 { 1192 public: 1193 pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : 1194 pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, 1195 rendering_buffer>(rb) 1196 { 1197 this->blender().gamma(g); 1198 } 1199 }; 1200 1201 1202 //-----------------------------------------------------pixfmt_bgrAAA_gamma 1203 template<class Gamma> class pixfmt_bgrAAA_gamma : 1204 public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, 1205 rendering_buffer> 1206 { 1207 public: 1208 pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : 1209 pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, 1210 rendering_buffer>(rb) 1211 { 1212 this->blender().gamma(g); 1213 } 1214 }; 1215 1216 1217 //-----------------------------------------------------pixfmt_rgbBBA_gamma 1218 template<class Gamma> class pixfmt_rgbBBA_gamma : 1219 public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, 1220 rendering_buffer> 1221 { 1222 public: 1223 pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : 1224 pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, 1225 rendering_buffer>(rb) 1226 { 1227 this->blender().gamma(g); 1228 } 1229 }; 1230 1231 1232 //-----------------------------------------------------pixfmt_bgrABB_gamma 1233 template<class Gamma> class pixfmt_bgrABB_gamma : 1234 public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, 1235 rendering_buffer> 1236 { 1237 public: 1238 pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : 1239 pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, 1240 rendering_buffer>(rb) 1241 { 1242 this->blender().gamma(g); 1243 } 1244 }; 1245 1246 1247 } 1248 1249 #endif 1250 1251