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
32namespace 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
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
143        void finalize(int y)
144        {
145            m_y = y;
146        }
147
148        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
158        int            y()         const { return m_y; }
159        unsigned       num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
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        {
191            span() {}
192            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:
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
294        void finalize(int y)
295        {
296            m_y = y;
297        }
298
299        //--------------------------------------------------------------------
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        //--------------------------------------------------------------------
308        int            y()         const { return m_y; }
309        unsigned       num_spans() const { return m_spans.size(); }
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