1
2 //----------------------------------------------------------------------------
3 // Anti-Grain Geometry - Version 2.3
4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5 //
6 // Permission to copy, use, modify, sell and distribute this software
7 // is granted provided this copyright notice appears in all copies.
8 // This software is provided "as is" without express or implied
9 // warranty, and with no claim as to its suitability for any purpose.
10 //
11 //----------------------------------------------------------------------------
12 // Contact: mcseem@antigrain.com
13 // mcseemagg@yahoo.com
14 // http://www.antigrain.com
15 //----------------------------------------------------------------------------
16 //
17 // Line dash generator
18 //
19 //----------------------------------------------------------------------------
20
21 #include "agg_shorten_path.h"
22 #include "agg_vcgen_dash.h"
23
24 namespace agg
25 {
vcgen_dash()26 vcgen_dash::vcgen_dash() :
27 m_total_dash_len(0),
28 m_num_dashes(0),
29 m_dash_start(0),
30 m_shorten(0),
31 m_curr_dash_start(0),
32 m_curr_dash(0),
33 m_src_vertices(),
34 m_closed(0),
35 m_status(initial),
36 m_src_vertex(0)
37 {
38 }
remove_all_dashes()39 void vcgen_dash::remove_all_dashes()
40 {
41 m_total_dash_len = 0;
42 m_num_dashes = 0;
43 m_curr_dash_start = 0;
44 m_curr_dash = 0;
45 }
add_dash(float dash_len,float gap_len)46 void vcgen_dash::add_dash(float dash_len, float gap_len)
47 {
48 if(m_num_dashes < max_dashes) {
49 m_total_dash_len += dash_len + gap_len;
50 m_dashes[m_num_dashes++] = dash_len;
51 m_dashes[m_num_dashes++] = gap_len;
52 }
53 }
dash_start(float ds)54 void vcgen_dash::dash_start(float ds)
55 {
56 m_dash_start = ds;
57 calc_dash_start(fabs(ds));
58 }
calc_dash_start(float ds)59 void vcgen_dash::calc_dash_start(float ds)
60 {
61 m_curr_dash = 0;
62 m_curr_dash_start = 0;
63 while(ds > 0) {
64 if(ds > m_dashes[m_curr_dash]) {
65 ds -= m_dashes[m_curr_dash];
66 ++m_curr_dash;
67 m_curr_dash_start = 0;
68 if(m_curr_dash >= m_num_dashes) {
69 m_curr_dash = 0;
70 }
71 } else {
72 m_curr_dash_start = ds;
73 ds = 0;
74 }
75 }
76 }
remove_all()77 void vcgen_dash::remove_all()
78 {
79 m_status = initial;
80 m_src_vertices.remove_all();
81 m_closed = 0;
82 }
add_vertex(float x,float y,unsigned cmd)83 void vcgen_dash::add_vertex(float x, float y, unsigned cmd)
84 {
85 m_status = initial;
86 if(is_move_to(cmd)) {
87 m_src_vertices.modify_last(vertex_dist(x, y));
88 } else {
89 if(is_vertex(cmd)) {
90 m_src_vertices.add(vertex_dist(x, y));
91 } else {
92 m_closed = get_close_flag(cmd);
93 }
94 }
95 }
rewind(unsigned)96 void vcgen_dash::rewind(unsigned)
97 {
98 if(m_status == initial) {
99 m_src_vertices.close(m_closed != 0);
100 shorten_path(m_src_vertices, m_shorten, m_closed);
101 }
102 m_status = ready;
103 m_src_vertex = 0;
104 }
vertex(float * x,float * y)105 unsigned vcgen_dash::vertex(float* x, float* y)
106 {
107 unsigned cmd = path_cmd_move_to;
108 while(!is_stop(cmd)) {
109 switch(m_status) {
110 case initial:
111 rewind(0);
112 case ready:
113 if(m_num_dashes < 2 || m_src_vertices.size() < 2) {
114 cmd = path_cmd_stop;
115 break;
116 }
117 m_status = polyline;
118 m_src_vertex = 1;
119 m_v1 = &m_src_vertices[0];
120 m_v2 = &m_src_vertices[1];
121 m_curr_rest = m_v1->dist;
122 *x = m_v1->x;
123 *y = m_v1->y;
124 if(m_dash_start >= 0) {
125 calc_dash_start(m_dash_start);
126 }
127 return path_cmd_move_to;
128 case polyline: {
129 float dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start;
130 unsigned cmd = (m_curr_dash & 1) ?
131 path_cmd_move_to :
132 path_cmd_line_to;
133 if(m_curr_rest > dash_rest) {
134 m_curr_rest -= dash_rest;
135 ++m_curr_dash;
136 if(m_curr_dash >= m_num_dashes) {
137 m_curr_dash = 0;
138 }
139 m_curr_dash_start = 0;
140 *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist;
141 *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist;
142 } else {
143 m_curr_dash_start += m_curr_rest;
144 *x = m_v2->x;
145 *y = m_v2->y;
146 ++m_src_vertex;
147 m_v1 = m_v2;
148 m_curr_rest = m_v1->dist;
149 if(m_closed) {
150 if(m_src_vertex > m_src_vertices.size()) {
151 m_status = stop;
152 } else {
153 m_v2 = &m_src_vertices
154 [
155 (m_src_vertex >= m_src_vertices.size()) ? 0 :
156 m_src_vertex
157 ];
158 }
159 } else {
160 if(m_src_vertex >= m_src_vertices.size()) {
161 m_status = stop;
162 } else {
163 m_v2 = &m_src_vertices[m_src_vertex];
164 }
165 }
166 }
167 return cmd;
168 }
169 break;
170 case stop:
171 cmd = path_cmd_stop;
172 break;
173 }
174 }
175 return path_cmd_stop;
176 }
177 }
178