1
2//----------------------------------------------------------------------------
3// Anti-Grain Geometry - Version 2.3
4// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5//
6// Permission to copy, use, modify, sell and distribute this software
7// is granted provided this copyright notice appears in all copies.
8// This software is provided "as is" without express or implied
9// warranty, and with no claim as to its suitability for any purpose.
10//
11//----------------------------------------------------------------------------
12// Contact: mcseem@antigrain.com
13//          mcseemagg@yahoo.com
14//          http://www.antigrain.com
15//----------------------------------------------------------------------------
16//
17// Adaptation for high precision colors has been sponsored by
18// Liberty Technology Systems, Inc., visit http://lib-sys.com
19//
20// Liberty Technology Systems, Inc. is the provider of
21// PostScript and PDF technology for software developers.
22//
23//----------------------------------------------------------------------------
24#ifndef AGG_PIXFMT_GRAY_INCLUDED
25#define AGG_PIXFMT_GRAY_INCLUDED
26#include "agg_basics.h"
27#include "agg_color_gray.h"
28#include "agg_rendering_buffer.h"
29namespace agg
30{
31template<class ColorT> struct blender_gray : public CFX_Object {
32    typedef ColorT color_type;
33    typedef typename color_type::value_type value_type;
34    typedef typename color_type::calc_type calc_type;
35    enum base_scale_e { base_shift = color_type::base_shift };
36    static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
37                                     unsigned alpha, unsigned cover = 0)
38    {
39        *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
40    }
41};
42template<class Blender, unsigned Step = 1, unsigned Offset = 0>
43class pixel_formats_gray : public CFX_Object
44{
45public:
46    typedef rendering_buffer::row_data row_data;
47    typedef rendering_buffer::span_data span_data;
48    typedef typename Blender::color_type color_type;
49    typedef typename color_type::value_type value_type;
50    typedef typename color_type::calc_type calc_type;
51    enum base_scale_e {
52        base_shift = color_type::base_shift,
53        base_size  = color_type::base_size,
54        base_mask  = color_type::base_mask
55    };
56private:
57    static AGG_INLINE void copy_or_blend_pix(value_type* p,
58            const color_type& c,
59            unsigned cover)
60    {
61        if (c.a) {
62            calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
63            if(alpha == base_mask) {
64                *p = c.v;
65            } else {
66                Blender::blend_pix(p, c.v, alpha, cover);
67            }
68        }
69    }
70    static AGG_INLINE void copy_or_blend_pix(value_type* p,
71            const color_type& c)
72    {
73        if (c.a) {
74            if(c.a == base_mask) {
75                *p = c.v;
76            } else {
77                Blender::blend_pix(p, c.v, c.a);
78            }
79        }
80    }
81public:
82    pixel_formats_gray(rendering_buffer& rb) :
83        m_rbuf(&rb)
84    {}
85    AGG_INLINE unsigned width()  const
86    {
87        return m_rbuf->width();
88    }
89    AGG_INLINE unsigned height() const
90    {
91        return m_rbuf->height();
92    }
93    AGG_INLINE color_type pixel(int x, int y) const
94    {
95        value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset;
96        return color_type(*p);
97    }
98    row_data row(int x, int y) const
99    {
100        return row_data(x,
101                        width() - 1,
102                        m_rbuf->row(y) +
103                        x * Step * sizeof(value_type) +
104                        Offset * sizeof(value_type));
105    }
106    span_data span(int x, int y, unsigned len)
107    {
108        return span_data(x, len,
109                         m_rbuf->row(y) +
110                         x * Step * sizeof(value_type) +
111                         Offset * sizeof(value_type));
112    }
113    AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
114    {
115        *((value_type*)m_rbuf->row(y) + x * Step + Offset) = c.v;
116    }
117    AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
118    {
119        copy_or_blend_pix((value_type*)m_rbuf->row(y) + x * Step + Offset, c, cover);
120    }
121    AGG_INLINE void copy_hline(int x, int y,
122                               unsigned len,
123                               const color_type& c)
124    {
125        value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset;
126        do {
127            *p = c.v;
128            p += Step;
129        } while(--len);
130    }
131    void blend_hline(int x, int y,
132                     unsigned len,
133                     const color_type& c,
134                     int8u cover)
135    {
136        if (c.a) {
137            value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset;
138            calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
139            if(alpha == base_mask) {
140                do {
141                    *p = c.v;
142                    p += Step;
143                } while(--len);
144            } else {
145                do {
146                    Blender::blend_pix(p, c.v, alpha, cover);
147                    p += Step;
148                } while(--len);
149            }
150        }
151    }
152    void blend_solid_hspan(int x, int y,
153                           unsigned len,
154                           const color_type& c,
155                           const int8u* covers)
156    {
157        if (c.a) {
158            value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset;
159            do {
160                calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
161                if(alpha == base_mask) {
162                    *p = c.v;
163                } else {
164                    Blender::blend_pix(p, c.v, alpha, *covers);
165                }
166                p += Step;
167                ++covers;
168            } while(--len);
169        }
170    }
171private:
172    rendering_buffer* m_rbuf;
173};
174typedef blender_gray<gray8>      blender_gray8;
175typedef pixel_formats_gray<blender_gray8, 1, 0> pixfmt_gray8;
176}
177#endif
178