The Design of FreeType 2
Let's have a look now at the internal objects that FreeType 2 uses, i.e. those not directly available to client applications, and let's see how they fit in the picture. 1. Memory management:All memory management operations are performed through three specific routines of the base layer, namely: FT_Alloc, FT_Realloc, and FT_Free. Each one of these functions expects a FT_Memory handle as its first parameter. The latter is a pointer to a simple object used to describe the current memory pool/manager to use. It contains a simple table of alloc/realloc/free functions. A memory manager is created at library initialisation time by FT_Init_FreeType by calling the function FT_New_Memory provided by the ftsystem component. By default, this manager uses the ANSI malloc, realloc and free functions. However, as ftsystem is a replaceable part of the base layer, a specific build of the library could provide a different default memory manager. Even with a default build, client applications are still able to provide their own memory manager by not calling FT_Init_FreeType but follow these simple steps:
2. Input streams:Font files are always read through FT_Stream objects. The definition of FT_StreamRec is located in the public file <freetype/ftsystem.h>, which allows client developers to provide their own implementation of streams if they wish so. The function FT_New_Face will always automatically create a new stream object from the C pathname given as its second argument. This is achieved by calling the function FT_New_Stream provided by the ftsystem component. As the latter is replaceable, the implementation of streams may vary greatly between platforms. As an example, the default implementation of streams is located in the file "src/base/ftsystem.c" and uses the ANSI fopen, fseek, fread calls. However, the Unix build of FreeType 2 provides an alternative implementation that uses memory-mapped files, when available on the host platform, resulting in a significant access speed-up. FreeType distinguishes between memory-based and disk-based streams. In the first case, all data is directly accessed in memory (e.g. ROM-based, write-only static data and memory-mapped files), while in the second, portions of the font files are read in chunks called "frames", and temorarily buffered adequately through typical seek/read operations. The FreeType stream sub-system also implements extremely efficient algorithms to very quickly load structures from font files while ensure complete safety in the case of "broken file". The function FT_New_Memory_Face can be used to directly create/open a FT_Face object from data that is readily available in memory (including ROM-based fonts). Finally, in the case where a custom input stream is needed, client applications can use the function FT_Open_Face, which can accept custom input streams.. This may be useful in the case of compressed or remote font files, or even embedded font files that need to be extracted from certain documents. Note that each face owns a single stream, which is also destroyed by FT_Done_Face. Generally speaking, it's certainly not a good idea to keep numerous FT_Face objects opened. 3. Modules:A FreeType 2 module is itself a piece of code. However, the library creates a single FT_Module object for each module that is registered when FT_Add_Module is called. The definition of FT_ModuleRec is not publicly available to client applications. However, each module type is described by a simple and public structure named FT_Module_Class, defined in <freetype/ftmodule.h>, and is detailed heavily later in this document: You need a pointer to a FT_Module_Class structure when calling FT_Add_Module, whose declaration is: FT_Error FT_Add_Module( FT_Library library, const FT_Module_Class* clazz ); Calling this function will do the following:
Note that this function doesn't return a FT_Module handle, given that module objects are completely internal to the library (and client applications shouldn't normally mess with them :-) Finally, it's important to understand that FreeType 2 recognizes and manages several kinds of modules. These will be explained in more details later in this document, but we'll list for now the following types:
Note that every FT_Face object is owned by the corresponding font driver (that depends on the original font file's format). This means that all face objects are destroyed when a module is removed/unregistered from a library instance (typically by calling FT_Remove_Module). Because of this, you should always take care that no FT_Face object is opened when you upgrade or remove a module from a library, as this could cause unexpected object deletion !! 4. Libraries:And we now come back to our well-known FT_Library objects. From what have been said here, we already know that a library instance owns at least the following:
There is however another object owned by the library instance that hasn't been described until now, and it's the raster pool. The raster pool is simply a block of memory of fixed size that is used internally as a "scratch area" for various memory-hungry transient operations. For example, it is used by each renderer when converting a vectorial glyph outline into a bitmap (actually, that's where its name comes from :-). The advantage of using a raster pool comes from the fact that it allows us to completely avoid memory allocation during certain memory-intensive though common transient operations (like glyph bitmap generation), speeding up the overall process. The size of the raster pool is fixed at initialisation time (it defaults to 16 Kb) and cannot be changed at run-time (though we could fix this if there's a real need for that). When a transient operation needs more memory than the pool's size, it can decide to either allocate a heap block as an exceptional condition, or sub-divide recursively the task to perform in order to never exceed the pool's threshold.. This extremely memory-conservative behaviour is certainly one of the keys to FreeType's performance in certain areas (most importantly in glyph rendering / scanline-conversion ). 5. SummaryFinally, the following picture illustrates what has been said in this section, as well as the previous, by presenting the complete object graph of FreeType 2's base design: |