FreeType Glyph Conventions

From Mxtctp

Jump to: navigation, search

原文链接:http://www.freetype.org/freetype2/docs/glyphs/index.html
翻译人员:HappyLiu


英文 中文
FreeType Glyph Conventions

Version 2.1
Copyright 1998-2000 David Turner (david@freetype.org)
Copyright 2000 The FreeType Development Team (devel@freetype.org)

FreeType字形约定

版本2.1
版权所有 1998-2000 David Turner (david@freetype.org)
版权所有 2000 FreeType开发小组 (devel@freetype.org)

This document presents the core conventions used within the FreeType library to manage font and glyph data. It is a must-read for all developers who need to understand digital typography, especially if you want to use the FreeType 2 library in your projects.
Table of Contents

I. Basic Typographic Concepts

  1. Font files, format and information
  2. Character images and mappings
  3. Character and font metrics

II. Glyph outlines

  1. Pixels, points and device resolutions
  2. Vectorial representation
  3. Hinting and bitmap rendering

III. Glyph metrics

  1. Baseline, pens and layouts
  2. Typographic metrics and bounding boxes
  3. Bearings and advances
  4. The effects of grid-fitting
  5. Text widths and bounding box

IV. Kerning

  1. Kerning pairs
  2. Applying kerning

V. Text processing

  1. Writing simple text strings
  2. Sub-pixel positioning
  3. Simple kerning
  4. Right-to-left layouts
  5. Vertical layouts
  6. WYSIWYG text layouts

VI. FreeType Outlines

  1. FreeType outline description and structure
  2. Bounding and control box computations
  3. Coordinates, scaling, and grid-fitting

VII. FreeType bitmaps

  1. Vectorial versus pixel coordinates
  2. FreeType bitmap and pixmap descriptor
  3. Converting outlines into bitmaps and pixmaps
目录

一、基本印刷概念

  1. 字体文件、格式和信息
  2. 字符图像和映射
  3. 字符和字体度量

二、字形轮廓

  1. 象素、点和设备解析度
  2. 向量表示
  3. Hinting和位图渲染

三、字形度量

  1. 基线、笔和布局
  2. 印刷度量和边界框
  3. 跨距(bearing)和步进
  4. 网格对齐的效果
  5. 文本宽度和边界框

四、字距调整

  1. 字距调整对
  2. 应用字距调整

五、文本处理

  1. 书写简单文本串
  2. 子象素定位
  3. 简单字距调整
  4. 自右向左布局
  5. 垂直布局
  6. 所见即所得布局

六、FT轮廓

  1. FT轮廓描述和结构
  2. 边界和控制框计算
  3. 坐标、缩放和网格对齐

七、FT位图

  1. 向量坐标和象素坐标对比
  2. FT位图和象素图描述符
  3. 轮廓转换到位图和象素图
I. Basic typographic concepts 一、基本印刷概念
1. Font files, format and information 1、字体文件、格式和信息
A font is a collection of various character images that can be used to display or print text. The images in a single font share some common properties, including look, style, serifs, etc. Typographically speaking, one has to distinguish between a font family and its multiple font faces, which usually differ in style though come from the same template. 字体是一组可以被显示和打印的多样的字符图像,在单个字体中共享一些共有的特性,包括外表、风格、衬线等。按印刷领域的说法,它必须区别一个字体家族和多种字体外观,后者通常是从同样的模板而来,但是风格不同。
For example, "Palatino Regular" and "Palatino Italic" are two distinct faces from the same famous family, called "Palatino" itself. 例如,Palatino Regular 和 Palatino Italic是两种不同的外观,但是属于同样的家族Palatino。
The single term font is nearly always used in ambiguous ways to refer to either a given family or given face, depending on the context. For example, most users of word-processors use "font" to describe a font family (e.g. "Courier", "Palatino", etc.); however most of these families are implemented through several data files depending on the file format: For TrueType, this is usually one per face (i.e. arial.ttf for "Arial Regular", ariali.ttf for "Arial Italic", etc.). The file is also called a "font" but really contains a font face. 单个字体术语根据上下文既可以指家族也可指外观。例如,大多文字处理器的用户用字体指不同的字体家族,然而,大多这些家族根据它们的格式会通过多个数据文件实现。对于 TrueType来讲,通常是每个外观一个文件(arial.ttf对应Arial Regular外观,ariali.ttf对应Arial Italic外观)这个文件也叫字体,但是实际上只是一个字体外观。
A digital font is thus a data file that may contain one or more font faces. For each of these, it contains character images, character metrics, as well as other kind of information important to the layout of text and the processing of specific character encodings. In some awkward formats, like Adobe's Type 1, a single font face is described through several files (i.e. one contains the character images, another one the character metrics). We will ignore this implementation issue in most parts of this document and consider digital fonts as single files, though FreeType 2.0 is able to support multiple-files fonts correctly. 数字字体是一个可以包含一个和多个字体外观的数据文件,它们每个都包含字符图像、字符度量,以及其他各种有关文本布局和特定字符编码的重要信息。对有些难用的格式,像Adobe的Type1,一个字体外观由几个文件描述(一个包含字符映象,一个包含字符度量等)。在这里我们忽略这种情况,只考虑一个外观一个文件的情况,不过在FT2.0中,能够处理多文件字体。
As a convenience, a font file containing more than one face is called a font collection. This case is rather rare but can be seen in many Asian fonts, which contain images for two or more representation forms of a given scripts (usually for horizontal and vertical layout. 为了方便说明,一个包含多个外观的字体文件我们叫做字体集合,这种情况不多见,但是多数亚洲字体都是如此,它们会包含两种或多种表现形式的图像,例如横向和纵向布局。
2. Character images and mappings 2、字符图像和映射
The character images are called glyphs. A single character can have several distinct images, i.e. several glyphs, depending on script, usage or context. Several characters can also take a single glyph (good examples are Roman ligatures like "fi" and "fl" which can be represented by a single glyph). The relationships between characters and glyphs can be very complex, but won't be discussed in this document. Moreover, some formats use more or less awkward schemes to store and access glyphs. For the sake of clarity, we only retain the following notions when working with FreeType:
  • A font file contains a set of glyphs; each one can be stored as a bitmap, a vector representation or any other scheme (most scalable formats use a combination of mathematical representation and control data/programs). These glyphs can be stored in any order in the font file, and is typically accessed through a simple glyph index.
  • The font file contains one or more tables, called a character map (or charmap in short), which is used to convert character codes for a given encoding (e.g. ASCII, Unicode, DBCS, Big5, etc..) into glyph indices relative to the font file. A single font face may contain several charmaps. For example, most TrueType fonts contain an Apple-specific charmap as well as a Unicode charmap, which makes them usable on both Mac and Windows platforms.
字符图像叫做字形,根据书写、用法和上下文,单个字符能够有多个不同的图像,即多个字形。多个字符也可以有一个字形(例如Roman??)。字符和字形之间的关系可能是非常复杂,本文不多述。而且,多数字体格式都使用不太难用的方案存储和访问字形。为了清晰的原因,当说明FT时,保持下面的观念
  • 一个字体文件包含一组字形,每个字形可以存成位图、向量表示或其他结构(更可缩放的格式使用一种数学表示和控制数据/程序的结合方式)。这些字形可以以任意顺序存在字体文件中,通常通过一个简单的字形索引访问。
  • 字体文件包含一个或多个表,叫做字符映射,用来为某种字符编码将字符码转换成字形索引,例如ASCII、Unicode、Big5等等。单个字体文件可能包含多个字符映射,例如大多TrueType字体文件都会包含一个Apple特定的字符映射和Unicode字符映射,使它在Mac和 Windows平台都可以使用。
3. Character and font metrics 3、字符和字体度量
Each glyph image is associated with various metrics which are used to describe how must be placed and managed when rendering text. These are described in more details in section III, they relate to glyph placement, cursor advances as well as text layout. They are extremely important to compute the flow of text when rendering a string of text. 每个字符图像都关联多种度量,被用来在渲染文本时,描述如何放置和管理它们。在后面会有详述,它们和字形位置、光标步进和文本布局有关。它们在渲染一个文本串时计算文本流时非常重要。
Each scalable format also contains some global metrics, expressed in notional units, to describe some properties of all glyphs in the same face. Examples for global metrics are the maximum glyph bounding box, the ascender, descender and text height for the font. 每个可缩放的字体格式也包含一些全局的度量,用概念单位表示,描述同一种外观的所有字形的一些特性,例如最大字形外框,字体的上行字符、下行字符和文本高度等。
Though these metrics also exist for non-scalable formats, they only apply for a set of given character dimensions and resolutions, and are usually expressed in pixels then. 虽然这些度量也会存在于一些不可缩放格式,但它们只应用于一组指定字符维度和分辨率,并且通常用象素表示。
II. Glyph Outlines 二、字形轮廓
This section describes the way scalable representations of glyph images, called outlines, are used by FreeType as well as client applications.
1. Pixels, points and device resolutions 1、象素、点和设备解析度
Though it is a very common assumption when dealing with computer graphics programs, the physical dimensions of a given pixel (be it for screens or printers) are not squared. Often, the output device, be it a screen or printer, exhibits varying resolutions in both horizontal and vertical direction, and this must be taken care of when rendering text. 当处理计算机图形程序时,指定象素的物理尺寸不是正方的。通常,输出设备是屏幕或打印机,在水平和垂直方向都有多种分辨率,当渲染文本是要注意这些情况。
It is thus common to define a device's characteristics through two numbers expressed in dpi (dots per inch). For example, a printer with a resolution of 300x600 dpi has 300 pixels per inch in the horizontal direction, and 600 in the vertical one. The resolution of a typical computer monitor varies with its size (15" and 17" monitors don't have the same pixel sizes at 640x480), and of course the graphics mode resolution. 定义设备的分辨率通常使用用dpi(每英寸点(dot)数)表示的两个数,例如,一个打印机的分辨率为300x600dpi表示在水平方向,每英寸有 300 个象素,在垂直方向有600个象素。一个典型的计算机显示器根据它的大小,分辨率不同(15和17显示器对640x480象素大小不同),当然图形模式分辨率也不一样。
As a consequence, the size of text is usually given in points, rather than device-specific pixels. Points are a simple physical unit, where 1 point = 1/72th of an inch, in digital typography. As an example, most Roman books are printed with a body text whose size is somewhere between 10 and 14 points. 所以,文本的大小通常用点(point)表示,而不是用设备特定的象素。点是一种简单的物理单位,在数字印刷中,一点等于1/72英寸。例如,大多罗马书籍使用10到14点大小印刷文字内容。
It is thus possible to compute the size of text in pixels from the size in points with the following formula:
pixel_size = point_size * resolution / 72
可以用点数大小来计算象素数,公式如下:
象素数 = 点数 * 分辨率 / 72
The resolution is expressed in dpi. Since horizontal and vertical resolutions may differ, a single point size usually defines a different text width and height in pixels. 分辨率用dpi表示,因为水平和垂直分辨率可以不同,单个点数通常定义不同象素文本宽度和高度。
Unlike what is often thought, the "size of text in pixels" is not directly related to the real dimensions of characters when they are displayed or printed. The relationship between these two concepts is a bit more complex and relate to some design choices made by the font designer. This is described in more detail in the next sub-section (see the explanations on the EM square).
2. Vectorial representation 2、向量表示
The source format of outlines is a collection of closed paths called contours. Each contour delimits an outer or inner region of the glyph, and can be made of either line segments or Bézier arcs. 字体轮廓的源格式是一组封闭的路径,叫做轮廓线。每个轮廓线划定字形的外部或内部区域,它们可以是线段或是Bezier曲线。
The arcs are defined through control points, and can be either second-order (these are conic Béziers) or third-order (cubic Béziers) polynomials, depending on the font format. Note that conic Béziers are usually called quadratic Béziers in the literature. Hence, each point of the outline has an associated flag indicating its type (normal or control point). And scaling the points will scale the whole outline. 曲线通过控制点定义,根据字体格式,可以是二次(conic Beziers)或三次(cubic Beziers)多项式。在文献中,conic Bezier通常称为quadratic Beziers。因此,轮廓中每个点都有一个标志表示它的类型是一般还是控制点,缩放这些点将缩放整个轮廓。
Each glyph's original outline points are located on a grid of indivisible units. The points are usually stored in a font file as 16-bit integer grid coordinates, with the grid origin's being at (0,0); they thus range from -16384 to 16383. (Even though point coordinates can be floats in other formats such as Type 1, we will restrict our analysis to integer values for simplicity). 每个字形最初的轮廓点放置在一个不可分割单元的网格中,点通常在字体文件中以16位整型网格坐标存储,网格的原点在(0,0),它的范围是-16384到-16383(虽然有的格式如Type1使用浮点型,但为简便起见,我们约定用整型分析)。
The grid is always oriented like the traditional mathematical two-dimensional plane, i.e., the X axis from the left to the right, and the Y axis from bottom to top. 网格的方向和传统数学二维平面一致,x轴从左到右,y轴从下到上。
In creating the glyph outlines, a type designer uses an imaginary square called the EM square. Typically, the EM square can be thought of as a tablet on which the characters are drawn. The square's size, i.e., the number of grid units on its sides, is very important for two reasons:
  • It is the reference used to scale the outlines to a given text dimension. For example, a size of 12pt at 300x300 dpi corresponds to 12*300/72 = 50 pixels. This is the size the EM square would appear on the output device if it was rendered directly. In other words, scaling from grid units to pixels uses the formula:
