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// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
17// Liberty Technology Systems, Inc., visit http://lib-sys.com
18//
19// Liberty Technology Systems, Inc. is the provider of
20// PostScript and PDF technology for software developers.
21//
22//----------------------------------------------------------------------------
23
24#ifndef AGG_SCANLINE_U_INCLUDED
25#define AGG_SCANLINE_U_INCLUDED
26
27#include "agg_array.h"
28
29namespace agg
30{
31    //=============================================================scanline_u8
32    //
33    // Unpacked scanline container class
34    //
35    // This class is used to transfer data from a scanline rasterizer
36    // to the rendering buffer. It's organized very simple. The class stores
37    // information of horizontal spans to render it into a pixel-map buffer.
38    // Each span has staring X, length, and an array of bytes that determine the
39    // cover-values for each pixel.
40    // Before using this class you should know the minimal and maximal pixel
41    // coordinates of your scanline. The protocol of using is:
42    // 1. reset(min_x, max_x)
43    // 2. add_cell() / add_span() - accumulate scanline.
44    //    When forming one scanline the next X coordinate must be always greater
45    //    than the last stored one, i.e. it works only with ordered coordinates.
46    // 3. Call finalize(y) and render the scanline.
47    // 3. Call reset_spans() to prepare for the new scanline.
48    //
49    // 4. Rendering:
50    //
51    // Scanline provides an iterator class that allows you to extract
52    // the spans and the cover values for each pixel. Be aware that clipping
53    // has not been done yet, so you should perform it yourself.
54    // Use scanline_u8::iterator to render spans:
55    //-------------------------------------------------------------------------
56    //
57    // int y = sl.y();                    // Y-coordinate of the scanline
58    //
59    // ************************************
60    // ...Perform vertical clipping here...
61    // ************************************
62    //
63    // scanline_u8::const_iterator span = sl.begin();
64    //
65    // unsigned char* row = m_rbuf->row(y); // The the address of the beginning
66    //                                      // of the current row
67    //
68    // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
69    //                                      // num_spans is always greater than 0.
70    //
71    // do
72    // {
73    //     const scanline_u8::cover_type* covers =
74    //         span->covers;                     // The array of the cover values
75    //
76    //     int num_pix = span->len;              // Number of pixels of the span.
77    //                                           // Always greater than 0, still it's
78    //                                           // better to use "int" instead of
79    //                                           // "unsigned" because it's more
80    //                                           // convenient for clipping
81    //     int x = span->x;
82    //
83    //     **************************************
84    //     ...Perform horizontal clipping here...
85    //     ...you have x, covers, and pix_count..
86    //     **************************************
87    //
88    //     unsigned char* dst = row + x;  // Calculate the start address of the row.
89    //                                    // In this case we assume a simple
90    //                                    // grayscale image 1-byte per pixel.
91    //     do
92    //     {
93    //         *dst++ = *covers++;        // Hypotetical rendering.
94    //     }
95    //     while(--num_pix);
96    //
97    //     ++span;
98    // }
99    // while(--num_spans);  // num_spans cannot be 0, so this loop is quite safe
100    //------------------------------------------------------------------------
101    //
102    // The question is: why should we accumulate the whole scanline when we
103    // could render just separate spans when they're ready?
104    // That's because using the scanline is generally faster. When is consists
105    // of more than one span the conditions for the processor cash system
106    // are better, because switching between two different areas of memory
107    // (that can be very large) occurs less frequently.
108    //------------------------------------------------------------------------
109    class scanline_u8
110    {
111    public:
112        typedef scanline_u8 self_type;
113        typedef int8u       cover_type;
114        typedef int16       coord_type;
115
116        //--------------------------------------------------------------------
117        struct span
118        {
119            coord_type  x;
120            coord_type  len;
121            cover_type* covers;
122        };
123
124        typedef span* iterator;
125        typedef const span* const_iterator;
126
127        //--------------------------------------------------------------------
128        scanline_u8() :
129            m_min_x(0),
130            m_last_x(0x7FFFFFF0),
131            m_cur_span(0)
132        {}
133
134        //--------------------------------------------------------------------
135        void reset(int min_x, int max_x)
136        {
137            unsigned max_len = max_x - min_x + 2;
138            if(max_len > m_spans.size())
139            {
140                m_spans.resize(max_len);
141                m_covers.resize(max_len);
142            }
143            m_last_x   = 0x7FFFFFF0;
144            m_min_x    = min_x;
145            m_cur_span = &m_spans[0];
146        }
147
148        //--------------------------------------------------------------------
149        void add_cell(int x, unsigned cover)
150        {
151            x -= m_min_x;
152            m_covers[x] = (cover_type)cover;
153            if(x == m_last_x+1)
154            {
155                m_cur_span->len++;
156            }
157            else
158            {
159                m_cur_span++;
160                m_cur_span->x      = (coord_type)(x + m_min_x);
161                m_cur_span->len    = 1;
162                m_cur_span->covers = &m_covers[x];
163            }
164            m_last_x = x;
165        }
166
167        //--------------------------------------------------------------------
168        void add_cells(int x, unsigned len, const cover_type* covers)
169        {
170            x -= m_min_x;
171            memcpy(&m_covers[x], covers, len * sizeof(cover_type));
172            if(x == m_last_x+1)
173            {
174                m_cur_span->len += (coord_type)len;
175            }
176            else
177            {
178                m_cur_span++;
179                m_cur_span->x      = (coord_type)(x + m_min_x);
180                m_cur_span->len    = (coord_type)len;
181                m_cur_span->covers = &m_covers[x];
182            }
183            m_last_x = x + len - 1;
184        }
185
186        //--------------------------------------------------------------------
187        void add_span(int x, unsigned len, unsigned cover)
188        {
189            x -= m_min_x;
190            memset(&m_covers[x], cover, len);
191            if(x == m_last_x+1)
192            {
193                m_cur_span->len += (coord_type)len;
194            }
195            else
196            {
197                m_cur_span++;
198                m_cur_span->x      = (coord_type)(x + m_min_x);
199                m_cur_span->len    = (coord_type)len;
200                m_cur_span->covers = &m_covers[x];
201            }
202            m_last_x = x + len - 1;
203        }
204
205        //--------------------------------------------------------------------
206        void finalize(int y)
207        {
208            m_y = y;
209        }
210
211        //--------------------------------------------------------------------
212        void reset_spans()
213        {
214            m_last_x    = 0x7FFFFFF0;
215            m_cur_span  = &m_spans[0];
216        }
217
218        //--------------------------------------------------------------------
219        int      y()           const { return m_y; }
220        unsigned num_spans()   const { return unsigned(m_cur_span - &m_spans[0]); }
221        const_iterator begin() const { return &m_spans[1]; }
222        iterator       begin()       { return &m_spans[1]; }
223
224    private:
225        scanline_u8(const self_type&);
226        const self_type& operator = (const self_type&);
227
228    private:
229        int                   m_min_x;
230        int                   m_last_x;
231        int                   m_y;
232        pod_array<cover_type> m_covers;
233        pod_array<span>       m_spans;
234        span*                 m_cur_span;
235    };
236
237
238
239
240    //==========================================================scanline_u8_am
241    //
242    // The scanline container with alpha-masking
243    //
244    //------------------------------------------------------------------------
245    template<class AlphaMask>
246    class scanline_u8_am : public scanline_u8
247    {
248    public:
249        typedef scanline_u8           base_type;
250        typedef AlphaMask             alpha_mask_type;
251        typedef base_type::cover_type cover_type;
252        typedef base_type::coord_type coord_type;
253
254        scanline_u8_am() : base_type(), m_alpha_mask(0) {}
255        scanline_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
256
257        //--------------------------------------------------------------------
258        void finalize(int span_y)
259        {
260            base_type::finalize(span_y);
261            if(m_alpha_mask)
262            {
263                typename base_type::iterator span = base_type::begin();
264                unsigned count = base_type::num_spans();
265                do
266                {
267                    m_alpha_mask->combine_hspan(span->x,
268                                                base_type::y(),
269                                                span->covers,
270                                                span->len);
271                    ++span;
272                }
273                while(--count);
274            }
275        }
276
277    private:
278        AlphaMask* m_alpha_mask;
279    };
280
281
282
283
284    //===========================================================scanline32_u8
285    class scanline32_u8
286    {
287    public:
288        typedef scanline32_u8 self_type;
289        typedef int8u         cover_type;
290        typedef int32         coord_type;
291
292        //--------------------------------------------------------------------
293        struct span
294        {
295            span() {}
296            span(coord_type x_, coord_type len_, cover_type* covers_) :
297                x(x_), len(len_), covers(covers_) {}
298
299            coord_type  x;
300            coord_type  len;
301            cover_type* covers;
302        };
303
304        typedef pod_bvector<span, 4> span_array_type;
305
306        //--------------------------------------------------------------------
307        class const_iterator
308        {
309        public:
310            const_iterator(const span_array_type& spans) :
311                m_spans(spans),
312                m_span_idx(0)
313            {}
314
315            const span& operator*()  const { return m_spans[m_span_idx];  }
316            const span* operator->() const { return &m_spans[m_span_idx]; }
317
318            void operator ++ () { ++m_span_idx; }
319
320        private:
321            const span_array_type& m_spans;
322            unsigned               m_span_idx;
323        };
324
325        //--------------------------------------------------------------------
326        class iterator
327        {
328        public:
329            iterator(span_array_type& spans) :
330                m_spans(spans),
331                m_span_idx(0)
332            {}
333
334            span& operator*()  { return m_spans[m_span_idx];  }
335            span* operator->() { return &m_spans[m_span_idx]; }
336
337            void operator ++ () { ++m_span_idx; }
338
339        private:
340            span_array_type& m_spans;
341            unsigned         m_span_idx;
342        };
343
344
345
346        //--------------------------------------------------------------------
347        scanline32_u8() :
348            m_min_x(0),
349            m_last_x(0x7FFFFFF0),
350            m_covers()
351        {}
352
353        //--------------------------------------------------------------------
354        void reset(int min_x, int max_x)
355        {
356            unsigned max_len = max_x - min_x + 2;
357            if(max_len > m_covers.size())
358            {
359                m_covers.resize(max_len);
360            }
361            m_last_x = 0x7FFFFFF0;
362            m_min_x  = min_x;
363            m_spans.remove_all();
364        }
365
366        //--------------------------------------------------------------------
367        void add_cell(int x, unsigned cover)
368        {
369            x -= m_min_x;
370            m_covers[x] = cover_type(cover);
371            if(x == m_last_x+1)
372            {
373                m_spans.last().len++;
374            }
375            else
376            {
377                m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
378            }
379            m_last_x = x;
380        }
381
382        //--------------------------------------------------------------------
383        void add_cells(int x, unsigned len, const cover_type* covers)
384        {
385            x -= m_min_x;
386            memcpy(&m_covers[x], covers, len * sizeof(cover_type));
387            if(x == m_last_x+1)
388            {
389                m_spans.last().len += coord_type(len);
390            }
391            else
392            {
393                m_spans.add(span(coord_type(x + m_min_x),
394                                 coord_type(len),
395                                 &m_covers[x]));
396            }
397            m_last_x = x + len - 1;
398        }
399
400        //--------------------------------------------------------------------
401        void add_span(int x, unsigned len, unsigned cover)
402        {
403            x -= m_min_x;
404            memset(&m_covers[x], cover, len);
405            if(x == m_last_x+1)
406            {
407                m_spans.last().len += coord_type(len);
408            }
409            else
410            {
411                m_spans.add(span(coord_type(x + m_min_x),
412                                 coord_type(len),
413                                 &m_covers[x]));
414            }
415            m_last_x = x + len - 1;
416        }
417
418        //--------------------------------------------------------------------
419        void finalize(int y)
420        {
421            m_y = y;
422        }
423
424        //--------------------------------------------------------------------
425        void reset_spans()
426        {
427            m_last_x = 0x7FFFFFF0;
428            m_spans.remove_all();
429        }
430
431        //--------------------------------------------------------------------
432        int      y()           const { return m_y; }
433        unsigned num_spans()   const { return m_spans.size(); }
434        const_iterator begin() const { return const_iterator(m_spans); }
435        iterator       begin()       { return iterator(m_spans); }
436
437    private:
438        scanline32_u8(const self_type&);
439        const self_type& operator = (const self_type&);
440
441    private:
442        int                   m_min_x;
443        int                   m_last_x;
444        int                   m_y;
445        pod_array<cover_type> m_covers;
446        span_array_type       m_spans;
447    };
448
449
450
451
452    //========================================================scanline32_u8_am
453    //
454    // The scanline container with alpha-masking
455    //
456    //------------------------------------------------------------------------
457    template<class AlphaMask>
458    class scanline32_u8_am : public scanline32_u8
459    {
460    public:
461        typedef scanline32_u8         base_type;
462        typedef AlphaMask             alpha_mask_type;
463        typedef base_type::cover_type cover_type;
464        typedef base_type::coord_type coord_type;
465
466
467        scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
468        scanline32_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
469
470        //--------------------------------------------------------------------
471        void finalize(int span_y)
472        {
473            base_type::finalize(span_y);
474            if(m_alpha_mask)
475            {
476                typename base_type::iterator span = base_type::begin();
477                unsigned count = base_type::num_spans();
478                do
479                {
480                    m_alpha_mask->combine_hspan(span->x,
481                                                base_type::y(),
482                                                span->covers,
483                                                span->len);
484                    ++span;
485                }
486                while(--count);
487            }
488        }
489
490    private:
491        AlphaMask* m_alpha_mask;
492    };
493
494
495
496}
497
498#endif
499
500