shithub: freetype+ttf2subf

ref: 6043b2404efc77a1c0dc09a193a6526a62e55e28
dir: /docs/design/design-4.html/

View raw version
<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>&lt;freetype/ftsystem.h&gt;</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>&lt;freetype/ftsystem.h&gt;</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>&lt;freetype/ftmodule.h&gt;</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>