�ɲɾ�����ӯ�����һ��ˣ��������С���˴��ͣ�������P���ҹ��ñ˽��ά�Բ��������˸߸ԣ�������ơ��ҹ��ñ�����ά�Բ���ˡ���˳^�ӣ������ӡ� ���ͯj�ӣ��ƺ���ӣ� ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!index.html000064400000015024152527427650006562 0ustar00 FreeType Design

FreeType Design

This document gives an overview of some FreeType 2 internals. Read this carefully if you want to understand the innards of the library in order to hack or extend it.

Note that many, quite important details are still missing, which are hopefully addressed in the not too distant future. Volunteers to help with this task are highly welcomed!

Last update: 13-Feb-2018

design-2.html000064400000023264152527427650007070 0ustar00 FreeType Design / I

FreeType Design / I

I. Components and APIs

It is 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 explain the connections and relationships between them.

A first brief description of this system of components could be as follows.

  • 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 which 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).

Basic FreeType design

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 and input stream access, as well as ftinit, which is in charge of library initialization (i.e., implementing the FT_Init_FreeType function).

  • FreeType 2 comes also with a set of optional components, which can be used either as a convenience layer 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 and OpenType variations fonts).

  • 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 modules both use the routines provided by the sfnt module).

  • Finally, FreeType provides services, which are a more light-weight way to access certain features across multiple modules, or to access some functionality provided by a single module.

    Services are internal to FreeType; similar to modules, it is necessary to ‘load’ a service, which can fail if the service's module is not available.

    An example for a service provided by a single module is ‘winfonts’ (see file svwinfnt.h), which allows access to the header of Windows bitmap fonts. An example for a service provided by multiple modules is ‘multi-masters’ (see file svmm.h) to manage the abovementioned ftmm component across the truetype, type1, and cff modules.

The following graphics shows the additional components (without services).

Detailed FreeType design

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 components can use module-specific interfaces or services ignored by the base layer. In the above example, ftmm directly accesses the Type 1 and TrueType modules to set and query data.

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

Last update: 13-Feb-2018

design-6.html000064400000027712152527427650007076 0ustar00 FreeType Design / V

FreeType Design / V

V. Interfaces and Services

We shall now go into detail about interfaces and services in FreeType.

Interfaces in FreeType are analogous to those found in object-oriented programming. They can be thought of as internal public APIs, and are essentially tables of function pointers.

Interfaces only describe the form and functionality, but the actual function body may be implemented elsewhere. The module that is implementing the interface will then pass the required function pointers to the table. This gives modularity and easy extendability.

There are two main kinds of interfaces: module interfaces, and services.

Module interfaces are defined for each module. For example, every font driver provides its own set of procedures for use in the base layer, which are registered in an FT_Driver. This way, very different font drivers can be used in the same way in the base layer.

Services are cross-module interfaces. These provide functionality needed in several font drivers.

Services are created when code from one module needs to be used in another. Rather than include files from another module, a service is created instead. Now, the other module just needs to include the header defining the interface.

Helper modules are an extreme example of this; all their public functionality is made for use in other font drivers and hence are in a single service.

In-depth guide: Creating a service

