Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED 00026 #define AGG_PATH_STORAGE_INTEGER_INCLUDED 00027 00028 #include <string.h> 00029 #include "agg_array.h" 00030 00031 namespace agg 00032 { 00033 //---------------------------------------------------------vertex_integer 00034 template<class T, unsigned CoordShift=6> struct vertex_integer 00035 { 00036 enum path_cmd 00037 { 00038 cmd_move_to = 0, 00039 cmd_line_to = 1, 00040 cmd_curve3 = 2, 00041 cmd_curve4 = 3 00042 }; 00043 00044 enum coord_scale_e 00045 { 00046 coord_shift = CoordShift, 00047 coord_scale = 1 << coord_shift 00048 }; 00049 00050 T x,y; 00051 vertex_integer() {} 00052 vertex_integer(T x_, T y_, unsigned flag) : 00053 x(((x_ << 1) & ~1) | (flag & 1)), 00054 y(((y_ << 1) & ~1) | (flag >> 1)) {} 00055 00056 unsigned vertex(double* x_, double* y_, 00057 double dx=0, double dy=0, 00058 double scale=1.0) const 00059 { 00060 *x_ = dx + (double(x >> 1) / coord_scale) * scale; 00061 *y_ = dy + (double(y >> 1) / coord_scale) * scale; 00062 switch(((y & 1) << 1) | (x & 1)) 00063 { 00064 case cmd_move_to: return path_cmd_move_to; 00065 case cmd_line_to: return path_cmd_line_to; 00066 case cmd_curve3: return path_cmd_curve3; 00067 case cmd_curve4: return path_cmd_curve4; 00068 } 00069 return path_cmd_stop; 00070 } 00071 }; 00072 00073 00074 //---------------------------------------------------path_storage_integer 00075 template<class T, unsigned CoordShift=6> class path_storage_integer 00076 { 00077 public: 00078 typedef T value_type; 00079 typedef vertex_integer<T, CoordShift> vertex_integer_type; 00080 00081 //-------------------------------------------------------------------- 00082 path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {} 00083 00084 //-------------------------------------------------------------------- 00085 void remove_all() { m_storage.remove_all(); } 00086 00087 //-------------------------------------------------------------------- 00088 void move_to(T x, T y) 00089 { 00090 m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to)); 00091 } 00092 00093 //-------------------------------------------------------------------- 00094 void line_to(T x, T y) 00095 { 00096 m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to)); 00097 } 00098 00099 //-------------------------------------------------------------------- 00100 void curve3(T x_ctrl, T y_ctrl, 00101 T x_to, T y_to) 00102 { 00103 m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3)); 00104 m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3)); 00105 } 00106 00107 //-------------------------------------------------------------------- 00108 void curve4(T x_ctrl1, T y_ctrl1, 00109 T x_ctrl2, T y_ctrl2, 00110 T x_to, T y_to) 00111 { 00112 m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4)); 00113 m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4)); 00114 m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4)); 00115 } 00116 00117 //-------------------------------------------------------------------- 00118 void close_polygon() {} 00119 00120 //-------------------------------------------------------------------- 00121 unsigned size() const { return m_storage.size(); } 00122 unsigned vertex(unsigned idx, double* x, double* y) const 00123 { 00124 return m_storage[idx].vertex(x, y); 00125 } 00126 00127 //-------------------------------------------------------------------- 00128 unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); } 00129 void serialize(int8u* ptr) const 00130 { 00131 unsigned i; 00132 for(i = 0; i < m_storage.size(); i++) 00133 { 00134 memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); 00135 ptr += sizeof(vertex_integer_type); 00136 } 00137 } 00138 00139 //-------------------------------------------------------------------- 00140 void rewind(unsigned) 00141 { 00142 m_vertex_idx = 0; 00143 m_closed = true; 00144 } 00145 00146 //-------------------------------------------------------------------- 00147 unsigned vertex(double* x, double* y) 00148 { 00149 if(m_storage.size() < 2 || m_vertex_idx > m_storage.size()) 00150 { 00151 *x = 0; 00152 *y = 0; 00153 return path_cmd_stop; 00154 } 00155 if(m_vertex_idx == m_storage.size()) 00156 { 00157 *x = 0; 00158 *y = 0; 00159 ++m_vertex_idx; 00160 return path_cmd_end_poly | path_flags_close; 00161 } 00162 unsigned cmd = m_storage[m_vertex_idx].vertex(x, y); 00163 if(is_move_to(cmd) && !m_closed) 00164 { 00165 *x = 0; 00166 *y = 0; 00167 m_closed = true; 00168 return path_cmd_end_poly | path_flags_close; 00169 } 00170 m_closed = false; 00171 ++m_vertex_idx; 00172 return cmd; 00173 } 00174 00175 //-------------------------------------------------------------------- 00176 rect_d bounding_rect() const 00177 { 00178 rect_d bounds(1e100, 1e100, -1e100, -1e100); 00179 if(m_storage.size() == 0) 00180 { 00181 bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; 00182 } 00183 else 00184 { 00185 unsigned i; 00186 for(i = 0; i < m_storage.size(); i++) 00187 { 00188 double x, y; 00189 m_storage[i].vertex(&x, &y); 00190 if(x < bounds.x1) bounds.x1 = x; 00191 if(y < bounds.y1) bounds.y1 = y; 00192 if(x > bounds.x2) bounds.x2 = x; 00193 if(y > bounds.y2) bounds.y2 = y; 00194 } 00195 } 00196 return bounds; 00197 } 00198 00199 private: 00200 pod_bvector<vertex_integer_type, 6> m_storage; 00201 unsigned m_vertex_idx; 00202 bool m_closed; 00203 }; 00204 00205 00206 00207 00208 //-----------------------------------------serialized_integer_path_adaptor 00209 template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor 00210 { 00211 public: 00212 typedef vertex_integer<T, CoordShift> vertex_integer_type; 00213 00214 //-------------------------------------------------------------------- 00215 serialized_integer_path_adaptor() : 00216 m_data(0), 00217 m_end(0), 00218 m_ptr(0), 00219 m_dx(0.0), 00220 m_dy(0.0), 00221 m_scale(1.0), 00222 m_vertices(0) 00223 {} 00224 00225 //-------------------------------------------------------------------- 00226 serialized_integer_path_adaptor(const int8u* data, unsigned size, 00227 double dx, double dy) : 00228 m_data(data), 00229 m_end(data + size), 00230 m_ptr(data), 00231 m_dx(dx), 00232 m_dy(dy), 00233 m_vertices(0) 00234 {} 00235 00236 //-------------------------------------------------------------------- 00237 void init(const int8u* data, unsigned size, 00238 double dx, double dy, double scale=1.0) 00239 { 00240 m_data = data; 00241 m_end = data + size; 00242 m_ptr = data; 00243 m_dx = dx; 00244 m_dy = dy; 00245 m_scale = scale; 00246 m_vertices = 0; 00247 } 00248 00249 00250 //-------------------------------------------------------------------- 00251 void rewind(unsigned) 00252 { 00253 m_ptr = m_data; 00254 m_vertices = 0; 00255 } 00256 00257 //-------------------------------------------------------------------- 00258 unsigned vertex(double* x, double* y) 00259 { 00260 if(m_data == 0 || m_ptr > m_end) 00261 { 00262 *x = 0; 00263 *y = 0; 00264 return path_cmd_stop; 00265 } 00266 00267 if(m_ptr == m_end) 00268 { 00269 *x = 0; 00270 *y = 0; 00271 m_ptr += sizeof(vertex_integer_type); 00272 return path_cmd_end_poly | path_flags_close; 00273 } 00274 00275 vertex_integer_type v; 00276 memcpy(&v, m_ptr, sizeof(vertex_integer_type)); 00277 unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale); 00278 if(is_move_to(cmd) && m_vertices > 2) 00279 { 00280 *x = 0; 00281 *y = 0; 00282 m_vertices = 0; 00283 return path_cmd_end_poly | path_flags_close; 00284 } 00285 ++m_vertices; 00286 m_ptr += sizeof(vertex_integer_type); 00287 return cmd; 00288 } 00289 00290 private: 00291 const int8u* m_data; 00292 const int8u* m_end; 00293 const int8u* m_ptr; 00294 double m_dx; 00295 double m_dy; 00296 double m_scale; 00297 unsigned m_vertices; 00298 }; 00299 00300 } 00301 00302 00303 #endif 00304