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