//---------------------------------------------------------------------------- // Anti-Grain Geometry (AGG) - Version 2.5 // A high quality rendering engine for C++ // Copyright (C) 2002-2006 Maxim Shemanarev // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://antigrain.com // // AGG is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // AGG is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with AGG; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, // MA 02110-1301, USA. //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_RGB_PACKED_INCLUDED #define AGG_PIXFMT_RGB_PACKED_INCLUDED #include <string.h> #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_rendering_buffer.h" namespace agg { //=========================================================blender_rgb555 struct blender_rgb555 { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 7) & 0xF8; calc_type g = (rgb >> 2) & 0xF8; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) | ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3) | 0x8000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 7) & 0xF8, (p >> 2) & 0xF8, (p << 3) & 0xF8); } }; //=====================================================blender_rgb555_pre struct blender_rgb555_pre { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; pixel_type rgb = *p; calc_type r = (rgb >> 7) & 0xF8; calc_type g = (rgb >> 2) & 0xF8; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) ((((r * alpha + cr * cover) >> 1) & 0x7C00) | (((g * alpha + cg * cover) >> 6) & 0x03E0) | ((b * alpha + cb * cover) >> 11) | 0x8000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3) | 0x8000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 7) & 0xF8, (p >> 2) & 0xF8, (p << 3) & 0xF8); } }; //=====================================================blender_rgb555_gamma template<class Gamma> class blender_rgb555_gamma { public: typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; typedef Gamma gamma_type; blender_rgb555_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 7) & 0xF8); calc_type g = m_gamma->dir((rgb >> 2) & 0xF8); calc_type b = m_gamma->dir((rgb << 3) & 0xF8); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3) | 0x8000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 7) & 0xF8, (p >> 2) & 0xF8, (p << 3) & 0xF8); } private: const Gamma* m_gamma; }; //=========================================================blender_rgb565 struct blender_rgb565 { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 8) & 0xF8; calc_type g = (rgb >> 3) & 0xFC; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) (((((cr - r) * alpha + (r << 8)) ) & 0xF800) | ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) | (((cb - b) * alpha + (b << 8)) >> 11)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 8) & 0xF8, (p >> 3) & 0xFC, (p << 3) & 0xF8); } }; //=====================================================blender_rgb565_pre struct blender_rgb565_pre { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; pixel_type rgb = *p; calc_type r = (rgb >> 8) & 0xF8; calc_type g = (rgb >> 3) & 0xFC; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) ((((r * alpha + cr * cover) ) & 0xF800) | (((g * alpha + cg * cover) >> 5 ) & 0x07E0) | ((b * alpha + cb * cover) >> 11)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 8) & 0xF8, (p >> 3) & 0xFC, (p << 3) & 0xF8); } }; //=====================================================blender_rgb565_gamma template<class Gamma> class blender_rgb565_gamma { public: typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; typedef Gamma gamma_type; blender_rgb565_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 8) & 0xF8); calc_type g = m_gamma->dir((rgb >> 3) & 0xFC); calc_type b = m_gamma->dir((rgb << 3) & 0xF8); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 8) & 0xF8, (p >> 3) & 0xFC, (p << 3) & 0xF8); } private: const Gamma* m_gamma; }; //=====================================================blender_rgbAAA struct blender_rgbAAA { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 14) & 0xFFC0; calc_type g = (rgb >> 4) & 0xFFC0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) | ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (b >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 14) & 0xFFC0, (p >> 4) & 0xFFC0, (p << 6) & 0xFFC0); } }; //==================================================blender_rgbAAA_pre struct blender_rgbAAA_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type rgb = *p; calc_type r = (rgb >> 14) & 0xFFC0; calc_type g = (rgb >> 4) & 0xFFC0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) | (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | ((b * alpha + cb * cover) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (b >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 14) & 0xFFC0, (p >> 4) & 0xFFC0, (p << 6) & 0xFFC0); } }; //=================================================blender_rgbAAA_gamma template<class Gamma> class blender_rgbAAA_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_rgbAAA_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0); calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0); calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (b >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 14) & 0xFFC0, (p >> 4) & 0xFFC0, (p << 6) & 0xFFC0); } private: const Gamma* m_gamma; }; //=====================================================blender_bgrAAA struct blender_bgrAAA { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = (bgr >> 14) & 0xFFC0; calc_type g = (bgr >> 4) & 0xFFC0; calc_type r = (bgr << 6) & 0xFFC0; *p = (pixel_type) (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) | ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (r >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 6) & 0xFFC0, (p >> 4) & 0xFFC0, (p >> 14) & 0xFFC0); } }; //=================================================blender_bgrAAA_pre struct blender_bgrAAA_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type bgr = *p; calc_type b = (bgr >> 14) & 0xFFC0; calc_type g = (bgr >> 4) & 0xFFC0; calc_type r = (bgr << 6) & 0xFFC0; *p = (pixel_type) ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) | (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | ((r * alpha + cr * cover) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (r >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 6) & 0xFFC0, (p >> 4) & 0xFFC0, (p >> 14) & 0xFFC0); } }; //=================================================blender_bgrAAA_gamma template<class Gamma> class blender_bgrAAA_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_bgrAAA_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0); calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0); calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (r >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 6) & 0xFFC0, (p >> 4) & 0xFFC0, (p >> 14) & 0xFFC0); } private: const Gamma* m_gamma; }; //=====================================================blender_rgbBBA struct blender_rgbBBA { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 16) & 0xFFE0; calc_type g = (rgb >> 5) & 0xFFE0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) | ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) | (((cb - b) * alpha + (b << 16)) >> 22)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 16) & 0xFFE0, (p >> 5) & 0xFFE0, (p << 6) & 0xFFC0); } }; //=================================================blender_rgbBBA_pre struct blender_rgbBBA_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type rgb = *p; calc_type r = (rgb >> 16) & 0xFFE0; calc_type g = (rgb >> 5) & 0xFFE0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) ((((r * alpha + cr * cover) ) & 0xFFE00000) | (((g * alpha + cg * cover) >> 11) & 0x001FFC00) | ((b * alpha + cb * cover) >> 22)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 16) & 0xFFE0, (p >> 5) & 0xFFE0, (p << 6) & 0xFFC0); } }; //=================================================blender_rgbBBA_gamma template<class Gamma> class blender_rgbBBA_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_rgbBBA_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0); calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0); calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 )); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 16) & 0xFFE0, (p >> 5) & 0xFFE0, (p << 6) & 0xFFC0); } private: const Gamma* m_gamma; }; //=====================================================blender_bgrABB struct blender_bgrABB { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = (bgr >> 16) & 0xFFC0; calc_type g = (bgr >> 6) & 0xFFE0; calc_type r = (bgr << 5) & 0xFFE0; *p = (pixel_type) (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) | ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) | (((cr - r) * alpha + (r << 16)) >> 21)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 5) & 0xFFE0, (p >> 6) & 0xFFE0, (p >> 16) & 0xFFC0); } }; //=================================================blender_bgrABB_pre struct blender_bgrABB_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type bgr = *p; calc_type b = (bgr >> 16) & 0xFFC0; calc_type g = (bgr >> 6) & 0xFFE0; calc_type r = (bgr << 5) & 0xFFE0; *p = (pixel_type) ((((b * alpha + cb * cover) ) & 0xFFC00000) | (((g * alpha + cg * cover) >> 10) & 0x003FF800) | ((r * alpha + cr * cover) >> 21)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 5) & 0xFFE0, (p >> 6) & 0xFFE0, (p >> 16) & 0xFFC0); } }; //=================================================blender_bgrABB_gamma template<class Gamma> class blender_bgrABB_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_bgrABB_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0); calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0); calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) | (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 )); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 5) & 0xFFE0, (p >> 6) & 0xFFE0, (p >> 16) & 0xFFC0); } private: const Gamma* m_gamma; }; //===========================================pixfmt_alpha_blend_rgb_packed template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_packed { public: typedef RenBuf rbuf_type; typedef typename rbuf_type::row_data row_data; typedef Blender blender_type; typedef typename blender_type::color_type color_type; typedef typename blender_type::pixel_type pixel_type; typedef int order_type; // A fake one typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask, pix_width = sizeof(pixel_type) }; private: //-------------------------------------------------------------------- AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) { if (c.a) { calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { *p = m_blender.make_pix(c.r, c.g, c.b); } else { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); } } } public: //-------------------------------------------------------------------- explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {} void attach(rbuf_type& rb) { m_rbuf = &rb; } //-------------------------------------------------------------------- template<class PixFmt> bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) { rect_i r(x1, y1, x2, y2); if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) { int stride = pixf.stride(); m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), (r.x2 - r.x1) + 1, (r.y2 - r.y1) + 1, stride); return true; } return false; } Blender& blender() { return m_blender; } //-------------------------------------------------------------------- AGG_INLINE unsigned width() const { return m_rbuf->width(); } AGG_INLINE unsigned height() const { return m_rbuf->height(); } AGG_INLINE int stride() const { return m_rbuf->stride(); } //-------------------------------------------------------------------- AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } //-------------------------------------------------------------------- AGG_INLINE int8u* pix_ptr(int x, int y) { return m_rbuf->row_ptr(y) + x * pix_width; } AGG_INLINE const int8u* pix_ptr(int x, int y) const { return m_rbuf->row_ptr(y) + x * pix_width; } //-------------------------------------------------------------------- AGG_INLINE void make_pix(int8u* p, const color_type& c) { *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b); } //-------------------------------------------------------------------- AGG_INLINE color_type pixel(int x, int y) const { return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { ((pixel_type*) m_rbuf->row_ptr(x, y, 1))[x] = m_blender.make_pix(c.r, c.g, c.b); } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover); } //-------------------------------------------------------------------- AGG_INLINE void copy_hline(int x, int y, unsigned len, const color_type& c) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { *p++ = v; } while(--len); } //-------------------------------------------------------------------- AGG_INLINE void copy_vline(int x, int y, unsigned len, const color_type& c) { pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; *p = v; } while(--len); } //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { *p++ = v; } while(--len); } else { do { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); ++p; } while(--len); } } } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v; } while(--len); } else { do { m_blender.blend_pix( (pixel_type*)m_rbuf->row_ptr(x, y++, 1), c.r, c.g, c.b, alpha, cover); } while(--len); } } } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { copy_or_blend_pix(p, c, *covers++); ++p; } while(--len); } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { do { copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, c, *covers++); } while(--len); } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); ++colors; } while(--len); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { do { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; *p = m_blender.make_pix(colors->r, colors->g, colors->b); ++colors; } while(--len); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); } while(--len); } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { do { copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, *colors++, covers ? *covers++ : cover); } while(--len); } //-------------------------------------------------------------------- template<class RenBuf2> void copy_from(const RenBuf2& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { const int8u* p = from.row_ptr(ysrc); if(p) { memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, p + xsrc * pix_width, len * pix_width); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::order_type src_order; const value_type* psrc = (const value_type*)from.row_ptr(ysrc); if(psrc) { psrc += xsrc * 4; pixel_type* pdst = (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { value_type alpha = psrc[src_order::A]; if(alpha) { if(alpha == base_mask && cover == 255) { *pdst = m_blender.make_pix(psrc[src_order::R], psrc[src_order::G], psrc[src_order::B]); } else { m_blender.blend_pix(pdst, psrc[src_order::R], psrc[src_order::G], psrc[src_order::B], alpha, cover); } } psrc += 4; ++pdst; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_color(const SrcPixelFormatRenderer& from, const color_type& color, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { pixel_type* pdst = (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { m_blender.blend_pix(pdst, color.r, color.g, color.b, color.a, cover); ++psrc; ++pdst; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_lut(const SrcPixelFormatRenderer& from, const color_type* color_lut, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { pixel_type* pdst = (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { const color_type& color = color_lut[*psrc]; m_blender.blend_pix(pdst, color.r, color.g, color.b, color.a, cover); ++psrc; ++pdst; } while(--len); } } private: rbuf_type* m_rbuf; Blender m_blender; }; typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555, rendering_buffer> pixfmt_rgb555; //----pixfmt_rgb555 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565, rendering_buffer> pixfmt_rgb565; //----pixfmt_rgb565 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555_pre, rendering_buffer> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565_pre, rendering_buffer> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA, rendering_buffer> pixfmt_rgbAAA; //----pixfmt_rgbAAA typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA, rendering_buffer> pixfmt_bgrAAA; //----pixfmt_bgrAAA typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA, rendering_buffer> pixfmt_rgbBBA; //----pixfmt_rgbBBA typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB, rendering_buffer> pixfmt_bgrABB; //----pixfmt_bgrABB typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_pre, rendering_buffer> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_pre, rendering_buffer> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_pre, rendering_buffer> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB_pre, rendering_buffer> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre //-----------------------------------------------------pixfmt_rgb555_gamma template<class Gamma> class pixfmt_rgb555_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_rgb565_gamma template<class Gamma> class pixfmt_rgb565_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_rgbAAA_gamma template<class Gamma> class pixfmt_rgbAAA_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_bgrAAA_gamma template<class Gamma> class pixfmt_bgrAAA_gamma : public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, rendering_buffer> { public: pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_rgbBBA_gamma template<class Gamma> class pixfmt_rgbBBA_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_bgrABB_gamma template<class Gamma> class pixfmt_bgrABB_gamma : public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, rendering_buffer> { public: pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; } #endif |