The Design of FreeType 2

Source: Internet
Author: User
Tags vector font

Design of FreeType 2

Introduction
This document provides the design and implementation details of the FreeType 2 function library. The goal of this document is to allow developers to better understand how FreeType 2 is organized and to allow them to expand, customize, and debug it.
First, let's first understand the purpose of this database, that is, why the database is written:
* It allows the customer application to easily access the font files, regardless of where the font files are stored and irrelevant to the font format.
* Convenient extraction of global font data, which is common in common font formats. (For example, global measurement standards, character encoding/character ing tables, etc)
* It is convenient to extract the font data of a character (measurement standard, image, name, and anything else)
* Access features specific to the font format (for example, sfnt table, multi-control, OpenType profile table)
The Design of FreeType 2 is also subject to the following requirements:
* High portability. This library must be able to run in any environment. This requirement introduces some very intense options, which are part of FreeType2's low-level system interface.
* Scalability. New features can be added with minimal changes to the basic code of the library. This requirement introduces a very simple design: almost all operations are provided in the form of modules.
* Customizable. It should be easy to build a version that only contains the features required by a specific project. This is important when you need to integrate it into a font server of an embedded graphics library.
* Simple and efficient. The main goal of this library is to only embedded systems with few CPU and memory resources.
The other parts of this document are divided into several parts. First, some chapters introduce the basic design of the database and the management of objects/data in FreeType 2.
The following sections focus on library customization and system-specific interfaces related to this topic, how to write your own modules, and how to cut the library initialization and compilation on demand.

I. Components and APIs
FT can be seen as a group of parts, each component is responsible for part of the task, they include

* A customer application generally calls the FT high-level API. Its functions are all in one component, called the basic layer.
* Based on the context and environment, the base layer calls one or more modules for work. In most cases, the customer application does not know which module to use.
* The basic layer also contains a set of routines for common processing, such as memory allocation, list processing, Io stream parsing, fixed point computing, and so on. These functions can be freely called by the module, they form an underlying basic API.

For example, indicate their relationship

In addition,

* For some special builds, some parts of the base layer can be replaced or seen as components. For example, the ftsystem component is responsible for memory management and input stream access, as well as ftinit for library initialization.
* Ft also has some optional components that can be used flexibly according to the client application. For example, the ftglyph component provides a simple API to manage the glyphs without relying on their internal representation. Or access the features in a specific format. For example, the ftmm component is used to access and manage the multiple masters data in the type1 font.
* At last, a module can call functions provided by other modules, which is useful for sharing code and tables among multiple font drive modules, for example, both the TrueType and CFF modules use functions provided by the sfnt module.

See.

 

Note the following points:

* An optional component can be used for high-level APIs or underlying APIs, such as the ftglyph above;
* Some optional components use the module-specific interface instead of the basic layer interface. In the preceding example, ftmm directly accesses the type1 module to access data;
* An alternative component can provide a high-level API function. For example, ftinit provides ft_init_freetype ()

Ii. Public objects and Classes

1. Object-oriented in ft
Although ft is written in ansi c, it is very easy to expand this library by adopting the object-oriented idea. Therefore, there are some code conventions below.

1. Each object type/class has a corresponding structure type and a corresponding structure pointer type, which is called the type/class handle type.

Suppose we need to manage an object of the foo class in ft, which can be defined as follows:

Typedef struct ft_foorec _ * ft_foo;

Typedef struct ft_foorec _

{

// Fields for the foo class

...

} Ft_foorec;

According to the Conventions, the handle type uses simple and meaningful identifiers and starts with FT _, for example, ft_foo. The struct uses the same name but adds the REC suffix. REC is the abbreviation of record. Each class type has a corresponding handle type;

2. class inheritance is implemented by encapsulating the base class into a new class. For example, we define a foobar class and inherit from the foo class.

Typedef struct ft_foobarrec _ * ft_foobar;

Typedef struct ft_foobarrec _
{
Ft_foorec root; // base class

} Ft_foobarrec;

As you can see, put an ft_foorec at the beginning of the ft_foobarrec definition, and specify the name as root. This ensures that a foobar object is also a foo object.

In actual use, you can perform type conversion.

Back

2. ft_library class
This type corresponds to a single instance handle of a database, and the corresponding ft_libraryrec is not defined, so that the customer application cannot access its internal attributes.

The database object is the father of all other ft objects. You need to create a new database instance before doing anything. When it is destroyed, all its children will be automatically destroyed, such as face and module.

Generally, the customer program should call ft_init_freetype () to create a new library object and use it for other operations.

Another way is to create a new library object by calling the ft_new_library () function, which is in the <FreeType/ftmodule. h>. This function returns an empty library without any module registration. You can call ft_add_module () to install the module.

Tune
It is more convenient to use ft_init_freetype () because it registers some modules by default. In this method, the module list is dynamically calculated during build and dependent on
. (See ftinit. C [l73], include
Ft_config_modules_h is actually including ftmodule. h. The default module is defined in ftmodule. H, so the module Array
The ft_default_modules size is dynamically determined during compilation .)

