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 #ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED 17 #define AGG_CONV_ADAPTOR_VCGEN_INCLUDED 18 #include "agg_basics.h" 19 namespace agg 20 { 21 struct null_markers { 22 void remove_all() {} 23 void add_vertex(FX_FLOAT, FX_FLOAT, unsigned) {} 24 void prepare_src() {} 25 void rewind(unsigned) {} 26 unsigned vertex(FX_FLOAT*, FX_FLOAT*) 27 { 28 return path_cmd_stop; 29 } 30 }; 31 template<class VertexSource, 32 class Generator, 33 class Markers = null_markers> class conv_adaptor_vcgen 34 { 35 enum status { 36 initial, 37 accumulate, 38 generate 39 }; 40 public: 41 conv_adaptor_vcgen(VertexSource& source) : 42 m_source(&source), 43 m_status(initial) 44 {} 45 void set_source(VertexSource& source) 46 { 47 m_source = &source; 48 } 49 Generator& generator() 50 { 51 return m_generator; 52 } 53 const Generator& generator() const 54 { 55 return m_generator; 56 } 57 Markers& markers() 58 { 59 return m_markers; 60 } 61 const Markers& markers() const 62 { 63 return m_markers; 64 } 65 void rewind(unsigned path_id) 66 { 67 m_source->rewind(path_id); 68 m_status = initial; 69 } 70 unsigned vertex(FX_FLOAT* x, FX_FLOAT* y); 71 private: 72 conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); 73 const conv_adaptor_vcgen<VertexSource, Generator, Markers>& 74 operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); 75 VertexSource* m_source; 76 Generator m_generator; 77 Markers m_markers; 78 status m_status; 79 unsigned m_last_cmd; 80 FX_FLOAT m_start_x; 81 FX_FLOAT m_start_y; 82 }; 83 template<class VertexSource, class Generator, class Markers> 84 unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(FX_FLOAT* x, FX_FLOAT* y) 85 { 86 unsigned cmd = path_cmd_stop; 87 bool done = false; 88 while(!done) { 89 switch(m_status) { 90 case initial: 91 m_markers.remove_all(); 92 m_last_cmd = m_source->vertex(&m_start_x, &m_start_y); 93 m_status = accumulate; 94 case accumulate: 95 if(is_stop(m_last_cmd)) { 96 return path_cmd_stop; 97 } 98 m_generator.remove_all(); 99 m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to); 100 m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to); 101 for(;;) { 102 cmd = m_source->vertex(x, y); 103 if(is_vertex(cmd)) { 104 m_last_cmd = cmd; 105 if(is_move_to(cmd)) { 106 m_start_x = *x; 107 m_start_y = *y; 108 break; 109 } 110 m_generator.add_vertex(*x, *y, cmd); 111 m_markers.add_vertex(*x, *y, path_cmd_line_to); 112 } else { 113 if(is_stop(cmd)) { 114 m_last_cmd = path_cmd_stop; 115 break; 116 } 117 if(is_end_poly(cmd)) { 118 m_generator.add_vertex(*x, *y, cmd); 119 break; 120 } 121 } 122 } 123 m_generator.rewind(0); 124 m_status = generate; 125 case generate: 126 cmd = m_generator.vertex(x, y); 127 if(is_stop(cmd)) { 128 m_status = accumulate; 129 break; 130 } 131 done = true; 132 break; 133 } 134 } 135 return cmd; 136 } 137 } 138 #endif 139