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_INCLUDED 00026 #define AGG_PATH_STORAGE_INCLUDED 00027 00028 #include <string.h> 00029 #include <math.h> 00030 #include "agg_math.h" 00031 #include "agg_array.h" 00032 #include "agg_bezier_arc.h" 00033 00034 namespace agg 00035 { 00036 00037 00038 //----------------------------------------------------vertex_block_storage 00039 template<class T, unsigned BlockShift=8, unsigned BlockPool=256> 00040 class vertex_block_storage 00041 { 00042 public: 00043 // Allocation parameters 00044 enum block_scale_e 00045 { 00046 block_shift = BlockShift, 00047 block_size = 1 << block_shift, 00048 block_mask = block_size - 1, 00049 block_pool = BlockPool 00050 }; 00051 00052 typedef T value_type; 00053 typedef vertex_block_storage<T, BlockShift, BlockPool> self_type; 00054 00055 ~vertex_block_storage(); 00056 vertex_block_storage(); 00057 vertex_block_storage(const self_type& v); 00058 const self_type& operator = (const self_type& ps); 00059 00060 void remove_all(); 00061 void free_all(); 00062 00063 void add_vertex(double x, double y, unsigned cmd); 00064 void modify_vertex(unsigned idx, double x, double y); 00065 void modify_vertex(unsigned idx, double x, double y, unsigned cmd); 00066 void modify_command(unsigned idx, unsigned cmd); 00067 void swap_vertices(unsigned v1, unsigned v2); 00068 00069 unsigned last_command() const; 00070 unsigned last_vertex(double* x, double* y) const; 00071 unsigned prev_vertex(double* x, double* y) const; 00072 00073 double last_x() const; 00074 double last_y() const; 00075 00076 unsigned total_vertices() const; 00077 unsigned vertex(unsigned idx, double* x, double* y) const; 00078 unsigned command(unsigned idx) const; 00079 00080 private: 00081 void allocate_block(unsigned nb); 00082 int8u* storage_ptrs(T** xy_ptr); 00083 00084 private: 00085 unsigned m_total_vertices; 00086 unsigned m_total_blocks; 00087 unsigned m_max_blocks; 00088 T** m_coord_blocks; 00089 int8u** m_cmd_blocks; 00090 }; 00091 00092 00093 //------------------------------------------------------------------------ 00094 template<class T, unsigned S, unsigned P> 00095 void vertex_block_storage<T,S,P>::free_all() 00096 { 00097 if(m_total_blocks) 00098 { 00099 T** coord_blk = m_coord_blocks + m_total_blocks - 1; 00100 while(m_total_blocks--) 00101 { 00102 pod_allocator<T>::deallocate( 00103 *coord_blk, 00104 block_size * 2 + 00105 block_size / (sizeof(T) / sizeof(unsigned char))); 00106 --coord_blk; 00107 } 00108 pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); 00109 m_total_blocks = 0; 00110 m_max_blocks = 0; 00111 m_coord_blocks = 0; 00112 m_cmd_blocks = 0; 00113 m_total_vertices = 0; 00114 } 00115 } 00116 00117 //------------------------------------------------------------------------ 00118 template<class T, unsigned S, unsigned P> 00119 vertex_block_storage<T,S,P>::~vertex_block_storage() 00120 { 00121 free_all(); 00122 } 00123 00124 //------------------------------------------------------------------------ 00125 template<class T, unsigned S, unsigned P> 00126 vertex_block_storage<T,S,P>::vertex_block_storage() : 00127 m_total_vertices(0), 00128 m_total_blocks(0), 00129 m_max_blocks(0), 00130 m_coord_blocks(0), 00131 m_cmd_blocks(0) 00132 { 00133 } 00134 00135 //------------------------------------------------------------------------ 00136 template<class T, unsigned S, unsigned P> 00137 vertex_block_storage<T,S,P>::vertex_block_storage(const vertex_block_storage<T,S,P>& v) : 00138 m_total_vertices(0), 00139 m_total_blocks(0), 00140 m_max_blocks(0), 00141 m_coord_blocks(0), 00142 m_cmd_blocks(0) 00143 { 00144 *this = v; 00145 } 00146 00147 //------------------------------------------------------------------------ 00148 template<class T, unsigned S, unsigned P> 00149 const vertex_block_storage<T,S,P>& 00150 vertex_block_storage<T,S,P>::operator = (const vertex_block_storage<T,S,P>& v) 00151 { 00152 remove_all(); 00153 unsigned i; 00154 for(i = 0; i < v.total_vertices(); i++) 00155 { 00156 double x, y; 00157 unsigned cmd = v.vertex(i, &x, &y); 00158 add_vertex(x, y, cmd); 00159 } 00160 return *this; 00161 } 00162 00163 //------------------------------------------------------------------------ 00164 template<class T, unsigned S, unsigned P> 00165 inline void vertex_block_storage<T,S,P>::remove_all() 00166 { 00167 m_total_vertices = 0; 00168 } 00169 00170 //------------------------------------------------------------------------ 00171 template<class T, unsigned S, unsigned P> 00172 inline void vertex_block_storage<T,S,P>::add_vertex(double x, double y, 00173 unsigned cmd) 00174 { 00175 T* coord_ptr = 0; 00176 *storage_ptrs(&coord_ptr) = (int8u)cmd; 00177 coord_ptr[0] = T(x); 00178 coord_ptr[1] = T(y); 00179 m_total_vertices++; 00180 } 00181 00182 //------------------------------------------------------------------------ 00183 template<class T, unsigned S, unsigned P> 00184 inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, 00185 double x, double y) 00186 { 00187 T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); 00188 pv[0] = T(x); 00189 pv[1] = T(y); 00190 } 00191 00192 //------------------------------------------------------------------------ 00193 template<class T, unsigned S, unsigned P> 00194 inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, 00195 double x, double y, 00196 unsigned cmd) 00197 { 00198 unsigned block = idx >> block_shift; 00199 unsigned offset = idx & block_mask; 00200 T* pv = m_coord_blocks[block] + (offset << 1); 00201 pv[0] = T(x); 00202 pv[1] = T(y); 00203 m_cmd_blocks[block][offset] = (int8u)cmd; 00204 } 00205 00206 //------------------------------------------------------------------------ 00207 template<class T, unsigned S, unsigned P> 00208 inline void vertex_block_storage<T,S,P>::modify_command(unsigned idx, 00209 unsigned cmd) 00210 { 00211 m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd; 00212 } 00213 00214 //------------------------------------------------------------------------ 00215 template<class T, unsigned S, unsigned P> 00216 inline void vertex_block_storage<T,S,P>::swap_vertices(unsigned v1, unsigned v2) 00217 { 00218 unsigned b1 = v1 >> block_shift; 00219 unsigned b2 = v2 >> block_shift; 00220 unsigned o1 = v1 & block_mask; 00221 unsigned o2 = v2 & block_mask; 00222 T* pv1 = m_coord_blocks[b1] + (o1 << 1); 00223 T* pv2 = m_coord_blocks[b2] + (o2 << 1); 00224 T val; 00225 val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val; 00226 val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val; 00227 int8u cmd = m_cmd_blocks[b1][o1]; 00228 m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2]; 00229 m_cmd_blocks[b2][o2] = cmd; 00230 } 00231 00232 //------------------------------------------------------------------------ 00233 template<class T, unsigned S, unsigned P> 00234 inline unsigned vertex_block_storage<T,S,P>::last_command() const 00235 { 00236 if(m_total_vertices) return command(m_total_vertices - 1); 00237 return path_cmd_stop; 00238 } 00239 00240 //------------------------------------------------------------------------ 00241 template<class T, unsigned S, unsigned P> 00242 inline unsigned vertex_block_storage<T,S,P>::last_vertex(double* x, double* y) const 00243 { 00244 if(m_total_vertices) return vertex(m_total_vertices - 1, x, y); 00245 return path_cmd_stop; 00246 } 00247 00248 //------------------------------------------------------------------------ 00249 template<class T, unsigned S, unsigned P> 00250 inline unsigned vertex_block_storage<T,S,P>::prev_vertex(double* x, double* y) const 00251 { 00252 if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y); 00253 return path_cmd_stop; 00254 } 00255 00256 //------------------------------------------------------------------------ 00257 template<class T, unsigned S, unsigned P> 00258 inline double vertex_block_storage<T,S,P>::last_x() const 00259 { 00260 if(m_total_vertices) 00261 { 00262 unsigned idx = m_total_vertices - 1; 00263 return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1]; 00264 } 00265 return 0.0; 00266 } 00267 00268 //------------------------------------------------------------------------ 00269 template<class T, unsigned S, unsigned P> 00270 inline double vertex_block_storage<T,S,P>::last_y() const 00271 { 00272 if(m_total_vertices) 00273 { 00274 unsigned idx = m_total_vertices - 1; 00275 return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1]; 00276 } 00277 return 0.0; 00278 } 00279 00280 //------------------------------------------------------------------------ 00281 template<class T, unsigned S, unsigned P> 00282 inline unsigned vertex_block_storage<T,S,P>::total_vertices() const 00283 { 00284 return m_total_vertices; 00285 } 00286 00287 //------------------------------------------------------------------------ 00288 template<class T, unsigned S, unsigned P> 00289 inline unsigned vertex_block_storage<T,S,P>::vertex(unsigned idx, 00290 double* x, double* y) const 00291 { 00292 unsigned nb = idx >> block_shift; 00293 const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); 00294 *x = pv[0]; 00295 *y = pv[1]; 00296 return m_cmd_blocks[nb][idx & block_mask]; 00297 } 00298 00299 //------------------------------------------------------------------------ 00300 template<class T, unsigned S, unsigned P> 00301 inline unsigned vertex_block_storage<T,S,P>::command(unsigned idx) const 00302 { 00303 return m_cmd_blocks[idx >> block_shift][idx & block_mask]; 00304 } 00305 00306 //------------------------------------------------------------------------ 00307 template<class T, unsigned S, unsigned P> 00308 void vertex_block_storage<T,S,P>::allocate_block(unsigned nb) 00309 { 00310 if(nb >= m_max_blocks) 00311 { 00312 T** new_coords = 00313 pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2); 00314 00315 unsigned char** new_cmds = 00316 (unsigned char**)(new_coords + m_max_blocks + block_pool); 00317 00318 if(m_coord_blocks) 00319 { 00320 memcpy(new_coords, 00321 m_coord_blocks, 00322 m_max_blocks * sizeof(T*)); 00323 00324 memcpy(new_cmds, 00325 m_cmd_blocks, 00326 m_max_blocks * sizeof(unsigned char*)); 00327 00328 pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); 00329 } 00330 m_coord_blocks = new_coords; 00331 m_cmd_blocks = new_cmds; 00332 m_max_blocks += block_pool; 00333 } 00334 m_coord_blocks[nb] = 00335 pod_allocator<T>::allocate(block_size * 2 + 00336 block_size / (sizeof(T) / sizeof(unsigned char))); 00337 00338 m_cmd_blocks[nb] = 00339 (unsigned char*)(m_coord_blocks[nb] + block_size * 2); 00340 00341 m_total_blocks++; 00342 } 00343 00344 //------------------------------------------------------------------------ 00345 template<class T, unsigned S, unsigned P> 00346 int8u* vertex_block_storage<T,S,P>::storage_ptrs(T** xy_ptr) 00347 { 00348 unsigned nb = m_total_vertices >> block_shift; 00349 if(nb >= m_total_blocks) 00350 { 00351 allocate_block(nb); 00352 } 00353 *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); 00354 return m_cmd_blocks[nb] + (m_total_vertices & block_mask); 00355 } 00356 00357 00358 00359 00360 //-----------------------------------------------------poly_plain_adaptor 00361 template<class T> class poly_plain_adaptor 00362 { 00363 public: 00364 typedef T value_type; 00365 00366 poly_plain_adaptor() : 00367 m_data(0), 00368 m_ptr(0), 00369 m_end(0), 00370 m_closed(false), 00371 m_stop(false) 00372 {} 00373 00374 poly_plain_adaptor(const T* data, unsigned num_points, bool closed) : 00375 m_data(data), 00376 m_ptr(data), 00377 m_end(data + num_points * 2), 00378 m_closed(closed), 00379 m_stop(false) 00380 {} 00381 00382 void init(const T* data, unsigned num_points, bool closed) 00383 { 00384 m_data = data; 00385 m_ptr = data; 00386 m_end = data + num_points * 2; 00387 m_closed = closed; 00388 m_stop = false; 00389 } 00390 00391 void rewind(unsigned) 00392 { 00393 m_ptr = m_data; 00394 m_stop = false; 00395 } 00396 00397 unsigned vertex(double* x, double* y) 00398 { 00399 if(m_ptr < m_end) 00400 { 00401 bool first = m_ptr == m_data; 00402 *x = *m_ptr++; 00403 *y = *m_ptr++; 00404 return first ? path_cmd_move_to : path_cmd_line_to; 00405 } 00406 *x = *y = 0.0; 00407 if(m_closed && !m_stop) 00408 { 00409 m_stop = true; 00410 return path_cmd_end_poly | path_flags_close; 00411 } 00412 return path_cmd_stop; 00413 } 00414 00415 private: 00416 const T* m_data; 00417 const T* m_ptr; 00418 const T* m_end; 00419 bool m_closed; 00420 bool m_stop; 00421 }; 00422 00423 00424 00425 00426 00427 //-------------------------------------------------poly_container_adaptor 00428 template<class Container> class poly_container_adaptor 00429 { 00430 public: 00431 typedef typename Container::value_type vertex_type; 00432 00433 poly_container_adaptor() : 00434 m_container(0), 00435 m_index(0), 00436 m_closed(false), 00437 m_stop(false) 00438 {} 00439 00440 poly_container_adaptor(const Container& data, bool closed) : 00441 m_container(&data), 00442 m_index(0), 00443 m_closed(closed), 00444 m_stop(false) 00445 {} 00446 00447 void init(const Container& data, bool closed) 00448 { 00449 m_container = &data; 00450 m_index = 0; 00451 m_closed = closed; 00452 m_stop = false; 00453 } 00454 00455 void rewind(unsigned) 00456 { 00457 m_index = 0; 00458 m_stop = false; 00459 } 00460 00461 unsigned vertex(double* x, double* y) 00462 { 00463 if(m_index < m_container->size()) 00464 { 00465 bool first = m_index == 0; 00466 const vertex_type& v = (*m_container)[m_index++]; 00467 *x = v.x; 00468 *y = v.y; 00469 return first ? path_cmd_move_to : path_cmd_line_to; 00470 } 00471 *x = *y = 0.0; 00472 if(m_closed && !m_stop) 00473 { 00474 m_stop = true; 00475 return path_cmd_end_poly | path_flags_close; 00476 } 00477 return path_cmd_stop; 00478 } 00479 00480 private: 00481 const Container* m_container; 00482 unsigned m_index; 00483 bool m_closed; 00484 bool m_stop; 00485 }; 00486 00487 00488 00489 //-----------------------------------------poly_container_reverse_adaptor 00490 template<class Container> class poly_container_reverse_adaptor 00491 { 00492 public: 00493 typedef typename Container::value_type vertex_type; 00494 00495 poly_container_reverse_adaptor() : 00496 m_container(0), 00497 m_index(-1), 00498 m_closed(false), 00499 m_stop(false) 00500 {} 00501 00502 poly_container_reverse_adaptor(const Container& data, bool closed) : 00503 m_container(&data), 00504 m_index(-1), 00505 m_closed(closed), 00506 m_stop(false) 00507 {} 00508 00509 void init(const Container& data, bool closed) 00510 { 00511 m_container = &data; 00512 m_index = m_container->size() - 1; 00513 m_closed = closed; 00514 m_stop = false; 00515 } 00516 00517 void rewind(unsigned) 00518 { 00519 m_index = m_container->size() - 1; 00520 m_stop = false; 00521 } 00522 00523 unsigned vertex(double* x, double* y) 00524 { 00525 if(m_index >= 0) 00526 { 00527 bool first = m_index == int(m_container->size() - 1); 00528 const vertex_type& v = (*m_container)[m_index--]; 00529 *x = v.x; 00530 *y = v.y; 00531 return first ? path_cmd_move_to : path_cmd_line_to; 00532 } 00533 *x = *y = 0.0; 00534 if(m_closed && !m_stop) 00535 { 00536 m_stop = true; 00537 return path_cmd_end_poly | path_flags_close; 00538 } 00539 return path_cmd_stop; 00540 } 00541 00542 private: 00543 const Container* m_container; 00544 int m_index; 00545 bool m_closed; 00546 bool m_stop; 00547 }; 00548 00549 00550 00551 00552 00553 //--------------------------------------------------------line_adaptor 00554 class line_adaptor 00555 { 00556 public: 00557 typedef double value_type; 00558 00559 line_adaptor() : m_line(m_coord, 2, false) {} 00560 line_adaptor(double x1, double y1, double x2, double y2) : 00561 m_line(m_coord, 2, false) 00562 { 00563 m_coord[0] = x1; 00564 m_coord[1] = y1; 00565 m_coord[2] = x2; 00566 m_coord[3] = y2; 00567 } 00568 00569 void init(double x1, double y1, double x2, double y2) 00570 { 00571 m_coord[0] = x1; 00572 m_coord[1] = y1; 00573 m_coord[2] = x2; 00574 m_coord[3] = y2; 00575 m_line.rewind(0); 00576 } 00577 00578 void rewind(unsigned) 00579 { 00580 m_line.rewind(0); 00581 } 00582 00583 unsigned vertex(double* x, double* y) 00584 { 00585 return m_line.vertex(x, y); 00586 } 00587 00588 private: 00589 double m_coord[4]; 00590 poly_plain_adaptor<double> m_line; 00591 }; 00592 00593 00594 00595 00596 00597 00598 00599 00600 00601 00602 00603 00604 00605 //---------------------------------------------------------------path_base 00606 // A container to store vertices with their flags. 00607 // A path consists of a number of contours separated with "move_to" 00608 // commands. The path storage can keep and maintain more than one 00609 // path. 00610 // To navigate to the beginning of a particular path, use rewind(path_id); 00611 // Where path_id is what start_new_path() returns. So, when you call 00612 // start_new_path() you need to store its return value somewhere else 00613 // to navigate to the path afterwards. 00614 // 00615 // See also: vertex_source concept 00616 //------------------------------------------------------------------------ 00617 template<class VertexContainer> class path_base 00618 { 00619 public: 00620 typedef VertexContainer container_type; 00621 typedef path_base<VertexContainer> self_type; 00622 00623 //-------------------------------------------------------------------- 00624 path_base() : m_vertices(), m_iterator(0) {} 00625 void remove_all() { m_vertices.remove_all(); m_iterator = 0; } 00626 void free_all() { m_vertices.free_all(); m_iterator = 0; } 00627 00628 // Make path functions 00629 //-------------------------------------------------------------------- 00630 unsigned start_new_path(); 00631 00632 void move_to(double x, double y); 00633 void move_rel(double dx, double dy); 00634 00635 void line_to(double x, double y); 00636 void line_rel(double dx, double dy); 00637 00638 void hline_to(double x); 00639 void hline_rel(double dx); 00640 00641 void vline_to(double y); 00642 void vline_rel(double dy); 00643 00644 void arc_to(double rx, double ry, 00645 double angle, 00646 bool large_arc_flag, 00647 bool sweep_flag, 00648 double x, double y); 00649 00650 void arc_rel(double rx, double ry, 00651 double angle, 00652 bool large_arc_flag, 00653 bool sweep_flag, 00654 double dx, double dy); 00655 00656 void curve3(double x_ctrl, double y_ctrl, 00657 double x_to, double y_to); 00658 00659 void curve3_rel(double dx_ctrl, double dy_ctrl, 00660 double dx_to, double dy_to); 00661 00662 void curve3(double x_to, double y_to); 00663 00664 void curve3_rel(double dx_to, double dy_to); 00665 00666 void curve4(double x_ctrl1, double y_ctrl1, 00667 double x_ctrl2, double y_ctrl2, 00668 double x_to, double y_to); 00669 00670 void curve4_rel(double dx_ctrl1, double dy_ctrl1, 00671 double dx_ctrl2, double dy_ctrl2, 00672 double dx_to, double dy_to); 00673 00674 void curve4(double x_ctrl2, double y_ctrl2, 00675 double x_to, double y_to); 00676 00677 void curve4_rel(double x_ctrl2, double y_ctrl2, 00678 double x_to, double y_to); 00679 00680 00681 void end_poly(unsigned flags = path_flags_close); 00682 void close_polygon(unsigned flags = path_flags_none); 00683 00684 // Accessors 00685 //-------------------------------------------------------------------- 00686 const container_type& vertices() const { return m_vertices; } 00687 container_type& vertices() { return m_vertices; } 00688 00689 unsigned total_vertices() const; 00690 00691 void rel_to_abs(double* x, double* y) const; 00692 00693 unsigned last_vertex(double* x, double* y) const; 00694 unsigned prev_vertex(double* x, double* y) const; 00695 00696 double last_x() const; 00697 double last_y() const; 00698 00699 unsigned vertex(unsigned idx, double* x, double* y) const; 00700 unsigned command(unsigned idx) const; 00701 00702 void modify_vertex(unsigned idx, double x, double y); 00703 void modify_vertex(unsigned idx, double x, double y, unsigned cmd); 00704 void modify_command(unsigned idx, unsigned cmd); 00705 00706 // VertexSource interface 00707 //-------------------------------------------------------------------- 00708 void rewind(unsigned path_id); 00709 unsigned vertex(double* x, double* y); 00710 00711 // Arrange the orientation of a polygon, all polygons in a path, 00712 // or in all paths. After calling arrange_orientations() or 00713 // arrange_orientations_all_paths(), all the polygons will have 00714 // the same orientation, i.e. path_flags_cw or path_flags_ccw 00715 //-------------------------------------------------------------------- 00716 unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation); 00717 unsigned arrange_orientations(unsigned path_id, path_flags_e orientation); 00718 void arrange_orientations_all_paths(path_flags_e orientation); 00719 void invert_polygon(unsigned start); 00720 00721 // Flip all vertices horizontally or vertically, 00722 // between x1 and x2, or between y1 and y2 respectively 00723 //-------------------------------------------------------------------- 00724 void flip_x(double x1, double x2); 00725 void flip_y(double y1, double y2); 00726 00727 // Concatenate path. The path is added as is. 00728 //-------------------------------------------------------------------- 00729 template<class VertexSource> 00730 void concat_path(VertexSource& vs, unsigned path_id = 0) 00731 { 00732 double x, y; 00733 unsigned cmd; 00734 vs.rewind(path_id); 00735 while(!is_stop(cmd = vs.vertex(&x, &y))) 00736 { 00737 m_vertices.add_vertex(x, y, cmd); 00738 } 00739 } 00740 00741 //-------------------------------------------------------------------- 00742 // Join path. The path is joined with the existing one, that is, 00743 // it behaves as if the pen of a plotter was always down (drawing) 00744 template<class VertexSource> 00745 void join_path(VertexSource& vs, unsigned path_id = 0) 00746 { 00747 double x, y; 00748 unsigned cmd; 00749 vs.rewind(path_id); 00750 cmd = vs.vertex(&x, &y); 00751 if(!is_stop(cmd)) 00752 { 00753 if(is_vertex(cmd)) 00754 { 00755 double x0, y0; 00756 unsigned cmd0 = last_vertex(&x0, &y0); 00757 if(is_vertex(cmd0)) 00758 { 00759 if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon) 00760 { 00761 if(is_move_to(cmd)) cmd = path_cmd_line_to; 00762 m_vertices.add_vertex(x, y, cmd); 00763 } 00764 } 00765 else 00766 { 00767 if(is_stop(cmd0)) 00768 { 00769 cmd = path_cmd_move_to; 00770 } 00771 else 00772 { 00773 if(is_move_to(cmd)) cmd = path_cmd_line_to; 00774 } 00775 m_vertices.add_vertex(x, y, cmd); 00776 } 00777 } 00778 while(!is_stop(cmd = vs.vertex(&x, &y))) 00779 { 00780 m_vertices.add_vertex(x, y, is_move_to(cmd) ? 00781 unsigned(path_cmd_line_to) : 00782 cmd); 00783 } 00784 } 00785 } 00786 00787 // Concatenate polygon/polyline. 00788 //-------------------------------------------------------------------- 00789 template<class T> void concat_poly(const T* data, 00790 unsigned num_points, 00791 bool closed) 00792 { 00793 poly_plain_adaptor<T> poly(data, num_points, closed); 00794 concat_path(poly); 00795 } 00796 00797 // Join polygon/polyline continuously. 00798 //-------------------------------------------------------------------- 00799 template<class T> void join_poly(const T* data, 00800 unsigned num_points, 00801 bool closed) 00802 { 00803 poly_plain_adaptor<T> poly(data, num_points, closed); 00804 join_path(poly); 00805 } 00806 00807 //-------------------------------------------------------------------- 00808 void translate(double dx, double dy, unsigned path_id=0); 00809 void translate_all_paths(double dx, double dy); 00810 00811 //-------------------------------------------------------------------- 00812 template<class Trans> 00813 void transform(const Trans& trans, unsigned path_id=0) 00814 { 00815 unsigned num_ver = m_vertices.total_vertices(); 00816 for(; path_id < num_ver; path_id++) 00817 { 00818 double x, y; 00819 unsigned cmd = m_vertices.vertex(path_id, &x, &y); 00820 if(is_stop(cmd)) break; 00821 if(is_vertex(cmd)) 00822 { 00823 trans.transform(&x, &y); 00824 m_vertices.modify_vertex(path_id, x, y); 00825 } 00826 } 00827 } 00828 00829 //-------------------------------------------------------------------- 00830 template<class Trans> 00831 void transform_all_paths(const Trans& trans) 00832 { 00833 unsigned idx; 00834 unsigned num_ver = m_vertices.total_vertices(); 00835 for(idx = 0; idx < num_ver; idx++) 00836 { 00837 double x, y; 00838 if(is_vertex(m_vertices.vertex(idx, &x, &y))) 00839 { 00840 trans.transform(&x, &y); 00841 m_vertices.modify_vertex(idx, x, y); 00842 } 00843 } 00844 } 00845 00846 00847 00848 private: 00849 unsigned perceive_polygon_orientation(unsigned start, unsigned end); 00850 void invert_polygon(unsigned start, unsigned end); 00851 00852 VertexContainer m_vertices; 00853 unsigned m_iterator; 00854 }; 00855 00856 //------------------------------------------------------------------------ 00857 template<class VC> 00858 unsigned path_base<VC>::start_new_path() 00859 { 00860 if(!is_stop(m_vertices.last_command())) 00861 { 00862 m_vertices.add_vertex(0.0, 0.0, path_cmd_stop); 00863 } 00864 return m_vertices.total_vertices(); 00865 } 00866 00867 00868 //------------------------------------------------------------------------ 00869 template<class VC> 00870 inline void path_base<VC>::rel_to_abs(double* x, double* y) const 00871 { 00872 if(m_vertices.total_vertices()) 00873 { 00874 double x2; 00875 double y2; 00876 if(is_vertex(m_vertices.last_vertex(&x2, &y2))) 00877 { 00878 *x += x2; 00879 *y += y2; 00880 } 00881 } 00882 } 00883 00884 //------------------------------------------------------------------------ 00885 template<class VC> 00886 inline void path_base<VC>::move_to(double x, double y) 00887 { 00888 m_vertices.add_vertex(x, y, path_cmd_move_to); 00889 } 00890 00891 //------------------------------------------------------------------------ 00892 template<class VC> 00893 inline void path_base<VC>::move_rel(double dx, double dy) 00894 { 00895 rel_to_abs(&dx, &dy); 00896 m_vertices.add_vertex(dx, dy, path_cmd_move_to); 00897 } 00898 00899 //------------------------------------------------------------------------ 00900 template<class VC> 00901 inline void path_base<VC>::line_to(double x, double y) 00902 { 00903 m_vertices.add_vertex(x, y, path_cmd_line_to); 00904 } 00905 00906 //------------------------------------------------------------------------ 00907 template<class VC> 00908 inline void path_base<VC>::line_rel(double dx, double dy) 00909 { 00910 rel_to_abs(&dx, &dy); 00911 m_vertices.add_vertex(dx, dy, path_cmd_line_to); 00912 } 00913 00914 //------------------------------------------------------------------------ 00915 template<class VC> 00916 inline void path_base<VC>::hline_to(double x) 00917 { 00918 m_vertices.add_vertex(x, last_y(), path_cmd_line_to); 00919 } 00920 00921 //------------------------------------------------------------------------ 00922 template<class VC> 00923 inline void path_base<VC>::hline_rel(double dx) 00924 { 00925 double dy = 0; 00926 rel_to_abs(&dx, &dy); 00927 m_vertices.add_vertex(dx, dy, path_cmd_line_to); 00928 } 00929 00930 //------------------------------------------------------------------------ 00931 template<class VC> 00932 inline void path_base<VC>::vline_to(double y) 00933 { 00934 m_vertices.add_vertex(last_x(), y, path_cmd_line_to); 00935 } 00936 00937 //------------------------------------------------------------------------ 00938 template<class VC> 00939 inline void path_base<VC>::vline_rel(double dy) 00940 { 00941 double dx = 0; 00942 rel_to_abs(&dx, &dy); 00943 m_vertices.add_vertex(dx, dy, path_cmd_line_to); 00944 } 00945 00946 //------------------------------------------------------------------------ 00947 template<class VC> 00948 void path_base<VC>::arc_to(double rx, double ry, 00949 double angle, 00950 bool large_arc_flag, 00951 bool sweep_flag, 00952 double x, double y) 00953 { 00954 if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command())) 00955 { 00956 const double epsilon = 1e-30; 00957 double x0 = 0.0; 00958 double y0 = 0.0; 00959 m_vertices.last_vertex(&x0, &y0); 00960 00961 rx = fabs(rx); 00962 ry = fabs(ry); 00963 00964 // Ensure radii are valid 00965 //------------------------- 00966 if(rx < epsilon || ry < epsilon) 00967 { 00968 line_to(x, y); 00969 return; 00970 } 00971 00972 if(calc_distance(x0, y0, x, y) < epsilon) 00973 { 00974 // If the endpoints (x, y) and (x0, y0) are identical, then this 00975 // is equivalent to omitting the elliptical arc segment entirely. 00976 return; 00977 } 00978 bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); 00979 if(a.radii_ok()) 00980 { 00981 join_path(a); 00982 } 00983 else 00984 { 00985 line_to(x, y); 00986 } 00987 } 00988 else 00989 { 00990 move_to(x, y); 00991 } 00992 } 00993 00994 //------------------------------------------------------------------------ 00995 template<class VC> 00996 void path_base<VC>::arc_rel(double rx, double ry, 00997 double angle, 00998 bool large_arc_flag, 00999 bool sweep_flag, 01000 double dx, double dy) 01001 { 01002 rel_to_abs(&dx, &dy); 01003 arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); 01004 } 01005 01006 //------------------------------------------------------------------------ 01007 template<class VC> 01008 void path_base<VC>::curve3(double x_ctrl, double y_ctrl, 01009 double x_to, double y_to) 01010 { 01011 m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); 01012 m_vertices.add_vertex(x_to, y_to, path_cmd_curve3); 01013 } 01014 01015 //------------------------------------------------------------------------ 01016 template<class VC> 01017 void path_base<VC>::curve3_rel(double dx_ctrl, double dy_ctrl, 01018 double dx_to, double dy_to) 01019 { 01020 rel_to_abs(&dx_ctrl, &dy_ctrl); 01021 rel_to_abs(&dx_to, &dy_to); 01022 m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); 01023 m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3); 01024 } 01025 01026 //------------------------------------------------------------------------ 01027 template<class VC> 01028 void path_base<VC>::curve3(double x_to, double y_to) 01029 { 01030 double x0; 01031 double y0; 01032 if(is_vertex(m_vertices.last_vertex(&x0, &y0))) 01033 { 01034 double x_ctrl; 01035 double y_ctrl; 01036 unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl); 01037 if(is_curve(cmd)) 01038 { 01039 x_ctrl = x0 + x0 - x_ctrl; 01040 y_ctrl = y0 + y0 - y_ctrl; 01041 } 01042 else 01043 { 01044 x_ctrl = x0; 01045 y_ctrl = y0; 01046 } 01047 curve3(x_ctrl, y_ctrl, x_to, y_to); 01048 } 01049 } 01050 01051 //------------------------------------------------------------------------ 01052 template<class VC> 01053 void path_base<VC>::curve3_rel(double dx_to, double dy_to) 01054 { 01055 rel_to_abs(&dx_to, &dy_to); 01056 curve3(dx_to, dy_to); 01057 } 01058 01059 //------------------------------------------------------------------------ 01060 template<class VC> 01061 void path_base<VC>::curve4(double x_ctrl1, double y_ctrl1, 01062 double x_ctrl2, double y_ctrl2, 01063 double x_to, double y_to) 01064 { 01065 m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); 01066 m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); 01067 m_vertices.add_vertex(x_to, y_to, path_cmd_curve4); 01068 } 01069 01070 //------------------------------------------------------------------------ 01071 template<class VC> 01072 void path_base<VC>::curve4_rel(double dx_ctrl1, double dy_ctrl1, 01073 double dx_ctrl2, double dy_ctrl2, 01074 double dx_to, double dy_to) 01075 { 01076 rel_to_abs(&dx_ctrl1, &dy_ctrl1); 01077 rel_to_abs(&dx_ctrl2, &dy_ctrl2); 01078 rel_to_abs(&dx_to, &dy_to); 01079 m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); 01080 m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); 01081 m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4); 01082 } 01083 01084 //------------------------------------------------------------------------ 01085 template<class VC> 01086 void path_base<VC>::curve4(double x_ctrl2, double y_ctrl2, 01087 double x_to, double y_to) 01088 { 01089 double x0; 01090 double y0; 01091 if(is_vertex(last_vertex(&x0, &y0))) 01092 { 01093 double x_ctrl1; 01094 double y_ctrl1; 01095 unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); 01096 if(is_curve(cmd)) 01097 { 01098 x_ctrl1 = x0 + x0 - x_ctrl1; 01099 y_ctrl1 = y0 + y0 - y_ctrl1; 01100 } 01101 else 01102 { 01103 x_ctrl1 = x0; 01104 y_ctrl1 = y0; 01105 } 01106 curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); 01107 } 01108 } 01109 01110 //------------------------------------------------------------------------ 01111 template<class VC> 01112 void path_base<VC>::curve4_rel(double dx_ctrl2, double dy_ctrl2, 01113 double dx_to, double dy_to) 01114 { 01115 rel_to_abs(&dx_ctrl2, &dy_ctrl2); 01116 rel_to_abs(&dx_to, &dy_to); 01117 curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); 01118 } 01119 01120 //------------------------------------------------------------------------ 01121 template<class VC> 01122 inline void path_base<VC>::end_poly(unsigned flags) 01123 { 01124 if(is_vertex(m_vertices.last_command())) 01125 { 01126 m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags); 01127 } 01128 } 01129 01130 //------------------------------------------------------------------------ 01131 template<class VC> 01132 inline void path_base<VC>::close_polygon(unsigned flags) 01133 { 01134 end_poly(path_flags_close | flags); 01135 } 01136 01137 //------------------------------------------------------------------------ 01138 template<class VC> 01139 inline unsigned path_base<VC>::total_vertices() const 01140 { 01141 return m_vertices.total_vertices(); 01142 } 01143 01144 //------------------------------------------------------------------------ 01145 template<class VC> 01146 inline unsigned path_base<VC>::last_vertex(double* x, double* y) const 01147 { 01148 return m_vertices.last_vertex(x, y); 01149 } 01150 01151 //------------------------------------------------------------------------ 01152 template<class VC> 01153 inline unsigned path_base<VC>::prev_vertex(double* x, double* y) const 01154 { 01155 return m_vertices.prev_vertex(x, y); 01156 } 01157 01158 //------------------------------------------------------------------------ 01159 template<class VC> 01160 inline double path_base<VC>::last_x() const 01161 { 01162 return m_vertices.last_x(); 01163 } 01164 01165 //------------------------------------------------------------------------ 01166 template<class VC> 01167 inline double path_base<VC>::last_y() const 01168 { 01169 return m_vertices.last_y(); 01170 } 01171 01172 //------------------------------------------------------------------------ 01173 template<class VC> 01174 inline unsigned path_base<VC>::vertex(unsigned idx, double* x, double* y) const 01175 { 01176 return m_vertices.vertex(idx, x, y); 01177 } 01178 01179 //------------------------------------------------------------------------ 01180 template<class VC> 01181 inline unsigned path_base<VC>::command(unsigned idx) const 01182 { 01183 return m_vertices.command(idx); 01184 } 01185 01186 //------------------------------------------------------------------------ 01187 template<class VC> 01188 void path_base<VC>::modify_vertex(unsigned idx, double x, double y) 01189 { 01190 m_vertices.modify_vertex(idx, x, y); 01191 } 01192 01193 //------------------------------------------------------------------------ 01194 template<class VC> 01195 void path_base<VC>::modify_vertex(unsigned idx, double x, double y, unsigned cmd) 01196 { 01197 m_vertices.modify_vertex(idx, x, y, cmd); 01198 } 01199 01200 //------------------------------------------------------------------------ 01201 template<class VC> 01202 void path_base<VC>::modify_command(unsigned idx, unsigned cmd) 01203 { 01204 m_vertices.modify_command(idx, cmd); 01205 } 01206 01207 //------------------------------------------------------------------------ 01208 template<class VC> 01209 inline void path_base<VC>::rewind(unsigned path_id) 01210 { 01211 m_iterator = path_id; 01212 } 01213 01214 //------------------------------------------------------------------------ 01215 template<class VC> 01216 inline unsigned path_base<VC>::vertex(double* x, double* y) 01217 { 01218 if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop; 01219 return m_vertices.vertex(m_iterator++, x, y); 01220 } 01221 01222 //------------------------------------------------------------------------ 01223 template<class VC> 01224 unsigned path_base<VC>::perceive_polygon_orientation(unsigned start, 01225 unsigned end) 01226 { 01227 // Calculate signed area (double area to be exact) 01228 //--------------------- 01229 unsigned np = end - start; 01230 double area = 0.0; 01231 unsigned i; 01232 for(i = 0; i < np; i++) 01233 { 01234 double x1, y1, x2, y2; 01235 m_vertices.vertex(start + i, &x1, &y1); 01236 m_vertices.vertex(start + (i + 1) % np, &x2, &y2); 01237 area += x1 * y2 - y1 * x2; 01238 } 01239 return (area < 0.0) ? path_flags_cw : path_flags_ccw; 01240 } 01241 01242 //------------------------------------------------------------------------ 01243 template<class VC> 01244 void path_base<VC>::invert_polygon(unsigned start, unsigned end) 01245 { 01246 unsigned i; 01247 unsigned tmp_cmd = m_vertices.command(start); 01248 01249 --end; // Make "end" inclusive 01250 01251 // Shift all commands to one position 01252 for(i = start; i < end; i++) 01253 { 01254 m_vertices.modify_command(i, m_vertices.command(i + 1)); 01255 } 01256 01257 // Assign starting command to the ending command 01258 m_vertices.modify_command(end, tmp_cmd); 01259 01260 // Reverse the polygon 01261 while(end > start) 01262 { 01263 m_vertices.swap_vertices(start++, end--); 01264 } 01265 } 01266 01267 //------------------------------------------------------------------------ 01268 template<class VC> 01269 void path_base<VC>::invert_polygon(unsigned start) 01270 { 01271 // Skip all non-vertices at the beginning 01272 while(start < m_vertices.total_vertices() && 01273 !is_vertex(m_vertices.command(start))) ++start; 01274 01275 // Skip all insignificant move_to 01276 while(start+1 < m_vertices.total_vertices() && 01277 is_move_to(m_vertices.command(start)) && 01278 is_move_to(m_vertices.command(start+1))) ++start; 01279 01280 // Find the last vertex 01281 unsigned end = start + 1; 01282 while(end < m_vertices.total_vertices() && 01283 !is_next_poly(m_vertices.command(end))) ++end; 01284 01285 invert_polygon(start, end); 01286 } 01287 01288 //------------------------------------------------------------------------ 01289 template<class VC> 01290 unsigned path_base<VC>::arrange_polygon_orientation(unsigned start, 01291 path_flags_e orientation) 01292 { 01293 if(orientation == path_flags_none) return start; 01294 01295 // Skip all non-vertices at the beginning 01296 while(start < m_vertices.total_vertices() && 01297 !is_vertex(m_vertices.command(start))) ++start; 01298 01299 // Skip all insignificant move_to 01300 while(start+1 < m_vertices.total_vertices() && 01301 is_move_to(m_vertices.command(start)) && 01302 is_move_to(m_vertices.command(start+1))) ++start; 01303 01304 // Find the last vertex 01305 unsigned end = start + 1; 01306 while(end < m_vertices.total_vertices() && 01307 !is_next_poly(m_vertices.command(end))) ++end; 01308 01309 if(end - start > 2) 01310 { 01311 if(perceive_polygon_orientation(start, end) != unsigned(orientation)) 01312 { 01313 // Invert polygon, set orientation flag, and skip all end_poly 01314 invert_polygon(start, end); 01315 unsigned cmd; 01316 while(end < m_vertices.total_vertices() && 01317 is_end_poly(cmd = m_vertices.command(end))) 01318 { 01319 m_vertices.modify_command(end++, set_orientation(cmd, orientation)); 01320 } 01321 } 01322 } 01323 return end; 01324 } 01325 01326 //------------------------------------------------------------------------ 01327 template<class VC> 01328 unsigned path_base<VC>::arrange_orientations(unsigned start, 01329 path_flags_e orientation) 01330 { 01331 if(orientation != path_flags_none) 01332 { 01333 while(start < m_vertices.total_vertices()) 01334 { 01335 start = arrange_polygon_orientation(start, orientation); 01336 if(is_stop(m_vertices.command(start))) 01337 { 01338 ++start; 01339 break; 01340 } 01341 } 01342 } 01343 return start; 01344 } 01345 01346 //------------------------------------------------------------------------ 01347 template<class VC> 01348 void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation) 01349 { 01350 if(orientation != path_flags_none) 01351 { 01352 unsigned start = 0; 01353 while(start < m_vertices.total_vertices()) 01354 { 01355 start = arrange_orientations(start, orientation); 01356 } 01357 } 01358 } 01359 01360 //------------------------------------------------------------------------ 01361 template<class VC> 01362 void path_base<VC>::flip_x(double x1, double x2) 01363 { 01364 unsigned i; 01365 double x, y; 01366 for(i = 0; i < m_vertices.total_vertices(); i++) 01367 { 01368 unsigned cmd = m_vertices.vertex(i, &x, &y); 01369 if(is_vertex(cmd)) 01370 { 01371 m_vertices.modify_vertex(i, x2 - x + x1, y); 01372 } 01373 } 01374 } 01375 01376 //------------------------------------------------------------------------ 01377 template<class VC> 01378 void path_base<VC>::flip_y(double y1, double y2) 01379 { 01380 unsigned i; 01381 double x, y; 01382 for(i = 0; i < m_vertices.total_vertices(); i++) 01383 { 01384 unsigned cmd = m_vertices.vertex(i, &x, &y); 01385 if(is_vertex(cmd)) 01386 { 01387 m_vertices.modify_vertex(i, x, y2 - y + y1); 01388 } 01389 } 01390 } 01391 01392 //------------------------------------------------------------------------ 01393 template<class VC> 01394 void path_base<VC>::translate(double dx, double dy, unsigned path_id) 01395 { 01396 unsigned num_ver = m_vertices.total_vertices(); 01397 for(; path_id < num_ver; path_id++) 01398 { 01399 double x, y; 01400 unsigned cmd = m_vertices.vertex(path_id, &x, &y); 01401 if(is_stop(cmd)) break; 01402 if(is_vertex(cmd)) 01403 { 01404 x += dx; 01405 y += dy; 01406 m_vertices.modify_vertex(path_id, x, y); 01407 } 01408 } 01409 } 01410 01411 //------------------------------------------------------------------------ 01412 template<class VC> 01413 void path_base<VC>::translate_all_paths(double dx, double dy) 01414 { 01415 unsigned idx; 01416 unsigned num_ver = m_vertices.total_vertices(); 01417 for(idx = 0; idx < num_ver; idx++) 01418 { 01419 double x, y; 01420 if(is_vertex(m_vertices.vertex(idx, &x, &y))) 01421 { 01422 x += dx; 01423 y += dy; 01424 m_vertices.modify_vertex(idx, x, y); 01425 } 01426 } 01427 } 01428 01429 //-----------------------------------------------------vertex_stl_storage 01430 template<class Container> class vertex_stl_storage 01431 { 01432 public: 01433 typedef typename Container::value_type vertex_type; 01434 typedef typename vertex_type::value_type value_type; 01435 01436 void remove_all() { m_vertices.clear(); } 01437 void free_all() { m_vertices.clear(); } 01438 01439 void add_vertex(double x, double y, unsigned cmd) 01440 { 01441 m_vertices.push_back(vertex_type(value_type(x), 01442 value_type(y), 01443 int8u(cmd))); 01444 } 01445 01446 void modify_vertex(unsigned idx, double x, double y) 01447 { 01448 vertex_type& v = m_vertices[idx]; 01449 v.x = value_type(x); 01450 v.y = value_type(y); 01451 } 01452 01453 void modify_vertex(unsigned idx, double x, double y, unsigned cmd) 01454 { 01455 vertex_type& v = m_vertices[idx]; 01456 v.x = value_type(x); 01457 v.y = value_type(y); 01458 v.cmd = int8u(cmd); 01459 } 01460 01461 void modify_command(unsigned idx, unsigned cmd) 01462 { 01463 m_vertices[idx].cmd = int8u(cmd); 01464 } 01465 01466 void swap_vertices(unsigned v1, unsigned v2) 01467 { 01468 vertex_type t = m_vertices[v1]; 01469 m_vertices[v1] = m_vertices[v2]; 01470 m_vertices[v2] = t; 01471 } 01472 01473 unsigned last_command() const 01474 { 01475 return m_vertices.size() ? 01476 m_vertices[m_vertices.size() - 1].cmd : 01477 path_cmd_stop; 01478 } 01479 01480 unsigned last_vertex(double* x, double* y) const 01481 { 01482 if(m_vertices.size() == 0) 01483 { 01484 *x = *y = 0.0; 01485 return path_cmd_stop; 01486 } 01487 return vertex(m_vertices.size() - 1, x, y); 01488 } 01489 01490 unsigned prev_vertex(double* x, double* y) const 01491 { 01492 if(m_vertices.size() < 2) 01493 { 01494 *x = *y = 0.0; 01495 return path_cmd_stop; 01496 } 01497 return vertex(m_vertices.size() - 2, x, y); 01498 } 01499 01500 double last_x() const 01501 { 01502 return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0; 01503 } 01504 01505 double last_y() const 01506 { 01507 return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0; 01508 } 01509 01510 unsigned total_vertices() const 01511 { 01512 return m_vertices.size(); 01513 } 01514 01515 unsigned vertex(unsigned idx, double* x, double* y) const 01516 { 01517 const vertex_type& v = m_vertices[idx]; 01518 *x = v.x; 01519 *y = v.y; 01520 return v.cmd; 01521 } 01522 01523 unsigned command(unsigned idx) const 01524 { 01525 return m_vertices[idx].cmd; 01526 } 01527 01528 private: 01529 Container m_vertices; 01530 }; 01531 01532 //-----------------------------------------------------------path_storage 01533 typedef path_base<vertex_block_storage<double> > path_storage; 01534 01535 // Example of declarations path_storage with pod_bvector as a container 01536 //----------------------------------------------------------------------- 01537 //typedef path_base<vertex_stl_storage<pod_bvector<vertex_d> > > path_storage; 01538 01539 } 01540 01541 01542 01543 // Example of declarations path_storage with std::vector as a container 01544 //--------------------------------------------------------------------------- 01545 //#include <vector> 01546 //namespace agg 01547 //{ 01548 // typedef path_base<vertex_stl_storage<std::vector<vertex_d> > > stl_path_storage; 01549 //} 01550 01551 01552 01553 01554 #endif