pixel_size = point_size * resolution / 72
pixel_coord = grid_coord * pixel_size / EM_size
  • The greater the EM size is, the larger resolution the designer can use when digitizing outlines. For example, in the extreme example of an EM size of 4 units, there are only 25 point positions available within the EM square which is clearly not enough. Typical TrueType fonts use an EM size of 2048 units; Type 1 PostScript fonts have a fixed EM size of 1000 grid units but point coordinates can be expressed as floating values.
在创建字形轮廓时,一个字体设计者使用一个假想的正方形,叫做EM正方形。他可以想象成一个画字符的平面。正方形的大小,即它边长的网格单元是很重要的,原因是
  • 它是用来将轮廓缩放到指定文本尺寸的参考,例如在300x300dpi中的12pt大小对应12*300/72=50象素。从网格单元缩放到象素可以使用下面的公式
象素数 = 点数 * 分辨率 / 72
象素坐标 = 网格坐标 * 象素数 / EM大小
  • EM尺寸越大,可以达到更大的分辨率,例如一个极端的例子,一个4单元的EM,只有25个点位置,显然不够,通常TrueType字体之用2048单元的EM;Type1 PostScript字体有一个固定1000网格单元的EM,但是点坐标可以用浮点值表示。
Note that glyphs can freely extend beyond the EM square if the font designer wants so. The EM is used as a convenience, and is a valuable convenience from traditional typography. 注意,字形可以自由超出EM正方形。
Grid units are very often called font units or EM units. 网格单元通常交错字体单元或EM单元。
As said before, pixel_size computed in the above formula does not relate directly to the size of characters on the screen. It simply is the size of the EM square if it was to be displayed. Each font designer is free to place its glyphs as it pleases him within the square. This explains why the letters of the following text have not the same height, even though they are displayed at the same point size with distinct fonts:

Comparison of font heights

上边的象素数并不是指实际字符的大小,而是EM正方形显示的大小,所以不同字体,虽然同样大小,但是它们的高度可能不同。
As one can see, the glyphs of the Courier family are smaller than those of Times New Roman, which themselves are slightly smaller than those of Arial, even though everything is displayed or printed at a size of 16 points. This only reflects design choices.
3. Hinting and Bitmap rendering 3、Hinting和位图渲染
The outline as stored in a font file is called the "master" outline, as its points coordinates are expressed in font units. Before it can be converted into a bitmap, it must be scaled to a given size/resolution. This is done through a very simple transformation, but always creates undesirable artifacts, e.g. stems of different widths or heights in letters like "E" or "H". 存储在一个字体文件中的轮廓叫"主"轮廓,它的点坐标用字体单元表示,在它被转换成一个位图时,它必须缩放至指定大小。这通过一个简单的转换完成,但是总会产生一些不想要的副作用,例如像字母E和H,它们主干的宽度和高度会不相同。
As a consequence, proper glyph rendering needs the scaled points to be aligned along the target device pixel grid, through an operation called grid-fitting (often called hinting). One of its main purposes is to ensure that important widths and heights are respected throughout the whole font (for example, it is very often desirable that the "I" and the "T" have their central vertical line of the same pixel width), as well as to manage features like stems and overshoots, which can cause problems at small pixel sizes. 所以,优秀的字形渲染过程在缩放"点"是,需要通过一个网格对齐(grid-fitting)的操作(通常叫hinting),将它们对齐到目标设备的象素网格。这主要目的之一是为了确保整个字体中,重要的宽度和高度能够一致。例如对于字符I和T来说,它们那个垂直笔划要保持同样象素宽度。另外,它的目的还有管理如stem和overshoot的特性,这在小象素字体会引起一些问题。
There are several ways to perform grid-fitting properly; most scalable formats associate some control data or programs with each glyph outline. Here is an overview:
  • explicit grid-fitting
