agg_rasterizer_cells_aa.h

来自「这是VCF框架的代码」· C头文件 代码 · 共 754 行 · 第 1/2 页

H
754
字号
//----------------------------------------------------------------------------// 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.////----------------------------------------------------------------------------//// The author gratefully acknowleges the support of David Turner, // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details.////----------------------------------------------------------------------------// Contact: mcseem@antigrain.com//          mcseemagg@yahoo.com//          http://www.antigrain.com//----------------------------------------------------------------------------//// Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com//// Liberty Technology Systems, Inc. is the provider of// PostScript and PDF technology for software developers.// //----------------------------------------------------------------------------#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED#define AGG_RASTERIZER_CELLS_AA_INCLUDED#include <string.h>#include <math.h>#include "agg_math.h"#include "agg_array.h"namespace agg{    //-----------------------------------------------------rasterizer_cells_aa    // An internal class that implements the main rasterization algorithm.    // Used in the rasterizer. Should not be used direcly.    template<class Cell> class rasterizer_cells_aa    {        enum cell_block_scale_e        {            cell_block_shift = 12,            cell_block_size  = 1 << cell_block_shift,            cell_block_mask  = cell_block_size - 1,            cell_block_pool  = 256,            cell_block_limit = 1024        };        struct sorted_y        {            unsigned start;            unsigned num;        };    public:        typedef Cell cell_type;        typedef rasterizer_cells_aa<Cell> self_type;        ~rasterizer_cells_aa();        rasterizer_cells_aa();        void reset();        void style(const cell_type& style_cell);        void line(int x1, int y1, int x2, int y2);        int min_x() const { return m_min_x; }        int min_y() const { return m_min_y; }        int max_x() const { return m_max_x; }        int max_y() const { return m_max_y; }        void sort_cells();        unsigned total_cells() const         {            return m_num_cells;        }        unsigned scanline_num_cells(unsigned y) const         {             return m_sorted_y[y - m_min_y].num;         }        const cell_type* const* scanline_cells(unsigned y) const        {             return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start;         }        bool sorted() const { return m_sorted; }    private:        rasterizer_cells_aa(const self_type&);        const self_type& operator = (const self_type&);        void set_curr_cell(int x, int y);        void add_curr_cell();        void render_hline(int ey, int x1, int y1, int x2, int y2);        void allocate_block();            private:        unsigned    m_num_blocks;        unsigned    m_max_blocks;        unsigned    m_curr_block;        unsigned    m_num_cells;        cell_type** m_cells;        cell_type*  m_curr_cell_ptr;        pod_vector<cell_type*> m_sorted_cells;        pod_vector<sorted_y>   m_sorted_y;        cell_type   m_curr_cell;        cell_type   m_style_cell;        int         m_min_x;        int         m_min_y;        int         m_max_x;        int         m_max_y;        bool        m_sorted;    };    //------------------------------------------------------------------------    template<class Cell>     rasterizer_cells_aa<Cell>::~rasterizer_cells_aa()    {        if(m_num_blocks)        {            cell_type** ptr = m_cells + m_num_blocks - 1;            while(m_num_blocks--)            {                delete [] *ptr;                ptr--;            }            delete [] m_cells;        }    }    //------------------------------------------------------------------------    template<class Cell>     rasterizer_cells_aa<Cell>::rasterizer_cells_aa() :        m_num_blocks(0),        m_max_blocks(0),        m_curr_block(0),        m_num_cells(0),        m_cells(0),        m_curr_cell_ptr(0),        m_sorted_cells(),        m_sorted_y(),        m_min_x(0x7FFFFFFF),        m_min_y(0x7FFFFFFF),        m_max_x(-0x7FFFFFFF),        m_max_y(-0x7FFFFFFF),        m_sorted(false)    {        m_style_cell.initial();        m_curr_cell.initial();    }    //------------------------------------------------------------------------    template<class Cell>     void rasterizer_cells_aa<Cell>::reset()    {        m_num_cells = 0;         m_curr_block = 0;        m_curr_cell.initial();        m_style_cell.initial();        m_sorted = false;        m_min_x =  0x7FFFFFFF;        m_min_y =  0x7FFFFFFF;        m_max_x = -0x7FFFFFFF;        m_max_y = -0x7FFFFFFF;    }    //------------------------------------------------------------------------    template<class Cell>     AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell()    {        if(m_curr_cell.area | m_curr_cell.cover)        {            if((m_num_cells & cell_block_mask) == 0)            {                if(m_num_blocks >= cell_block_limit) return;                allocate_block();            }            *m_curr_cell_ptr++ = m_curr_cell;            ++m_num_cells;            //if(m_curr_cell.x < m_min_x) m_min_x = m_curr_cell.x;            //if(m_curr_cell.x > m_max_x) m_max_x = m_curr_cell.x;            //if(m_curr_cell.y < m_min_y) m_min_y = m_curr_cell.y;            //if(m_curr_cell.y > m_max_y) m_max_y = m_curr_cell.y;        }    }    //------------------------------------------------------------------------    template<class Cell>     AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y)    {        if(m_curr_cell.not_equal(x, y, m_style_cell))        {            add_curr_cell();            m_curr_cell.style(m_style_cell);            m_curr_cell.x     = x;            m_curr_cell.y     = y;            m_curr_cell.cover = 0;            m_curr_cell.area  = 0;        }    }    //------------------------------------------------------------------------    template<class Cell>     AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey,                                                             int x1, int y1,                                                             int x2, int y2)    {        int ex1 = x1 >> poly_subpixel_shift;        int ex2 = x2 >> poly_subpixel_shift;        int fx1 = x1 & poly_subpixel_mask;        int fx2 = x2 & poly_subpixel_mask;        int delta, p, first, dx;        int incr, lift, mod, rem;        //trivial case. Happens often        if(y1 == y2)        {            set_curr_cell(ex2, ey);            return;        }        //everything is located in a single cell.  That is easy!        if(ex1 == ex2)        {            delta = y2 - y1;            m_curr_cell.cover += delta;            m_curr_cell.area  += (fx1 + fx2) * delta;            return;        }        //ok, we'll have to render a run of adjacent cells on the same        //hline...        p     = (poly_subpixel_scale - fx1) * (y2 - y1);        first = poly_subpixel_scale;        incr  = 1;        dx = x2 - x1;        if(dx < 0)        {            p     = fx1 * (y2 - y1);            first = 0;            incr  = -1;            dx    = -dx;        }        delta = p / dx;        mod   = p % dx;        if(mod < 0)        {            delta--;            mod += dx;        }        m_curr_cell.cover += delta;        m_curr_cell.area  += (fx1 + first) * delta;        ex1 += incr;        set_curr_cell(ex1, ey);        y1  += delta;        if(ex1 != ex2)        {            p     = poly_subpixel_scale * (y2 - y1 + delta);            lift  = p / dx;            rem   = p % dx;            if (rem < 0)            {                lift--;                rem += dx;            }            mod -= dx;            while (ex1 != ex2)            {                delta = lift;                mod  += rem;                if(mod >= 0)                {                    mod -= dx;                    delta++;                }                m_curr_cell.cover += delta;                m_curr_cell.area  += poly_subpixel_scale * delta;                y1  += delta;                ex1 += incr;                set_curr_cell(ex1, ey);            }        }        delta = y2 - y1;        m_curr_cell.cover += delta;        m_curr_cell.area  += (fx2 + poly_subpixel_scale - first) * delta;    }    //------------------------------------------------------------------------    template<class Cell>     AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell)    {         m_style_cell.style(style_cell);     }    //------------------------------------------------------------------------    template<class Cell>     void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2)    {        enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };        int dx = x2 - x1;        if(dx >= dx_limit || dx <= -dx_limit)        {            int cx = (x1 + x2) >> 1;            int cy = (y1 + y2) >> 1;            line(x1, y1, cx, cy);            line(cx, cy, x2, y2);        }        int dy = y2 - y1;        int ex1 = x1 >> poly_subpixel_shift;        int ex2 = x2 >> poly_subpixel_shift;        int ey1 = y1 >> poly_subpixel_shift;        int ey2 = y2 >> poly_subpixel_shift;        int fy1 = y1 & poly_subpixel_mask;        int fy2 = y2 & poly_subpixel_mask;        int x_from, x_to;        int p, rem, mod, lift, delta, first, incr;        if(ex1 < m_min_x) m_min_x = ex1;        if(ex1 > m_max_x) m_max_x = ex1;        if(ey1 < m_min_y) m_min_y = ey1;        if(ey1 > m_max_y) m_max_y = ey1;        if(ex2 < m_min_x) m_min_x = ex2;        if(ex2 > m_max_x) m_max_x = ex2;        if(ey2 < m_min_y) m_min_y = ey2;        if(ey2 > m_max_y) m_max_y = ey2;        set_curr_cell(ex1, ey1);        //everything is on a single hline        if(ey1 == ey2)        {            render_hline(ey1, x1, fy1, x2, fy2);            return;        }        //Vertical line - we have to calculate start and end cells,        //and then - the common values of the area and coverage for        //all cells of the line. We know exactly there's only one         //cell, so, we don't have to call render_hline().        incr  = 1;        if(dx == 0)        {            int ex = x1 >> poly_subpixel_shift;            int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1;            int area;            first = poly_subpixel_scale;            if(dy < 0)            {                first = 0;

⌨️ 快捷键说明

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