Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_font_cache_manager.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 
00025 #ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
00026 #define AGG_FONT_CACHE_MANAGER_INCLUDED
00027 
00028 #include <string.h>
00029 #include "agg_array.h"
00030 
00031 namespace agg
00032 {
00033 
00034     //---------------------------------------------------------glyph_data_type
00035     enum glyph_data_type
00036     {
00037         glyph_data_invalid = 0,
00038         glyph_data_mono    = 1,
00039         glyph_data_gray8   = 2,
00040         glyph_data_outline = 3
00041     };
00042 
00043 
00044     //-------------------------------------------------------------glyph_cache
00045     struct glyph_cache
00046     {
00047         unsigned        glyph_index;
00048         int8u*          data;
00049         unsigned        data_size;
00050         glyph_data_type data_type;
00051         rect_i          bounds;
00052         double          advance_x;
00053         double          advance_y;
00054     };
00055 
00056 
00057     //--------------------------------------------------------------font_cache
00058     class font_cache
00059     {
00060     public:
00061         enum block_size_e { block_size = 16384-16 };
00062 
00063         //--------------------------------------------------------------------
00064         font_cache() : 
00065             m_allocator(block_size),
00066             m_font_signature(0)
00067         {}
00068 
00069         //--------------------------------------------------------------------
00070         void signature(const char* font_signature)
00071         {
00072             m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
00073             strcpy(m_font_signature, font_signature);
00074             memset(m_glyphs, 0, sizeof(m_glyphs));
00075         }
00076 
00077         //--------------------------------------------------------------------
00078         bool font_is(const char* font_signature) const
00079         {
00080             return strcmp(font_signature, m_font_signature) == 0;
00081         }
00082 
00083         //--------------------------------------------------------------------
00084         const glyph_cache* find_glyph(unsigned glyph_code) const
00085         {
00086             unsigned msb = (glyph_code >> 8) & 0xFF;
00087             if(m_glyphs[msb]) 
00088             {
00089                 return m_glyphs[msb][glyph_code & 0xFF];
00090             }
00091             return 0;
00092         }
00093 
00094         //--------------------------------------------------------------------
00095         glyph_cache* cache_glyph(unsigned        glyph_code, 
00096                                  unsigned        glyph_index,
00097                                  unsigned        data_size,
00098                                  glyph_data_type data_type,
00099                                  const rect_i&   bounds,
00100                                  double          advance_x,
00101                                  double          advance_y)
00102         {
00103             unsigned msb = (glyph_code >> 8) & 0xFF;
00104             if(m_glyphs[msb] == 0)
00105             {
00106                 m_glyphs[msb] = 
00107                     (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, 
00108                                                         sizeof(glyph_cache*));
00109                 memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
00110             }
00111 
00112             unsigned lsb = glyph_code & 0xFF;
00113             if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
00114 
00115             glyph_cache* glyph = 
00116                 (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
00117                                                    sizeof(double));
00118 
00119             glyph->glyph_index        = glyph_index;
00120             glyph->data               = m_allocator.allocate(data_size);
00121             glyph->data_size          = data_size;
00122             glyph->data_type          = data_type;
00123             glyph->bounds             = bounds;
00124             glyph->advance_x          = advance_x;
00125             glyph->advance_y          = advance_y;
00126             return m_glyphs[msb][lsb] = glyph;
00127         }
00128 
00129     private:
00130         block_allocator m_allocator;
00131         glyph_cache**   m_glyphs[256];
00132         char*           m_font_signature;
00133     };
00134 
00135 
00136 
00137 
00138 
00139 
00140     
00141     //---------------------------------------------------------font_cache_pool
00142     class font_cache_pool
00143     {
00144     public:
00145         //--------------------------------------------------------------------
00146         ~font_cache_pool()
00147         {
00148             unsigned i;
00149             for(i = 0; i < m_num_fonts; ++i)
00150             {
00151                 obj_allocator<font_cache>::deallocate(m_fonts[i]);
00152             }
00153             pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
00154         }
00155 
00156         //--------------------------------------------------------------------
00157         font_cache_pool(unsigned max_fonts=32) : 
00158             m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
00159             m_max_fonts(max_fonts),
00160             m_num_fonts(0),
00161             m_cur_font(0)
00162         {}
00163 
00164 
00165         //--------------------------------------------------------------------
00166         void font(const char* font_signature, bool reset_cache = false)
00167         {
00168             int idx = find_font(font_signature);
00169             if(idx >= 0)
00170             {
00171                 if(reset_cache)
00172                 {
00173                     obj_allocator<font_cache>::deallocate(m_fonts[idx]);
00174                     m_fonts[idx] = obj_allocator<font_cache>::allocate();
00175                     m_fonts[idx]->signature(font_signature);
00176                 }
00177                 m_cur_font = m_fonts[idx];
00178             }
00179             else
00180             {
00181                 if(m_num_fonts >= m_max_fonts)
00182                 {
00183                     obj_allocator<font_cache>::deallocate(m_fonts[0]);
00184                     memcpy(m_fonts, 
00185                            m_fonts + 1, 
00186                            (m_max_fonts - 1) * sizeof(font_cache*));
00187                     m_num_fonts = m_max_fonts - 1;
00188                 }
00189                 m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
00190                 m_fonts[m_num_fonts]->signature(font_signature);
00191                 m_cur_font = m_fonts[m_num_fonts];
00192                 ++m_num_fonts;
00193             }
00194         }
00195 
00196         //--------------------------------------------------------------------
00197         const font_cache* font() const
00198         {
00199             return m_cur_font;
00200         }
00201 
00202         //--------------------------------------------------------------------
00203         const glyph_cache* find_glyph(unsigned glyph_code) const
00204         {
00205             if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
00206             return 0;
00207         }
00208 
00209         //--------------------------------------------------------------------
00210         glyph_cache* cache_glyph(unsigned        glyph_code, 
00211                                  unsigned        glyph_index,
00212                                  unsigned        data_size,
00213                                  glyph_data_type data_type,
00214                                  const rect_i&   bounds,
00215                                  double          advance_x,
00216                                  double          advance_y)
00217         {
00218             if(m_cur_font) 
00219             {
00220                 return m_cur_font->cache_glyph(glyph_code,
00221                                                glyph_index,
00222                                                data_size,
00223                                                data_type,
00224                                                bounds,
00225                                                advance_x,
00226                                                advance_y);
00227             }
00228             return 0;
00229         }
00230 
00231 
00232         //--------------------------------------------------------------------
00233         int find_font(const char* font_signature)
00234         {
00235             unsigned i;
00236             for(i = 0; i < m_num_fonts; i++)
00237             {
00238                 if(m_fonts[i]->font_is(font_signature)) return int(i);
00239             }
00240             return -1;
00241         }
00242 
00243     private:
00244         font_cache** m_fonts;
00245         unsigned     m_max_fonts;
00246         unsigned     m_num_fonts;
00247         font_cache*  m_cur_font;
00248     };
00249 
00250 
00251 
00252 
00253     //------------------------------------------------------------------------
00254     enum glyph_rendering
00255     {
00256         glyph_ren_native_mono,
00257         glyph_ren_native_gray8,
00258         glyph_ren_outline,
00259         glyph_ren_agg_mono,
00260         glyph_ren_agg_gray8
00261     };
00262 
00263 
00264 
00265 
00266     //------------------------------------------------------font_cache_manager
00267     template<class FontEngine> class font_cache_manager
00268     {
00269     public:
00270         typedef FontEngine font_engine_type;
00271         typedef font_cache_manager<FontEngine> self_type;
00272         typedef typename font_engine_type::path_adaptor_type   path_adaptor_type;
00273         typedef typename font_engine_type::gray8_adaptor_type  gray8_adaptor_type;
00274         typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
00275         typedef typename font_engine_type::mono_adaptor_type   mono_adaptor_type;
00276         typedef typename mono_adaptor_type::embedded_scanline  mono_scanline_type;
00277 
00278         //--------------------------------------------------------------------
00279         font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
00280             m_fonts(max_fonts),
00281             m_engine(engine),
00282             m_change_stamp(-1),
00283             m_prev_glyph(0),
00284             m_last_glyph(0)
00285         {}
00286 
00287         //--------------------------------------------------------------------
00288         void reset_last_glyph()
00289         {
00290             m_prev_glyph = m_last_glyph = 0;
00291         }
00292 
00293         //--------------------------------------------------------------------
00294         const glyph_cache* glyph(unsigned glyph_code)
00295         {
00296             synchronize();
00297             const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
00298             if(gl) 
00299             {
00300                 m_prev_glyph = m_last_glyph;
00301                 return m_last_glyph = gl;
00302             }
00303             else
00304             {
00305                 if(m_engine.prepare_glyph(glyph_code))
00306                 {
00307                     m_prev_glyph = m_last_glyph;
00308                     m_last_glyph = m_fonts.cache_glyph(glyph_code, 
00309                                                        m_engine.glyph_index(),
00310                                                        m_engine.data_size(),
00311                                                        m_engine.data_type(),
00312                                                        m_engine.bounds(),
00313                                                        m_engine.advance_x(),
00314                                                        m_engine.advance_y());
00315                     m_engine.write_glyph_to(m_last_glyph->data);
00316                     return m_last_glyph;
00317                 }
00318             }
00319             return 0;
00320         }
00321 
00322         //--------------------------------------------------------------------
00323         void init_embedded_adaptors(const glyph_cache* gl, 
00324                                     double x, double y, 
00325                                     double scale=1.0)
00326         {
00327             if(gl)
00328             {
00329                 switch(gl->data_type)
00330                 {
00331                 default: return;
00332                 case glyph_data_mono:
00333                     m_mono_adaptor.init(gl->data, gl->data_size, x, y);
00334                     break;
00335 
00336                 case glyph_data_gray8:
00337                     m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
00338                     break;
00339 
00340                 case glyph_data_outline:
00341                     m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
00342                     break;
00343                 }
00344             }
00345         }
00346 
00347 
00348         //--------------------------------------------------------------------
00349         path_adaptor_type&   path_adaptor()   { return m_path_adaptor;   }
00350         gray8_adaptor_type&  gray8_adaptor()  { return m_gray8_adaptor;  }
00351         gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
00352         mono_adaptor_type&   mono_adaptor()   { return m_mono_adaptor;   }
00353         mono_scanline_type&  mono_scanline()  { return m_mono_scanline;  }
00354 
00355         //--------------------------------------------------------------------
00356         const glyph_cache* perv_glyph() const { return m_prev_glyph; }
00357         const glyph_cache* last_glyph() const { return m_last_glyph; }
00358 
00359         //--------------------------------------------------------------------
00360         bool add_kerning(double* x, double* y)
00361         {
00362             if(m_prev_glyph && m_last_glyph)
00363             {
00364                 return m_engine.add_kerning(m_prev_glyph->glyph_index, 
00365                                             m_last_glyph->glyph_index,
00366                                             x, y);
00367             }
00368             return false;
00369         }
00370 
00371         //--------------------------------------------------------------------
00372         void precache(unsigned from, unsigned to)
00373         {
00374             for(; from <= to; ++from) glyph(from);
00375         }
00376 
00377         //--------------------------------------------------------------------
00378         void reset_cache()
00379         {
00380             m_fonts.font(m_engine.font_signature(), true);
00381             m_change_stamp = m_engine.change_stamp();
00382             m_prev_glyph = m_last_glyph = 0;
00383         }
00384 
00385     private:
00386         //--------------------------------------------------------------------
00387         font_cache_manager(const self_type&);
00388         const self_type& operator = (const self_type&);
00389 
00390         //--------------------------------------------------------------------
00391         void synchronize()
00392         {
00393             if(m_change_stamp != m_engine.change_stamp())
00394             {
00395                 m_fonts.font(m_engine.font_signature());
00396                 m_change_stamp = m_engine.change_stamp();
00397                 m_prev_glyph = m_last_glyph = 0;
00398             }
00399         }
00400 
00401         font_cache_pool     m_fonts;
00402         font_engine_type&   m_engine;
00403         int                 m_change_stamp;
00404         double              m_dx;
00405         double              m_dy;
00406         const glyph_cache*  m_prev_glyph;
00407         const glyph_cache*  m_last_glyph;
00408         path_adaptor_type   m_path_adaptor;
00409         gray8_adaptor_type  m_gray8_adaptor;
00410         gray8_scanline_type m_gray8_scanline;
00411         mono_adaptor_type   m_mono_adaptor;
00412         mono_scanline_type  m_mono_scanline;
00413     };
00414 
00415 }
00416 
00417 #endif
00418 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines