ttf字库

FreeType 2 教程
第二步 管理字型
@ 2009 David Turner (david@freetype.org)
@ 2009 The FreeType Development Team (http://www.freetype.org/)
翻译:liaoying

简介

这是FreeType2教程的第二部分,它包括以下内容:
获取字型数据
简单管理字型图像
获取全局数据(包括字距kerning)
渲染一个简单文本(包括字距kerning功能)
渲染一个居中文本(包括字距kerning功能)
渲染一个经过转换过的文本(包括centering功能)
通过字型数据(metrics)设计字体单位,以及怎样放置到设备上.

1.字型数据(Glyph metrics)
字型数据,就如它的名字所暗示的一样,是某些和每个字型相关的,用于字型布局的数据.
对于一个字型,常常出现两组数据:用于水平布局的数据(比如Latin, Cyrillic, Arabic, Hebrew等语言)和用于垂直布局的数据(比如Chinese, Japanese, Korean等语言).
注意只有一少部分字体格式提供了垂直布局的数据.你可以通过宏FT_HAS_VERTICAL来测试一个给定的face是不是包含垂直布局的数据.
某些字型数据可以在第一次载入字型到字型槽之后进行访问,访问必须功过face->glyph->metrics结构体,它是FT_Glyph_Metrics类型.我们将在后面仔细讨论.现在,我们只需注意它所包含的属性:
width 这是字型图像边框(bbox)的宽度,它和布局方向无关.

height 这是字型图像框(bbox)的高度,也和布局方向无关.需要注意的是,不要将这个height和FT_Size_Metrics中的height搞混了.

horiBearingX 对于水平布局,这是当前笔位置到字型图像框最左边距的水平距离.

horiBearingY 对于水平布局,这是基线到字型图像框最上面的垂直距离.

horiAdvance 对于水平布局,这是绘制字符串的时候笔位置的水平增量.

vertBearingX 垂直布局用,偷懒不译,水平布局搞清楚了,垂直布局也就差不多了.

vertBearingY 同上.

vertAdvance 同上.

注意:由于不是所有的字体都一定包含垂直布局的字型数据,vertBearingX, vertBearingY 和 vertAdvance这三个属性应该在确保FT_HAS_VERTICAL()返回TRUE的时候有效.(原文有误,为False).

这个图将这些数据描述得很清楚.
水平布局时的数据:图片链接


垂直布局时的数据:图片链接

字型数据face->glyph->metrics通常是用26.6的像素格式来表示(26.6格式:其实32位的数据,高26位表示整数,低6位表示小数,目的是用整数模拟浮点数,以兼容不支持浮点运算的处理器.使用时,右移6位或者乘以1/64即可转换为普通整数).如果在调用FT_Load_Glyph或者FT_Load_Char的时候,给于FT_LOAD_NO_SCALE标记,则这些数据将以原始单位表示.
字型槽对象也有一些我们感兴趣的属性,他们可以减轻我们开发者的工作.你可以用face->glyph->xxx来进行访问,xxx可以是以下一些属性:
advance 这个属性是FT_Vector类型(二维矢量),它为一个字型保留了经过变换的步进(advance)属性.当你使用FT_Set_Transform函数进行变换的时候,这个属性将非常有用,这已经在教程的第一部分的旋转字型部分进行了说明.除了这种情况,它的值就默认是[metrics.horiAdvance,0].当然,如果你载入字体的时候指定了FT_LOAD_VERTICAL标记,它的值就是[0,metrics.vertAdvance].

linearHoriAdvance 这个属性包含字型在水平方向上线性变换后的步进值.的确,字型槽返回的metrics.horiAdvance的值通常是被字体驱动取整,然后用来载入字型图像之后的像素坐标(它将是和64的乘积). linearHoriAdvance 是一个16.16的定点浮点数据,如果要得到原始数据,不妨除以65536或者是右移16位.它可以用来呈现虚拟的设备无关的文本布局.

linearVertAdvance 垂直布局用,和水平的差不多.

2.管理字型图像
字型槽中载入的字型图像可以转换为一个位图,或者在载入的时候使用FT_LOAD_RENDER,或者直接调用FT_Render_Glyph(),都可以.每当你载入了一个新的字型图像,原来字型槽中的字型图像将被冲掉.

有时候,在转换为位图之前,你可能需要从字型槽中获取字型图像,并将它在你的应用程序中缓存起来,甚至需要做一些附加的变换和度量.

FreeType2的API有一些特定的扩展功能,它可以轻松,灵活并具有一般性的处理字型图像.要使用这些API,需要包含FT_GLYPH_H头文件:#include FT_GLYPH_H

现在我们解释一下怎样使用这些函数:
a.提取字型图像
你可以很容易的提取一个单独的字型图像.如下代码所示:
FT_Glyph glyph; /* a handle to the glyph image */ ...

error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NORMAL );
if ( error )
{ ... }

error = FT_Get_Glyph(face->glyph, &glyph );
if ( error )
{ ... }

