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
34namespace 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