Anti-Grain Geometry Tutorial
agg_vcgen_stroke.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 // Stroke generator
17 //
18 //----------------------------------------------------------------------------
19 #include "agg_vcgen_stroke.h"
20 #include "agg_shorten_path.h"
21 
22 namespace agg
23 {
24 
25  //------------------------------------------------------------------------
26  vcgen_stroke::vcgen_stroke() :
27  m_stroker(),
28  m_src_vertices(),
29  m_out_vertices(),
30  m_shorten(0.0),
31  m_closed(0),
32  m_status(initial),
33  m_src_vertex(0),
34  m_out_vertex(0)
35  {
36  }
37 
38  //------------------------------------------------------------------------
39  void vcgen_stroke::remove_all()
40  {
41  m_src_vertices.remove_all();
42  m_closed = 0;
43  m_status = initial;
44  }
45 
46 
47  //------------------------------------------------------------------------
48  void vcgen_stroke::add_vertex(double x, double y, unsigned cmd)
49  {
50  m_status = initial;
51  if(is_move_to(cmd))
52  {
53  m_src_vertices.modify_last(vertex_dist(x, y));
54  }
55  else
56  {
57  if(is_vertex(cmd))
58  {
59  m_src_vertices.add(vertex_dist(x, y));
60  }
61  else
62  {
63  m_closed = get_close_flag(cmd);
64  }
65  }
66  }
67 
68  //------------------------------------------------------------------------
69  void vcgen_stroke::rewind(unsigned)
70  {
71  if(m_status == initial)
72  {
73  m_src_vertices.close(m_closed != 0);
74  shorten_path(m_src_vertices, m_shorten, m_closed);
75  if(m_src_vertices.size() < 3) m_closed = 0;
76  }
77  m_status = ready;
78  m_src_vertex = 0;
79  m_out_vertex = 0;
80  }
81 
82 
83  //------------------------------------------------------------------------
84  unsigned vcgen_stroke::vertex(double* x, double* y)
85  {
86  unsigned cmd = path_cmd_line_to;
87  while(!is_stop(cmd))
88  {
89  switch(m_status)
90  {
91  case initial:
92  rewind(0);
93 
94  case ready:
95  if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
96  {
97  cmd = path_cmd_stop;
98  break;
99  }
100  m_status = m_closed ? outline1 : cap1;
101  cmd = path_cmd_move_to;
102  m_src_vertex = 0;
103  m_out_vertex = 0;
104  break;
105 
106  case cap1:
107  m_stroker.calc_cap(m_out_vertices,
108  m_src_vertices[0],
109  m_src_vertices[1],
110  m_src_vertices[0].dist);
111  m_src_vertex = 1;
112  m_prev_status = outline1;
113  m_status = out_vertices;
114  m_out_vertex = 0;
115  break;
116 
117  case cap2:
118  m_stroker.calc_cap(m_out_vertices,
119  m_src_vertices[m_src_vertices.size() - 1],
120  m_src_vertices[m_src_vertices.size() - 2],
121  m_src_vertices[m_src_vertices.size() - 2].dist);
122  m_prev_status = outline2;
123  m_status = out_vertices;
124  m_out_vertex = 0;
125  break;
126 
127  case outline1:
128  if(m_closed)
129  {
130  if(m_src_vertex >= m_src_vertices.size())
131  {
132  m_prev_status = close_first;
133  m_status = end_poly1;
134  break;
135  }
136  }
137  else
138  {
139  if(m_src_vertex >= m_src_vertices.size() - 1)
140  {
141  m_status = cap2;
142  break;
143  }
144  }
145  m_stroker.calc_join(m_out_vertices,
146  m_src_vertices.prev(m_src_vertex),
147  m_src_vertices.curr(m_src_vertex),
148  m_src_vertices.next(m_src_vertex),
149  m_src_vertices.prev(m_src_vertex).dist,
150  m_src_vertices.curr(m_src_vertex).dist);
151  ++m_src_vertex;
152  m_prev_status = m_status;
153  m_status = out_vertices;
154  m_out_vertex = 0;
155  break;
156 
157  case close_first:
158  m_status = outline2;
159  cmd = path_cmd_move_to;
160 
161  case outline2:
162  if(m_src_vertex <= unsigned(m_closed == 0))
163  {
164  m_status = end_poly2;
165  m_prev_status = stop;
166  break;
167  }
168 
169  --m_src_vertex;
170  m_stroker.calc_join(m_out_vertices,
171  m_src_vertices.next(m_src_vertex),
172  m_src_vertices.curr(m_src_vertex),
173  m_src_vertices.prev(m_src_vertex),
174  m_src_vertices.curr(m_src_vertex).dist,
175  m_src_vertices.prev(m_src_vertex).dist);
176 
177  m_prev_status = m_status;
178  m_status = out_vertices;
179  m_out_vertex = 0;
180  break;
181 
182  case out_vertices:
183  if(m_out_vertex >= m_out_vertices.size())
184  {
185  m_status = m_prev_status;
186  }
187  else
188  {
189  const point_d& c = m_out_vertices[m_out_vertex++];
190  *x = c.x;
191  *y = c.y;
192  return cmd;
193  }
194  break;
195 
196  case end_poly1:
197  m_status = m_prev_status;
198  return path_cmd_end_poly | path_flags_close | path_flags_ccw;
199 
200  case end_poly2:
201  m_status = m_prev_status;
202  return path_cmd_end_poly | path_flags_close | path_flags_cw;
203 
204  case stop:
205  cmd = path_cmd_stop;
206  break;
207  }
208  }
209  return cmd;
210  }
211 
212 }
Definition: agg_arc.cpp:24