FreeType的光栅化功能
FreeType是一个字体格式开源工程。其中不但支持各种字体格式的解析,还提供了一个独立的光栅化引擎。
---------------------------下面的文字解释了什么是光栅化--------------------------------------------------------------------
现在流行的字体格式如TureType,Opentype等,其中描述的字形信息(就是字符的笔划信息)都是矢量的。
其中字符的每一个笔划都是由多条曲线或直线(直线可视为一次曲线)包围而形成的。一次曲线需要两个点来确定。
二次需要三个点,三次就需要四个点。字体内部就保存了这些点的坐标。显示字体的时候,因为显示器和打印机
都是点阵设备,所以必须将字符转化为用点阵来描述。这个过程就是光栅化。说白了,就是矢量描述转化为点阵描述。
不过字体的光栅化与与其它光栅化(如图形学中的Bresenham,DDA算法等)不同的是,它关心的是区域的点阵化,
即判断每个点属于那个区域。
----------------------------------------------------------------------------------------------------------------------------------------------
FreeType2.3.7实际提供了两个光栅化引擎。ft_grays_raster和ft_standard_raster。
分别位于:src\smooth\ftgrays.c 和 src\raster\ftraster.c 。二者的用法完全相同。FreeType自己用的是前者。
要想在FreeType之外独立使用两个引擎,我们分两个的步骤:
1、编译问题。把相关的文件加入工程,设置_STANDALONE_等宏。可能要修改代码,比如注释掉一些代码行等。
将int64_t 改为 __int64(for vc),等等。这些事,对于一个编程熟手来说,应该10分钟搞定了。我就不多啰嗦。
2、代码调用。主要的函数调用有三个:
ft_grays_raster.raster_reset(raster,pool_base,pool_size);
ft_grays_raster.raster_render(raster,¶m);
这三个调用中,头两个很easy。参数很简单:
FT_Raster raster;
int pool_size = 10240;
BYTE* pool_base = new BYTE[pool_size];
ft_grays_raster.raster_new(memory,&raster);
ft_grays_raster.raster_reset(raster,pool_base,pool_size);
第三个调用有点麻烦,先看一下参数param的如何设置:
param.target = &bmp;
param.source = &outline;
param.flags = FT_RASTER_FLAG_AA;
param.gray_spans = NULL;
param.black_spans = NULL;
param.bit_test = NULL;
param.bit_set = NULL;
param.user = NULL;
其中bmp和outline的定义如下:
FT_Outline outline;
这两个参数非常重要,一个是输出(位图格式),一个是输入(矢量格式)。
先看一下FT_Bitmap的格式,它描述了一个位图,其中的buffer是位图的位数据,是4字节对齐的,从上往下的数据(你必须先了解windows位图的格式才可以理解上面的话)。因此bmp应这样设置:
bmp.width = 16;//输出位图的size.
bmp.rows = 16;
bmp.pitch = 16;//每行需要的字节数,4字节对齐的.
bmp.buffer = new BYTE[bmp.rows*bmp.pitch];
bmp.num_grays = 256;
bmp.pixel_mode = FT_PIXEL_MODE_GRAY;
bmp.palette_mode = 0;
bmp.palette = NULL;
memset(bmp.buffer,0,bmp.rows*bmp.pitch);
FT_Outline的格式就比较复杂些。它描述了一系列的轮廓线。其n_contours和n_points成员是容易理解的,分别表示轮廓的数目和点的数目。轮廓指围成一个闭合区域的边界。比如字符”一“是一条轮廓,字符‘二’是两条轮廓。字符”十“是一条轮廓。对更复杂的字符,就不一定能直接看出有多少个轮廓,因为轮廓之间会有重叠。点的数目,是指末端点和首端点不重合情况下的数目。比如,对一个矩形,应该是4个端点,而不是5个。FreeType内部会自动将末端点连到首段点。
其它几个成员的含义如下:
outline.tags = new char [n_points]; //每个点的类型.
outline.contours = new short [n_contours]; //每条轮廓线占用的点数.
outline.flags = FT_OUTLINE_OWNER|FT_OUTLINE_HIGH_PRECISION;
points,tags,contours描述了每条轮廓的具体数据。三者必须严格对应上。这三个数组的具体格式也就是本篇文章的意义所在了。
points数组,tags数组 一般可以从字体文件数据中得到。但是其中的单位可能会有不同。这个跟字体的格式有关。不行就多试几个比例值。只要看到任何一点输出(比如一个字的其中一个笔画),就离成功不远了,在附近多试几个比例值。很快就可以让字符和位图的大小能符合了。
contours数组描述了一个轮廓使用的点数。比如:
contours[0]如果为8,则表示points数组中,元素0-8,都是第一条轮廓线的。
然后point数组中,9-contours[1]都是第二条轮廓线的。
依次类推,第n条轮廓线的点是: contours[n-2]+1 到 contours[n-1] (其中n>=2)
很明显,最后一个轮廓线对应的 contours[x]元素,其值必定等于 n_points-1。因为points数组最后一个元素就是 points[n_points-1]。
如果不满足此条件,ft_grays_raster直接跳出,认为数据错误。