• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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