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