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#ifndef AGG_IMAGE_ACCESSORS_INCLUDED
17#define AGG_IMAGE_ACCESSORS_INCLUDED
18
19#include "agg_basics.h"
20
21namespace agg
22{
23
24    //-----------------------------------------------------image_accessor_clip
25    template<class PixFmt> class image_accessor_clip
26    {
27    public:
28        typedef PixFmt   pixfmt_type;
29        typedef typename pixfmt_type::color_type color_type;
30        typedef typename pixfmt_type::order_type order_type;
31        typedef typename pixfmt_type::value_type value_type;
32        enum pix_width_e { pix_width = pixfmt_type::pix_width };
33
34        image_accessor_clip() {}
35        image_accessor_clip(const pixfmt_type& pixf, const color_type& bk) :
36            m_pixf(&pixf)
37        {
38            pixfmt_type::make_pix(m_bk_buf, bk);
39        }
40
41        void attach(const pixfmt_type& pixf)
42        {
43            m_pixf = &pixf;
44        }
45
46        void background_color(const color_type& bk)
47        {
48            pixfmt_type::make_pix(m_bk_buf, bk);
49        }
50
51    private:
52        AGG_INLINE const int8u* pixel() const
53        {
54            if(m_y >= 0 && m_y < (int)m_pixf->height() &&
55               m_x >= 0 && m_x < (int)m_pixf->width())
56            {
57                return m_pixf->pix_ptr(m_x, m_y);
58            }
59            return m_bk_buf;
60        }
61
62    public:
63        AGG_INLINE const int8u* span(int x, int y, unsigned len)
64        {
65            m_x = m_x0 = x;
66            m_y = y;
67            if(y >= 0 && y < (int)m_pixf->height() &&
68               x >= 0 && x+(int)len <= (int)m_pixf->width())
69            {
70                return m_pix_ptr = m_pixf->pix_ptr(x, y);
71            }
72            m_pix_ptr = 0;
73            return pixel();
74        }
75
76        AGG_INLINE const int8u* next_x()
77        {
78            if(m_pix_ptr) return m_pix_ptr += pix_width;
79            ++m_x;
80            return pixel();
81        }
82
83        AGG_INLINE const int8u* next_y()
84        {
85            ++m_y;
86            m_x = m_x0;
87            if(m_pix_ptr &&
88               m_y >= 0 && m_y < (int)m_pixf->height())
89            {
90                return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
91            }
92            m_pix_ptr = 0;
93            return pixel();
94        }
95
96    private:
97        const pixfmt_type* m_pixf;
98        int8u              m_bk_buf[4];
99        int                m_x, m_x0, m_y;
100        const int8u*       m_pix_ptr;
101    };
102
103
104
105
106    //--------------------------------------------------image_accessor_no_clip
107    template<class PixFmt> class image_accessor_no_clip
108    {
109    public:
110        typedef PixFmt   pixfmt_type;
111        typedef typename pixfmt_type::color_type color_type;
112        typedef typename pixfmt_type::order_type order_type;
113        typedef typename pixfmt_type::value_type value_type;
114        enum pix_width_e { pix_width = pixfmt_type::pix_width };
115
116        image_accessor_no_clip() {}
117        image_accessor_no_clip(const pixfmt_type& pixf) : m_pixf(&pixf) {}
118
119        void attach(const pixfmt_type& pixf)
120        {
121            m_pixf = &pixf;
122        }
123
124        AGG_INLINE const int8u* span(int x, int y, unsigned)
125        {
126            m_x = x;
127            m_y = y;
128            return m_pix_ptr = m_pixf->pix_ptr(x, y);
129        }
130
131        AGG_INLINE const int8u* next_x()
132        {
133            return m_pix_ptr += pix_width;
134        }
135
136        AGG_INLINE const int8u* next_y()
137        {
138            ++m_y;
139            return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
140        }
141
142    private:
143        const pixfmt_type* m_pixf;
144        int                m_x, m_y;
145        const int8u*       m_pix_ptr;
146    };
147
148
149
150
151    //----------------------------------------------------image_accessor_clone
152    template<class PixFmt> class image_accessor_clone
153    {
154    public:
155        typedef PixFmt   pixfmt_type;
156        typedef typename pixfmt_type::color_type color_type;
157        typedef typename pixfmt_type::order_type order_type;
158        typedef typename pixfmt_type::value_type value_type;
159        enum pix_width_e { pix_width = pixfmt_type::pix_width };
160
161        image_accessor_clone() {}
162        image_accessor_clone(const pixfmt_type& pixf) : m_pixf(&pixf) {}
163
164        void attach(const pixfmt_type& pixf)
165        {
166            m_pixf = &pixf;
167        }
168
169    private:
170        AGG_INLINE const int8u* pixel() const
171        {
172            int x = m_x;
173            int y = m_y;
174            if(x < 0) x = 0;
175            if(y < 0) y = 0;
176            if(x >= (int)m_pixf->width())  x = m_pixf->width() - 1;
177            if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1;
178            return m_pixf->pix_ptr(x, y);
179        }
180
181    public:
182        AGG_INLINE const int8u* span(int x, int y, unsigned len)
183        {
184            m_x = m_x0 = x;
185            m_y = y;
186            if(y >= 0 && y < (int)m_pixf->height() &&
187               x >= 0 && (int)(x+len) <= (int)m_pixf->width())
188            {
189                return m_pix_ptr = m_pixf->pix_ptr(x, y);
190            }
191            m_pix_ptr = 0;
192            return pixel();
193        }
194
195        AGG_INLINE const int8u* next_x()
196        {
197            if(m_pix_ptr) return m_pix_ptr += pix_width;
198            ++m_x;
199            return pixel();
200        }
201
202        AGG_INLINE const int8u* next_y()
203        {
204            ++m_y;
205            m_x = m_x0;
206            if(m_pix_ptr &&
207               m_y >= 0 && m_y < (int)m_pixf->height())
208            {
209                return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
210            }
211            m_pix_ptr = 0;
212            return pixel();
213        }
214
215    private:
216        const pixfmt_type* m_pixf;
217        int                m_x, m_x0, m_y;
218        const int8u*       m_pix_ptr;
219    };
220
221
222
223
224
225    //-----------------------------------------------------image_accessor_wrap
226    template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap
227    {
228    public:
229        typedef PixFmt   pixfmt_type;
230        typedef typename pixfmt_type::color_type color_type;
231        typedef typename pixfmt_type::order_type order_type;
232        typedef typename pixfmt_type::value_type value_type;
233        enum pix_width_e { pix_width = pixfmt_type::pix_width };
234
235        image_accessor_wrap() {}
236        image_accessor_wrap(const pixfmt_type& pixf) :
237            m_pixf(&pixf),
238            m_wrap_x(pixf.width()),
239            m_wrap_y(pixf.height())
240        {}
241
242        void attach(const pixfmt_type& pixf)
243        {
244            m_pixf = &pixf;
245        }
246
247        AGG_INLINE const int8u* span(int x, int y, unsigned)
248        {
249            m_x = x;
250            m_row_ptr = m_pixf->row_ptr(m_wrap_y(y));
251            return m_row_ptr + m_wrap_x(x) * pix_width;
252        }
253
254        AGG_INLINE const int8u* next_x()
255        {
256            int x = ++m_wrap_x;
257            return m_row_ptr + x * pix_width;
258        }
259
260        AGG_INLINE const int8u* next_y()
261        {
262            m_row_ptr = m_pixf->row_ptr(++m_wrap_y);
263            return m_row_ptr + m_wrap_x(m_x) * pix_width;
264        }
265
266    private:
267        const pixfmt_type* m_pixf;
268        const int8u*       m_row_ptr;
269        int                m_x;
270        WrapX              m_wrap_x;
271        WrapY              m_wrap_y;
272    };
273
274
275
276
277    //--------------------------------------------------------wrap_mode_repeat
278    class wrap_mode_repeat
279    {
280    public:
281        wrap_mode_repeat() {}
282        wrap_mode_repeat(unsigned size) :
283            m_size(size),
284            m_add(size * (0x3FFFFFFF / size)),
285            m_value(0)
286        {}
287
288        AGG_INLINE unsigned operator() (int v)
289        {
290            return m_value = (unsigned(v) + m_add) % m_size;
291        }
292
293        AGG_INLINE unsigned operator++ ()
294        {
295            ++m_value;
296            if(m_value >= m_size) m_value = 0;
297            return m_value;
298        }
299    private:
300        unsigned m_size;
301        unsigned m_add;
302        unsigned m_value;
303    };
304
305
306    //---------------------------------------------------wrap_mode_repeat_pow2
307    class wrap_mode_repeat_pow2
308    {
309    public:
310        wrap_mode_repeat_pow2() {}
311        wrap_mode_repeat_pow2(unsigned size) : m_value(0)
312        {
313            m_mask = 1;
314            while(m_mask < size) m_mask = (m_mask << 1) | 1;
315            m_mask >>= 1;
316        }
317        AGG_INLINE unsigned operator() (int v)
318        {
319            return m_value = unsigned(v) & m_mask;
320        }
321        AGG_INLINE unsigned operator++ ()
322        {
323            ++m_value;
324            if(m_value > m_mask) m_value = 0;
325            return m_value;
326        }
327    private:
328        unsigned m_mask;
329        unsigned m_value;
330    };
331
332
333    //----------------------------------------------wrap_mode_repeat_auto_pow2
334    class wrap_mode_repeat_auto_pow2
335    {
336    public:
337        wrap_mode_repeat_auto_pow2() {}
338        wrap_mode_repeat_auto_pow2(unsigned size) :
339            m_size(size),
340            m_add(size * (0x3FFFFFFF / size)),
341            m_mask((m_size & (m_size-1)) ? 0 : m_size-1),
342            m_value(0)
343        {}
344
345        AGG_INLINE unsigned operator() (int v)
346        {
347            if(m_mask) return m_value = unsigned(v) & m_mask;
348            return m_value = (unsigned(v) + m_add) % m_size;
349        }
350        AGG_INLINE unsigned operator++ ()
351        {
352            ++m_value;
353            if(m_value >= m_size) m_value = 0;
354            return m_value;
355        }
356
357    private:
358        unsigned m_size;
359        unsigned m_add;
360        unsigned m_mask;
361        unsigned m_value;
362    };
363
364
365    //-------------------------------------------------------wrap_mode_reflect
366    class wrap_mode_reflect
367    {
368    public:
369        wrap_mode_reflect() {}
370        wrap_mode_reflect(unsigned size) :
371            m_size(size),
372            m_size2(size * 2),
373            m_add(m_size2 * (0x3FFFFFFF / m_size2)),
374            m_value(0)
375        {}
376
377        AGG_INLINE unsigned operator() (int v)
378        {
379            m_value = (unsigned(v) + m_add) % m_size2;
380            if(m_value >= m_size) return m_size2 - m_value - 1;
381            return m_value;
382        }
383
384        AGG_INLINE unsigned operator++ ()
385        {
386            ++m_value;
387            if(m_value >= m_size2) m_value = 0;
388            if(m_value >= m_size) return m_size2 - m_value - 1;
389            return m_value;
390        }
391    private:
392        unsigned m_size;
393        unsigned m_size2;
394        unsigned m_add;
395        unsigned m_value;
396    };
397
398
399
400    //--------------------------------------------------wrap_mode_reflect_pow2
401    class wrap_mode_reflect_pow2
402    {
403    public:
404        wrap_mode_reflect_pow2() {}
405        wrap_mode_reflect_pow2(unsigned size) : m_value(0)
406        {
407            m_mask = 1;
408            m_size = 1;
409            while(m_mask < size)
410            {
411                m_mask = (m_mask << 1) | 1;
412                m_size <<= 1;
413            }
414        }
415        AGG_INLINE unsigned operator() (int v)
416        {
417            m_value = unsigned(v) & m_mask;
418            if(m_value >= m_size) return m_mask - m_value;
419            return m_value;
420        }
421        AGG_INLINE unsigned operator++ ()
422        {
423            ++m_value;
424            m_value &= m_mask;
425            if(m_value >= m_size) return m_mask - m_value;
426            return m_value;
427        }
428    private:
429        unsigned m_size;
430        unsigned m_mask;
431        unsigned m_value;
432    };
433
434
435
436    //---------------------------------------------wrap_mode_reflect_auto_pow2
437    class wrap_mode_reflect_auto_pow2
438    {
439    public:
440        wrap_mode_reflect_auto_pow2() {}
441        wrap_mode_reflect_auto_pow2(unsigned size) :
442            m_size(size),
443            m_size2(size * 2),
444            m_add(m_size2 * (0x3FFFFFFF / m_size2)),
445            m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1),
446            m_value(0)
447        {}
448
449        AGG_INLINE unsigned operator() (int v)
450        {
451            m_value = m_mask ? unsigned(v) & m_mask :
452                              (unsigned(v) + m_add) % m_size2;
453            if(m_value >= m_size) return m_size2 - m_value - 1;
454            return m_value;
455        }
456        AGG_INLINE unsigned operator++ ()
457        {
458            ++m_value;
459            if(m_value >= m_size2) m_value = 0;
460            if(m_value >= m_size) return m_size2 - m_value - 1;
461            return m_value;
462        }
463
464    private:
465        unsigned m_size;
466        unsigned m_size2;
467        unsigned m_add;
468        unsigned m_mask;
469        unsigned m_value;
470    };
471
472
473}
474
475
476#endif
477