1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.2 3 // Copyright (C) 2002-2004 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 <string.h> 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 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 = 16384-16 }; 53 54 //-------------------------------------------------------------------- 55 font_cache(const char* font_signature) : 56 m_allocator(block_size), 57 m_font_signature(0) 58 { 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)); 62 } 63 64 //-------------------------------------------------------------------- 65 bool font_is(const char* font_signature) const 66 { 67 return strcmp(font_signature, m_font_signature) == 0; 68 } 69 70 //-------------------------------------------------------------------- 71 const glyph_cache* find_glyph(unsigned glyph_code) const 72 { 73 unsigned msb = (glyph_code >> 8) & 0xFF; 74 if(m_glyphs[msb]) 75 { 76 return m_glyphs[msb][glyph_code & 0xFF]; 77 } 78 return 0; 79 } 80 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) 89 { 90 unsigned msb = (glyph_code >> 8) & 0xFF; 91 if(m_glyphs[msb] == 0) 92 { 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); 97 } 98 99 unsigned lsb = glyph_code & 0xFF; 100 if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite 101 102 glyph_cache* glyph = 103 (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), 104 sizeof(double)); 105 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; 114 } 115 116 private: 117 pod_allocator m_allocator; 118 glyph_cache** m_glyphs[256]; 119 char* m_font_signature; 120 }; 121 122 123 124 125 126 127 128 //---------------------------------------------------------font_cache_pool 129 class font_cache_pool 130 { 131 public: 132 //-------------------------------------------------------------------- 133 ~font_cache_pool() 134 { 135 unsigned i; 136 for(i = 0; i < m_num_fonts; ++i) 137 { 138 delete m_fonts[i]; 139 } 140 delete [] m_fonts; 141 } 142 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) 149 {} 150 151 152 //-------------------------------------------------------------------- 153 void font(const char* font_signature, bool reset_cache = false) 154 { 155 int idx = find_font(font_signature); 156 if(idx >= 0) 157 { 158 if(reset_cache) 159 { 160 delete m_fonts[idx]; 161 m_fonts[idx] = new font_cache(font_signature); 162 } 163 m_cur_font = m_fonts[idx]; 164 } 165 else 166 { 167 if(m_num_fonts >= m_max_fonts) 168 { 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; 174 } 175 m_fonts[m_num_fonts] = new font_cache(font_signature); 176 m_cur_font = m_fonts[m_num_fonts]; 177 ++m_num_fonts; 178 } 179 } 180 181 //-------------------------------------------------------------------- 182 const font_cache* font() const 183 { 184 return m_cur_font; 185 } 186 187 //-------------------------------------------------------------------- 188 const glyph_cache* find_glyph(unsigned glyph_code) const 189 { 190 if(m_cur_font) return m_cur_font->find_glyph(glyph_code); 191 return 0; 192 } 193 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) 202 { 203 if(m_cur_font) 204 { 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); 212 } 213 return 0; 214 } 215 216 217 //-------------------------------------------------------------------- 218 int find_font(const char* font_signature) 219 { 220 unsigned i; 221 for(i = 0; i < m_num_fonts; i++) 222 { 223 if(m_fonts[i]->font_is(font_signature)) return int(i); 224 } 225 return -1; 226 } 227 228 private: 229 font_cache** m_fonts; 230 unsigned m_max_fonts; 231 unsigned m_num_fonts; 232 font_cache* m_cur_font; 233 }; 234 235 236 237 238 //------------------------------------------------------------------------ 239 enum glyph_rendering 240 { 241 glyph_ren_native_mono, 242 glyph_ren_native_gray8, 243 glyph_ren_outline, 244 glyph_ren_agg_mono, 245 glyph_ren_agg_gray8 246 }; 247 248 249 250 251 //------------------------------------------------------font_cache_manager 252 template<class FontEngine> class font_cache_manager 253 { 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; 262 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) 270 {} 271 272 //-------------------------------------------------------------------- 273 const glyph_cache* glyph(unsigned glyph_code) 274 { 275 synchronize(); 276 const glyph_cache* gl = m_fonts.find_glyph(glyph_code); 277 if(gl) 278 { 279 m_prev_glyph = m_last_glyph; 280 return m_last_glyph = gl; 281 } 282 else 283 { 284 if(m_engine.prepare_glyph(glyph_code)) 285 { 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; 296 } 297 } 298 return 0; 299 } 300 301 //-------------------------------------------------------------------- 302 void init_embedded_adaptors(const glyph_cache* gl, 303 double x, double y, 304 double scale=1.0) 305 { 306 if(gl) 307 { 308 switch(gl->data_type) 309 { 310 default: return; 311 case glyph_data_mono: 312 m_mono_adaptor.init(gl->data, gl->data_size, x, y); 313 break; 314 315 case glyph_data_gray8: 316 m_gray8_adaptor.init(gl->data, gl->data_size, x, y); 317 break; 318 319 case glyph_data_outline: 320 m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); 321 break; 322 } 323 } 324 } 325 326 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; } 333 334 //-------------------------------------------------------------------- 335 const glyph_cache* perv_glyph() const { return m_prev_glyph; } 336 const glyph_cache* last_glyph() const { return m_last_glyph; } 337 338 //-------------------------------------------------------------------- 339 bool add_kerning(double* x, double* y) 340 { 341 if(m_prev_glyph && m_last_glyph) 342 { 343 return m_engine.add_kerning(m_prev_glyph->glyph_index, 344 m_last_glyph->glyph_index, 345 x, y); 346 } 347 return false; 348 } 349 350 //-------------------------------------------------------------------- 351 void precache(unsigned from, unsigned to) 352 { 353 for(; from <= to; ++from) glyph(from); 354 } 355 356 //-------------------------------------------------------------------- 357 void reset_cache() 358 { 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; 362 } 363 364 private: 365 //-------------------------------------------------------------------- 366 font_cache_manager(const self_type&); 367 const self_type& operator = (const self_type&); 368 369 //-------------------------------------------------------------------- 370 void synchronize() 371 { 372 if(m_change_stamp != m_engine.change_stamp()) 373 { 374 m_fonts.font(m_engine.font_signature()); 375 m_change_stamp = m_engine.change_stamp(); 376 m_prev_glyph = m_last_glyph = 0; 377 } 378 } 379 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; 392 }; 393 394 } 395 396 #endif 397 398