The TrueType format defines a stack-based virtual machine, for which programs can be written with the help of more than 200 opcodes (most of these relating to geometrical operations). Each glyph is thus made of both an outline and a control program to perform the actual grid-fitting in the way defined by the font designer.
  • implicit grid-fitting (also called hinting)
The Type 1 format takes a much simpler approach: Each glyph is made of an outline as well as several pieces called hints which are used to describe some important features of the glyph, like the presence of stems, some width regularities, and the like. There aren't a lot of hint types, and it is up to the final renderer to interpret the hints in order to produce a fitted outline.
  • automatic grid-fitting
Some formats simply include no control information with each glyph outline, apart font metrics like the advance width and height. It is then up to the renderer to "guess" the more interesting features of the outline in order to perform some decent grid-fitting.
有若干种方式来处理网格对齐,多数可缩放格式中,每种字形轮廓都有一些控制数据和程序。
  • 显式网格对齐
TrueType格式定义了一个基于栈的虚拟机(VM),可以借助多于200中操作码(大多是几何操作)来编写程序,每个字形都由一个轮廓和一个控制程序组成,后者可以处理实际的网格对齐,他由字体设计者定义。
  • 隐式网格对齐(也叫hinting)
Type1格式有一个更简单的方式,每个字形由一个轮廓以及若干叫hints的片断组成,后者用来描述字形的某些重要特性,例如主干的存在、某些宽度匀称性等诸如此类。没有多少种hint,要看渲染器如何解释hint来产生一个对齐的轮廓。
  • 自动网格对齐
有些格式很简单,没有包括控制信息,将字体度量如步进、宽度和高度分开。要靠渲染器来猜测轮廓的一些特性来实现得体的网格对齐。
The following table summarises the pros and cons of each scheme.
grid-fitting scheme advantages disadvantages
explicit Quality. Excellent results at small sizes are possible. This is very important for screen display.

Consistency. All renderers produce the same glyph bitmaps.

Speed. Intepreting bytecode can be slow if the glyph programs are complex.

Size. Glyph programs can be long.

Technical difficulty. It is extremely difficult to write good hinting programs. Very few tools available.

implicit Size. Hints are usually much smaller than explicit glyph programs.

Speed. Grid-fitting is usually a fast process.

Quality. Often questionable at small sizes. Better with anti-aliasing though.

Inconsistency. Results can vary between different renderers, or even distinct versions of the same engine.

automatic Size. No need for control information, resulting in smaller font files.

Speed. Depends on the grid-fitting algorithm. Usually faster than explicit grid-fitting.

Quality. Often questionable at small sizes. Better with anti-aliasing though.

Speed. Depends on the grid-fitting algorithm.

Inconsistency. Results can vary between different renderers, or even distinct versions of the same engine.

下面总结了每种方案的优点和缺点
方案 优点 缺点
显式 质量:对小字体有很好的结果,这对屏幕显示非常重要。

一致性:所有渲染器产生同样的字形位图。

速度:如果程序很复杂,解释字节码很慢

大小:字形程序会很长。

技术难度:编写优秀的hinting程序非常难,没有好的工具支持。

隐式 大小:Hint通常比显式字形程序小的多

速度:网格对齐会非常快

质量:小字体不好,最后结合反走样

不一致:不同渲染器结果不同,甚至同一引擎不同版本也不同。

自动 大小:不需要控制信息,导致更小的字体文件

速度:依赖对齐算法,通常比显式对齐快。

质量:小字体不好,最后结合反走样

速度:依赖算法

不一致:不同渲染器结果不同,甚至同一引擎不同版本也不同。

III. Glyph metrics 三、字形度量
1. Baseline, pens and layouts 1、基线、笔和布局
The baseline is an imaginary line that is used to "guide" glyphs when rendering text. It can be horizontal (e.g. Roman, Cyrillic, Arabic, etc.) or vertical (e.g. Chinese, Japanese, Korean, etc). Moreover, to render text, a virtual point, located on the baseline, called the pen position or origin, is used to locate glyphs. 基线是一个假想的线,用来在渲染文本时知道字形,它可以是水平(如Roman)和是垂直的(如中文)。而且,为了渲染文本,在基线上有一个虚拟的点,叫做笔位置(pen position)或原点(origin),他用来定位字形。
Each layout uses a different convention for glyph placement:
  • With horizontal layout, glyphs simply "rest" on the baseline. Text is rendered by incrementing the pen position, either to the right or to the left.
The distance between two successive pen positions is glyph-specific and is called the advance width. Note that its value is always positive, even for right-to-left oriented alphabets, like Arabic. This introduces some differences in the way text is rendered.
The pen position is always placed on the baseline.
horizontal layout
  • With a vertical layout, glyphs are centered around the baseline:
vertical layout
每种布局使用不同的规约来放置字形:
  • 对水平布局,字形简单地搁在基线上,通过增加笔位置来渲染文本,既可以向右也可以向左增加。
两个相邻笔位置之间的距离是根据字形不同的,叫做步进宽度(advance width)。注意这个值总是正数,即使是从右往左的方向排列字符,如Arabic。这和文本渲染的方式有些不同。
笔位置总是放置在基线上。
  • 对垂直布局,字形在基线上居中放置:
2. Typographic metrics and bounding boxes 2、印刷度量和边界框
A various number of face metrics are defined for all glyphs in a given font.
  • Ascent
The distance from the baseline to the highest/upper grid coordinate used to place an outline point. It is a positive value, due to the grid's orientation with the Y axis upwards.
  • Descent
The distance from the baseline to the lowest grid coordinate used to place an outline point. This is a negative value, due to the grid's orientation.
  • Linegap
The distance that must be placed between two lines of text. The baseline-to-baseline distance should be computed as:
ascent - descent + linegap
if you use the typographic values.
在指定字体中,定义了多种外观度量。
  • 上行高度(ascent)。
从基线到放置轮廓点最高/上的网格坐标,因为Y轴方向是向上的,所以它是一个正值。
  • 下行高度(descent)。
从基线到放置轮廓点最低/下的网格坐标,因为Y轴方向是向上的,所以它是一个负值。
  • 行距(linegap)。
两行文本间必须的距离,基线到基线的距离应该计算成
上行高度 - 下行高度 + 行距
Other, simpler metrics are:
  • The glyph's bounding box, also called bbox
This is an imaginary box that encloses all glyphs from the font, usually as tightly as possible. It is represented by four fields, namely xMin, yMin, xMax, and yMax, that can be computed for any outline. Their values can be in font units (if measured in the original outline) or in fractional/integer pixel units (when measured on scaled outlines).
Note that if it wasn't for grid-fitting, you wouldn't need to know a box's complete values, but only its dimensions to know how big is a glyph outline/bitmap. However, correct rendering of hinted glyphs needs the preservation of important grid alignment on each glyph translation/placement on the baseline.
  • Internal leading
This concept comes directly from the world of traditional typography. It represents the amount of space within the leading which is reserved for glyph features that lay outside of the EM square (like accentuation). It usually can be computed as:
internal leading = ascent - descent - EM_size
  • External leading
This is another name for the line gap.
  • 边界框(bounding box,bbox)。
这是一个假想的框子,他尽可能紧密的装入字形。通过四个值来表示,叫做xMin、yMin、xMax、yMax,对任何轮廓都可以计算,它们可以是字体单元(测量原始轮廓)或者整型象素单元(测量已缩放的轮廓)。
注意,如果不是为了网格对齐,你无需知道这个框子的这个值,只需知道它的大小即可。但为了正确渲染一个对齐的字形,需要保存每个字形在基线上转换、放置的重要对齐。
  • 内部leading。
这个概念从传统印刷业而来,他表示字形出了EM正方形空间数量,通常计算如下
internal leading = ascent - descent - EM_size
  • 外部leading。
行距的别名。
3. Bearings and Advances 3、跨距(bearing)和步进
Each glyph has also distances called bearings and advances. Their definition is constant, but their values depend on the layout, as the same glyph can be used to render text either horizontally or vertically:
  • Left side bearing or bearingX
The horizontal distance from the current pen position to the glyph's left bbox edge. It is positive for horizontal layouts, and in most cases negative for vertical ones.
  • Top side bearing or bearingY
The vertical distance from the baseline to the top of the glyph's bbox. It is usually positive for horizontal layouts, and negative for vertical ones.
  • Advance width or advanceX
The horizontal distance the pen position must be incremented (for left-to-right writing) or decremented (for right-to-left writing) by after each glyph is rendered when processing text. It is always positive for horizontal layouts, and null for vertical ones.
  • Advance height advanceY
The vertical distance the pen position must be decremented by after each glyph is rendered. It is always null for horizontal layouts, and positive for vertical layouts.
  • Glyph width
The glyph's horizontal extent. For unscaled font coordinates, it is bbox.xMax-bbox.xMin. For scaled glyphs, its computation requests specific care, described in the grid-fitting chapter below.
  • Glyph height
The glyph's vertical extent. For unscaled font coordinates, it is bbox.yMax-bbox.yMin. For scaled glyphs, its computation requests specific care, described in the grid-fitting chapter below.
  • Right side bearing
Only used for horizontal layouts to describe the distance from the bbox's right edge to the advance width. It is in most cases a non-negative number:
advance_width - left_side_bearing - (xMax-xMin)
每个字形都有叫跨距和步进的距离,它们的定义是常量,但是它们的值依赖布局,同样的字形可以用来渲染横向或纵向文字。
  • 左跨距或bearingX。
从当前笔位置到字形左bbox边界的水平距离,对水平布局是正数,对垂直布局大多是负值。
  • 上跨距或bearingY。
从基线到bbox上边界的垂直距离,对水平布局是正值,对垂直布局是负值。
  • 步进宽度或advanceX。
当处理文本渲染一个字形后,笔位置必须增加(从左向右)或减少(从右向左)的水平距离。对水平布局总是正值,垂直布局为null。
  • 步进高度或advanceY。
当每个字形渲染后,笔位置必须减少的垂直距离。对水平布局为null,对垂直布局总是正值。
  • 字形宽度。
字形的水平长度。对未缩放的字体坐标,它是bbox.xMax-bbox.xMin,对已缩放字形,它的计算要看特定情况,视乎不同的网格对齐而定。
  • 字形高度。
字形的垂直长度。对未缩放的字体坐标,它是bbox.yMax-bbox.yMin,对已缩放字形,它的计算要看特定情况,视乎不同的网格对齐而定。
  • 右跨距。
只用于水平布局,描述从bbox右边到步进宽度的距离,通常是一个非负值。
advance_width - left_side_bearing - (xMax-xMin)
Here is a picture giving all the details for horizontal metrics:
horizontal glyph metrics
下图是水平布局所有的度量
And here is another one for the vertical metrics:
vertical glyph metrics
下图是垂直布局的度量
4. The effects of grid-fitting 4、网格对齐的效果
Because hinting aligns the glyph's control points to the pixel grid, this process slightly modifies the dimensions of character images in ways that differ from simple scaling. 因为hinting将字形的控制点对齐到象素网格,这个过程将稍稍修改字符图像的尺寸,和简单的缩放有所区别。
For example, the image of the lowercase "m" letter sometimes fits a square in the master grid. However, to make it readable at small pixel sizes, hinting tends to enlarge its scaled outline in order to keep its three legs distinctly visible, resulting in a larger character bitmap. 例如,小写字母m的图像在主网格中有时是一个正方形,但是为了使它在小象素大小情况下可以辨别,hinting试图扩大它已缩放轮廓,以让它三条腿区分开来,这将导致一个更大的字符位图。
The glyph metrics are also influenced by the grid-fitting process:
  • The image's width and height are altered. Even if this is only by one pixel, it can make a big difference at small pixel sizes.
  • The image's bounding box is modified, thus modifying the bearings.
  • The advances must be updated. For example, the advance width must be incremented if the hinted bitmap is larger than the scaled one, to reflect the augmented glyph width.
字形度量也会受网格对齐过程的影响:
  • 图像的宽度和高度改变了,即使只是一个象素,对于小象素大小字形区别都很大;
  • 图像的边界框改变了,也改变了跨距;
  • 步进必须更改,例如如果被hint的位图比缩放的位图大时,必须增加步进宽度,来反映扩大的字形宽度。
This has some implications:
  • Because of hinting, simply scaling the font ascent or descent might not give correct results. A possible solution is to keep the ceiling of the scaled ascent, and floor of the scaled descent.
  • There is no easy way to get the hinted glyph and advance widths of a range of glyphs, as hinting works differently on each outline. The only solution is to hint each glyph separately and record the returned values. Some formats, like TrueType, even include a table of pre-computed values for a small set of common character pixel sizes.
  • Hinting depends on the final character width and height in pixels, which means that it is highly resolution-dependent. This property makes correct WYSIWYG layouts difficult to implement.
这有一些含义如下,
  • 因为hinting,简单缩放字体上行或下行高度可能不会有正确的结果,一个可能的方法时保持被缩放上行高度的顶和被缩放下行高度的底。
  • 没有容易的方法去hint一个范围内字形并步进它们宽度,因为hinting对每个轮廓工作都不一样。唯一的方法时单独hint每个字形,并记录返回值。有些格式,如TrueType,包含一些表对一些通用字符预先计算出它们的象素大小。
  • hinting依赖最终字符宽度和高度的象素值,意味着它非常依赖分辨率,这个特性使得正确的所见即所得布局非常难以实现。
Performing 2D transformations on glyph outlines is very easy with FreeType. However, when using translation on a hinted outlines, one should aways take care of exclusively using integer pixel distances (which means that the parameters to the FT_Outline_Translate() API should all be multiples of 64, as the point coordinates are in 26.6 fixed float format). 在FT 中,对字形轮廓处理2D变换很简单,但是对一个已hint的轮廓,需要注意专有地使用整型象素距离(意味着FT_Outline_Translate() 函数的参数应该都乘以64,因为点坐标都是26.6固定浮点格式)。
Otherwise, the translation will simply ruin the hinter's work, resulting in a very low quality bitmaps! 否则,变换将破坏hinter的工作,导致非常难看的位图。
5. Text widths and bounding box 5、文本宽度和边界框
As seen before, the "origin" of a given glyph corresponds to the position of the pen on the baseline. It is not necessarily located on one of the glyph's bounding box corners, unlike many typical bitmapped font formats. In some cases, the origin can be out of the bounding box, in others, it can be within it, depending on the shape of the given glyph. 如上所示,指定字形的原点对应基线上笔的位置,没有必要定位字形边界框的某个角,这不像多数典型的位图字体格式。有些情况,原点可以在边界框的外边,有时,也可以在里边,这要看给定的字形外形了。
Likewise, the glyph's "advance width" is the increment to apply to the pen position during layout, and is not related to the glyph's "width", which really is the glyph's bounding width. 同样,字形的步进宽度是在布局时应用于笔位置的增量,而不是字形的宽度,那是字形边界的宽度。
The same conventions apply to strings of text. This means that:
  • The bounding box of a given string of text doesn't necessarily contain the text cursor, nor is the latter located on one of its corners.
  • The string's advance width isn't related to its bounding box dimensions. Especially if it contains beginning and terminal spaces or tabs.
  • Finally, additional processing like kerning creates strings of text whose dimensions are not directly related to the simple juxtaposition of individual glyph metrics. For example, the advance width of "VA" isn't the sum of the advances of "V" and "A" taken separately.
对文本串,具有相同的规约,这意味着:
  • 指定文本串的边界框没有必要包含文本光标,也不需要后边的字形放置在它的角上。
  • 字符串的步进宽度和它的边界框大小无关,特别时它在开始和最后包含空格或tab。
  • 最后,附加的处理如间距调整能够创建文本串,它的大小不直接依赖单独字形度量并列排列。例如,VA的步进宽度不是V和A各自的步进之和。
IV. Kerning 四、字距调整
The term kerning refers to specific information used to adjust the relative positions of coincident glyphs in a string of text. This section describes several types of kerning information, as well as the way to process them when performing text layout. 字距调整这个术语指用来在一个文本串中调整重合字形的相对位置的特定信息。
1. Kerning pairs 1、字距调整对
Kerning consists of modifying the spacing between two successive glyphs according to their outlines. For example, a "T" and a "y" can be easily moved closer, as the top of the "y" fits nicely under the upper right bar of the "T". 字距调整包括根据相邻字形的轮廓修改它们之间的距离。例如T和y可以贴得更近一点,因为y的上缘正好在T的右上角一横的下边。
When laying out text with only their standard widths, some consecutive glyphs seem a bit too close or too distant. For example, the space between the "A" and the "V" in the following word seems a little wider than needed.
the word 'bravo' unkerned
当仅仅根据字形的标准宽度来布局文本,一些连续的字符看上去有点太挤和太松,例如下图中A和V的就显得距离太远。
Compare this to the same word, where the distance between these two letters has been slightly reduced:
the word 'bravo' with kerning
比较一下下图,同样的单词,A和V的距离拉近些
As you can see, this adjustment can make a great difference. Some font faces thus include a table containing kerning distances for a set of given glyph pairs for text layout.
  • The pairs are ordered, i.e., the space for pair (A,V) isn't necessarily the space for pair (V,A). They also index glyphs, and not characters.
  • Kerning distances can be expressed in horizontal or vertical directions, depending on layout and/or script. For example, some horizontal layouts like Arabic can make use of vertical kerning adjustments between successive glyphs. A vertical script can have vertical kerning distances.
  • Kerning distances are expressed in grid units. They are usually oriented in the X axis, which means that a negative value indicates that two glyphs must be set closer in a horizontal layout.
可以看到,这个调整可以导致很大的区别。有的字体外观包含一个表,它包含文本布局所需的指定字形对的字距距离。
  • 这个对是顺序的,AV对的距离和VA对不一定一致;
  • 依据布局或书写,字距可以表示水平或垂直方向。
  • 字距表示成网格单元,它们通常是X轴方向的,意味着负值表示两个字形需要在水平方向放的更近一点。
2. Applying kerning 2、应用字距调整
Applying kerning when rendering text is a rather easy process. It merely consists in adding the scaled kern distance to the pen position before writing each next glyph. However, the typographically correct renderer must take a few more details in consideration. 在渲染文本时应用字据调整是一个比较简单的过程,只需要在写下一个字形时,将缩放的字距加到笔位置即可。然而,正确的渲染器要考虑的更细一点。
The "sliding dot" problem is a good example: Many font faces include a kerning distance between capital letters like "T" or "F" and a following dot ("."), in order to slide the latter glyph just right to their main leg:
example for sliding dots
"滑动点"问题是一个很好的例子:很多字体外观包括一个大写字符(如T、F)和一个点.之间的字距调整,以将点正好放置在前者的主腿的右侧。
This sometimes requires additional adjustments between the dot and the letter following it, depending on the shapes of the enclosing letters. When applying "standard" kerning adjustments, the previous sentence would become:
example for too much kerning
根据字符的外形,有时候需要在点和随后的字符间作附加的调整,当应用"标准"的字距调整,上面的句子如下
This is clearly too contracted. The solution here, as exhibited in the first example, is to only slide the dots when possible. Of course, this requires a certain knowledge of the text's meaning. The above adjustments would not necessarily be welcome if we were rendering the final dot of a given paragraph. 这显然太紧凑了。一个方案是,只在需要时滑动点,当然这需要对文本的意思有了解。如果当我们在渲染特定段落的最后一个点时,上面的调整就不适合了。
This is only one example, and there are many others showing that a real typographer is needed to layout text properly. If not available, some kind of user interaction or tagging of the text could be used to specify some adjustments, but in all cases, this requires some support in applications and text libraries. 这只是一个例子,还有很多其他例子显示一个真正的印刷工人需要恰当地布局文本。
For more mundane and common uses, however, we can have a very simple algorithm, which avoids the sliding dot problem, and others, though not producing optimal results. It can be seen as
  1. Place the first glyph on the baseline.
  2. Save the location of the pen position/origin in pen1.
  3. Adjust the pen position with the kerning distance between the first and second glyph.
  4. Place the second glyph and compute the next pen position/origin in pen2.
  5. Use pen1 as the next pen position if it is beyond pen2, use pen2 otherwise.
有一个很简单地算法,可以避免滑动点问题。
  1. 在基线上放置第一个字形;
  2. 将笔位置保存到pen1;
  3. 根据第一个和第二个字形的字距距离调整笔位置;
  4. 放置第二个字形,并计算下个笔位置,放到pen2;
  5. 如果pen1大于pen2,使用pen1作为下个笔位置,否则使用pen2。
V. Text processing 五、文本处理
This section demonstrates how to use the concepts previously defined to render text, whatever the layout you use.
1. Writing simple text strings 1、书写简单文本串
In this first example, we will generate a simple string of Roman text, i.e. with a horizontal left-to-right layout. Using exclusively pixel metrics, the process looks like:
  1. Convert the character string into a series of glyph indices.
  2. Place the pen to the cursor position.
  3. Get or load the glyph image.
  4. Translate the glyph so that its 'origin' matches the pen position.
  5. Render the glyph to the target device.
  6. Increment the pen position by the glyph's advance width in pixels.
  7. Start over at step&nbsp3 for each of the remaining glyphs.
  8. When all glyphs are done, set the text cursor to the new pen position.

Note that kerning isn't part of this algorithm.

在第一个例子中,我们将生成一个简单的Roman文字串,即采用水平的自左向右布局,使用专有的象素度量,这个过程如下:
  1. 将字符串转换成一系列字形索引;
  2. 将笔放置在光标位置;
  3. 获得或装入字形图像;
  4. 平移字形以使它的原点匹配笔位置;
  5. 将字形渲染到目标设备;
  6. 根据字形的步进象素增加笔位置;
  7. 对剩余的字形进行第三步;
  8. 当所有字形都处理了,在新的笔位置设置文本光标。

注意字距调整不在这个算法中。

2. Sub-pixel positioning 2、子象素定位
It is somewhat useful to use sub-pixel positioning when rendering text. This is crucial, for example, to provide semi-WYSIWYG text layouts. Text rendering is very similar to the algorithm described in subsection 1, with the following few differences:
  • The pen position is expressed in fractional pixels.
  • Because translating a hinted outline by a non-integer distance will ruin its grid-fitting, the position of the glyph origin must be rounded before rendering the character image.
  • The advance width is expressed in fractional pixels, and isn't necessarily an integer.
在渲染文本时使用子象素定位有时很有用。这非常重要,例如为了提供半所见即所得的文本布局,文本渲染的算法和上一节很相似,但是有些区别:
  • 笔位置表示成小数形式的象素;
  • 因为将一个已经hint过的轮廓平移一个非整型距离将破坏网格对齐,字形原点的位置在渲染字符图像前必须取整;
  • 步进宽度表示成小数形式的象素,没有必要是整型。
Here an improved version of the algorithm:
  1. Convert the character string into a series of glyph indices.
  2. Place the pen to the cursor position. This can be a non-integer point.
  3. Get or load the glyph image.
  4. Translate the glyph so that its "origin" matches the rounded pen position.
  5. Render the glyph to the target device.
  6. Increment the pen position by the glyph's advance width in fractional pixels.
  7. Start over at step 3 for each of the remaining glyphs.
  8. When all glyphs are done, set the text cursor to the new pen position.

Note that with fractional pixel positioning, the space between two given letters isn't fixed, but determined by the accumulation of previous rounding errors in glyph positioning.

这里是算法的改进版本:
  1. 将字符串转换成一系列字形索引;
  2. 将笔放置在光标位置,这可以是一个非整型点;
  3. 获得或装入字形图像;
  4. 平移字形以使它的原点匹配取整后的笔位置;
  5. 将字形渲染到目标设备;
  6. 根据字形的步进象素宽度增加笔位置,这个宽度可以是小数形式;
  7. 对剩余的字形进行第三步;
  8. 当所有字形都处理了,在新的笔位置设置文本光标。

注意使用小数象素定位后,两个指定字符间的空间将不是固定的,它右先前的取整操作堆积的数决定。

3. Simple kerning 3、简单字距调整
Adding kerning to the basic text rendering algorithm is easy: When a kerning pair is found, simply add the scaled kerning distance to the pen position before step 4. Of course, the distance should be rounded in the case of algorithm 1, though it doesn't need to for algorithm 2. This gives us: 在基本文本渲染算法上增加字距调整非常简单,当一个字距调整对发现了,简单地在第4步前,将缩放后的调整距离增加到笔位置即可。当然,这个距离在算法1需要被取整,算法2不必要。
Algorithm 1 with kerning:
  1. Convert the character string into a series of glyph indices.
  2. Place the pen to the cursor position.
  3. Get or load the glyph image.
  4. Add the rounded scaled kerning distance, if any, to the pen position.
  5. Translate the glyph so that its "origin" matches the pen position.
  6. Render the glyph to the target device.
  7. Increment the pen position by the glyph's advance width in pixels.
  8. Start over at step 3 for each of the remaining glyphs.
Algorithm 2 with kerning:
  1. Convert the character string into a series of glyph indices.
  2. Place the pen to the cursor position.
  3. Get or load the glyph image.
  4. Add the scaled unrounded kerning distance, if any, to the pen position.
  5. Translate the glyph so that its "origin" matches the rounded pen position.
  6. Render the glyph to the target device.
  7. Increment the pen position by the glyph's advance width in fractional pixels.
  8. Start over at step 3 for each of the remaining glyphs.
Of course, the algorithm described in section IV can also be applied to prevent the sliding dot problem if one wants to.
4. Right-to-left layout 4、自右向左布局
The process of laying out Arabic or Hebrew text is extremely similar. The only difference is that the pen position must be decremented before the glyph rendering (remember: the advance width is always positive, even for Arabic glyphs). 布局Arabic或Heberw文字的过程非常相似,区别只是在字形渲染前,笔位置需要减少(记住步进宽度总是正值)
Right-to-left algorithm 1:
  1. Convert the character string into a series of glyph indices.
  2. Place the pen to the cursor position.
  3. Get or load the glyph image.
  4. Decrement the pen position by the glyph's advance width in pixels.
  5. Translate the glyph so that its "origin" matches the pen position.
  6. Render the glyph to the target device.
  7. Start over at step 3 for each of the remaining glyphs.
The changes to algorithm 2, as well as the inclusion of kerning are left as an exercise to the reader.
5. Vertical layouts 5、垂直布局
Laying out vertical text uses exactly the same processes, with the following significant differences:
  • The baseline is vertical, and the vertical metrics must be used instead of the horizontal one.
  • The left bearing is usually negative, but this doesn't change the fact that the glyph origin must be located on the baseline.
  • The advance height is always positive, so the pen position must be decremented if one wants to write top to bottom (assuming the Y axis is oriented upwards).
布局垂直文字也是同样的过程,重要的区别如下:
  • 基线是垂直的,使用垂直的度量而不是水平度量;
  • 左跨距通常是负的,但字形原点必须在基线上;
  • 步进高度总是正值,所以笔位置必须减少以从上至下书写;
Here the algorithm:
  1. Convert the character string into a series of glyph indices.
  2. Place the pen to the cursor position.
  3. Get or load the glyph image.
  4. Translate the glyph so that its "origin" matches the pen position.
  5. Render the glyph to the target device.
  6. Decrement the vertical pen position by the glyph's advance height in pixels.
  7. Start over at step 3 for each of the remaining glyphs.
  8. When all glyphs are done, set the text cursor to the new pen position.
6. WYSIWYG text layouts 6、所见即所得布局
As you probably know, the acronym WYSIWYG stands for "What You See Is What You Get". Basically, this means that the output of a document on the screen should match "perfectly" its printed version. A true WYSIWYG system requires two things:
  • device-independent text layout
This means that the document's formatting is the same on the screen than on any printed output, including line breaks, justification, ligatures, fonts, position of inline images, etc.
  • matching display and print character sizes
The displayed size of a given character should match its dimensions when printed. For example, a text string which is exactly 1 inch tall when printed should also appear 1 inch tall on the screen (when using a scale of 100%).
It is clear that matching sizes cannot be possible if the computer has no knowledge of the physical resolutions of the display device(s) it is using. And of course, this is the most common case! That is not too unfortunate, however, because most users really don't care about this feature. Legibility is much more important.
When the Mac appeared, Apple decided to choose a resolution of 72 dpi to describe the Macintosh screen to the font sub-system (whatever the monitor used). This choice was most probably driven by the fact that, at this resolution, 1 point equals exactly 1 pixel. However, it neglected one crucial fact: As most users tend to choose a document character size between 10 and 14 points, the resultant displayed text was rather small and not too legible without scaling. Microsoft engineers took notice of this problem and chose a resolution of 96 dpi on Windows, which resulted in slightly larger, and more legible, displayed characters (for the same printed text size).
These distinct resolutions explain some differences when displaying text at the same character size on a Mac and a Windows machine. Moreover, it is not unusual to find some TrueType fonts with enhanced hinting (technical note: through delta-hinting) for the sizes of 10, 12, 14 and 16 points at 96 dpi.
The term device-independent text is, unfortunately, often abused. For example, many word processors, including MS Word, do not really use device-independent glyph positioning algorithms when laying out text. Rather, they use the target printer's resolution to compute hinted glyph metrics for the layout. Though it guarantees that the printed version is always the "nicest" it can be, especially for very low resolution printers (like dot-matrix), it has a very sad effect: Changing the printer can have dramatic effects on the whole document layout, especially if it makes strong use of justification, uses few page breaks, etc.
Because glyph metrics vary slightly when the resolution changes (due to hinting), line breaks can change enormously, when these differences accumulate over long runs of text. Try for example printing a very long document (with no page breaks) on a 300 dpi ink-jet printer, then the same one on a 3000 dpi laser printer: You will be extremely lucky if your final page count didn't change between the prints! Of course, we can still call this WYSIWYG, as long as the printer resolution is fixed.
Some applications, like Adobe Acrobat, which targeted device-independent placement from the start, do not suffer from this problem. There are two ways to achieve this: either use the scaled and unhinted glyph metrics when laying out text both in the rendering and printing processes, or simply use whatever metrics you want and store them with the text in order to get sure they are printed the same on all devices (the latter being probably the best solution, as it also enables font substitution without breaking text layouts).
Just like matching sizes, device-independent placement isn't necessarily a feature that most users want. However, it is pretty clear that for any kind of professional document processing work, it is a requirement.
VI. FreeType outlines 六、FT轮廓
The purpose of this section is to present the way FreeType manages vectorial outlines, as well as the most common operations that can be applied on them.
1. FreeType outline description and structure 1、FT轮廓描述和结构
a. Outline curve decomposition a. 轮廓曲线分解
An outline is described as a series of closed contours in the 2D plane. Each contour is made of a series of line segments and Bézier arcs. Depending on the file format, these can be second-order or third-order polynomials. The former are also called quadratic or conic arcs, and they are used in the TrueType format. The latter are called cubic arcs and are mostly used in the Type 1 format. 一个轮廓是2D平面上一系列封闭的轮廓线。每个轮廓线由一系列线段和Bezier弧组成,根据文件格式不同,曲线可以是二次和三次多项式,前者叫quadratic或conic弧,它们在TrueType格式中用到,后者叫cubic弧,多数用于Type1格式。
Each arc is described through a series of start, end, and control points. Each point of the outline has a specific tag which indicates whether it is used to describe a line segment or an arc. The tags can take the following values:
FT_CURVE_TAG_ON Used when the point is "on" the curve. This corresponds to start and end points of segments and arcs. The other tags specify what is called an "off" point, i.e. a point which isn't located on the contour itself, but serves as a control point for a Bézier arc.
FT_CURVE_TAG_CONIC Used for an "off" point used to control a conic Bézier arc.
FT_CURVE_TAG_CUBIC Used for an "off" point used to control a cubic Bézier arc.

Use the FT_CURVE_TAG(tag) macro to filter out other, internally used flags.

每条弧由一系列起点、终点和控制点描述,轮廓的每个点有一个特定的标记,表示它用来描述一个线段还是一条弧。这个标记可以有以下值:
FT_Curve_Tag_On 当点在曲线上,这对应线段和弧的起点和终点。其他标记叫做"Off"点,即它不在轮廓线上,但是作为Bezier弧的控制点。
FT_Curve_Tag_Conic 一个Off点,控制一个conic Bezier弧
FT_Curve_Tag_Cubic 一个Off点,控制一个cubic Bezier弧
The following rules are applied to decompose the contour's points into segments and arcs:
  • Two successive "on" points indicate a line segment joining them.
  • One conic "off" point amidst two "on" points indicates a conic Bézier arc, the "off" point being the control point, and the "on" ones the start and end points.
  • Two successive cubic "off" points amidst two "on" points indicate a cubic Bézier arc. There must be exactly two cubic control points and two "on" points for each cubic arc (using a single cubic "off" point between two "on" points is forbidden, for example).
  • Finally, two successive conic "off" points forces the rasterizer to create (during the scan-line conversion process exclusively) a virtual "on" point amidst them, at their exact middle. This greatly facilitates the definition of successive conic Bézier arcs. Moreover, it is the way outlines are described in the TrueType specification.
下面的规则应用于将轮廓点分解成线段和弧
  • 两个相邻的"on"点表示一条线段;
  • 一个conic Off点在两个on点之间表示一个conic Bezier弧,off点是控制点,on点是起点和终点;
  • 两个相邻的cubic off点在两个on点之间表示一个cubic Bezier弧,它必须有两个cubic控制点和两个on点。
  • 最后,两个相邻的conic off点强制??在它们正中间创建一个虚拟的on点。这大大方便定义连续的conic弧。TrueType规范就是这么定义的。
