1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
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 // Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
22 //----------------------------------------------------------------------------
24 #ifndef AGG_SCANLINE_U_INCLUDED
25 #define AGG_SCANLINE_U_INCLUDED
27 #include "agg_array.h"
31 //=============================================================scanline_u8
33 // Unpacked scanline container class
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.
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 //-------------------------------------------------------------------------
57 // int y = sl.y(); // Y-coordinate of the scanline
59 // ************************************
60 // ...Perform vertical clipping here...
61 // ************************************
63 // scanline_u8::const_iterator span = sl.begin();
65 // unsigned char* row = m_rbuf->row(y); // The the address of the beginning
66 // // of the current row
68 // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
69 // // num_spans is always greater than 0.
73 // const scanline_u8::cover_type* covers =
74 // span->covers; // The array of the cover values
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
83 // **************************************
84 // ...Perform horizontal clipping here...
85 // ...you have x, covers, and pix_count..
86 // **************************************
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.
93 // *dst++ = *covers++; // Hypotetical rendering.
99 // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
100 //------------------------------------------------------------------------
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 //------------------------------------------------------------------------
112 typedef scanline_u8 self_type
;
113 typedef int8u cover_type
;
114 typedef int16 coord_type
;
116 //--------------------------------------------------------------------
124 typedef span
* iterator
;
125 typedef const span
* const_iterator
;
127 //--------------------------------------------------------------------
130 m_last_x(0x7FFFFFF0),
134 //--------------------------------------------------------------------
135 void reset(int min_x
, int max_x
)
137 unsigned max_len
= max_x
- min_x
+ 2;
138 if(max_len
> m_spans
.size())
140 m_spans
.resize(max_len
);
141 m_covers
.resize(max_len
);
143 m_last_x
= 0x7FFFFFF0;
145 m_cur_span
= &m_spans
[0];
148 //--------------------------------------------------------------------
149 void add_cell(int x
, unsigned cover
)
152 m_covers
[x
] = (cover_type
)cover
;
160 m_cur_span
->x
= (coord_type
)(x
+ m_min_x
);
162 m_cur_span
->covers
= &m_covers
[x
];
167 //--------------------------------------------------------------------
168 void add_cells(int x
, unsigned len
, const cover_type
* covers
)
171 memcpy(&m_covers
[x
], covers
, len
* sizeof(cover_type
));
174 m_cur_span
->len
+= (coord_type
)len
;
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
];
183 m_last_x
= x
+ len
- 1;
186 //--------------------------------------------------------------------
187 void add_span(int x
, unsigned len
, unsigned cover
)
190 memset(&m_covers
[x
], cover
, len
);
193 m_cur_span
->len
+= (coord_type
)len
;
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
];
202 m_last_x
= x
+ len
- 1;
205 //--------------------------------------------------------------------
211 //--------------------------------------------------------------------
214 m_last_x
= 0x7FFFFFF0;
215 m_cur_span
= &m_spans
[0];
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]; }
225 scanline_u8(const self_type
&);
226 const self_type
& operator = (const self_type
&);
232 pod_array
<cover_type
> m_covers
;
233 pod_array
<span
> m_spans
;
240 //==========================================================scanline_u8_am
242 // The scanline container with alpha-masking
244 //------------------------------------------------------------------------
245 template<class AlphaMask
>
246 class scanline_u8_am
: public scanline_u8
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
;
254 scanline_u8_am() : base_type(), m_alpha_mask(0) {}
255 scanline_u8_am(AlphaMask
& am
) : base_type(), m_alpha_mask(&am
) {}
257 //--------------------------------------------------------------------
258 void finalize(int span_y
)
260 base_type::finalize(span_y
);
263 typename
base_type::iterator span
= base_type::begin();
264 unsigned count
= base_type::num_spans();
267 m_alpha_mask
->combine_hspan(span
->x
,
278 AlphaMask
* m_alpha_mask
;
284 //===========================================================scanline32_u8
288 typedef scanline32_u8 self_type
;
289 typedef int8u cover_type
;
290 typedef int32 coord_type
;
292 //--------------------------------------------------------------------
296 span(coord_type x_
, coord_type len_
, cover_type
* covers_
) :
297 x(x_
), len(len_
), covers(covers_
) {}
304 typedef pod_bvector
<span
, 4> span_array_type
;
306 //--------------------------------------------------------------------
310 const_iterator(const span_array_type
& spans
) :
315 const span
& operator*() const { return m_spans
[m_span_idx
]; }
316 const span
* operator->() const { return &m_spans
[m_span_idx
]; }
318 void operator ++ () { ++m_span_idx
; }
321 const span_array_type
& m_spans
;
325 //--------------------------------------------------------------------
329 iterator(span_array_type
& spans
) :
334 span
& operator*() { return m_spans
[m_span_idx
]; }
335 span
* operator->() { return &m_spans
[m_span_idx
]; }
337 void operator ++ () { ++m_span_idx
; }
340 span_array_type
& m_spans
;
346 //--------------------------------------------------------------------
349 m_last_x(0x7FFFFFF0),
353 //--------------------------------------------------------------------
354 void reset(int min_x
, int max_x
)
356 unsigned max_len
= max_x
- min_x
+ 2;
357 if(max_len
> m_covers
.size())
359 m_covers
.resize(max_len
);
361 m_last_x
= 0x7FFFFFF0;
363 m_spans
.remove_all();
366 //--------------------------------------------------------------------
367 void add_cell(int x
, unsigned cover
)
370 m_covers
[x
] = cover_type(cover
);
373 m_spans
.last().len
++;
377 m_spans
.add(span(coord_type(x
+ m_min_x
), 1, &m_covers
[x
]));
382 //--------------------------------------------------------------------
383 void add_cells(int x
, unsigned len
, const cover_type
* covers
)
386 memcpy(&m_covers
[x
], covers
, len
* sizeof(cover_type
));
389 m_spans
.last().len
+= coord_type(len
);
393 m_spans
.add(span(coord_type(x
+ m_min_x
),
397 m_last_x
= x
+ len
- 1;
400 //--------------------------------------------------------------------
401 void add_span(int x
, unsigned len
, unsigned cover
)
404 memset(&m_covers
[x
], cover
, len
);
407 m_spans
.last().len
+= coord_type(len
);
411 m_spans
.add(span(coord_type(x
+ m_min_x
),
415 m_last_x
= x
+ len
- 1;
418 //--------------------------------------------------------------------
424 //--------------------------------------------------------------------
427 m_last_x
= 0x7FFFFFF0;
428 m_spans
.remove_all();
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
); }
438 scanline32_u8(const self_type
&);
439 const self_type
& operator = (const self_type
&);
445 pod_array
<cover_type
> m_covers
;
446 span_array_type m_spans
;
452 //========================================================scanline32_u8_am
454 // The scanline container with alpha-masking
456 //------------------------------------------------------------------------
457 template<class AlphaMask
>
458 class scanline32_u8_am
: public scanline32_u8
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
;
467 scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
468 scanline32_u8_am(AlphaMask
& am
) : base_type(), m_alpha_mask(&am
) {}
470 //--------------------------------------------------------------------
471 void finalize(int span_y
)
473 base_type::finalize(span_y
);
476 typename
base_type::iterator span
= base_type::begin();
477 unsigned count
= base_type::num_spans();
480 m_alpha_mask
->combine_hspan(span
->x
,
491 AlphaMask
* m_alpha_mask
;