1226584Sdim//----------------------------------------------------------------------------
2226584Sdim// Anti-Grain Geometry - Version 2.4
3226584Sdim// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4226584Sdim//
5226584Sdim// Permission to copy, use, modify, sell and distribute this software
6226584Sdim// is granted provided this copyright notice appears in all copies.
7226584Sdim// This software is provided "as is" without express or implied
8226584Sdim// warranty, and with no claim as to its suitability for any purpose.
9226584Sdim//
10226584Sdim//----------------------------------------------------------------------------
11226584Sdim// Contact: mcseem@antigrain.com
12226584Sdim//          mcseemagg@yahoo.com
13226584Sdim//          http://www.antigrain.com
14226584Sdim//----------------------------------------------------------------------------
15226584Sdim
16226584Sdim#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
17226584Sdim#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
18226584Sdim
19226584Sdim#include "agg_basics.h"
20226584Sdim#include "agg_dda_line.h"
21226584Sdim#include "agg_trans_affine.h"
22226584Sdim
23226584Sdimnamespace agg
24249423Sdim{
25226584Sdim
26226584Sdim    //================================================span_interpolator_linear
27226584Sdim    template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
28226584Sdim    class span_interpolator_linear
29226584Sdim    {
30226584Sdim    public:
31226584Sdim        typedef Transformer trans_type;
32226584Sdim
33226584Sdim        enum subpixel_scale_e
34226584Sdim        {
35226584Sdim            subpixel_shift = SubpixelShift,
36226584Sdim            subpixel_scale  = 1 << subpixel_shift
37226584Sdim        };
38226584Sdim
39226584Sdim        //--------------------------------------------------------------------
40226584Sdim        span_interpolator_linear() {}
41226584Sdim        span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {}
42226584Sdim        span_interpolator_linear(const trans_type& trans,
43226584Sdim                                 double x, double y, unsigned len) :
44226584Sdim            m_trans(&trans)
45226584Sdim        {
46226584Sdim            begin(x, y, len);
47226584Sdim        }
48226584Sdim
49226584Sdim        //----------------------------------------------------------------
50226584Sdim        const trans_type& transformer() const { return *m_trans; }
51226584Sdim        void transformer(const trans_type& trans) { m_trans = &trans; }
52226584Sdim
53226584Sdim        //----------------------------------------------------------------
54226584Sdim        void begin(double x, double y, unsigned len)
55226584Sdim        {
56226584Sdim            double tx;
57226584Sdim            double ty;
58226584Sdim
59226584Sdim            tx = x;
60226584Sdim            ty = y;
61226584Sdim            m_trans->transform(&tx, &ty);
62226584Sdim            int x1 = iround(tx * subpixel_scale);
63226584Sdim            int y1 = iround(ty * subpixel_scale);
64226584Sdim
65226584Sdim            tx = x + len;
66226584Sdim            ty = y;
67226584Sdim            m_trans->transform(&tx, &ty);
68226584Sdim            int x2 = iround(tx * subpixel_scale);
69226584Sdim            int y2 = iround(ty * subpixel_scale);
70226584Sdim
71226584Sdim            m_li_x = dda2_line_interpolator(x1, x2, len);
72226584Sdim            m_li_y = dda2_line_interpolator(y1, y2, len);
73226584Sdim        }
74226584Sdim
75226584Sdim        //----------------------------------------------------------------
76226584Sdim        void resynchronize(double xe, double ye, unsigned len)
77226584Sdim        {
78226584Sdim            m_trans->transform(&xe, &ye);
79226584Sdim            m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len);
80226584Sdim            m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len);
81226584Sdim        }
82226584Sdim
83226584Sdim        //----------------------------------------------------------------
84226584Sdim        void operator++()
85226584Sdim        {
86226584Sdim            ++m_li_x;
87226584Sdim            ++m_li_y;
88226584Sdim        }
89226584Sdim
90226584Sdim        //----------------------------------------------------------------
91226584Sdim        void coordinates(int* x, int* y) const
92226584Sdim        {
93226584Sdim            *x = m_li_x.y();
94226584Sdim            *y = m_li_y.y();
95226584Sdim        }
96226584Sdim
97226584Sdim    private:
98226584Sdim        const trans_type* m_trans;
99226584Sdim        dda2_line_interpolator m_li_x;
100226584Sdim        dda2_line_interpolator m_li_y;
101226584Sdim    };
102226584Sdim
103226584Sdim
104226584Sdim
105226584Sdim
106226584Sdim
107226584Sdim
108226584Sdim    //=====================================span_interpolator_linear_subdiv
109226584Sdim    template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
110226584Sdim    class span_interpolator_linear_subdiv
111226584Sdim    {
112226584Sdim    public:
113226584Sdim        typedef Transformer trans_type;
114226584Sdim
115226584Sdim        enum subpixel_scale_e
116226584Sdim        {
117226584Sdim            subpixel_shift = SubpixelShift,
118226584Sdim            subpixel_scale = 1 << subpixel_shift
119226584Sdim        };
120226584Sdim
121226584Sdim
122226584Sdim        //----------------------------------------------------------------
123226584Sdim        span_interpolator_linear_subdiv() :
124226584Sdim            m_subdiv_shift(4),
125226584Sdim            m_subdiv_size(1 << m_subdiv_shift),
126226584Sdim            m_subdiv_mask(m_subdiv_size - 1) {}
127226584Sdim
128226584Sdim        span_interpolator_linear_subdiv(const trans_type& trans,
129226584Sdim                                        unsigned subdiv_shift = 4) :
130226584Sdim            m_subdiv_shift(subdiv_shift),
131226584Sdim            m_subdiv_size(1 << m_subdiv_shift),
132226584Sdim            m_subdiv_mask(m_subdiv_size - 1),
133226584Sdim            m_trans(&trans) {}
134226584Sdim
135226584Sdim        span_interpolator_linear_subdiv(const trans_type& trans,
136226584Sdim                                        double x, double y, unsigned len,
137226584Sdim                                        unsigned subdiv_shift = 4) :
138226584Sdim            m_subdiv_shift(subdiv_shift),
139226584Sdim            m_subdiv_size(1 << m_subdiv_shift),
140226584Sdim            m_subdiv_mask(m_subdiv_size - 1),
141226584Sdim            m_trans(&trans)
142226584Sdim        {
143226584Sdim            begin(x, y, len);
144226584Sdim        }
145226584Sdim
146226584Sdim        //----------------------------------------------------------------
147226584Sdim        const trans_type& transformer() const { return *m_trans; }
148226584Sdim        void transformer(const trans_type& trans) { m_trans = &trans; }
149226584Sdim
150226584Sdim        //----------------------------------------------------------------
151226584Sdim        unsigned subdiv_shift() const { return m_subdiv_shift; }
152226584Sdim        void subdiv_shift(unsigned shift)
153226584Sdim        {
154226584Sdim            m_subdiv_shift = shift;
155226584Sdim            m_subdiv_size = 1 << m_subdiv_shift;
156234353Sdim            m_subdiv_mask = m_subdiv_size - 1;
157226584Sdim        }
158226584Sdim
159226584Sdim        //----------------------------------------------------------------
160226584Sdim        void begin(double x, double y, unsigned len)
161239462Sdim        {
162226584Sdim            double tx;
163226584Sdim            double ty;
164226584Sdim            m_pos   = 1;
165226584Sdim            m_src_x = iround(x * subpixel_scale) + subpixel_scale;
166226584Sdim            m_src_y = y;
167226584Sdim            m_len   = len;
168226584Sdim
169226584Sdim            if(len > m_subdiv_size) len = m_subdiv_size;
170226584Sdim            tx = x;
171226584Sdim            ty = y;
172226584Sdim            m_trans->transform(&tx, &ty);
173226584Sdim            int x1 = iround(tx * subpixel_scale);
174226584Sdim            int y1 = iround(ty * subpixel_scale);
175226584Sdim
176226584Sdim            tx = x + len;
177226584Sdim            ty = y;
178226584Sdim            m_trans->transform(&tx, &ty);
179226584Sdim
180226584Sdim            m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len);
181226584Sdim            m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len);
182226584Sdim        }
183226584Sdim
184226584Sdim        //----------------------------------------------------------------
185226584Sdim        void operator++()
186226584Sdim        {
187226584Sdim            ++m_li_x;
188226584Sdim            ++m_li_y;
189226584Sdim            if(m_pos >= m_subdiv_size)
190226584Sdim            {
191226584Sdim                unsigned len = m_len;
192226584Sdim                if(len > m_subdiv_size) len = m_subdiv_size;
193226584Sdim                double tx = double(m_src_x) / double(subpixel_scale) + len;
194226584Sdim                double ty = m_src_y;
195226584Sdim                m_trans->transform(&tx, &ty);
196226584Sdim                m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len);
197226584Sdim                m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len);
198226584Sdim                m_pos = 0;
199226584Sdim            }
200226584Sdim            m_src_x += subpixel_scale;
201226584Sdim            ++m_pos;
202226584Sdim            --m_len;
203226584Sdim        }
204226584Sdim
205226584Sdim        //----------------------------------------------------------------
206226584Sdim        void coordinates(int* x, int* y) const
207226584Sdim        {
208226584Sdim            *x = m_li_x.y();
209226584Sdim            *y = m_li_y.y();
210226584Sdim        }
211226584Sdim
212234353Sdim    private:
213226584Sdim        unsigned m_subdiv_shift;
214226584Sdim        unsigned m_subdiv_size;
215226584Sdim        unsigned m_subdiv_mask;
216226584Sdim        const trans_type* m_trans;
217226584Sdim        dda2_line_interpolator m_li_x;
218226584Sdim        dda2_line_interpolator m_li_y;
219226584Sdim        int      m_src_x;
220226584Sdim        double   m_src_y;
221226584Sdim        unsigned m_pos;
222226584Sdim        unsigned m_len;
223226584Sdim    };
224226584Sdim
225226584Sdim
226226584Sdim}
227226584Sdim
228249423Sdim
229226584Sdim
230226584Sdim#endif
231226584Sdim
232226584Sdim
233226584Sdim