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