btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_font_cache_manager.h
blobe9cf5bf606b610f6c780a7d9b2f0d68ae83d5627
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 //----------------------------------------------------------------------------
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_i bounds;
43 double advance_x;
44 double advance_y;
48 //--------------------------------------------------------------font_cache
49 class font_cache
51 public:
52 enum block_size_e { block_size = 16384-16 };
54 //--------------------------------------------------------------------
55 font_cache() :
56 m_allocator(block_size),
57 m_font_signature(0)
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;
78 if(m_glyphs[msb])
80 return m_glyphs[msb][glyph_code & 0xFF];
82 return 0;
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)
94 unsigned msb = (glyph_code >> 8) & 0xFF;
95 if(m_glyphs[msb] == 0)
97 m_glyphs[msb] =
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
106 glyph_cache* glyph =
107 (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
108 sizeof(double));
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;
120 private:
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
135 public:
136 //--------------------------------------------------------------------
137 ~font_cache_pool()
139 unsigned i;
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),
151 m_num_fonts(0),
152 m_cur_font(0)
156 //--------------------------------------------------------------------
157 void font(const char* font_signature, bool reset_cache = false)
159 int idx = find_font(font_signature);
160 if(idx >= 0)
162 if(reset_cache)
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];
170 else
172 if(m_num_fonts >= m_max_fonts)
174 obj_allocator<font_cache>::deallocate(m_fonts[0]);
175 memcpy(m_fonts,
176 m_fonts + 1,
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];
183 ++m_num_fonts;
187 //--------------------------------------------------------------------
188 const font_cache* font() const
190 return m_cur_font;
193 //--------------------------------------------------------------------
194 const glyph_cache* find_glyph(unsigned glyph_code) const
196 if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
197 return 0;
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)
209 if(m_cur_font)
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);
219 return 0;
223 //--------------------------------------------------------------------
224 int find_font(const char* font_signature)
226 unsigned i;
227 for(i = 0; i < m_num_fonts; i++)
229 if(m_fonts[i]->font_is(font_signature)) return int(i);
231 return -1;
234 private:
235 font_cache** m_fonts;
236 unsigned m_max_fonts;
237 unsigned m_num_fonts;
238 font_cache* m_cur_font;
244 //------------------------------------------------------------------------
245 enum glyph_rendering
247 glyph_ren_native_mono,
248 glyph_ren_native_gray8,
249 glyph_ren_outline,
250 glyph_ren_agg_mono,
251 glyph_ren_agg_gray8
257 //------------------------------------------------------font_cache_manager
258 template<class FontEngine> class font_cache_manager
260 public:
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) :
271 m_fonts(max_fonts),
272 m_engine(engine),
273 m_change_stamp(-1),
274 m_prev_glyph(0),
275 m_last_glyph(0)
278 //--------------------------------------------------------------------
279 const glyph_cache* glyph(unsigned glyph_code)
281 synchronize();
282 const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
283 if(gl)
285 m_prev_glyph = m_last_glyph;
286 return m_last_glyph = gl;
288 else
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(),
297 m_engine.bounds(),
298 m_engine.advance_x(),
299 m_engine.advance_y());
300 m_engine.write_glyph_to(m_last_glyph->data);
301 return m_last_glyph;
304 return 0;
307 //--------------------------------------------------------------------
308 void init_embedded_adaptors(const glyph_cache* gl,
309 double x, double y,
310 double scale=1.0)
312 if(gl)
314 switch(gl->data_type)
316 default: return;
317 case glyph_data_mono:
318 m_mono_adaptor.init(gl->data, gl->data_size, x, y);
319 break;
321 case glyph_data_gray8:
322 m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
323 break;
325 case glyph_data_outline:
326 m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
327 break;
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,
351 x, y);
353 return false;
356 //--------------------------------------------------------------------
357 void precache(unsigned from, unsigned to)
359 for(; from <= to; ++from) glyph(from);
362 //--------------------------------------------------------------------
363 void reset_cache()
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 //--------------------------------------------------------------------
371 void reset()
373 m_prev_glyph = m_last_glyph = 0;
376 private:
377 //--------------------------------------------------------------------
378 font_cache_manager(const self_type&);
379 const self_type& operator = (const self_type&);
381 //--------------------------------------------------------------------
382 void synchronize()
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;
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;
408 #endif