1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 
16 #ifndef AGG_FONT_CACHE_MANAGER2_INCLUDED
17 #define AGG_FONT_CACHE_MANAGER2_INCLUDED
18 
19 #include <cassert>
20 #include <exception>
21 #include <string.h>
22 #include "agg_array.h"
23 
24 namespace agg {
25 
26 namespace fman {
27   //---------------------------------------------------------glyph_data_type
28   enum glyph_data_type
29   {
30     glyph_data_invalid = 0,
31     glyph_data_mono    = 1,
32     glyph_data_gray8   = 2,
33     glyph_data_outline = 3
34   };
35 
36 
37   //-------------------------------------------------------------cached_glyph
38   struct cached_glyph
39   {
40     void *			cached_font;
41     unsigned		glyph_code;
42     unsigned        glyph_index;
43     int8u*          data;
44     unsigned        data_size;
45     glyph_data_type data_type;
46     rect_i          bounds;
47     double          advance_x;
48     double          advance_y;
49   };
50 
51 
52   //--------------------------------------------------------------cached_glyphs
53   class cached_glyphs
54   {
55   public:
56     enum block_size_e { block_size = 16384-16 };
57 
58     //--------------------------------------------------------------------
cached_glyphs()59     cached_glyphs()
60       : m_allocator(block_size)
61     { memset(m_glyphs, 0, sizeof(m_glyphs)); }
62 
63     //--------------------------------------------------------------------
find_glyph(unsigned glyph_code)64     const cached_glyph* find_glyph(unsigned glyph_code) const
65     {
66       unsigned msb = (glyph_code >> 8) & 0xFF;
67       if(m_glyphs[msb])
68       {
69         return m_glyphs[msb][glyph_code & 0xFF];
70       }
71       return 0;
72     }
73 
74     //--------------------------------------------------------------------
cache_glyph(void * cached_font,unsigned glyph_code,unsigned glyph_index,unsigned data_size,glyph_data_type data_type,const rect_i & bounds,double advance_x,double advance_y)75     cached_glyph* cache_glyph(
76       void *			cached_font,
77       unsigned        glyph_code,
78       unsigned        glyph_index,
79       unsigned        data_size,
80       glyph_data_type data_type,
81       const rect_i&   bounds,
82       double          advance_x,
83       double          advance_y)
84     {
85       unsigned msb = (glyph_code >> 8) & 0xFF;
86       if(m_glyphs[msb] == 0)
87       {
88         m_glyphs[msb] =
89           (cached_glyph**)m_allocator.allocate(sizeof(cached_glyph*) * 256,
90           sizeof(cached_glyph*));
91         memset(m_glyphs[msb], 0, sizeof(cached_glyph*) * 256);
92       }
93 
94       unsigned lsb = glyph_code & 0xFF;
95       if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
96 
97       cached_glyph* glyph =
98         (cached_glyph*)m_allocator.allocate(sizeof(cached_glyph),
99         sizeof(double));
100 
101       glyph->cached_font		  = cached_font;
102       glyph->glyph_code		  = glyph_code;
103       glyph->glyph_index        = glyph_index;
104       glyph->data               = m_allocator.allocate(data_size);
105       glyph->data_size          = data_size;
106       glyph->data_type          = data_type;
107       glyph->bounds             = bounds;
108       glyph->advance_x          = advance_x;
109       glyph->advance_y          = advance_y;
110       return m_glyphs[msb][lsb] = glyph;
111     }
112 
113   private:
114     block_allocator m_allocator;
115     cached_glyph**   m_glyphs[256];
116   };
117 
118 
119 
120   //------------------------------------------------------------------------
121   enum glyph_rendering
122   {
123     glyph_ren_native_mono,
124     glyph_ren_native_gray8,
125     glyph_ren_outline,
126     glyph_ren_agg_mono,
127     glyph_ren_agg_gray8
128   };
129 
130 
131 
132 
133   //------------------------------------------------------font_cache_manager
134   template<class FontEngine> class font_cache_manager
135   {
136   public:
137     typedef FontEngine font_engine_type;
138     typedef font_cache_manager<FontEngine> self_type;
139     typedef typename font_engine_type::path_adaptor_type   path_adaptor_type;
140     typedef typename font_engine_type::gray8_adaptor_type  gray8_adaptor_type;
141     typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
142     typedef typename font_engine_type::mono_adaptor_type   mono_adaptor_type;
143     typedef typename mono_adaptor_type::embedded_scanline  mono_scanline_type;
144 
145     struct cached_font
146     {
cached_fontcached_font147       cached_font(
148         font_engine_type& engine,
149         typename FontEngine::loaded_face *face,
150         double height,
151         double width,
152         bool hinting,
153         glyph_rendering rendering )
154         : m_engine( engine )
155         , m_face( face )
156         , m_height( height )
157         , m_width( width )
158         , m_hinting( hinting )
159         , m_rendering( rendering )
160       {
161         select_face();
162         m_face_height=m_face->height();
163         m_face_width=m_face->width();
164         m_face_ascent=m_face->ascent();
165         m_face_descent=m_face->descent();
166         m_face_ascent_b=m_face->ascent_b();
167         m_face_descent_b=m_face->descent_b();
168       }
169 
heightcached_font170       double height() const
171       {
172         return m_face_height;
173       }
174 
widthcached_font175       double width() const
176       {
177         return m_face_width;
178       }
179 
ascentcached_font180       double ascent() const
181       {
182         return m_face_ascent;
183       }
184 
descentcached_font185       double descent() const
186       {
187         return m_face_descent;
188       }
189 
ascent_bcached_font190       double ascent_b() const
191       {
192         return m_face_ascent_b;
193       }
194 
descent_bcached_font195       double descent_b() const
196       {
197         return m_face_descent_b;
198       }
199 
add_kerningcached_font200       bool add_kerning( const cached_glyph *first, const cached_glyph *second, double* x, double* y)
201       {
202         if( !first || !second )
203           return false;
204         select_face();
205         return m_face->add_kerning(
206           first->glyph_index, second->glyph_index, x, y );
207       }
208 
select_facecached_font209       void select_face()
210       {
211         m_face->select_instance( m_height, m_width, m_hinting, m_rendering );
212       }
213 
get_glyphcached_font214       const cached_glyph *get_glyph(unsigned cp)
215       {
216         const cached_glyph *glyph=m_glyphs.find_glyph(cp);
217         if( glyph==0 )
218         {
219           typename FontEngine::prepared_glyph prepared;
220           select_face();
221           bool success=m_face->prepare_glyph(cp, &prepared);
222           if( success )
223           {
224             glyph=m_glyphs.cache_glyph(
225               this,
226               prepared.glyph_code,
227               prepared.glyph_index,
228               prepared.data_size,
229               prepared.data_type,
230               prepared.bounds,
231               prepared.advance_x,
232               prepared.advance_y );
233             assert( glyph!=0 );
234             m_face->write_glyph_to(&prepared,glyph->data);
235           }
236         }
237         return glyph;
238       }
239 
240       font_engine_type&   m_engine;
241       typename FontEngine::loaded_face *m_face;
242       double				m_height;
243       double				m_width;
244       bool				m_hinting;
245       glyph_rendering		m_rendering;
246       double				m_face_height;
247       double				m_face_width;
248       double				m_face_ascent;
249       double				m_face_descent;
250       double				m_face_ascent_b;
251       double				m_face_descent_b;
252       cached_glyphs		m_glyphs;
253     };
254 
255     //--------------------------------------------------------------------
256     font_cache_manager(font_engine_type& engine, unsigned max_fonts=32)
m_engine(engine)257       :m_engine(engine)
258     { }
259 
260     //--------------------------------------------------------------------
261     void init_embedded_adaptors(const cached_glyph* gl,
262       double x, double y,
263       double scale=1.0)
264     {
265       if(gl)
266       {
267         switch(gl->data_type)
268         {
269         default: return;
270         case glyph_data_mono:
271           m_mono_adaptor.init(gl->data, gl->data_size, x, y);
272           break;
273 
274         case glyph_data_gray8:
275           m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
276           break;
277 
278         case glyph_data_outline:
279           m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
280           break;
281         }
282       }
283     }
284 
285 
286     //--------------------------------------------------------------------
path_adaptor()287     path_adaptor_type&   path_adaptor()   { return m_path_adaptor;   }
gray8_adaptor()288     gray8_adaptor_type&  gray8_adaptor()  { return m_gray8_adaptor;  }
gray8_scanline()289     gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
mono_adaptor()290     mono_adaptor_type&   mono_adaptor()   { return m_mono_adaptor;   }
mono_scanline()291     mono_scanline_type&  mono_scanline()  { return m_mono_scanline;  }
292 
293 
294   private:
295     //--------------------------------------------------------------------
296     font_cache_manager(const self_type&);
297     const self_type& operator = (const self_type&);
298 
299     font_engine_type&   m_engine;
300     path_adaptor_type   m_path_adaptor;
301     gray8_adaptor_type  m_gray8_adaptor;
302     gray8_scanline_type m_gray8_scanline;
303     mono_adaptor_type   m_mono_adaptor;
304     mono_scanline_type  m_mono_scanline;
305   };
306 
307 }
308 }
309 
310 #endif
311 
312