diff --git a/docs/design/basic-design.png b/docs/design/basic-design.png index 881e1a8de..5acdccc54 100644 Binary files a/docs/design/basic-design.png and b/docs/design/basic-design.png differ diff --git a/docs/design/design-1.html b/docs/design/design-1.html new file mode 100644 index 000000000..604fbc873 --- /dev/null +++ b/docs/design/design-1.html @@ -0,0 +1,82 @@ + +The Design of FreeType 2 - Introduction + + + + + +
+ +

The Design of FreeType 2

+ +
+

Introduction

+
+ +

This document provides details on the design and implementation + of the FreeType 2 library. Its goal is to allow developers to + better understand the way FT2 is organized, in order to let them + extend, customize and debug it.

+ +

Before anything else, it is important to understand the purpose + of this library, i.e. why it has been written:

+ +
    +
  • first of all, to allow client applications to access font files + easily, wherever they could be stored, and as independently + of font format as possible.

  • + +
  • to allow easy retrieval of global font data most commonly + found in normal font formats (i.e. global metrics, + encoding/charmaps, etc..)

  • + +
  • to allow easy retrieval of individual glyph data + (metrics, images, name, anything else)

  • + +
  • to allow access to font format-specific "features" + whenever possible (e.g. SFNT tables, Multiple Masters, + OpenType Layout tables, etc..)

  • +
+ +

its design has also severely been influenced by the following + requirements:

+ +
    +
  • high portability, as the library must be able to run + on any kind of environment. this requirement introduces a few + drastic choices that are part of FreeType 2's low-level system + interface.

  • + +
  • extendibility, as new features should be added with + the least modifications in the library's code base. this + requirements induces an extremely simple design where nearly + all operations are provided by modules. +

  • + +
  • customization, it should be easy to build a version + of the library that only contains the features needed by a + specific project. This really is important when you need to + integrate it in a font server for embedded graphics libraries.

  • + +
  • compactness and efficiency, given that the + primary target for this library is embedded systems with low + cpu and memory resources.

  • +
+ +

The rest of this document is divided in several sections. First, a + few chapters will present the library's basic design as well as the + objects/data managed internally by FreeType 2.

+ +

A later section is then dedicated to library customization, relating + such topics as system-specific interfaces, how to write your own + module and how to tailor library initialisation & compilation + to your needs.

+ +
+ + diff --git a/docs/design/design-2.html b/docs/design/design-2.html new file mode 100644 index 000000000..fba5c9887 --- /dev/null +++ b/docs/design/design-2.html @@ -0,0 +1,112 @@ + +The Design of FreeType 2 - Basic Design + + + + + +
+ +

The Design of FreeType 2

+ +
+

I. Components and APIs

+
+ +

It's better to describe FreeType 2 as a collection of + components. Each one of them is a more or less abstract + part of the library that is in charge of one specific task. We will + now explicit the connections and relationships between them.

+ +

A first brief description of this system of components could be:

+
    +
  • + client applications typically call the FreeType 2 high-level + API, whose functions are implemented in a single component + called the Base Layer. +

  • + +
  • + depending on the context or the task, the base + layer then calls one or more module components to + perform the work. In most cases, the client application doesn't + need to know what module was called. +

  • + +
  • + the base layer also contains a set of routines that are + used for generic things like memory allocation, list + processing, i/o stream parsing, fixed point computation, + etc.. these functions can also be called by a module + at any time, and they form what is called the low-level + base API. +

  • +
+ +

This is illustrated by the following graphics (note that component + entry points are represented as colored triangles):

+ +
+ +

Now, a few additional things must be added to complete this picture:

+ +
    +
  • some parts of the base layer can be replaced for specific builds + of the library, and can thus be considered as components themselves. + this is the case for the ftsystem component, which is in + charge of implementing memory management & input stream access, + as well as the ftinit, which is in charge of library + initialisation (i.e. implementing FT_Init_FreeType). +

  • + +
  • + FreeType 2 comes also with a set of optional components, + which can be used either as a convenience for client applications + (e.g. the ftglyph component, used to provide a simple API + to manage glyph images independently of their internal representation), + or to access format-specific features (e.g. the ftmm component + used to access and manage Multiple Masters data in Type 1 fonts) +

  • + +
  • + Finally, a module is capable of calling functions provided by + another module. This is very useful to share code and tables + between several font driver modules (for example, the truetype + and cff both use the routines provided by the sfnt + module). +

  • +
