1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
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_e
{ block_size
= 16384-16 };
54 //--------------------------------------------------------------------
56 m_allocator(block_size
),
60 //--------------------------------------------------------------------
61 void signature(const char* font_signature
)
63 m_font_signature
= (char*)m_allocator
.allocate(strlen(font_signature
) + 1);
64 strcpy(m_font_signature
, font_signature
);
65 memset(m_glyphs
, 0, sizeof(m_glyphs
));
68 //--------------------------------------------------------------------
69 bool font_is(const char* font_signature
) const
71 return strcmp(font_signature
, m_font_signature
) == 0;
74 //--------------------------------------------------------------------
75 const glyph_cache
* find_glyph(unsigned glyph_code
) const
77 unsigned msb
= (glyph_code
>> 8) & 0xFF;
80 return m_glyphs
[msb
][glyph_code
& 0xFF];
85 //--------------------------------------------------------------------
86 glyph_cache
* cache_glyph(unsigned glyph_code
,
89 glyph_data_type data_type
,
94 unsigned msb
= (glyph_code
>> 8) & 0xFF;
95 if(m_glyphs
[msb
] == 0)
98 (glyph_cache
**)m_allocator
.allocate(sizeof(glyph_cache
*) * 256,
99 sizeof(glyph_cache
*));
100 memset(m_glyphs
[msb
], 0, sizeof(glyph_cache
*) * 256);
103 unsigned lsb
= glyph_code
& 0xFF;
104 if(m_glyphs
[msb
][lsb
]) return 0; // Already exists, do not overwrite
107 (glyph_cache
*)m_allocator
.allocate(sizeof(glyph_cache
),
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
;
121 block_allocator m_allocator
;
122 glyph_cache
** m_glyphs
[256];
123 char* m_font_signature
;
132 //---------------------------------------------------------font_cache_pool
133 class font_cache_pool
136 //--------------------------------------------------------------------
140 for(i
= 0; i
< m_num_fonts
; ++i
)
142 obj_allocator
<font_cache
>::deallocate(m_fonts
[i
]);
144 pod_allocator
<font_cache
*>::deallocate(m_fonts
, m_max_fonts
);
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
),
156 //--------------------------------------------------------------------
157 void font(const char* font_signature
, bool reset_cache
= false)
159 int idx
= find_font(font_signature
);
164 obj_allocator
<font_cache
>::deallocate(m_fonts
[idx
]);
165 m_fonts
[idx
] = obj_allocator
<font_cache
>::allocate();
166 m_fonts
[idx
]->signature(font_signature
);
168 m_cur_font
= m_fonts
[idx
];
172 if(m_num_fonts
>= m_max_fonts
)
174 obj_allocator
<font_cache
>::deallocate(m_fonts
[0]);
177 (m_max_fonts
- 1) * sizeof(font_cache
*));
178 m_num_fonts
= m_max_fonts
- 1;
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
];
187 //--------------------------------------------------------------------
188 const font_cache
* font() const
193 //--------------------------------------------------------------------
194 const glyph_cache
* find_glyph(unsigned glyph_code
) const
196 if(m_cur_font
) return m_cur_font
->find_glyph(glyph_code
);
200 //--------------------------------------------------------------------
201 glyph_cache
* cache_glyph(unsigned glyph_code
,
202 unsigned glyph_index
,
204 glyph_data_type data_type
,
205 const rect_i
& bounds
,
211 return m_cur_font
->cache_glyph(glyph_code
,
223 //--------------------------------------------------------------------
224 int find_font(const char* font_signature
)
227 for(i
= 0; i
< m_num_fonts
; i
++)
229 if(m_fonts
[i
]->font_is(font_signature
)) return int(i
);
235 font_cache
** m_fonts
;
236 unsigned m_max_fonts
;
237 unsigned m_num_fonts
;
238 font_cache
* m_cur_font
;
244 //------------------------------------------------------------------------
247 glyph_ren_native_mono
,
248 glyph_ren_native_gray8
,
257 //------------------------------------------------------font_cache_manager
258 template<class FontEngine
> class font_cache_manager
261 typedef FontEngine font_engine_type
;
262 typedef font_cache_manager
<FontEngine
> self_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
;
269 //--------------------------------------------------------------------
270 font_cache_manager(font_engine_type
& engine
, unsigned max_fonts
=32) :
278 //--------------------------------------------------------------------
279 const glyph_cache
* glyph(unsigned glyph_code
)
282 const glyph_cache
* gl
= m_fonts
.find_glyph(glyph_code
);
285 m_prev_glyph
= m_last_glyph
;
286 return m_last_glyph
= gl
;
290 if(m_engine
.prepare_glyph(glyph_code
))
292 m_prev_glyph
= m_last_glyph
;
293 m_last_glyph
= m_fonts
.cache_glyph(glyph_code
,
294 m_engine
.glyph_index(),
295 m_engine
.data_size(),
296 m_engine
.data_type(),
298 m_engine
.advance_x(),
299 m_engine
.advance_y());
300 m_engine
.write_glyph_to(m_last_glyph
->data
);
307 //--------------------------------------------------------------------
308 void init_embedded_adaptors(const glyph_cache
* gl
,
314 switch(gl
->data_type
)
317 case glyph_data_mono
:
318 m_mono_adaptor
.init(gl
->data
, gl
->data_size
, x
, y
);
321 case glyph_data_gray8
:
322 m_gray8_adaptor
.init(gl
->data
, gl
->data_size
, x
, y
);
325 case glyph_data_outline
:
326 m_path_adaptor
.init(gl
->data
, gl
->data_size
, x
, y
, scale
);
333 //--------------------------------------------------------------------
334 path_adaptor_type
& path_adaptor() { return m_path_adaptor
; }
335 gray8_adaptor_type
& gray8_adaptor() { return m_gray8_adaptor
; }
336 gray8_scanline_type
& gray8_scanline() { return m_gray8_scanline
; }
337 mono_adaptor_type
& mono_adaptor() { return m_mono_adaptor
; }
338 mono_scanline_type
& mono_scanline() { return m_mono_scanline
; }
340 //--------------------------------------------------------------------
341 const glyph_cache
* perv_glyph() const { return m_prev_glyph
; }
342 const glyph_cache
* last_glyph() const { return m_last_glyph
; }
344 //--------------------------------------------------------------------
345 bool add_kerning(double* x
, double* y
)
347 if(m_prev_glyph
&& m_last_glyph
)
349 return m_engine
.add_kerning(m_prev_glyph
->glyph_index
,
350 m_last_glyph
->glyph_index
,
356 //--------------------------------------------------------------------
357 void precache(unsigned from
, unsigned to
)
359 for(; from
<= to
; ++from
) glyph(from
);
362 //--------------------------------------------------------------------
365 m_fonts
.font(m_engine
.font_signature(), true);
366 m_change_stamp
= m_engine
.change_stamp();
367 m_prev_glyph
= m_last_glyph
= 0;
370 //--------------------------------------------------------------------
373 m_prev_glyph
= m_last_glyph
= 0;
377 //--------------------------------------------------------------------
378 font_cache_manager(const self_type
&);
379 const self_type
& operator = (const self_type
&);
381 //--------------------------------------------------------------------
384 if(m_change_stamp
!= m_engine
.change_stamp())
386 m_fonts
.font(m_engine
.font_signature());
387 m_change_stamp
= m_engine
.change_stamp();
388 m_prev_glyph
= m_last_glyph
= 0;
392 font_cache_pool m_fonts
;
393 font_engine_type
& m_engine
;
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
;