This section will teach you how to write your own service.

  1. Make the service interface header.

    We will be calling our service demo for demonstration purposes. First, create the header file, which goes in include/freetype/internal/services, and add the boilerplate.

    #include FT_INTERNAL_SERVICE_H
    FT_BEGIN_HEADER
    #define FT_SERVICE_ID_DEMO  "demo"
    
    /* ...  */
    
    FT_END_HEADER

    This line in particular is required to register the new service later on.

    #define service-id service-tag
  2. We will have identified some functions that are needed in another module. Extract the function signatures of these and place them in the header.

    [typedef return-type
       (*type-name)(function-signature);]+

    Example:

    typedef FT_Error
      (*SampleDoSomethingFunc)( int  foo );
    typedef void
      (*SampleDoAnotherFunc)( int    foo,
                              float  bar );
  3. Define the service interface.

    Use the FT_DEFINE_SERVICE macro to do this.

    FT_DEFINE_SERVICE( service-name )
    {
      [type-name  interface-entry;]+
    }

    Example:

    FT_DEFINE_SERVICE( Demo )
    {
      SampleDoSomethingFunc  doSomething;
      SampleDoAnotherFunc    doAnother;
    };

    Here is the definition of the above macro (in ftserv.h).

    #define FT_DEFINE_SERVICE( name )            \
      typedef struct FT_Service_ ## name ## Rec_ \
        FT_Service_ ## name ## Rec ;             \
      typedef struct FT_Service_ ## name ## Rec_ \
        const * FT_Service_ ## name ;            \
      struct FT_Service_ ## name ## Rec_

    This defines a new struct called FT_Service_DemoRec, along with a handle type for the struct, FT_Service_Demo.

  4. Register (and/or implement) the functions for the newly created interface.

    In the module implementing the interface, add a definition like the following

    static const service-record  table-name =
    {
      function-name
      [,function-name2 [,...]]
    }

    which corresponds to the interface defined in step 3. Example:

    static const FT_Service_DemoRec  demo_service_rec =
    {
      function1,
      function2
    };

    This initializes the function pointers table. In this example, function1 has the function signature of SampleDoSomethingFunc and implements the doSomething functionality, and so on.

  5. Register the new service.

    Next, add this code to define the service list in this module, or append the new service to an existing list.

    static const FT_ServiceDescRec service-list-name[] =
    {
      { service-id, &table-name },
      [{ service-id2, &table-name2 }, [...]]
      { NULL, NULL }
    }

    Example:

    static const FT_ServiceDescRec demo_services[] =
    {
      { FT_SERVICE_ID_DEMO, &demo_service_rec },
      { NULL, NULL }
    };

    service-id is what we #define'd in the service header file in step 1. Note that the {NULL, NULL} sentinel value at the end is required.

    Now we need a way for other modules to find this service. First, we need to implement the get_interface function in FT_Module_Class. Here is a minimal example that does not do any validation.

    FT_CALLBACK_DEF( FT_Module_Interface )
    get-interface-name( FT_Module    module,
                        const char*  module_interface )
    {
      return ft_service_list_lookup( service-list-name,
                                     module_interface );
    }

    Then, pass it into the FT_DEFINE_MODULE macro for this module.

    (FT_Module_Requester) get-interface-name

    The last step is optional but recommended, which is to register the new service header in ftserv.h.

    #define FT_SERVICE_DEMO_H  <freetype/internal/services/svdemo.h>
  6. Use the new service.

    Now, in the file that wants to use the service, add the following code to get the service.

    service-record-handle  service;
    
    
    FT_FACE_FIND_GLOBAL_SERVICE( face,
                                 service,
                                 service-id-tail );

    face should be of type FT_Face, which is usually the current face instance being used in the driver, and FreeType tries to find the service in the driver of this face first, before searching all other modules.

    service-id-tail is the part of service-id following FT_SERVICE_ID_.

    Now to call some function in the service.

    service->interface-entry( params );

    Example:

    FT_Service_Demo  demo;
    FT_Error         error;
    
    
    FT_FACE_FIND_GLOBAL_SERVICE( face, demo, DEMO );
    
    error = demo->doSomething(0);
    

Last update: 13-Feb-2018