+ +

Hence, a more complete picture would be:

+ +
+ +

Please take note of the following important points:

+ +
    +
  • + an optional component can use either the high-level or base + API. This is the case of ftglyph in the above picture. +

  • + +
  • + some optional component can use module-specific interfaces + ignored by the base layer. In the above example, ftmm + directly accesses the Type 1 module to set/query data +

  • + +
  • + a replacable component can provide a function of the high-level + API. For example, ftinit provides FT_Init_FreeType + to client applications. +

  • +
+ +
+ + diff --git a/docs/design/design-3.html b/docs/design/design-3.html new file mode 100644 index 000000000..83900f278 --- /dev/null +++ b/docs/design/design-3.html @@ -0,0 +1,263 @@ + +The Design of FreeType 2 - Public Objects + + + + + +
+ +

The Design of FreeType 2

+ +
+

II. Public Objects and Classes

+
+ +

We will now detail the abstractions provided by FreeType 2 to + client applications to manage font files and data. As you would + normally expect, these are implemented through objects/classes.

+ +

1. Object Orientation in FreeType 2:

+ +

Though written in ANSI C, the library employs a few + techniques, inherited from object-oriented programming, to make + it easy to extend. Hence, the following conventions apply in + the FT2 source code:

+ +
    +
  1. + each object type/class has a corresponding structure type and + a corresponding structure pointer type. the latter is called the + handle type for the type/class.

    + +

    Consider that we need to manage objects of type "foo" in FT2. + We would define the following structure and handle types as + follow:

    + +
    
    +     typedef struct FT_FooRec_*    FT_Foo;
    +
    +     typedef struct FT_FooRec_
    +     {
    +       // fields for the "foo" class
    +       ...
    +
    +     } FT_FooRec;
    +  
    + +

    As a convention, handle types use simple but meaningful identifiers + beginning with "FT_", as in "FT_Foo", while structures use the same + name with a "Rec" suffix appended to it ('Rec' is short for "record"). + Note that each class type has a corresponding handle type. +

    + + +
  2. + class derivation is achieved internally by wrapping base class + structures into new ones. As an example, let's define a "foobar" + class that is derived from "foo". We would do something like:

    + +
    
    +     typedef struct FT_FooBarRec_*    FT_FooBar;
    +
    +     typedef struct FT_FooBarRec_
    +     {
    +       // the base "foo" class fields
    +       FT_FooRec     root;
    +
    +       // fields proper to the "foobar" class
    +       ...
    +
    +     } FT_FooBarRec;
    +  
    + +

    As you can see, we ensure that a "foobar" object is also a "foo" + object by placing a FT_FooRec at the start of the + FT_FooBarRec definition. It is called root + by convention.

    + +

    Note that a FT_FooBar handle also points to a "foo" object + and can be typecasted to FT_Foo. Similarly, when the + library handles a FT_Foo handle to client applications, + the object can be really implemented as a FT_FooBar or any + derived class from "foo".

    + +

  3. + + +

    Note that in the following sections of this chapter, we will refer + to "the FT_Foo class" to indicate the type of objects + handled through FT_Foo pointers, be they implemented as + "foo" or "foobar".

    + +
    + +

    2. The FT_Library class:

    + +

    This type corresponds to a handle to a single instance of the + library. Note that the corresponding structure FT_LibraryRec + is not defined in public header files, making client applications + unable to access its internal fields.

    + +

    The library object is the "parent" of all other objects in FreeType 2. + You need to create a new library instance before doing anything else + with the library. Similarly, destroying it will automatically + destroy all its children (i.e. faces and modules).

    + +

    Typical client applications should call FT_Init_FreeType, + in order to create a new library object, ready to be used for + further action.

    + +

    Another alternative is to create a fresh new library instance + by calling the function FT_New_Library, defined in the + <freetype/ftmodule.h> public header file. This + function will however return an "empty" library instance with + no module registered in it. You can "install" modules in the + instance by calling FT_Add_Module manually.

    + +

    Calling FT_Init_FreeType is a lot more convenient, because + this function basically registers a set of default modules into + each new library instance. The way this list is accessed and/or + computed is determined at build time, and depends on the content + of the ftinit component. This process is explained in + details later in this document.

    + +

    For now, one should consider that library objects are created + with FT_Init_FreeType, and destroyed along with all + children with FT_Done_FreeType.

    +
    + +

    3. The FT_Face class:

    + +

    A face object corresponds to a single font face, i.e. + a specific typeface with a specific style. For example, "Arial" + and "Arial Italic" correspond to two distinct faces.

    + +

    A face object is normally created through FT_New_Face. + This function takes the following parameters: a FT_Library + handle, a C file pathname used to indicate which font file to + open, an index used to decide which face to load from the file + (a single file may contain several faces in certain cases), + as well as the address of a FT_Face handle. It returns + an error code:

    + +
    
    +  FT_Error  FT_New_Face( FT_Library   library,
    +                         const char*  filepathname,
    +                         FT_Long      face_index,
    +                         FT_Face     *face );
    +
    + +

    in case of success, the function will return 0, and the handle + pointed to by the "face" parameter will be set to a non-NULL value.

    + +

    Note that the face object contains several fields used to + describe global font data that can be accessed directly by + client applications. For example, the total number of glyphs + in the face, the face's family name, style name, the EM size + for scalable formats, etc.. For more details, look at the + FT_FaceRec definition in the FT2 API Reference.

    + +
    + +

    4. The FT_Size class:

    + +

    Each FT_Face object has one or more FT_Size + objects. A size object is used to store data specific to a + given character width and height. Each newly created face object + has one size, which is directly accessible as face->size.

    + +

    The content of a size object can be changed by calling either + FT_Set_Pixel_Sizes or FT_Set_Char_Size.

    + +

    A new size object can be created with FT_New_Size, and + destroyed manually with FT_Done_Size. Note that typical + applications don't need to do this normally: they tend to use + the default size object provided with each FT_Face.

    + +

    The public fields of FT_Size objects are defined in + a very small structure named FT_SizeRec. However, it is + important to understand that some font drivers define their own + derivatives of FT_Size to store important internal data + that is re-computed each time the character size changes. Most of + the time, these are size-specific font hints./p> + +

    For example, the TrueType driver stores the scaled CVT table that + results from the execution of the "cvt" program in a TT_Size, + while the Type 1 driver stores scaled global metrics (like blue zones) + in a T1_Size object. Don't worry if you don't understand + the current paragraph, most of this stuff is highly font format + specific and doesn't need to be explained to client developers :-)

    + +
    + +

    5. The FT_GlyphSlot class:

    + +

    The purpose of a glyph slot is to provide a place where glyph + images can be loaded one by one easily, independently of the + glyph image format (bitmap, vector outline, or anything else).

    + +

    Ideally, once a glyph slot is created, any glyph image can + be loaded into it without additional memory allocation. In practice, + this is only possible with certain formats like TrueType which + explicitely provide data to compute a slot's maximum size.

    + +

    Another reason for glyph slots is that they're also used to hold + format-specific hints for a given glyphs has well as all other + data necessary to correctly load the glyph.

    + +

    The base FT_GlyphSlotRec structure only presents glyph + metrics and images to client applications, while actual implementation + may contain more sophisticated data.

    + +

    As an example, the TrueType-specific TT_GlyphSlotRec + structure contains additional fields to hold glyph-specific bytecode, + transient outlines used during the hinting process, and a few other + things. + + the Type1-specific T1_GlyphSlotRec structure holds + glyph hints during glyph loading, as well as additional logic used + to properly hint the glyphs when a native T1 hinter is used.

    + +

    Finally, each face object has a single glyph slot, that is directly + accessible as face->glyph.

    + +
    + +

    6. The FT_CharMap class:

    + +

    Finally, the FT_CharMap type is used as a handle to + character map objects, or "charmaps" to be brief. A charmap is + simply some sort of table or dictionary which is used to translate + character codes in a given encoding into glyph indices for the + font.

    + +

    A single face may contain several charmaps. Each one of them + corresponds to a given character repertoire, like Unicode, Apple Roman, + Windows codepages, and other ugly "standards".

    + +

    Each FT_CharMap object contains a "platform" and an "encoding" + field used to identify precisely the character repertoire corresponding + to it.

    + +

    Each font format provides its own derivative of FT_CharMapRec + and thus needs to implement these objects.

    + +
    +

    7. Objects relationships:

    + +

    The following diagram summarizes what we just said regarding the + public objects managed by the library, as well as explicitely + describes their relationships:

    + +

    Note that this picture will be updated at the end of the next + chapter, related to internal objects.

    + +
