From 0fc54d0078a9c32a155e3c962a25d2bf19f88bb4 Mon Sep 17 00:00:00 2001 From: David Turner Date: Thu, 23 Nov 2000 03:01:07 +0000 Subject: [PATCH] adding cache manager documentation (draft) --- docs/cache/cache.txt | 267 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 docs/cache/cache.txt diff --git a/docs/cache/cache.txt b/docs/cache/cache.txt new file mode 100644 index 000000000..4c51948c6 --- /dev/null +++ b/docs/cache/cache.txt @@ -0,0 +1,267 @@ + The FreeType 2 cache sub-system explained + (c) 2000 David Turner + + ----------------------------------------------- + +Introduction : +-------------- + + this document describes the caching sub-system that comes + with the FreeType library, version 2.0. Note that unlike + the rest of the library, this code is still in beta stage + and might still suffer slight changes in the future. + + Its basic design shouldn't evolve though and is explained + in this paper. + + +I. Requirements and Design Goals: +--------------------------------- + + The FT2 cache sub-system was designed to implement caching + of glyph images. However, it is extremely flexible and can + be easily extended to cache other kind of data like metrics, + character maps, coverage tables, etc.. + + +II. Base Concepts: +------------------ + + 1. The cache manager object: + + at the heart of the caching sub-system is a single object + called the "cache manager". It is used to deal with FT_Face + and FT_Size objects, as well as to manager a LRU list of + abstract "cache nodes". + + a. caching FT_Face and FT_Size objects: + + each FT_Face object created by FreeType 2 can take from + a few hundred bytes to several tens of kilobytes, depending + on the original font's file format as well as its content. + + there is no easy way to compute the size of a given FT_Face + object, so it's always a good idea to assume that it is + large and to want to limit the number of live face objects + as much as possible. + + similarly, each FT_Face can have one or more FT_Size childs, + whose byte size depends heavily on the font format. + + the first purpose of the cache manager is to provide a + small cache for FT_Face and FT_Size objects. Basically, + an application can use it as follows: + + - each font face is described to the cache manager + through a typeless pointer, called a FTC_FaceID. + + the cache manager itself doesn't interpret or use + the value of FTC_FaceIDs directly. Rather, it passes + them to a user-provided function called a + "face requester". see the defintion of the + FTC_Face_Requester type in + for details.. + + the face requester is in charge of translating a given + face into into a real new FT_Face object that is + returned to the cache manager. The latter will keep + the face object alive as long as it needs to. + + the face requester is unique and must be passed + to the function named FTC_Manager_New used to + create/initialise a new cache manager. + + + - to lookup a given FT_Face, call the function + FTC_Manager_Lookup_Face as in the following code: + + FTC_Manager_Lookup_Face( manager, + face_id, + &face ); + + if the corresponding FT_Face object is kept in + the cache manager's list, it will be returned + directly. Otherwise, this function will call + the user-provided face requester to create + a new FT_Face object, add it to the manager's + list to finally return it. + + FT_Face objects are always destroyed by the cache + manager. An application that uses the cache + sub-system should never call FT_Done_Face !! + + - to lookup a given FT_Size and FT_Face, call the + function FTC_Manager_Lookup_Size, as in: + + FTC_Manager_Lookup_Size( manager, + ftc_font, + &face, + &size ); + + where "ftc_font" is a pointer to a FTC_Font descriptor + (a structure containing a FTC_FaceIDs and character + dimensions corresponding to the desired FT_Size). + + note that the function returns both a FT_Face and + a FT_Size object. You don't need to call + FTC_Manager_Lookup_Face before it !! + + also note that returned FT_Size objects are always + destroyed by the cache manager. A client application + that uses it should never call FT_Done_Size !! + + + the big advantage of using FTC_FaceIDs is that is + makes the caching sub-system completely independent + of the way font files are installed / listed / managed + in your application. In most implementations, a FTC_FaceID + is really a pointer to an application-specific structure + that describe the source font file + face index. + + + b - manage a MRU list of abstract "cache nodes": + + the second role of the cache manager is to hold and manager + a list of abstract "cache nodes". The list is always sorted + in most-recently-used order. The manager always ensure that + the total size of nodes in memory doesn't over-reach a + certain threshold, by eliminating "old" nodes when + necessary. + + the cache manager doesn't know much about the cache nodes: + + - it knows how to move them in its list + - it knows how to destroy them when they're too old + - it knows how to "size" them (i.e. compute their byte + size in memory) + + + 2. Cache objects: + + the cache manager doesn't create new cache nodes however, this + is the charge of what are called "cache objects". + + Basically, each cache object is in charge of managing cache + nodes of a certain type. Its role is to: + + - provide a simple description of its cache nodes to the + manager (i.e. through a FTC_CacheNode_Class structure) + + - provide a high-level API that can be called by client + applications to lookup cache nodes of the corresponding + type. + + this function usually creates new nodes when they're not + available yet. + + - also, and even though this is completely transparent to + the applications and the cache manager, each cache object + manages "node sets", where each set contains cache nodes + usually correspond to the same font face + font size. + + + For example, the cache sub-system currently comes with two + distinct cache classes: + + - a FTC_Image_Cache, which is used to cache FT_Glyph images + (with one FT_Glyph per cache node). + + + - a FTC_SBit_Cache, which is used to cache small glyph bitmaps + ("sbit" means "embedded bitmaps" in digital typography). + + + the small bitmaps glyph is useful because storing one glyph + image per cache node isn't memory efficient when the data + associated to each node is very small. Indeed, each cache + node has a minimal size of 20 bytes, which is huge when + your data is an 8x8 monochrome bitmap :-) + + Hence, a FTC_SBit_Cache is capable of storing several + contiguous sbits in a single cache node, resulting in much + higher cached glyphs / total cache size. + + an application can lookup a FT_Glyph image with a FTC_Image_Cache + by calling: + + error = FTC_Image_Cache_Lookup( image_cache, + ftc_font, + glyph_index, + &ft_glyph ); + + or a FTC_SBit (small bitmap descriptor) by calling: + + error = FTC_SBit_Cache_Lookup( sbit_cache, + ftc_font, + glyph_index, + &ftc_sbit ); + +III. Extending the cache sub-system: + + It is possible to extend the current cache sub-system by + providing your own cache class and register it in the cache + manager. That might be useful to cache other kind of data + in the sub-system, like glyph metrics (without images), + + To do it, you'll need to read the cache sub-system public + header files rather heavily :-) Fortunately, they're pretty + well commented and should guide you to your goal. + + Note that the cache sub-system already provides two "abstract + cache" classes that can be re-used by your own implementation: + + + 1. The abstract "FTC_GlyphCache" class: + + this code is used to implement an abstract "glyph cache", + i.e. one that simply maps one glyph data per cache node. + + it is sub-classed by FTC_Image_Cache, whose implementation + only consists in simple code to store a FT_Glyph in each + cache node. + + you could sub-class it in your application to store glyph + images in a different format, for example. + + see the files and + "src/cache/ftcglyph.h" for details. + + + 2. The abstract "FTC_ChunkCache" class: + + this code is used to implement an abstract "glyph chunk cache". + it's very similar to a FTC_GlyphCache, except that it is capable + of storing several glyph-specific elements per cache node. + + it is sub-classed by FTC_SBit_Cache, whose implementation + only consists in code to store a FTC_SBitRec record in each + node element. + + you could sub-class it in your application to store small + glyph data, like metrics, glyph names, wathever. + + see the files and + "src/cache/ftcchunk.h" for details.. + + + Note that the two abstract caches are rather complex because + they use "glyph sets". Each glyph set corresponds to a single + font face + font size combination. both caches are also + glyph-specific, though it is perfectly possible to use + broader selection criterion, here are a few examples: + + - caching language coverage maps corresponding to + a given font face + language combination + + - caching charmaps, layout tables, and other global + data.. + + - caching (font_face + font_size) specific "latin1" + ascender + descender + + + as you can see, a lot is possible with this design :-) + + + +