Commit 0fc54d0078a9c32a155e3c962a25d2bf19f88bb4

David Turner 2000-11-23T03:01:07

adding cache manager documentation (draft)

diff --git a/docs/cache/cache.txt b/docs/cache/cache.txt
new file mode 100644
index 0000000..4c51948
--- /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 <freetype/ftcache.h>
+         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 <freetype/cache/ftcglyph.h> 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 <freetype/cache/ftcchunk.h> 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 :-)
+
+
+
+