1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
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 #ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED
17 #define AGG_SCANLINE_STORAGE_AA_INCLUDED
22 #include "agg_array.h"
23 #include "agg_render_scanlines.h"
29 //----------------------------------------------scanline_cell_storage
30 template<class T
> class scanline_cell_storage
41 //---------------------------------------------------------------
42 ~scanline_cell_storage()
47 //---------------------------------------------------------------
48 scanline_cell_storage() :
55 //---------------------------------------------------------------
56 scanline_cell_storage(const scanline_cell_storage
<T
>& v
) :
60 copy_extra_storage(v
);
63 //---------------------------------------------------------------
64 const scanline_cell_storage
<T
>&
65 operator = (const scanline_cell_storage
<T
>& v
)
69 copy_extra_storage(v
);
73 //---------------------------------------------------------------
77 for(i
= m_extra_storage
.size()-1; i
>= 0; --i
)
79 delete [] m_extra_storage
[(unsigned)i
].ptr
;
81 m_extra_storage
.remove_all();
85 //---------------------------------------------------------------
86 int add_cells(const T
* cells
, unsigned num_cells
)
88 int idx
= m_cells
.allocate_continuous_block(num_cells
);
91 T
* ptr
= &m_cells
[idx
];
92 memcpy(ptr
, cells
, sizeof(T
) * num_cells
);
97 s
.ptr
= new T
[num_cells
];
98 memcpy(s
.ptr
, cells
, sizeof(T
) * num_cells
);
99 m_extra_storage
.add(s
);
100 return -int(m_extra_storage
.size());
103 //---------------------------------------------------------------
104 const T
* operator [] (int idx
) const
108 if((unsigned)idx
>= m_cells
.size()) return 0;
109 return &m_cells
[(unsigned)idx
];
111 unsigned i
= unsigned(-idx
- 1);
112 if(i
>= m_extra_storage
.size()) return 0;
113 return m_extra_storage
[i
].ptr
;
116 //---------------------------------------------------------------
117 T
* operator [] (int idx
)
121 if((unsigned)idx
>= m_cells
.size()) return 0;
122 return &m_cells
[(unsigned)idx
];
124 unsigned i
= unsigned(-idx
- 1);
125 if(i
>= m_extra_storage
.size()) return 0;
126 return m_extra_storage
[i
].ptr
;
130 void copy_extra_storage(const scanline_cell_storage
<T
>& v
)
133 for(i
= 0; i
< v
.m_extra_storage
.size(); ++i
)
135 const extra_span
& src
= v
.m_extra_storage
[i
];
138 dst
.ptr
= new T
[dst
.len
];
139 memcpy(dst
.ptr
, src
.ptr
, dst
.len
* sizeof(T
));
140 m_extra_storage
.add(dst
);
144 pod_deque
<T
, 12> m_cells
;
145 pod_deque
<extra_span
, 6> m_extra_storage
;
153 //-----------------------------------------------scanline_storage_aa
154 template<class T
> class scanline_storage_aa
157 typedef T cover_type
;
159 //---------------------------------------------------------------
163 int16 len
; // If negative, it's a solid span, covers is valid
164 int covers_id
; // The index of the cells in the scanline_cell_storage
167 //---------------------------------------------------------------
176 //---------------------------------------------------------------
177 class embedded_scanline
181 //-----------------------------------------------------------
188 int16 len
; // If negative, it's a solid span, covers is valid
192 const_iterator(const embedded_scanline
& sl
) :
193 m_storage(sl
.m_storage
),
194 m_span_idx(sl
.m_scanline
.start_span
)
199 const span
& operator*() const { return m_span
; }
200 const span
* operator->() const { return &m_span
; }
211 const span_data
& s
= m_storage
->span_by_index(m_span_idx
);
214 m_span
.covers
= m_storage
->covers_by_index(s
.covers_id
);
217 const scanline_storage_aa
* m_storage
;
222 friend class const_iterator
;
225 //-----------------------------------------------------------
226 embedded_scanline(const scanline_storage_aa
& storage
) :
232 //-----------------------------------------------------------
233 void reset(int, int) {}
234 unsigned num_spans() const { return m_scanline
.num_spans
; }
235 int y() const { return m_scanline
.y
; }
236 const_iterator
begin() const { return const_iterator(*this); }
238 //-----------------------------------------------------------
239 void init(unsigned scanline_idx
)
241 m_scanline_idx
= scanline_idx
;
242 m_scanline
= m_storage
->scanline_by_index(m_scanline_idx
);
246 const scanline_storage_aa
* m_storage
;
247 scanline_data m_scanline
;
248 unsigned m_scanline_idx
;
252 //---------------------------------------------------------------
253 scanline_storage_aa() :
255 m_spans(256-2), // Block increment size
257 m_min_x( 0x7FFFFFFF),
258 m_min_y( 0x7FFFFFFF),
259 m_max_x(-0x7FFFFFFF),
260 m_max_y(-0x7FFFFFFF),
263 m_fake_scanline
.y
= 0;
264 m_fake_scanline
.num_spans
= 0;
265 m_fake_scanline
.start_span
= 0;
268 m_fake_span
.covers_id
= 0;
271 // Renderer Interface
272 //---------------------------------------------------------------
273 void prepare(unsigned)
275 m_covers
.remove_all();
276 m_scanlines
.remove_all();
277 m_spans
.remove_all();
278 m_min_x
= 0x7FFFFFFF;
279 m_min_y
= 0x7FFFFFFF;
280 m_max_x
= -0x7FFFFFFF;
281 m_max_y
= -0x7FFFFFFF;
285 //---------------------------------------------------------------
286 template<class Scanline
> void render(const Scanline
& sl
)
288 scanline_data sl_this
;
291 if(y
< m_min_y
) m_min_y
= y
;
292 if(y
> m_max_y
) m_max_y
= y
;
295 sl_this
.num_spans
= sl
.num_spans();
296 sl_this
.start_span
= m_spans
.size();
297 typename
Scanline::const_iterator span_iterator
= sl
.begin();
299 unsigned num_spans
= sl_this
.num_spans
;
304 sp
.x
= span_iterator
->x
;
305 sp
.len
= span_iterator
->len
;
306 int len
= abs(int(sp
.len
));
308 m_covers
.add_cells(span_iterator
->covers
,
312 int x2
= sp
.x
+ len
- 1;
313 if(x1
< m_min_x
) m_min_x
= x1
;
314 if(x2
> m_max_x
) m_max_x
= x2
;
318 m_scanlines
.add(sl_this
);
322 //---------------------------------------------------------------
323 // Iterate scanlines interface
324 int min_x() const { return m_min_x
; }
325 int min_y() const { return m_min_y
; }
326 int max_x() const { return m_max_x
; }
327 int max_y() const { return m_max_y
; }
329 //---------------------------------------------------------------
330 bool rewind_scanlines()
333 return m_scanlines
.size() > 0;
337 //---------------------------------------------------------------
338 template<class Scanline
> bool sweep_scanline(Scanline
& sl
)
343 if(m_cur_scanline
>= m_scanlines
.size()) return false;
344 const scanline_data
& sl_this
= m_scanlines
[m_cur_scanline
];
346 unsigned num_spans
= sl_this
.num_spans
;
347 unsigned span_idx
= sl_this
.start_span
;
350 const span_data
& sp
= m_spans
[span_idx
++];
351 const T
* covers
= covers_by_index(sp
.covers_id
);
354 sl
.add_span(sp
.x
, unsigned(-sp
.len
), *covers
);
358 sl
.add_cells(sp
.x
, sp
.len
, covers
);
365 sl
.finalize(sl_this
.y
);
373 //---------------------------------------------------------------
374 // Specialization for embedded_scanline
375 bool sweep_scanline(embedded_scanline
& sl
)
379 if(m_cur_scanline
>= m_scanlines
.size()) return false;
380 sl
.init(m_cur_scanline
);
383 while(sl
.num_spans() == 0);
387 //---------------------------------------------------------------
388 unsigned byte_size() const
391 unsigned size
= sizeof(int16
) * 4; // min_x, min_y, max_x, max_y
393 for(i
= 0; i
< m_scanlines
.size(); ++i
)
395 size
+= sizeof(int16
) * 3; // scanline size in bytes, Y, num_spans
397 const scanline_data
& sl_this
= m_scanlines
[i
];
399 unsigned num_spans
= sl_this
.num_spans
;
400 unsigned span_idx
= sl_this
.start_span
;
403 const span_data
& sp
= m_spans
[span_idx
++];
405 size
+= sizeof(int16
) * 2; // X, span_len
408 size
+= sizeof(T
); // cover
412 size
+= sizeof(T
) * unsigned(sp
.len
); // covers
421 //---------------------------------------------------------------
422 static void write_int16(int8u
* dst
, int16 val
)
424 dst
[0] = ((const int8u
*)&val
)[0];
425 dst
[1] = ((const int8u
*)&val
)[1];
429 //---------------------------------------------------------------
430 void serialize(int8u
* data
) const
434 write_int16(data
, int16u(min_x())); // min_x
435 data
+= sizeof(int16u
);
436 write_int16(data
, int16u(min_y())); // min_y
437 data
+= sizeof(int16u
);
438 write_int16(data
, int16u(max_x())); // max_x
439 data
+= sizeof(int16u
);
440 write_int16(data
, int16u(max_y())); // max_y
441 data
+= sizeof(int16u
);
443 for(i
= 0; i
< m_scanlines
.size(); ++i
)
445 const scanline_data
& sl_this
= m_scanlines
[i
];
447 int8u
* size_ptr
= data
;
448 data
+= sizeof(int16
); // Reserve space for scanline size in bytes
450 write_int16(data
, int16(sl_this
.y
)); // Y
451 data
+= sizeof(int16
);
453 write_int16(data
, int16(sl_this
.num_spans
)); // num_spans
454 data
+= sizeof(int16
);
456 unsigned num_spans
= sl_this
.num_spans
;
457 unsigned span_idx
= sl_this
.start_span
;
460 const span_data
& sp
= m_spans
[span_idx
++];
461 const T
* covers
= covers_by_index(sp
.covers_id
);
463 write_int16(data
, int16(sp
.x
)); // X
464 data
+= sizeof(int16
);
466 write_int16(data
, int16(sp
.len
)); // span_len
467 data
+= sizeof(int16
);
471 memcpy(data
, covers
, sizeof(T
));
476 memcpy(data
, covers
, unsigned(sp
.len
) * sizeof(T
));
477 data
+= sizeof(T
) * unsigned(sp
.len
);
481 write_int16(size_ptr
, int16(unsigned(data
- size_ptr
)));
486 //---------------------------------------------------------------
487 const scanline_data
& scanline_by_index(unsigned i
) const
489 return (i
< m_scanlines
.size()) ? m_scanlines
[i
] : m_fake_scanline
;
492 //---------------------------------------------------------------
493 const span_data
& span_by_index(unsigned i
) const
495 return (i
< m_spans
.size()) ? m_spans
[i
] : m_fake_span
;
498 //---------------------------------------------------------------
499 const T
* covers_by_index(int i
) const
505 scanline_cell_storage
<T
> m_covers
;
506 pod_deque
<span_data
, 10> m_spans
;
507 pod_deque
<scanline_data
, 8> m_scanlines
;
508 span_data m_fake_span
;
509 scanline_data m_fake_scanline
;
514 unsigned m_cur_scanline
;
518 typedef scanline_storage_aa
<int8u
> scanline_storage_aa8
; //--------scanline_storage_aa8
519 typedef scanline_storage_aa
<int16u
> scanline_storage_aa16
; //--------scanline_storage_aa16
520 typedef scanline_storage_aa
<int32u
> scanline_storage_aa32
; //--------scanline_storage_aa32
525 //------------------------------------------serialized_scanlines_adaptor_aa
526 template<class T
> class serialized_scanlines_adaptor_aa
529 typedef T cover_type
;
531 //---------------------------------------------------------------------
532 class embedded_scanline
535 typedef T cover_type
;
537 //-----------------------------------------------------------------
544 int16 len
; // If negative, it's a solid span, "covers" is valid
548 const_iterator(const embedded_scanline
& sl
) :
555 const span
& operator*() const { return m_span
; }
556 const span
* operator->() const { return &m_span
; }
566 m_ptr
+= m_span
.len
* sizeof(T
);
575 ((int8u
*)&val
)[0] = *m_ptr
++;
576 ((int8u
*)&val
)[1] = *m_ptr
++;
582 m_span
.x
= read_int16() + m_dx
;
583 m_span
.len
= read_int16();
584 m_span
.covers
= m_ptr
;
592 friend class const_iterator
;
595 //-----------------------------------------------------------------
596 embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
598 //-----------------------------------------------------------------
599 void reset(int, int) {}
600 unsigned num_spans() const { return m_num_spans
; }
601 int y() const { return m_y
; }
602 const_iterator
begin() const { return const_iterator(*this); }
606 //-----------------------------------------------------------------
610 ((int8u
*)&val
)[0] = *m_ptr
++;
611 ((int8u
*)&val
)[1] = *m_ptr
++;
616 //-----------------------------------------------------------------
617 void init(const int8u
* ptr
, int dx
, int dy
)
620 m_y
= read_int16() + dy
;
621 m_num_spans
= unsigned(read_int16());
628 unsigned m_num_spans
;
635 //--------------------------------------------------------------------
636 serialized_scanlines_adaptor_aa() :
644 m_max_x(-0x7FFFFFFF),
648 //--------------------------------------------------------------------
649 serialized_scanlines_adaptor_aa(const int8u
* data
, unsigned size
,
650 double dx
, double dy
) :
654 m_dx(int(floor(dx
+ 0.5))),
655 m_dy(int(floor(dy
+ 0.5))),
658 m_max_x(-0x7FFFFFFF),
662 //--------------------------------------------------------------------
663 void init(const int8u
* data
, unsigned size
, double dx
, double dy
)
668 m_dx
= int(floor(dx
+ 0.5));
669 m_dy
= int(floor(dy
+ 0.5));
670 m_min_x
= 0x7FFFFFFF;
671 m_min_y
= 0x7FFFFFFF;
672 m_max_x
= -0x7FFFFFFF;
673 m_max_y
= -0x7FFFFFFF;
677 //--------------------------------------------------------------------
681 ((int8u
*)&val
)[0] = *m_ptr
++;
682 ((int8u
*)&val
)[1] = *m_ptr
++;
686 //--------------------------------------------------------------------
687 unsigned read_int16u()
690 ((int8u
*)&val
)[0] = *m_ptr
++;
691 ((int8u
*)&val
)[1] = *m_ptr
++;
696 // Iterate scanlines interface
697 //--------------------------------------------------------------------
698 bool rewind_scanlines()
703 m_min_x
= read_int16() + m_dx
;
704 m_min_y
= read_int16() + m_dy
;
705 m_max_x
= read_int16() + m_dx
;
706 m_max_y
= read_int16() + m_dy
;
712 //--------------------------------------------------------------------
713 int min_x() const { return m_min_x
; }
714 int min_y() const { return m_min_y
; }
715 int max_x() const { return m_max_x
; }
716 int max_y() const { return m_max_y
; }
718 //--------------------------------------------------------------------
719 template<class Scanline
> bool sweep_scanline(Scanline
& sl
)
724 if(m_ptr
>= m_end
) return false;
726 read_int16(); // Skip scanline size in bytes
727 int y
= read_int16() + m_dy
;
728 unsigned num_spans
= read_int16();
732 int x
= read_int16() + m_dx
;
733 int len
= read_int16();
737 sl
.add_span(x
, unsigned(-len
), *m_ptr
);
742 sl
.add_cells(x
, len
, m_ptr
);
743 m_ptr
+= len
* sizeof(T
);
758 //--------------------------------------------------------------------
759 // Specialization for embedded_scanline
760 bool sweep_scanline(embedded_scanline
& sl
)
764 if(m_ptr
>= m_end
) return false;
766 unsigned byte_size
= read_int16u();
767 sl
.init(m_ptr
, m_dx
, m_dy
);
768 m_ptr
+= byte_size
- sizeof(int16
);
770 while(sl
.num_spans() == 0);
788 typedef serialized_scanlines_adaptor_aa
<int8u
> serialized_scanlines_adaptor_aa8
; //----serialized_scanlines_adaptor_aa8
789 typedef serialized_scanlines_adaptor_aa
<int16u
> serialized_scanlines_adaptor_aa16
; //----serialized_scanlines_adaptor_aa16
790 typedef serialized_scanlines_adaptor_aa
<int32u
> serialized_scanlines_adaptor_aa32
; //----serialized_scanlines_adaptor_aa32