如你所见,我们做了这些事:
1.创建一个FT_Glyph的变量,名字叫做glyph.这是一个字型图像的句柄(指针).
2.载入一个字型图像到face的字型槽.我们不需要使用FT_LOAD_RENDER,因为我们仅仅指向抓取一个可变换的字型图像,用于下面的变换.
3.从字型槽中拷贝一个字型图像到一个新的FT_Glyph对象中,调用FT_Get_Glyph即可.这个函数返回一个错误码并填充glyph.

重要的是,我们必须注意到提取出来的字型图像和原始的字型图像(仍然在字型槽中)是同样的格式.举个例子,如果我们从TrueType的字体文件中载入了一个字型,那么这个字型图像将可变换的矢量轮廓.

如果你想精确的知道字型是怎样模拟和存储的,你可以访问glyph->format属性.一个字型对象可以调用FT_Done_Glyph来进行销毁.

字型对象精确的包含了一个字型图像和一个表示字型步进的2维的矢量(以16.16方式表示,根据译者验证, glyph->advance.x , face->glyph->advance.x , face->glyph->metrics->horiAdvance这三个值是一样的).

注意,不像其他FreeType对象,library不会保留所有分配了内存的glyph对象的列表.这意味着,你必须手动销毁这些glyph对象,而不是使用FT_Done_FreeType来做所有的清理工作.

b.变换,拷贝字型图像
如果字型图像是可变换的(必须保证glyph->format不是FT_GLYPH_FORMAT_BITMAP),那么我们可以随时调用FT_Glyph_Transform()来进行变换.

你也可以调用FT_Glyph_Copy()拷贝一份单独的字型图像.下面是一些示例代码:

FT_Glyph glyph, glyph2;
FT_Matrix matrix;
FT_Vector delta;

//... load glyph image in `glyph' ...
/* copy glyph to glyph2 */
error = FT_Glyph_Copy( glyph, &glyph2 );
if ( error )
{ ... could not copy (out of memory) ... }

/*translate `glyph' */
delta.x = -100 * 64;
/* coordinates are in 26.6 pixel format */
delta.y = 50 * 64;
FT_Glyph_Transform( glyph, 0, &delta );

/* transform glyph2 (horizontal shear) 貌似是变斜体字矩阵*/
matrix.xx = 0x10000L;
matrix.xy = 0.12 * 0x10000L;
matrix.yx = 0;
matrix.yy = 0x10000L;
FT_Glyph_Transform( glyph2, &matrix, 0 );

注意,变换时,2*2的变换矩阵经常需要16.16的步进向量,所以你不需要重新计算它.

c.度量字型图像
你可以调用FT_Glyph_Get_CBox ()来获取任何字型图像的控制框(CBox),可以获得可变换或者不可不换的CBox:
FT_BBox bbox;
FT_Glyph_Get_CBox( glyph, bbox_mode, &bbox );

坐标系统是相对于字型的原点(笔位置,0,0)的,通常使用Y向上的常用坐标系统.这个函数需要一个特别的参数,即bbox的模式,来指定控制框的坐标系统怎样表示.

如果字型载入的时候使用了FT_LOAD_NO_SCALE标记,那么bbox_mode必须使用FT_GLYPH_BBOX_UNSCALED来获取没有变换成为26.6格式的字体单位.FT_GLYPH_BBOX_SUBPIXELS的值是这个常量的另外一个名字,实质是一样的.

注意控制框的最大坐标值是专用的,即每个字型都不同,这意味着每载入一个字型,你都需要要使用整数或者26.6格式的数来重新计算字型图像的宽度和高度:
width = bbox.xMax - bbox.xMin;
height = bbox.yMax - bbox.yMin;

还要注意,对于26.6的坐标系统,如果FT_GLYPH_BBOX_GRIDFIT作为bbox mode,那么,坐标系将是网格对齐的.相当于:
bbox.xMin = FLOOR( bbox.xMin )
bbox.yMin = FLOOR( bbox.yMin )
bbox.xMax = CEILING( bbox.xMax )
bbox.yMax = CEILING( bbox.yMax )

如果要将bbox置于整数坐标系统中,把bbox_mode置为FT_GLYPH_BBOX_TRUNCATE即可.
最后,如果要将控制框置于网格对齐的坐标系统中,将bbox_mode置为FT_GLYPH_BBOX_PIXELS即可.

d.将字型图像转换为位图
一旦你很方便的完成了字型的缓存或者转换之后,你也许需要将字型对象转换为位图.调用FT_Glyph_To_Bitmap()函数可以很方便的完成转换.它负责将任何字型转换为位图:
FT_Vector origin;
origin.x = 32; /* 1/2 pixel in 26.6 format */
origin.y = 0;
error = FT_Glyph_To_Bitmap(&glyph, render_mode, &origin, 1 );
/*destroy original image == true */

