Anti-Grain Geometry Tutorial
agg_vcgen_dash.cpp
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 <cmath>
21 #include "agg_vcgen_dash.h"
22 #include "agg_shorten_path.h"
23 
24 namespace agg
25 {
26 
27  //------------------------------------------------------------------------
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  //------------------------------------------------------------------------
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  //------------------------------------------------------------------------
55  void vcgen_dash::add_dash(double dash_len, double gap_len)
56  {
57  if(m_num_dashes < max_dashes)
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  //------------------------------------------------------------------------
67  void vcgen_dash::dash_start(double ds)
68  {
69  m_dash_start = ds;
70  calc_dash_start(std::fabs(ds));
71  }
72 
73 
74  //------------------------------------------------------------------------
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  //------------------------------------------------------------------------
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  //------------------------------------------------------------------------
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  //------------------------------------------------------------------------
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  //------------------------------------------------------------------------
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 
Definition: agg_arc.cpp:24