Anti-Grain Geometry Tutorial
agg_scanline_storage_aa.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 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_STORAGE_AA_INCLUDED
25 #define AGG_SCANLINE_STORAGE_AA_INCLUDED
26 
27 #include <cstring>
28 #include <cstdlib>
29 #include <limits>
30 #include "agg_array.h"
31 
32 
33 namespace agg
34 {
35 
36  //----------------------------------------------scanline_cell_storage
37  template<class T> class scanline_cell_storage
38  {
39  struct extra_span
40  {
41  unsigned len;
42  T* ptr;
43  };
44 
45  public:
46  typedef T value_type;
47 
48  //---------------------------------------------------------------
50  {
51  remove_all();
52  }
53 
54  //---------------------------------------------------------------
56  m_cells(128-2),
57  m_extra_storage()
58  {}
59 
60 
61  // Copying
62  //---------------------------------------------------------------
64  m_cells(v.m_cells),
65  m_extra_storage()
66  {
67  copy_extra_storage(v);
68  }
69 
70  //---------------------------------------------------------------
72  operator = (const scanline_cell_storage<T>& v)
73  {
74  remove_all();
75  m_cells = v.m_cells;
76  copy_extra_storage(v);
77  return *this;
78  }
79 
80  //---------------------------------------------------------------
81  void remove_all()
82  {
83  int i;
84  for(i = m_extra_storage.size()-1; i >= 0; --i)
85  {
86  pod_allocator<T>::deallocate(m_extra_storage[i].ptr,
87  m_extra_storage[i].len);
88  }
89  m_extra_storage.remove_all();
90  m_cells.remove_all();
91  }
92 
93  //---------------------------------------------------------------
94  int add_cells(const T* cells, unsigned num_cells)
95  {
96  int idx = m_cells.allocate_continuous_block(num_cells);
97  if(idx >= 0)
98  {
99  T* ptr = &m_cells[idx];
100  std::memcpy(ptr, cells, sizeof(T) * num_cells);
101  return idx;
102  }
103  extra_span s;
104  s.len = num_cells;
105  s.ptr = pod_allocator<T>::allocate(num_cells);
106  std::memcpy(s.ptr, cells, sizeof(T) * num_cells);
107  m_extra_storage.add(s);
108  return -int(m_extra_storage.size());
109  }
110 
111  //---------------------------------------------------------------
112  const T* operator [] (int idx) const
113  {
114  if(idx >= 0)
115  {
116  if((unsigned)idx >= m_cells.size()) return 0;
117  return &m_cells[(unsigned)idx];
118  }
119  unsigned i = unsigned(-idx - 1);
120  if(i >= m_extra_storage.size()) return 0;
121  return m_extra_storage[i].ptr;
122  }
123 
124  //---------------------------------------------------------------
125  T* operator [] (int idx)
126  {
127  if(idx >= 0)
128  {
129  if((unsigned)idx >= m_cells.size()) return 0;
130  return &m_cells[(unsigned)idx];
131  }
132  unsigned i = unsigned(-idx - 1);
133  if(i >= m_extra_storage.size()) return 0;
134  return m_extra_storage[i].ptr;
135  }
136 
137  private:
138  void copy_extra_storage(const scanline_cell_storage<T>& v)
139  {
140  unsigned i;
141  for(i = 0; i < v.m_extra_storage.size(); ++i)
142  {
143  const extra_span& src = v.m_extra_storage[i];
144  extra_span dst;
145  dst.len = src.len;
146  dst.ptr = pod_allocator<T>::allocate(dst.len);
147  std::memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
148  m_extra_storage.add(dst);
149  }
150  }
151 
152  pod_bvector<T, 12> m_cells;
153  pod_bvector<extra_span, 6> m_extra_storage;
154  };
155 
156 
157 
158 
159 
160 
161  //-----------------------------------------------scanline_storage_aa
162  template<class T> class scanline_storage_aa
163  {
164  public:
165  typedef T cover_type;
166 
167  //---------------------------------------------------------------
168  struct span_data
169  {
170  int32 x;
171  int32 len; // If negative, it's a solid span, covers is valid
172  int covers_id; // The index of the cells in the scanline_cell_storage
173  };
174 
175  //---------------------------------------------------------------
177  {
178  int y;
179  unsigned num_spans;
180  unsigned start_span;
181  };
182 
183 
184  //---------------------------------------------------------------
186  {
187  public:
188 
189  //-----------------------------------------------------------
191  {
192  public:
193  struct span
194  {
195  int32 x;
196  int32 len; // If negative, it's a solid span, covers is valid
197  const T* covers;
198  };
199 
200  const_iterator() : m_storage(0) {}
202  m_storage(sl.m_storage),
203  m_span_idx(sl.m_scanline.start_span)
204  {
205  init_span();
206  }
207 
208  const span& operator*() const { return m_span; }
209  const span* operator->() const { return &m_span; }
210 
211  void operator ++ ()
212  {
213  ++m_span_idx;
214  init_span();
215  }
216 
217  private:
218  void init_span()
219  {
220  const span_data& s = m_storage->span_by_index(m_span_idx);
221  m_span.x = s.x;
222  m_span.len = s.len;
223  m_span.covers = m_storage->covers_by_index(s.covers_id);
224  }
225 
226  scanline_storage_aa* m_storage;
227  unsigned m_span_idx;
228  span m_span;
229  };
230 
231  friend class const_iterator;
232 
233 
234  //-----------------------------------------------------------
235  embedded_scanline(const scanline_storage_aa& storage) :
236  m_storage(&storage)
237  {
238  init(0);
239  }
240 
241  //-----------------------------------------------------------
242  void reset(int, int) {}
243  unsigned num_spans() const { return m_scanline.num_spans; }
244  int y() const { return m_scanline.y; }
245  const_iterator begin() const { return const_iterator(*this); }
246 
247  //-----------------------------------------------------------
248  void init(unsigned scanline_idx)
249  {
250  m_scanline_idx = scanline_idx;
251  m_scanline = m_storage->scanline_by_index(m_scanline_idx);
252  }
253 
254  private:
255  const scanline_storage_aa* m_storage;
256  scanline_data m_scanline;
257  unsigned m_scanline_idx;
258  };
259 
260 
261  //---------------------------------------------------------------
263  m_covers(),
264  m_spans(256-2), // Block increment size
265  m_scanlines(),
266  m_min_x(std::numeric_limits<int>::max()),
267  m_min_y(std::numeric_limits<int>::max()),
268  m_max_x(std::numeric_limits<int>::min()),
269  m_max_y(std::numeric_limits<int>::min()),
270  m_cur_scanline(0)
271  {
272  m_fake_scanline.y = 0;
273  m_fake_scanline.num_spans = 0;
274  m_fake_scanline.start_span = 0;
275  m_fake_span.x = 0;
276  m_fake_span.len = 0;
277  m_fake_span.covers_id = 0;
278  }
279 
280  // Renderer Interface
281  //---------------------------------------------------------------
282  void prepare()
283  {
284  m_covers.remove_all();
285  m_scanlines.remove_all();
286  m_spans.remove_all();
287  m_min_x = std::numeric_limits<int>::max();
288  m_min_y = std::numeric_limits<int>::max();
289  m_max_x = std::numeric_limits<int>::min();
290  m_max_y = std::numeric_limits<int>::min();
291  m_cur_scanline = 0;
292  }
293 
294  //---------------------------------------------------------------
295  template<class Scanline> void render(const Scanline& sl)
296  {
297  scanline_data sl_this;
298 
299  int y = sl.y();
300  if(y < m_min_y) m_min_y = y;
301  if(y > m_max_y) m_max_y = y;
302 
303  sl_this.y = y;
304  sl_this.num_spans = sl.num_spans();
305  sl_this.start_span = m_spans.size();
306  typename Scanline::const_iterator span_iterator = sl.begin();
307 
308  unsigned num_spans = sl_this.num_spans;
309  for(;;)
310  {
311  span_data sp;
312 
313  sp.x = span_iterator->x;
314  sp.len = span_iterator->len;
315  int len = std::abs(int(sp.len));
316  sp.covers_id =
317  m_covers.add_cells(span_iterator->covers,
318  unsigned(len));
319  m_spans.add(sp);
320  int x1 = sp.x;
321  int x2 = sp.x + len - 1;
322  if(x1 < m_min_x) m_min_x = x1;
323  if(x2 > m_max_x) m_max_x = x2;
324  if(--num_spans == 0) break;
325  ++span_iterator;
326  }
327  m_scanlines.add(sl_this);
328  }
329 
330 
331  //---------------------------------------------------------------
332  // Iterate scanlines interface
333  int min_x() const { return m_min_x; }
334  int min_y() const { return m_min_y; }
335  int max_x() const { return m_max_x; }
336  int max_y() const { return m_max_y; }
337 
338  //---------------------------------------------------------------
339  bool rewind_scanlines()
340  {
341  m_cur_scanline = 0;
342  return m_scanlines.size() > 0;
343  }
344 
345 
346  //---------------------------------------------------------------
347  template<class Scanline> bool sweep_scanline(Scanline& sl)
348  {
349  sl.reset_spans();
350  for(;;)
351  {
352  if(m_cur_scanline >= m_scanlines.size()) return false;
353  const scanline_data& sl_this = m_scanlines[m_cur_scanline];
354 
355  unsigned num_spans = sl_this.num_spans;
356  unsigned span_idx = sl_this.start_span;
357  do
358  {
359  const span_data& sp = m_spans[span_idx++];
360  const T* covers = covers_by_index(sp.covers_id);
361  if(sp.len < 0)
362  {
363  sl.add_span(sp.x, unsigned(-sp.len), *covers);
364  }
365  else
366  {
367  sl.add_cells(sp.x, sp.len, covers);
368  }
369  }
370  while(--num_spans);
371  ++m_cur_scanline;
372  if(sl.num_spans())
373  {
374  sl.finalize(sl_this.y);
375  break;
376  }
377  }
378  return true;
379  }
380 
381 
382  //---------------------------------------------------------------
383  // Specialization for embedded_scanline
384  bool sweep_scanline(embedded_scanline& sl)
385  {
386  do
387  {
388  if(m_cur_scanline >= m_scanlines.size()) return false;
389  sl.init(m_cur_scanline);
390  ++m_cur_scanline;
391  }
392  while(sl.num_spans() == 0);
393  return true;
394  }
395 
396  //---------------------------------------------------------------
397  unsigned byte_size() const
398  {
399  unsigned i;
400  unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
401 
402  for(i = 0; i < m_scanlines.size(); ++i)
403  {
404  size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans
405 
406  const scanline_data& sl_this = m_scanlines[i];
407 
408  unsigned num_spans = sl_this.num_spans;
409  unsigned span_idx = sl_this.start_span;
410  do
411  {
412  const span_data& sp = m_spans[span_idx++];
413 
414  size += sizeof(int32) * 2; // X, span_len
415  if(sp.len < 0)
416  {
417  size += sizeof(T); // cover
418  }
419  else
420  {
421  size += sizeof(T) * unsigned(sp.len); // covers
422  }
423  }
424  while(--num_spans);
425  }
426  return size;
427  }
428 
429 
430  //---------------------------------------------------------------
431  static void write_int32(int8u* dst, int32 val)
432  {
433  dst[0] = ((const int8u*)&val)[0];
434  dst[1] = ((const int8u*)&val)[1];
435  dst[2] = ((const int8u*)&val)[2];
436  dst[3] = ((const int8u*)&val)[3];
437  }
438 
439 
440  //---------------------------------------------------------------
441  void serialize(int8u* data) const
442  {
443  unsigned i;
444 
445  write_int32(data, min_x()); // min_x
446  data += sizeof(int32);
447  write_int32(data, min_y()); // min_y
448  data += sizeof(int32);
449  write_int32(data, max_x()); // max_x
450  data += sizeof(int32);
451  write_int32(data, max_y()); // max_y
452  data += sizeof(int32);
453 
454  for(i = 0; i < m_scanlines.size(); ++i)
455  {
456  const scanline_data& sl_this = m_scanlines[i];
457 
458  int8u* size_ptr = data;
459  data += sizeof(int32); // Reserve space for scanline size in bytes
460 
461  write_int32(data, sl_this.y); // Y
462  data += sizeof(int32);
463 
464  write_int32(data, sl_this.num_spans); // num_spans
465  data += sizeof(int32);
466 
467  unsigned num_spans = sl_this.num_spans;
468  unsigned span_idx = sl_this.start_span;
469  do
470  {
471  const span_data& sp = m_spans[span_idx++];
472  const T* covers = covers_by_index(sp.covers_id);
473 
474  write_int32(data, sp.x); // X
475  data += sizeof(int32);
476 
477  write_int32(data, sp.len); // span_len
478  data += sizeof(int32);
479 
480  if(sp.len < 0)
481  {
482  std::memcpy(data, covers, sizeof(T));
483  data += sizeof(T);
484  }
485  else
486  {
487  std::memcpy(data, covers, unsigned(sp.len) * sizeof(T));
488  data += sizeof(T) * unsigned(sp.len);
489  }
490  }
491  while(--num_spans);
492  write_int32(size_ptr, int32(unsigned(data - size_ptr)));
493  }
494  }
495 
496 
497  //---------------------------------------------------------------
498  const scanline_data& scanline_by_index(unsigned i) const
499  {
500  return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
501  }
502 
503  //---------------------------------------------------------------
504  const span_data& span_by_index(unsigned i) const
505  {
506  return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
507  }
508 
509  //---------------------------------------------------------------
510  const T* covers_by_index(int i) const
511  {
512  return m_covers[i];
513  }
514 
515  private:
516  scanline_cell_storage<T> m_covers;
518  pod_bvector<scanline_data, 8> m_scanlines;
519  span_data m_fake_span;
520  scanline_data m_fake_scanline;
521  int m_min_x;
522  int m_min_y;
523  int m_max_x;
524  int m_max_y;
525  unsigned m_cur_scanline;
526  };
527 
528 
529  typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8
530  typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16
531  typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32
532 
533 
534 
535 
536  //------------------------------------------serialized_scanlines_adaptor_aa
537  template<class T> class serialized_scanlines_adaptor_aa
538  {
539  public:
540  typedef T cover_type;
541 
542  //---------------------------------------------------------------------
544  {
545  public:
546  typedef T cover_type;
547 
548  //-----------------------------------------------------------------
550  {
551  public:
552  struct span
553  {
554  int32 x;
555  int32 len; // If negative, it's a solid span, "covers" is valid
556  const T* covers;
557  };
558 
559  const_iterator() : m_ptr(0) {}
560  const_iterator(const embedded_scanline* sl) :
561  m_ptr(sl->m_ptr),
562  m_dx(sl->m_dx)
563  {
564  init_span();
565  }
566 
567  const span& operator*() const { return m_span; }
568  const span* operator->() const { return &m_span; }
569 
570  void operator ++ ()
571  {
572  if(m_span.len < 0)
573  {
574  m_ptr += sizeof(T);
575  }
576  else
577  {
578  m_ptr += m_span.len * sizeof(T);
579  }
580  init_span();
581  }
582 
583  private:
584  int read_int32()
585  {
586  int32 val;
587  ((int8u*)&val)[0] = *m_ptr++;
588  ((int8u*)&val)[1] = *m_ptr++;
589  ((int8u*)&val)[2] = *m_ptr++;
590  ((int8u*)&val)[3] = *m_ptr++;
591  return val;
592  }
593 
594  void init_span()
595  {
596  m_span.x = read_int32() + m_dx;
597  m_span.len = read_int32();
598  m_span.covers = m_ptr;
599  }
600 
601  const int8u* m_ptr;
602  span m_span;
603  int m_dx;
604  };
605 
606  friend class const_iterator;
607 
608 
609  //-----------------------------------------------------------------
610  embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
611 
612  //-----------------------------------------------------------------
613  void reset(int, int) {}
614  unsigned num_spans() const { return m_num_spans; }
615  int y() const { return m_y; }
616  const_iterator begin() const { return const_iterator(this); }
617 
618 
619  private:
620  //-----------------------------------------------------------------
621  int read_int32()
622  {
623  int32 val;
624  ((int8u*)&val)[0] = *m_ptr++;
625  ((int8u*)&val)[1] = *m_ptr++;
626  ((int8u*)&val)[2] = *m_ptr++;
627  ((int8u*)&val)[3] = *m_ptr++;
628  return val;
629  }
630 
631  public:
632  //-----------------------------------------------------------------
633  void init(const int8u* ptr, int dx, int dy)
634  {
635  m_ptr = ptr;
636  m_y = read_int32() + dy;
637  m_num_spans = unsigned(read_int32());
638  m_dx = dx;
639  }
640 
641  private:
642  const int8u* m_ptr;
643  int m_y;
644  unsigned m_num_spans;
645  int m_dx;
646  };
647 
648 
649 
650  public:
651  //--------------------------------------------------------------------
653  m_data(0),
654  m_end(0),
655  m_ptr(0),
656  m_dx(0),
657  m_dy(0),
658  m_min_x(std::numeric_limits<int>::max()),
659  m_min_y(std::numeric_limits<int>::max()),
660  m_max_x(std::numeric_limits<int>::min()),
661  m_max_y(std::numeric_limits<int>::min())
662  {}
663 
664  //--------------------------------------------------------------------
665  serialized_scanlines_adaptor_aa(const int8u* data, unsigned size,
666  double dx, double dy) :
667  m_data(data),
668  m_end(data + size),
669  m_ptr(data),
670  m_dx(iround(dx)),
671  m_dy(iround(dy)),
672  m_min_x(std::numeric_limits<int>::max()),
673  m_min_y(std::numeric_limits<int>::max()),
674  m_max_x(std::numeric_limits<int>::min()),
675  m_max_y(std::numeric_limits<int>::min())
676  {}
677 
678  //--------------------------------------------------------------------
679  void init(const int8u* data, unsigned size, double dx, double dy)
680  {
681  m_data = data;
682  m_end = data + size;
683  m_ptr = data;
684  m_dx = iround(dx);
685  m_dy = iround(dy);
686  m_min_x = std::numeric_limits<int>::max();
687  m_min_y = std::numeric_limits<int>::max();
688  m_max_x = std::numeric_limits<int>::min();
689  m_max_y = std::numeric_limits<int>::min();
690  }
691 
692  private:
693  //--------------------------------------------------------------------
694  int read_int32()
695  {
696  int32 val;
697  ((int8u*)&val)[0] = *m_ptr++;
698  ((int8u*)&val)[1] = *m_ptr++;
699  ((int8u*)&val)[2] = *m_ptr++;
700  ((int8u*)&val)[3] = *m_ptr++;
701  return val;
702  }
703 
704  //--------------------------------------------------------------------
705  unsigned read_int32u()
706  {
707  int32u val;
708  ((int8u*)&val)[0] = *m_ptr++;
709  ((int8u*)&val)[1] = *m_ptr++;
710  ((int8u*)&val)[2] = *m_ptr++;
711  ((int8u*)&val)[3] = *m_ptr++;
712  return val;
713  }
714 
715  public:
716  // Iterate scanlines interface
717  //--------------------------------------------------------------------
718  bool rewind_scanlines()
719  {
720  m_ptr = m_data;
721  if(m_ptr < m_end)
722  {
723  m_min_x = read_int32() + m_dx;
724  m_min_y = read_int32() + m_dy;
725  m_max_x = read_int32() + m_dx;
726  m_max_y = read_int32() + m_dy;
727  }
728  return m_ptr < m_end;
729  }
730 
731  //--------------------------------------------------------------------
732  int min_x() const { return m_min_x; }
733  int min_y() const { return m_min_y; }
734  int max_x() const { return m_max_x; }
735  int max_y() const { return m_max_y; }
736 
737  //--------------------------------------------------------------------
738  template<class Scanline> bool sweep_scanline(Scanline& sl)
739  {
740  sl.reset_spans();
741  for(;;)
742  {
743  if(m_ptr >= m_end) return false;
744 
745  read_int32(); // Skip scanline size in bytes
746  int y = read_int32() + m_dy;
747  unsigned num_spans = read_int32();
748 
749  do
750  {
751  int x = read_int32() + m_dx;
752  int len = read_int32();
753 
754  if(len < 0)
755  {
756  sl.add_span(x, unsigned(-len), *m_ptr);
757  m_ptr += sizeof(T);
758  }
759  else
760  {
761  sl.add_cells(x, len, m_ptr);
762  m_ptr += len * sizeof(T);
763  }
764  }
765  while(--num_spans);
766 
767  if(sl.num_spans())
768  {
769  sl.finalize(y);
770  break;
771  }
772  }
773  return true;
774  }
775 
776 
777  //--------------------------------------------------------------------
778  // Specialization for embedded_scanline
779  bool sweep_scanline(embedded_scanline& sl)
780  {
781  do
782  {
783  if(m_ptr >= m_end) return false;
784 
785  unsigned byte_size = read_int32u();
786  sl.init(m_ptr, m_dx, m_dy);
787  m_ptr += byte_size - sizeof(int32);
788  }
789  while(sl.num_spans() == 0);
790  return true;
791  }
792 
793  private:
794  const int8u* m_data;
795  const int8u* m_end;
796  const int8u* m_ptr;
797  int m_dx;
798  int m_dy;
799  int m_min_x;
800  int m_min_y;
801  int m_max_x;
802  int m_max_y;
803  };
804 
805 
806 
807  typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8
808  typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16
809  typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32
810 
811 }
812 
813 
814 #endif
815 
Definition: agg_arc.cpp:24