⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agg_path_storage.h

📁 okular
💻 H
字号:
//----------------------------------------------------------------------------// 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 <assert.h>#include "agg_basics.h"namespace agg{    //------------------------------------------------------------path_storage    // A container to store vertices with their flags.     // A path consists of a number of contours separated with "move_to"     // commands. The path storage can keep and maintain more than one    // path.     // To navigate to the beginning of a particular path, use rewind(path_id);    // Where path_id is what start_new_path() returns. So, when you call    // start_new_path() you need to store its return value somewhere else    // to navigate to the path afterwards.    //    // See Implementation: agg_path_storage.cpp     // See also: vertex_source concept    //------------------------------------------------------------------------    class path_storage    {        // Allocation parameters        enum        {            block_shift = 8,            block_size  = 1 << block_shift,            block_mask  = block_size - 1,            block_pool  = 256        };    public:        //--------------------------------------------------------------------        class const_iterator        {            void vertex()            {                if(m_vertex_idx < m_path->total_vertices())                 {                    m_vertex.cmd = m_path->vertex(m_vertex_idx, &m_vertex.x, &m_vertex.y);                }                else                {                    m_vertex.cmd = path_cmd_stop;                    m_vertex.x = m_vertex.y = 0.0;                }            }        public:            const_iterator() {}            const_iterator(unsigned cmd) { m_vertex.cmd = cmd; }            const_iterator(const const_iterator& i) :                 m_path(i.m_path),                m_vertex_idx(i.m_vertex_idx),                m_vertex(i.m_vertex)             {            }            const_iterator(const path_storage& p, unsigned id) :                 m_path(&p),                m_vertex_idx(id)            {                vertex();            }            const_iterator& operator++()             {                ++m_vertex_idx;                vertex();                return *this;            }            const vertex_type& operator*() const { return m_vertex; }            const vertex_type* operator->() const { return &m_vertex; }            bool operator != (const const_iterator& i)             {                 return m_vertex.cmd != i.m_vertex.cmd;             }        private:            const path_storage* m_path;            unsigned            m_vertex_idx;            vertex_type         m_vertex;        };        ~path_storage();        path_storage();        path_storage(const path_storage& ps);        void remove_all();        unsigned last_vertex(double* x, double* y) const;        unsigned prev_vertex(double* x, double* y) const;        void rel_to_abs(double* x, double* y) const;        void move_to(double x, double y);        void move_rel(double dx, double dy);        void line_to(double x, double y);        void line_rel(double dx, double dy);        void arc_to(double rx, double ry,                    double angle,                    bool large_arc_flag,                    bool sweep_flag,                    double x, double y);        void arc_rel(double rx, double ry,                     double angle,                     bool large_arc_flag,                     bool sweep_flag,                     double dx, double dy);        void curve3(double x_ctrl, double y_ctrl,                     double x_to,   double y_to);        void curve3_rel(double dx_ctrl, double dy_ctrl,                         double dx_to,   double dy_to);        void curve3(double x_to, double y_to);        void curve3_rel(double dx_to, double dy_to);        void curve4(double x_ctrl1, double y_ctrl1,                     double x_ctrl2, double y_ctrl2,                     double x_to,    double y_to);        void curve4_rel(double dx_ctrl1, double dy_ctrl1,                         double dx_ctrl2, double dy_ctrl2,                         double dx_to,    double dy_to);        void curve4(double x_ctrl2, double y_ctrl2,                     double x_to,    double y_to);        void curve4_rel(double x_ctrl2, double y_ctrl2,                         double x_to,    double y_to);        void end_poly(unsigned flags = path_flags_close);        void close_polygon(unsigned flags = path_flags_none)        {            end_poly(path_flags_close | flags);        }        void add_poly(const double* vertices, unsigned num,                       bool solid_path = false,                      unsigned end_flags = path_flags_none);        template<class VertexSource>         void add_path(VertexSource& vs,                       unsigned path_id = 0,                       bool solid_path = true)        {            double 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);            }        }        unsigned start_new_path();        void copy_from(const path_storage& ps);        const path_storage& operator = (const path_storage& ps)        {            copy_from(ps);            return *this;        }        unsigned total_vertices() const { return m_total_vertices; }        unsigned vertex(unsigned idx, double* x, double* y) const        {            unsigned nb = idx >> block_shift;            const double* 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];        }        void     rewind(unsigned path_id);        unsigned vertex(double* x, double* y);        const_iterator begin(unsigned id) const { return const_iterator(*this, id); }        const_iterator begin()            const { return const_iterator(*this, 0); }        const_iterator end()              const { return const_iterator(path_cmd_stop); }        // Arrange the orientation of all the polygons. After calling this        // method all the polygons will have the same orientation        // determined by the new_orientation flag, i.e.,         // path_flags_cw or path_flags_ccw        unsigned arrange_orientations(unsigned path_id, path_flags_e new_orientation);        void arrange_orientations_all_paths(path_flags_e new_orientation);        // Flip all the vertices horizontally or vertically        void flip_x(double x1, double x2);        void flip_y(double y1, double y2);                // This function adds a vertex with its flags directly. Since there's no         // checking for errors, keeping proper path integrity is the responsibility        // of the caller. It can be said the function is "not very public".         void add_vertex(double x, double y, unsigned cmd);        // Allows you to modify vertex coordinates. The caller must know         // the index of the vertex.         void modify_vertex(unsigned idx, double x, double y)        {            double* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1);            *pv++ = x;            *pv   = y;        }        // Allows you to modify vertex command. The caller must know         // the index of the vertex.         void modify_command(unsigned idx, unsigned cmd)        {            m_cmd_blocks[idx >> block_shift][idx & block_mask] = (unsigned char)cmd;        }    private:        void allocate_block(unsigned nb);        unsigned char* storage_ptrs(double** xy_ptr);        unsigned perceive_polygon_orientation(unsigned idx,                                               double xs, double ys,                                              unsigned* orientation);        void reverse_polygon(unsigned start, unsigned end);    private:        unsigned        m_total_vertices;        unsigned        m_total_blocks;        unsigned        m_max_blocks;        double**        m_coord_blocks;        unsigned char** m_cmd_blocks;        unsigned        m_iterator;    };    //------------------------------------------------------------------------    inline unsigned path_storage::vertex(double* x, double* y)    {        if(m_iterator >= m_total_vertices) return path_cmd_stop;        return vertex(m_iterator++, x, y);    }    //------------------------------------------------------------------------    inline unsigned path_storage::prev_vertex(double* x, double* 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(double* x, double* y) const    {        if(m_total_vertices)        {            return vertex(m_total_vertices - 1, x, y);        }        return path_cmd_stop;    }    //------------------------------------------------------------------------    inline void path_storage::rel_to_abs(double* x, double* y) const    {        if(m_total_vertices)        {            double x2;            double y2;            if(is_vertex(vertex(m_total_vertices - 1, &x2, &y2)))            {                *x += x2;                *y += y2;            }        }    }    //------------------------------------------------------------------------    inline unsigned char* path_storage::storage_ptrs(double** xy_ptr)    {        unsigned nb = m_total_vertices >> block_shift;        if(nb >= m_total_blocks)        {            allocate_block(nb);        }        assert(m_coord_blocks);        *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(double x, double y, unsigned cmd)    {        double* 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(double x, double y)    {        add_vertex(x, y, path_cmd_move_to);    }    //------------------------------------------------------------------------    inline void path_storage::move_rel(double dx, double dy)    {        rel_to_abs(&dx, &dy);        add_vertex(dx, dy, path_cmd_move_to);    }    //------------------------------------------------------------------------    inline void path_storage::line_to(double x, double y)    {        add_vertex(x, y, path_cmd_line_to);    }    //------------------------------------------------------------------------    inline void path_storage::line_rel(double dx, double dy)    {        rel_to_abs(&dx, &dy);        add_vertex(dx, dy, path_cmd_line_to);    }}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -