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