//----------------------------------------------------------------------------
// 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_