3. ft_face class
An appearance object corresponds to the appearance of a single font, that is, a specific appearance type of a specific style. For example, Arial and Arial italic are two different appearances.

An appearance object is usually created using ft_new_face (). This function accepts the following parameters: An ft_library handle and a C file path name indicating the font file, an index that determines the appearance of the file (a file may have a different appearance), and the address of the 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 );

If the function is successfully called, 0 is returned. The face parameter is set to a non-null value.

The appearance object contains some attributes used to describe the global font data and can be directly accessed by the customer program. For example, the number of glyphs in the appearance, the name of the appearance family, the style name, And the EM size, see ft_facerec.

4. ft_size class
Each ft_face object has one or more ft_size objects. A size object is used to store specific data with the specified character width and height. Each newly created appearance object has a size, you can use face-> size for direct access.

The size object content can be changed by calling ft_set_pixel_sizes () or ft_set_char_size.

A new size object can be created through ft_new_size () and destroyed through ft_done_size (). Generally, the customer program does not need to perform this step. They can usually use the default size object provided by each ft_face.

Ft_size
Public attributes are defined in ft_sizerec, but note that some font drivers define their own ft_size subclasses to store important internal data, each time the character size changes
Computing. In most cases, they are hint fonts of specific sizes. For example, the TrueType driver stores the CVT table and puts the result into the tt_size struct by executing the CVT program.
The type1 driver places scaled global metrics in the t1_size object.

5. ft_glyphslot class
Word
The purpose of a shape slot is to provide a place where you can easily mount a shape image one by one, regardless of its format (bitmap, vector contour, or other ). Ideally, once a font slot is created, any font image can
To load, no other memory allocation is required. In practice, this is only true for a specific format. For example, TrueType, it explicitly provides data to calculate the maximum size of a slot.

Another reason for the font slot is that it is used to save the hint in the specific format for the specified font, and other necessary data to correctly load the font.

The basic ft_glyphslotrec struct only shows metics and images to the customer program, while the real implementation contains more data.

For example, a specific tt_glyphslotrec structure of TrueType contains additional properties that store the bytecode specific to the font, temporary outlines during the hint process, and other things.

Finally, each appearance object has a single font slot that can be directly accessed using face-> glyph.

6. ft_charmap class
The ft_charmap type is used as the handle of a character map object. A Character Chart is a table or dictionary used to convert the character code from a certain encoding to a font-shaped index.

A single appearance may contain several character graphs, each corresponding to a specified character command system, such as Unicode, Apple Roman, and Windows codepages.

Each ft_charmap object contains a platform and encoding attribute to identify its character command system. Each font format provides its own ft_charmaprec inheritance type and implements them.

7. Object relationship
I just outlined what we mentioned earlier about public-class hosting in the library, and also clearly described their previous relationships.

3. Internal objects and Classes
1. Memory Management
Institute
Memory management operations are completed through three specific routines in the base layer, namely ft_alloc, ft_realloc, and ft_free. Each function requires
The ft_memory handle is used as its first parameter. It is a pointer used to describe the current memory pool/manager object. Call the function in ft_init_freetype during library Initialization
The number ft_new_memory creates a memory manager, which is located in the ftsystem part.

By default, this manager uses ANSI
Malloc, realloc, and free functions, but ftsystem is a replaceable part of the base layer. The specific libraries can provide different memory managers. Even if the default
The client program can still provide its own memory manager by calling ft_init_freetype through the following steps:

1. manually create an ft_memory object. ft_memoryrec is located in the public file <FreeType/ftsystem. h>.

2. Use your own memory manager to call ft_new_library () to create a new library instance. The new library does not contain any registered modules.

3. register the default module by calling the ft_add_default_modules () function (in the ftinit part), or manually register your driver by calling the ft_add_module repeatedly.

2. input stream
Word
The object is always read through the ft_stream object. The definition of ft_streamrec is located in the public file <FreeType/ftsystem. h>.
To allow developers to provide their own stream implementations. The ft_new_face () function automatically creates a new stream object with a C path name based on its second parameter. By calling
The ft_new_stream () provided by the ftsystem component is complete and can be replaced by the latter. The stream implementation may be quite different on different platforms.

For example, the default implementation of a stream is in the file src/base/ftsystem. C and the ANSI fopen/fseek and fread functions are used. However, in the Unix Version of FT2, another implementation using memory ing files is provided, which can greatly increase the speed of the host system.

FT distinguishes between memory-based and disk-based streams. For the former, all data is directly accessed in the memory (for example, Rom, only static data and memory ing files are written), while the latter, use the frame concept to read a part of a font file, use a typical seek/read operation, and temporarily buffer it.

Ft_new_memory_face
A function can be used to create/open an ft_face object directly from data that can be read in the memory. Finally, if the customer needs to input a stream, the customer program can use the ft_open_face () function.
Accept customer input streams. This is useful when compressing or remote font files and extracting embedded font files from specific documents.

Note that each appearance has a stream and is destroyed through ft_done_face. In general, it is not a good idea to keep multiple ft_faces in the open state.

