ttf文件结构解析Word格式文档下载.docx
《ttf文件结构解析Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《ttf文件结构解析Word格式文档下载.docx(22页珍藏版)》请在冰点文库上搜索。
of
TableEntry
}TableDirectory;
TrueType
字体中的所有数据都使用big-endian编码,最高位字节在最前面(因为TrueType字体最初是由apple公司定义的,而apple公司的os运行在motorola的cpu上)。
如果一人TrueType字体以00
01
00
00
17开头,我们就可以知道它的格式是轮廓字体资源("
)版本1.0的格式,有23个表。
TableDirectory结构的最后一个字段是可变长度的tableentry结构的数组,安体中的每个表对应其中一项。
TrueType字体中的每个表都保存了不同的逻辑信息-----如图元中数据、字符到图元的映射、字距调整信息等等。
有表是必须的,有些是可选的。
下表列出了TrueType字体中常见的表。
head
字体头
字体的全局信息
cmap
字符代码到图元的映射
把字符代码映射为图元索引
glyf
图元数据
图元轮廓定义以及网格调整指令
maxp
最大需求表
字体中所需内存分配情况的汇总数据
mmtx
水平规格
图元水平规格
loca
位置表索引
把元索引转换为图元的位置
name
命名表
版权说明、字体名、字体族名、风格名等等
hmtx
水平布局
字体水平布局星系:
上高、下高、行间距、最大前进宽度、最小左支撑、最小右支撑
kerm
字距调整表
字距调整对的数组
post
PostScript信息
所有图元的PostScript
FontInfo目录项和PostScript名
PCLT
PCL
5数据
HP
5Printer
Language
的字体信息:
字体数、宽度、x高度、风格、记号集等等
OS/2
OS/2和Windows特有的规格
TrueType字体所需的规格集
在TableDirectory结构中,所有的TableEntry结构都必须根据它们的标记名排序。
比如,cmap必须出现在head前,而head必须在glyf前。
但是实际的表可以出现在TrueType字体文件中的任意位置。
Win32API
提供了一个应用程序可用于查询原始TrueType字体信息的函数:
DWORD
GetFontData(HDC
hDC,DWORD
dwTable
DWORD
dwOffset,
LPVOID
lpbBuffer
cbData);
GetFontData函数可以用于查询设备上下文中当前逻辑字体所对应的TrueType字体,因此传递的不是逻辑字体句柄,而是设备上下文句柄。
你可以查询整个TrueType文件基是文件中的一个表。
要查询整个文件的话dwTable参数应该为0;
否则,应该传递要查询的表的四字符标记的DWORD格式。
参数dwOffset是要查询的表中的起始偏移,要查询整个表的话应该为0;
参数;
pvBuffer是缓冲区的地址,cbData是缓冲区的大小。
如果最后个参数为NULL和0,GetFontData函数返回字体文件或表的大小;
就会把到的数据拷贝到应用程序所提供的缓冲区中。
下面的例和查询整个TrueType字体的原始数据:
TableDirctory
*
GetTrueTypeFont
(HDC
hDC
&
nFontSize)
//query
font
size
nFontSize=GetFontData(hDC,0,0,NULL,0);
TableDirectory
pFont
=(TableDirectory
*)new
BYTE(nFontSize);
if
(pFont==NULL)
return
NULL;
GetFontData(hDC,0,0,pFont,nFontSize);
pFont;
}
GetFontData使得应用程序能够在自己的文档中内嵌TrueType字体,以确保这些文档能在没有相应字体的其他机器上显示。
它的做法是允许应用程序查询字体数据,然后写入到文档中作为文档的一部分,在文档被打于时再安装该字体以确保文档能以创建时同样的方式显示。
比如,Windows
NT/2000的假脱机程序在打印到远端服务器时会在假脱机文件中内嵌入TrueType字体以保证文档能在另一台机器上正确地打印。
一旦接受到TrueType字体的原始数据,它的头中的TableDirectory结构很容易分析。
需要检查的只有版本号和表的数目,然后就可以检查单个的表。
我们来看一些重要的和有趣的表。
1.字体头
字体头表(head表)中包含了TrueType字体的全局信息。
下面是字体头表的结构。
Table;
//x00010000
ro
fontRevision;
//Set
by
manufacturer.
checkSumAdjustment;
magicNumer;
to
0x5f0f3cf5
flags;
unitsPerEm;
//Valid
range
is
from
16
16384
longDT
created;
//International
date
(8-byte
field).
modified;
FWord
xMin;
//For
all
glyph
bounding
boxes.
yMin;
xMax;
macStyle;
lowestRecPPEM;
//Smallest
readable
size
in
pixels.
SHORT
fontDirctionHint;
indexToLocFormat;
//0
short
offsets
1
long.
glyphDataFormat;
current
format.
}Table_head;
字体的历史记录在三个字段中:
字全版本号、字体最初创建时间和字体最后修改时间。
有8
个字节用于记录时间戳,记录的是从1904年1月1日午夜12:
00开始的秒数,因此我们不用担心y2k问题,或是什么y2m问题。
字体设计时是针对一个参考网格设计的,该网格被称为em-square,字体中的图元用网格中的坐标表示。
因此em-squrare的大小决定胃该字体的图元被缩放的方式,同时也反映胃该字体的质量。
字体头中保存了每个em-square的格数和能
包含所有图元的边界框。
Em-square的有效值是从16到16384,常见的值是2048、4096和8192。
比如,Windings字体的em-square的格数是2048,图元的边界框是[0,-432,2783,1841]。
字体头表中的其他信息包括最小可读像素大小、字体方向、在位置表中图元索引的格式和图元数据格式等等。
最大需求表
TrueType字体是一种非常灵活的数据结构,它可以包含可变数目的图元,每个图元可以有不同数目的控制点,甚至还可以有数量可变的图元指令。
最大需求表的目的是告知字体栅格器(rasterizer)对内存的需求,以便
在出来字体前分配合适大小的内存。
因为性能对字体栅格器非常重要,像MFC的CAarray那样需要频繁进行数据拷贝操作的动态增长的数据结构不合要求。
下面是maxp表的结构。
Version;
//0x00010000
1.0.
numGlypha;
//Number
glyphs
the
.
maxPoints;
//Max
points
noncomposite
RSHORT
maxContours;
contours
glyph.
maxCompositePoints;
a
composite
maxCompositeContours;
maxZones;
//
1
not
use
twilight
zone
[Z0],
//or
2
so
Z0;
most
cases.
max
TwilightPoints
;
/
Maximum
used
Z0.
maxStorage;
storage
area
locations.
maxFunctionDefs;
FDEFs.
maxStackElements;
depth.
maxSizeOfInstructions;
byte
count
inst.
maxComponentElements;
top
components
refernced.
maxComponentDepth;
//Max
levels
recursion.
}Table_maxp;
numGlyphs字段保存了字体中图元的总数,这决定了到位置表的图元索引的数量,可以用于严正图元索引的有效性。
TrueType字体中的每个图元都可以是合成图元或简单图元。
简单图元可以有一条或多大体上轮廓中国,条用一些控制点定义。
合成图元用几个其他图元的组合来定义。
maxPoints\maxCountors\maxCompositePoints
maxCompositeContours这几个字段说明了图元定义的复杂度。
除了图元的定义,TrueType字体还使用了图元指令用于提示字体扫描器如何对控制点进行调整以得到更均衡更漂亮的光栅化后的图元。
图元指令也可以出现在字体程序表(fpgm表)以及控制值程序表(“prep”)的全局字体层中。
TrueType图元指令是一个伪计算机字节指令,该机类似于Java的虚拟机,这些指令可以用堆栈计算机执行。
MaxStackElements
maxSizeOfInstructions两个字段同志堆栈计算机这些指令的复杂度。
以Windings字体为例,该字体有226个图元,图元最多有47条轮廓线,简单图元最多有268个点,合成图元最多有141个点,合成图元最多有14条轮廓线,最坏情况下需要492层堆栈,最长的指令有1119个字节。
字符到图元索引的映射表(cmap表)定义了从不同代码页中的字符
代码到图元索引的映射关系,这是在TrueType字体中存取图元信息的关键。
cmap表包含几个了表以支持不同的平台和不同的字符编码方案。
下面是cmap表的结构。
Platform;
//platform
ID
EncodingID;
//encoding
TableOffset
//offset
encoding
table
struct
WCHAR
wcLow;
cGlyphs;
cbThis;
//sizeof
(GLYPHSET)+sizeof(WCRANGE)+(cRanges-1)
flAccel;
cGlyphsSupported;
cRanges;
WCRANGE
ranges[1];
//ranges[cRanges]
}GLYPHSET;
GetFontUnicodeRanges(HDC
hDC,LPGLYPHSET
lpgs);
GetGlyphIndices(HDC
hDC,LPCTSTR
lpstr,int
c
LPWORD
pgi,DWORD
fl);
通常一种字体只提供UNICODE字符集中的字符的一个子集。
这些字符可以被分组为多个区域,cmap映射表中就是这么做的。
GetFontUnicodeRanges函数在一个GLYPHSET结构中返回支持的图元的数量、支持的UNICODE区域的数量以及设备上下文中字体的这些区域的详细信息。
GLYPHSET是一个可变长的结构
,其大小取决于所支持的UNICODE区域的数量。
因此,和Win32
API中支持可变长结构一样,
GetFontUnicodeRanges函数通常需要调用两
次。
第一次调用时得到以NULL指针作为最后一莜参数,GDI会返回所需窨的大小。
调用者然后分配所需的内存,再次调用以得到真正的数据。
这两
种情况下,GetFontUnicodeRanges函数都会返回保存整个结构所需的数据大小。
MSDN文档可能还是错误地描述成了如果第二个参数是NULL,GetFontUnicodeRanges函数返回指向GLYPHSET结构的指针。
下面是用于查询上下文中当前字体GLYPHSET结构的一个简单函数。
GLYPHSET
*QueryUnicodeRanges(HDC
hDC)
size=GetFontUnicodeRanges(hDC,NULL);
(size==0)
*pGlyphSet=(GLYPHSET
BYTE(size);
//get
real
data
pGlyphSet->
cbThis=size;
size=GetFontUnicodeRanges(hDC,pGlyphSet);
pGlyphSet;
如果在一些Windows
TrueType字体上试着调用GetFontUnicodeRanges函数,你会发现这些字体通常支持1000个以上的图元,这些图元被分成几百个UNICODE区域。
比如,“Times
New
Roman”有我143个图元,分布在145个区域中,和一个区域是0x20到0x7f,即可打印的7位ASCII代码区域。
GetFontUnicodeRanges函数只使用了TrueType字体“cmap”表的一部分部分信息,即从UNICODE到图元索引的映射域。
GetGlyphIndices函数则能真正使用这些映射关系把一个字符串转换为一个图元索引的数组。
它接收一个设备上下文句柄、一个字符串指针、字符串长度、一个WORD数组的指针和一个标志。
生成的图元索引将保存在WORD数组中。
如果标志为GGI_MASK_NONEXISTING_GLYPHS,找不到的字符的图元索引会被标注成0xFFFF。
此函数得到的图元索引可以传给其他GDI函数,如ExtTextOut函数。
2.位置索引
TrueType字体中最有用的信息是glyf表中的图元数据。
有了图元索引,要找到相应的图元,需要表(loca表)索引以把图元索引转换为图元数据表内的偏移量。
位置索引表中保存了n+1个图元数据表的索引,其中n是保存在最大需求表中的图元数量。
最后一个额外
的偏移量并不指向一个新图元,而是指向最后一个图元的偏移量和当前图元的偏移量和当前图元的偏移量间的差值得到图元的长度。
位置索引表中的每一个索引以无符号短整数对齐的,如果使用了短整数格式,索引表实际存储的是WORD偏移量,而不是BYTE偏移量。
这合得短整数格式的位置索引表能
支持128KB大小的图元数据表。
3.图元数据
图元数据(glyf表)是TrueType字体的核心信息,因此通常它是最大的表。
因为的位置索引是一张单独的表,图元数据表就完全只是图元的序列而已,每个图元以图元头结构开始:
WORD
numberOfContours;
//contor
number,negative
composite
//Minimum
x
coordinate
data.
y
//Maximum
yMax;
}GlyphHeader;
对于简单图元,numberOfContours字段中保存的是当前图元的轮廓线的树木;
对于合成图元,numberOfContours字段是一个负值。
后者的轮廓线的总数必须基于组成该合成图元的所有图元的数据计算得到。
GlyphHeader结构中后四个字段记录了图元的边界框。
对于简单图元,图元的描述紧跟在GlyphHeader结构之后。
图元的描述由几部分信息组成:
所有轮廓线结束点的索引、图元指令和一系列的控制点。
每个控制点包括一个标志以x和y坐标。
概念上而言,控制所需的信息和GDI函数PolyDraw函数所需的信息相同:
一组标志和一组点的坐标。
但TrueType字体中的控制点的编码要复杂得多。
下面是图元描述信息的概述:
endPtsOfContours[n];
//n=number
contours
instructionlength;
BYTE
instruction[i];
//i
=
instruction
length
flags[];
//variable
xCoordinates[];
yCoordinates[];
图元可以包含一条或多条轮廓线。
比如,字母"
O"
有两
条轮廓线,一条是内部的轮廓,另一条是外部的轮廓。
对于每一条轮廓线,endPtsOfContours数组保存了其终点的索引,从该索引中可以计算出轮廓线中点的数量。
比如,endPtsOfCont