您好,欢迎来到素彩网!

关于TrueType字体的结构

来源:sc115.com | 155 次浏览 | 2015-09-27

标签: 字体 结构

        TrueType字体通常包含在单个TrueType字体文件中,其文件后缀为.TTF。OpenType字体是以类似于TrueType字体的格式编码的POSTSCRIPT字体。OPENTYPE字体使用.OTF文件后缀。OPENTYPE还允许把多个OPENTYPE字体组合在一个文件中以利于数据共享。这些字体被称为TrueType字体集(TrueType collection),其文件后缀为.TTC。
TrueType字体用machintosh的轮廓字体资源的格式编码,有一个唯一的标记名"sfnt"。windows没有macintosh的位图字体资源格式,字体目录包含了字体格式的版本号和几个表,每个表都有一个tableentry结构项,tableentry结构包含了资源标记、校验和、偏移量和每个表的大小。下面是TrueType字体目录的c语言定义:
typedef sturct
{
char tag[4];
ULONG checkSum;
ULONG offset;
ULONG length;
}TableEntry;

typedef struct
{
Fixed sfntversion; //0x10000 for version 1.0
USHORT numTables;
USHORT searchRange;
USHORT entrySelector;
USHORT rangeShift;
TableEntry entries[1];//variable number of TableEntry
}TableDirectory;

TrueType 字体中的所有数据都使用big-endian编码,最高位字节在最前面(因为TrueType字体最初是由apple公司定义的,而apple公司的os运行在motorola的cpu上)。如果一人TrueType字体以00 01 00 00 ,00 17开头,我们就可以知道它的格式是轮廓字体资源("sfnt")版本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 PCL 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 ,DWORD cbData);
GetFontData函数可以用于查询设备上下文中当前逻辑字体所对应的TrueType字体,因此传递的不是逻辑字体句柄,而是设备上下文句柄。你可以查询整个TrueType文件基是文件中的一个表。要查询整个文件的话dwTable参数应该为0;否则,应该传递要查询的表的四字符标记的DWORD格式。参数dwOffset是要查询的表中的起始偏移,要查询整个表的话应该为0;参数;pvBuffer是缓冲区的地址,cbData是缓冲区的大小。如果最后个参数为NULL和0,GetFontData函数返回字体文件或表的大小;就会把到的数据拷贝到应用程序所提供的缓冲区中。
下面的例和查询整个TrueType字体的原始数据:
TableDirctory * GetTrueTypeFont (HDC hDC ,DWORD &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);

