agg_font_cache_manager.h

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

H
398
字号
//----------------------------------------------------------------------------// 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//----------------------------------------------------------------------------#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED#define AGG_FONT_CACHE_MANAGER_INCLUDED#include <string.h>#include "agg_array.h"namespace agg{    //---------------------------------------------------------glyph_data_type    enum glyph_data_type    {        glyph_data_invalid = 0,        glyph_data_mono    = 1,        glyph_data_gray8   = 2,        glyph_data_outline = 3    };    //-------------------------------------------------------------glyph_cache    struct glyph_cache    {        unsigned        glyph_index;        int8u*          data;        unsigned        data_size;        glyph_data_type data_type;        rect_i          bounds;        double          advance_x;        double          advance_y;    };    //--------------------------------------------------------------font_cache    class font_cache    {    public:        enum block_size_e { block_size = 16384-16 };        //--------------------------------------------------------------------        font_cache(const char* font_signature) :             m_allocator(block_size),            m_font_signature(0)        {            m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);            strcpy(m_font_signature, font_signature);            memset(m_glyphs, 0, sizeof(m_glyphs));        }        //--------------------------------------------------------------------        bool font_is(const char* font_signature) const        {            return strcmp(font_signature, m_font_signature) == 0;        }        //--------------------------------------------------------------------        const glyph_cache* find_glyph(unsigned glyph_code) const        {            unsigned msb = (glyph_code >> 8) & 0xFF;            if(m_glyphs[msb])             {                return m_glyphs[msb][glyph_code & 0xFF];            }            return 0;        }        //--------------------------------------------------------------------        glyph_cache* cache_glyph(unsigned        glyph_code,                                  unsigned        glyph_index,                                 unsigned        data_size,                                 glyph_data_type data_type,                                 const rect_i&   bounds,                                 double          advance_x,                                 double          advance_y)        {            unsigned msb = (glyph_code >> 8) & 0xFF;            if(m_glyphs[msb] == 0)            {                m_glyphs[msb] =                     (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,                                                         sizeof(glyph_cache*));                memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);            }            unsigned lsb = glyph_code & 0xFF;            if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite            glyph_cache* glyph =                 (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),                                                   sizeof(double));            glyph->glyph_index = glyph_index;            glyph->data        = m_allocator.allocate(data_size);            glyph->data_size   = data_size;            glyph->data_type   = data_type;            glyph->bounds      = bounds;            glyph->advance_x   = advance_x;            glyph->advance_y   = advance_y;            return m_glyphs[msb][lsb] = glyph;        }    private:        pod_allocator   m_allocator;        glyph_cache**   m_glyphs[256];        char*           m_font_signature;    };        //---------------------------------------------------------font_cache_pool    class font_cache_pool    {    public:        //--------------------------------------------------------------------        ~font_cache_pool()        {            unsigned i;            for(i = 0; i < m_num_fonts; ++i)            {                delete m_fonts[i];            }            delete [] m_fonts;        }        //--------------------------------------------------------------------        font_cache_pool(unsigned max_fonts=32) :             m_fonts(new font_cache* [max_fonts]),            m_max_fonts(max_fonts),            m_num_fonts(0),            m_cur_font(0)        {}        //--------------------------------------------------------------------        void font(const char* font_signature, bool reset_cache = false)        {            int idx = find_font(font_signature);            if(idx >= 0)            {                if(reset_cache)                {                    delete m_fonts[idx];                    m_fonts[idx] = new font_cache(font_signature);                }                m_cur_font = m_fonts[idx];            }            else            {                if(m_num_fonts >= m_max_fonts)                {                    delete m_fonts[0];                    memcpy(m_fonts,                            m_fonts + 1,                            (m_max_fonts - 1) * sizeof(font_cache*));                    m_num_fonts = m_max_fonts - 1;                }                m_fonts[m_num_fonts] = new font_cache(font_signature);                m_cur_font = m_fonts[m_num_fonts];                ++m_num_fonts;            }        }        //--------------------------------------------------------------------        const font_cache* font() const        {            return m_cur_font;        }        //--------------------------------------------------------------------        const glyph_cache* find_glyph(unsigned glyph_code) const        {            if(m_cur_font) return m_cur_font->find_glyph(glyph_code);            return 0;        }        //--------------------------------------------------------------------        glyph_cache* cache_glyph(unsigned        glyph_code,                                  unsigned        glyph_index,                                 unsigned        data_size,                                 glyph_data_type data_type,                                 const rect_i&   bounds,                                 double          advance_x,                                 double          advance_y)        {            if(m_cur_font)             {                return m_cur_font->cache_glyph(glyph_code,                                               glyph_index,                                               data_size,                                               data_type,                                               bounds,                                               advance_x,                                               advance_y);            }            return 0;        }        //--------------------------------------------------------------------        int find_font(const char* font_signature)        {            unsigned i;            for(i = 0; i < m_num_fonts; i++)            {                if(m_fonts[i]->font_is(font_signature)) return int(i);            }            return -1;        }    private:        font_cache** m_fonts;        unsigned     m_max_fonts;        unsigned     m_num_fonts;        font_cache*  m_cur_font;    };    //------------------------------------------------------------------------    enum glyph_rendering    {        glyph_ren_native_mono,        glyph_ren_native_gray8,        glyph_ren_outline,        glyph_ren_agg_mono,        glyph_ren_agg_gray8    };    //------------------------------------------------------font_cache_manager    template<class FontEngine> class font_cache_manager    {    public:        typedef FontEngine font_engine_type;        typedef font_cache_manager<FontEngine> self_type;        typedef typename font_engine_type::path_adaptor_type   path_adaptor_type;        typedef typename font_engine_type::gray8_adaptor_type  gray8_adaptor_type;        typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;        typedef typename font_engine_type::mono_adaptor_type   mono_adaptor_type;        typedef typename mono_adaptor_type::embedded_scanline  mono_scanline_type;        //--------------------------------------------------------------------        font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :            m_fonts(max_fonts),            m_engine(engine),            m_change_stamp(-1),            m_prev_glyph(0),            m_last_glyph(0)        {}        //--------------------------------------------------------------------        const glyph_cache* glyph(unsigned glyph_code)        {            synchronize();            const glyph_cache* gl = m_fonts.find_glyph(glyph_code);            if(gl)             {                m_prev_glyph = m_last_glyph;                return m_last_glyph = gl;            }            else            {                if(m_engine.prepare_glyph(glyph_code))                {                    m_prev_glyph = m_last_glyph;                    m_last_glyph = m_fonts.cache_glyph(glyph_code,                                                        m_engine.glyph_index(),                                                       m_engine.data_size(),                                                       m_engine.data_type(),                                                       m_engine.bounds(),                                                       m_engine.advance_x(),                                                       m_engine.advance_y());                    m_engine.write_glyph_to(m_last_glyph->data);                    return m_last_glyph;                }            }            return 0;        }        //--------------------------------------------------------------------        void init_embedded_adaptors(const glyph_cache* gl,                                     double x, double y,                                     double scale=1.0)        {            if(gl)            {                switch(gl->data_type)                {                default: return;                case glyph_data_mono:                    m_mono_adaptor.init(gl->data, gl->data_size, x, y);                    break;                case glyph_data_gray8:                    m_gray8_adaptor.init(gl->data, gl->data_size, x, y);                    break;                case glyph_data_outline:                    m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);                    break;                }            }        }        //--------------------------------------------------------------------        path_adaptor_type&   path_adaptor()   { return m_path_adaptor;   }        gray8_adaptor_type&  gray8_adaptor()  { return m_gray8_adaptor;  }        gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }        mono_adaptor_type&   mono_adaptor()   { return m_mono_adaptor;   }        mono_scanline_type&  mono_scanline()  { return m_mono_scanline;  }        //--------------------------------------------------------------------        const glyph_cache* perv_glyph() const { return m_prev_glyph; }        const glyph_cache* last_glyph() const { return m_last_glyph; }        //--------------------------------------------------------------------        bool add_kerning(double* x, double* y)        {            if(m_prev_glyph && m_last_glyph)            {                return m_engine.add_kerning(m_prev_glyph->glyph_index,                                             m_last_glyph->glyph_index,                                            x, y);            }            return false;        }        //--------------------------------------------------------------------        void precache(unsigned from, unsigned to)        {            for(; from <= to; ++from) glyph(from);        }        //--------------------------------------------------------------------        void reset_cache()        {            m_fonts.font(m_engine.font_signature(), true);            m_change_stamp = m_engine.change_stamp();            m_prev_glyph = m_last_glyph = 0;        }    private:        //--------------------------------------------------------------------        font_cache_manager(const self_type&);        const self_type& operator = (const self_type&);        //--------------------------------------------------------------------        void synchronize()        {            if(m_change_stamp != m_engine.change_stamp())            {                m_fonts.font(m_engine.font_signature());                m_change_stamp = m_engine.change_stamp();                m_prev_glyph = m_last_glyph = 0;            }        }        font_cache_pool     m_fonts;        font_engine_type&   m_engine;        int                 m_change_stamp;        double              m_dx;        double              m_dy;        const glyph_cache*  m_prev_glyph;        const glyph_cache*  m_last_glyph;        path_adaptor_type   m_path_adaptor;        gray8_adaptor_type  m_gray8_adaptor;        gray8_scanline_type m_gray8_scanline;        mono_adaptor_type   m_mono_adaptor;        mono_scanline_type  m_mono_scanline;    };}#endif

⌨️ 快捷键说明

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