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#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
17#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
18
19#include "agg_basics.h"
20#include "agg_dda_line.h"
21#include "agg_trans_affine.h"
22
23namespace agg
24{
25
26    //================================================span_interpolator_linear
27    template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
28    class span_interpolator_linear
29    {
30    public:
31        typedef Transformer trans_type;
32
33        enum subpixel_scale_e
34        {
35            subpixel_shift = SubpixelShift,
36            subpixel_scale  = 1 << subpixel_shift
37        };
38
39        //--------------------------------------------------------------------
40        span_interpolator_linear() {}
41        span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {}
42        span_interpolator_linear(const trans_type& trans,
43                                 double x, double y, unsigned len) :
44            m_trans(&trans)
45        {
46            begin(x, y, len);
47        }
48
49        //----------------------------------------------------------------
50        const trans_type& transformer() const { return *m_trans; }
51        void transformer(const trans_type& trans) { m_trans = &trans; }
52
53        //----------------------------------------------------------------
54        void begin(double x, double y, unsigned len)
55        {
56            double tx;
57            double ty;
58
59            tx = x;
60            ty = y;
61            m_trans->transform(&tx, &ty);
62            int x1 = iround(tx * subpixel_scale);
63            int y1 = iround(ty * subpixel_scale);
64
65            tx = x + len;
66            ty = y;
67            m_trans->transform(&tx, &ty);
68            int x2 = iround(tx * subpixel_scale);
69            int y2 = iround(ty * subpixel_scale);
70
71            m_li_x = dda2_line_interpolator(x1, x2, len);
72            m_li_y = dda2_line_interpolator(y1, y2, len);
73        }
74
75        //----------------------------------------------------------------
76        void resynchronize(double xe, double ye, unsigned len)
77        {
78            m_trans->transform(&xe, &ye);
79            m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len);
80            m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len);
81        }
82
83        //----------------------------------------------------------------
84        void operator++()
85        {
86            ++m_li_x;
87            ++m_li_y;
88        }
89
90        //----------------------------------------------------------------
91        void coordinates(int* x, int* y) const
92        {
93            *x = m_li_x.y();
94            *y = m_li_y.y();
95        }
96
97    private:
98        const trans_type* m_trans;
99        dda2_line_interpolator m_li_x;
100        dda2_line_interpolator m_li_y;
101    };
102
103
104
105
106
107
108    //=====================================span_interpolator_linear_subdiv
109    template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
110    class span_interpolator_linear_subdiv
111    {
112    public:
113        typedef Transformer trans_type;
114
115        enum subpixel_scale_e
116        {
117            subpixel_shift = SubpixelShift,
118            subpixel_scale = 1 << subpixel_shift
119        };
120
121
122        //----------------------------------------------------------------
123        span_interpolator_linear_subdiv() :
124            m_subdiv_shift(4),
125            m_subdiv_size(1 << m_subdiv_shift),
126            m_subdiv_mask(m_subdiv_size - 1) {}
127
128        span_interpolator_linear_subdiv(const trans_type& trans,
129                                        unsigned subdiv_shift = 4) :
130            m_subdiv_shift(subdiv_shift),
131            m_subdiv_size(1 << m_subdiv_shift),
132            m_subdiv_mask(m_subdiv_size - 1),
133            m_trans(&trans) {}
134
135        span_interpolator_linear_subdiv(const trans_type& trans,
136                                        double x, double y, unsigned len,
137                                        unsigned subdiv_shift = 4) :
138            m_subdiv_shift(subdiv_shift),
139            m_subdiv_size(1 << m_subdiv_shift),
140            m_subdiv_mask(m_subdiv_size - 1),
141            m_trans(&trans)
142        {
143            begin(x, y, len);
144        }
145
146        //----------------------------------------------------------------
147        const trans_type& transformer() const { return *m_trans; }
148        void transformer(const trans_type& trans) { m_trans = &trans; }
149
150        //----------------------------------------------------------------
151        unsigned subdiv_shift() const { return m_subdiv_shift; }
152        void subdiv_shift(unsigned shift)
153        {
154            m_subdiv_shift = shift;
155            m_subdiv_size = 1 << m_subdiv_shift;
156            m_subdiv_mask = m_subdiv_size - 1;
157        }
158
159        //----------------------------------------------------------------
160        void begin(double x, double y, unsigned len)
161        {
162            double tx;
163            double ty;
164            m_pos   = 1;
165            m_src_x = iround(x * subpixel_scale) + subpixel_scale;
166            m_src_y = y;
167            m_len   = len;
168
169            if(len > m_subdiv_size) len = m_subdiv_size;
170            tx = x;
171            ty = y;
172            m_trans->transform(&tx, &ty);
173            int x1 = iround(tx * subpixel_scale);
174            int y1 = iround(ty * subpixel_scale);
175
176            tx = x + len;
177            ty = y;
178            m_trans->transform(&tx, &ty);
179
180            m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len);
181            m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len);
182        }
183
184        //----------------------------------------------------------------
185        void operator++()
186        {
187            ++m_li_x;
188            ++m_li_y;
189            if(m_pos >= m_subdiv_size)
190            {
191                unsigned len = m_len;
192                if(len > m_subdiv_size) len = m_subdiv_size;
193                double tx = double(m_src_x) / double(subpixel_scale) + len;
194                double ty = m_src_y;
195                m_trans->transform(&tx, &ty);
196                m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len);
197                m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len);
198                m_pos = 0;
199            }
200            m_src_x += subpixel_scale;
201            ++m_pos;
202            --m_len;
203        }
204
205        //----------------------------------------------------------------
206        void coordinates(int* x, int* y) const
207        {
208            *x = m_li_x.y();
209            *y = m_li_y.y();
210        }
211
212    private:
213        unsigned m_subdiv_shift;
214        unsigned m_subdiv_size;
215        unsigned m_subdiv_mask;
216        const trans_type* m_trans;
217        dda2_line_interpolator m_li_x;
218        dda2_line_interpolator m_li_y;
219        int      m_src_x;
220        double   m_src_y;
221        unsigned m_pos;
222        unsigned m_len;
223    };
224
225
226}
227
228
229
230#endif
231
232
233