simple-model.png000064400000003116152527427650007661 0ustar00PNG  IHDRz3 PLTE tTIDATxAn:ߖ#Y-F(p.X!Vu76Ks3A|9vL(((((((((((((((((((((^>v rC#n?#k݅R$>dlKYwyIHreY}d'{Ndr.#o~{kߞ Y| `dn fLF["e{R(( +TaMdy~R)YBj r8~/H7#uw{չ&~}^dL_ކYL~H2a{ٿ|IEer~YKD0k=Tld7>|#ﭗGAXW:Zv E>|?v7 Hqx'ε2 yq%e,;_&\e " vyfE@&Iy_"'y0V oIHQdw~Zw드}y~e&E@GR2G_J}9V}@KI] r/Yep|@ ;Ɋ%9G8v@_ $?|ޗǰ/QP.|_s/n=Q|1%@B("/ *8a7OҗѰFILGm~9d/)Ź,DOATNEr933bKݓn$wfu^I1xLe"JA4۸S$l؂g5k,*MfzY$l]6aȏK>;5de>4'(MqUu{3q-4vtvf9]*;1}V&]ULL{KFGĝlz{tLT;C^%35:"yI3Yn,mBFe*qd"_&cYdc~9Tٛ~rF4#GOP\4I$DZdպP]+ QiT. vc L[# U[4l,+lÄPe{wpddB(4Çp`I&R&)nێXkފd#vÔiQRF TeL[,K3 BmBæ %KZT5F2gJ)3%C2a8H_-Ctw63 2ya|@!H"|vs4fwXM"$r1,K 1*#D{^*K䟔LbH"$H"|Er!]d ^/-P0l%L}|A//Oú#1}tN$DI$DKߏx?ٕtEXtAuthorDavid TurnerIENDB`library-model.png000064400000003220152527427650010030 0ustar00PNG  IHDRU PLTE tT#IDATxn< p9#ͩڧp$9cT{x08ߖ/)qD`aaaaaaaoCCC9:~NNy;Ng:N;#V1ǜ<΃>׫&Dh̙eSgsu1s^tF;طN{xpPw/u;*:Uvמ'gs|WI|Y9s˜ssG{u{Two?;Jy^Zq~|tUBCqm[[3xщ1ikਲ਼cyqgً @pBA{8~dq5s1s^*:_X &Rm[s$(Ɯ9ᶶc9.s@6Ll ('_Y:6Ɯ~o)94F^d=G539>G<=K R0?"@N: @Ô*; 0kA&O:CMs0ϩ=,5 <'> %н,t]`Cj~%F]q+ǏLcWF=$iOJt0qonSN_rhlq3$ײ\tI]g"zA )I#+>v:Ҷ:^՜E-5k SbF>9Nʼné\ud㴝;3&.w,w!S  WW}NDJ99}u*շOM;r~WI Nf:wdo #-bHXw:Ŵj&,\=K`}: [^Aط$kD5g`Nz9z5qa]1uKz9-9c9NĦÀK`Itw y NQCߢz%;x'c9ly⺘v]JtEXtAuthorDavid TurnerIENDB`detailed-design.png000064400000004362152527427650010320 0ustar00PNG  IHDR#PLTEIDATxq0o;ص@؁GdהS(U"AظxS8 ²,˲,˲ *A|;i3 f0`3 f0Ò2$b#Cg@1Mв96@ Bb,A@(~ >D@6c-r+ARϐА!!:MXp> ۄAY6}Dž(A"HB0^F( f0`3 f0`~ʝفd)OL3 f0`3 f0`3 f0`3J(KG4~nt40Õ PM}4 g/ߊa_2`_Q*!>h$U1/g3Qu 뱳nҮ3pE3  Pm-#gx;*452 m>PxvnR Ĕ-RN䬨t̗53@Lc[<\iϧ`3t%$>VZ>l3 f0`3 f [~0 oxҎv/eزlM lYW0lhkڥMݶ^l,KK~amUo-Wo왵a ꉅG4|v/7M:GS_±P]V$C|p>su<ƀ 1aXLJ'_Oqyf!@ 1V v)@WT.5^aUU 0FYH2^ { }0yhu[Sã 31"3X Ex)VC8!Tn E!  Q|9C0S y=(CRH8?i*fl' Ъ!C 6Ъ!FHv ,0PBC ih H4c~؛3i`85`;>Kw@ƀϛB-31:2ϛ6׬Kk}V}:tLsjY գ P+e?y #P1ܛ :auz'kIM2F]!|2`:LC fo.0,7ó ;6`3 f0`3 3$?2 K`K/j8x?aO2Gm?|Þd'0HM)'3&sԦiKV9j >aC{9jz|I2Gmϔcv2Gm_xU}NM$O/V9j|f0`3 f0`3 f0`·cw2dYeYeYeYeYeYJrGqW8i5Yxnew{60#F PL&U "zH,dAbD>"S;o|4hQ@Ġtئޞ/ [c%6NwPe RcGn%S(d1Cw,|TE0`p|>t/tǶC>N .1b}| U}kT ) ˲*EIޕ->afu;9q~ \E0{: D)vzH&>`Hqj9A FreeType Design / IV

FreeType Design / IV

IV. Module Classes

