|  | 
 | //---------------------------------------------------------------------------- | 
 | // 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 pdfium | 
 | { | 
 | 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(float* x, float* y) | 
 |         { | 
 |           return (m_vertex_idx < m_path->total_vertices()) | 
 |                      ? m_path->vertex(m_vertex_idx++, x, y) | 
 |                      : static_cast<unsigned>(path_cmd_stop); | 
 |         } | 
 |     private: | 
 |         const path_storage* m_path; | 
 |         unsigned            m_vertex_idx; | 
 |     }; | 
 |     ~path_storage(); | 
 |     path_storage(); | 
 |     unsigned last_vertex(float* x, float* y) const; | 
 |     unsigned prev_vertex(float* x, float* y) const; | 
 |     void move_to(float x, float y); | 
 |     void line_to(float x, float y); | 
 |     void curve4(float x_ctrl1, float y_ctrl1, | 
 |                 float x_ctrl2, float y_ctrl2, | 
 |                 float x_to,    float y_to); | 
 |     template<class VertexSource> | 
 |     void add_path(VertexSource& vs, | 
 |                   unsigned path_id = 0, | 
 |                   bool solid_path = true) | 
 |     { | 
 |         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) | 
 |     { | 
 |         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, float* x, float* y) const | 
 |     { | 
 |         unsigned nb = idx >> block_shift; | 
 |         const 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(float* x, float* y); | 
 |     void add_vertex(float x, float y, unsigned cmd); | 
 |     void end_poly(); | 
 | private: | 
 |     void allocate_block(unsigned nb); | 
 |     unsigned char* storage_ptrs(float** xy_ptr); | 
 | private: | 
 |     unsigned        m_total_vertices; | 
 |     unsigned        m_total_blocks; | 
 |     unsigned        m_max_blocks; | 
 |     float**   m_coord_blocks; | 
 |     unsigned char** m_cmd_blocks; | 
 |     unsigned        m_iterator; | 
 | }; | 
 | inline unsigned path_storage::vertex(float* x, float* y) | 
 | { | 
 |     if(m_iterator >= m_total_vertices) { | 
 |         return path_cmd_stop; | 
 |     } | 
 |     return vertex(m_iterator++, x, y); | 
 | } | 
 | inline unsigned path_storage::prev_vertex(float* x, 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(float* x, 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(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(float x, float y, unsigned cmd) | 
 | { | 
 |     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(float x, float y) | 
 | { | 
 |     add_vertex(x, y, path_cmd_move_to); | 
 | } | 
 | inline void path_storage::line_to(float x, float y) | 
 | { | 
 |     add_vertex(x, y, path_cmd_line_to); | 
 | } | 
 | } | 
 | }  // namespace pdfium | 
 | #endif |