return pFont;
}
GetFontData使得应用程序能够在自己的文档中内嵌TrueType字体,以确保这些文档能在没有相应字体的其他机器上显示。它的做法是允许应用程序查询字体数据,然后写入到文档中作为文档的一部分,在文档被打于时再安装该字体以确保文档能以创建时同样的方式显示。比如,Windows NT/2000的假脱机程序在打印到远端服务器时会在假脱机文件中内嵌入TrueType字体以保证文档能在另一台机器上正确地打印。
一旦接受到TrueType字体的原始数据,它的头中的TableDirectory结构很容易分析。需要检查的只有版本号和表的数目,然后就可以检查单个的表。我们来看一些重要的和有趣的表。
1.字体头
字体头表(head表)中包含了TrueType字体的全局信息。下面是字体头表的结构。
typedef sturct
{
Fixed Table;//x00010000 ro version 1.0
Fixed fontRevision;//Set by font manufacturer.
ULONG checkSumAdjustment;
ULONG magicNumer; //Set to 0x5f0f3cf5
USHORT flags;
USHORT unitsPerEm; //Valid range is from 16 to 16384
longDT created; //International date (8-byte field).
longDT modified; //International date (8-byte field).
FWord xMin; //For all glyph bounding boxes.
FWord yMin; //For all glyph bounding boxes.
FWord xMax; //For all glyph bounding boxes.
FWord xMax; //For all glyph bounding boxes.
USHORT macStyle;
USHORT lowestRecPPEM; //Smallest readable size in pixels.
SHORT fontDirctionHint;
SHORT indexToLocFormat; //0 for short offsets ,1 for long.
SHORT glyphDataFormat; //0 for 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表的结构。
typedef struct
{
Fixed Version;//0x00010000 for version 1.0.
USHORT numGlypha; //Number of glyphs in the font .
USHORT maxPoints; //Max points in noncomposite glyph .
RSHORT maxContours; //Max contours in noncomposite glyph.
USHORT maxCompositePoints;//Max points in a composite glyph.
USHORT maxCompositeContours; //Max contours in a composite glyph.
USHORT maxZones;// 1 if not use the twilight zone [Z0],
//or 2 if so use Z0;2 in most cases.
USHORT max TwilightPoints ;/ Maximum points used in Z0.
USHORT maxStorage; //Number of storage area locations.
USHORT maxFunctionDefs; //Number of FDEFs.
USHORT maxStackElements; //Number of depth.
USHORT maxSizeOfInstructions; //Max byte count for glyph inst.
USHORT maxComponentElements; //Max number top components refernced.
USHORT maxComponentDepth; //Max levels of recursion.
}Table_maxp;

numGlyphs字段保存了字体中图元的总数,这决定了到位置表的图元索引的数量,可以用于严正图元索引的有效性。TrueType字体中的每个图元都可以是合成图元或简单图元。简单图元可以有一条或多大体上轮廓中国,条用一些控制点定义。合成图元用几个其他图元的组合来定义。maxPointsmaxCountorsmaxCompositePoints maxCompositeContours这几个字段说明了图元定义的复杂度。
除了图元的定义,TrueType字体还使用了图元指令用于提示字体扫描器如何对控制点进行调整以得到更均衡更漂亮的光栅化后的图元。图元指令也可以出现在字体程序表(fpgm表)以及控制值程序表(“prep”)的全局字体层中。TrueType图元指令是一个伪计算机字节指令,该机类似于Java的虚拟机,这些指令可以用堆栈计算机执行。MaxStackElements maxSizeOfInstructions两个字段同志堆栈计算机这些指令的复杂度。
以Windings字体为例,该字体有226个图元,图元最多有47条轮廓线,简单图元最多有268个点,合成图元最多有141个点,合成图元最多有14条轮廓线,最坏情况下需要492层堆栈,最长的指令有1119个字节。
字符到图元索引的映射表(cmap表)定义了从不同代码页中的字符代码到图元索引的映射关系,这是在TrueType字体中存取图元信息的关键。cmap表包含几个了表以支持不同的平台和不同的字符编码方案。

下面是cmap表的结构。

typedef struct
{
USHORT Platform; //platform ID
USHORT EncodingID; //encoding ID
ULONG TableOffset ;//offset to encoding table  

typedef struct {
WCHAR wcLow;
USHORT cGlyphs;
}

typedef struct
{
DWORD cbThis; //sizeof (GLYPHSET)+sizeof(WCRANGE)+(cRanges-1)
DWORD flAccel;
DWORD cGlyphsSupported;
DWORD cRanges;
WCRANGE ranges[1]; //ranges[cRanges]
}GLYPHSET;

DWORD GetFontUnicodeRanges(HDC hDC,LPGLYPHSET lpgs);
DWORD 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)
{
//query for size
DWORD size=GetFontUnicodeRanges(hDC,NULL);

if (size==0) return NULL;
GLYPHSET *pGlyphSet=(GLYPHSET *)new BYTE(size);

//get real data
pGlyphSet->cbThis=size;
size=GetFontUnicodeRanges(hDC,pGlyphSet);

return pGlyphSet;
}

 1/3    1 2 3 下一页 尾页

搜索: 字体 结构 

最热-字体安装

繁难字库生僻字大全

中文版Vista新设微软雅黑字体

使用11px及10px的清晰汉字字体

多种方法玩好Windows系统字体

Windows系统造字功能详细用法

为什么在安装字体时会出现文件损坏?

Windows7安装字体和用快捷方式安装字体

古汉字字体怎么输入?

方正GBK编码字库清单

象素字简介及象素字体查找好去处

为什么有些字体安装好后有的字打不出来

关于字体的一个惊人发现……

如何解决“无法新增字体”问题

素材
风趣 149风趣 149
风趣 155风趣 155
风趣 160风趣 160
风趣 110风趣 110
风趣 113风趣 113
风趣 116风趣 116
风趣 120风趣 120
风趣 126风趣 126
风趣 122风趣 122