xref: /haiku/headers/libs/agg/agg_scanline_u.h (revision 95bac3fda53a4cb21880712d7b43f8c21db32a2e)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.2
3 // Copyright (C) 2002-2004 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_SCANLINE_U_INCLUDED
17 #define AGG_SCANLINE_U_INCLUDED
18 
19 #include <string.h>
20 #include "agg_basics.h"
21 
22 namespace agg
23 {
24     //==============================================================scanline_u
25     //
26     // Unpacked scanline container class
27     //
28     // This class is used to transfer data from a scanline rastyerizer
29     // to the rendering buffer. It's organized very simple. The class stores
30     // information of horizontal spans to render it into a pixel-map buffer.
31     // Each span has staring X, length, and an array of bytes that determine the
32     // cover-values for each pixel.
33     // Before using this class you should know the minimal and maximal pixel
34     // coordinates of your scanline. The protocol of using is:
35     // 1. reset(min_x, max_x)
36     // 2. add_cell() / add_span() - accumulate scanline.
37     //    When forming one scanline the next X coordinate must be always greater
38     //    than the last stored one, i.e. it works only with ordered coordinates.
39     // 3. Call finalize(y) and render the scanline.
40     // 3. Call reset_spans() to prepare for the new scanline.
41     //
42     // 4. Rendering:
43     //
44     // Scanline provides an iterator class that allows you to extract
45     // the spans and the cover values for each pixel. Be aware that clipping
46     // has not been done yet, so you should perform it yourself.
47     // Use scanline_u8::iterator to render spans:
48     //-------------------------------------------------------------------------
49     //
50     // int y = sl.y();                    // Y-coordinate of the scanline
51     //
52     // ************************************
53     // ...Perform vertical clipping here...
54     // ************************************
55     //
56     // scanline_u8::const_iterator span = sl.begin();
57     //
58     // unsigned char* row = m_rbuf->row(y); // The the address of the beginning
59     //                                      // of the current row
60     //
61     // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
62     //                                      // num_spans is always greater than 0.
63     //
64     // do
65     // {
66     //     const scanline_u8::cover_type* covers =
67     //         span->covers;                     // The array of the cover values
68     //
69     //     int num_pix = span->len;              // Number of pixels of the span.
70     //                                           // Always greater than 0, still it's
71     //                                           // better to use "int" instead of
72     //                                           // "unsigned" because it's more
73     //                                           // convenient for clipping
74     //     int x = span->x;
75     //
76     //     **************************************
77     //     ...Perform horizontal clipping here...
78     //     ...you have x, covers, and pix_count..
79     //     **************************************
80     //
81     //     unsigned char* dst = row + x;  // Calculate the start address of the row.
82     //                                    // In this case we assume a simple
83     //                                    // grayscale image 1-byte per pixel.
84     //     do
85     //     {
86     //         *dst++ = *covers++;        // Hypotetical rendering.
87     //     }
88     //     while(--num_pix);
89     //
90     //     ++span;
91     // }
92     // while(--num_spans);  // num_spans cannot be 0, so this loop is quite safe
93     //------------------------------------------------------------------------
94     //
95     // The question is: why should we accumulate the whole scanline when we
96     // could render just separate spans when they're ready?
97     // That's because using the scaline is generally faster. When is consists
98     // of more than one span the conditions for the processor cash system
99     // are better, because switching between two different areas of memory
100     // (that can be very large) occures less frequently.
101     //------------------------------------------------------------------------
102     template<class T> class scanline_u
103     {
104     public:
105         typedef T cover_type;
106 
107         //--------------------------------------------------------------------
108         struct span
109         {
110             int16 x;
111             int16 len;
112             cover_type* covers;
113         };
114 
115         typedef span* iterator;
116         typedef const span* const_iterator;
117 
118         //--------------------------------------------------------------------
119         ~scanline_u();
120         scanline_u();
121 
122         void     reset(int min_x, int max_x);
123         void     add_cell(int x, unsigned cover);
124         void     add_cells(int x, unsigned len, const T* covers);
125         void     add_span(int x, unsigned len, unsigned cover);
126         void     finalize(int y) { m_y = y; }
127         void     reset_spans();
128 
129         int      y()           const { return m_y; }
130         unsigned num_spans()   const { return unsigned(m_cur_span - m_spans); }
131         const_iterator begin() const { return m_spans + 1; }
132         iterator       begin()       { return m_spans + 1; }
133 
134     private:
135         scanline_u<T>(const scanline_u<T>&);
136         const scanline_u<T>& operator = (const scanline_u<T>&);
137 
138     private:
139         int           m_min_x;
140         unsigned      m_max_len;
141         int           m_last_x;
142         int           m_y;
143         cover_type*   m_covers;
144         span*         m_spans;
145         span*         m_cur_span;
146     };
147 
148 
149 
150     //------------------------------------------------------------------------
151     template<class T> scanline_u<T>::~scanline_u()
152     {
153         delete [] m_spans;
154         delete [] m_covers;
155     }
156 
157 
158     //------------------------------------------------------------------------
159     template<class T> scanline_u<T>::scanline_u() :
160         m_min_x(0),
161         m_max_len(0),
162         m_last_x(0x7FFFFFF0),
163         m_covers(0),
164         m_spans(0),
165         m_cur_span(0)
166     {
167     }
168 
169 
170     //------------------------------------------------------------------------
171     template<class T> void scanline_u<T>::reset(int min_x, int max_x)
172     {
173         unsigned max_len = max_x - min_x + 2;
174         if(max_len > m_max_len)
175         {
176             delete [] m_spans;
177             delete [] m_covers;
178             m_covers  = new cover_type [max_len];
179             m_spans   = new span       [max_len];
180             m_max_len = max_len;
181         }
182         m_last_x        = 0x7FFFFFF0;
183         m_min_x         = min_x;
184         m_cur_span      = m_spans;
185     }
186 
187 
188     //------------------------------------------------------------------------
189     template<class T> inline void scanline_u<T>::reset_spans()
190     {
191         m_last_x    = 0x7FFFFFF0;
192         m_cur_span  = m_spans;
193     }
194 
195 
196     //------------------------------------------------------------------------
197     template<class T> inline void scanline_u<T>::add_cell(int x, unsigned cover)
198     {
199         x -= m_min_x;
200         m_covers[x] = (unsigned char)cover;
201         if(x == m_last_x+1)
202         {
203             m_cur_span->len++;
204         }
205         else
206         {
207             m_cur_span++;
208             m_cur_span->x      = (int16)(x + m_min_x);
209             m_cur_span->len    = 1;
210             m_cur_span->covers = m_covers + x;
211         }
212         m_last_x = x;
213     }
214 
215 
216     //------------------------------------------------------------------------
217     template<class T> void scanline_u<T>::add_cells(int x, unsigned len, const T* covers)
218     {
219         x -= m_min_x;
220         memcpy(m_covers + x, covers, len * sizeof(T));
221         if(x == m_last_x+1)
222         {
223             m_cur_span->len += (int16)len;
224         }
225         else
226         {
227             m_cur_span++;
228             m_cur_span->x      = (int16)(x + m_min_x);
229             m_cur_span->len    = (int16)len;
230             m_cur_span->covers = m_covers + x;
231         }
232         m_last_x = x + len - 1;
233     }
234 
235 
236     //------------------------------------------------------------------------
237     template<class T> void scanline_u<T>::add_span(int x, unsigned len, unsigned cover)
238     {
239         x -= m_min_x;
240         memset(m_covers + x, cover, len);
241         if(x == m_last_x+1)
242         {
243             m_cur_span->len += (int16)len;
244         }
245         else
246         {
247             m_cur_span++;
248             m_cur_span->x      = (int16)(x + m_min_x);
249             m_cur_span->len    = (int16)len;
250             m_cur_span->covers = m_covers + x;
251         }
252         m_last_x = x + len - 1;
253     }
254 
255 
256     //=============================================================scanline_u8
257     typedef scanline_u<int8u> scanline_u8;
258 
259     //============================================================scanline_u16
260     typedef scanline_u<int16u> scanline_u16;
261 
262     //============================================================scanline_u32
263     typedef scanline_u<int32u> scanline_u32;
264 
265 
266     //=============================================================scanline_am
267     //
268     // The scanline container with alpha-masking
269     //
270     //------------------------------------------------------------------------
271     template<class AlphaMask, class CoverT>
272     class scanline_am : public scanline_u<CoverT>
273     {
274     public:
275         typedef AlphaMask alpha_mask_type;
276         typedef CoverT cover_type;
277         typedef scanline_u<CoverT> scanline_type;
278 
279         scanline_am() : scanline_type(), m_alpha_mask(0) {}
280         scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {}
281 
282         //--------------------------------------------------------------------
283         void finalize(int span_y)
284         {
285             scanline_u<CoverT>::finalize(span_y);
286             if(m_alpha_mask)
287             {
288                 typename scanline_type::iterator span = scanline_type::begin();
289                 unsigned count = scanline_type::num_spans();
290                 do
291                 {
292                     m_alpha_mask->combine_hspan(span->x,
293                                                 scanline_type::y(),
294                                                 span->covers,
295                                                 span->len);
296                     ++span;
297                 }
298                 while(--count);
299             }
300         }
301 
302     private:
303         const AlphaMask* m_alpha_mask;
304     };
305 
306 
307     //==========================================================scanline_u8_am
308     template<class AlphaMask>
309     class scanline_u8_am : public scanline_am<AlphaMask, int8u>
310     {
311     public:
312         typedef AlphaMask alpha_mask_type;
313         typedef int8u cover_type;
314         typedef scanline_am<alpha_mask_type, cover_type> self_type;
315 
316         scanline_u8_am() : self_type() {}
317         scanline_u8_am(const AlphaMask& am) : self_type(am) {}
318     };
319 
320 }
321 
322 #endif
323 
324