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/include/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 {
73 FX_FLOAT dx = FXSYS_MulDiv(v1.y - v0.y, width, len);
74 FX_FLOAT dy = FXSYS_MulDiv(v1.x - v0.x, width, len);
75 cap[0] = v0.x - dx;
76 cap[1] = v0.y + dy;
77 cap[2] = v0.x + dx;
78 cap[3] = v0.y - dy;
79 }
rewind(unsigned)80 void vcgen_stroke::rewind(unsigned)
81 {
82 if(m_status == initial) {
83 m_src_vertices.close(m_closed != 0);
84 if(m_src_vertices.size() < 3) {
85 m_closed = 0;
86 }
87 }
88 m_status = ready;
89 m_src_vertex = 0;
90 m_out_vertex = 0;
91 }
vertex(FX_FLOAT * x,FX_FLOAT * y)92 unsigned vcgen_stroke::vertex(FX_FLOAT* x, FX_FLOAT* y)
93 {
94 unsigned cmd = path_cmd_line_to;
95 line_join_e curj;
96 while(!is_stop(cmd)) {
97 switch(m_status) {
98 case initial:
99 rewind(0);
100 case ready:
101 if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) {
102 cmd = path_cmd_stop;
103 break;
104 }
105 m_status = m_closed ? outline1 : cap1;
106 cmd = path_cmd_move_to;
107 m_src_vertex = 0;
108 m_out_vertex = 0;
109 break;
110 case cap1:
111 stroke_calc_cap(m_out_vertices,
112 m_src_vertices[0],
113 m_src_vertices[1],
114 m_src_vertices[0].dist,
115 m_line_cap,
116 m_width,
117 m_approx_scale);
118 m_src_vertex = 1;
119 m_prev_status = outline1;
120 m_status = out_vertices;
121 m_out_vertex = 0;
122 break;
123 case cap2:
124 stroke_calc_cap(m_out_vertices,
125 m_src_vertices[m_src_vertices.size() - 1],
126 m_src_vertices[m_src_vertices.size() - 2],
127 m_src_vertices[m_src_vertices.size() - 2].dist,
128 m_line_cap,
129 m_width,
130 m_approx_scale);
131 m_prev_status = outline2;
132 m_status = out_vertices;
133 m_out_vertex = 0;
134 break;
135 case outline1:
136 if(m_closed) {
137 if(m_src_vertex >= m_src_vertices.size()) {
138 m_prev_status = close_first;
139 m_status = end_poly1;
140 break;
141 }
142 } else {
143 if(m_src_vertex >= m_src_vertices.size() - 1) {
144 m_status = cap2;
145 break;
146 }
147 }
148 curj = m_src_vertices[m_src_vertex].cmd & path_flags_jr ? miter_join_round : m_line_join;
149 stroke_calc_join(m_out_vertices,
150 m_src_vertices.prev(m_src_vertex),
151 m_src_vertices.curr(m_src_vertex),
152 m_src_vertices.next(m_src_vertex),
153 m_src_vertices.prev(m_src_vertex).dist,
154 m_src_vertices.curr(m_src_vertex).dist,
155 m_width,
156 curj,
157 m_inner_join,
158 m_miter_limit,
159 m_inner_miter_limit,
160 m_approx_scale);
161 ++m_src_vertex;
162 m_prev_status = m_status;
163 m_status = out_vertices;
164 m_out_vertex = 0;
165 break;
166 case close_first:
167 m_status = outline2;
168 cmd = path_cmd_move_to;
169 case outline2:
170 if(m_src_vertex <= unsigned(m_closed == 0)) {
171 m_status = end_poly2;
172 m_prev_status = stop;
173 break;
174 }
175 --m_src_vertex;
176 curj = m_src_vertices[m_src_vertex].cmd & path_flags_jr ? miter_join_round : m_line_join;
177 stroke_calc_join(m_out_vertices,
178 m_src_vertices.next(m_src_vertex),
179 m_src_vertices.curr(m_src_vertex),
180 m_src_vertices.prev(m_src_vertex),
181 m_src_vertices.curr(m_src_vertex).dist,
182 m_src_vertices.prev(m_src_vertex).dist,
183 m_width,
184 curj,
185 m_inner_join,
186 m_miter_limit,
187 m_inner_miter_limit,
188 m_approx_scale);
189 m_prev_status = m_status;
190 m_status = out_vertices;
191 m_out_vertex = 0;
192 break;
193 case out_vertices:
194 if(m_out_vertex >= m_out_vertices.size()) {
195 m_status = m_prev_status;
196 } else {
197 const point_type& c = m_out_vertices[m_out_vertex++];
198 *x = c.x;
199 *y = c.y;
200 return cmd;
201 }
202 break;
203 case end_poly1:
204 m_status = m_prev_status;
205 return path_cmd_end_poly | path_flags_close | path_flags_ccw;
206 case end_poly2:
207 m_status = m_prev_status;
208 return path_cmd_end_poly | path_flags_close | path_flags_cw;
209 case stop:
210 cmd = path_cmd_stop;
211 break;
212 }
213 }
214 return cmd;
215 }
216 }
217