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 
29 namespace mapserver
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         //--------------------------------------------------------------------
scanline_u8()128         scanline_u8() :
129             m_min_x(0),
130             m_last_x(0x7FFFFFF0),
131             m_cur_span(0)
132         {}
133 
134         //--------------------------------------------------------------------
reset(int min_x,int max_x)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         //--------------------------------------------------------------------
add_cell(int x,unsigned cover)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         //--------------------------------------------------------------------
add_cells(int x,unsigned len,const cover_type * covers)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         //--------------------------------------------------------------------
add_span(int x,unsigned len,unsigned cover)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         //--------------------------------------------------------------------
finalize(int y)206         void finalize(int y)
207         {
208             m_y = y;
209         }
210 
211         //--------------------------------------------------------------------
reset_spans()212         void reset_spans()
213         {
214             m_last_x    = 0x7FFFFFF0;
215             m_cur_span  = &m_spans[0];
216         }
217 
218         //--------------------------------------------------------------------
y()219         int      y()           const { return m_y; }
num_spans()220         unsigned num_spans()   const { return unsigned(m_cur_span - &m_spans[0]); }
begin()221         const_iterator begin() const { return &m_spans[1]; }
begin()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 
scanline_u8_am()254         scanline_u8_am() : base_type(), m_alpha_mask(0) {}
scanline_u8_am(const AlphaMask & am)255         scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
256 
257         //--------------------------------------------------------------------
finalize(int span_y)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         const 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         {
spanspan295             span() {}
spanspan296             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:
const_iterator(const span_array_type & spans)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:
iterator(span_array_type & spans)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         //--------------------------------------------------------------------
scanline32_u8()347         scanline32_u8() :
348             m_min_x(0),
349             m_last_x(0x7FFFFFF0),
350             m_covers()
351         {}
352 
353         //--------------------------------------------------------------------
reset(int min_x,int max_x)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         //--------------------------------------------------------------------
add_cell(int x,unsigned cover)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         //--------------------------------------------------------------------
add_cells(int x,unsigned len,const cover_type * covers)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         //--------------------------------------------------------------------
add_span(int x,unsigned len,unsigned cover)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         //--------------------------------------------------------------------
finalize(int y)419         void finalize(int y)
420         {
421             m_y = y;
422         }
423 
424         //--------------------------------------------------------------------
reset_spans()425         void reset_spans()
426         {
427             m_last_x = 0x7FFFFFF0;
428             m_spans.remove_all();
429         }
430 
431         //--------------------------------------------------------------------
y()432         int      y()           const { return m_y; }
num_spans()433         unsigned num_spans()   const { return m_spans.size(); }
begin()434         const_iterator begin() const { return const_iterator(m_spans); }
begin()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 
scanline32_u8_am()467         scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
scanline32_u8_am(const AlphaMask & am)468         scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
469 
470         //--------------------------------------------------------------------
finalize(int span_y)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         const AlphaMask* m_alpha_mask;
492     };
493 
494 
495 
496 }
497 
498 #endif
499 
500