Anti-Grain Geometry Tutorial
agg_scanline_u.h
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 <cstring>
28 #include "agg_array.h"
29 
30 namespace agg
31 {
32  //=============================================================scanline_u8
33  //
34  // Unpacked scanline container class
35  //
36  // This class is used to transfer data from a scanline rasterizer
37  // to the rendering buffer. It's organized very simple. The class stores
38  // information of horizontal spans to render it into a pixel-map buffer.
39  // Each span has staring X, length, and an array of bytes that determine the
40  // cover-values for each pixel.
41  // Before using this class you should know the minimal and maximal pixel
42  // coordinates of your scanline. The protocol of using is:
43  // 1. reset(min_x, max_x)
44  // 2. add_cell() / add_span() - accumulate scanline.
45  // When forming one scanline the next X coordinate must be always greater
46  // than the last stored one, i.e. it works only with ordered coordinates.
47  // 3. Call finalize(y) and render the scanline.
48  // 3. Call reset_spans() to prepare for the new scanline.
49  //
50  // 4. Rendering:
51  //
52  // Scanline provides an iterator class that allows you to extract
53  // the spans and the cover values for each pixel. Be aware that clipping
54  // has not been done yet, so you should perform it yourself.
55  // Use scanline_u8::iterator to render spans:
56  //-------------------------------------------------------------------------
57  //
58  // int y = sl.y(); // Y-coordinate of the scanline
59  //
60  // ************************************
61  // ...Perform vertical clipping here...
62  // ************************************
63  //
64  // scanline_u8::const_iterator span = sl.begin();
65  //
66  // unsigned char* row = m_rbuf->row(y); // The address of the beginning
67  // // of the current row
68  //
69  // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
70  // // num_spans is always greater than 0.
71  //
72  // do
73  // {
74  // const scanline_u8::cover_type* covers =
75  // span->covers; // The array of the cover values
76  //
77  // int num_pix = span->len; // Number of pixels of the span.
78  // // Always greater than 0, still it's
79  // // better to use "int" instead of
80  // // "unsigned" because it's more
81  // // convenient for clipping
82  // int x = span->x;
83  //
84  // **************************************
85  // ...Perform horizontal clipping here...
86  // ...you have x, covers, and pix_count..
87  // **************************************
88  //
89  // unsigned char* dst = row + x; // Calculate the start address of the row.
90  // // In this case we assume a simple
91  // // grayscale image 1-byte per pixel.
92  // do
93  // {
94  // *dst++ = *covers++; // Hypotetical rendering.
95  // }
96  // while(--num_pix);
97  //
98  // ++span;
99  // }
100  // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
101  //------------------------------------------------------------------------
102  //
103  // The question is: why should we accumulate the whole scanline when we
104  // could render just separate spans when they're ready?
105  // That's because using the scanline is generally faster. When is consists
106  // of more than one span the conditions for the processor cash system
107  // are better, because switching between two different areas of memory
108  // (that can be very large) occurs less frequently.
109  //------------------------------------------------------------------------
111  {
112  public:
113  typedef scanline_u8 self_type;
114  typedef int8u cover_type;
115  typedef int16 coord_type;
116 
117  //--------------------------------------------------------------------
118  struct span
119  {
120  coord_type x;
121  coord_type len;
122  cover_type* covers;
123  };
124 
125  typedef span* iterator;
126  typedef const span* const_iterator;
127 
128  //--------------------------------------------------------------------
129  scanline_u8() :
130  m_min_x(0),
131  m_last_x(0x7FFFFFF0),
132  m_cur_span(0)
133  {}
134 
135  //--------------------------------------------------------------------
136  void reset(int min_x, int max_x)
137  {
138  unsigned max_len = max_x - min_x + 2;
139  if(max_len > m_spans.size())
140  {
141  m_spans.resize(max_len);
142  m_covers.resize(max_len);
143  }
144  m_last_x = 0x7FFFFFF0;
145  m_min_x = min_x;
146  m_cur_span = &m_spans[0];
147  }
148 
149  //--------------------------------------------------------------------
150  void add_cell(int x, unsigned cover)
151  {
152  x -= m_min_x;
153  m_covers[x] = (cover_type)cover;
154  if(x == m_last_x+1)
155  {
156  m_cur_span->len++;
157  }
158  else
159  {
160  m_cur_span++;
161  m_cur_span->x = (coord_type)(x + m_min_x);
162  m_cur_span->len = 1;
163  m_cur_span->covers = &m_covers[x];
164  }
165  m_last_x = x;
166  }
167 
168  //--------------------------------------------------------------------
169  void add_cells(int x, unsigned len, const cover_type* covers)
170  {
171  x -= m_min_x;
172  std::memcpy(&m_covers[x], covers, len * sizeof(cover_type));
173  if(x == m_last_x+1)
174  {
175  m_cur_span->len += (coord_type)len;
176  }
177  else
178  {
179  m_cur_span++;
180  m_cur_span->x = (coord_type)(x + m_min_x);
181  m_cur_span->len = (coord_type)len;
182  m_cur_span->covers = &m_covers[x];
183  }
184  m_last_x = x + len - 1;
185  }
186 
187  //--------------------------------------------------------------------
188  void add_span(int x, unsigned len, unsigned cover)
189  {
190  x -= m_min_x;
191  std::memset(&m_covers[x], cover, len);
192  if(x == m_last_x+1)
193  {
194  m_cur_span->len += (coord_type)len;
195  }
196  else
197  {
198  m_cur_span++;
199  m_cur_span->x = (coord_type)(x + m_min_x);
200  m_cur_span->len = (coord_type)len;
201  m_cur_span->covers = &m_covers[x];
202  }
203  m_last_x = x + len - 1;
204  }
205 
206  //--------------------------------------------------------------------
207  void finalize(int y)
208  {
209  m_y = y;
210  }
211 
212  //--------------------------------------------------------------------
213  void reset_spans()
214  {
215  m_last_x = 0x7FFFFFF0;
216  m_cur_span = &m_spans[0];
217  }
218 
219  //--------------------------------------------------------------------
220  int y() const { return m_y; }
221  unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
222  const_iterator begin() const { return &m_spans[1]; }
223  iterator begin() { return &m_spans[1]; }
224 
225  private:
226  scanline_u8(const self_type&);
227  const self_type& operator = (const self_type&);
228 
229  private:
230  int m_min_x;
231  int m_last_x;
232  int m_y;
233  pod_array<cover_type> m_covers;
234  pod_array<span> m_spans;
235  span* m_cur_span;
236  };
237 
238 
239 
240 
241  //==========================================================scanline_u8_am
242  //
243  // The scanline container with alpha-masking
244  //
245  //------------------------------------------------------------------------
246  template<class AlphaMask>
248  {
249  public:
250  typedef scanline_u8 base_type;
251  typedef AlphaMask alpha_mask_type;
252  typedef base_type::cover_type cover_type;
253  typedef base_type::coord_type coord_type;
254 
255  scanline_u8_am() : base_type(), m_alpha_mask(0) {}
256  scanline_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
257 
258  //--------------------------------------------------------------------
259  void finalize(int span_y)
260  {
261  base_type::finalize(span_y);
262  if(m_alpha_mask)
263  {
264  typename base_type::iterator span = base_type::begin();
265  unsigned count = base_type::num_spans();
266  do
267  {
268  m_alpha_mask->combine_hspan(span->x,
269  base_type::y(),
270  span->covers,
271  span->len);
272  ++span;
273  }
274  while(--count);
275  }
276  }
277 
278  private:
279  AlphaMask* m_alpha_mask;
280  };
281 
282 
283 
284 
285  //===========================================================scanline32_u8
287  {
288  public:
289  typedef scanline32_u8 self_type;
290  typedef int8u cover_type;
291  typedef int32 coord_type;
292 
293  //--------------------------------------------------------------------
294  struct span
295  {
296  span() {}
297  span(coord_type x_, coord_type len_, cover_type* covers_) :
298  x(x_), len(len_), covers(covers_) {}
299 
300  coord_type x;
301  coord_type len;
302  cover_type* covers;
303  };
304 
306 
307  //--------------------------------------------------------------------
309  {
310  public:
311  const_iterator(const span_array_type& spans) :
312  m_spans(spans),
313  m_span_idx(0)
314  {}
315 
316  const span& operator*() const { return m_spans[m_span_idx]; }
317  const span* operator->() const { return &m_spans[m_span_idx]; }
318 
319  void operator ++ () { ++m_span_idx; }
320 
321  private:
322  const span_array_type& m_spans;
323  unsigned m_span_idx;
324  };
325 
326  //--------------------------------------------------------------------
327  class iterator
328  {
329  public:
330  iterator(span_array_type& spans) :
331  m_spans(spans),
332  m_span_idx(0)
333  {}
334 
335  span& operator*() { return m_spans[m_span_idx]; }
336  span* operator->() { return &m_spans[m_span_idx]; }
337 
338  void operator ++ () { ++m_span_idx; }
339 
340  private:
341  span_array_type& m_spans;
342  unsigned m_span_idx;
343  };
344 
345 
346 
347  //--------------------------------------------------------------------
348  scanline32_u8() :
349  m_min_x(0),
350  m_last_x(0x7FFFFFF0),
351  m_covers()
352  {}
353 
354  //--------------------------------------------------------------------
355  void reset(int min_x, int max_x)
356  {
357  unsigned max_len = max_x - min_x + 2;
358  if(max_len > m_covers.size())
359  {
360  m_covers.resize(max_len);
361  }
362  m_last_x = 0x7FFFFFF0;
363  m_min_x = min_x;
364  m_spans.remove_all();
365  }
366 
367  //--------------------------------------------------------------------
368  void add_cell(int x, unsigned cover)
369  {
370  x -= m_min_x;
371  m_covers[x] = cover_type(cover);
372  if(x == m_last_x+1)
373  {
374  m_spans.last().len++;
375  }
376  else
377  {
378  m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
379  }
380  m_last_x = x;
381  }
382 
383  //--------------------------------------------------------------------
384  void add_cells(int x, unsigned len, const cover_type* covers)
385  {
386  x -= m_min_x;
387  std::memcpy(&m_covers[x], covers, len * sizeof(cover_type));
388  if(x == m_last_x+1)
389  {
390  m_spans.last().len += coord_type(len);
391  }
392  else
393  {
394  m_spans.add(span(coord_type(x + m_min_x),
395  coord_type(len),
396  &m_covers[x]));
397  }
398  m_last_x = x + len - 1;
399  }
400 
401  //--------------------------------------------------------------------
402  void add_span(int x, unsigned len, unsigned cover)
403  {
404  x -= m_min_x;
405  std::memset(&m_covers[x], cover, len);
406  if(x == m_last_x+1)
407  {
408  m_spans.last().len += coord_type(len);
409  }
410  else
411  {
412  m_spans.add(span(coord_type(x + m_min_x),
413  coord_type(len),
414  &m_covers[x]));
415  }
416  m_last_x = x + len - 1;
417  }
418 
419  //--------------------------------------------------------------------
420  void finalize(int y)
421  {
422  m_y = y;
423  }
424 
425  //--------------------------------------------------------------------
426  void reset_spans()
427  {
428  m_last_x = 0x7FFFFFF0;
429  m_spans.remove_all();
430  }
431 
432  //--------------------------------------------------------------------
433  int y() const { return m_y; }
434  unsigned num_spans() const { return m_spans.size(); }
435  const_iterator begin() const { return const_iterator(m_spans); }
436  iterator begin() { return iterator(m_spans); }
437 
438  private:
439  scanline32_u8(const self_type&);
440  const self_type& operator = (const self_type&);
441 
442  private:
443  int m_min_x;
444  int m_last_x;
445  int m_y;
446  pod_array<cover_type> m_covers;
447  span_array_type m_spans;
448  };
449 
450 
451 
452 
453  //========================================================scanline32_u8_am
454  //
455  // The scanline container with alpha-masking
456  //
457  //------------------------------------------------------------------------
458  template<class AlphaMask>
460  {
461  public:
462  typedef scanline32_u8 base_type;
463  typedef AlphaMask alpha_mask_type;
464  typedef base_type::cover_type cover_type;
465  typedef base_type::coord_type coord_type;
466 
467 
468  scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
469  scanline32_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
470 
471  //--------------------------------------------------------------------
472  void finalize(int span_y)
473  {
474  base_type::finalize(span_y);
475  if(m_alpha_mask)
476  {
477  typename base_type::iterator span = base_type::begin();
478  unsigned count = base_type::num_spans();
479  do
480  {
481  m_alpha_mask->combine_hspan(span->x,
482  base_type::y(),
483  span->covers,
484  span->len);
485  ++span;
486  }
487  while(--count);
488  }
489  }
490 
491  private:
492  AlphaMask* m_alpha_mask;
493  };
494 
495 
496 
497 }
498 
499 #endif
500 
Definition: agg_arc.cpp:24