We will now try to explain more precisely the types of modules that FreeType 2 is capable of managing.

  • Renderer modules manage scalable glyph images. This means transforming them, computing their bounding box, and converting them to either monochrome or anti-aliased bitmaps.

    Note that FreeType 2 is capable of dealing with any kind of glyph images, as long as a renderer module is provided for it. The library comes by default with two renderers.

    raster

    Supports the conversion of vectorial outlines (described by an FT_Outline object) to monochrome bitmaps.

    smooth

    Supports the conversion of the same outlines to anti-aliased pixmaps (using 256 levels of gray). Note that this renderer also supports direct span generation, this is, it provides a hook into the engine so that the application can manipulate the rendering results itself, instead of letting the rasterizer fill a pixmap. See this tutorial demo file for an example.

  • Font driver modules support one or more specific font formats. Here is a list with the most important ones.

    truetype

    TrueType fonts.

    type1

    Postscript Type 1 fonts, both in binary (.pfb) or ASCII (.pfa) formats, including Multiple Master fonts.

    cid

    Postscript CID-keyed fonts.

    cff

    OpenType CFF and CFF2, bare CFF, and CEF fonts (CEF is a derivative of CFF used by Adobe in its SVG viewer).

    winfonts

    Windows bitmap fonts (i.e., .fon and .fnt).

    Note that font drivers can support bitmapped or scalable glyph images. A given font driver that supports Bézier outlines through FT_Outline can also provide its own hinter, or rely on FreeType's autofit module for auto-hinting.

  • Helper modules are used to hold shared code that is often used by several font drivers, or even other modules. The most important are as follows.

    sfnt

    Support for font formats based on the SFNT storage scheme: TrueType, OpenType, as well as other variants (like TrueType fonts that only contain embedded bitmaps).

    psnames

    Various useful functions related to glyph name ordering and Postscript encodings and charsets. For example, this module is capable of automatically synthetizing a Unicode charmap from a Type 1 glyph name dictionary.

    psaux

    Auxiliary functions related to Postscript charstring decoding, as needed by the type1, cid, and cff drivers.

  • Finally, the auto-hinter module (autofit) has a specific role in FreeType 2, as it can be used automatically during glyph loading to process individual glyph outlines when a font driver doesn't provide its own hinting engine.

    A paper published in the EuroTeX 2003 proceedings, titled Real-Time Grid Fitting of Typographic Outlines, gives further insight into the auto-hinting system's inner workings.

We will now study how modules are described, then managed by the library.

1. The FT_Module_Class Structure

Here is the definition of FT_Module_Class, with some explanations. The following code is taken from ftmodapi.h.

typedef struct  FT_Module_Class_
{
  FT_ULong               module_flags;
  FT_Int                 module_size;
  const FT_String*       module_name;
  FT_Fixed               module_version;
  FT_Fixed               module_requires;

  const void*            module_interface;

  FT_Module_Constructor  module_init;
  FT_Module_Destructor   module_done;
  FT_Module_Requester    get_interface;

} FT_Module_Class;

A description of its fields.

module_flags

A set of bit flags to describe the module's category. Valid values are listed below.

  • FT_MODULE_FONT_DRIVER if the module is a font driver
  • FT_MODULE_RENDERER if the module is a renderer
  • FT_MODULE_HINTER if the module is an auto-hinter
  • FT_MODULE_DRIVER_SCALABLE if the module is a font driver supporting scalable glyph formats
  • FT_MODULE_DRIVER_NO_OUTLINES if the module is a font driver supporting scalable glyph formats that cannot be described by an FT_Outline object
  • FT_MODULE_DRIVER_HAS_HINTER if the module is a font driver that provides its own hinting scheme/algorithm
  • FT_MODULE_DRIVER_HINTS_LIGHTLY if the module is a font driver that generates ‘light’ hints (this is, only along the vertical axis).

module_size

An integer that gives the size in bytes of a given module object. This should never be less than sizeof(FT_ModuleRec), but can be more if the module needs to sub-class the base FT_ModuleRec class.

module_name

The module's internal name, coded as a simple ASCII C string. There can't be two modules with the same name registered in a given FT_Library object. However, FT_Add_Module uses the module_version field to detect module upgrades and perform them cleanly, even at run-time.

module_version

A 16.16 fixed-point number giving the module's major and minor version numbers. It is used to determine whether a module needs to be upgraded when calling FT_Add_Module.

module_requires

A 16.16 fixed-point number giving the version of FreeType 2 that is required to install this module. The default value is 0x20000 for FreeType version 2.x

module_interface

Most modules support one or more ‘interfaces’, i.e., tables of function pointers. This field points to the module's main interface, if there is one. It is a short-cut that prevents users of the module to call get_interface each time they need to access one of the object's common entry points.

