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 // Contour generator 17 // 18 //---------------------------------------------------------------------------- 19 20 #include "agg_vcgen_contour.h" 21 22 namespace agg 23 { 24 25 //------------------------------------------------------------------------ vcgen_contour()26 vcgen_contour::vcgen_contour() : 27 m_stroker(), 28 m_width(1), 29 m_src_vertices(), 30 m_out_vertices(), 31 m_status(initial), 32 m_src_vertex(0), 33 m_closed(0), 34 m_orientation(0), 35 m_auto_detect(false) 36 { 37 } 38 39 //------------------------------------------------------------------------ remove_all()40 void vcgen_contour::remove_all() 41 { 42 m_src_vertices.remove_all(); 43 m_closed = 0; 44 m_orientation = 0; 45 m_status = initial; 46 } 47 48 //------------------------------------------------------------------------ add_vertex(double x,double y,unsigned cmd)49 void vcgen_contour::add_vertex(double x, double y, unsigned cmd) 50 { 51 m_status = initial; 52 if(is_move_to(cmd)) 53 { 54 m_src_vertices.modify_last(vertex_dist(x, y)); 55 } 56 else 57 { 58 if(is_vertex(cmd)) 59 { 60 m_src_vertices.add(vertex_dist(x, y)); 61 } 62 else 63 { 64 if(is_end_poly(cmd)) 65 { 66 m_closed = get_close_flag(cmd); 67 if(m_orientation == path_flags_none) 68 { 69 m_orientation = get_orientation(cmd); 70 } 71 } 72 } 73 } 74 } 75 76 //------------------------------------------------------------------------ rewind(unsigned)77 void vcgen_contour::rewind(unsigned) 78 { 79 if(m_status == initial) 80 { 81 m_src_vertices.close(true); 82 if(m_auto_detect) 83 { 84 if(!is_oriented(m_orientation)) 85 { 86 m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ? 87 path_flags_ccw : 88 path_flags_cw; 89 } 90 } 91 if(is_oriented(m_orientation)) 92 { 93 m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width); 94 } 95 } 96 m_status = ready; 97 m_src_vertex = 0; 98 } 99 100 //------------------------------------------------------------------------ vertex(double * x,double * y)101 unsigned vcgen_contour::vertex(double* x, double* y) 102 { 103 unsigned cmd = path_cmd_line_to; 104 while(!is_stop(cmd)) 105 { 106 switch(m_status) 107 { 108 case initial: 109 rewind(0); 110 111 case ready: 112 if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) 113 { 114 cmd = path_cmd_stop; 115 break; 116 } 117 m_status = outline; 118 cmd = path_cmd_move_to; 119 m_src_vertex = 0; 120 m_out_vertex = 0; 121 122 case outline: 123 if(m_src_vertex >= m_src_vertices.size()) 124 { 125 m_status = end_poly; 126 break; 127 } 128 m_stroker.calc_join(m_out_vertices, 129 m_src_vertices.prev(m_src_vertex), 130 m_src_vertices.curr(m_src_vertex), 131 m_src_vertices.next(m_src_vertex), 132 m_src_vertices.prev(m_src_vertex).dist, 133 m_src_vertices.curr(m_src_vertex).dist); 134 ++m_src_vertex; 135 m_status = out_vertices; 136 m_out_vertex = 0; 137 138 case out_vertices: 139 if(m_out_vertex >= m_out_vertices.size()) 140 { 141 m_status = outline; 142 } 143 else 144 { 145 const point_d& c = m_out_vertices[m_out_vertex++]; 146 *x = c.x; 147 *y = c.y; 148 return cmd; 149 } 150 break; 151 152 case end_poly: 153 if(!m_closed) return path_cmd_stop; 154 m_status = stop; 155 return path_cmd_end_poly | path_flags_close | path_flags_ccw; 156 157 case stop: 158 return path_cmd_stop; 159 } 160 } 161 return cmd; 162 } 163 164 } 165