+ + diff --git a/docs/design/design-4.html b/docs/design/design-4.html new file mode 100644 index 000000000..0a0c63338 --- /dev/null +++ b/docs/design/design-4.html @@ -0,0 +1,289 @@ + +The Design of FreeType 2 - Internal Objects + + + + + +
+ +

The Design of FreeType 2

+ +
+

III. Internal Objects and Classes

+
+ +

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:

+ +
    +
  1. + create a new FT_Memory object by hand. The definition of + FT_MemoryRec is located in the public file + <freetype/ftsystem.h>. +

  2. + +
  3. + call FT_New_Library to create a new library instance using + your custom memory manager. This new library is "virgin" and doesn't + contain any registered modules. +

  4. + +
  5. + Register the set of default modules by calling the function + FT_Add_Default_Modules provided by the ftinit + component, or manually register your drivers by repeatedly + calling FT_Add_Module. +

  6. +
+ + +
+

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:

+ +
    +
  • + it will check if the library already holds a module object corresponding + to the same module name as the one found in the FT_Module_Class. +

  • + +
  • + it this is the case, it will compare the module version number to see + if it is possible to upgrade the module to a new version. If + the module class's version number is smaller than the already + installed one, the function returns immediately. Similarly, it checks + that the version of FreeType 2 that is running is correct compared + to the one required by the module. +

  • + +
  • + it creates a new FT_Module object, using data and flags + of the module class to determine its byte size and how to properly + initialize it. +

  • + +
  • + when a module initializer is present in the module class, it will + be called to complete the module object's initialisation. +

  • + +
  • + the new module is added to the library's list of "registered" + modules. In case of an upgrade, the previous module object is + simply destroyed. +

  • + +
