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 #ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED 17 #define AGG_PATH_STORAGE_INTEGER_INCLUDED 18 19 #include <string.h> 20 #include "agg_array.h" 21 22 namespace agg 23 { 24 //---------------------------------------------------------vertex_integer 25 template<class T, unsigned CoordShift=6> struct vertex_integer 26 { 27 enum path_cmd 28 { 29 cmd_move_to = 0, 30 cmd_line_to = 1, 31 cmd_curve3 = 2, 32 cmd_curve4 = 3 33 }; 34 35 enum coord_scale_e 36 { 37 coord_shift = CoordShift, 38 coord_scale = 1 << coord_shift 39 }; 40 41 T x,y; vertex_integervertex_integer42 vertex_integer() {} vertex_integervertex_integer43 vertex_integer(T x_, T y_, unsigned flag) : 44 x(((x_ << 1) & ~1) | (flag & 1)), 45 y(((y_ << 1) & ~1) | (flag >> 1)) {} 46 47 unsigned vertex(double* x_, double* y_, 48 double dx=0, double dy=0, 49 double scale=1.0) const 50 { 51 *x_ = dx + (double(x >> 1) / coord_scale) * scale; 52 *y_ = dy + (double(y >> 1) / coord_scale) * scale; 53 switch(((y & 1) << 1) | (x & 1)) 54 { 55 case cmd_move_to: return path_cmd_move_to; 56 case cmd_line_to: return path_cmd_line_to; 57 case cmd_curve3: return path_cmd_curve3; 58 case cmd_curve4: return path_cmd_curve4; 59 } 60 return path_cmd_stop; 61 } 62 }; 63 64 65 //---------------------------------------------------path_storage_integer 66 template<class T, unsigned CoordShift=6> class path_storage_integer 67 { 68 public: 69 typedef T value_type; 70 typedef vertex_integer<T, CoordShift> vertex_integer_type; 71 72 //-------------------------------------------------------------------- path_storage_integer()73 path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {} 74 75 //-------------------------------------------------------------------- remove_all()76 void remove_all() { m_storage.remove_all(); } 77 78 //-------------------------------------------------------------------- move_to(T x,T y)79 void move_to(T x, T y) 80 { 81 m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to)); 82 } 83 84 //-------------------------------------------------------------------- line_to(T x,T y)85 void line_to(T x, T y) 86 { 87 m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to)); 88 } 89 90 //-------------------------------------------------------------------- curve3(T x_ctrl,T y_ctrl,T x_to,T y_to)91 void curve3(T x_ctrl, T y_ctrl, 92 T x_to, T y_to) 93 { 94 m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3)); 95 m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3)); 96 } 97 98 //-------------------------------------------------------------------- curve4(T x_ctrl1,T y_ctrl1,T x_ctrl2,T y_ctrl2,T x_to,T y_to)99 void curve4(T x_ctrl1, T y_ctrl1, 100 T x_ctrl2, T y_ctrl2, 101 T x_to, T y_to) 102 { 103 m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4)); 104 m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4)); 105 m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4)); 106 } 107 108 //-------------------------------------------------------------------- close_polygon()109 void close_polygon() {} 110 111 //-------------------------------------------------------------------- size()112 unsigned size() const { return m_storage.size(); } vertex(unsigned idx,double * x,double * y)113 unsigned vertex(unsigned idx, double* x, double* y) const 114 { 115 return m_storage[idx].vertex(x, y); 116 } 117 118 //-------------------------------------------------------------------- byte_size()119 unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); } serialize(int8u * ptr)120 void serialize(int8u* ptr) const 121 { 122 unsigned i; 123 for(i = 0; i < m_storage.size(); i++) 124 { 125 memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); 126 ptr += sizeof(vertex_integer_type); 127 } 128 } 129 130 //-------------------------------------------------------------------- rewind(unsigned)131 void rewind(unsigned) 132 { 133 m_vertex_idx = 0; 134 m_closed = true; 135 } 136 137 //-------------------------------------------------------------------- vertex(double * x,double * y)138 unsigned vertex(double* x, double* y) 139 { 140 if(m_storage.size() < 2 || m_vertex_idx > m_storage.size()) 141 { 142 *x = 0; 143 *y = 0; 144 return path_cmd_stop; 145 } 146 if(m_vertex_idx == m_storage.size()) 147 { 148 *x = 0; 149 *y = 0; 150 ++m_vertex_idx; 151 return path_cmd_end_poly | path_flags_close; 152 } 153 unsigned cmd = m_storage[m_vertex_idx].vertex(x, y); 154 if(is_move_to(cmd) && !m_closed) 155 { 156 *x = 0; 157 *y = 0; 158 m_closed = true; 159 return path_cmd_end_poly | path_flags_close; 160 } 161 m_closed = false; 162 ++m_vertex_idx; 163 return cmd; 164 } 165 166 //-------------------------------------------------------------------- bounding_rect()167 rect_d bounding_rect() const 168 { 169 rect_d bounds(1e100, 1e100, -1e100, -1e100); 170 if(m_storage.size() == 0) 171 { 172 bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; 173 } 174 else 175 { 176 unsigned i; 177 for(i = 0; i < m_storage.size(); i++) 178 { 179 double x, y; 180 m_storage[i].vertex(&x, &y); 181 if(x < bounds.x1) bounds.x1 = x; 182 if(y < bounds.y1) bounds.y1 = y; 183 if(x > bounds.x2) bounds.x2 = x; 184 if(y > bounds.y2) bounds.y2 = y; 185 } 186 } 187 return bounds; 188 } 189 190 private: 191 pod_bvector<vertex_integer_type, 6> m_storage; 192 unsigned m_vertex_idx; 193 bool m_closed; 194 }; 195 196 197 198 199 //-----------------------------------------serialized_integer_path_adaptor 200 template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor 201 { 202 public: 203 typedef vertex_integer<T, CoordShift> vertex_integer_type; 204 205 //-------------------------------------------------------------------- serialized_integer_path_adaptor()206 serialized_integer_path_adaptor() : 207 m_data(0), 208 m_end(0), 209 m_ptr(0), 210 m_dx(0.0), 211 m_dy(0.0), 212 m_scale(1.0), 213 m_vertices(0) 214 {} 215 216 //-------------------------------------------------------------------- serialized_integer_path_adaptor(const int8u * data,unsigned size,double dx,double dy)217 serialized_integer_path_adaptor(const int8u* data, unsigned size, 218 double dx, double dy) : 219 m_data(data), 220 m_end(data + size), 221 m_ptr(data), 222 m_dx(dx), 223 m_dy(dy), 224 m_vertices(0) 225 {} 226 227 //-------------------------------------------------------------------- 228 void init(const int8u* data, unsigned size, 229 double dx, double dy, double scale=1.0) 230 { 231 m_data = data; 232 m_end = data + size; 233 m_ptr = data; 234 m_dx = dx; 235 m_dy = dy; 236 m_scale = scale; 237 m_vertices = 0; 238 } 239 240 241 //-------------------------------------------------------------------- rewind(unsigned)242 void rewind(unsigned) 243 { 244 m_ptr = m_data; 245 m_vertices = 0; 246 } 247 248 //-------------------------------------------------------------------- vertex(double * x,double * y)249 unsigned vertex(double* x, double* y) 250 { 251 if(m_data == 0 || m_ptr > m_end) 252 { 253 *x = 0; 254 *y = 0; 255 return path_cmd_stop; 256 } 257 258 if(m_ptr == m_end) 259 { 260 *x = 0; 261 *y = 0; 262 m_ptr += sizeof(vertex_integer_type); 263 return path_cmd_end_poly | path_flags_close; 264 } 265 266 vertex_integer_type v; 267 memcpy(&v, m_ptr, sizeof(vertex_integer_type)); 268 unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale); 269 if(is_move_to(cmd) && m_vertices > 2) 270 { 271 *x = 0; 272 *y = 0; 273 m_vertices = 0; 274 return path_cmd_end_poly | path_flags_close; 275 } 276 ++m_vertices; 277 m_ptr += sizeof(vertex_integer_type); 278 return cmd; 279 } 280 281 private: 282 const int8u* m_data; 283 const int8u* m_end; 284 const int8u* m_ptr; 285 double m_dx; 286 double m_dy; 287 double m_scale; 288 unsigned m_vertices; 289 }; 290 291 } 292 293 294 #endif 295 296