📄 agg_path_storage.h
字号:
//----------------------------------------------------------------------------// Anti-Grain Geometry - Version 2.4// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)//// Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied// warranty, and with no claim as to its suitability for any purpose.////----------------------------------------------------------------------------// Contact: mcseem@antigrain.com// mcseemagg@yahoo.com// http://www.antigrain.com//----------------------------------------------------------------------------#ifndef AGG_PATH_STORAGE_INCLUDED#define AGG_PATH_STORAGE_INCLUDED#include <string.h>#include <math.h>#include "agg_math.h"#include "agg_array.h"#include "agg_bezier_arc.h"namespace agg{ //----------------------------------------------------vertex_block_storage template<class T, unsigned BlockShift=8, unsigned BlockPool=256> class vertex_block_storage { public: // Allocation parameters enum block_scale_e { block_shift = BlockShift, block_size = 1 << block_shift, block_mask = block_size - 1, block_pool = BlockPool }; typedef T value_type; typedef vertex_block_storage<T, BlockShift, BlockPool> self_type; ~vertex_block_storage(); vertex_block_storage(); vertex_block_storage(const self_type& v); const self_type& operator = (const self_type& ps); void remove_all(); void free_all(); void add_vertex(double x, double y, unsigned cmd); void modify_vertex(unsigned idx, double x, double y); void modify_vertex(unsigned idx, double x, double y, unsigned cmd); void modify_command(unsigned idx, unsigned cmd); void swap_vertices(unsigned v1, unsigned v2); unsigned last_command() const; unsigned last_vertex(double* x, double* y) const; unsigned prev_vertex(double* x, double* y) const; double last_x() const; double last_y() const; unsigned total_vertices() const; unsigned vertex(unsigned idx, double* x, double* y) const; unsigned command(unsigned idx) const; private: void allocate_block(unsigned nb); int8u* storage_ptrs(T** xy_ptr); private: unsigned m_total_vertices; unsigned m_total_blocks; unsigned m_max_blocks; T** m_coord_blocks; int8u** m_cmd_blocks; }; //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> void vertex_block_storage<T,S,P>::free_all() { if(m_total_blocks) { T** coord_blk = m_coord_blocks + m_total_blocks - 1; while(m_total_blocks--) { delete [] *coord_blk; --coord_blk; } delete [] m_coord_blocks; m_total_blocks = 0; m_max_blocks = 0; m_coord_blocks = 0; m_cmd_blocks = 0; m_total_vertices = 0; } } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> vertex_block_storage<T,S,P>::~vertex_block_storage() { free_all(); } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> vertex_block_storage<T,S,P>::vertex_block_storage() : m_total_vertices(0), m_total_blocks(0), m_max_blocks(0), m_coord_blocks(0), m_cmd_blocks(0) { } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> vertex_block_storage<T,S,P>::vertex_block_storage(const vertex_block_storage<T,S,P>& v) : m_total_vertices(0), m_total_blocks(0), m_max_blocks(0), m_coord_blocks(0), m_cmd_blocks(0) { *this = v; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> const vertex_block_storage<T,S,P>& vertex_block_storage<T,S,P>::operator = (const vertex_block_storage<T,S,P>& v) { remove_all(); unsigned i; for(i = 0; i < v.total_vertices(); i++) { double x, y; unsigned cmd = v.vertex(i, &x, &y); add_vertex(x, y, cmd); } return *this; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::remove_all() { m_total_vertices = 0; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::add_vertex(double x, double y, unsigned cmd) { T* coord_ptr = 0; *storage_ptrs(&coord_ptr) = (int8u)cmd; coord_ptr[0] = T(x); coord_ptr[1] = T(y); m_total_vertices++; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, double x, double y) { T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); pv[0] = T(x); pv[1] = T(y); } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, double x, double y, unsigned cmd) { unsigned block = idx >> block_shift; unsigned offset = idx & block_mask; T* pv = m_coord_blocks[block] + (offset << 1); pv[0] = T(x); pv[1] = T(y); m_cmd_blocks[block][offset] = (int8u)cmd; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::modify_command(unsigned idx, unsigned cmd) { m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::swap_vertices(unsigned v1, unsigned v2) { unsigned b1 = v1 >> block_shift; unsigned b2 = v2 >> block_shift; unsigned o1 = v1 & block_mask; unsigned o2 = v2 & block_mask; T* pv1 = m_coord_blocks[b1] + (o1 << 1); T* pv2 = m_coord_blocks[b2] + (o2 << 1); T val; val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val; val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val; int8u cmd = m_cmd_blocks[b1][o1]; m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2]; m_cmd_blocks[b2][o2] = cmd; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::last_command() const { if(m_total_vertices) return command(m_total_vertices - 1); return path_cmd_stop; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::last_vertex(double* x, double* y) const { if(m_total_vertices) return vertex(m_total_vertices - 1, x, y); return path_cmd_stop; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::prev_vertex(double* x, double* y) const { if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y); return path_cmd_stop; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline double vertex_block_storage<T,S,P>::last_x() const { if(m_total_vertices) { unsigned idx = m_total_vertices - 1; return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1]; } return 0.0; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline double vertex_block_storage<T,S,P>::last_y() const { if(m_total_vertices) { unsigned idx = m_total_vertices - 1; return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1]; } return 0.0; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::total_vertices() const { return m_total_vertices; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::vertex(unsigned idx, double* x, double* y) const { unsigned nb = idx >> block_shift; const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); *x = pv[0]; *y = pv[1]; return m_cmd_blocks[nb][idx & block_mask]; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::command(unsigned idx) const { return m_cmd_blocks[idx >> block_shift][idx & block_mask]; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> void vertex_block_storage<T,S,P>::allocate_block(unsigned nb) { if(nb >= m_max_blocks) { T** new_coords = new T* [(m_max_blocks + block_pool) * 2]; unsigned char** new_cmds = (unsigned char**)(new_coords + m_max_blocks + block_pool); if(m_coord_blocks) { memcpy(new_coords, m_coord_blocks, m_max_blocks * sizeof(T*)); memcpy(new_cmds, m_cmd_blocks, m_max_blocks * sizeof(unsigned char*)); delete [] m_coord_blocks; } m_coord_blocks = new_coords; m_cmd_blocks = new_cmds; m_max_blocks += block_pool; } m_coord_blocks[nb] = new T [block_size * 2 + block_size / (sizeof(T) / sizeof(unsigned char))]; m_cmd_blocks[nb] = (unsigned char*)(m_coord_blocks[nb] + block_size * 2); m_total_blocks++; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> int8u* vertex_block_storage<T,S,P>::storage_ptrs(T** xy_ptr) { unsigned nb = m_total_vertices >> block_shift; if(nb >= m_total_blocks) { allocate_block(nb); } *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); return m_cmd_blocks[nb] + (m_total_vertices & block_mask); } //-----------------------------------------------------poly_plain_adaptor template<class T> class poly_plain_adaptor { public: typedef T value_type; poly_plain_adaptor() : m_data(0), m_ptr(0), m_end(0), m_closed(false), m_stop(false) {} poly_plain_adaptor(const T* data, unsigned num_points, bool closed) : m_data(data), m_ptr(data), m_end(data + num_points * 2), m_closed(closed), m_stop(false) {} void init(const T* data, unsigned num_points, bool closed)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -