http://www.zhaozi.cn/e/DoPrint/?classid=94&id=45
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;
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字体所需的规格集
DWORD GetFontData(HDC hDC,DWORD dwTable ,DWORD dwOffset, LPVOID lpbBuffer ,DWORD cbData);
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;
}
1.字体头
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;
最大需求表
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;
下面是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);
下面是用于查询上下文中当前字体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;
}
2.位置索引
位置索引表中保存了n+1个图元数据表的索引,其中n是保存在最大需求表中的图元数量。最后一个额外的偏移量并不指向一个新图元,而是指向最后一个图元的偏移量和当前图元的偏移量和当前图元的偏移量间的差值得到图元的长度。
3.图元数据
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;
USHORT endPtsOfContours[n]; //n=number of contours
USHORT instructionlength;
BYTE instruction[i]; //i = instruction length
BYTE flags[]; //variable size
BYTE xCoordinates[]; //variable size
BYTE yCoordinates[]; //variable size
我们提到棕em-square被限制为最大为16384个网格,因此通常情况下需要各两个字节来表示x坐标和y坐标。为了节省空间,图元中保存的是相对坐标。第一个点的坐标是相对(0,0)记录的,所有随后的点记录者是和上一个点的坐标差值。有些差值可以用一个字节表示,有些差值为0,另外一些差值则无法用耽搁字节表示。标志数组保存了每个坐标的编码信息以及其他一些信息。下面是标志中各个位的含义的总结:
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
};
int KTrueType::DecodeGlyph(int index, KCurve & curve, XFORM * xm) const
{
const GlyphHeader * pHeader = GetGlyph(index);
if ( pHeader==NULL )
{
// assert(false);
return 0;
}
int nContour = (short) reverse(pHeader->numberOfContours);
if ( nContour<0 )
{
return DecodeCompositeGlyph(pHeader+1, curve); // after the header
}
if ( nContour==0 )
return 0;
curve.SetBound(reverse((WORD)pHeader->xMin), reverse((WORD)pHeader->yMin),
reverse((WORD)pHeader->xMax), reverse((WORD)pHeader->yMax));
const USHORT * pEndPoint = (const USHORT *) (pHeader+1);
int nPoints = reverse(pEndPoint[nContour-1]) + 1; // endpoint of last contour + 1
int nInst = reverse(pEndPoint[nContour]); // instructon length
curve.m_glyphindex = index;
curve.m_glyphsize = (int) GetGlyph(index+1) - (int) GetGlyph(index);
curve.m_Ascender = m_Ascender;
curve.m_Descender = m_Descender;
curve.m_LineGap = m_LineGap;
GetMetrics(index, curve.m_advancewidth, curve.m_lsb);
if ( curve.m_glyphsize==0 )
return 0;
curve.m_instrsize = nInst;
const BYTE * pFlag = (const BYTE *) & pEndPoint[nContour] + 2 + nInst; // first byte in flag
const BYTE * pX = pFlag;
int xlen = 0;
for (int i=0; i<nPoints; i++, pX++)
{
int unit = 0;
switch ( pX[0] & G_XMASK )
{
case G_XADDBYTE:
case G_XSUBBYTE:
unit = 1;
break;
case G_XADDINT:
unit = 2;
}
if ( pX[0] & G_REPEAT )
{
xlen += unit * (pX[1]+1);
i += pX[1];
pX ++;
}
else
xlen += unit;
}
const BYTE * pY = pX + xlen;
int x = 0;
}
int KTrueType::DecodeCompositeGlyph(const void * pGlyph, KCurve & curve) const
{
KDataStream str(pGlyph);
unsigned flags;
int len = 0;
do
{
flags = str.GetWord();
unsigned glyphIndex = str.GetWord();
// 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 to the new glyph.
// The second number indicates the new glyph's "matched" point. Once a glyph is added, its point numbers
// begin directly after the last glyphs (endpoint of first glyph + 1).
// When arguments 1 and 2 are an x and a y offset instead of points and the bit ROUND_XY_TO_GRID is set to 1,
// the values are rounded to those of the closest grid lines before they are added to the glyph.
// X and Y offsets are described in FUnits.
signed short argument1;
signed short argument2;
if ( flags & ARG_1_AND_2_ARE_WORDS )
{
argument1 = str.GetWord(); // (SHORT or FWord) argument1;
argument2 = str.GetWord(); // (SHORT or FWord) argument2;
}
else
{
argument1 = (signed char) str.GetByte();
argument2 = (signed char) str.GetByte();
}
signed short xscale, yscale, scale01, scale10;
xscale = 1;
yscale = 1;
scale01 = 0;
scale10 = 0;
if ( flags & WE_HAVE_A_SCALE )
{
xscale = str.GetWord();
yscale = xscale; // Format 2.14
}
else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE )
{
xscale = str.GetWord();
yscale = str.GetWord();
}
else if ( flags & WE_HAVE_A_TWO_BY_TWO )
{
xscale = str.GetWord();
scale01 = str.GetWord();
scale10 = str.GetWord();
yscale = str.GetWord();
}
if ( flags & ARGS_ARE_XY_VALUES )
{
XFORM xm;
xm.eDx = (float) argument1;
xm.eDy = (float) argument2;
xm.eM11 = xscale / (float) 16384.0;
xm.eM12 = scale01 / (float) 16384.0;
xm.eM21 = scale10 / (float) 16384.0;
xm.eM22 = yscale / (float) 16384.0;
len += DecodeGlyph(glyphIndex, curve, & xm);
}
else
assert(false);
}
while ( flags & MORE_COMPONENTS );
if ( flags & WE_HAVE_INSTRUCTIONS )
{
unsigned numInstr = str.GetWord();
for (unsigned i=0; i<numInstr; i++)
str.GetByte();
}
// The purpose of USE_MY_METRICS is to force the lsb and rsb to take on a desired value.
// For example, an i-circumflex (Unicode 00ef) is often composed of the circumflex and a dotless-i.
// In order to force the composite to have the same metrics as the dotless-i,
// set USE_MY_METRICS for the dotless-i component of the composite. Without this bit,
// the rsb and lsb would be calculated from the HMTX entry for the composite (or would need to be
// explicitly set with TrueType instructions).
// Note that the behavior of the USE_MY_METRICS operation is undefined for rotated composite components.
return len;
}
//draw a 2nd-degree Bezier curve segment
BOOL Bezier2(HDC hDC,int & x0,int & y0, int x1, int y1, int x2 ,int y2)
{
// p0 p1 p2 - > p0 (p0 + 2p1)/3 (2p1+p2)/3, p2
POINT P[3] = { { (x0+2*x1)/3,(y0+2*y1)/3},
{(2*x1+x2)/3,(2*y1+y2)/3},
{x2,y2} };
x0=x2;y0=y2;
return PolyBezierTo(hDC,P,3);
}
对于用三个控制点(p0,p1,p2)定义的二阶Bezier曲线,相应的三阶Bezier曲线的控制点为(p0,(p0+2*p1)/3,(2*p1+p2)/3,p2)。
4.图元指令
控制图元中关键位置的尺寸
保持对称性和衬线等 重要的图元设计细节。