3. Module
Ft2
The module itself is a piece of code. The library calls the ft_add_moudle () function to register the module and creates an ft_module object for each module. Ft_modulerec setting
The definition is not public to the client program, but each module type is described by a simple public structure ft_module_class, which is defined in <
FreeType/ftmodule. h>.

When ft_add_module is called, you need to specify a pointer to the ft_module_class structure. Its declaration is as follows:

Ft_error ft_add_module (ft_library library,

Const ft_module_class * clazz );

To call this function, perform the following operations:

* Check whether the database has a module object named ft_module_class;

* If yes, compare the version number of the module to see if it can be upgraded. if the version number of the module class is smaller than that of the mounted module, the function returns immediately. Of course, check whether the running ft version meets the FT version required by the module to be installed.

* Create a New ft_module object. Use the module class data flag to determine its size and initialization;

* If there is a module initiator in the module class, it will be called to complete the initialization of the module object;

* The new module is added to the "registered" module list of the database. For upgrade, the previous module object only needs to be destroyed.

Note that this function does not return the ft_module handle. It is completely internal to the database and the client program should not play with it. Finally, you need to know several FT2 identification and management modules, which will be detailed later. Here we will list them as follows:

* The Renderer module is used to convert an original font image into a bitmap or pixel image. FT2 comes with two Renderer, one is to generate a monochrome bitmap, and the other is to generate a high-quality reversed pixel map.

* The font driver module supports multiple font formats. A typical font driver must provide specific ft_face, ft_size, ft_glyphslot, and ft_charmap implementations;

* The assistant module is shared by multiple font drivers. For example, the sfnt module analyzes and manages sfnt-based tables for TrueType and opentype font drives;

* At last, the auto-hinter module has a special position in the library design. Regardless of the original font format, it processes the vector font contour to produce high-quality results.

Note that each ft_face object belongs to the corresponding font Driver Based on the original font file format. This means that after a module is removed/canceled from a database instance, all appearance objects are destroyed (usually the ft_remove_module () function is called ).

Therefore, you must note that the ft_face object is not opened when you upgrade or remove a module, because this will cause unexpected objects to be deleted.

4. Database
Ft_library object. As mentioned above, a library instance must at least include the following:

* A memory management object (ft_memory) is used to allocate and release memory in the instance;

* An ft_module object list corresponds to "installed" or "registered" modules. It can be managed at any time through ft_add_module () and ft_remove_module;

* Remember that the appearance object belongs to the font drive and the font drive module belongs to the library.

Another object belongs to the database instance, but it is not mentioned: raster pool

The grating pool is a fixed memory, which requires large operations for some memory as the internal "Draft area" to avoid memory allocation. For example, it is used when each Renderer converts a vector font profile to a bitmap (that is why it is called a grating pool ).

The size of the grating pool is determined at initialization (16 KB by default) and cannot be modified during runtime. When the memory required by an instantaneous operation exceeds the size of the pool, another part can be allocated as an exception or recursive subdivision task to ensure that it does not exceed the limit of the pool.

This extreme memory conservative behavior aims at FT performance, especially in some places, such as font rendering and scanning line conversion.

5. Summary
Finally, the above content is displayed, which indicates the object graph of the FT basic design.


Iv. Modules

There are several modules in ft

* The rendering module is used to manage scalable font images. This means that they are converted, the border is calculated, and they are converted to monochrome and reverse bitmap. FT can process any type of font image. As long as a rendering module is provided for it, FT has two Renderer by default.

Raster supports conversion from vector contour (described by ft_outline object) to monochrome bitmap

Smooth supports converting the same contour to a high-quality reversed pixel image, with a gray scale of 256. This Renderer also supports directly generating span.

* The font driver module is used to support one or more specific font formats. By default, ft is driven by the following fonts:

TrueType supports TrueType font files

Type1 supports the postscript type1 font, which can be in binary (. pfb) and ASCII (. PFA) formats, including the multiple master font

The Cid supports the postscript CID-keyed font.

CFF supports OpenType, CFF, and Cef fonts (CEF is a variant of CFF, used in Adobe SVG Viewer

Winfonts supports Windows bitmap fonts,. Fon and. fnt.

The font driver supports bitmap and scalable font images. A font driver that supports the besuppliers profile can provide its own hinter or depend on the FT autohinter module through ft_outline.

* The assistant module is used to process some shared code. It is usually driven by multiple fonts or even other modules. The default assistant is as follows:

Sfnt is used to support the font format based on the sfnt storage outline, TrueType and OpenType fonts and other variants.

Psnames is used to provide functions related to the sorting of glyph names and the postscript encoding/character set. For example, you can automatically synthesize a Unicode Character Chart from a type1 name dictionary.

Psaux is used to provide functions for decoding type1 characters. This feature is required for type1, CID, and CFF.

* At last, the autohinter module is a special role in ft. When a font driver does not provide its own hint engine, it can process its own glyph outlines when loading.

Now we will learn how the module describes and how it is managed by the FreeType2 database.
1 ft_module_class Structure

2 ft_module type

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.