Note that it is possible to mix conic and cubic arcs in a single contour, even though no current font driver produces such outlines.
segment example conic arc example
cubic arc example cubic arc with virtual 'on' point
注意,在单个轮廓线中可以混合使用conic和cubic弧,不过现在没有那种字体驱动产生这样的轮廓。
b. Outline descriptor b. 轮廓描述符
A FreeType outline is described through a simple structure:
FT_Outline
n_points the number of points in the outline
n_contours the number of contours in the outline
points array of point coordinates
contours array of contour end indices
tags array of point flags
FT轮廓通过一个简单的结构描述
FT_Outline
n_points 轮廓中的点数
n_contours 轮廓中轮廓线数
points 点坐标数组
contours 轮廓线端点索引数组
tags 点标记数组
Here, points is a pointer to an array of FT_Vector records, used to store the vectorial coordinates of each outline point. These are expressed in 1/64th of a pixel, which is also known as the 26.6 fixed float format. 这里,points是一个FT_Vector记录数组的指针,用来存储每个轮廓点的向量坐标。它表示为一个象素1/64,也叫做26.6固定浮点格式。
contours is an array of point indices used to delimit contours in the outline. For example, the first contour always starts at point 0, and ends at point contours[0]. The second contour starts at point contours[0]+1 and ends at contours[1], etc. contours是一组点索引,用来划定轮廓的轮廓线。例如,第一个轮廓线总是从0点开始,以contours[0]点结束。第二个轮廓线从contours[0]+1点开始,以contours[1]结束,等等。
Note that each contour is closed, and that n_points should be equal to contours[n_contours-1]+1 for a valid outline. 注意,每条轮廓线都是封闭的,n_points应该和contours[n_controus-1]+1相同。
Finally, tags is an array of bytes, used to store each outline point's tag. 最后,tags是一组字节,用来存放每个轮廓的点标记。
2. Bounding and control box computations 2、边界和控制框计算
A bounding box (also called bbox) is simply a rectangle that completely encloses the shape of a given outline. The interesting case is the smallest bounding box possible, and in the following we subsume this under the term "bounding box". Because of the way arcs are defined, Bézier control points are not necessarily contained within an outline's (smallest) bounding box. 边界框(bbox)是一个完全包含指定轮廓的矩形,所要的是最小的边界框。因为弧的定义,bezier的控制点无需包含在轮廓的边界框中。
This situation happens when one Bézier arc is, for example, the upper edge of an outline and an "off" point happens to be above the bbox. However, it is very rare in the case of character outlines because most font designers and creation tools always place "on" points at the extrema of each curved edges, as it makes hinting much easier. 例如轮廓的上缘是一个Bezier弧,一个off点就位于bbox的上面。不过这在字符轮廓中很少出现,因为大多字体设计者和创建工具都会在每个曲线拐点处放一个on点,这会使hinting更加容易。
We thus define the control box (also called cbox) as the smallest possible rectangle that encloses all points of a given outline (including its "off" points). Clearly, it always includes the bbox, and equates it in most cases. 于是我们定义了控制框(cbox),它是一个包含轮廓所有点的最小矩形,很明显,它包含bbox,通常它们是一样的。
Unlike the bbox, the cbox is much faster to compute.
a glyph with different bbox and cbox a glyph with identical bbox and cbox
不像 bbox,cbox计算起来非常快。
Control and bounding boxes can be computed automatically through the functions FT_Outline_Get_CBox() and FT_Outline_Get_BBox(). The former function is always very fast, while the latter may be slow in the case of "outside" control points (as it needs to find the extreme of conic and cubic arcs for "perfect" computations). If this isn't the case, it is as fast as computing the control box. 控制框和边界框可以通过函数FT_Outline_Get_CBox()和 FT_Outline_Get_BBox()自动计算,前者总是非常快,后者在有外界控制点的情况下会慢一点,因为需要找到conic和cubic弧的末端,如果不是这种情况,它和计算控制框一样快。
Note also that even though most glyph outlines have equal cbox and bbox to ease hinting, this is not necessary the case anymore when a transformation like rotation is applied to them. 注意,虽然大多字形轮廓为易于hint具有相同的cbox和bbox,这在它们进行变换以后,如旋转,就不再是这种情况了。
3. Coordinates, scaling and grid-fitting 3、坐标、缩放和网格对齐
An outline point's vectorial coordinates are expressed in the 26.6 format, i.e. in 1/64th of a pixel, hence the coordinates (1.0,-2.5) is stored as the integer pair (x:64,y:-192). 轮廓点的向量坐标表示为26.6格式,即一个象素的1/64。因此,坐标(1.0,-2.5)存放整型对(x:64,y:-192)。
After a master glyph outline is scaled from the EM grid to the current character dimensions, the hinter or grid-fitter is in charge of aligning important outline points (mainly edge delimiters) to the pixel grid. Even though this process is much too complex to be described in a few lines, its purpose is mainly to round point positions, while trying to preserve important properties like widths, stems, etc. 在主字形轮廓从EM网格缩放到当前字符大小后,hinter负责对齐重要的轮廓点到象素网格。虽然这个过程很难几句话说清楚,但是它的目的也就是取整点的位置,以保持字形重要的特性,如宽度、主干等。
The following operations can be used to round vectorial distances in the 26.6 format to the grid:
round( x ) == ( x + 32 ) & -64
floor( x ) == x & -64
ceiling( x ) == ( x + 63 ) & -64
下面的操作可以用来将26.6格式的向量距离取整到网格:
round( x ) == ( x + 32 ) & -64
floor( x ) == x & -64
ceiling( x ) == ( x + 63 ) & -64
Once a glyph outline is grid-fitted or transformed, it often is interesting to compute the glyph image's pixel dimensions before rendering it. To do so, one has to consider the following:

The scan-line converter draws all the pixels whose centers fall inside the glyph shape. It can also detect drop-outs, i.e. discontinuities coming from extremely thin shape fragments, in order to draw the "missing" pixels. These new pixels are always located at a distance less than half of a pixel but it is not easy to predict where they will appear before rendering.

一旦一个字形轮廓经过对齐或变换,在渲染之前通常要计算字形的图像象素大小。做到这一点,必须考虑如下:

扫描线转换器画出所有中心在字形形状中的象素,他也可以检测drop-outs???

This leads to the following computations:
  • compute the bbox
  • grid-fit the bounding box with the following:
xmin = floor( bbox.xMin )
xmax = ceiling( bbox.xMax )
ymin = floor( bbox.yMin )
ymax = ceiling( bbox.yMax )
  • return pixel dimensions, i.e.
width = (xmax - xmin)/64
and
height = (ymax - ymin)/64
这导致如下的计算:
  • 计算bbox;
  • 对齐bbox如下:
xmin = floor( bbox.xMin )
xmax = ceiling( bbox.xMax )
ymin = floor( bbox.yMin )
ymax = ceiling( bbox.yMax )
  • 返回象素尺寸,即
