Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef AGG_FONT_CACHE_MANAGER_INCLUDED 00026 #define AGG_FONT_CACHE_MANAGER_INCLUDED 00027 00028 #include <string.h> 00029 #include "agg_array.h" 00030 00031 namespace agg 00032 { 00033 00034 //---------------------------------------------------------glyph_data_type 00035 enum glyph_data_type 00036 { 00037 glyph_data_invalid = 0, 00038 glyph_data_mono = 1, 00039 glyph_data_gray8 = 2, 00040 glyph_data_outline = 3 00041 }; 00042 00043 00044 //-------------------------------------------------------------glyph_cache 00045 struct glyph_cache 00046 { 00047 unsigned glyph_index; 00048 int8u* data; 00049 unsigned data_size; 00050 glyph_data_type data_type; 00051 rect_i bounds; 00052 double advance_x; 00053 double advance_y; 00054 }; 00055 00056 00057 //--------------------------------------------------------------font_cache 00058 class font_cache 00059 { 00060 public: 00061 enum block_size_e { block_size = 16384-16 }; 00062 00063 //-------------------------------------------------------------------- 00064 font_cache() : 00065 m_allocator(block_size), 00066 m_font_signature(0) 00067 {} 00068 00069 //-------------------------------------------------------------------- 00070 void signature(const char* font_signature) 00071 { 00072 m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); 00073 strcpy(m_font_signature, font_signature); 00074 memset(m_glyphs, 0, sizeof(m_glyphs)); 00075 } 00076 00077 //-------------------------------------------------------------------- 00078 bool font_is(const char* font_signature) const 00079 { 00080 return strcmp(font_signature, m_font_signature) == 0; 00081 } 00082 00083 //-------------------------------------------------------------------- 00084 const glyph_cache* find_glyph(unsigned glyph_code) const 00085 { 00086 unsigned msb = (glyph_code >> 8) & 0xFF; 00087 if(m_glyphs[msb]) 00088 { 00089 return m_glyphs[msb][glyph_code & 0xFF]; 00090 } 00091 return 0; 00092 } 00093 00094 //-------------------------------------------------------------------- 00095 glyph_cache* cache_glyph(unsigned glyph_code, 00096 unsigned glyph_index, 00097 unsigned data_size, 00098 glyph_data_type data_type, 00099 const rect_i& bounds, 00100 double advance_x, 00101 double advance_y) 00102 { 00103 unsigned msb = (glyph_code >> 8) & 0xFF; 00104 if(m_glyphs[msb] == 0) 00105 { 00106 m_glyphs[msb] = 00107 (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, 00108 sizeof(glyph_cache*)); 00109 memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256); 00110 } 00111 00112 unsigned lsb = glyph_code & 0xFF; 00113 if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite 00114 00115 glyph_cache* glyph = 00116 (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), 00117 sizeof(double)); 00118 00119 glyph->glyph_index = glyph_index; 00120 glyph->data = m_allocator.allocate(data_size); 00121 glyph->data_size = data_size; 00122 glyph->data_type = data_type; 00123 glyph->bounds = bounds; 00124 glyph->advance_x = advance_x; 00125 glyph->advance_y = advance_y; 00126 return m_glyphs[msb][lsb] = glyph; 00127 } 00128 00129 private: 00130 block_allocator m_allocator; 00131 glyph_cache** m_glyphs[256]; 00132 char* m_font_signature; 00133 }; 00134 00135 00136 00137 00138 00139 00140 00141 //---------------------------------------------------------font_cache_pool 00142 class font_cache_pool 00143 { 00144 public: 00145 //-------------------------------------------------------------------- 00146 ~font_cache_pool() 00147 { 00148 unsigned i; 00149 for(i = 0; i < m_num_fonts; ++i) 00150 { 00151 obj_allocator<font_cache>::deallocate(m_fonts[i]); 00152 } 00153 pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts); 00154 } 00155 00156 //-------------------------------------------------------------------- 00157 font_cache_pool(unsigned max_fonts=32) : 00158 m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)), 00159 m_max_fonts(max_fonts), 00160 m_num_fonts(0), 00161 m_cur_font(0) 00162 {} 00163 00164 00165 //-------------------------------------------------------------------- 00166 void font(const char* font_signature, bool reset_cache = false) 00167 { 00168 int idx = find_font(font_signature); 00169 if(idx >= 0) 00170 { 00171 if(reset_cache) 00172 { 00173 obj_allocator<font_cache>::deallocate(m_fonts[idx]); 00174 m_fonts[idx] = obj_allocator<font_cache>::allocate(); 00175 m_fonts[idx]->signature(font_signature); 00176 } 00177 m_cur_font = m_fonts[idx]; 00178 } 00179 else 00180 { 00181 if(m_num_fonts >= m_max_fonts) 00182 { 00183 obj_allocator<font_cache>::deallocate(m_fonts[0]); 00184 memcpy(m_fonts, 00185 m_fonts + 1, 00186 (m_max_fonts - 1) * sizeof(font_cache*)); 00187 m_num_fonts = m_max_fonts - 1; 00188 } 00189 m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate(); 00190 m_fonts[m_num_fonts]->signature(font_signature); 00191 m_cur_font = m_fonts[m_num_fonts]; 00192 ++m_num_fonts; 00193 } 00194 } 00195 00196 //-------------------------------------------------------------------- 00197 const font_cache* font() const 00198 { 00199 return m_cur_font; 00200 } 00201 00202 //-------------------------------------------------------------------- 00203 const glyph_cache* find_glyph(unsigned glyph_code) const 00204 { 00205 if(m_cur_font) return m_cur_font->find_glyph(glyph_code); 00206 return 0; 00207 } 00208 00209 //-------------------------------------------------------------------- 00210 glyph_cache* cache_glyph(unsigned glyph_code, 00211 unsigned glyph_index, 00212 unsigned data_size, 00213 glyph_data_type data_type, 00214 const rect_i& bounds, 00215 double advance_x, 00216 double advance_y) 00217 { 00218 if(m_cur_font) 00219 { 00220 return m_cur_font->cache_glyph(glyph_code, 00221 glyph_index, 00222 data_size, 00223 data_type, 00224 bounds, 00225 advance_x, 00226 advance_y); 00227 } 00228 return 0; 00229 } 00230 00231 00232 //-------------------------------------------------------------------- 00233 int find_font(const char* font_signature) 00234 { 00235 unsigned i; 00236 for(i = 0; i < m_num_fonts; i++) 00237 { 00238 if(m_fonts[i]->font_is(font_signature)) return int(i); 00239 } 00240 return -1; 00241 } 00242 00243 private: 00244 font_cache** m_fonts; 00245 unsigned m_max_fonts; 00246 unsigned m_num_fonts; 00247 font_cache* m_cur_font; 00248 }; 00249 00250 00251 00252 00253 //------------------------------------------------------------------------ 00254 enum glyph_rendering 00255 { 00256 glyph_ren_native_mono, 00257 glyph_ren_native_gray8, 00258 glyph_ren_outline, 00259 glyph_ren_agg_mono, 00260 glyph_ren_agg_gray8 00261 }; 00262 00263 00264 00265 00266 //------------------------------------------------------font_cache_manager 00267 template<class FontEngine> class font_cache_manager 00268 { 00269 public: 00270 typedef FontEngine font_engine_type; 00271 typedef font_cache_manager<FontEngine> self_type; 00272 typedef typename font_engine_type::path_adaptor_type path_adaptor_type; 00273 typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type; 00274 typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type; 00275 typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type; 00276 typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type; 00277 00278 //-------------------------------------------------------------------- 00279 font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) : 00280 m_fonts(max_fonts), 00281 m_engine(engine), 00282 m_change_stamp(-1), 00283 m_prev_glyph(0), 00284 m_last_glyph(0) 00285 {} 00286 00287 //-------------------------------------------------------------------- 00288 void reset_last_glyph() 00289 { 00290 m_prev_glyph = m_last_glyph = 0; 00291 } 00292 00293 //-------------------------------------------------------------------- 00294 const glyph_cache* glyph(unsigned glyph_code) 00295 { 00296 synchronize(); 00297 const glyph_cache* gl = m_fonts.find_glyph(glyph_code); 00298 if(gl) 00299 { 00300 m_prev_glyph = m_last_glyph; 00301 return m_last_glyph = gl; 00302 } 00303 else 00304 { 00305 if(m_engine.prepare_glyph(glyph_code)) 00306 { 00307 m_prev_glyph = m_last_glyph; 00308 m_last_glyph = m_fonts.cache_glyph(glyph_code, 00309 m_engine.glyph_index(), 00310 m_engine.data_size(), 00311 m_engine.data_type(), 00312 m_engine.bounds(), 00313 m_engine.advance_x(), 00314 m_engine.advance_y()); 00315 m_engine.write_glyph_to(m_last_glyph->data); 00316 return m_last_glyph; 00317 } 00318 } 00319 return 0; 00320 } 00321 00322 //-------------------------------------------------------------------- 00323 void init_embedded_adaptors(const glyph_cache* gl, 00324 double x, double y, 00325 double scale=1.0) 00326 { 00327 if(gl) 00328 { 00329 switch(gl->data_type) 00330 { 00331 default: return; 00332 case glyph_data_mono: 00333 m_mono_adaptor.init(gl->data, gl->data_size, x, y); 00334 break; 00335 00336 case glyph_data_gray8: 00337 m_gray8_adaptor.init(gl->data, gl->data_size, x, y); 00338 break; 00339 00340 case glyph_data_outline: 00341 m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); 00342 break; 00343 } 00344 } 00345 } 00346 00347 00348 //-------------------------------------------------------------------- 00349 path_adaptor_type& path_adaptor() { return m_path_adaptor; } 00350 gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } 00351 gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } 00352 mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } 00353 mono_scanline_type& mono_scanline() { return m_mono_scanline; } 00354 00355 //-------------------------------------------------------------------- 00356 const glyph_cache* perv_glyph() const { return m_prev_glyph; } 00357 const glyph_cache* last_glyph() const { return m_last_glyph; } 00358 00359 //-------------------------------------------------------------------- 00360 bool add_kerning(double* x, double* y) 00361 { 00362 if(m_prev_glyph && m_last_glyph) 00363 { 00364 return m_engine.add_kerning(m_prev_glyph->glyph_index, 00365 m_last_glyph->glyph_index, 00366 x, y); 00367 } 00368 return false; 00369 } 00370 00371 //-------------------------------------------------------------------- 00372 void precache(unsigned from, unsigned to) 00373 { 00374 for(; from <= to; ++from) glyph(from); 00375 } 00376 00377 //-------------------------------------------------------------------- 00378 void reset_cache() 00379 { 00380 m_fonts.font(m_engine.font_signature(), true); 00381 m_change_stamp = m_engine.change_stamp(); 00382 m_prev_glyph = m_last_glyph = 0; 00383 } 00384 00385 private: 00386 //-------------------------------------------------------------------- 00387 font_cache_manager(const self_type&); 00388 const self_type& operator = (const self_type&); 00389 00390 //-------------------------------------------------------------------- 00391 void synchronize() 00392 { 00393 if(m_change_stamp != m_engine.change_stamp()) 00394 { 00395 m_fonts.font(m_engine.font_signature()); 00396 m_change_stamp = m_engine.change_stamp(); 00397 m_prev_glyph = m_last_glyph = 0; 00398 } 00399 } 00400 00401 font_cache_pool m_fonts; 00402 font_engine_type& m_engine; 00403 int m_change_stamp; 00404 double m_dx; 00405 double m_dy; 00406 const glyph_cache* m_prev_glyph; 00407 const glyph_cache* m_last_glyph; 00408 path_adaptor_type m_path_adaptor; 00409 gray8_adaptor_type m_gray8_adaptor; 00410 gray8_scanline_type m_gray8_scanline; 00411 mono_adaptor_type m_mono_adaptor; 00412 mono_scanline_type m_mono_scanline; 00413 }; 00414 00415 } 00416 00417 #endif 00418