Anti-Grain Geometry Tutorial
agg_scanline_storage_bin.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 
25 #ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED
26 #define AGG_SCANLINE_STORAGE_BIN_INCLUDED
27 
28 #include <cstdlib>
29 #include <limits>
30 #include "agg_array.h"
31 
32 
33 namespace agg
34 {
35 
36  //-----------------------------------------------scanline_storage_bin
38  {
39  public:
40  //---------------------------------------------------------------
41  struct span_data
42  {
43  int32 x;
44  int32 len;
45  };
46 
47  //---------------------------------------------------------------
49  {
50  int y;
51  unsigned num_spans;
52  unsigned start_span;
53  };
54 
55 
56  //---------------------------------------------------------------
58  {
59  public:
60 
61  //-----------------------------------------------------------
63  {
64  public:
65  const_iterator() : m_storage(0) {}
67  m_storage(sl->m_storage),
68  m_span_idx(sl->m_scanline.start_span)
69  {
70  m_span = m_storage->span_by_index(m_span_idx);
71  }
72 
73  const span_data& operator*() const { return m_span; }
74  const span_data* operator->() const { return &m_span; }
75 
76  void operator ++ ()
77  {
78  ++m_span_idx;
79  m_span = m_storage->span_by_index(m_span_idx);
80  }
81 
82  private:
83  const scanline_storage_bin* m_storage;
84  unsigned m_span_idx;
85  span_data m_span;
86  };
87 
88  friend class const_iterator;
89 
90 
91  //-----------------------------------------------------------
93  m_storage(&storage)
94  {
95  setup(0);
96  }
97 
98  //-----------------------------------------------------------
99  void reset(int, int) {}
100  unsigned num_spans() const { return m_scanline.num_spans; }
101  int y() const { return m_scanline.y; }
102  const_iterator begin() const { return const_iterator(this); }
103 
104  //-----------------------------------------------------------
105  void setup(unsigned scanline_idx)
106  {
107  m_scanline_idx = scanline_idx;
108  m_scanline = m_storage->scanline_by_index(m_scanline_idx);
109  }
110 
111  private:
112  scanline_storage_bin* m_storage;
113  scanline_data m_scanline;
114  unsigned m_scanline_idx;
115  };
116 
117 
118  //---------------------------------------------------------------
120  m_spans(256-2), // Block increment size
121  m_scanlines(),
122  m_min_x(std::numeric_limits<int>::max()),
123  m_min_y(std::numeric_limits<int>::max()),
124  m_max_x(std::numeric_limits<int>::min()),
125  m_max_y(std::numeric_limits<int>::min()),
126  m_cur_scanline(0)
127  {
128  m_fake_scanline.y = 0;
129  m_fake_scanline.num_spans = 0;
130  m_fake_scanline.start_span = 0;
131  m_fake_span.x = 0;
132  m_fake_span.len = 0;
133  }
134 
135  // Renderer Interface
136  //---------------------------------------------------------------
137  void prepare()
138  {
139  m_scanlines.remove_all();
140  m_spans.remove_all();
141  m_min_x = std::numeric_limits<int>::max();
142  m_min_y = std::numeric_limits<int>::max();
143  m_max_x = std::numeric_limits<int>::min();
144  m_max_y = std::numeric_limits<int>::min();
145  m_cur_scanline = 0;
146  }
147 
148  //---------------------------------------------------------------
149  template<class Scanline> void render(const Scanline& sl)
150  {
151  scanline_data sl_this;
152 
153  int y = sl.y();
154  if(y < m_min_y) m_min_y = y;
155  if(y > m_max_y) m_max_y = y;
156 
157  sl_this.y = y;
158  sl_this.num_spans = sl.num_spans();
159  sl_this.start_span = m_spans.size();
160  typename Scanline::const_iterator span_iterator = sl.begin();
161 
162  unsigned num_spans = sl_this.num_spans;
163  for(;;)
164  {
165  span_data sp;
166  sp.x = span_iterator->x;
167  sp.len = (int32)std::abs((int)(span_iterator->len));
168  m_spans.add(sp);
169  int x1 = sp.x;
170  int x2 = sp.x + sp.len - 1;
171  if(x1 < m_min_x) m_min_x = x1;
172  if(x2 > m_max_x) m_max_x = x2;
173  if(--num_spans == 0) break;
174  ++span_iterator;
175  }
176  m_scanlines.add(sl_this);
177  }
178 
179 
180  //---------------------------------------------------------------
181  // Iterate scanlines interface
182  int min_x() const { return m_min_x; }
183  int min_y() const { return m_min_y; }
184  int max_x() const { return m_max_x; }
185  int max_y() const { return m_max_y; }
186 
187  //---------------------------------------------------------------
188  bool rewind_scanlines()
189  {
190  m_cur_scanline = 0;
191  return m_scanlines.size() > 0;
192  }
193 
194 
195  //---------------------------------------------------------------
196  template<class Scanline> bool sweep_scanline(Scanline& sl)
197  {
198  sl.reset_spans();
199  for(;;)
200  {
201  if(m_cur_scanline >= m_scanlines.size()) return false;
202  const scanline_data& sl_this = m_scanlines[m_cur_scanline];
203 
204  unsigned num_spans = sl_this.num_spans;
205  unsigned span_idx = sl_this.start_span;
206  do
207  {
208  const span_data& sp = m_spans[span_idx++];
209  sl.add_span(sp.x, sp.len, cover_full);
210  }
211  while(--num_spans);
212 
213  ++m_cur_scanline;
214  if(sl.num_spans())
215  {
216  sl.finalize(sl_this.y);
217  break;
218  }
219  }
220  return true;
221  }
222 
223 
224  //---------------------------------------------------------------
225  // Specialization for embedded_scanline
226  bool sweep_scanline(embedded_scanline& sl)
227  {
228  do
229  {
230  if(m_cur_scanline >= m_scanlines.size()) return false;
231  sl.setup(m_cur_scanline);
232  ++m_cur_scanline;
233  }
234  while(sl.num_spans() == 0);
235  return true;
236  }
237 
238 
239  //---------------------------------------------------------------
240  unsigned byte_size() const
241  {
242  unsigned i;
243  unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
244 
245  for(i = 0; i < m_scanlines.size(); ++i)
246  {
247  size += sizeof(int32) * 2 + // Y, num_spans
248  unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len
249  }
250  return size;
251  }
252 
253 
254  //---------------------------------------------------------------
255  static void write_int32(int8u* dst, int32 val)
256  {
257  dst[0] = ((const int8u*)&val)[0];
258  dst[1] = ((const int8u*)&val)[1];
259  dst[2] = ((const int8u*)&val)[2];
260  dst[3] = ((const int8u*)&val)[3];
261  }
262 
263 
264  //---------------------------------------------------------------
265  void serialize(int8u* data) const
266  {
267  unsigned i;
268 
269  write_int32(data, min_x()); // min_x
270  data += sizeof(int32);
271  write_int32(data, min_y()); // min_y
272  data += sizeof(int32);
273  write_int32(data, max_x()); // max_x
274  data += sizeof(int32);
275  write_int32(data, max_y()); // max_y
276  data += sizeof(int32);
277 
278  for(i = 0; i < m_scanlines.size(); ++i)
279  {
280  const scanline_data& sl_this = m_scanlines[i];
281 
282  write_int32(data, sl_this.y); // Y
283  data += sizeof(int32);
284 
285  write_int32(data, sl_this.num_spans); // num_spans
286  data += sizeof(int32);
287 
288  unsigned num_spans = sl_this.num_spans;
289  unsigned span_idx = sl_this.start_span;
290  do
291  {
292  const span_data& sp = m_spans[span_idx++];
293 
294  write_int32(data, sp.x); // X
295  data += sizeof(int32);
296 
297  write_int32(data, sp.len); // len
298  data += sizeof(int32);
299  }
300  while(--num_spans);
301  }
302  }
303 
304 
305  //---------------------------------------------------------------
306  const scanline_data& scanline_by_index(unsigned i) const
307  {
308  return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
309  }
310 
311  //---------------------------------------------------------------
312  const span_data& span_by_index(unsigned i) const
313  {
314  return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
315  }
316 
317 
318  private:
320  pod_bvector<scanline_data, 8> m_scanlines;
321  span_data m_fake_span;
322  scanline_data m_fake_scanline;
323  int m_min_x;
324  int m_min_y;
325  int m_max_x;
326  int m_max_y;
327  unsigned m_cur_scanline;
328  };
329 
330 
331 
332 
333 
334 
335 
336 
337 
338 
339 
340 
341 
342  //---------------------------------------serialized_scanlines_adaptor_bin
344  {
345  public:
346  typedef bool cover_type;
347 
348  //--------------------------------------------------------------------
350  {
351  public:
352 
353  //----------------------------------------------------------------
355  {
356  public:
357  struct span
358  {
359  int32 x;
360  int32 len;
361  };
362 
363  const_iterator() : m_ptr(0) {}
364  const_iterator(const embedded_scanline* sl) :
365  m_ptr(sl->m_ptr),
366  m_dx(sl->m_dx)
367  {
368  m_span.x = read_int32() + m_dx;
369  m_span.len = read_int32();
370  }
371 
372  const span& operator*() const { return m_span; }
373  const span* operator->() const { return &m_span; }
374 
375  void operator ++ ()
376  {
377  m_span.x = read_int32() + m_dx;
378  m_span.len = read_int32();
379  }
380 
381  private:
382  int read_int32()
383  {
384  int32 val;
385  ((int8u*)&val)[0] = *m_ptr++;
386  ((int8u*)&val)[1] = *m_ptr++;
387  ((int8u*)&val)[2] = *m_ptr++;
388  ((int8u*)&val)[3] = *m_ptr++;
389  return val;
390  }
391 
392  const int8u* m_ptr;
393  span m_span;
394  int m_dx;
395  };
396 
397  friend class const_iterator;
398 
399 
400  //----------------------------------------------------------------
401  embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
402 
403  //----------------------------------------------------------------
404  void reset(int, int) {}
405  unsigned num_spans() const { return m_num_spans; }
406  int y() const { return m_y; }
407  const_iterator begin() const { return const_iterator(this); }
408 
409 
410  private:
411  //----------------------------------------------------------------
412  int read_int32()
413  {
414  int32 val;
415  ((int8u*)&val)[0] = *m_ptr++;
416  ((int8u*)&val)[1] = *m_ptr++;
417  ((int8u*)&val)[2] = *m_ptr++;
418  ((int8u*)&val)[3] = *m_ptr++;
419  return val;
420  }
421 
422  public:
423  //----------------------------------------------------------------
424  void init(const int8u* ptr, int dx, int dy)
425  {
426  m_ptr = ptr;
427  m_y = read_int32() + dy;
428  m_num_spans = unsigned(read_int32());
429  m_dx = dx;
430  }
431 
432  private:
433  const int8u* m_ptr;
434  int m_y;
435  unsigned m_num_spans;
436  int m_dx;
437  };
438 
439 
440 
441  public:
442  //--------------------------------------------------------------------
444  m_data(0),
445  m_end(0),
446  m_ptr(0),
447  m_dx(0),
448  m_dy(0),
449  m_min_x(std::numeric_limits<int>::max()),
450  m_min_y(std::numeric_limits<int>::max()),
451  m_max_x(std::numeric_limits<int>::min()),
452  m_max_y(std::numeric_limits<int>::min())
453  {}
454 
455  //--------------------------------------------------------------------
456  serialized_scanlines_adaptor_bin(const int8u* data, unsigned size,
457  double dx, double dy) :
458  m_data(data),
459  m_end(data + size),
460  m_ptr(data),
461  m_dx(iround(dx)),
462  m_dy(iround(dy)),
463  m_min_x(std::numeric_limits<int>::max()),
464  m_min_y(std::numeric_limits<int>::max()),
465  m_max_x(std::numeric_limits<int>::min()),
466  m_max_y(std::numeric_limits<int>::min())
467  {}
468 
469  //--------------------------------------------------------------------
470  void init(const int8u* data, unsigned size, double dx, double dy)
471  {
472  m_data = data;
473  m_end = data + size;
474  m_ptr = data;
475  m_dx = iround(dx);
476  m_dy = iround(dy);
477  m_min_x = std::numeric_limits<int>::max();
478  m_min_y = std::numeric_limits<int>::max();
479  m_max_x = std::numeric_limits<int>::min();
480  m_max_y = std::numeric_limits<int>::min();
481  }
482 
483  private:
484  //--------------------------------------------------------------------
485  int read_int32()
486  {
487  int32 val;
488  ((int8u*)&val)[0] = *m_ptr++;
489  ((int8u*)&val)[1] = *m_ptr++;
490  ((int8u*)&val)[2] = *m_ptr++;
491  ((int8u*)&val)[3] = *m_ptr++;
492  return val;
493  }
494 
495  public:
496  // Iterate scanlines interface
497  //--------------------------------------------------------------------
498  bool rewind_scanlines()
499  {
500  m_ptr = m_data;
501  if(m_ptr < m_end)
502  {
503  m_min_x = read_int32() + m_dx;
504  m_min_y = read_int32() + m_dy;
505  m_max_x = read_int32() + m_dx;
506  m_max_y = read_int32() + m_dy;
507  }
508  return m_ptr < m_end;
509  }
510 
511  //--------------------------------------------------------------------
512  int min_x() const { return m_min_x; }
513  int min_y() const { return m_min_y; }
514  int max_x() const { return m_max_x; }
515  int max_y() const { return m_max_y; }
516 
517  //--------------------------------------------------------------------
518  template<class Scanline> bool sweep_scanline(Scanline& sl)
519  {
520  sl.reset_spans();
521  for(;;)
522  {
523  if(m_ptr >= m_end) return false;
524 
525  int y = read_int32() + m_dy;
526  unsigned num_spans = read_int32();
527 
528  do
529  {
530  int x = read_int32() + m_dx;
531  int len = read_int32();
532 
533  if(len < 0) len = -len;
534  sl.add_span(x, unsigned(len), cover_full);
535  }
536  while(--num_spans);
537 
538  if(sl.num_spans())
539  {
540  sl.finalize(y);
541  break;
542  }
543  }
544  return true;
545  }
546 
547 
548  //--------------------------------------------------------------------
549  // Specialization for embedded_scanline
550  bool sweep_scanline(embedded_scanline& sl)
551  {
552  do
553  {
554  if(m_ptr >= m_end) return false;
555 
556  sl.init(m_ptr, m_dx, m_dy);
557 
558  // Jump to the next scanline
559  //--------------------------
560  read_int32(); // Y
561  int num_spans = read_int32(); // num_spans
562  m_ptr += num_spans * sizeof(int32) * 2;
563  }
564  while(sl.num_spans() == 0);
565  return true;
566  }
567 
568  private:
569  const int8u* m_data;
570  const int8u* m_end;
571  const int8u* m_ptr;
572  int m_dx;
573  int m_dy;
574  int m_min_x;
575  int m_min_y;
576  int m_max_x;
577  int m_max_y;
578  };
579 
580 
581 
582 }
583 
584 #endif
585 
Definition: agg_arc.cpp:24