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 //---------------------------------------------------------------------------- 15 16 #ifndef AGG_FONT_CACHE_MANAGER2_INCLUDED 17 #define AGG_FONT_CACHE_MANAGER2_INCLUDED 18 19 #include <cassert> 20 #include <exception> 21 #include <string.h> 22 #include "agg_array.h" 23 24 namespace agg { 25 26 namespace fman { 27 //---------------------------------------------------------glyph_data_type 28 enum glyph_data_type 29 { 30 glyph_data_invalid = 0, 31 glyph_data_mono = 1, 32 glyph_data_gray8 = 2, 33 glyph_data_outline = 3 34 }; 35 36 37 //-------------------------------------------------------------cached_glyph 38 struct cached_glyph 39 { 40 void * cached_font; 41 unsigned glyph_code; 42 unsigned glyph_index; 43 int8u* data; 44 unsigned data_size; 45 glyph_data_type data_type; 46 rect_i bounds; 47 double advance_x; 48 double advance_y; 49 }; 50 51 52 //--------------------------------------------------------------cached_glyphs 53 class cached_glyphs 54 { 55 public: 56 enum block_size_e { block_size = 16384-16 }; 57 58 //-------------------------------------------------------------------- cached_glyphs()59 cached_glyphs() 60 : m_allocator(block_size) 61 { memset(m_glyphs, 0, sizeof(m_glyphs)); } 62 63 //-------------------------------------------------------------------- find_glyph(unsigned glyph_code)64 const cached_glyph* find_glyph(unsigned glyph_code) const 65 { 66 unsigned msb = (glyph_code >> 8) & 0xFF; 67 if(m_glyphs[msb]) 68 { 69 return m_glyphs[msb][glyph_code & 0xFF]; 70 } 71 return 0; 72 } 73 74 //-------------------------------------------------------------------- cache_glyph(void * cached_font,unsigned glyph_code,unsigned glyph_index,unsigned data_size,glyph_data_type data_type,const rect_i & bounds,double advance_x,double advance_y)75 cached_glyph* cache_glyph( 76 void * cached_font, 77 unsigned glyph_code, 78 unsigned glyph_index, 79 unsigned data_size, 80 glyph_data_type data_type, 81 const rect_i& bounds, 82 double advance_x, 83 double advance_y) 84 { 85 unsigned msb = (glyph_code >> 8) & 0xFF; 86 if(m_glyphs[msb] == 0) 87 { 88 m_glyphs[msb] = 89 (cached_glyph**)m_allocator.allocate(sizeof(cached_glyph*) * 256, 90 sizeof(cached_glyph*)); 91 memset(m_glyphs[msb], 0, sizeof(cached_glyph*) * 256); 92 } 93 94 unsigned lsb = glyph_code & 0xFF; 95 if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite 96 97 cached_glyph* glyph = 98 (cached_glyph*)m_allocator.allocate(sizeof(cached_glyph), 99 sizeof(double)); 100 101 glyph->cached_font = cached_font; 102 glyph->glyph_code = glyph_code; 103 glyph->glyph_index = glyph_index; 104 glyph->data = m_allocator.allocate(data_size); 105 glyph->data_size = data_size; 106 glyph->data_type = data_type; 107 glyph->bounds = bounds; 108 glyph->advance_x = advance_x; 109 glyph->advance_y = advance_y; 110 return m_glyphs[msb][lsb] = glyph; 111 } 112 113 private: 114 block_allocator m_allocator; 115 cached_glyph** m_glyphs[256]; 116 }; 117 118 119 120 //------------------------------------------------------------------------ 121 enum glyph_rendering 122 { 123 glyph_ren_native_mono, 124 glyph_ren_native_gray8, 125 glyph_ren_outline, 126 glyph_ren_agg_mono, 127 glyph_ren_agg_gray8 128 }; 129 130 131 132 133 //------------------------------------------------------font_cache_manager 134 template<class FontEngine> class font_cache_manager 135 { 136 public: 137 typedef FontEngine font_engine_type; 138 typedef font_cache_manager<FontEngine> self_type; 139 typedef typename font_engine_type::path_adaptor_type path_adaptor_type; 140 typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type; 141 typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type; 142 typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type; 143 typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type; 144 145 struct cached_font 146 { cached_fontcached_font147 cached_font( 148 font_engine_type& engine, 149 typename FontEngine::loaded_face *face, 150 double height, 151 double width, 152 bool hinting, 153 glyph_rendering rendering ) 154 : m_engine( engine ) 155 , m_face( face ) 156 , m_height( height ) 157 , m_width( width ) 158 , m_hinting( hinting ) 159 , m_rendering( rendering ) 160 { 161 select_face(); 162 m_face_height=m_face->height(); 163 m_face_width=m_face->width(); 164 m_face_ascent=m_face->ascent(); 165 m_face_descent=m_face->descent(); 166 m_face_ascent_b=m_face->ascent_b(); 167 m_face_descent_b=m_face->descent_b(); 168 } 169 heightcached_font170 double height() const 171 { 172 return m_face_height; 173 } 174 widthcached_font175 double width() const 176 { 177 return m_face_width; 178 } 179 ascentcached_font180 double ascent() const 181 { 182 return m_face_ascent; 183 } 184 descentcached_font185 double descent() const 186 { 187 return m_face_descent; 188 } 189 ascent_bcached_font190 double ascent_b() const 191 { 192 return m_face_ascent_b; 193 } 194 descent_bcached_font195 double descent_b() const 196 { 197 return m_face_descent_b; 198 } 199 add_kerningcached_font200 bool add_kerning( const cached_glyph *first, const cached_glyph *second, double* x, double* y) 201 { 202 if( !first || !second ) 203 return false; 204 select_face(); 205 return m_face->add_kerning( 206 first->glyph_index, second->glyph_index, x, y ); 207 } 208 select_facecached_font209 void select_face() 210 { 211 m_face->select_instance( m_height, m_width, m_hinting, m_rendering ); 212 } 213 get_glyphcached_font214 const cached_glyph *get_glyph(unsigned cp) 215 { 216 const cached_glyph *glyph=m_glyphs.find_glyph(cp); 217 if( glyph==0 ) 218 { 219 typename FontEngine::prepared_glyph prepared; 220 select_face(); 221 bool success=m_face->prepare_glyph(cp, &prepared); 222 if( success ) 223 { 224 glyph=m_glyphs.cache_glyph( 225 this, 226 prepared.glyph_code, 227 prepared.glyph_index, 228 prepared.data_size, 229 prepared.data_type, 230 prepared.bounds, 231 prepared.advance_x, 232 prepared.advance_y ); 233 assert( glyph!=0 ); 234 m_face->write_glyph_to(&prepared,glyph->data); 235 } 236 } 237 return glyph; 238 } 239 240 font_engine_type& m_engine; 241 typename FontEngine::loaded_face *m_face; 242 double m_height; 243 double m_width; 244 bool m_hinting; 245 glyph_rendering m_rendering; 246 double m_face_height; 247 double m_face_width; 248 double m_face_ascent; 249 double m_face_descent; 250 double m_face_ascent_b; 251 double m_face_descent_b; 252 cached_glyphs m_glyphs; 253 }; 254 255 //-------------------------------------------------------------------- 256 font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) m_engine(engine)257 :m_engine(engine) 258 { } 259 260 //-------------------------------------------------------------------- 261 void init_embedded_adaptors(const cached_glyph* gl, 262 double x, double y, 263 double scale=1.0) 264 { 265 if(gl) 266 { 267 switch(gl->data_type) 268 { 269 default: return; 270 case glyph_data_mono: 271 m_mono_adaptor.init(gl->data, gl->data_size, x, y); 272 break; 273 274 case glyph_data_gray8: 275 m_gray8_adaptor.init(gl->data, gl->data_size, x, y); 276 break; 277 278 case glyph_data_outline: 279 m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); 280 break; 281 } 282 } 283 } 284 285 286 //-------------------------------------------------------------------- path_adaptor()287 path_adaptor_type& path_adaptor() { return m_path_adaptor; } gray8_adaptor()288 gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } gray8_scanline()289 gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } mono_adaptor()290 mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } mono_scanline()291 mono_scanline_type& mono_scanline() { return m_mono_scanline; } 292 293 294 private: 295 //-------------------------------------------------------------------- 296 font_cache_manager(const self_type&); 297 const self_type& operator = (const self_type&); 298 299 font_engine_type& m_engine; 300 path_adaptor_type m_path_adaptor; 301 gray8_adaptor_type m_gray8_adaptor; 302 gray8_scanline_type m_gray8_scanline; 303 mono_adaptor_type m_mono_adaptor; 304 mono_scanline_type m_mono_scanline; 305 }; 306 307 } 308 } 309 310 #endif 311 312