1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 #ifndef AGG_SCANLINE_U_INCLUDED
17 #define AGG_SCANLINE_U_INCLUDED
20 #include "agg_basics.h"
24 //==============================================================scanline_u
26 // Unpacked scanline container class
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.
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 //-------------------------------------------------------------------------
50 // int y = sl.y(); // Y-coordinate of the scanline
52 // ************************************
53 // ...Perform vertical clipping here...
54 // ************************************
56 // scanline_u8::const_iterator span = sl.begin();
58 // unsigned char* row = m_rbuf->row(y); // The the address of the beginning
59 // // of the current row
61 // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
62 // // num_spans is always greater than 0.
66 // const scanline_u8::cover_type* covers =
67 // span->covers; // The array of the cover values
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
76 // **************************************
77 // ...Perform horizontal clipping here...
78 // ...you have x, covers, and pix_count..
79 // **************************************
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.
86 // *dst++ = *covers++; // Hypotetical rendering.
92 // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
93 //------------------------------------------------------------------------
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
105 typedef T cover_type
;
107 //--------------------------------------------------------------------
115 typedef span
* iterator
;
116 typedef const span
* const_iterator
;
118 //--------------------------------------------------------------------
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
; }
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; }
135 scanline_u
<T
>(const scanline_u
<T
>&);
136 const scanline_u
<T
>& operator = (const scanline_u
<T
>&);
143 cover_type
* m_covers
;
150 //------------------------------------------------------------------------
151 template<class T
> scanline_u
<T
>::~scanline_u()
158 //------------------------------------------------------------------------
159 template<class T
> scanline_u
<T
>::scanline_u() :
162 m_last_x(0x7FFFFFF0),
170 //------------------------------------------------------------------------
171 template<class T
> void scanline_u
<T
>::reset(int min_x
, int max_x
)
173 unsigned max_len
= max_x
- min_x
+ 2;
174 if(max_len
> m_max_len
)
178 m_covers
= new cover_type
[max_len
];
179 m_spans
= new span
[max_len
];
182 m_last_x
= 0x7FFFFFF0;
184 m_cur_span
= m_spans
;
188 //------------------------------------------------------------------------
189 template<class T
> inline void scanline_u
<T
>::reset_spans()
191 m_last_x
= 0x7FFFFFF0;
192 m_cur_span
= m_spans
;
196 //------------------------------------------------------------------------
197 template<class T
> inline void scanline_u
<T
>::add_cell(int x
, unsigned cover
)
200 m_covers
[x
] = (unsigned char)cover
;
208 m_cur_span
->x
= (int16
)(x
+ m_min_x
);
210 m_cur_span
->covers
= m_covers
+ x
;
216 //------------------------------------------------------------------------
217 template<class T
> void scanline_u
<T
>::add_cells(int x
, unsigned len
, const T
* covers
)
220 memcpy(m_covers
+ x
, covers
, len
* sizeof(T
));
223 m_cur_span
->len
+= (int16
)len
;
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
;
232 m_last_x
= x
+ len
- 1;
236 //------------------------------------------------------------------------
237 template<class T
> void scanline_u
<T
>::add_span(int x
, unsigned len
, unsigned cover
)
240 memset(m_covers
+ x
, cover
, len
);
243 m_cur_span
->len
+= (int16
)len
;
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
;
252 m_last_x
= x
+ len
- 1;
256 //=============================================================scanline_u8
257 typedef scanline_u
<int8u
> scanline_u8
;
259 //============================================================scanline_u16
260 typedef scanline_u
<int16u
> scanline_u16
;
262 //============================================================scanline_u32
263 typedef scanline_u
<int32u
> scanline_u32
;
266 //=============================================================scanline_am
268 // The scanline container with alpha-masking
270 //------------------------------------------------------------------------
271 template<class AlphaMask
, class CoverT
>
272 class scanline_am
: public scanline_u
<CoverT
>
275 typedef AlphaMask alpha_mask_type
;
276 typedef CoverT cover_type
;
277 typedef scanline_u
<CoverT
> scanline_type
;
279 scanline_am() : scanline_type(), m_alpha_mask(0) {}
280 scanline_am(const AlphaMask
& am
) : scanline_type(), m_alpha_mask(&am
) {}
282 //--------------------------------------------------------------------
283 void finalize(int span_y
)
285 scanline_u
<CoverT
>::finalize(span_y
);
288 typename
scanline_type::iterator span
= scanline_type::begin();
289 unsigned count
= scanline_type::num_spans();
292 m_alpha_mask
->combine_hspan(span
->x
,
303 const AlphaMask
* m_alpha_mask
;
307 //==========================================================scanline_u8_am
308 template<class AlphaMask
>
309 class scanline_u8_am
: public scanline_am
<AlphaMask
, int8u
>
312 typedef AlphaMask alpha_mask_type
;
313 typedef int8u cover_type
;
314 typedef scanline_am
<alpha_mask_type
, cover_type
> self_type
;
316 scanline_u8_am() : self_type() {}
317 scanline_u8_am(const AlphaMask
& am
) : self_type(am
) {}