xref: /haiku/src/libs/agg/src/agg_trans_single_path.cpp (revision e39da397f5ff79f2db9f9a3ddf1852b6710578af)
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 #include "agg_math.h"
17 #include "agg_vertex_sequence.h"
18 #include "agg_trans_single_path.h"
19 
20 namespace agg
21 {
22 
23     //------------------------------------------------------------------------
trans_single_path()24     trans_single_path::trans_single_path() :
25         m_base_length(0.0),
26         m_kindex(0.0),
27         m_status(initial),
28         m_preserve_x_scale(true)
29     {
30     }
31 
32     //------------------------------------------------------------------------
reset()33     void trans_single_path::reset()
34     {
35         m_src_vertices.remove_all();
36         m_kindex = 0.0;
37         m_status = initial;
38     }
39 
40     //------------------------------------------------------------------------
move_to(double x,double y)41     void trans_single_path::move_to(double x, double y)
42     {
43         if(m_status == initial)
44         {
45             m_src_vertices.modify_last(vertex_dist(x, y));
46             m_status = making_path;
47         }
48         else
49         {
50             line_to(x, y);
51         }
52     }
53 
54     //------------------------------------------------------------------------
line_to(double x,double y)55     void trans_single_path::line_to(double x, double y)
56     {
57         if(m_status == making_path)
58         {
59             m_src_vertices.add(vertex_dist(x, y));
60         }
61     }
62 
63 
64     //------------------------------------------------------------------------
finalize_path()65     void trans_single_path::finalize_path()
66     {
67         if(m_status == making_path && m_src_vertices.size() > 1)
68         {
69             unsigned i;
70             double dist;
71             double d;
72 
73             m_src_vertices.close(false);
74             if(m_src_vertices.size() > 2)
75             {
76                 if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 <
77                    m_src_vertices[m_src_vertices.size() - 3].dist)
78                 {
79                     d = m_src_vertices[m_src_vertices.size() - 3].dist +
80                         m_src_vertices[m_src_vertices.size() - 2].dist;
81 
82                     m_src_vertices[m_src_vertices.size() - 2] =
83                         m_src_vertices[m_src_vertices.size() - 1];
84 
85                     m_src_vertices.remove_last();
86                     m_src_vertices[m_src_vertices.size() - 2].dist = d;
87                 }
88             }
89 
90             dist = 0.0;
91             for(i = 0; i < m_src_vertices.size(); i++)
92             {
93                 vertex_dist& v = m_src_vertices[i];
94                 double d = v.dist;
95                 v.dist = dist;
96                 dist += d;
97             }
98             m_kindex = (m_src_vertices.size() - 1) / dist;
99             m_status = ready;
100         }
101     }
102 
103 
104 
105     //------------------------------------------------------------------------
total_length() const106     double trans_single_path::total_length() const
107     {
108         if(m_base_length >= 1e-10) return m_base_length;
109         return (m_status == ready) ?
110             m_src_vertices[m_src_vertices.size() - 1].dist :
111             0.0;
112     }
113 
114 
115     //------------------------------------------------------------------------
transform(double * x,double * y) const116     void trans_single_path::transform(double *x, double *y) const
117     {
118         if(m_status == ready)
119         {
120             if(m_base_length > 1e-10)
121             {
122                 *x *= m_src_vertices[m_src_vertices.size() - 1].dist /
123                       m_base_length;
124             }
125 
126             double x1 = 0.0;
127             double y1 = 0.0;
128             double dx = 1.0;
129             double dy = 1.0;
130             double d  = 0.0;
131             double dd = 1.0;
132             if(*x < 0.0)
133             {
134                 // Extrapolation on the left
135                 //--------------------------
136                 x1 = m_src_vertices[0].x;
137                 y1 = m_src_vertices[0].y;
138                 dx = m_src_vertices[1].x - x1;
139                 dy = m_src_vertices[1].y - y1;
140                 dd = m_src_vertices[1].dist - m_src_vertices[0].dist;
141                 d  = *x;
142             }
143             else
144             if(*x > m_src_vertices[m_src_vertices.size() - 1].dist)
145             {
146                 // Extrapolation on the right
147                 //--------------------------
148                 unsigned i = m_src_vertices.size() - 2;
149                 unsigned j = m_src_vertices.size() - 1;
150                 x1 = m_src_vertices[j].x;
151                 y1 = m_src_vertices[j].y;
152                 dx = x1 - m_src_vertices[i].x;
153                 dy = y1 - m_src_vertices[i].y;
154                 dd = m_src_vertices[j].dist - m_src_vertices[i].dist;
155                 d  = *x - m_src_vertices[j].dist;
156             }
157             else
158             {
159                 // Interpolation
160                 //--------------------------
161                 unsigned i = 0;
162                 unsigned j = m_src_vertices.size() - 1;
163                 if(m_preserve_x_scale)
164                 {
165                     unsigned k;
166                     for(i = 0; (j - i) > 1; )
167                     {
168                         if(*x < m_src_vertices[k = (i + j) >> 1].dist)
169                         {
170                             j = k;
171                         }
172                         else
173                         {
174                             i = k;
175                         }
176                     }
177                     d  = m_src_vertices[i].dist;
178                     dd = m_src_vertices[j].dist - d;
179                     d  = *x - d;
180                 }
181                 else
182                 {
183                     i = unsigned(*x * m_kindex);
184                     j = i + 1;
185                     dd = m_src_vertices[j].dist - m_src_vertices[i].dist;
186                     d = ((*x * m_kindex) - i) * dd;
187                 }
188                 x1 = m_src_vertices[i].x;
189                 y1 = m_src_vertices[i].y;
190                 dx = m_src_vertices[j].x - x1;
191                 dy = m_src_vertices[j].y - y1;
192             }
193             double x2 = x1 + dx * d / dd;
194             double y2 = y1 + dy * d / dd;
195             *x = x2 - *y * dy / dd;
196             *y = y2 + *y * dx / dd;
197         }
198     }
199 
200 
201 }
202 
203