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 // Line dash generator 17 // 18 //---------------------------------------------------------------------------- 19 20 #include <math.h> 21 #include "agg_vcgen_dash.h" 22 #include "agg_shorten_path.h" 23 24 namespace agg 25 { 26 27 //------------------------------------------------------------------------ vcgen_dash()28 vcgen_dash::vcgen_dash() : 29 m_total_dash_len(0.0), 30 m_num_dashes(0), 31 m_dash_start(0.0), 32 m_shorten(0.0), 33 m_curr_dash_start(0.0), 34 m_curr_dash(0), 35 m_src_vertices(), 36 m_closed(0), 37 m_status(initial), 38 m_src_vertex(0) 39 { 40 } 41 42 43 44 //------------------------------------------------------------------------ remove_all_dashes()45 void vcgen_dash::remove_all_dashes() 46 { 47 m_total_dash_len = 0.0; 48 m_num_dashes = 0; 49 m_curr_dash_start = 0.0; 50 m_curr_dash = 0; 51 } 52 53 54 //------------------------------------------------------------------------ add_dash(double dash_len,double gap_len)55 void vcgen_dash::add_dash(double dash_len, double gap_len) 56 { 57 if(m_num_dashes < max_dashes - 1) 58 { 59 m_total_dash_len += dash_len + gap_len; 60 m_dashes[m_num_dashes++] = dash_len; 61 m_dashes[m_num_dashes++] = gap_len; 62 } 63 } 64 65 66 //------------------------------------------------------------------------ dash_start(double ds)67 void vcgen_dash::dash_start(double ds) 68 { 69 m_dash_start = ds; 70 calc_dash_start(fabs(ds)); 71 } 72 73 74 //------------------------------------------------------------------------ calc_dash_start(double ds)75 void vcgen_dash::calc_dash_start(double ds) 76 { 77 m_curr_dash = 0; 78 m_curr_dash_start = 0.0; 79 while(ds > 0.0) 80 { 81 if(ds > m_dashes[m_curr_dash]) 82 { 83 ds -= m_dashes[m_curr_dash]; 84 ++m_curr_dash; 85 m_curr_dash_start = 0.0; 86 if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; 87 } 88 else 89 { 90 m_curr_dash_start = ds; 91 ds = 0.0; 92 } 93 } 94 } 95 96 97 //------------------------------------------------------------------------ remove_all()98 void vcgen_dash::remove_all() 99 { 100 m_status = initial; 101 m_src_vertices.remove_all(); 102 m_closed = 0; 103 } 104 105 106 //------------------------------------------------------------------------ add_vertex(double x,double y,unsigned cmd)107 void vcgen_dash::add_vertex(double x, double y, unsigned cmd) 108 { 109 m_status = initial; 110 if(is_move_to(cmd)) 111 { 112 m_src_vertices.modify_last(vertex_dist(x, y)); 113 } 114 else 115 { 116 if(is_vertex(cmd)) 117 { 118 m_src_vertices.add(vertex_dist(x, y)); 119 } 120 else 121 { 122 m_closed = get_close_flag(cmd); 123 } 124 } 125 } 126 127 128 //------------------------------------------------------------------------ rewind(unsigned)129 void vcgen_dash::rewind(unsigned) 130 { 131 if(m_status == initial) 132 { 133 m_src_vertices.close(m_closed != 0); 134 shorten_path(m_src_vertices, m_shorten, m_closed); 135 } 136 m_status = ready; 137 m_src_vertex = 0; 138 } 139 140 141 //------------------------------------------------------------------------ vertex(double * x,double * y)142 unsigned vcgen_dash::vertex(double* x, double* y) 143 { 144 unsigned cmd = path_cmd_move_to; 145 while(!is_stop(cmd)) 146 { 147 switch(m_status) 148 { 149 case initial: 150 rewind(0); 151 152 case ready: 153 if(m_num_dashes < 2 || m_src_vertices.size() < 2) 154 { 155 cmd = path_cmd_stop; 156 break; 157 } 158 m_status = polyline; 159 m_src_vertex = 1; 160 m_v1 = &m_src_vertices[0]; 161 m_v2 = &m_src_vertices[1]; 162 m_curr_rest = m_v1->dist; 163 *x = m_v1->x; 164 *y = m_v1->y; 165 if(m_dash_start >= 0.0) calc_dash_start(m_dash_start); 166 return path_cmd_move_to; 167 168 case polyline: 169 { 170 double dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; 171 172 unsigned cmd = (m_curr_dash & 1) ? 173 path_cmd_move_to : 174 path_cmd_line_to; 175 176 if(m_curr_rest > dash_rest) 177 { 178 m_curr_rest -= dash_rest; 179 ++m_curr_dash; 180 if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; 181 m_curr_dash_start = 0.0; 182 *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist; 183 *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist; 184 } 185 else 186 { 187 m_curr_dash_start += m_curr_rest; 188 *x = m_v2->x; 189 *y = m_v2->y; 190 ++m_src_vertex; 191 m_v1 = m_v2; 192 m_curr_rest = m_v1->dist; 193 if(m_closed) 194 { 195 if(m_src_vertex > m_src_vertices.size()) 196 { 197 m_status = stop; 198 } 199 else 200 { 201 m_v2 = &m_src_vertices 202 [ 203 (m_src_vertex >= m_src_vertices.size()) ? 0 : 204 m_src_vertex 205 ]; 206 } 207 } 208 else 209 { 210 if(m_src_vertex >= m_src_vertices.size()) 211 { 212 m_status = stop; 213 } 214 else 215 { 216 m_v2 = &m_src_vertices[m_src_vertex]; 217 } 218 } 219 } 220 return cmd; 221 } 222 break; 223 224 case stop: 225 cmd = path_cmd_stop; 226 break; 227 } 228 229 } 230 return path_cmd_stop; 231 } 232 233 234 } 235 236