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 (at) antigrain.com 13 // mcseemagg (at) 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 #include "core/fxcrt/fx_basic.h" 24 25 namespace agg 26 { 27 vcgen_dash::vcgen_dash() : 28 m_total_dash_len(0), 29 m_num_dashes(0), 30 m_dash_start(0), 31 m_shorten(0), 32 m_curr_dash_start(0), 33 m_curr_dash(0), 34 m_src_vertices(), 35 m_closed(0), 36 m_status(initial), 37 m_src_vertex(0) 38 { 39 } 40 void vcgen_dash::remove_all_dashes() 41 { 42 m_total_dash_len = 0; 43 m_num_dashes = 0; 44 m_curr_dash_start = 0; 45 m_curr_dash = 0; 46 } 47 void vcgen_dash::add_dash(FX_FLOAT dash_len, FX_FLOAT gap_len) 48 { 49 if(m_num_dashes < max_dashes) { 50 m_total_dash_len += dash_len + gap_len; 51 m_dashes[m_num_dashes++] = dash_len; 52 m_dashes[m_num_dashes++] = gap_len; 53 } 54 } 55 void vcgen_dash::dash_start(FX_FLOAT ds) 56 { 57 m_dash_start = ds; 58 calc_dash_start(FXSYS_fabs(ds)); 59 } 60 void vcgen_dash::calc_dash_start(FX_FLOAT ds) 61 { 62 m_curr_dash = 0; 63 m_curr_dash_start = 0; 64 while(ds > 0) { 65 if(ds > m_dashes[m_curr_dash]) { 66 ds -= m_dashes[m_curr_dash]; 67 ++m_curr_dash; 68 m_curr_dash_start = 0; 69 if(m_curr_dash >= m_num_dashes) { 70 m_curr_dash = 0; 71 } 72 } else { 73 m_curr_dash_start = ds; 74 ds = 0; 75 } 76 } 77 } 78 void vcgen_dash::remove_all() 79 { 80 m_status = initial; 81 m_src_vertices.remove_all(); 82 m_closed = 0; 83 } 84 void vcgen_dash::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) 85 { 86 m_status = initial; 87 if(is_move_to(cmd)) { 88 m_src_vertices.modify_last(vertex_dist(x, y)); 89 } else { 90 if(is_vertex(cmd)) { 91 m_src_vertices.add(vertex_dist(x, y)); 92 } else { 93 m_closed = get_close_flag(cmd); 94 } 95 } 96 } 97 void vcgen_dash::rewind(unsigned) 98 { 99 if(m_status == initial) { 100 m_src_vertices.close(m_closed != 0); 101 shorten_path(m_src_vertices, m_shorten, m_closed); 102 } 103 m_status = ready; 104 m_src_vertex = 0; 105 } 106 unsigned vcgen_dash::vertex(FX_FLOAT* x, FX_FLOAT* y) 107 { 108 unsigned cmd = path_cmd_move_to; 109 while(!is_stop(cmd)) { 110 switch(m_status) { 111 case initial: 112 rewind(0); 113 case ready: 114 if(m_num_dashes < 2 || m_src_vertices.size() < 2) { 115 cmd = path_cmd_stop; 116 break; 117 } 118 m_status = polyline; 119 m_src_vertex = 1; 120 m_v1 = &m_src_vertices[0]; 121 m_v2 = &m_src_vertices[1]; 122 m_curr_rest = m_v1->dist; 123 *x = m_v1->x; 124 *y = m_v1->y; 125 if(m_dash_start >= 0) { 126 calc_dash_start(m_dash_start); 127 } 128 return path_cmd_move_to; 129 case polyline: { 130 FX_FLOAT dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; 131 unsigned cmd = (m_curr_dash & 1) ? 132 path_cmd_move_to : 133 path_cmd_line_to; 134 if(m_curr_rest > dash_rest) { 135 m_curr_rest -= dash_rest; 136 ++m_curr_dash; 137 if(m_curr_dash >= m_num_dashes) { 138 m_curr_dash = 0; 139 } 140 m_curr_dash_start = 0; 141 *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist; 142 *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist; 143 } else { 144 m_curr_dash_start += m_curr_rest; 145 *x = m_v2->x; 146 *y = m_v2->y; 147 ++m_src_vertex; 148 m_v1 = m_v2; 149 m_curr_rest = m_v1->dist; 150 if(m_closed) { 151 if(m_src_vertex > m_src_vertices.size()) { 152 m_status = stop; 153 } else { 154 m_v2 = &m_src_vertices 155 [ 156 (m_src_vertex >= m_src_vertices.size()) ? 0 : 157 m_src_vertex 158 ]; 159 } 160 } else { 161 if(m_src_vertex >= m_src_vertices.size()) { 162 m_status = stop; 163 } else { 164 m_v2 = &m_src_vertices[m_src_vertex]; 165 } 166 } 167 } 168 return cmd; 169 } 170 break; 171 case stop: 172 cmd = path_cmd_stop; 173 break; 174 } 175 } 176 return path_cmd_stop; 177 } 178 } 179