width = (xmax - xmin)/64
height = (ymax - ymin)/64
By grid-fitting the bounding box, it is guaranteed that all the pixel centers that are to be drawn, including those coming from drop-out control, will be within the adjusted box. Then the box's dimensions in pixels can be computed. 通过对齐bbox,可以保证所有的象素中心将画到,包括那些从drop-out控制来的,将在调整后的框子之中。接着,框子的象素尺寸可以计算出来。
Note also that, when translating a grid-fitted outline, one should always use integer distances to move an outline in the 2D plane. Otherwise, glyph edges won't be aligned on the pixel grid anymore, and the hinter's work will be lost, producing very low quality bitmaps and pixmaps. 同时注意,当平移一个对齐的轮廓,应该总是使用整型距离来移动。否则,字形的边缘将不再对齐象素网格,hinter的工作将无效,产生非常难看的位图。
VII. FreeType bitmaps 七、FT位图
The purpose of this section is to present the way FreeType manages bitmaps and pixmaps, and how they relate to the concepts previously defined. The relationships between vectorial and pixel coordinates is explained.
1. Vectorial versus pixel coordinates 1、向量坐标和象素坐标对比
This sub-section explains the differences between vectorial and pixel coordinates. To make things clear, brackets will be used to describe pixel coordinates, e.g. [3,5], while parentheses will be used for vectorial ones, e.g. (-2,3.5). 这里阐述了向量坐标的象素坐标的区别,为了更清楚的说明,使用方括号来表示象素坐标,使用圆括号表示向量坐标。
In the pixel case, as we use the Y upwards convention; the coordinate [0,0] always refers to the lower left pixel of a bitmap, while coordinate [width-1, rows-1] to its upper right pixel. 在象素坐标中,我们使用Y轴向上的规约,坐标[0,0]总是指位图左下角象素,坐标[width-1, rows-1]是右上角象素。
In the vectorial case, point coordinates are expressed in floating units, like (1.25, -2.3). Such a position doesn't refer to a given pixel, but simply to an immaterial point in the 2D plane. 在向量坐标中,点坐标用浮点单位表示,如(1.25, -2.3),这个位置并不是指一个特定象素,而是在2D平面上一个非实质性的点。
The pixels themselves are indeed square boxes of the 2D plane, whose centers lie in half pixel coordinates. For example, the lower left pixel of a bitmap is delimited by the square (0,0)-(1,1), its center being at location (0.5,0.5). 象素其实在2D平面上是一个方块,它的中心是象素坐标值的一半,例如位图的左下角象素通过方块(0,0)-(1,1)界定,它的中心位于 (0.5,0.5)。注意这儿用的是向量坐标表示。
This introduces some differences when computing distances. For example, the length in pixels of the line [0,0]-[10,0] is 11. However, the vectorial distance between (0,0)-(10,0) covers exactly 10 pixel centers, hence its length is 10.
bitmap and vector grid
这对计算距离就会发生一些区别。例如,[0,0]-[10.0]一条线的象素长度是11,然而, (0,0)-(10,0)的向量程度覆盖了10个象素,因此它的长度是10。
2. FreeType bitmap and pixmap descriptor 2、FT位图和象素图描述符
A bitmap or pixmap is described through a single structure, called FT_Bitmap, defined in the file <freetype/ftimage.h>. It is a simple descriptor whose fields are:
FT_Bitmap
rows the number of rows, i.e. lines, in the bitmap
width the number of horizontal pixels in the bitmap
pitch its absolute value is the number of bytes per bitmap line; it can be either positive or negative depending on the bitmap's vertical orientation
buffer a typeless pointer to the bitmap pixel bufer
pixel_mode an enumeration used to describe the pixel format of the bitmap; examples are ft_pixel_mode_mono for 1-bit monochrome bitmaps and ft_pixel_mode_grays for 8-bit anti-aliased "gray" values
num_grays this is only used for "gray" pixel modes, it gives the number of gray levels used to describe the anti-aliased gray levels -- 256 by default with FreeType 2
一个位图和象素图通过一个叫FT_Bitmap的单一结构描述,他定义在中,属性如下
FT_Bitmap
rows 行数,即位图中的水平线数
width 位图的水平象素数
pitch 它的绝对值是位图每行占的字节数,根据位图向量方向,可以是正值或是负值
buffer 一个指向位图象素缓冲的无类型指针
pixel_mode 一个枚举值,用来表示位图的象素格式;例如ft_pixel_mode_mono表示1位单色位图,ft_pixel_mode_grays表示8位反走样灰度值
num_grays 这只用于灰度象素模式,它给出描述反走样灰度级别的级数,FT缺省值为255。
Note that the sign of the pitch fields determines whether the rows in the pixel buffer are stored in ascending or descending order. pitch 属性值的正负符号确定象素缓冲中的行是升序还是降序存放。
Remember that FreeType uses the Y upwards convention in the 2D plane, which means that a coordinate of (0,0) always refer to the lower-left corner of a bitmap. 上面说道FT在2D平面上使用Y轴向上的规约,这意味着(0,0)总是指向位图的左下角。
If the pitch is positive, the rows are stored in decreasing vertical position; the first bytes of the pixel buffer are part of the upper bitmap row. 如果 picth是正值,按照向量减少的方向存储行,即象素缓冲的第一个字节表示位图最上一行的部分。
On the opposite, if the pitch is negative, the first bytes of the pixel buffer are part of the lower bitmap row. 如果是负值,第一个字节将表示位图最下一行的部分。
In all cases, one can see the pitch as the byte increment needed to skip to the next lower scanline in a given bitmap buffer. 对所有的情况,pitch可以看作是在指定位图缓冲中,跳到下一个扫描行的字节增量。
 : negative 'pitch' positive 'pitch'
The "positive pitch" convention is very often used, though some systems might need the other. 通常都使用正pitch,当然有的系统会使用负值。
3. Converting outlines into bitmaps and pixmaps 3、轮廓转换到位图和象素图
Generating a bitmap or pixmap image from a vectorial image is easy with FreeType. However, one must understand a few points regarding the positioning of the outline in the 2D plane before converting it to a bitmap:
  • The glyph loader and hinter always places the outline in the 2D plane so that (0,0) matches its character origin. This means that the glyph's outline, and corresponding bounding box, can be placed anywhere in the 2D plane (see the graphics in section III).
  • The target bitmap's area is mapped to the 2D plane, with its lower left corner at (0,0). This means that a bitmap or pixmap of dimensions [w,h] will be mapped to a 2D rectangle window delimited by (0,0)-(w,h).
  • When scan-converting the outline, everything that falls within the bitmap window is rendered, the rest is ignored.
使用FT从一个向量图像转换到位图和象素图非常简单,但是,在转换前,必须理解有关在2D平面上放置轮廓的一些问题:
  • 字形转载器和hinter在2D平面上放置轮廓时,总将(0,0)匹配到字符原点,这意味着字形轮廓,及对应的边界框,可以在平面中放置于任何地方。
  • 目标位图映射到2D平面上,左下角在(0,0)上,这就是说一个[w,h]大小的位图和象素图将被映射到(0,0)-(w,h)界定的2D矩形窗口。
  • 当扫描转换轮廓,所有在这个位图窗口的部分将被渲染,其他的被忽略。
A common mistake made by many developers when they begin using FreeType is believing that a loaded outline can be directly rendered in a bitmap of adequate dimensions. The following images illustrate why this is a problem.
  • The first image shows a loaded outline in the 2D plane.
  • The second one shows the target window for a bitmap of arbitrary dimensions [w,h].
  • The third one shows the juxtaposition of the outline and window in the 2D plane.
  • The last image shows what will really be rendered in the bitmap.
clipping algorithm
很多使用FT的开发者都会有个误解,认为一个装入的轮廓可以直接渲染成一个适当大小的位图,下面的图像表明这个问题。
  • 第一个图表明一个2D平面上一个装入的轮廓;
  • 第二个表示一个任意大小[w,h]维护的目标窗口;
  • 第三个表示在2D平面上轮廓和窗口的合并;
  • 最后一个表示位图实际被渲染的部分。
Indeed, in nearly all cases, the loaded or transformed outline must be translated before it is rendered into a target bitmap, in order to adjust its position relative to the target window. 实际上,几乎所有的情况,装入或变换过的轮廓必须在渲染成目标位图之前作平移操作,以调整到相对目标窗口的位置。
For example, the correct way of creating a standalone glyph bitmap is as follows
  • Compute the size of the glyph bitmap. It can be computed directly from the glyph metrics, or by computing its bounding box (this is useful when a transformation has been applied to the outline after the load, as the glyph metrics are not valid anymore).
  • Create the bitmap with the computed dimensions. Don't forget to fill the pixel buffer with the background color.
  • Translate the outline so that its lower left corner matches (0,0). Don't forget that in order to preserve hinting, one should use integer, i.e. rounded distances (of course, this isn't required if preserving hinting information doesn't matter, like with rotated text). Usually, this means translating with a vector (-ROUND(xMin), -ROUND(yMin)).
  • Call the rendering function (it can be FT_Outline_Render() for example).
例如,创建一个单独的字形位图正确的方法如下:
  • 计算字形位图的大小,可以直接从字形度量计算出来,或者计算它的边界框(这在经过变换后非常有用,此时字形度量不再有效)。
  • 根据计算的大小创建位图,别忘了用背景色填充象素缓冲;
  • 平移轮廓,使左下角匹配到(0,0)。别忘了为了hinting,应该使用整型。通常,这就是说平移一个向量(-ROUND(xMin), -ROUND(yMin))。
  • 调用渲染功能,例如FT_Outline_Render()函数。
In the case where one wants to write glyph images directly into a large bitmap, the outlines must be translated so that their vectorial position correspond to the current text cursor/character origin. 在将字形图像直接写入一个大位图的情况,轮廓必须经过平移,以将它们的向量位置对应到当前文本光标/字符原点上。
Personal tools