summaryrefslogtreecommitdiff
path: root/agg/inc/agg_font_cache_manager.h
diff options
context:
space:
mode:
Diffstat (limited to 'agg/inc/agg_font_cache_manager.h')
-rwxr-xr-xagg/inc/agg_font_cache_manager.h397
1 files changed, 397 insertions, 0 deletions
diff --git a/agg/inc/agg_font_cache_manager.h b/agg/inc/agg_font_cache_manager.h
new file mode 100755
index 000000000000..55c4d39db75d
--- /dev/null
+++ b/agg/inc/agg_font_cache_manager.h
@@ -0,0 +1,397 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.3
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+
+#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
+#define AGG_FONT_CACHE_MANAGER_INCLUDED
+
+#include <string.h>
+#include "agg_array.h"
+
+namespace agg
+{
+
+ //---------------------------------------------------------glyph_data_type
+ enum glyph_data_type
+ {
+ glyph_data_invalid = 0,
+ glyph_data_mono = 1,
+ glyph_data_gray8 = 2,
+ glyph_data_outline = 3
+ };
+
+
+ //-------------------------------------------------------------glyph_cache
+ struct glyph_cache
+ {
+ unsigned glyph_index;
+ int8u* data;
+ unsigned data_size;
+ glyph_data_type data_type;
+ rect bounds;
+ double advance_x;
+ double advance_y;
+ };
+
+
+ //--------------------------------------------------------------font_cache
+ class font_cache
+ {
+ public:
+ enum { block_size = 16384-16 };
+
+ //--------------------------------------------------------------------
+ font_cache(const char* font_signature) :
+ m_allocator(block_size),
+ m_font_signature(0)
+ {
+ m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
+ strcpy(m_font_signature, font_signature);
+ memset(m_glyphs, 0, sizeof(m_glyphs));
+ }
+
+ //--------------------------------------------------------------------
+ bool font_is(const char* font_signature) const
+ {
+ return strcmp(font_signature, m_font_signature) == 0;
+ }
+
+ //--------------------------------------------------------------------
+ const glyph_cache* find_glyph(unsigned glyph_code) const
+ {
+ unsigned msb = (glyph_code >> 8) & 0xFF;
+ if(m_glyphs[msb])
+ {
+ return m_glyphs[msb][glyph_code & 0xFF];
+ }
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ glyph_cache* cache_glyph(unsigned glyph_code,
+ unsigned glyph_index,
+ unsigned data_size,
+ glyph_data_type data_type,
+ const rect& bounds,
+ double advance_x,
+ double advance_y)
+ {
+ unsigned msb = (glyph_code >> 8) & 0xFF;
+ if(m_glyphs[msb] == 0)
+ {
+ m_glyphs[msb] =
+ (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
+ sizeof(glyph_cache*));
+ memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
+ }
+
+ unsigned lsb = glyph_code & 0xFF;
+ if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
+
+ glyph_cache* glyph =
+ (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
+ sizeof(double));
+
+ glyph->glyph_index = glyph_index;
+ glyph->data = m_allocator.allocate(data_size);
+ glyph->data_size = data_size;
+ glyph->data_type = data_type;
+ glyph->bounds = bounds;
+ glyph->advance_x = advance_x;
+ glyph->advance_y = advance_y;
+ return m_glyphs[msb][lsb] = glyph;
+ }
+
+ private:
+ pod_allocator m_allocator;
+ glyph_cache** m_glyphs[256];
+ char* m_font_signature;
+ };
+
+
+
+
+
+
+
+ //---------------------------------------------------------font_cache_pool
+ class font_cache_pool
+ {
+ public:
+ //--------------------------------------------------------------------
+ ~font_cache_pool()
+ {
+ unsigned i;
+ for(i = 0; i < m_num_fonts; ++i)
+ {
+ delete m_fonts[i];
+ }
+ delete [] m_fonts;
+ }
+
+ //--------------------------------------------------------------------
+ font_cache_pool(unsigned max_fonts=32) :
+ m_fonts(new font_cache* [max_fonts]),
+ m_max_fonts(max_fonts),
+ m_num_fonts(0),
+ m_cur_font(0)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void font(const char* font_signature, bool reset_cache = false)
+ {
+ int idx = find_font(font_signature);
+ if(idx >= 0)
+ {
+ if(reset_cache)
+ {
+ delete m_fonts[idx];
+ m_fonts[idx] = new font_cache(font_signature);
+ }
+ m_cur_font = m_fonts[idx];
+ }
+ else
+ {
+ if(m_num_fonts >= m_max_fonts)
+ {
+ delete m_fonts[0];
+ memcpy(m_fonts,
+ m_fonts + 1,
+ (m_max_fonts - 1) * sizeof(font_cache*));
+ m_num_fonts = m_max_fonts - 1;
+ }
+ m_fonts[m_num_fonts] = new font_cache(font_signature);
+ m_cur_font = m_fonts[m_num_fonts];
+ ++m_num_fonts;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ const font_cache* font() const
+ {
+ return m_cur_font;
+ }
+
+ //--------------------------------------------------------------------
+ const glyph_cache* find_glyph(unsigned glyph_code) const
+ {
+ if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ glyph_cache* cache_glyph(unsigned glyph_code,
+ unsigned glyph_index,
+ unsigned data_size,
+ glyph_data_type data_type,
+ const rect& bounds,
+ double advance_x,
+ double advance_y)
+ {
+ if(m_cur_font)
+ {
+ return m_cur_font->cache_glyph(glyph_code,
+ glyph_index,
+ data_size,
+ data_type,
+ bounds,
+ advance_x,
+ advance_y);
+ }
+ return 0;
+ }
+
+
+ //--------------------------------------------------------------------
+ int find_font(const char* font_signature)
+ {
+ unsigned i;
+ for(i = 0; i < m_num_fonts; i++)
+ {
+ if(m_fonts[i]->font_is(font_signature)) return int(i);
+ }
+ return -1;
+ }
+
+ private:
+ font_cache** m_fonts;
+ unsigned m_max_fonts;
+ unsigned m_num_fonts;
+ font_cache* m_cur_font;
+ };
+
+
+
+
+ //------------------------------------------------------------------------
+ enum glyph_rendering
+ {
+ glyph_ren_native_mono,
+ glyph_ren_native_gray8,
+ glyph_ren_outline,
+ glyph_ren_agg_mono,
+ glyph_ren_agg_gray8
+ };
+
+
+
+
+ //------------------------------------------------------font_cache_manager
+ template<class FontEngine> class font_cache_manager
+ {
+ public:
+ typedef FontEngine font_engine_type;
+ typedef font_cache_manager<FontEngine> self_type;
+ typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
+ typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
+ typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
+ typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
+ typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
+
+ //--------------------------------------------------------------------
+ font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
+ m_fonts(max_fonts),
+ m_engine(engine),
+ m_change_stamp(-1),
+ m_prev_glyph(0),
+ m_last_glyph(0)
+ {}
+
+ //--------------------------------------------------------------------
+ const glyph_cache* glyph(unsigned glyph_code)
+ {
+ synchronize();
+ const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
+ if(gl)
+ {
+ m_prev_glyph = m_last_glyph;
+ return m_last_glyph = gl;
+ }
+ else
+ {
+ if(m_engine.prepare_glyph(glyph_code))
+ {
+ m_prev_glyph = m_last_glyph;
+ m_last_glyph = m_fonts.cache_glyph(glyph_code,
+ m_engine.glyph_index(),
+ m_engine.data_size(),
+ m_engine.data_type(),
+ m_engine.bounds(),
+ m_engine.advance_x(),
+ m_engine.advance_y());
+ m_engine.write_glyph_to(m_last_glyph->data);
+ return m_last_glyph;
+ }
+ }
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ void init_embedded_adaptors(const glyph_cache* gl,
+ double x, double y,
+ double scale=1.0)
+ {
+ if(gl)
+ {
+ switch(gl->data_type)
+ {
+ default: return;
+ case glyph_data_mono:
+ m_mono_adaptor.init(gl->data, gl->data_size, x, y);
+ break;
+
+ case glyph_data_gray8:
+ m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
+ break;
+
+ case glyph_data_outline:
+ m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
+ break;
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ path_adaptor_type& path_adaptor() { return m_path_adaptor; }
+ gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
+ gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
+ mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
+ mono_scanline_type& mono_scanline() { return m_mono_scanline; }
+
+ //--------------------------------------------------------------------
+ const glyph_cache* perv_glyph() const { return m_prev_glyph; }
+ const glyph_cache* last_glyph() const { return m_last_glyph; }
+
+ //--------------------------------------------------------------------
+ bool add_kerning(double* x, double* y)
+ {
+ if(m_prev_glyph && m_last_glyph)
+ {
+ return m_engine.add_kerning(m_prev_glyph->glyph_index,
+ m_last_glyph->glyph_index,
+ x, y);
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ void precache(unsigned from, unsigned to)
+ {
+ for(; from <= to; ++from) glyph(from);
+ }
+
+ //--------------------------------------------------------------------
+ void reset_cache()
+ {
+ m_fonts.font(m_engine.font_signature(), true);
+ m_change_stamp = m_engine.change_stamp();
+ m_prev_glyph = m_last_glyph = 0;
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ font_cache_manager(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ //--------------------------------------------------------------------
+ void synchronize()
+ {
+ if(m_change_stamp != m_engine.change_stamp())
+ {
+ m_fonts.font(m_engine.font_signature());
+ m_change_stamp = m_engine.change_stamp();
+ m_prev_glyph = m_last_glyph = 0;
+ }
+ }
+
+ font_cache_pool m_fonts;
+ font_engine_type& m_engine;
+ int m_change_stamp;
+ double m_dx;
+ double m_dy;
+ const glyph_cache* m_prev_glyph;
+ const glyph_cache* m_last_glyph;
+ path_adaptor_type m_path_adaptor;
+ gray8_adaptor_type m_gray8_adaptor;
+ gray8_scanline_type m_gray8_scanline;
+ mono_adaptor_type m_mono_adaptor;
+ mono_scanline_type m_mono_scanline;
+ };
+
+}
+
+#endif
+