Note that it is optional, and can be set to NULL. Other interfaces can also be accessed through the get_interface field.

module_init

A pointer to a function to initialize the fields of a fresh new FT_Module object. It is called after the module's base fields have been set by the library, and is generally used to initialize the fields of FT_ModuleRec subclasses.

Most module classes set it to NULL to indicate that no extra initialization is necessary.

module_done

A pointer to a function to finalize the fields of a given FT_Module object. Note that it is called before the library unsets the module's base fields, and is generally used to finalize the fields of FT_ModuleRec subclasses.

Most module classes set it to NULL to indicate that no extra finalization is necessary

get_interface

A pointer to a function to request the address of a given module interface. Set it to NULL if you don't need to support additional interfaces but the main one.

2. The FT_Module Type

The FT_Module type is a handle (i.e., a pointer) to a given module object or instance, whose base structure is given by the internal FT_ModuleRec type. We will intentionally not describe this structure here, as there is no point to look so far into the library's design.

When FT_Add_Module is called, it first allocates a new module instance, using the module_size class field to determine its byte size. The function initializes the root FT_ModuleRec field, then calls the class-specific initializer module_init when this field is not set to NULL.

Note that the library defines several sub-classes of FT_ModuleRec.

  • FT_Renderer for renderer modules

  • FT_Driver for font driver modules

  • FT_AutoHinter for the auto-hinter

Helper modules use the base FT_ModuleRec type.

Last update: 13-Feb-2018

design-3.html000064400000041725152527427650007073 0ustar00 FreeType Design / II

FreeType Design / II

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

  1. Almost all object types or classes have a corresponding structure type and a corresponding structure pointer type. The latter is called the handle type for the type or 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’).

  2. 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 this.

    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 an FT_FooBar handle also points to a ‘foo’ object and can be typecast to FT_Foo. Similarly, when the library returns an FT_Foo handle to client applications, the object can be really implemented as 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 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 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 an 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 returns FT_Err_Ok (which is value 0), and the handle pointed to by the face parameter is 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 stores 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 FT_Request_Size, 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: usually it is fully sufficient 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.

For example, the TrueType driver stores the scaled CVT (Control Value Table) data that results from the execution of the ‘prep’ 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 the 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.

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 a handle to character map objects, or charmaps. A charmap is simply some sort of table or dictionary 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 to precisely identify 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 Relationship

The following diagram summarizes what we have just said regarding the public objects managed by the library; it also describes their relationship.

Simple library model

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

Last update: 13-Feb-2018

