3.图元数据
图元数据(glyf表)是TrueType字体的核心信息,因此通常它是最大的表。因为的位置索引是一张单独的表,图元数据表就完全只是图元的序列而已,每个图元以图元头结构开始:
typedef struct
{
WORD numberOfContours; //contor number,negative if composite
FWord xMin; //Minimum x for coordinate data.
FWord yMin; //Minimum y for coordinate data.
FWord xMax; //Maximum x for coordinate data.
FWord yMax; //Maximum y for coordinate data.
}GlyphHeader;
typedef enum
{
G_ONCURVE = 0x01, // on curve ,off curve
G_REPEAT =0x08, //next byte is flag repeat count
G_XMASK =0x12,
G_XADDBYTE =0x12, //X is positive byte
G_XSUBBYTE =0x12, //X is negative byte
G_XSAME =0x10, //X is same
G_XADDINT =0x00, //X is signed word
G_YMASK =0x24,
G_YADDBYTE =0x24, //Y is positive byte
G_YSUBBYTE =0x04, //Y is negative byte
G_YSAME =0x20 , //Y is same
G_YADDINT =0x00, //Y is signed word
};
// Argument1 and argument2 can be either x and y offsets to be added to the glyph or two point numbers.
// In the latter case, the first point number indicates the point that is to be matched
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;
if (size==0) return NULL;
GLYPHSET *pGlyphSet=(GLYPHSET *)new BYTE(size);
//get real data
pGlyphSet->cbThis=size;
size=GetFontUnicodeRanges(hDC,pGlyphSet);
return 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函数。