+ +

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:

+ +
    +
  • + renderer modules are used to convert native glyph images to + bitmaps/pixmaps. FT2 comes with two renderer modules + by default: one to generate monochrome bitmaps, the other to generate + high-quality anti-aliased pixmaps. +

  • + +
  • + font driver modules are used to support one or more specific + font format. Typically, each font driver provides a specific + implementation/derivative of FT_Face, FT_Size, + FT_GlyphSlot as well as FT_CharMap. +

  • + +
  • + helper modules are used to contain code that is shared + by several font drivers. For example, the sfnt module is + used to parse and manage tables found in SFNT-based font formats; + it is then used by both the TrueType and OpenType font drivers. +

  • + +
  • + finally, the auto-hinter module has a specific place in + the library's design, as its role is to process vectorial glyph + outlines, independently of their native font format, to produce + optimal results at small pixel sizes.. +

  • +
+ +

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:

+ +
    +
  • + a memory manager object (FT_Memory), used for all + allocation/releases within the instance. +

  • + +
  • + a list of FT_Module objects, corresponding to the + "installed" or "registered" modules of the instance. This + list can be changed at any time through FT_Add_Module + and FT_Remove_Module. +

  • + +
  • + finally, remember that face objects are owner by font drivers + that are themselves modules owned by the library. +

  • +
+ +

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. Summary

+ +

Finally, 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:

+ +
+ +
+ + diff --git a/docs/design/detailed-design.png b/docs/design/detailed-design.png index 174c1a967..d27f761a1 100644 Binary files a/docs/design/detailed-design.png and b/docs/design/detailed-design.png differ