  
  
  
  The design of FreeType 2
  Copyright 1998-2000 David Turner (
mailto:david@freetype.orgdavid@freetype.org )  Copyright 2000 The FreeType Development Team (
mailto:devel@freetype.orgdevel@freetype.org )
  
  
  
    
      
design-2.htmlPrevious     
    
      
index.htmlContents     
    
      
design-4.htmlNext     
  
  
  
  
  
  
    
      II. Public Objects and Classes
    
  
  
  
We will now explain 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 FreeType 2 source
    code:
    
      
        
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
        FreeType 2.  We would define the following structure and handle
        types as follows:
        
    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
.
      
      
        
Class derivation is achieved internally by wrapping base class
        structures into new ones.  As an example, we 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 returns a 
FT_Foo handle to client applications,
        the object can be really implemented as a 
FT_FooBar or any
        derived class from "foo".
      
    
    
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
    actions.
    
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: an 
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), and 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
    FreeType 2 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 contents 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    structure, 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 explicitly provide
    data to compute a slot's maximum size.
    
Another reason for glyph slots is that they are also used to hold
    format-specific hints for a given glyphs as 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 Type 1-specific 
T1_GlyphSlotRec structure holds glyph
    hints during glyph loading, as well as additional logic used to properly
    hint the glyphs when a native Type 1 hinter is used.
    
Finally, each face object has a single glyph slot that is directly
    accessible as 
face->glyph.
    
    
      6. The 
FT_CharMap class
    
    
The FT_CharMap type is used as a handle to character map
    objects, or 
charmaps.  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 encodings.
    
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 have just said regarding the
    public objects managed by the library, as well as explicitely describes
    their relationships
    
      
Simple library model    
    
Note that this picture will be updated at the end of the next
    chapter, related to 
internal objects.
  
  
  
  
    
      
design-2.htmlPrevious     
    
      
index.htmlContents     
    
      
design-4.htmlNext     
  
  
  
