1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
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 // Adaptation for 32-bit screen coordinates 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.
22 //----------------------------------------------------------------------------
24 #ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED
25 #define AGG_SCANLINE_STORAGE_AA_INCLUDED
30 #include "agg_array.h"
36 //----------------------------------------------scanline_cell_storage
37 template<class T
> class scanline_cell_storage
48 //---------------------------------------------------------------
49 ~scanline_cell_storage()
54 //---------------------------------------------------------------
55 scanline_cell_storage() :
62 //---------------------------------------------------------------
63 scanline_cell_storage(const scanline_cell_storage
<T
>& v
) :
67 copy_extra_storage(v
);
70 //---------------------------------------------------------------
71 const scanline_cell_storage
<T
>&
72 operator = (const scanline_cell_storage
<T
>& v
)
76 copy_extra_storage(v
);
80 //---------------------------------------------------------------
84 for(i
= m_extra_storage
.size()-1; i
>= 0; --i
)
86 pod_allocator
<T
>::deallocate(m_extra_storage
[i
].ptr
,
87 m_extra_storage
[i
].len
);
89 m_extra_storage
.remove_all();
93 //---------------------------------------------------------------
94 int add_cells(const T
* cells
, unsigned num_cells
)
96 int idx
= m_cells
.allocate_continuous_block(num_cells
);
99 T
* ptr
= &m_cells
[idx
];
100 memcpy(ptr
, cells
, sizeof(T
) * num_cells
);
105 s
.ptr
= pod_allocator
<T
>::allocate(num_cells
);
106 memcpy(s
.ptr
, cells
, sizeof(T
) * num_cells
);
107 m_extra_storage
.add(s
);
108 return -int(m_extra_storage
.size());
111 //---------------------------------------------------------------
112 const T
* operator [] (int idx
) const
116 if((unsigned)idx
>= m_cells
.size()) return 0;
117 return &m_cells
[(unsigned)idx
];
119 unsigned i
= unsigned(-idx
- 1);
120 if(i
>= m_extra_storage
.size()) return 0;
121 return m_extra_storage
[i
].ptr
;
124 //---------------------------------------------------------------
125 T
* operator [] (int idx
)
129 if((unsigned)idx
>= m_cells
.size()) return 0;
130 return &m_cells
[(unsigned)idx
];
132 unsigned i
= unsigned(-idx
- 1);
133 if(i
>= m_extra_storage
.size()) return 0;
134 return m_extra_storage
[i
].ptr
;
138 void copy_extra_storage(const scanline_cell_storage
<T
>& v
)
141 for(i
= 0; i
< v
.m_extra_storage
.size(); ++i
)
143 const extra_span
& src
= v
.m_extra_storage
[i
];
146 dst
.ptr
= pod_allocator
<T
>::allocate(dst
.len
);
147 memcpy(dst
.ptr
, src
.ptr
, dst
.len
* sizeof(T
));
148 m_extra_storage
.add(dst
);
152 pod_bvector
<T
, 12> m_cells
;
153 pod_bvector
<extra_span
, 6> m_extra_storage
;
161 //-----------------------------------------------scanline_storage_aa
162 template<class T
> class scanline_storage_aa
165 typedef T cover_type
;
167 //---------------------------------------------------------------
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
175 //---------------------------------------------------------------
184 //---------------------------------------------------------------
185 class embedded_scanline
189 //-----------------------------------------------------------
196 int32 len
; // If negative, it's a solid span, covers is valid
200 const_iterator() : m_storage(0) {}
201 const_iterator(const embedded_scanline
& sl
) :
202 m_storage(sl
.m_storage
),
203 m_span_idx(sl
.m_scanline
.start_span
)
208 const span
& operator*() const { return m_span
; }
209 const span
* operator->() const { return &m_span
; }
220 const span_data
& s
= m_storage
->span_by_index(m_span_idx
);
223 m_span
.covers
= m_storage
->covers_by_index(s
.covers_id
);
226 const scanline_storage_aa
* m_storage
;
231 friend class const_iterator
;
234 //-----------------------------------------------------------
235 embedded_scanline(const scanline_storage_aa
& storage
) :
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); }
247 //-----------------------------------------------------------
248 void init(unsigned scanline_idx
)
250 m_scanline_idx
= scanline_idx
;
251 m_scanline
= m_storage
->scanline_by_index(m_scanline_idx
);
255 const scanline_storage_aa
* m_storage
;
256 scanline_data m_scanline
;
257 unsigned m_scanline_idx
;
261 //---------------------------------------------------------------
262 scanline_storage_aa() :
264 m_spans(256-2), // Block increment size
266 m_min_x( 0x7FFFFFFF),
267 m_min_y( 0x7FFFFFFF),
268 m_max_x(-0x7FFFFFFF),
269 m_max_y(-0x7FFFFFFF),
272 m_fake_scanline
.y
= 0;
273 m_fake_scanline
.num_spans
= 0;
274 m_fake_scanline
.start_span
= 0;
277 m_fake_span
.covers_id
= 0;
280 // Renderer Interface
281 //---------------------------------------------------------------
284 m_covers
.remove_all();
285 m_scanlines
.remove_all();
286 m_spans
.remove_all();
287 m_min_x
= 0x7FFFFFFF;
288 m_min_y
= 0x7FFFFFFF;
289 m_max_x
= -0x7FFFFFFF;
290 m_max_y
= -0x7FFFFFFF;
294 //---------------------------------------------------------------
295 template<class Scanline
> void render(const Scanline
& sl
)
297 scanline_data sl_this
;
300 if(y
< m_min_y
) m_min_y
= y
;
301 if(y
> m_max_y
) m_max_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();
308 unsigned num_spans
= sl_this
.num_spans
;
313 sp
.x
= span_iterator
->x
;
314 sp
.len
= span_iterator
->len
;
315 int len
= abs(int(sp
.len
));
317 m_covers
.add_cells(span_iterator
->covers
,
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;
327 m_scanlines
.add(sl_this
);
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
; }
338 //---------------------------------------------------------------
339 bool rewind_scanlines()
342 return m_scanlines
.size() > 0;
346 //---------------------------------------------------------------
347 template<class Scanline
> bool sweep_scanline(Scanline
& sl
)
352 if(m_cur_scanline
>= m_scanlines
.size()) return false;
353 const scanline_data
& sl_this
= m_scanlines
[m_cur_scanline
];
355 unsigned num_spans
= sl_this
.num_spans
;
356 unsigned span_idx
= sl_this
.start_span
;
359 const span_data
& sp
= m_spans
[span_idx
++];
360 const T
* covers
= covers_by_index(sp
.covers_id
);
363 sl
.add_span(sp
.x
, unsigned(-sp
.len
), *covers
);
367 sl
.add_cells(sp
.x
, sp
.len
, covers
);
374 sl
.finalize(sl_this
.y
);
382 //---------------------------------------------------------------
383 // Specialization for embedded_scanline
384 bool sweep_scanline(embedded_scanline
& sl
)
388 if(m_cur_scanline
>= m_scanlines
.size()) return false;
389 sl
.init(m_cur_scanline
);
392 while(sl
.num_spans() == 0);
396 //---------------------------------------------------------------
397 unsigned byte_size() const
400 unsigned size
= sizeof(int32
) * 4; // min_x, min_y, max_x, max_y
402 for(i
= 0; i
< m_scanlines
.size(); ++i
)
404 size
+= sizeof(int32
) * 3; // scanline size in bytes, Y, num_spans
406 const scanline_data
& sl_this
= m_scanlines
[i
];
408 unsigned num_spans
= sl_this
.num_spans
;
409 unsigned span_idx
= sl_this
.start_span
;
412 const span_data
& sp
= m_spans
[span_idx
++];
414 size
+= sizeof(int32
) * 2; // X, span_len
417 size
+= sizeof(T
); // cover
421 size
+= sizeof(T
) * unsigned(sp
.len
); // covers
430 //---------------------------------------------------------------
431 static void write_int32(int8u
* dst
, int32 val
)
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];
440 //---------------------------------------------------------------
441 void serialize(int8u
* data
) const
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
);
454 for(i
= 0; i
< m_scanlines
.size(); ++i
)
456 const scanline_data
& sl_this
= m_scanlines
[i
];
458 int8u
* size_ptr
= data
;
459 data
+= sizeof(int32
); // Reserve space for scanline size in bytes
461 write_int32(data
, sl_this
.y
); // Y
462 data
+= sizeof(int32
);
464 write_int32(data
, sl_this
.num_spans
); // num_spans
465 data
+= sizeof(int32
);
467 unsigned num_spans
= sl_this
.num_spans
;
468 unsigned span_idx
= sl_this
.start_span
;
471 const span_data
& sp
= m_spans
[span_idx
++];
472 const T
* covers
= covers_by_index(sp
.covers_id
);
474 write_int32(data
, sp
.x
); // X
475 data
+= sizeof(int32
);
477 write_int32(data
, sp
.len
); // span_len
478 data
+= sizeof(int32
);
482 memcpy(data
, covers
, sizeof(T
));
487 memcpy(data
, covers
, unsigned(sp
.len
) * sizeof(T
));
488 data
+= sizeof(T
) * unsigned(sp
.len
);
492 write_int32(size_ptr
, int32(unsigned(data
- size_ptr
)));
497 //---------------------------------------------------------------
498 const scanline_data
& scanline_by_index(unsigned i
) const
500 return (i
< m_scanlines
.size()) ? m_scanlines
[i
] : m_fake_scanline
;
503 //---------------------------------------------------------------
504 const span_data
& span_by_index(unsigned i
) const
506 return (i
< m_spans
.size()) ? m_spans
[i
] : m_fake_span
;
509 //---------------------------------------------------------------
510 const T
* covers_by_index(int i
) const
516 scanline_cell_storage
<T
> m_covers
;
517 pod_bvector
<span_data
, 10> m_spans
;
518 pod_bvector
<scanline_data
, 8> m_scanlines
;
519 span_data m_fake_span
;
520 scanline_data m_fake_scanline
;
525 unsigned m_cur_scanline
;
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
536 //------------------------------------------serialized_scanlines_adaptor_aa
537 template<class T
> class serialized_scanlines_adaptor_aa
540 typedef T cover_type
;
542 //---------------------------------------------------------------------
543 class embedded_scanline
546 typedef T cover_type
;
548 //-----------------------------------------------------------------
555 int32 len
; // If negative, it's a solid span, "covers" is valid
559 const_iterator() : m_ptr(0) {}
560 const_iterator(const embedded_scanline
& sl
) :
567 const span
& operator*() const { return m_span
; }
568 const span
* operator->() const { return &m_span
; }
578 m_ptr
+= m_span
.len
* sizeof(T
);
587 ((int8u
*)&val
)[0] = *m_ptr
++;
588 ((int8u
*)&val
)[1] = *m_ptr
++;
589 ((int8u
*)&val
)[2] = *m_ptr
++;
590 ((int8u
*)&val
)[3] = *m_ptr
++;
596 m_span
.x
= read_int32() + m_dx
;
597 m_span
.len
= read_int32();
598 m_span
.covers
= m_ptr
;
606 friend class const_iterator
;
609 //-----------------------------------------------------------------
610 embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
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); }
620 //-----------------------------------------------------------------
624 ((int8u
*)&val
)[0] = *m_ptr
++;
625 ((int8u
*)&val
)[1] = *m_ptr
++;
626 ((int8u
*)&val
)[2] = *m_ptr
++;
627 ((int8u
*)&val
)[3] = *m_ptr
++;
632 //-----------------------------------------------------------------
633 void init(const int8u
* ptr
, int dx
, int dy
)
636 m_y
= read_int32() + dy
;
637 m_num_spans
= unsigned(read_int32());
644 unsigned m_num_spans
;
651 //--------------------------------------------------------------------
652 serialized_scanlines_adaptor_aa() :
660 m_max_x(-0x7FFFFFFF),
664 //--------------------------------------------------------------------
665 serialized_scanlines_adaptor_aa(const int8u
* data
, unsigned size
,
666 double dx
, double dy
) :
674 m_max_x(-0x7FFFFFFF),
678 //--------------------------------------------------------------------
679 void init(const int8u
* data
, unsigned size
, double dx
, double dy
)
686 m_min_x
= 0x7FFFFFFF;
687 m_min_y
= 0x7FFFFFFF;
688 m_max_x
= -0x7FFFFFFF;
689 m_max_y
= -0x7FFFFFFF;
693 //--------------------------------------------------------------------
697 ((int8u
*)&val
)[0] = *m_ptr
++;
698 ((int8u
*)&val
)[1] = *m_ptr
++;
699 ((int8u
*)&val
)[2] = *m_ptr
++;
700 ((int8u
*)&val
)[3] = *m_ptr
++;
704 //--------------------------------------------------------------------
705 unsigned read_int32u()
708 ((int8u
*)&val
)[0] = *m_ptr
++;
709 ((int8u
*)&val
)[1] = *m_ptr
++;
710 ((int8u
*)&val
)[2] = *m_ptr
++;
711 ((int8u
*)&val
)[3] = *m_ptr
++;
716 // Iterate scanlines interface
717 //--------------------------------------------------------------------
718 bool rewind_scanlines()
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
;
728 return m_ptr
< m_end
;
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
; }
737 //--------------------------------------------------------------------
738 template<class Scanline
> bool sweep_scanline(Scanline
& sl
)
743 if(m_ptr
>= m_end
) return false;
745 read_int32(); // Skip scanline size in bytes
746 int y
= read_int32() + m_dy
;
747 unsigned num_spans
= read_int32();
751 int x
= read_int32() + m_dx
;
752 int len
= read_int32();
756 sl
.add_span(x
, unsigned(-len
), *m_ptr
);
761 sl
.add_cells(x
, len
, m_ptr
);
762 m_ptr
+= len
* sizeof(T
);
777 //--------------------------------------------------------------------
778 // Specialization for embedded_scanline
779 bool sweep_scanline(embedded_scanline
& sl
)
783 if(m_ptr
>= m_end
) return false;
785 unsigned byte_size
= read_int32u();
786 sl
.init(m_ptr
, m_dx
, m_dy
);
787 m_ptr
+= byte_size
- sizeof(int32
);
789 while(sl
.num_spans() == 0);
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