update dev300-m58
[ooovba.git] / agg / inc / agg_font_cache_manager.h
blob6ff9fade21f811d49dbce3de1021c376f3eab5ac
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
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 //----------------------------------------------------------------------------
16 #ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
17 #define AGG_FONT_CACHE_MANAGER_INCLUDED
19 #include <string.h>
20 #include "agg_array.h"
22 namespace agg
25 //---------------------------------------------------------glyph_data_type
26 enum glyph_data_type
28 glyph_data_invalid = 0,
29 glyph_data_mono = 1,
30 glyph_data_gray8 = 2,
31 glyph_data_outline = 3
35 //-------------------------------------------------------------glyph_cache
36 struct glyph_cache
38 unsigned glyph_index;
39 int8u* data;
40 unsigned data_size;
41 glyph_data_type data_type;
42 rect bounds;
43 double advance_x;
44 double advance_y;
48 //--------------------------------------------------------------font_cache
49 class font_cache
51 public:
52 enum { block_size = 16384-16 };
54 //--------------------------------------------------------------------
55 font_cache(const char* font_signature) :
56 m_allocator(block_size),
57 m_font_signature(0)
59 m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
60 strcpy(m_font_signature, font_signature);
61 memset(m_glyphs, 0, sizeof(m_glyphs));
64 //--------------------------------------------------------------------
65 bool font_is(const char* font_signature) const
67 return strcmp(font_signature, m_font_signature) == 0;
70 //--------------------------------------------------------------------
71 const glyph_cache* find_glyph(unsigned glyph_code) const
73 unsigned msb = (glyph_code >> 8) & 0xFF;
74 if(m_glyphs[msb])
76 return m_glyphs[msb][glyph_code & 0xFF];
78 return 0;
81 //--------------------------------------------------------------------
82 glyph_cache* cache_glyph(unsigned glyph_code,
83 unsigned glyph_index,
84 unsigned data_size,
85 glyph_data_type data_type,
86 const rect& bounds,
87 double advance_x,
88 double advance_y)
90 unsigned msb = (glyph_code >> 8) & 0xFF;
91 if(m_glyphs[msb] == 0)
93 m_glyphs[msb] =
94 (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
95 sizeof(glyph_cache*));
96 memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
99 unsigned lsb = glyph_code & 0xFF;
100 if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
102 glyph_cache* glyph =
103 (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
104 sizeof(double));
106 glyph->glyph_index = glyph_index;
107 glyph->data = m_allocator.allocate(data_size);
108 glyph->data_size = data_size;
109 glyph->data_type = data_type;
110 glyph->bounds = bounds;
111 glyph->advance_x = advance_x;
112 glyph->advance_y = advance_y;
113 return m_glyphs[msb][lsb] = glyph;
116 private:
117 pod_allocator m_allocator;
118 glyph_cache** m_glyphs[256];
119 char* m_font_signature;
128 //---------------------------------------------------------font_cache_pool
129 class font_cache_pool
131 public:
132 //--------------------------------------------------------------------
133 ~font_cache_pool()
135 unsigned i;
136 for(i = 0; i < m_num_fonts; ++i)
138 delete m_fonts[i];
140 delete [] m_fonts;
143 //--------------------------------------------------------------------
144 font_cache_pool(unsigned max_fonts=32) :
145 m_fonts(new font_cache* [max_fonts]),
146 m_max_fonts(max_fonts),
147 m_num_fonts(0),
148 m_cur_font(0)
152 //--------------------------------------------------------------------
153 void font(const char* font_signature, bool reset_cache = false)
155 int idx = find_font(font_signature);
156 if(idx >= 0)
158 if(reset_cache)
160 delete m_fonts[idx];
161 m_fonts[idx] = new font_cache(font_signature);
163 m_cur_font = m_fonts[idx];
165 else
167 if(m_num_fonts >= m_max_fonts)
169 delete m_fonts[0];
170 memcpy(m_fonts,
171 m_fonts + 1,
172 (m_max_fonts - 1) * sizeof(font_cache*));
173 m_num_fonts = m_max_fonts - 1;
175 m_fonts[m_num_fonts] = new font_cache(font_signature);
176 m_cur_font = m_fonts[m_num_fonts];
177 ++m_num_fonts;
181 //--------------------------------------------------------------------
182 const font_cache* font() const
184 return m_cur_font;
187 //--------------------------------------------------------------------
188 const glyph_cache* find_glyph(unsigned glyph_code) const
190 if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
191 return 0;
194 //--------------------------------------------------------------------
195 glyph_cache* cache_glyph(unsigned glyph_code,
196 unsigned glyph_index,
197 unsigned data_size,
198 glyph_data_type data_type,
199 const rect& bounds,
200 double advance_x,
201 double advance_y)
203 if(m_cur_font)
205 return m_cur_font->cache_glyph(glyph_code,
206 glyph_index,
207 data_size,
208 data_type,
209 bounds,
210 advance_x,
211 advance_y);
213 return 0;
217 //--------------------------------------------------------------------
218 int find_font(const char* font_signature)
220 unsigned i;
221 for(i = 0; i < m_num_fonts; i++)
223 if(m_fonts[i]->font_is(font_signature)) return int(i);
225 return -1;
228 private:
229 font_cache** m_fonts;
230 unsigned m_max_fonts;
231 unsigned m_num_fonts;
232 font_cache* m_cur_font;
238 //------------------------------------------------------------------------
239 enum glyph_rendering
241 glyph_ren_native_mono,
242 glyph_ren_native_gray8,
243 glyph_ren_outline,
244 glyph_ren_agg_mono,
245 glyph_ren_agg_gray8
251 //------------------------------------------------------font_cache_manager
252 template<class FontEngine> class font_cache_manager
254 public:
255 typedef FontEngine font_engine_type;
256 typedef font_cache_manager<FontEngine> self_type;
257 typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
258 typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
259 typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
260 typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
261 typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
263 //--------------------------------------------------------------------
264 font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
265 m_fonts(max_fonts),
266 m_engine(engine),
267 m_change_stamp(-1),
268 m_prev_glyph(0),
269 m_last_glyph(0)
272 //--------------------------------------------------------------------
273 const glyph_cache* glyph(unsigned glyph_code)
275 synchronize();
276 const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
277 if(gl)
279 m_prev_glyph = m_last_glyph;
280 return m_last_glyph = gl;
282 else
284 if(m_engine.prepare_glyph(glyph_code))
286 m_prev_glyph = m_last_glyph;
287 m_last_glyph = m_fonts.cache_glyph(glyph_code,
288 m_engine.glyph_index(),
289 m_engine.data_size(),
290 m_engine.data_type(),
291 m_engine.bounds(),
292 m_engine.advance_x(),
293 m_engine.advance_y());
294 m_engine.write_glyph_to(m_last_glyph->data);
295 return m_last_glyph;
298 return 0;
301 //--------------------------------------------------------------------
302 void init_embedded_adaptors(const glyph_cache* gl,
303 double x, double y,
304 double scale=1.0)
306 if(gl)
308 switch(gl->data_type)
310 default: return;
311 case glyph_data_mono:
312 m_mono_adaptor.init(gl->data, gl->data_size, x, y);
313 break;
315 case glyph_data_gray8:
316 m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
317 break;
319 case glyph_data_outline:
320 m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
321 break;
327 //--------------------------------------------------------------------
328 path_adaptor_type& path_adaptor() { return m_path_adaptor; }
329 gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
330 gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
331 mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
332 mono_scanline_type& mono_scanline() { return m_mono_scanline; }
334 //--------------------------------------------------------------------
335 const glyph_cache* perv_glyph() const { return m_prev_glyph; }
336 const glyph_cache* last_glyph() const { return m_last_glyph; }
338 //--------------------------------------------------------------------
339 bool add_kerning(double* x, double* y)
341 if(m_prev_glyph && m_last_glyph)
343 return m_engine.add_kerning(m_prev_glyph->glyph_index,
344 m_last_glyph->glyph_index,
345 x, y);
347 return false;
350 //--------------------------------------------------------------------
351 void precache(unsigned from, unsigned to)
353 for(; from <= to; ++from) glyph(from);
356 //--------------------------------------------------------------------
357 void reset_cache()
359 m_fonts.font(m_engine.font_signature(), true);
360 m_change_stamp = m_engine.change_stamp();
361 m_prev_glyph = m_last_glyph = 0;
364 private:
365 //--------------------------------------------------------------------
366 font_cache_manager(const self_type&);
367 const self_type& operator = (const self_type&);
369 //--------------------------------------------------------------------
370 void synchronize()
372 if(m_change_stamp != m_engine.change_stamp())
374 m_fonts.font(m_engine.font_signature());
375 m_change_stamp = m_engine.change_stamp();
376 m_prev_glyph = m_last_glyph = 0;
380 font_cache_pool m_fonts;
381 font_engine_type& m_engine;
382 int m_change_stamp;
383 double m_dx;
384 double m_dy;
385 const glyph_cache* m_prev_glyph;
386 const glyph_cache* m_last_glyph;
387 path_adaptor_type m_path_adaptor;
388 gray8_adaptor_type m_gray8_adaptor;
389 gray8_scanline_type m_gray8_scanline;
390 mono_adaptor_type m_mono_adaptor;
391 mono_scanline_type m_mono_scanline;
396 #endif