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#ifndef AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED
16#define AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED
17
18#include "agg_basics.h"
19
20namespace agg
21{
22
23    //=================================================span_subdiv_adaptor
24    template<class Interpolator, unsigned SubpixelShift = 8>
25    class span_subdiv_adaptor
26    {
27    public:
28        typedef Interpolator interpolator_type;
29        typedef typename interpolator_type::trans_type trans_type;
30
31        enum sublixel_scale_e
32        {
33            subpixel_shift = SubpixelShift,
34            subpixel_scale = 1 << subpixel_shift
35        };
36
37
38        //----------------------------------------------------------------
39        span_subdiv_adaptor() :
40            m_subdiv_shift(4),
41            m_subdiv_size(1 << m_subdiv_shift),
42            m_subdiv_mask(m_subdiv_size - 1) {}
43
44        span_subdiv_adaptor(interpolator_type& interpolator,
45                             unsigned subdiv_shift = 4) :
46            m_subdiv_shift(subdiv_shift),
47            m_subdiv_size(1 << m_subdiv_shift),
48            m_subdiv_mask(m_subdiv_size - 1),
49            m_interpolator(&interpolator) {}
50
51        span_subdiv_adaptor(interpolator_type& interpolator,
52                             double x, double y, unsigned len,
53                             unsigned subdiv_shift = 4) :
54            m_subdiv_shift(subdiv_shift),
55            m_subdiv_size(1 << m_subdiv_shift),
56            m_subdiv_mask(m_subdiv_size - 1),
57            m_interpolator(&interpolator)
58        {
59            begin(x, y, len);
60        }
61
62
63        //----------------------------------------------------------------
64        const interpolator_type& interpolator() const { return *m_interpolator; }
65        void interpolator(interpolator_type& intr) { m_interpolator = &intr; }
66
67        //----------------------------------------------------------------
68        const trans_type& transformer() const
69        {
70            return *m_interpolator->transformer();
71        }
72        void transformer(const trans_type& trans)
73        {
74            m_interpolator->transformer(trans);
75        }
76
77        //----------------------------------------------------------------
78        unsigned subdiv_shift() const { return m_subdiv_shift; }
79        void subdiv_shift(unsigned shift)
80        {
81            m_subdiv_shift = shift;
82            m_subdiv_size = 1 << m_subdiv_shift;
83            m_subdiv_mask = m_subdiv_size - 1;
84        }
85
86        //----------------------------------------------------------------
87        void begin(double x, double y, unsigned len)
88        {
89            m_pos   = 1;
90            m_src_x = iround(x * subpixel_scale) + subpixel_scale;
91            m_src_y = y;
92            m_len   = len;
93            if(len > m_subdiv_size) len = m_subdiv_size;
94            m_interpolator->begin(x, y, len);
95        }
96
97        //----------------------------------------------------------------
98        void operator++()
99        {
100            ++(*m_interpolator);
101            if(m_pos >= m_subdiv_size)
102            {
103                unsigned len = m_len;
104                if(len > m_subdiv_size) len = m_subdiv_size;
105                m_interpolator->resynchronize(double(m_src_x) / double(subpixel_scale) + len,
106                                              m_src_y,
107                                              len);
108                m_pos = 0;
109            }
110            m_src_x += subpixel_scale;
111            ++m_pos;
112            --m_len;
113        }
114
115        //----------------------------------------------------------------
116        void coordinates(int* x, int* y) const
117        {
118            m_interpolator->coordinates(x, y);
119        }
120
121        //----------------------------------------------------------------
122        void local_scale(int* x, int* y) const
123        {
124            m_interpolator->local_scale(x, y);
125        }
126
127
128    private:
129        unsigned m_subdiv_shift;
130        unsigned m_subdiv_size;
131        unsigned m_subdiv_mask;
132        interpolator_type* m_interpolator;
133        int      m_src_x;
134        double   m_src_y;
135        unsigned m_pos;
136        unsigned m_len;
137    };
138
139}
140
141#endif
142