1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.2 3 // Copyright (C) 2002-2004 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 #ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED 17 #define AGG_CONV_ADAPTOR_VCGEN_INCLUDED 18 19 #include "agg_basics.h" 20 #include "agg_vertex_iterator.h" 21 22 namespace agg 23 { 24 //------------------------------------------------------------null_markers 25 struct null_markers 26 { 27 void remove_all() {} 28 void add_vertex(double, double, unsigned) {} 29 void prepare_src() {} 30 31 void rewind(unsigned) {} 32 unsigned vertex(double*, double*) { return path_cmd_stop; } 33 34 typedef null_markers source_type; 35 typedef vertex_iterator<source_type> iterator; 36 iterator begin(unsigned id) { return iterator(*this, id); } 37 iterator end() { return iterator(path_cmd_stop); } 38 }; 39 40 41 //------------------------------------------------------conv_adaptor_vcgen 42 template<class VertexSource, 43 class Generator, 44 class Markers=null_markers> class conv_adaptor_vcgen 45 { 46 enum status 47 { 48 initial, 49 accumulate, 50 generate 51 }; 52 53 public: 54 conv_adaptor_vcgen(VertexSource& source) : 55 m_source(&source), 56 m_status(initial) 57 {} 58 59 void set_source(VertexSource& source) { m_source = &source; } 60 61 Generator& generator() { return m_generator; } 62 const Generator& generator() const { return m_generator; } 63 64 Markers& markers() { return m_markers; } 65 const Markers& markers() const { return m_markers; } 66 67 void rewind(unsigned id) 68 { 69 m_source->rewind(id); 70 m_status = initial; 71 } 72 73 unsigned vertex(double* x, double* y); 74 75 typedef conv_adaptor_vcgen<VertexSource, Generator, Markers> source_type; 76 typedef vertex_iterator<source_type> iterator; 77 iterator begin(unsigned id) { return iterator(*this, id); } 78 iterator end() { return iterator(path_cmd_stop); } 79 80 private: 81 // Prohibit copying 82 conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); 83 const conv_adaptor_vcgen<VertexSource, Generator, Markers>& 84 operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); 85 86 VertexSource* m_source; 87 Generator m_generator; 88 Markers m_markers; 89 status m_status; 90 unsigned m_last_cmd; 91 double m_start_x; 92 double m_start_y; 93 }; 94 95 96 97 98 99 //------------------------------------------------------------------------ 100 template<class VertexSource, class Generator, class Markers> 101 unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y) 102 { 103 unsigned cmd = path_cmd_stop; 104 bool done = false; 105 while(!done) 106 { 107 switch(m_status) 108 { 109 case initial: 110 m_markers.remove_all(); 111 m_last_cmd = m_source->vertex(&m_start_x, &m_start_y); 112 m_status = accumulate; 113 114 case accumulate: 115 if(is_stop(m_last_cmd)) return path_cmd_stop; 116 117 m_generator.remove_all(); 118 m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to); 119 m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to); 120 121 for(;;) 122 { 123 cmd = m_source->vertex(x, y); 124 if(is_vertex(cmd)) 125 { 126 m_last_cmd = cmd; 127 if(is_move_to(cmd)) 128 { 129 m_start_x = *x; 130 m_start_y = *y; 131 break; 132 } 133 m_generator.add_vertex(*x, *y, cmd); 134 m_markers.add_vertex(*x, *y, path_cmd_line_to); 135 } 136 else 137 { 138 if(is_stop(cmd)) 139 { 140 m_last_cmd = path_cmd_stop; 141 break; 142 } 143 if(is_end_poly(cmd)) 144 { 145 m_generator.add_vertex(*x, *y, cmd); 146 break; 147 } 148 } 149 } 150 m_generator.rewind(0); 151 m_status = generate; 152 153 case generate: 154 cmd = m_generator.vertex(x, y); 155 if(is_stop(cmd)) 156 { 157 m_status = accumulate; 158 break; 159 } 160 done = true; 161 break; 162 } 163 } 164 return cmd; 165 } 166 167 } 168 169 #endif 170