basic-design.png000064400000003650152527427650007625 0ustar00PNG  IHDR9|zPLTE5IDATxkr:wd;H[I 6zJL}z"4DX,bX,eB(HS0)La S0)La SЂ2k^H!C}GSy>@ BZ1fcQ(N@=A`q]S lW!P @j]SRtOw-MW "բPʶiQlzE*f!(PF$)BaBua,"b8;sS0)La S0)La S|GE0>ALa S0)La S_)R`"eB)b ߫)$}HEtzKUC"PMOq^SwV,&ёC{Sb~w^\G2goN],G@nPRԩޱE Em]D23.v [ 6y!cS*LE1t "D(t1mB_xgV*kSz0qz/S;vma]tpL\k\.ԃkYUqvRi4`Q)T18vX .qQ)O 񕭗otQ/l@ݕ?K(ӯX˛c+WW(؞be躟JRXfI)ϟrSb;q2E~nũ(%az9yaY#La Sb0{|8#&(@VqgSP$K +ZŸ)ғ',(%YKYoE?dGxIE2VfQ7ܐ"-3ߊۈܟhW+) *^,AR(Tw~oŭZn"";rQ̎0[wn*@>Y E]}qh/BjP3uek)~S$KfūY=KbYo^ޣz0)La S8(~AsPvt?qu?uSFMoWiԀ e}h}\)B[RdZ0Y(ptm SX!#G$x_زca܀[SSTj&C=ؗ\]v7?Bc]x?ů2PONFg@|E0)La S8 3Lb}}],چN{ <Ȇ!l)z9}~Eil)1 5'a&lZXPwr "; HL#(U>` IibVd꼁E~%}rOzGOl>MS- orX,bX,Sٱ˯tEXtAuthorDavid TurnerIENDB`design-4.html000064400000036657152527427650007104 0ustar00 FreeType Design / III

FreeType Design / III

III. Internal Objects and Classes

Let us have a look now at the internal objects that FreeType 2 uses, i.e., those not directly available to client applications, and see how they fit into the picture.

1. Memory Management

Most memory management operations are performed through three specific routines of the base layer: FT_Alloc, FT_Realloc, and FT_Free. Each one of these functions expects a FT_Memory handle as its first parameter. Note, however, that there exist more, similar variants for specific purposes which we skip here for simplicity.

FT_Memory is a pointer to a simple object that describes the current memory pool or manager. It contains a small table of alloc, realloc, and free functions. A memory manager is created at library initialization time by FT_Init_FreeType, calling the (internal) function FT_New_Memory provided by the ftsystem component.

By default, this manager uses the ANSI functions malloc, realloc, and free. 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 header file ftsystem.h.

  2. Call FT_New_Library to create a new library instance using your custom memory manager. This new library doesn't yet contain any registered modules.

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

2. Input Streams

Font files are always read through FT_Stream objects. The definition of FT_StreamRec is located in the public header file ftsystem.h, which allows client developers to provide their own implementation of streams if they wish so.

The function FT_New_Face always automatically creates a new stream object from the C pathname given as its second argument. This is achieved by calling the (internal) 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 functions fopen, fseek, and fread. 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 temporarily buffered similarly through typical seek and read operations.

The FreeType stream sub-system also implements extremely efficient algorithms to very quickly load structures from font files while ensuring complete safety in the case of a ‘broken file’.

The function FT_New_Memory_Face can be used to directly create and open an 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.

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 public structure named FT_Module_Class, defined in header file ftmodule.h, and is described later in this document.

You need a pointer to an FT_Module_Class structure when calling FT_Add_Module.

FT_Error
FT_Add_Module( FT_Library              library,
               const FT_Module_Class*  clazz );

This function does the following tasks.

  • Check whether the library already holds a module object corresponding to the same module name as the one found in FT_Module_Class.

  • If this is the case, compare the module version number to see whether 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, return immediately. Similarly, check that the version of FreeType 2 that is running is correct compared to the one required by the module.

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

  • If a module initializer is present in the module class, call it to complete the module object's initialization.

  • Add the new module to the library's list of ‘registered’ modules. In case of an upgrade, destroy the previous module object.

Note that this function doesn't return an FT_Module handle, given that module objects are completely internal to the library (and client applications shouldn't normally mess with them :-)

Finally, it is important to understand that FreeType 2 recognizes and manages several kinds of modules. These will be explained later on in this document.

  • Renderer modules are used to convert native glyph images to bitmaps or pixmaps. FreeType 2 comes with two renderer modules by default: one to generate monochrome bitmaps, the other to generate anti-aliased pixmaps.

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

  • Helper modules are shared by several font drivers. For example, the sfnt module parses and manages tables found in SFNT-based font formats; it is then used by both the TrueType font and CFF 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, depending on the original font file's format. This means that all face objects are destroyed when a module is removed or unregistered from a library instance (typically by calling the FT_Remove_Module function). 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. 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.

Complete library model

Last update: 13-Feb-2018

design-1.html000064400000016570152527427660007072 0ustar00 FreeType Design

FreeType Design

Introduction

This document provides details on the design and implementation of the FreeType 2 library. Its goal is to help developers better understand how FreeType 2 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.

  • It allows client applications to access font files easily, wherever they could be stored, and as independently of the font format as possible.

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

  • It allows easy retrieval of individual glyph data (metrics, images, name, anything else).

  • Access to font format-specific ‘features’ whenever possible (e.g., SFNT tables, Multiple Masters, OpenType layout tables, font variations, etc.).

Its design has also severely been influenced by the following requirements.

  • High portability. 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.

  • Extendability. New features should be added with the least modifications in the library's code base. This requirement induces an extremely simple design where nearly all operations are provided by modules or services.

  • 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 into a font server for embedded graphics libraries, say.

  • Compactness and efficiency. The primary target for this library originally were embedded systems with low CPU and memory resources. Today, however, memory constraints are much less strict, and the focus of development shifted to support as much font features as possible.

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 and data managed internally by FreeType 2.

It is intended to eventually add sections that cover library customization, relating to topics as system-specific interfaces, how to write your own modules or services and how to tailor library initialization and compilation to your needs. Those sections are not written yet, however.

Last update: 13-Feb-2018