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 // Class scanline_p - a general purpose scanline container with packed spans.
17 //
18 //----------------------------------------------------------------------------
19 //
20 // Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
21 // Liberty Technology Systems, Inc., visit http://lib-sys.com
22 //
23 // Liberty Technology Systems, Inc. is the provider of
24 // PostScript and PDF technology for software developers.
25 //
26 //----------------------------------------------------------------------------
27 #ifndef AGG_SCANLINE_P_INCLUDED
28 #define AGG_SCANLINE_P_INCLUDED
29 
30 #include "agg_array.h"
31 
32 namespace agg
33 {
34 
35     //=============================================================scanline_p8
36     //
37     // This is a general purpose scaline container which supports the interface
38     // used in the rasterizer::render(). See description of scanline_u8
39     // for details.
40     //
41     //------------------------------------------------------------------------
42     class scanline_p8
43     {
44     public:
45         typedef scanline_p8 self_type;
46         typedef int8u       cover_type;
47         typedef int16       coord_type;
48 
49         //--------------------------------------------------------------------
50         struct span
51         {
52             coord_type        x;
53             coord_type        len; // If negative, it's a solid span, covers is valid
54             const cover_type* covers;
55         };
56 
57         typedef span* iterator;
58         typedef const span* const_iterator;
59 
scanline_p8()60         scanline_p8() :
61             m_last_x(0x7FFFFFF0),
62             m_covers(),
63             m_cover_ptr(0),
64             m_spans(),
65             m_cur_span(0)
66         {
67         }
68 
69         //--------------------------------------------------------------------
reset(int min_x,int max_x)70         void reset(int min_x, int max_x)
71         {
72             unsigned max_len = max_x - min_x + 3;
73             if(max_len > m_spans.size())
74             {
75                 m_spans.resize(max_len);
76                 m_covers.resize(max_len);
77             }
78             m_last_x    = 0x7FFFFFF0;
79             m_cover_ptr = &m_covers[0];
80             m_cur_span  = &m_spans[0];
81             m_cur_span->len = 0;
82         }
83 
84         //--------------------------------------------------------------------
add_cell(int x,unsigned cover)85         void add_cell(int x, unsigned cover)
86         {
87             *m_cover_ptr = (cover_type)cover;
88             if(x == m_last_x+1 && m_cur_span->len > 0)
89             {
90                 m_cur_span->len++;
91             }
92             else
93             {
94                 m_cur_span++;
95                 m_cur_span->covers = m_cover_ptr;
96                 m_cur_span->x = (int16)x;
97                 m_cur_span->len = 1;
98             }
99             m_last_x = x;
100             m_cover_ptr++;
101         }
102 
103         //--------------------------------------------------------------------
add_cells(int x,unsigned len,const cover_type * covers)104         void add_cells(int x, unsigned len, const cover_type* covers)
105         {
106             memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
107             if(x == m_last_x+1 && m_cur_span->len > 0)
108             {
109                 m_cur_span->len += (int16)len;
110             }
111             else
112             {
113                 m_cur_span++;
114                 m_cur_span->covers = m_cover_ptr;
115                 m_cur_span->x = (int16)x;
116                 m_cur_span->len = (int16)len;
117             }
118             m_cover_ptr += len;
119             m_last_x = x + len - 1;
120         }
121 
122         //--------------------------------------------------------------------
add_span(int x,unsigned len,unsigned cover)123         void add_span(int x, unsigned len, unsigned cover)
124         {
125             if(x == m_last_x+1 &&
126                m_cur_span->len < 0 &&
127                cover == *m_cur_span->covers)
128             {
129                 m_cur_span->len -= (int16)len;
130             }
131             else
132             {
133                 *m_cover_ptr = (cover_type)cover;
134                 m_cur_span++;
135                 m_cur_span->covers = m_cover_ptr++;
136                 m_cur_span->x      = (int16)x;
137                 m_cur_span->len    = (int16)(-int(len));
138             }
139             m_last_x = x + len - 1;
140         }
141 
142         //--------------------------------------------------------------------
finalize(int y)143         void finalize(int y)
144         {
145             m_y = y;
146         }
147 
148         //--------------------------------------------------------------------
reset_spans()149         void reset_spans()
150         {
151             m_last_x    = 0x7FFFFFF0;
152             m_cover_ptr = &m_covers[0];
153             m_cur_span  = &m_spans[0];
154             m_cur_span->len = 0;
155         }
156 
157         //--------------------------------------------------------------------
y()158         int            y()         const { return m_y; }
num_spans()159         unsigned       num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
begin()160         const_iterator begin()     const { return &m_spans[1]; }
161 
162     private:
163         scanline_p8(const self_type&);
164         const self_type& operator = (const self_type&);
165 
166         int                   m_last_x;
167         int                   m_y;
168         pod_array<cover_type> m_covers;
169         cover_type*           m_cover_ptr;
170         pod_array<span>       m_spans;
171         span*                 m_cur_span;
172     };
173 
174 
175 
176 
177 
178 
179 
180 
181     //==========================================================scanline32_p8
182     class scanline32_p8
183     {
184     public:
185         typedef scanline32_p8 self_type;
186         typedef int8u         cover_type;
187         typedef int32         coord_type;
188 
189         struct span
190         {
spanspan191             span() {}
spanspan192             span(coord_type x_, coord_type len_, const cover_type* covers_) :
193                 x(x_), len(len_), covers(covers_) {}
194 
195             coord_type x;
196             coord_type len; // If negative, it's a solid span, covers is valid
197             const cover_type* covers;
198         };
199         typedef pod_bvector<span, 4> span_array_type;
200 
201 
202         //--------------------------------------------------------------------
203         class const_iterator
204         {
205         public:
const_iterator(const span_array_type & spans)206             const_iterator(const span_array_type& spans) :
207                 m_spans(spans),
208                 m_span_idx(0)
209             {}
210 
211             const span& operator*()  const { return m_spans[m_span_idx];  }
212             const span* operator->() const { return &m_spans[m_span_idx]; }
213 
214             void operator ++ () { ++m_span_idx; }
215 
216         private:
217             const span_array_type& m_spans;
218             unsigned               m_span_idx;
219         };
220 
221         //--------------------------------------------------------------------
scanline32_p8()222         scanline32_p8() :
223             m_max_len(0),
224             m_last_x(0x7FFFFFF0),
225             m_covers(),
226             m_cover_ptr(0)
227         {
228         }
229 
230         //--------------------------------------------------------------------
reset(int min_x,int max_x)231         void reset(int min_x, int max_x)
232         {
233             unsigned max_len = max_x - min_x + 3;
234             if(max_len > m_covers.size())
235             {
236                 m_covers.resize(max_len);
237             }
238             m_last_x    = 0x7FFFFFF0;
239             m_cover_ptr = &m_covers[0];
240             m_spans.remove_all();
241         }
242 
243         //--------------------------------------------------------------------
add_cell(int x,unsigned cover)244         void add_cell(int x, unsigned cover)
245         {
246             *m_cover_ptr = cover_type(cover);
247             if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
248             {
249                 m_spans.last().len++;
250             }
251             else
252             {
253                 m_spans.add(span(coord_type(x), 1, m_cover_ptr));
254             }
255             m_last_x = x;
256             m_cover_ptr++;
257         }
258 
259         //--------------------------------------------------------------------
add_cells(int x,unsigned len,const cover_type * covers)260         void add_cells(int x, unsigned len, const cover_type* covers)
261         {
262             memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
263             if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
264             {
265                 m_spans.last().len += coord_type(len);
266             }
267             else
268             {
269                 m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr));
270             }
271             m_cover_ptr += len;
272             m_last_x = x + len - 1;
273         }
274 
275         //--------------------------------------------------------------------
add_span(int x,unsigned len,unsigned cover)276         void add_span(int x, unsigned len, unsigned cover)
277         {
278             if(x == m_last_x+1 &&
279                m_spans.size() &&
280                m_spans.last().len < 0 &&
281                cover == *m_spans.last().covers)
282             {
283                 m_spans.last().len -= coord_type(len);
284             }
285             else
286             {
287                 *m_cover_ptr = cover_type(cover);
288                 m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
289             }
290             m_last_x = x + len - 1;
291         }
292 
293         //--------------------------------------------------------------------
finalize(int y)294         void finalize(int y)
295         {
296             m_y = y;
297         }
298 
299         //--------------------------------------------------------------------
reset_spans()300         void reset_spans()
301         {
302             m_last_x    = 0x7FFFFFF0;
303             m_cover_ptr = &m_covers[0];
304             m_spans.remove_all();
305         }
306 
307         //--------------------------------------------------------------------
y()308         int            y()         const { return m_y; }
num_spans()309         unsigned       num_spans() const { return m_spans.size(); }
begin()310         const_iterator begin()     const { return const_iterator(m_spans); }
311 
312     private:
313         scanline32_p8(const self_type&);
314         const self_type& operator = (const self_type&);
315 
316         unsigned              m_max_len;
317         int                   m_last_x;
318         int                   m_y;
319         pod_array<cover_type> m_covers;
320         cover_type*           m_cover_ptr;
321         span_array_type       m_spans;
322     };
323 
324 
325 }
326 
327 
328 #endif
329 
330