TrueType字体文件解析

在使用一些老外写的报表工具或控件时,总是会遇到中文乱码的问题;呵呵,这不我最终也遇上了,在我们的产品中使用了一个叫做eDocEngineer的报表输出控件;然后在中文平台上输出PDF等文档时,中文无法输出。经调试发现原来是TrueType字体文件解析时出了问题。老外对于TrueType字体的解析基本上只考虑了扩展名为ttf的情况,也即一个字体文件里只有一个字体,没有考虑到True Type Collection的情况,也即扩展名为ttc。

在使用win API函数GetFontData提取字体文件的数据时,一般都会写着GetFontData(DC, 0, 0, nil, 0)来获取字体数据的长度,然后再调用GetFontData(DC, 0, 0, Buff, FontLen)来获取这个字体的数据。对于ttf文件时,这样写是没有问题,但在处理True Type Collection时这里就会遇到Offset问题,最根本的原因就是ttc与ttf的区别。

ttc的格式与ttf的格式基本相同,offset也都是从文件头开始的;为什么使用处理ttf的方式来处理ttc会遇到问题呢?原因就在于虽然两者格式基本相同,但ttc文件里还是多了些东西。我们来比较下两种文件的格式:

首先是ttf的文件格式,ttf首先是从一个Table Directory开始的,一个ttf只有一个Directory,Directory的结构如下

FIXED version

USHORT numOfTables

USHORT searchRange

USHORT entrySelector

USHORT rangeShift

接下来就是Table Entries结构,之后就是存在的实际数据。

我们再来看ttc的文件格式,ttc文件的文件头如下:

TAG         TTCTag ---'ttcf'

FIXED32  Version

ULONG    numOfDirectories

接下来就是Directory结构

我们可以看到ttf跟ttc的区别了。然后里面所有的offset都是从文件头开始计算的,因此如果在处理ttc文件时也用GetFontData(DC, 0,0, nil,0)的方式来提取字体数据,就会遇到offset问题。要解决这个问题,就需要把ttc的所有数据都提取出来,也即应该修改下GetFontData的第二个参数dwMetricsTable, 相对于ttc的参数值为0x66637474,也即为GetFontData(DC, 0x66637474, 0, nil, 0)或GetFontData(DC, 0x66637474, 0, buff, fontLen)来获得整个ttc文件的数据。然后再按照文件结构来解析即可。

 

更多关于字体文件结构的信息,可以参阅一个朋友的博文<关于TrueType字体结构的文章>.

你可能感兴趣的:(TrueType字体文件解析)