1
2 //----------------------------------------------------------------------------
3 // XYQ: 2006-01-22 Copied from AGG project.
4 // TODO: This file uses intensive floating point operations, so it's NOT suitable
5 // for platforms like Symbian OS. We need to change to FIX format.
6 //----------------------------------------------------------------------------
7 //----------------------------------------------------------------------------
8 // Anti-Grain Geometry - Version 2.3
9 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
10 //
11 // Permission to copy, use, modify, sell and distribute this software
12 // is granted provided this copyright notice appears in all copies.
13 // This software is provided "as is" without express or implied
14 // warranty, and with no claim as to its suitability for any purpose.
15 //
16 //----------------------------------------------------------------------------
17 // Contact: mcseem@antigrain.com
18 // mcseemagg@yahoo.com
19 // http://www.antigrain.com
20 //----------------------------------------------------------------------------
21 //
22 // Stroke generator
23 //
24 //----------------------------------------------------------------------------
25
26 #include "agg_vcgen_stroke.h"
27 #include "core/fxcrt/fx_basic.h"
28
29 namespace agg
30 {
31
vcgen_stroke()32 vcgen_stroke::vcgen_stroke() :
33 m_src_vertices(),
34 m_out_vertices(),
35 m_width(0.5f),
36 m_miter_limit(4 * 1.0f),
37 m_inner_miter_limit(1.0f + 1.0f / 100),
38 m_approx_scale(1.0f),
39 m_line_cap(butt_cap),
40 m_line_join(miter_join),
41 m_inner_join(inner_miter),
42 m_closed(0),
43 m_status(initial),
44 m_src_vertex(0),
45 m_out_vertex(0)
46 {
47 }
remove_all()48 void vcgen_stroke::remove_all()
49 {
50 m_src_vertices.remove_all();
51 m_closed = 0;
52 m_status = initial;
53 }
add_vertex(FX_FLOAT x,FX_FLOAT y,unsigned cmd)54 void vcgen_stroke::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd)
55 {
56 m_status = initial;
57 if(is_move_to(cmd)) {
58 m_src_vertices.modify_last(vertex_dist_cmd(x, y, cmd));
59 } else {
60 if(is_vertex(cmd)) {
61 m_src_vertices.add(vertex_dist_cmd(x, y, cmd));
62 } else {
63 m_closed = get_close_flag(cmd);
64 }
65 }
66 }
calc_butt_cap(FX_FLOAT * cap,const vertex_dist & v0,const vertex_dist & v1,FX_FLOAT len,FX_FLOAT width)67 static inline void calc_butt_cap(FX_FLOAT* cap,
68 const vertex_dist& v0,
69 const vertex_dist& v1,
70 FX_FLOAT len,
71 FX_FLOAT width) {
72 FX_FLOAT dx = (v1.y - v0.y) * width / len;
73 FX_FLOAT dy = (v1.x - v0.x) * width / len;
74 cap[0] = v0.x - dx;
75 cap[1] = v0.y + dy;
76 cap[2] = v0.x + dx;
77 cap[3] = v0.y - dy;
78 }
rewind(unsigned)79 void vcgen_stroke::rewind(unsigned)
80 {
81 if(m_status == initial) {
82 m_src_vertices.close(m_closed != 0);
83 if(m_src_vertices.size() < 3) {
84 m_closed = 0;
85 }
86 }
87 m_status = ready;
88 m_src_vertex = 0;
89 m_out_vertex = 0;
90 }
vertex(FX_FLOAT * x,FX_FLOAT * y)91 unsigned vcgen_stroke::vertex(FX_FLOAT* x, FX_FLOAT* y)
92 {
93 unsigned cmd = path_cmd_line_to;
94 line_join_e curj;
95 while(!is_stop(cmd)) {
96 switch(m_status) {
97 case initial:
98 rewind(0);
99 case ready:
100 if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) {
101 cmd = path_cmd_stop;
102 break;
103 }
104 m_status = m_closed ? outline1 : cap1;
105 cmd = path_cmd_move_to;
106 m_src_vertex = 0;
107 m_out_vertex = 0;
108 break;
109 case cap1:
110 stroke_calc_cap(m_out_vertices,
111 m_src_vertices[0],
112 m_src_vertices[1],
113 m_src_vertices[0].dist,
114 m_line_cap,
115 m_width,
116 m_approx_scale);
117 m_src_vertex = 1;
118 m_prev_status = outline1;
119 m_status = out_vertices;
120 m_out_vertex = 0;
121 break;
122 case cap2:
123 stroke_calc_cap(m_out_vertices,
124 m_src_vertices[m_src_vertices.size() - 1],
125 m_src_vertices[m_src_vertices.size() - 2],
126 m_src_vertices[m_src_vertices.size() - 2].dist,
127 m_line_cap,
128 m_width,
129 m_approx_scale);
130 m_prev_status = outline2;
131 m_status = out_vertices;
132 m_out_vertex = 0;
133 break;
134 case outline1:
135 if(m_closed) {
136 if(m_src_vertex >= m_src_vertices.size()) {
137 m_prev_status = close_first;
138 m_status = end_poly1;
139 break;
140 }
141 } else {
142 if(m_src_vertex >= m_src_vertices.size() - 1) {
143 m_status = cap2;
144 break;
145 }
146 }
147 curj = m_src_vertices[m_src_vertex].cmd & path_flags_jr ? miter_join_round : m_line_join;
148 stroke_calc_join(m_out_vertices,
149 m_src_vertices.prev(m_src_vertex),
150 m_src_vertices.curr(m_src_vertex),
151 m_src_vertices.next(m_src_vertex),
152 m_src_vertices.prev(m_src_vertex).dist,
153 m_src_vertices.curr(m_src_vertex).dist,
154 m_width,
155 curj,
156 m_inner_join,
157 m_miter_limit,
158 m_inner_miter_limit,
159 m_approx_scale);
160 ++m_src_vertex;
161 m_prev_status = m_status;
162 m_status = out_vertices;
163 m_out_vertex = 0;
164 break;
165 case close_first:
166 m_status = outline2;
167 cmd = path_cmd_move_to;
168 case outline2:
169 if(m_src_vertex <= unsigned(m_closed == 0)) {
170 m_status = end_poly2;
171 m_prev_status = stop;
172 break;
173 }
174 --m_src_vertex;
175 curj = m_src_vertices[m_src_vertex].cmd & path_flags_jr ? miter_join_round : m_line_join;
176 stroke_calc_join(m_out_vertices,
177 m_src_vertices.next(m_src_vertex),
178 m_src_vertices.curr(m_src_vertex),
179 m_src_vertices.prev(m_src_vertex),
180 m_src_vertices.curr(m_src_vertex).dist,
181 m_src_vertices.prev(m_src_vertex).dist,
182 m_width,
183 curj,
184 m_inner_join,
185 m_miter_limit,
186 m_inner_miter_limit,
187 m_approx_scale);
188 m_prev_status = m_status;
189 m_status = out_vertices;
190 m_out_vertex = 0;
191 break;
192 case out_vertices:
193 if(m_out_vertex >= m_out_vertices.size()) {
194 m_status = m_prev_status;
195 } else {
196 const point_type& c = m_out_vertices[m_out_vertex++];
197 *x = c.x;
198 *y = c.y;
199 return cmd;
200 }
201 break;
202 case end_poly1:
203 m_status = m_prev_status;
204 return path_cmd_end_poly | path_flags_close | path_flags_ccw;
205 case end_poly2:
206 m_status = m_prev_status;
207 return path_cmd_end_poly | path_flags_close | path_flags_cw;
208 case stop:
209 cmd = path_cmd_stop;
210 break;
211 }
212 }
213 return cmd;
214 }
215 }
216