Anti-Grain Geometry Tutorial
agg_font_cache_manager.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_MANAGER_INCLUDED
17 #define AGG_FONT_CACHE_MANAGER_INCLUDED
18 
19 #include <cstring>
20 #include "agg_array.h"
21 
22 namespace agg
23 {
24 
25  //---------------------------------------------------------glyph_data_type
26  enum glyph_data_type
27  {
28  glyph_data_invalid = 0,
29  glyph_data_mono = 1,
30  glyph_data_gray8 = 2,
31  glyph_data_outline = 3
32  };
33 
34 
35  //-------------------------------------------------------------glyph_cache
36  struct glyph_cache
37  {
38  unsigned glyph_index;
39  int8u* data;
40  unsigned data_size;
41  glyph_data_type data_type;
42  rect_i bounds;
43  double advance_x;
44  double advance_y;
45  };
46 
47 
48  //--------------------------------------------------------------font_cache
49  class font_cache
50  {
51  public:
52  enum block_size_e { block_size = 16384-16 };
53 
54  //--------------------------------------------------------------------
55  font_cache() :
56  m_allocator(block_size),
57  m_font_signature(0)
58  {}
59 
60  //--------------------------------------------------------------------
61  void signature(const char* font_signature)
62  {
63  m_font_signature = (char*)m_allocator.allocate(std::strlen(font_signature) + 1);
64  std::strcpy(m_font_signature, font_signature);
65  std::memset(m_glyphs, 0, sizeof(m_glyphs));
66  }
67 
68  //--------------------------------------------------------------------
69  bool font_is(const char* font_signature) const
70  {
71  return std::strcmp(font_signature, m_font_signature) == 0;
72  }
73 
74  //--------------------------------------------------------------------
75  const glyph_cache* find_glyph(unsigned glyph_code) const
76  {
77  unsigned msb = (glyph_code >> 8) & 0xFF;
78  if(m_glyphs[msb])
79  {
80  return m_glyphs[msb][glyph_code & 0xFF];
81  }
82  return 0;
83  }
84 
85  //--------------------------------------------------------------------
86  glyph_cache* cache_glyph(unsigned glyph_code,
87  unsigned glyph_index,
88  unsigned data_size,
89  glyph_data_type data_type,
90  const rect_i& bounds,
91  double advance_x,
92  double advance_y)
93  {
94  unsigned msb = (glyph_code >> 8) & 0xFF;
95  if(m_glyphs[msb] == 0)
96  {
97  m_glyphs[msb] =
98  (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
99  sizeof(glyph_cache*));
100  std::memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
101  }
102 
103  unsigned lsb = glyph_code & 0xFF;
104  if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
105 
106  glyph_cache* glyph =
107  (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
108  sizeof(double));
109 
110  glyph->glyph_index = glyph_index;
111  glyph->data = m_allocator.allocate(data_size);
112  glyph->data_size = data_size;
113  glyph->data_type = data_type;
114  glyph->bounds = bounds;
115  glyph->advance_x = advance_x;
116  glyph->advance_y = advance_y;
117  return m_glyphs[msb][lsb] = glyph;
118  }
119 
120  private:
121  block_allocator m_allocator;
122  glyph_cache** m_glyphs[256];
123  char* m_font_signature;
124  };
125 
126 
127 
128 
129 
130 
131 
132  //---------------------------------------------------------font_cache_pool
134  {
135  public:
136  //--------------------------------------------------------------------
137  ~font_cache_pool()
138  {
139  unsigned i;
140  for(i = 0; i < m_num_fonts; ++i)
141  {
143  }
144  pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
145  }
146 
147  //--------------------------------------------------------------------
148  font_cache_pool(unsigned max_fonts=32) :
149  m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
150  m_max_fonts(max_fonts),
151  m_num_fonts(0),
152  m_cur_font(0)
153  {}
154 
155 
156  //--------------------------------------------------------------------
157  void font(const char* font_signature, bool reset_cache = false)
158  {
159  int idx = find_font(font_signature);
160  if(idx >= 0)
161  {
162  if(reset_cache)
163  {
165  m_fonts[idx] = obj_allocator<font_cache>::allocate();
166  m_fonts[idx]->signature(font_signature);
167  }
168  m_cur_font = m_fonts[idx];
169  }
170  else
171  {
172  if(m_num_fonts >= m_max_fonts)
173  {
175  std::memcpy(m_fonts,
176  m_fonts + 1,
177  (m_max_fonts - 1) * sizeof(font_cache*));
178  m_num_fonts = m_max_fonts - 1;
179  }
180  m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
181  m_fonts[m_num_fonts]->signature(font_signature);
182  m_cur_font = m_fonts[m_num_fonts];
183  ++m_num_fonts;
184  }
185  }
186 
187  //--------------------------------------------------------------------
188  const font_cache* font() const
189  {
190  return m_cur_font;
191  }
192 
193  //--------------------------------------------------------------------
194  const glyph_cache* find_glyph(unsigned glyph_code) const
195  {
196  if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
197  return 0;
198  }
199 
200  //--------------------------------------------------------------------
201  glyph_cache* cache_glyph(unsigned glyph_code,
202  unsigned glyph_index,
203  unsigned data_size,
204  glyph_data_type data_type,
205  const rect_i& bounds,
206  double advance_x,
207  double advance_y)
208  {
209  if(m_cur_font)
210  {
211  return m_cur_font->cache_glyph(glyph_code,
212  glyph_index,
213  data_size,
214  data_type,
215  bounds,
216  advance_x,
217  advance_y);
218  }
219  return 0;
220  }
221 
222 
223  //--------------------------------------------------------------------
224  int find_font(const char* font_signature)
225  {
226  unsigned i;
227  for(i = 0; i < m_num_fonts; i++)
228  {
229  if(m_fonts[i]->font_is(font_signature)) return int(i);
230  }
231  return -1;
232  }
233 
234  private:
235  font_cache** m_fonts;
236  unsigned m_max_fonts;
237  unsigned m_num_fonts;
238  font_cache* m_cur_font;
239  };
240 
241 
242 
243 
244  //------------------------------------------------------------------------
245  enum glyph_rendering
246  {
247  glyph_ren_native_mono,
248  glyph_ren_native_gray8,
249  glyph_ren_outline,
250  glyph_ren_agg_mono,
251  glyph_ren_agg_gray8
252  };
253 
254 
255 
256 
257  //------------------------------------------------------font_cache_manager
258  template<class FontEngine> class font_cache_manager
259  {
260  public:
261  typedef FontEngine font_engine_type;
263  typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
264  typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
265  typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
266  typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
267  typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
268 
269  //--------------------------------------------------------------------
270  font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
271  m_fonts(max_fonts),
272  m_engine(engine),
273  m_change_stamp(-1),
274  m_prev_glyph(0),
275  m_last_glyph(0)
276  {}
277 
278  //--------------------------------------------------------------------
279  void reset_last_glyph()
280  {
281  m_prev_glyph = m_last_glyph = 0;
282  }
283 
284  //--------------------------------------------------------------------
285  const glyph_cache* glyph(unsigned glyph_code)
286  {
287  synchronize();
288  const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
289  if(gl)
290  {
291  m_prev_glyph = m_last_glyph;
292  return m_last_glyph = gl;
293  }
294  else
295  {
296  if(m_engine.prepare_glyph(glyph_code))
297  {
298  m_prev_glyph = m_last_glyph;
299  m_last_glyph = m_fonts.cache_glyph(glyph_code,
300  m_engine.glyph_index(),
301  m_engine.data_size(),
302  m_engine.data_type(),
303  m_engine.bounds(),
304  m_engine.advance_x(),
305  m_engine.advance_y());
306  m_engine.write_glyph_to(m_last_glyph->data);
307  return m_last_glyph;
308  }
309  }
310  return 0;
311  }
312 
313  //--------------------------------------------------------------------
314  void init_embedded_adaptors(const glyph_cache* gl,
315  double x, double y,
316  double scale=1.0)
317  {
318  if(gl)
319  {
320  switch(gl->data_type)
321  {
322  default: return;
323  case glyph_data_mono:
324  m_mono_adaptor.init(gl->data, gl->data_size, x, y);
325  break;
326 
327  case glyph_data_gray8:
328  m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
329  break;
330 
331  case glyph_data_outline:
332  m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
333  break;
334  }
335  }
336  }
337 
338 
339  //--------------------------------------------------------------------
340  path_adaptor_type& path_adaptor() { return m_path_adaptor; }
341  gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
342  gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
343  mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
344  mono_scanline_type& mono_scanline() { return m_mono_scanline; }
345 
346  //--------------------------------------------------------------------
347  const glyph_cache* perv_glyph() const { return m_prev_glyph; }
348  const glyph_cache* last_glyph() const { return m_last_glyph; }
349 
350  //--------------------------------------------------------------------
351  bool add_kerning(double* x, double* y)
352  {
353  if(m_prev_glyph && m_last_glyph)
354  {
355  return m_engine.add_kerning(m_prev_glyph->glyph_index,
356  m_last_glyph->glyph_index,
357  x, y);
358  }
359  return false;
360  }
361 
362  //--------------------------------------------------------------------
363  void precache(unsigned from, unsigned to)
364  {
365  for(; from <= to; ++from) glyph(from);
366  }
367 
368  //--------------------------------------------------------------------
369  void reset_cache()
370  {
371  m_fonts.font(m_engine.font_signature(), true);
372  m_change_stamp = m_engine.change_stamp();
373  m_prev_glyph = m_last_glyph = 0;
374  }
375 
376  private:
377  //--------------------------------------------------------------------
378  font_cache_manager(const self_type&);
379  const self_type& operator = (const self_type&);
380 
381  //--------------------------------------------------------------------
382  void synchronize()
383  {
384  if(m_change_stamp != m_engine.change_stamp())
385  {
386  m_fonts.font(m_engine.font_signature());
387  m_change_stamp = m_engine.change_stamp();
388  m_prev_glyph = m_last_glyph = 0;
389  }
390  }
391 
392  font_cache_pool m_fonts;
393  font_engine_type& m_engine;
394  int m_change_stamp;
395  double m_dx;
396  double m_dy;
397  const glyph_cache* m_prev_glyph;
398  const glyph_cache* m_last_glyph;
399  path_adaptor_type m_path_adaptor;
400  gray8_adaptor_type m_gray8_adaptor;
401  gray8_scanline_type m_gray8_scanline;
402  mono_adaptor_type m_mono_adaptor;
403  mono_scanline_type m_mono_scanline;
404  };
405 
406 }
407 
408 #endif
409 
Definition: agg_arc.cpp:24