注意:
1.第一个参数是字型句柄的地址(指针的指针),当这个函数被调用的时候,函数将通过这个指针来访问字型对象.调用完成之后,这个句柄将指向一个新的字型对象,这个新的字型对象包含渲染后的位图.
2.第二个参数是一个标准的渲染模式,用来指定你想得到那种位图.FT_RENDER_MODE_DEFAULT将得到一个8位抗锯齿灰度位图,使用FT_RENDER_MODE_MONO将得到一个1位单色位图.
3.第三个参数是一个二维向量的指针,它用来在转换为位图之前,转化源字型的位置.注意,函数调用之后,源图像将被转化回它自己的原点位置.如果你不需要在渲染位图之前做转换,则置NULL;
4.最后一个参数是一个布尔类型,它指定源字型对象是否在调用后被销毁.如果置为false,应用程序又没有保留其指针,那么源字型对象将永远不能销毁.

字型对象总是包含一个位图(如果没有返回错误的话),你必须将它的句柄强转成FT_BitmapGlyph类型之后才能访问.这种类型是FT_Glyph的一种"子类",它包含了额外的属性,详见FT_BitmapGlyphRec:
left 和字型槽的bitmap_left一样,这是原点到位图左边界的水平距离.它以整数的方式存放.

top 和字型槽的bitmap_top一样,它是原点到位图上边界的垂直距离.它以整数方式存放,符合和Y的正方向一样.

bitmap 和字型槽的bitmap一样,这是位图的数据.

3.全局字型数据
和字型数据不一样的是,全局数据是用来描述整个字体Face的距离和特性.他们或者以26.6像素格式的方式,或者以font units为单位,方便变换.

a.设计全局数据
对于可变换的数据格式,所有的全局数据都是以font unit为单位来呈现,这样方便接下来的变换,符合上一部分教程所描述的规则.你可以直接通过FT_Face的句柄来访问他们.
不过,使用前你需要见车字体的face是否可变换.使用宏FT_IS_SCALABLE可以很方便的检测,如果可变换,返回True;
在可变换的条件下,你可以访问到的全局数据有:
units_per_EM 这事字体Face的EM举行的大小,它用于将字型映射到设备上,正如上一章节所说.它的值往往是2048(对于TrueType字体),或者是1000(对于Type 1字体),但是也有可能是其他值.比如说对于固定大小的点阵字体,它的值是1.

bbox 全局的字型框,它是一个Face里面所有字型框的最大值.

ascender 全局的上行高度,它是一个Face里面,对于所有字型,基线到字型最高点的最大值.不幸的是,在不同的字体里面,它的定义是不同的.在有些字体中,它代表所有拉丁字符的上行高度(不包括accents?),有些又包括accents.还有一些它表示bbox.yMax.

descender 全局的下行高度.和上面的差不多,取反即可.

height 全局的字体高度,它简单的用来表示一行的高度,即基线到基线之间的高度.注意他经常大于上行高度和下行高度的绝对值之和.但是不能保证字体不会越过这个高度.

max_advance_width 所有字型的水平步进的最大值.它可以用来快速的计算一个文本字符串的最大宽度.它不能理解为字型图像宽度的最大值.

max_advance_height 用于垂直布局,意义同上.

underline_position 当你想要渲染一段带下划线的文本的时候,这个值用来表示相对于基线的下划线的位置.如果它在基线下方,那么它将是一个负值.

underline_thickness 表示下划线的厚度(高度).

要记住,不幸的是,上行高度和下行高度的值有可能是不可靠的,由于不同字体之间的差异.

 

 

 

转自:http://hi.baidu.com/liaoying

这份文档提供了FreeType 2函数库设计与实现的细节。本文档的目标是让开发人员更好的理解FreeType 2是如何组织的,并让他们扩充、定制和调试它。 首先,我们先了解这个库的目的,也就是说,为什么会写这个库: * 它让客户应用程序方便的访问字体文件,无论字体文件存储在哪里,并且与字体格式无关。 * 方便的提取全局字体数据,这些数据在平常的字体格式中普遍存在。(例如:全局度量标准,字符编码/字符映射表,等等) * 方便的提取某个字符的字形数据(度量标准,图像,名字,其他任何东西) * 访问字体格式特定的功能(例如,SFNT表,多重控制,OpenType轮廓表) Freetype 2的设计也受如下要求很大的影响: * 高可移植性。这个库必须可以运行在任何环境中。这个要求引入了一些非常激烈的选择,这些是FreeType2的低级系统界面的一部分。 * 可扩展性。新特性应该可以在极少改动库基础代码的前提下添加。这个要求引入了非常简单的设计:几乎所有操作都是以模块的形式提供的。 * 可定制。它应该能够很容易建立一个只包含某个特定项目所需的特性的版本。当你需要集成它到一个嵌入式图形库的字体服务器中时,这是非常重要的。 * 简洁高效。这个库的主要目标是只有很少cpu和内存资源的嵌入式系统。 这份文档的其他部分分为几个部分。首先,一些章节介绍了库的基本设计以及Freetype 2内部对象/数据的管理。 接下来的章节专注于库的定制和与这个话题相关的系统特定的界面,如何写你自己的模块和如何按需裁减库初始化和编译。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值