Mercurial > hg > octave-lyh
changeset 17278:ba865ea9c7e9
Add simple FreeType font cache in class ft_manager.
* libinterp/corefcn/txt-eng-ft.cc (ft_face_destroyed): New static function.
(ft_manager::font_destroyed): New static method.
(ft_manager::do_font_destroyed): New method.
(ft_manager::ft_key, ft_manager::ft_cache): New typedef's.
(ft_manager::cache): New member, storing weak references to loaded fonts.
(ft_manager::do_get_font): Look for font into the cache. Use fontconfig and
freetype if not found. Insert newly loaded fonts into the cache. Install
finalizer to update the cache on font destruction.
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Sun, 18 Aug 2013 16:36:41 -0400 |
parents | 5b088598df1d |
children | cb7233cfbf43 |
files | libinterp/corefcn/txt-eng-ft.cc |
diffstat | 1 files changed, 66 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/txt-eng-ft.cc +++ b/libinterp/corefcn/txt-eng-ft.cc @@ -31,6 +31,8 @@ #endif #include <iostream> +#include <map> +#include <utility> #include "singleton-cleanup.h" @@ -65,6 +67,9 @@ #include "PermMatrix.h" #endif +// Forward declaration +static void ft_face_destroyed (void* object); + class ft_manager { @@ -99,10 +104,24 @@ ? instance->do_get_font (name, weight, angle, size) : 0); } + static void font_destroyed (FT_Face face) + { + if (instance_ok ()) + instance->do_font_destroyed (face); + } + private: static ft_manager *instance; + typedef std::pair<std::string, double> ft_key; + typedef std::map<ft_key, FT_Face> ft_cache; + + // Cache the fonts loaded by freetype. This cache only contains + // weak references to the fonts, strong references are only present + // in class ft_render. + ft_cache cache; + private: // No copying! @@ -149,6 +168,18 @@ { FT_Face retval = 0; + // Look first into the font cache, then use fontconfig. If the font + // is present in the cache, simply add a reference and return it. + + ft_key key (name + ":" + weight + ":" + angle, size); + ft_cache::const_iterator it = cache.find (key); + + if (it != cache.end ()) + { + FT_Reference_Face (it->second); + return it->second; + } + std::string file; #if defined (HAVE_FONTCONFIG) @@ -221,12 +252,41 @@ #endif } - if (! file.empty () && FT_New_Face (library, file.c_str (), 0, &retval)) - ::warning ("ft_manager: unable to load font: %s", file.c_str ()); + if (! file.empty ()) + { + if (FT_New_Face (library, file.c_str (), 0, &retval)) + ::warning ("ft_manager: unable to load font: %s", file.c_str ()); + else + { + // Install a finalizer to notify ft_manager that the font is + // being destroyed. The class ft_manager only keeps weak + // references to font objects. + + retval->generic.data = new ft_key (key); + retval->generic.finalizer = ft_face_destroyed; + + // Insert loaded font into the cache. + + cache[key] = retval; + } + } return retval; } + void do_font_destroyed (FT_Face face) + { + if (face->generic.data) + { + ft_key* pkey = + reinterpret_cast<ft_key*> (face->generic.data); + + cache.erase (*pkey); + delete pkey; + face->generic.data = 0; + } + } + private: FT_Library library; bool freetype_initialized; @@ -235,6 +295,10 @@ ft_manager* ft_manager::instance = 0; +static void +ft_face_destroyed (void* object) +{ ft_manager::font_destroyed (reinterpret_cast<FT_Face> (object)); } + // --------------------------------------------------------------------------- ft_render::ft_render (void)