agg_span_gouraud_rgba.h

来自「这是VCF框架的代码」· C头文件 代码 · 共 278 行

H
278
字号
//----------------------------------------------------------------------------// 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.////----------------------------------------------------------------------------// Contact: mcseem@antigrain.com//          mcseemagg@yahoo.com//          http://www.antigrain.com//----------------------------------------------------------------------------//// Adaptation for high precision colors 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_SPAN_GOURAUD_RGBA_INCLUDED#define AGG_SPAN_GOURAUD_RGBA_INCLUDED#include "agg_basics.h"#include "agg_color_rgba.h"#include "agg_dda_line.h"#include "agg_span_gouraud.h"namespace agg{    //=======================================================span_gouraud_rgba    template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT>    {    public:        typedef ColorT color_type;        typedef typename ColorT::value_type value_type;        typedef span_gouraud<color_type> base_type;        typedef typename base_type::coord_type coord_type;        enum subpixel_scale_e        {             subpixel_shift = 4,             subpixel_scale = 1 << subpixel_shift        };    private:        //--------------------------------------------------------------------        struct rgba_calc        {            void init(const coord_type& c1, const coord_type& c2)            {                m_x1  = c1.x - 0.5;                 m_y1  = c1.y - 0.5;                m_dx  = c2.x - c1.x;                double dy = c2.y - c1.y;                m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy;                m_r1  = c1.color.r;                m_g1  = c1.color.g;                m_b1  = c1.color.b;                m_a1  = c1.color.a;                m_dr  = c2.color.r - m_r1;                m_dg  = c2.color.g - m_g1;                m_db  = c2.color.b - m_b1;                m_da  = c2.color.a - m_a1;            }            void calc(double y)            {                double k = (y - m_y1) * m_1dy;                if(k < 0.0) k = 0.0;                if(k > 1.0) k = 1.0;                m_r = m_r1 + iround(m_dr * k);                m_g = m_g1 + iround(m_dg * k);                m_b = m_b1 + iround(m_db * k);                m_a = m_a1 + iround(m_da * k);                m_x = iround((m_x1 + m_dx * k) * subpixel_scale);            }            double m_x1;            double m_y1;            double m_dx;            double m_1dy;            int    m_r1;            int    m_g1;            int    m_b1;            int    m_a1;            int    m_dr;            int    m_dg;            int    m_db;            int    m_da;            int    m_r;            int    m_g;            int    m_b;            int    m_a;            int    m_x;        };    public:        //--------------------------------------------------------------------        span_gouraud_rgba() {}        span_gouraud_rgba(const color_type& c1,                           const color_type& c2,                           const color_type& c3,                          double x1, double y1,                           double x2, double y2,                          double x3, double y3,                           double d = 0) :             base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)        {}        //--------------------------------------------------------------------        void prepare()        {            coord_type coord[3];            base_type::arrange_vertices(coord);            m_y2 = int(coord[1].y);            m_swap = cross_product(coord[0].x, coord[0].y,                                    coord[2].x, coord[2].y,                                   coord[1].x, coord[1].y) < 0.0;            m_rgba1.init(coord[0], coord[2]);            m_rgba2.init(coord[0], coord[1]);            m_rgba3.init(coord[1], coord[2]);        }        //--------------------------------------------------------------------        void generate(color_type* span, int x, int y, unsigned len)        {            m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);            const rgba_calc* pc1 = &m_rgba1;            const rgba_calc* pc2 = &m_rgba2;            if(y <= m_y2)            {                          // Bottom part of the triangle (first subtriangle)                //-------------------------                m_rgba2.calc(y + m_rgba2.m_1dy);            }            else            {                // Upper part (second subtriangle)                m_rgba3.calc(y - m_rgba3.m_1dy);                //-------------------------                pc2 = &m_rgba3;            }            if(m_swap)            {                // It means that the triangle is oriented clockwise,                 // so that we need to swap the controlling structures                //-------------------------                const rgba_calc* t = pc2;                pc2 = pc1;                pc1 = t;            }            // Get the horizontal length with subpixel accuracy            // and protect it from division by zero            //-------------------------            int nlen = abs(pc2->m_x - pc1->m_x);            if(nlen <= 0) nlen = 1;            dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen);            dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen);            dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen);            dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);            // Calculate the starting point of the gradient with subpixel             // accuracy and correct (roll back) the interpolators.            // This operation will also clip the beginning of the span            // if necessary.            //-------------------------            int start = pc1->m_x - (x << subpixel_shift);            r    -= start;             g    -= start;             b    -= start;             a    -= start;            nlen += start;            int vr, vg, vb, va;            enum lim_e { lim = color_type::base_mask };            // Beginning part of the span. Since we rolled back the             // interpolators, the color values may have overflow.            // So that, we render the beginning part with checking             // for overflow. It lasts until "start" is positive;            // typically it's 1-2 pixels, but may be more in some cases.            //-------------------------            while(len && start > 0)            {                vr = r.y();                vg = g.y();                vb = b.y();                va = a.y();                if(vr < 0) vr = 0; if(vr > lim) vr = lim;                if(vg < 0) vg = 0; if(vg > lim) vg = lim;                if(vb < 0) vb = 0; if(vb > lim) vb = lim;                if(va < 0) va = 0; if(va > lim) va = lim;                span->r = (value_type)vr;                span->g = (value_type)vg;                span->b = (value_type)vb;                span->a = (value_type)va;                r     += subpixel_scale;                 g     += subpixel_scale;                 b     += subpixel_scale;                 a     += subpixel_scale;                nlen  -= subpixel_scale;                start -= subpixel_scale;                ++span;                --len;            }            // Middle part, no checking for overflow.            // Actual spans can be longer than the calculated length            // because of anti-aliasing, thus, the interpolators can             // overflow. But while "nlen" is positive we are safe.            //-------------------------            while(len && nlen > 0)            {                span->r = (value_type)r.y();                span->g = (value_type)g.y();                span->b = (value_type)b.y();                span->a = (value_type)a.y();                r    += subpixel_scale;                 g    += subpixel_scale;                 b    += subpixel_scale;                 a    += subpixel_scale;                nlen -= subpixel_scale;                ++span;                --len;            }            // Ending part; checking for overflow.            // Typically it's 1-2 pixels, but may be more in some cases.            //-------------------------            while(len)            {                vr = r.y();                vg = g.y();                vb = b.y();                va = a.y();                if(vr < 0) vr = 0; if(vr > lim) vr = lim;                if(vg < 0) vg = 0; if(vg > lim) vg = lim;                if(vb < 0) vb = 0; if(vb > lim) vb = lim;                if(va < 0) va = 0; if(va > lim) va = lim;                span->r = (value_type)vr;                span->g = (value_type)vg;                span->b = (value_type)vb;                span->a = (value_type)va;                r += subpixel_scale;                 g += subpixel_scale;                 b += subpixel_scale;                 a += subpixel_scale;                ++span;                --len;            }        }    private:        bool      m_swap;        int       m_y2;        rgba_calc m_rgba1;        rgba_calc m_rgba2;        rgba_calc m_rgba3;    };}#endif

⌨️ 快捷键说明

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