Anti-Grain Geometry Tutorial
agg_font_cache_manager2.h
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 <cstring>
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
54  {
55  public:
56  enum block_size_e { block_size = 16384-16 };
57 
58  //--------------------------------------------------------------------
60  : m_allocator(block_size)
61  { std::memset(m_glyphs, 0, sizeof(m_glyphs)); }
62 
63  //--------------------------------------------------------------------
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  //--------------------------------------------------------------------
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  std::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;
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  {
147  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 
170  double height() const
171  {
172  return m_face_height;
173  }
174 
175  double width() const
176  {
177  return m_face_width;
178  }
179 
180  double ascent() const
181  {
182  return m_face_ascent;
183  }
184 
185  double descent() const
186  {
187  return m_face_descent;
188  }
189 
190  double ascent_b() const
191  {
192  return m_face_ascent_b;
193  }
194 
195  double descent_b() const
196  {
197  return m_face_descent_b;
198  }
199 
200  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 
209  void select_face()
210  {
211  m_face->select_instance( m_height, m_width, m_hinting, m_rendering );
212  }
213 
214  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)
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  //--------------------------------------------------------------------
287  path_adaptor_type& path_adaptor() { return m_path_adaptor; }
288  gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
289  gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
290  mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
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 
Definition: agg_arc.cpp:24