1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry (AGG) - Version 2.5
3 // A high quality rendering engine for C++
4 // Copyright (C) 2002-2006 Maxim Shemanarev
5 // Contact: mcseem@antigrain.com
6 //          mcseemagg@yahoo.com
7 //          http://antigrain.com
8 //
9 // AGG is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // AGG is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with AGG; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 // MA 02110-1301, USA.
23 //----------------------------------------------------------------------------
24 
25 #ifndef AGG_RENDERING_BUFFER_INCLUDED
26 #define AGG_RENDERING_BUFFER_INCLUDED
27 
28 #include "agg_array.h"
29 
30 namespace agg
31 {
32 
33     //===========================================================row_accessor
34     template<class T> class row_accessor
35     {
36     public:
37         typedef const_row_info<T> row_data;
38 
39         //-------------------------------------------------------------------
row_accessor()40         row_accessor() :
41             m_buf(0),
42             m_start(0),
43             m_width(0),
44             m_height(0),
45             m_stride(0)
46         {
47         }
48 
49         //--------------------------------------------------------------------
row_accessor(T * buf,unsigned width,unsigned height,int stride)50         row_accessor(T* buf, unsigned width, unsigned height, int stride) :
51             m_buf(0),
52             m_start(0),
53             m_width(0),
54             m_height(0),
55             m_stride(0)
56         {
57             attach(buf, width, height, stride);
58         }
59 
60 
61         //--------------------------------------------------------------------
attach(T * buf,unsigned width,unsigned height,int stride)62         void attach(T* buf, unsigned width, unsigned height, int stride)
63         {
64 			m_buf = m_start = buf;
65 			m_width = width;
66 			m_height = height;
67 			m_stride = stride;
68 			if(stride < 0)
69             {
70 				m_start = m_buf - int(height - 1) * stride;
71 			}
72         }
73 
74         //--------------------------------------------------------------------
buf()75         AGG_INLINE       T* buf()          { return m_buf;    }
buf()76         AGG_INLINE const T* buf()    const { return m_buf;    }
width()77         AGG_INLINE unsigned width()  const { return m_width;  }
height()78         AGG_INLINE unsigned height() const { return m_height; }
stride()79         AGG_INLINE int      stride() const { return m_stride; }
stride_abs()80         AGG_INLINE unsigned stride_abs() const
81         {
82             return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
83         }
84 
85         //--------------------------------------------------------------------
row_ptr(int,int y,unsigned)86 		AGG_INLINE       T* row_ptr(int, int y, unsigned)
87         {
88             return m_start + y * m_stride;
89         }
row_ptr(int y)90 		AGG_INLINE       T* row_ptr(int y)       { return m_start + y * m_stride; }
row_ptr(int y)91 		AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
row(int y)92 		AGG_INLINE row_data row    (int y) const
93         {
94             return row_data(0, m_width-1, row_ptr(y));
95         }
96 
97         //--------------------------------------------------------------------
98         template<class RenBuf>
copy_from(const RenBuf & src)99         void copy_from(const RenBuf& src)
100         {
101             unsigned h = height();
102             if(src.height() < h) h = src.height();
103 
104             unsigned l = stride_abs();
105             if(src.stride_abs() < l) l = src.stride_abs();
106 
107             l *= sizeof(T);
108 
109             unsigned y;
110             unsigned w = width();
111             for (y = 0; y < h; y++)
112             {
113                 memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
114             }
115         }
116 
117         //--------------------------------------------------------------------
clear(T value)118         void clear(T value)
119         {
120             unsigned y;
121             unsigned w = width();
122             unsigned stride = stride_abs();
123             for(y = 0; y < height(); y++)
124             {
125                 T* p = row_ptr(0, y, w);
126                 unsigned x;
127                 for(x = 0; x < stride; x++)
128                 {
129                     *p++ = value;
130                 }
131             }
132         }
133 
134     private:
135         //--------------------------------------------------------------------
136         T*            m_buf;    // Pointer to renrdering buffer
137         T*            m_start;  // Pointer to first pixel depending on stride
138         unsigned      m_width;  // Width in pixels
139         unsigned      m_height; // Height in pixels
140         int           m_stride; // Number of bytes per row. Can be < 0
141     };
142 
143 
144 
145 
146     //==========================================================row_ptr_cache
147     template<class T> class row_ptr_cache
148     {
149     public:
150         typedef const_row_info<T> row_data;
151 
152         //-------------------------------------------------------------------
row_ptr_cache()153         row_ptr_cache() :
154             m_buf(0),
155             m_rows(),
156             m_width(0),
157             m_height(0),
158             m_stride(0)
159         {
160         }
161 
162         //--------------------------------------------------------------------
row_ptr_cache(T * buf,unsigned width,unsigned height,int stride)163         row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
164             m_buf(0),
165             m_rows(),
166             m_width(0),
167             m_height(0),
168             m_stride(0)
169         {
170             attach(buf, width, height, stride);
171         }
172 
173         //--------------------------------------------------------------------
attach(T * buf,unsigned width,unsigned height,int stride)174         void attach(T* buf, unsigned width, unsigned height, int stride)
175         {
176             m_buf = buf;
177             m_width = width;
178             m_height = height;
179             m_stride = stride;
180             if(height > m_rows.size())
181             {
182                 m_rows.resize(height);
183             }
184 
185             T* row_ptr = m_buf;
186 
187             if(stride < 0)
188             {
189                 row_ptr = m_buf - int(height - 1) * stride;
190             }
191 
192             T** rows = &m_rows[0];
193 
194             while(height--)
195             {
196                 *rows++ = row_ptr;
197                 row_ptr += stride;
198             }
199         }
200 
201         //--------------------------------------------------------------------
buf()202         AGG_INLINE       T* buf()          { return m_buf;    }
buf()203         AGG_INLINE const T* buf()    const { return m_buf;    }
width()204         AGG_INLINE unsigned width()  const { return m_width;  }
height()205         AGG_INLINE unsigned height() const { return m_height; }
stride()206         AGG_INLINE int      stride() const { return m_stride; }
stride_abs()207         AGG_INLINE unsigned stride_abs() const
208         {
209             return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
210         }
211 
212         //--------------------------------------------------------------------
row_ptr(int,int y,unsigned)213         AGG_INLINE       T* row_ptr(int, int y, unsigned)
214         {
215             return m_rows[y];
216         }
row_ptr(int y)217         AGG_INLINE       T* row_ptr(int y)       { return m_rows[y]; }
row_ptr(int y)218         AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
row(int y)219         AGG_INLINE row_data row    (int y) const
220         {
221             return row_data(0, m_width-1, m_rows[y]);
222         }
223 
224         //--------------------------------------------------------------------
rows()225         T const* const* rows() const { return &m_rows[0]; }
226 
227         //--------------------------------------------------------------------
228         template<class RenBuf>
copy_from(const RenBuf & src)229         void copy_from(const RenBuf& src)
230         {
231             unsigned h = height();
232             if(src.height() < h) h = src.height();
233 
234             unsigned l = stride_abs();
235             if(src.stride_abs() < l) l = src.stride_abs();
236 
237             l *= sizeof(T);
238 
239             unsigned y;
240             unsigned w = width();
241             for (y = 0; y < h; y++)
242             {
243                 memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
244             }
245         }
246 
247         //--------------------------------------------------------------------
clear(T value)248         void clear(T value)
249         {
250             unsigned y;
251             unsigned w = width();
252             unsigned stride = stride_abs();
253             for(y = 0; y < height(); y++)
254             {
255                 T* p = row_ptr(0, y, w);
256                 unsigned x;
257                 for(x = 0; x < stride; x++)
258                 {
259                     *p++ = value;
260                 }
261             }
262         }
263 
264     private:
265         //--------------------------------------------------------------------
266         T*            m_buf;        // Pointer to renrdering buffer
267         pod_array<T*> m_rows;       // Pointers to each row of the buffer
268         unsigned      m_width;      // Width in pixels
269         unsigned      m_height;     // Height in pixels
270         int           m_stride;     // Number of bytes per row. Can be < 0
271     };
272 
273 
274 
275 
276     //========================================================rendering_buffer
277     //
278     // The definition of the main type for accessing the rows in the frame
279     // buffer. It provides functionality to navigate to the rows in a
280     // rectangular matrix, from top to bottom or from bottom to top depending
281     // on stride.
282     //
283     // row_accessor is cheap to create/destroy, but performs one multiplication
284     // when calling row_ptr().
285     //
286     // row_ptr_cache creates an array of pointers to rows, so, the access
287     // via row_ptr() may be faster. But it requires memory allocation
288     // when creating. For example, on typical Intel Pentium hardware
289     // row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
290     //
291     // It's used only in short hand typedefs like pixfmt_rgba32 and can be
292     // redefined in agg_config.h
293     // In real applications you can use both, depending on your needs
294     //------------------------------------------------------------------------
295 #ifdef AGG_RENDERING_BUFFER
296     typedef AGG_RENDERING_BUFFER rendering_buffer;
297 #else
298 //  typedef row_ptr_cache<int8u> rendering_buffer;
299     typedef row_accessor<int8u> rendering_buffer;
300 #endif
301 
302 }
303 
304 
305 #endif
306