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_BIN_INCLUDED
17 #define AGG_SCANLINE_STORAGE_BIN_INCLUDED
22 #include "agg_array.h"
23 #include "agg_render_scanlines.h"
29 //-----------------------------------------------scanline_storage_bin
30 class scanline_storage_bin
33 //---------------------------------------------------------------
40 //---------------------------------------------------------------
49 //---------------------------------------------------------------
50 class embedded_scanline
54 //-----------------------------------------------------------
58 const_iterator(const embedded_scanline
& sl
) :
59 m_storage(sl
.m_storage
),
60 m_span_idx(sl
.m_scanline
.start_span
)
62 m_span
= m_storage
->span_by_index(m_span_idx
);
65 const span_data
& operator*() const { return m_span
; }
66 const span_data
* operator->() const { return &m_span
; }
71 m_span
= m_storage
->span_by_index(m_span_idx
);
75 const scanline_storage_bin
* m_storage
;
80 friend class const_iterator
;
83 //-----------------------------------------------------------
84 embedded_scanline(const scanline_storage_bin
& storage
) :
90 //-----------------------------------------------------------
91 void reset(int, int) {}
92 unsigned num_spans() const { return m_scanline
.num_spans
; }
93 int y() const { return m_scanline
.y
; }
94 const_iterator
begin() const { return const_iterator(*this); }
96 //-----------------------------------------------------------
97 void setup(unsigned scanline_idx
)
99 m_scanline_idx
= scanline_idx
;
100 m_scanline
= m_storage
->scanline_by_index(m_scanline_idx
);
104 const scanline_storage_bin
* m_storage
;
105 scanline_data m_scanline
;
106 unsigned m_scanline_idx
;
110 //---------------------------------------------------------------
111 scanline_storage_bin() :
112 m_spans(256-2), // Block increment size
114 m_min_x( 0x7FFFFFFF),
115 m_min_y( 0x7FFFFFFF),
116 m_max_x(-0x7FFFFFFF),
117 m_max_y(-0x7FFFFFFF),
120 m_fake_scanline
.y
= 0;
121 m_fake_scanline
.num_spans
= 0;
122 m_fake_scanline
.start_span
= 0;
127 // Renderer Interface
128 //---------------------------------------------------------------
129 void prepare(unsigned)
131 m_scanlines
.remove_all();
132 m_spans
.remove_all();
133 m_min_x
= 0x7FFFFFFF;
134 m_min_y
= 0x7FFFFFFF;
135 m_max_x
= -0x7FFFFFFF;
136 m_max_y
= -0x7FFFFFFF;
140 //---------------------------------------------------------------
141 template<class Scanline
> void render(const Scanline
& sl
)
143 scanline_data sl_this
;
146 if(y
< m_min_y
) m_min_y
= y
;
147 if(y
> m_max_y
) m_max_y
= y
;
150 sl_this
.num_spans
= sl
.num_spans();
151 sl_this
.start_span
= m_spans
.size();
152 typename
Scanline::const_iterator span_iterator
= sl
.begin();
154 unsigned num_spans
= sl_this
.num_spans
;
158 sp
.x
= span_iterator
->x
;
159 sp
.len
= (int16
)abs((int)(span_iterator
->len
));
162 int x2
= sp
.x
+ sp
.len
- 1;
163 if(x1
< m_min_x
) m_min_x
= x1
;
164 if(x2
> m_max_x
) m_max_x
= x2
;
168 m_scanlines
.add(sl_this
);
172 //---------------------------------------------------------------
173 // Iterate scanlines interface
174 int min_x() const { return m_min_x
; }
175 int min_y() const { return m_min_y
; }
176 int max_x() const { return m_max_x
; }
177 int max_y() const { return m_max_y
; }
179 //---------------------------------------------------------------
180 bool rewind_scanlines()
183 return m_scanlines
.size() > 0;
187 //---------------------------------------------------------------
188 template<class Scanline
> bool sweep_scanline(Scanline
& sl
)
193 if(m_cur_scanline
>= m_scanlines
.size()) return false;
194 const scanline_data
& sl_this
= m_scanlines
[m_cur_scanline
];
196 unsigned num_spans
= sl_this
.num_spans
;
197 unsigned span_idx
= sl_this
.start_span
;
200 const span_data
& sp
= m_spans
[span_idx
++];
201 sl
.add_span(sp
.x
, sp
.len
, cover_full
);
208 sl
.finalize(sl_this
.y
);
216 //---------------------------------------------------------------
217 // Specialization for embedded_scanline
218 bool sweep_scanline(embedded_scanline
& sl
)
222 if(m_cur_scanline
>= m_scanlines
.size()) return false;
223 sl
.setup(m_cur_scanline
);
226 while(sl
.num_spans() == 0);
231 //---------------------------------------------------------------
232 unsigned byte_size() const
235 unsigned size
= sizeof(int16
) * 4; // min_x, min_y, max_x, max_y
237 for(i
= 0; i
< m_scanlines
.size(); ++i
)
239 size
+= sizeof(int16
) * 2 + // Y, num_spans
240 unsigned(m_scanlines
[i
].num_spans
) * sizeof(int16
) * 2; // X, span_len
246 //---------------------------------------------------------------
247 static void write_int16(int8u
* dst
, int16 val
)
249 dst
[0] = ((const int8u
*)&val
)[0];
250 dst
[1] = ((const int8u
*)&val
)[1];
254 //---------------------------------------------------------------
255 void serialize(int8u
* data
) const
259 write_int16(data
, int16u(min_x())); // min_x
260 data
+= sizeof(int16u
);
261 write_int16(data
, int16u(min_y())); // min_y
262 data
+= sizeof(int16u
);
263 write_int16(data
, int16u(max_x())); // max_x
264 data
+= sizeof(int16u
);
265 write_int16(data
, int16u(max_y())); // max_y
266 data
+= sizeof(int16u
);
268 for(i
= 0; i
< m_scanlines
.size(); ++i
)
270 const scanline_data
& sl_this
= m_scanlines
[i
];
272 write_int16(data
, int16(sl_this
.y
)); // Y
273 data
+= sizeof(int16
);
275 write_int16(data
, int16(sl_this
.num_spans
)); // num_spans
276 data
+= sizeof(int16
);
278 unsigned num_spans
= sl_this
.num_spans
;
279 unsigned span_idx
= sl_this
.start_span
;
282 const span_data
& sp
= m_spans
[span_idx
++];
284 write_int16(data
, int16(sp
.x
)); // X
285 data
+= sizeof(int16
);
287 write_int16(data
, int16(sp
.len
)); // len
288 data
+= sizeof(int16
);
295 //---------------------------------------------------------------
296 const scanline_data
& scanline_by_index(unsigned i
) const
298 return (i
< m_scanlines
.size()) ? m_scanlines
[i
] : m_fake_scanline
;
301 //---------------------------------------------------------------
302 const span_data
& span_by_index(unsigned i
) const
304 return (i
< m_spans
.size()) ? m_spans
[i
] : m_fake_span
;
309 pod_deque
<span_data
, 10> m_spans
;
310 pod_deque
<scanline_data
, 8> m_scanlines
;
311 span_data m_fake_span
;
312 scanline_data m_fake_scanline
;
317 unsigned m_cur_scanline
;
332 //---------------------------------------serialized_scanlines_adaptor_bin
333 class serialized_scanlines_adaptor_bin
336 typedef bool cover_type
;
338 //--------------------------------------------------------------------
339 class embedded_scanline
343 //----------------------------------------------------------------
353 const_iterator(const embedded_scanline
& sl
) :
357 m_span
.x
= read_int16() + m_dx
;
358 m_span
.len
= read_int16();
361 const span
& operator*() const { return m_span
; }
362 const span
* operator->() const { return &m_span
; }
366 m_span
.x
= read_int16() + m_dx
;
367 m_span
.len
= read_int16();
374 ((int8u
*)&val
)[0] = *m_ptr
++;
375 ((int8u
*)&val
)[1] = *m_ptr
++;
384 friend class const_iterator
;
387 //----------------------------------------------------------------
388 embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
390 //----------------------------------------------------------------
391 void reset(int, int) {}
392 unsigned num_spans() const { return m_num_spans
; }
393 int y() const { return m_y
; }
394 const_iterator
begin() const { return const_iterator(*this); }
398 //----------------------------------------------------------------
402 ((int8u
*)&val
)[0] = *m_ptr
++;
403 ((int8u
*)&val
)[1] = *m_ptr
++;
408 //----------------------------------------------------------------
409 void init(const int8u
* ptr
, int dx
, int dy
)
412 m_y
= read_int16() + dy
;
413 m_num_spans
= unsigned(read_int16());
420 unsigned m_num_spans
;
427 //--------------------------------------------------------------------
428 serialized_scanlines_adaptor_bin() :
436 m_max_x(-0x7FFFFFFF),
440 //--------------------------------------------------------------------
441 serialized_scanlines_adaptor_bin(const int8u
* data
, unsigned size
,
442 double dx
, double dy
) :
446 m_dx(int(floor(dx
+ 0.5))),
447 m_dy(int(floor(dy
+ 0.5))),
450 m_max_x(-0x7FFFFFFF),
454 //--------------------------------------------------------------------
455 void init(const int8u
* data
, unsigned size
, double dx
, double dy
)
460 m_dx
= int(floor(dx
+ 0.5));
461 m_dy
= int(floor(dy
+ 0.5));
462 m_min_x
= 0x7FFFFFFF;
463 m_min_y
= 0x7FFFFFFF;
464 m_max_x
= -0x7FFFFFFF;
465 m_max_y
= -0x7FFFFFFF;
469 //--------------------------------------------------------------------
473 ((int8u
*)&val
)[0] = *m_ptr
++;
474 ((int8u
*)&val
)[1] = *m_ptr
++;
479 // Iterate scanlines interface
480 //--------------------------------------------------------------------
481 bool rewind_scanlines()
486 m_min_x
= read_int16() + m_dx
;
487 m_min_y
= read_int16() + m_dy
;
488 m_max_x
= read_int16() + m_dx
;
489 m_max_y
= read_int16() + m_dy
;
495 //--------------------------------------------------------------------
496 int min_x() const { return m_min_x
; }
497 int min_y() const { return m_min_y
; }
498 int max_x() const { return m_max_x
; }
499 int max_y() const { return m_max_y
; }
501 //--------------------------------------------------------------------
502 template<class Scanline
> bool sweep_scanline(Scanline
& sl
)
507 if(m_ptr
>= m_end
) return false;
509 int y
= read_int16() + m_dy
;
510 unsigned num_spans
= read_int16();
514 int x
= read_int16() + m_dx
;
515 int len
= read_int16();
517 if(len
< 0) len
= -len
;
518 sl
.add_span(x
, unsigned(len
), cover_full
);
532 //--------------------------------------------------------------------
533 // Specialization for embedded_scanline
534 bool sweep_scanline(embedded_scanline
& sl
)
538 if(m_ptr
>= m_end
) return false;
540 sl
.init(m_ptr
, m_dx
, m_dy
);
542 // Jump to the next scanline
543 //--------------------------
545 int num_spans
= read_int16(); // num_spans
546 m_ptr
+= num_spans
* sizeof(int16
) * 2;
548 while(sl
.num_spans() == 0);