xref: /haiku/headers/libs/agg/agg_image_accessors.h (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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 
21 namespace 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