1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
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
20 #include "agg_array.h"
25 //---------------------------------------------------------glyph_data_type
28 glyph_data_invalid
= 0,
31 glyph_data_outline
= 3
35 //-------------------------------------------------------------glyph_cache
41 glyph_data_type data_type
;
48 //--------------------------------------------------------------font_cache
52 enum { block_size
= 16384-16 };
54 //--------------------------------------------------------------------
55 font_cache(const char* font_signature
) :
56 m_allocator(block_size
),
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;
76 return m_glyphs
[msb
][glyph_code
& 0xFF];
81 //--------------------------------------------------------------------
82 glyph_cache
* cache_glyph(unsigned glyph_code
,
85 glyph_data_type data_type
,
90 unsigned msb
= (glyph_code
>> 8) & 0xFF;
91 if(m_glyphs
[msb
] == 0)
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
103 (glyph_cache
*)m_allocator
.allocate(sizeof(glyph_cache
),
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
;
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
132 //--------------------------------------------------------------------
136 for(i
= 0; i
< m_num_fonts
; ++i
)
143 //--------------------------------------------------------------------
144 font_cache_pool(unsigned max_fonts
=32) :
145 m_fonts(new font_cache
* [max_fonts
]),
146 m_max_fonts(max_fonts
),
152 //--------------------------------------------------------------------
153 void font(const char* font_signature
, bool reset_cache
= false)
155 int idx
= find_font(font_signature
);
161 m_fonts
[idx
] = new font_cache(font_signature
);
163 m_cur_font
= m_fonts
[idx
];
167 if(m_num_fonts
>= m_max_fonts
)
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
];
181 //--------------------------------------------------------------------
182 const font_cache
* font() const
187 //--------------------------------------------------------------------
188 const glyph_cache
* find_glyph(unsigned glyph_code
) const
190 if(m_cur_font
) return m_cur_font
->find_glyph(glyph_code
);
194 //--------------------------------------------------------------------
195 glyph_cache
* cache_glyph(unsigned glyph_code
,
196 unsigned glyph_index
,
198 glyph_data_type data_type
,
205 return m_cur_font
->cache_glyph(glyph_code
,
217 //--------------------------------------------------------------------
218 int find_font(const char* font_signature
)
221 for(i
= 0; i
< m_num_fonts
; i
++)
223 if(m_fonts
[i
]->font_is(font_signature
)) return int(i
);
229 font_cache
** m_fonts
;
230 unsigned m_max_fonts
;
231 unsigned m_num_fonts
;
232 font_cache
* m_cur_font
;
238 //------------------------------------------------------------------------
241 glyph_ren_native_mono
,
242 glyph_ren_native_gray8
,
251 //------------------------------------------------------font_cache_manager
252 template<class FontEngine
> class font_cache_manager
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) :
272 //--------------------------------------------------------------------
273 const glyph_cache
* glyph(unsigned glyph_code
)
276 const glyph_cache
* gl
= m_fonts
.find_glyph(glyph_code
);
279 m_prev_glyph
= m_last_glyph
;
280 return m_last_glyph
= gl
;
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(),
292 m_engine
.advance_x(),
293 m_engine
.advance_y());
294 m_engine
.write_glyph_to(m_last_glyph
->data
);
301 //--------------------------------------------------------------------
302 void init_embedded_adaptors(const glyph_cache
* gl
,
308 switch(gl
->data_type
)
311 case glyph_data_mono
:
312 m_mono_adaptor
.init(gl
->data
, gl
->data_size
, x
, y
);
315 case glyph_data_gray8
:
316 m_gray8_adaptor
.init(gl
->data
, gl
->data_size
, x
, y
);
319 case glyph_data_outline
:
320 m_path_adaptor
.init(gl
->data
, gl
->data_size
, x
, y
, scale
);
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
,
350 //--------------------------------------------------------------------
351 void precache(unsigned from
, unsigned to
)
353 for(; from
<= to
; ++from
) glyph(from
);
356 //--------------------------------------------------------------------
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;
365 //--------------------------------------------------------------------
366 font_cache_manager(const self_type
&);
367 const self_type
& operator = (const self_type
&);
369 //--------------------------------------------------------------------
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
;
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
;