290 lines
11 KiB
HTML
290 lines
11 KiB
HTML
|
<html>
|
||
|
<head><title>The Design of FreeType 2 - Internal Objects</title>
|
||
|
<basefont face="Georgia, Arial, Helvetica, Geneva">
|
||
|
<style content="text/css">
|
||
|
P { text-align=justify }
|
||
|
H1 { text-align=center }
|
||
|
H2 { text-align=center }
|
||
|
LI { text-align=justify }
|
||
|
</style>
|
||
|
</head>
|
||
|
<body text=#000000 bgcolor=#ffffff>
|
||
|
|
||
|
<center><table width="500"><tr><td>
|
||
|
|
||
|
<center><h1>The Design of FreeType 2</h1></center>
|
||
|
|
||
|
<table width="100%" cellpadding=5><tr bgcolor="#ccccee"><td>
|
||
|
<h1>III. Internal Objects and Classes</h1>
|
||
|
</td></tr></table>
|
||
|
|
||
|
<p>Let's have a look now at the <em>internal</em> objects that FreeType 2
|
||
|
uses, i.e. those not directly available to client applications, and
|
||
|
let's see how they fit in the picture.</p>
|
||
|
|
||
|
<h2>1. Memory management:</h2>
|
||
|
|
||
|
<p>All memory management operations are performed through three specific
|
||
|
routines of the base layer, namely: <tt>FT_Alloc</tt>, <tt>FT_Realloc</tt>,
|
||
|
and <tt>FT_Free</tt>. Each one of these functions expects a
|
||
|
<tt>FT_Memory</tt> handle as its first parameter.</p>
|
||
|
|
||
|
<p>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 <tt>FT_Init_FreeType</tt> by calling
|
||
|
the function <tt>FT_New_Memory</tt> provided by the <b>ftsystem</b>
|
||
|
component.</p>
|
||
|
|
||
|
<p>By default, this manager uses the ANSI <tt>malloc</tt>, <tt>realloc</tt>
|
||
|
and <tt>free</tt> functions. However, as <b>ftsystem</b> is a replaceable
|
||
|
part of the base layer, a specific build of the library could provide
|
||
|
a different default memory manager.</p>
|
||
|
|
||
|
<p>Even with a default build, client applications are still able to provide
|
||
|
their own memory manager by not calling <tt>FT_Init_FreeType</tt> but
|
||
|
follow these simple steps:</p>
|
||
|
|
||
|
<ol>
|
||
|
<li><p>
|
||
|
create a new <tt>FT_Memory</tt> object by hand. The definition of
|
||
|
<tt>FT_MemoryRec</tt> is located in the public file
|
||
|
<tt><freetype/ftsystem.h></tt>.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
call <tt>FT_New_Library</tt> to create a new library instance using
|
||
|
your custom memory manager. This new library is "virgin" and doesn't
|
||
|
contain any registered modules.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
Register the set of default modules by calling the function
|
||
|
<tt>FT_Add_Default_Modules</tt> provided by the <b>ftinit</b>
|
||
|
component, or manually register your drivers by repeatedly
|
||
|
calling <tt>FT_Add_Module</tt>.
|
||
|
</p></li>
|
||
|
</ol>
|
||
|
|
||
|
|
||
|
<hr>
|
||
|
<h2>2. Input streams:</h2>
|
||
|
|
||
|
<p>Font files are always read through <tt>FT_Stream</tt> objects. The
|
||
|
definition of <tt>FT_StreamRec</tt> is located in the public file
|
||
|
<tt><freetype/ftsystem.h></tt>, which allows client developers
|
||
|
to provide their own implementation of streams if they wish so.</p>
|
||
|
|
||
|
<p>The function <tt>FT_New_Face</tt> will always automatically create a
|
||
|
new stream object from the C pathname given as its second argument.
|
||
|
This is achieved by calling the function <tt>FT_New_Stream</tt> provided
|
||
|
by the <b>ftsystem</b> component. As the latter is replaceable,
|
||
|
the implementation of streams may vary greatly between platforms.</p>
|
||
|
|
||
|
<p>As an example, the default implementation of streams is located in
|
||
|
the file "<tt>src/base/ftsystem.c</tt>" and uses the ANSI <tt>fopen</tt>,
|
||
|
<tt>fseek</tt>, <tt>fread</tt> 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.</p>
|
||
|
|
||
|
<p>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.</p>
|
||
|
|
||
|
<p>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".</p>
|
||
|
|
||
|
<p>The function <tt>FT_New_Memory_Face</tt> can be used
|
||
|
to directly create/open a <tt>FT_Face</tt> object from data that is
|
||
|
readily available in memory (including ROM-based fonts).</p>
|
||
|
|
||
|
<p>Finally, in the case where a custom input stream is needed, client
|
||
|
applications can use the function <tt>FT_Open_Face</tt>, 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.</p>
|
||
|
|
||
|
<p>Note that each face owns a single stream, which is also destroyed
|
||
|
by <tt>FT_Done_Face</tt>. Generally speaking, it's certainly
|
||
|
<em>not a good idea</em> to keep numerous <tt>FT_Face</tt> objects
|
||
|
opened.</p>
|
||
|
|
||
|
<hr>
|
||
|
<h2>3. Modules:</h2>
|
||
|
|
||
|
<p>A FreeType 2 module is itself a piece of code. However, the library
|
||
|
creates a single <tt>FT_Module</tt> object for each module that is
|
||
|
registered when <tt>FT_Add_Module</tt> is called.</p>
|
||
|
|
||
|
<p>The definition of <tt>FT_ModuleRec</tt> is not publicly available
|
||
|
to client applications. However, each <em>module type</em> is described
|
||
|
by a simple and public structure named <tt>FT_Module_Class</tt>,
|
||
|
defined in <tt><freetype/ftmodule.h></tt>, and is detailed
|
||
|
heavily later in this document:</p>
|
||
|
|
||
|
<p>You need a pointer to a <tt>FT_Module_Class</tt> structure when
|
||
|
calling <tt>FT_Add_Module</tt>, whose declaration is:</p>
|
||
|
|
||
|
<pre><font color="blue">
|
||
|
FT_Error FT_Add_Module( FT_Library library,
|
||
|
const FT_Module_Class* clazz );
|
||
|
</font></pre>
|
||
|
|
||
|
<p>Calling this function will do the following:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><p>
|
||
|
it will check if the library already holds a module object corresponding
|
||
|
to the same module name as the one found in the <tt>FT_Module_Class</tt>.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
it this is the case, it will compare the module version number to see
|
||
|
if it is possible to <em>upgrade</em> 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.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
it creates a new <tt>FT_Module</tt> object, using data and flags
|
||
|
of the module class to determine its byte size and how to properly
|
||
|
initialize it.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
when a module initializer is present in the module class, it will
|
||
|
be called to complete the module object's initialisation.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
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.
|
||
|
</p></li>
|
||
|
|
||
|
</ul>
|
||
|
|
||
|
<p>Note that this function doesn't return a <tt>FT_Module</tt> handle,
|
||
|
given that module objects are completely internal to the library
|
||
|
(and client applications shouldn't normally mess with them :-)</p>
|
||
|
|
||
|
<p>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:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><p>
|
||
|
<b>renderer</b> 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.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
<b>font driver</b> modules are used to support one or more specific
|
||
|
font format. Typically, each font driver provides a specific
|
||
|
implementation/derivative of <tt>FT_Face</tt>, <tt>FT_Size</tt>,
|
||
|
<tt>FT_GlyphSlot</tt> as well as <tt>FT_CharMap</tt>.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
<b>helper</b> modules are used to contain code that is shared
|
||
|
by several font drivers. For example, the <b>sfnt</b> 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.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
finally, the <b>auto-hinter</b> 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..
|
||
|
</p></li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Note that every <tt>FT_Face</tt> object is <em>owned</em> 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
|
||
|
<tt>FT_Remove_Module</tt>).</p>
|
||
|
|
||
|
<font color="red">
|
||
|
<p>Because of this, you should always take care that no <tt>FT_Face</tt>
|
||
|
object is opened when you upgrade or remove a module from a library,
|
||
|
as this could cause unexpected object deletion !!</p>
|
||
|
</font>
|
||
|
|
||
|
<hr>
|
||
|
<h2>4. Libraries:</h2>
|
||
|
|
||
|
<p>And we now come back to our well-known <tt>FT_Library</tt> objects.
|
||
|
From what have been said here, we already know that a library
|
||
|
instance owns at least the following:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><p>
|
||
|
a memory manager object (<tt>FT_Memory</tt>), used for all
|
||
|
allocation/releases within the instance.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
a list of <tt>FT_Module</tt> objects, corresponding to the
|
||
|
"installed" or "registered" modules of the instance. This
|
||
|
list can be changed at any time through <tt>FT_Add_Module</tt>
|
||
|
and <tt>FT_Remove_Module</tt>.
|
||
|
</p></li>
|
||
|
|
||
|
<li><p>
|
||
|
finally, remember that face objects are owner by font drivers
|
||
|
that are themselves modules owned by the library.
|
||
|
</p></li>
|
||
|
</ul>
|
||
|
|
||
|
<p>There is however another object owned by the library instance that
|
||
|
hasn't been described until now, and it's the <em>raster pool</em>.</p>
|
||
|
|
||
|
<p>The <b>raster pool</b> 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 :-).</p>
|
||
|
|
||
|
<p>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.</p>
|
||
|
|
||
|
<p>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).</p>
|
||
|
|
||
|
<p>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..</p>
|
||
|
|
||
|
<p>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 ).</p>
|
||
|
|
||
|
<hr>
|
||
|
<h2>5. Summary</h2>
|
||
|
|
||
|
<p>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:</p>
|
||
|
|
||
|
<center><img src="to-be-done.png" width="100" height="100"></center>
|
||
|
|
||
|
</td></tr></table></center>
|
||
|
</body>
|
||
|
</html>
|