btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_scanline_u.h
blob630eb9deac3b7a6277ecc36610e4a56ca578313a
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 //----------------------------------------------------------------------------
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.
21 //
22 //----------------------------------------------------------------------------
24 #ifndef AGG_SCANLINE_U_INCLUDED
25 #define AGG_SCANLINE_U_INCLUDED
27 #include "agg_array.h"
29 namespace agg
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.
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 //-------------------------------------------------------------------------
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();
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.
71 // do
72 // {
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
81 // int x = span->x;
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.
91 // do
92 // {
93 // *dst++ = *covers++; // Hypotetical rendering.
94 // }
95 // while(--num_pix);
97 // ++span;
98 // }
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 //------------------------------------------------------------------------
109 class scanline_u8
111 public:
112 typedef scanline_u8 self_type;
113 typedef int8u cover_type;
114 typedef int16 coord_type;
116 //--------------------------------------------------------------------
117 struct span
119 coord_type x;
120 coord_type len;
121 cover_type* covers;
124 typedef span* iterator;
125 typedef const span* const_iterator;
127 //--------------------------------------------------------------------
128 scanline_u8() :
129 m_min_x(0),
130 m_last_x(0x7FFFFFF0),
131 m_cur_span(0)
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;
144 m_min_x = min_x;
145 m_cur_span = &m_spans[0];
148 //--------------------------------------------------------------------
149 void add_cell(int x, unsigned cover)
151 x -= m_min_x;
152 m_covers[x] = (cover_type)cover;
153 if(x == m_last_x+1)
155 m_cur_span->len++;
157 else
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];
164 m_last_x = x;
167 //--------------------------------------------------------------------
168 void add_cells(int x, unsigned len, const cover_type* covers)
170 x -= m_min_x;
171 memcpy(&m_covers[x], covers, len * sizeof(cover_type));
172 if(x == m_last_x+1)
174 m_cur_span->len += (coord_type)len;
176 else
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];
183 m_last_x = x + len - 1;
186 //--------------------------------------------------------------------
187 void add_span(int x, unsigned len, unsigned cover)
189 x -= m_min_x;
190 memset(&m_covers[x], cover, len);
191 if(x == m_last_x+1)
193 m_cur_span->len += (coord_type)len;
195 else
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];
202 m_last_x = x + len - 1;
205 //--------------------------------------------------------------------
206 void finalize(int y)
208 m_y = y;
211 //--------------------------------------------------------------------
212 void reset_spans()
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]; }
224 private:
225 scanline_u8(const self_type&);
226 const self_type& operator = (const self_type&);
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;
240 //==========================================================scanline_u8_am
242 // The scanline container with alpha-masking
244 //------------------------------------------------------------------------
245 template<class AlphaMask>
246 class scanline_u8_am : public scanline_u8
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;
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);
261 if(m_alpha_mask)
263 typename base_type::iterator span = base_type::begin();
264 unsigned count = base_type::num_spans();
267 m_alpha_mask->combine_hspan(span->x,
268 base_type::y(),
269 span->covers,
270 span->len);
271 ++span;
273 while(--count);
277 private:
278 AlphaMask* m_alpha_mask;
284 //===========================================================scanline32_u8
285 class scanline32_u8
287 public:
288 typedef scanline32_u8 self_type;
289 typedef int8u cover_type;
290 typedef int32 coord_type;
292 //--------------------------------------------------------------------
293 struct span
295 span() {}
296 span(coord_type x_, coord_type len_, cover_type* covers_) :
297 x(x_), len(len_), covers(covers_) {}
299 coord_type x;
300 coord_type len;
301 cover_type* covers;
304 typedef pod_bvector<span, 4> span_array_type;
306 //--------------------------------------------------------------------
307 class const_iterator
309 public:
310 const_iterator(const span_array_type& spans) :
311 m_spans(spans),
312 m_span_idx(0)
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; }
320 private:
321 const span_array_type& m_spans;
322 unsigned m_span_idx;
325 //--------------------------------------------------------------------
326 class iterator
328 public:
329 iterator(span_array_type& spans) :
330 m_spans(spans),
331 m_span_idx(0)
334 span& operator*() { return m_spans[m_span_idx]; }
335 span* operator->() { return &m_spans[m_span_idx]; }
337 void operator ++ () { ++m_span_idx; }
339 private:
340 span_array_type& m_spans;
341 unsigned m_span_idx;
346 //--------------------------------------------------------------------
347 scanline32_u8() :
348 m_min_x(0),
349 m_last_x(0x7FFFFFF0),
350 m_covers()
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;
362 m_min_x = min_x;
363 m_spans.remove_all();
366 //--------------------------------------------------------------------
367 void add_cell(int x, unsigned cover)
369 x -= m_min_x;
370 m_covers[x] = cover_type(cover);
371 if(x == m_last_x+1)
373 m_spans.last().len++;
375 else
377 m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
379 m_last_x = x;
382 //--------------------------------------------------------------------
383 void add_cells(int x, unsigned len, const cover_type* covers)
385 x -= m_min_x;
386 memcpy(&m_covers[x], covers, len * sizeof(cover_type));
387 if(x == m_last_x+1)
389 m_spans.last().len += coord_type(len);
391 else
393 m_spans.add(span(coord_type(x + m_min_x),
394 coord_type(len),
395 &m_covers[x]));
397 m_last_x = x + len - 1;
400 //--------------------------------------------------------------------
401 void add_span(int x, unsigned len, unsigned cover)
403 x -= m_min_x;
404 memset(&m_covers[x], cover, len);
405 if(x == m_last_x+1)
407 m_spans.last().len += coord_type(len);
409 else
411 m_spans.add(span(coord_type(x + m_min_x),
412 coord_type(len),
413 &m_covers[x]));
415 m_last_x = x + len - 1;
418 //--------------------------------------------------------------------
419 void finalize(int y)
421 m_y = y;
424 //--------------------------------------------------------------------
425 void reset_spans()
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); }
437 private:
438 scanline32_u8(const self_type&);
439 const self_type& operator = (const self_type&);
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;
452 //========================================================scanline32_u8_am
454 // The scanline container with alpha-masking
456 //------------------------------------------------------------------------
457 template<class AlphaMask>
458 class scanline32_u8_am : public scanline32_u8
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;
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);
474 if(m_alpha_mask)
476 typename base_type::iterator span = base_type::begin();
477 unsigned count = base_type::num_spans();
480 m_alpha_mask->combine_hspan(span->x,
481 base_type::y(),
482 span->covers,
483 span->len);
484 ++span;
486 while(--count);
490 private:
491 AlphaMask* m_alpha_mask;
498 #endif