xref: /haiku/src/libs/agg/src/agg_vcgen_dash.cpp (revision 03c41782bb4580b84cc34498b8ed66d11e37b995)
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 // Line dash generator
17 //
18 //----------------------------------------------------------------------------
19 
20 #include <math.h>
21 #include "agg_vcgen_dash.h"
22 #include "agg_shorten_path.h"
23 
24 namespace agg
25 {
26 
27     //------------------------------------------------------------------------
vcgen_dash()28     vcgen_dash::vcgen_dash() :
29         m_total_dash_len(0.0),
30         m_num_dashes(0),
31         m_dash_start(0.0),
32         m_shorten(0.0),
33         m_curr_dash_start(0.0),
34         m_curr_dash(0),
35         m_src_vertices(),
36         m_closed(0),
37         m_status(initial),
38         m_src_vertex(0)
39     {
40     }
41 
42 
43 
44     //------------------------------------------------------------------------
remove_all_dashes()45     void vcgen_dash::remove_all_dashes()
46     {
47         m_total_dash_len = 0.0;
48         m_num_dashes = 0;
49         m_curr_dash_start = 0.0;
50         m_curr_dash = 0;
51     }
52 
53 
54     //------------------------------------------------------------------------
add_dash(double dash_len,double gap_len)55     void vcgen_dash::add_dash(double dash_len, double gap_len)
56     {
57         if(m_num_dashes < max_dashes - 1)
58         {
59             m_total_dash_len += dash_len + gap_len;
60             m_dashes[m_num_dashes++] = dash_len;
61             m_dashes[m_num_dashes++] = gap_len;
62         }
63     }
64 
65 
66     //------------------------------------------------------------------------
dash_start(double ds)67     void vcgen_dash::dash_start(double ds)
68     {
69         m_dash_start = ds;
70         calc_dash_start(fabs(ds));
71     }
72 
73 
74     //------------------------------------------------------------------------
calc_dash_start(double ds)75     void vcgen_dash::calc_dash_start(double ds)
76     {
77         m_curr_dash = 0;
78         m_curr_dash_start = 0.0;
79         while(ds > 0.0)
80         {
81             if(ds > m_dashes[m_curr_dash])
82             {
83                 ds -= m_dashes[m_curr_dash];
84                 ++m_curr_dash;
85                 m_curr_dash_start = 0.0;
86                 if(m_curr_dash >= m_num_dashes) m_curr_dash = 0;
87             }
88             else
89             {
90                 m_curr_dash_start = ds;
91                 ds = 0.0;
92             }
93         }
94     }
95 
96 
97     //------------------------------------------------------------------------
remove_all()98     void vcgen_dash::remove_all()
99     {
100         m_status = initial;
101         m_src_vertices.remove_all();
102         m_closed = 0;
103     }
104 
105 
106     //------------------------------------------------------------------------
add_vertex(double x,double y,unsigned cmd)107     void vcgen_dash::add_vertex(double x, double y, unsigned cmd)
108     {
109         m_status = initial;
110         if(is_move_to(cmd))
111         {
112             m_src_vertices.modify_last(vertex_dist(x, y));
113         }
114         else
115         {
116             if(is_vertex(cmd))
117             {
118                 m_src_vertices.add(vertex_dist(x, y));
119             }
120             else
121             {
122                 m_closed = get_close_flag(cmd);
123             }
124         }
125     }
126 
127 
128     //------------------------------------------------------------------------
rewind(unsigned)129     void vcgen_dash::rewind(unsigned)
130     {
131         if(m_status == initial)
132         {
133             m_src_vertices.close(m_closed != 0);
134             shorten_path(m_src_vertices, m_shorten, m_closed);
135         }
136         m_status = ready;
137         m_src_vertex = 0;
138     }
139 
140 
141     //------------------------------------------------------------------------
vertex(double * x,double * y)142     unsigned vcgen_dash::vertex(double* x, double* y)
143     {
144         unsigned cmd = path_cmd_move_to;
145         while(!is_stop(cmd))
146         {
147             switch(m_status)
148             {
149             case initial:
150                 rewind(0);
151 
152             case ready:
153                 if(m_num_dashes < 2 || m_src_vertices.size() < 2)
154                 {
155                     cmd = path_cmd_stop;
156                     break;
157                 }
158                 m_status = polyline;
159                 m_src_vertex = 1;
160                 m_v1 = &m_src_vertices[0];
161                 m_v2 = &m_src_vertices[1];
162                 m_curr_rest = m_v1->dist;
163                 *x = m_v1->x;
164                 *y = m_v1->y;
165                 if(m_dash_start >= 0.0) calc_dash_start(m_dash_start);
166                 return path_cmd_move_to;
167 
168             case polyline:
169                 {
170                     double dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start;
171 
172                     unsigned cmd = (m_curr_dash & 1) ?
173                                    path_cmd_move_to :
174                                    path_cmd_line_to;
175 
176                     if(m_curr_rest > dash_rest)
177                     {
178                         m_curr_rest -= dash_rest;
179                         ++m_curr_dash;
180                         if(m_curr_dash >= m_num_dashes) m_curr_dash = 0;
181                         m_curr_dash_start = 0.0;
182                         *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist;
183                         *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist;
184                     }
185                     else
186                     {
187                         m_curr_dash_start += m_curr_rest;
188                         *x = m_v2->x;
189                         *y = m_v2->y;
190                         ++m_src_vertex;
191                         m_v1 = m_v2;
192                         m_curr_rest = m_v1->dist;
193                         if(m_closed)
194                         {
195                             if(m_src_vertex > m_src_vertices.size())
196                             {
197                                 m_status = stop;
198                             }
199                             else
200                             {
201                                 m_v2 = &m_src_vertices
202                                 [
203                                     (m_src_vertex >= m_src_vertices.size()) ? 0 :
204                                     m_src_vertex
205                                 ];
206                             }
207                         }
208                         else
209                         {
210                             if(m_src_vertex >= m_src_vertices.size())
211                             {
212                                 m_status = stop;
213                             }
214                             else
215                             {
216                                 m_v2 = &m_src_vertices[m_src_vertex];
217                             }
218                         }
219                     }
220                     return cmd;
221                 }
222                 break;
223 
224             case stop:
225                 cmd = path_cmd_stop;
226                 break;
227             }
228 
229         }
230         return path_cmd_stop;
231     }
232 
233 
234 }
235 
236