diff options
Diffstat (limited to 'third_party/agg23/agg_path_storage.h')
-rw-r--r-- | third_party/agg23/agg_path_storage.h | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/third_party/agg23/agg_path_storage.h b/third_party/agg23/agg_path_storage.h new file mode 100644 index 0000000000..dc13851d09 --- /dev/null +++ b/third_party/agg23/agg_path_storage.h @@ -0,0 +1,172 @@ + +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// 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 "agg_basics.h" +namespace agg +{ +class path_storage +{ + enum block_scale_e { + block_shift = 8, + block_size = 1 << block_shift, + block_mask = block_size - 1, + block_pool = 256 + }; +public: + class vertex_source + { + public: + vertex_source() {} + vertex_source(const path_storage& p) : m_path(&p), m_vertex_idx(0) {} + void rewind(unsigned path_id) + { + m_vertex_idx = path_id; + } + unsigned vertex(FX_FLOAT* x, FX_FLOAT* y) + { + return (m_vertex_idx < m_path->total_vertices()) ? + m_path->vertex(m_vertex_idx++, x, y) : + path_cmd_stop; + } + private: + const path_storage* m_path; + unsigned m_vertex_idx; + }; + ~path_storage(); + path_storage(); + unsigned last_vertex(FX_FLOAT* x, FX_FLOAT* y) const; + unsigned prev_vertex(FX_FLOAT* x, FX_FLOAT* y) const; + void move_to(FX_FLOAT x, FX_FLOAT y); + void line_to(FX_FLOAT x, FX_FLOAT y); + void curve4(FX_FLOAT x_ctrl1, FX_FLOAT y_ctrl1, + FX_FLOAT x_ctrl2, FX_FLOAT y_ctrl2, + FX_FLOAT x_to, FX_FLOAT y_to); + template<class VertexSource> + void add_path(VertexSource& vs, + unsigned path_id = 0, + bool solid_path = true) + { + FX_FLOAT x, y; + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) { + if(is_move_to(cmd) && solid_path && m_total_vertices) { + cmd = path_cmd_line_to; + } + add_vertex(x, y, cmd); + } + } + template<class VertexSource> + void add_path_curve(VertexSource& vs, + unsigned path_id = 0, + bool solid_path = true) + { + FX_FLOAT x, y; + unsigned cmd; + int flag; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex_curve_flag(&x, &y, flag))) { + if(is_move_to(cmd) && solid_path && m_total_vertices) { + cmd = path_cmd_line_to | flag; + } + add_vertex(x, y, cmd | flag); + } + } + unsigned total_vertices() const + { + return m_total_vertices; + } + unsigned vertex(unsigned idx, FX_FLOAT* x, FX_FLOAT* y) const + { + unsigned nb = idx >> block_shift; + const FX_FLOAT* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); + *x = *pv++; + *y = *pv; + return m_cmd_blocks[nb][idx & block_mask]; + } + unsigned command(unsigned idx) const + { + return m_cmd_blocks[idx >> block_shift][idx & block_mask]; + } + unsigned getflag(unsigned idx) const + { + return m_cmd_blocks[idx >> block_shift][idx & block_mask] & path_flags_jr; + } + void rewind(unsigned path_id); + unsigned vertex(FX_FLOAT* x, FX_FLOAT* y); + void add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd); + void end_poly(); +private: + void allocate_block(unsigned nb); + unsigned char* storage_ptrs(FX_FLOAT** xy_ptr); +private: + unsigned m_total_vertices; + unsigned m_total_blocks; + unsigned m_max_blocks; + FX_FLOAT** m_coord_blocks; + unsigned char** m_cmd_blocks; + unsigned m_iterator; +}; +inline unsigned path_storage::vertex(FX_FLOAT* x, FX_FLOAT* y) +{ + if(m_iterator >= m_total_vertices) { + return path_cmd_stop; + } + return vertex(m_iterator++, x, y); +} +inline unsigned path_storage::prev_vertex(FX_FLOAT* x, FX_FLOAT* y) const +{ + if(m_total_vertices > 1) { + return vertex(m_total_vertices - 2, x, y); + } + return path_cmd_stop; +} +inline unsigned path_storage::last_vertex(FX_FLOAT* x, FX_FLOAT* y) const +{ + if(m_total_vertices) { + return vertex(m_total_vertices - 1, x, y); + } + return path_cmd_stop; +} +inline unsigned char* path_storage::storage_ptrs(FX_FLOAT** 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); +} +inline void path_storage::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) +{ + FX_FLOAT* coord_ptr = 0; + unsigned char* cmd_ptr = storage_ptrs(&coord_ptr); + *cmd_ptr = (unsigned char)cmd; + *coord_ptr++ = x; + *coord_ptr = y; + m_total_vertices++; +} +inline void path_storage::move_to(FX_FLOAT x, FX_FLOAT y) +{ + add_vertex(x, y, path_cmd_move_to); +} +inline void path_storage::line_to(FX_FLOAT x, FX_FLOAT y) +{ + add_vertex(x, y, path_cmd_line_to); +} +} +#endif |