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

📄 agg_rasterizer_cells_aa.h

📁 windows ce 下的画各种b样条曲线
💻 H
📖 第 1 页 / 共 2 页
字号:
//----------------------------------------------------------------------------
// Anti-Grain Geometry (AGG) - Version 2.5
// A high quality rendering engine for C++
// Copyright (C) 2002-2006 Maxim Shemanarev
// Contact: mcseem@antigrain.com
//          mcseemagg@yahoo.com
//          http://antigrain.com
// 
// AGG is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// AGG is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with AGG; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
// MA 02110-1301, USA.
//----------------------------------------------------------------------------
//
// 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.
//
//----------------------------------------------------------------------------
//
// 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--)
            {
                pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
                ptr--;
            }
            pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
        }
    }

    //------------------------------------------------------------------------
    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;
        }
    }

    //------------------------------------------------------------------------
    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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -