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