The design of FreeType 2
From Mxtctp
原文链接:http://www.freetype.org/freetype2/docs/design/index.html
翻译人员:HappyLiu
| 英文 | 中文 | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| The design of FreeType 2
Copyright 1998-2000 David Turner (david@freetype.org) | FreeType 2的设计
版权所有 1998-2000 David Turner (david@freetype.org) | ||||||||||||||||||||
| This document describes the details of FreeType 2's internals. Read this carefully if you need to understand the innards of the library in order to hack or extend it. | |||||||||||||||||||||
| Table of Contents
Introduction | 目录
介绍 | ||||||||||||||||||||
| Introduction | 介绍 | ||||||||||||||||||||
| This document provides details on the design and implementation of the FreeType 2 library. Its goal is to allow developers to better understand the way how FreeType 2 is organized, in order to let them extend, customize, and debug it. | 这份文档提供了FreeType 2函数库设计与实现的细节。本文档的目标是让开发人员更好的理解FreeType 2是如何组织的,并让他们扩充、定制和调试它。 | ||||||||||||||||||||
Before anything else, it is important to understand the purpose of this library, i.e., why it has been written:
| 首先,我们先了解这个库的目的,也就是说,为什么会写这个库:
| ||||||||||||||||||||
Its design has also severely been influenced by the following requirements:
| Freetype 2的设计也受如下要求很大的影响:
| ||||||||||||||||||||
| 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/data managed internally by FreeType 2. | 这份文档的其他部分分为几个部分。首先,一些章节介绍了库的基本设计以及Freetype 2内部对象/数据的管理。 | ||||||||||||||||||||
| A later section is then dedicated to library customization, relating such topics as system-specific interfaces, how to write your own module and how to tailor library initialization & compilation to your needs. | 接下来的章节专注于库的定制和与这个话题相关的系统特定的界面,如何写你自己的模块和如何按需裁减库初始化和编译。 | ||||||||||||||||||||
| I. Components and APIs | 一、组件和API | ||||||||||||||||||||
| It's 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 explicit the connections and relationships between them. | FT可以看作是一组组件,每个组件负责一部分任务,它们包括 | ||||||||||||||||||||
A first brief description of this system of components could be:
|
| ||||||||||||||||||||
| This is illustrated by the following graphics (note that component entry points are represented as colored triangles): | 如下图,表明它们的关系 | ||||||||||||||||||||
Now, a few additional things must be added to complete this picture:
| 另外,
| ||||||||||||||||||||
| Hence, a more complete picture would be: | 见下图,是对上图的一个细化。 | ||||||||||||||||||||
Please take note of the following important points:
| 请注意一些要点:
| ||||||||||||||||||||
| 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 | 1、FT中的面向对象 | ||||||||||||||||||||
| 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: | 虽然FT是使用ANSI C编写,但是采用面向对象的思想,是这个库非常容易扩展。因此,下面有一些代码规约: | ||||||||||||||||||||
| 1. 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. | 1. 每个对象类型/类都有一个对应的结构类型和一个对应的结构指针类型。后者称为类型/类的句柄类型。
设想我们需要管理FT中一个foo类的对象,可以定义如下 typedef struct FT_FooRec_* FT_Foo;
typedef struct FT_FooRec_
{
// fields for the "foo" class
...
} FT_FooRec;
依照规约,句柄类型使用简单而有含义的标识符,并以FT_开始,如FT_Foo,而结构体使用相同的名称但是加上Rec后缀。Rec是记录的缩写。每个类类型都有对应的句柄类型; | ||||||||||||||||||||
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:
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". | 2. 类继承通过将基类包装到一个新类中实现,例如,我们定义一个foobar类,从foo类继承,可以实现为
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;
可以看到,将一个FT_FooRec放在FT_FooBarRec定义的开始,并约定名为root,可以确保一个foobar对象也是一个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 | 2、FT_Library类 | ||||||||||||||||||||
| 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. | 这个类型对应一个库的单一实例句柄,没有定义相应的FT_LibraryRec,使客户应用无法访问它的内部属性。 | ||||||||||||||||||||
| 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). | 库对象是所有FT其他对象的父亲,你需要在做任何事情前创建一个新的库实例,销毁它时会自动销毁他所有的孩子,如face和module等。 | ||||||||||||||||||||
| Typical client applications should call FT_Init_FreeType() in order to create a new library object, ready to be used for further actions. | 通常客户程序应该调用FT_Init_FreeType()来创建新的库对象,准备作其他操作时使用。 | ||||||||||||||||||||
| 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. | 另一个方式是通过调用函数FT_New_Library()来创建一个新的库对象,它在中定义,这个函数返回一个空的库,没有任何模块注册,你可以通过调用FT_Add_Module()来安装模块。 | ||||||||||||||||||||
| 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. | 调用FT_Init_FreeType()更方便一些,因为他会缺省地注册一些模块。这个方式中,模块列表在构建时动态计算,并依赖ftinit部件的内容。(译注:见ftinit.c[l73]行,include FT_CONFIG_MODULES_H,其实就是包含ftmodule.h,在ftmodule.h中定义缺省的模块,所以模块数组 ft_default_modules的大小是在编译时动态确定的。) | ||||||||||||||||||||
| 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 | 3、FT_Face类 | ||||||||||||||||||||
| 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. | 一个外观对象对应单个字体外观,即一个特定风格的特定外观类型,例如Arial和Arial Italic是两个不同的外观。 | ||||||||||||||||||||
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. | 一个外观对象通常使用FT_New_Face()来创建,这个函数接受如下参数:一个FT_Library句柄,一个表示字体文件的C文件路径名,一个决定从文件中装载外观的索引(一个文件中可能有不同的外观),和FT_Face句柄的地址,它返回一个错误码。
FT_Error FT_New_Face( FT_Library library,
const char* filepathname,
FT_Long face_index,
FT_Face* face );
函数调用成功,返回0,face参数将被设置成一个非NULL值。 | ||||||||||||||||||||
| 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. | 外观对象包含一些用来描述全局字体数据的属性,可以被客户程序直接访问。例如外观中字形的数量、外观家族的名称、风格名称、EM大小等,详见FT_FaceRec定义。 | ||||||||||||||||||||
| 4. The FT_Size class | 4、FT_Size类 | ||||||||||||||||||||
| 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. | 每个FT_Face对象都有一个或多个FT_Size对象,一个尺寸对象用来存放指定字符宽度和高度的特定数据,每个新创建的外观对象有一个尺寸,可以通过face->size直接访问。 | ||||||||||||||||||||
| The contents of a size object can be changed by calling either FT_Set_Pixel_Sizes() or FT_Set_Char_Size(). | 尺寸对象的内容可以通过调用FT_Set_Pixel_Sizes()或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. | 一个新的尺寸对象可以通过FT_New_Size()创建,通过FT_Done_Size()销毁,一般客户程序无需做这一步,它们通常可以使用每个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> | FT_Size 公共属性定义在FT_SizeRec中,但是需要注意的是有些字体驱动定义它们自己的FT_Size的子类,以存储重要的内部数据,在每次字符大小改变时计算。大多数情况下,它们是尺寸特定的字体hint。 | ||||||||||||||||||||
| 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 :-) | 例如,TrueType驱动存储CVT表,通过cvt程序执行将结果放入TT_Size结构体中,而 Type1驱动将scaled global metrics放在T1_Size对象中。 | ||||||||||||||||||||
| 5. The FT_GlyphSlot class | 5、FT_GlyphSlot类 | ||||||||||||||||||||
| 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. | 理想的,一旦一个字形槽创建了,任何字形映象可以装入,无需其他的内存分配。在实际中,只对于特定格式才如此,像TrueType,它显式地提供数据来计算一个槽的最大尺寸。 | ||||||||||||||||||||
| 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. | 另一个字形槽地原因是他用来为指定字形保存格式特定的hint,以及其他为正确装入字形的必要数据。 | ||||||||||||||||||||
| The base FT_GlyphSlotRec structure only presents glyph metrics and images to client applications, while actual implementation may contain more sophisticated data. | 基本的FT_GlyphSlotRec结构体只向客户程序展现了字形metics和映象,而真正的实现回包含更多的数据。 | ||||||||||||||||||||
| 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. | 例如,TrueType特定的TT_GlyphSlotRec结构包含附加的属性,存放字形特定的字节码、在hint过程中暂时的轮廓和其他一些东西。 | ||||||||||||||||||||
| Finally, each face object has a single glyph slot that is directly accessible as face->glyph. | 最后,每个外观对象有一个单一字形槽,可以用face->glyph直接访问。 | ||||||||||||||||||||
| 6. The FT_CharMap class | 6、FT_CharMap类 | ||||||||||||||||||||
| 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. | FT_CharMap类型用来作为一个字符地图对象的句柄,一个字符图是一种表或字典,用来将字符码从某种编码转换成字体的字形索引。 | ||||||||||||||||||||
| 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. | 单个外观可能包含若干字符图,每个对应一个指定的字符指令系统,例如Unicode、Apple Roman、Windows codepages等等。 | ||||||||||||||||||||
| Each FT_CharMap object contains a "platform" and an "encoding" field used to identify precisely the character repertoire corresponding to it. | 每个FT_CharMap对象包含一个platform和encoding属性,用来标识它对应的字符指令系统。 | ||||||||||||||||||||
| Each font format provides its own derivative of FT_CharMapRec and thus needs to implement these objects. | 每个字体格式都提供它们自己的FT_CharMapRec的继承类型并实现它们。 | ||||||||||||||||||||
| 7. Objects relationships | 7、对象关系 | ||||||||||||||||||||
| The following diagram summarizes what we have just said regarding the public objects managed by the library, as well as explicitely describes their relationships | |||||||||||||||||||||
| Note that this picture will be updated at the end of the next chapter, related to internal objects. | |||||||||||||||||||||
| 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 | 1、内存管理 | ||||||||||||||||||||
| All memory management operations are performed through three specific routines of the base layer, namely: FT_Alloc(), FT_Realloc(), and FT_Free(). Each one of these functions expects a FT_Memory handle as its first parameter. | 所有内存管理操作通过基础层中3个特定例程完成,叫做FT_Alloc()、FT_Realloc()、 FT_Free()。每个函数需要一个 FT_Memory句柄作为它的第一个参数。 | ||||||||||||||||||||
| The latter is a pointer to a simple object used to describe the current memory pool/manager. It contains a simple table of alloc/realloc/free functions. A memory manager is created at library initialization time by FT_Init_FreeType(), calling the function FT_New_Memory() provided by the ftsystem component. | 它是一个用来描述当前内存池/管理器对象的指针。在库初始化时,在FT_Init_FreeType中调用函数FT_New_Memory创建一个内存管理器,这个函数位于ftsystem部件当中。 | ||||||||||||||||||||
| By default, this manager uses the ANSI malloc(), realloc(), and free() functions. However, as ftsystem is a replaceable part of the base layer, a specific build of the library could provide a different default memory manager. | 缺省情况下,这个管理器使用ANSI malloc、realloc和free函数,不过ftsystem是基础层中一个可替换的部分,库的特定构建可以提供不同的内存管理器。 | ||||||||||||||||||||
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:
| 即使使用缺省的版本,客户程序仍然可以提供自己的内存管理器,通过如下的步骤,调用FT_Init_FreeType实现:
| ||||||||||||||||||||
| 2. Input streams | 2、输入流 | ||||||||||||||||||||
| Font files are always read through FT_Stream objects. The definition of FT_StreamRec is located in the public file <freetype/ftsystem.h>, which allows client developers to provide their own implementation of streams if they wish so. | 字体文件总是通过FT_Stream对象读取,FT_StreamRec的定义位于公共文件<freetype/ftsystem.h>中,可以允许客户开发者提供自己的流实现。 | ||||||||||||||||||||
| The function FT_New_Face() will always automatically create a new stream object from the C pathname given as its second argument. This is achieved by calling the function FT_New_Stream() provided by the ftsystem component. As the latter is replaceable, the implementation of streams may vary greatly between platforms. | FT_New_Face()函数会自动根据他第二个参数,一个 C路径名创建一个新的流对象。它通过调用由 ftsystem部件提供的FT_New_Stream()完成,后者时可替换的,在不同平台上,流的实现可能大不一样。 | ||||||||||||||||||||
| As an example, the default implementation of streams is located in the file src/base/ftsystem.c and uses the ANSI fopen(), fseek(), and fread() 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. | 举例来说,流的缺省实现位于文件src/base/ftsystem.c并使用ANSI fopen/fseek和fread函数。不过在FT2的Unix版本中,提供了另一个使用内存映射文件的实现,对于主机系统来说,可以大大提高速度。 | ||||||||||||||||||||
| 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/read operations. | FT区分基于内存和基于磁盘的流,对于前者,所有数据在内存直接访问(例如ROM、只写静态数据和内存映射文件),而后者,使用帧(frame)的概念从字体文件中读出一部分,使用典型的seek/read操作并暂时缓冲。 | ||||||||||||||||||||
| 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/open a FT_Face object from data that is readily available in memory (including ROM-based fonts). | FT_New_Memory_Face() 函数可以用来直接从内存中可读取的数据创建/打开一个FT_Face对象。 | ||||||||||||||||||||
| 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. | 最后,如果需要客户输入流,客户程序能够使用FT_Open_Face()函数接受客户输入流。这在压缩或远程字体文件的情况下,以及从特定文档抽取嵌入式字体文件非常有用。 | ||||||||||||||||||||
| Note that each face owns a single stream, which is also destroyed by FT_Done_Face(). Generally speaking, it is certainly not a good idea to keep numerous FT_Face objects opened. | 注意每个外观拥有一个流,并且通过FT_Done_Face被销毁。总的来说,保持多个FT_Face在打开状态不是一个很好的主意。 | ||||||||||||||||||||
| 3. Modules | 3、模块 | ||||||||||||||||||||
| 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. | FT2 模块本身是一段代码,库调用FT_Add_Moudle()函数注册模块,并为每个模块创建了一个FT_Module对象。 | ||||||||||||||||||||
| 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 <freetype/ftmodule.h>, and is described later in this document. | FT_ModuleRec的定义对客户程序不是公开的,但是每个模块类型通过一个简单的公共结构FT_Module_Class描述,它定义在< freetype/ftmodule.h>中,后面将详述。 | ||||||||||||||||||||
You need a pointer to an FT_Module_Class structure when calling FT_Add_Module(), whose declaration is:
FT_Error FT_Add_Module( FT_Library library,
const FT_Module_Class* clazz );
| 当调用FT_Add_Module是,需要指定一个FT_Module_Class结构的指针,它的声明如下:
FT_Error FT_Add_Module( FT_Library library,
const FT_Module_Class* clazz );
| ||||||||||||||||||||
Calling this function will do the following:
| 调用这个函数将作如下操作:
| ||||||||||||||||||||
| 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 :-) | 注意这个函数并不返回FT_Module句柄,它完全是库内部的事情,客户程序不应该摆弄他。 | ||||||||||||||||||||
Finally, it is 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 will list for now the following types:
| 最后,要知道FT2识别和管理若干种模块,这在后面将有详述,这里列举如下:
| ||||||||||||||||||||
| 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/unregistered from a library instance (typically by calling the FT_Remove_Module() function). | 注意每个FT_Face对象依据原始字体文件格式,都属于相应的字体驱动。这就是说,当一个模块从一个库实例移除/取消注册后,所有的外观对象都被销毁(通常是调用FT_Remove_Module()函数)。 | ||||||||||||||||||||
| 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! | 因此,你要注意当你升级或移除一个模块时,没有打开FT_Face对象,因为这会导致不预期的对象删除。 | ||||||||||||||||||||
| 4. Libraries | 4、库 | ||||||||||||||||||||
We now come back to our well-known FT_Library object. From what have been said before, we already know that a library instance owns at least the following:
| 现在来说说FT_Library对象,如上所述,一个库实例至少包含如下:
| ||||||||||||||||||||
| There is however another object owned by the library instance that hasn't been described yet: the raster pool. | 还有一个对象属于库实例,但仍未提到:raster pool | ||||||||||||||||||||
| The raster pool is simply a block of memory of fixed size that is used internally as a "scratch area" for various memory-hungry transient operations, avoiding memory allocation. 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 :-). | 光栅池是一个固定大小的一块内存,为一些内存需要大的操作作为内部的"草稿区域",避免内存分配。例如,它用在每个渲染器转换一个向量字形轮廓到一个位图时(这其实就是它为何叫光栅池的原因)。 | ||||||||||||||||||||
| The size of the raster pool is fixed at initialisation time (it defaults to 16kByte) and cannot be changed at run-time (though we could fix this if there is a real need for that). | 光栅池的大小在初始化的时候定下来的(缺省为16k字节),运行期不能修改。 | ||||||||||||||||||||
| 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. | 当一个瞬时操作需要的内存超出这个池的大小,可以另外分配一块作为例外条件,或者是递归细分任务,以确保不会超出池的极限。 | ||||||||||||||||||||
| 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). | 这种极度的内存保守行为是为了FT的性能考虑,特别在某些地方,如字形渲染、扫描线转换等。 | ||||||||||||||||||||
| 5. Summary | 5、总结 | ||||||||||||||||||||
| 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: | 最后,下图展示的上面所述内容,他表示FT基本设计的对象图 | ||||||||||||||||||||
| IV. Module Classes | 四、模块类 | ||||||||||||||||||||
| We will now try to explain more precisely the types of modules that FreeType 2 is capable of managing. Note that each one of them is decribed with more details in the following chapters of this document. | 在FT中有若干种模块 | ||||||||||||||||||||
|
| ||||||||||||||||||||
|
| ||||||||||||||||||||
|
| ||||||||||||||||||||
|
| ||||||||||||||||||||
| We will now study how modules are described, then managed by the library. | 我们现在来学习模块是如何描述以及如何被FreeType2库管理的。 | ||||||||||||||||||||
| 1. The FT_Module_Class structure | 1 FT_Module_Class结构 | ||||||||||||||||||||
| As described later in this document, library initialization is performed by calling the FT_Init_FreeType() function. The latter is in charge of creating a new "empty" FT_Library object, then register each "default" module by repeatedly calling the FT_Add_Module() function. | |||||||||||||||||||||
Similarly, client applications can call FT_Add_Module() any time they wish in order to register a new module in the library. Let us take a look at this function's declaration:
extern FT_Error FT_Add_Module(
FT_Library library,
const FT_Module_Class* clazz );
| |||||||||||||||||||||
| As one can see, this function expects a handle to a library object, as well as a pointer to a FT_Module_Class structure. It returns an error code. In case of success, a new module object is created and added to the library. Note by the way that the module isn't returned directly by the call! | |||||||||||||||||||||
Here the definition of FT_Module_Class, with some explanation. The following code is taken from <freetype/ftmodule.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:
| |||||||||||||||||||||
| 2. The FT_Module type | 2 FT_Module类型 | ||||||||||||||||||||
| The FT_Module type is a handle (i.e. a pointer) to a given module object/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, which are, as you could have guessed:
| |||||||||||||||||||||
| Helper modules use the base FT_ModuleRec type. We will describe these classes in the next chapters. |

