如何绘制truetype标志符号轮廓剖析.docx
《如何绘制truetype标志符号轮廓剖析.docx》由会员分享,可在线阅读,更多相关《如何绘制truetype标志符号轮廓剖析.docx(14页珍藏版)》请在冰豆网上搜索。
如何绘制truetype标志符号轮廓剖析
从TrueType字体, GetGlyphOutline的Win32API函数可以返回本机标志符号轮廓数据。
若要绘制一个TrueType标志符号轮廓,数据必须转换从其本机B样条定义为贝塞尔行定义的序列。
然后可以使用PolyBezier的Win32API函数来绘制轮廓。
在Win32应用程序编程Interface(API) GetGlyphOutline函数可检索TrueType大纲。
GGO_NATIVE格式选项填充缓冲区与TrueType轮廓的二次B样条曲线。
二次B样条由TrueType中用于描述TrueType字体文件中的标志符号轮廓。
绘制这些轮廓曲线一个可以实现的B样条绘图函数或使用PolyBezier函数的Win32API。
二次B样条曲线是一类的参数化曲线定义多个通过几个控制点的曲线段的路径。
一条二次曲线是第二个顺序参数化曲线。
没有要绘制直接但如果二次将转换为一个三次方,它可以绘制用Win32API函数用于绘制贝塞尔曲线;二次样条的API中的函数调用的PolyBezier。
特定和参数化曲线中的二次B样条曲线通常是计算机科学中的图形完善查主题。
它们也可以非常复杂。
各种文本中发布了算法可用于实现的函数来绘制一个二次样条,但描述这样的算法是超出了本文的范围。
由于贝塞尔曲线是一条三次或第三个单参数化曲线, PolyBezier函数可以绘制二次样条。
由于二次样条的第二个订单方程,它可以在更高的订单立方公式方面表示。
尽管表达为立方二次公式给出的示例代码中,不是本文中讨论其派生。
本文中的代码示例将演示如何分析GGO_NATIVE标志符号缓冲区GetGlyphOutline函数返回。
GGO_NATIVE格式标志返回的缓冲区符合的TTPOLYGONHEADER结构。
TTPOLYGONHEADER结构和紧跟在它后面的数据构成TrueType标志符号的一个的轮廓。
轮廓线是一个完整路径的曲线,则隐式关闭,如果它不会显式返回通过这种方式。
请上的TTPOLYGONHEADER和TTPOLYCURVE结构,参阅平台SDK文档。
标志符号轮廓包含,由TTPOLYCURVE结构的多个曲线段。
在轮廓, TTPOLYGONHEADER后跟一个或多个TTPOLYCURVE结构和点坐标数据。
PfxStart成员给出轮廓线的起始坐标的点。
按照TTPOLYGONHEADER的曲线记录的计数是赋予cb成员。
相对于标志符号原点是起始点。
标志符号原点是左下的角处的字符基线的字符。
每个TTPOLYCURVE曲线记录(曲线段)组成,二次B样条控制点或简单的折线点。
由TTPOLYCURVEcpfx成员给出点的计数。
由wType成员给出的折线或样条曲线类型。
坐标的点数组紧跟结构。
由apfx成员给出曲线的起始点。
由于标志符号可能包含多个轮廓,在缓冲区中包含一个或多个组的TTPOLYGONHEADER结构和数据。
后续的轮廓被打包紧跟上一个本机的缓冲区中。
下一步的轮廓开始在曲线上一个记录的最后一个点之外的下一个字节的TTPOLYGONHEADER 。
此示例代码通过分析GGO_NATIVE缓冲区创建列表的窗体中每个轮廓的贝塞尔线段绘制轮廓的TrueType标志符号。
然后使用PolyBezier绘制贝塞尔曲线的直线段的列表。
将分析该缓冲区的代码是DrawT2Outline函数中。
若要创建贝塞尔行的列表的第一步是确定列表缓冲区的大小。
四个点定义贝塞尔行。
PolyBezier函数将解释视为一个连续的行位置的下一行开始就是与前一行的终结点的贝塞尔线段的点的数组。
因此,只有三个点都需要描述其他贝塞尔曲线线段。
折线曲线或二次B样条曲线,可能包含GGO_NATIVE缓冲区。
两个点定义一条线段,而三个点定义B样条。
由于每一种类型是绘制贝塞尔行使用PolyBezier,最坏的情况发生时是完全由直线段组成的一个轮廓将扩展到多个贝赛尔曲线。
请注意表示附加曲线段B样条曲线表示中的要求只有一分。
该点明确地定义了"B"或关闭曲线点和隐式定义了附加曲线点。
上的曲线点是下一个"B"点到点。
因此额外的线段或一条附加曲线段将扩展到三个的其他点的贝塞尔行。
该代码假定整个本地缓冲区将POINTFX结构组成,因此它可以确定点所表示的缓冲区的最大可能数。
实际的数字,略小的这是因为没有结构开销中描述的轮廓线和曲线。
由最大可能数点乘以数据结构大小的点和乘以三,给出的贝塞尔曲线列表缓冲区的大小。
三是其他所需的每个额外的线段或二次样条线段时转换为贝塞尔曲线的点的数量。
一旦贝塞尔缓冲区已被分配了该代码将第一个TTPOLYGONHEADER处开始分析本机的缓冲区。
该循环的迭代过程代码处理一个轮廓,并将其绘制。
第二个内部循环分析每种曲线类型。
对于折线曲线(TT_PRIM_LINE),折线的每条线段转换并附加到的贝赛尔曲线与AppendPolyLineToBezier函数的列表。
如果该曲线二次B样条(TT_PRIM_QSPLINE), AppendQuadBSplineToBezier函数转换,并将追加二次B样条。
上述每个函数使用循环到其独立控制点分析出每个曲线段。
然后直线或曲线转换为贝塞尔曲线,并附加到列表中的贝赛尔曲线。
贝塞尔行可以轻松地绘制一条直线。
开始和结束的媒介只是点的直线段的另一端。
这是MakeBezierFromLine函数中。
若要将转换的三次方贝塞尔样条二次曲线要求表达方面的二次控制点立方的控制点。
若要翻译的控制点的计算公式位于MakeBezierFromQBSpline函数。
之前绘制轮廓后,代码将确保路径通过调用CloseContour函数关闭。
只有开始和一系列的贝赛尔曲线的结束点不重合,则调用的函数。
然后将调用PolyBezier函数。
绘制轮廓后下,一步的轮廓线TTPOLYGONHEADER发现的推进lpHeader指针当前轮廓中的记录的末尾之外。
如果这会导致超出缓冲区结尾的本机指针的值,该代码已处理所有的轮廓,并将退出。
/****************************************************************************
*FUNCTION:
IntFromFixed
*RETURNS:
intvalueapproximatingtheFIXEDvalue.
****************************************************************************/
intPASCALNEARIntFromFixed(FIXEDf)
{
if(f.fract>=0x8000)
return(f.value+1);
else
return(f.value);
}
/****************************************************************************
*FUNCTION:
fxDiv2
*RETURNS:
(val1+val2)/2forFIXEDvalues
****************************************************************************/
FIXEDPASCALNEARfxDiv2(FIXEDfxVal1,FIXEDfxVal2)
{
longl;
l=(*((longfar*)&(fxVal1))+*((longfar*)&(fxVal2)))/2;
return(*(FIXED*)&l);
}
/****************************************************************************
*FUNCTION:
MakeBezierFromLine
*
*PURPOSE:
ConvertsalinedefinebytwopointstoafourpointBezier
*splinerepresentationofthelineinpPts.
*
*
*RETURNS:
numberofBezierpointsplacedintothepPtsPOINTarray.
****************************************************************************/
UINTMakeBezierFromLine(POINT*pPts,POINTstartpt,POINTendpt)
{
UINTcTotal=0;
//startingpointofBezier
pPts[cTotal]=startpt;
cTotal++;
//1rstControl,pt==endpointmakesBezieraline
pPts[cTotal].x=endpt.x;
pPts[cTotal].y=endpt.y;
cTotal++;
//2ndControl,pt==startpointmakesBezieraline
pPts[cTotal].x=startpt.x;
pPts[cTotal].y=startpt.y;
cTotal++;
//endingpointofBezier
pPts[cTotal]=endpt;
cTotal++;
returncTotal;
}
/****************************************************************************
*FUNCTION:
MakeBezierFromQBSpline
*
*PURPOSE:
ConvertsaquadraticsplineinpSlinetoafourpointBezier
*splineinpPts.
*
*
*RETURNS:
numberofBezierpointsplacedintothepPtsPOINTarray.
****************************************************************************/
UINTMakeBezierFromQBSpline(POINT*pPts,POINTFX*pSpline)
{
POINTP0,//Quadraticoncurvestartpoint
P1,//Quadraticcontrolpoint
P2;//Quadraticoncurveendpoint
UINTcTotal=0;
//ConverttheQuadraticpointstointeger
P0.x=IntFromFixed(pSpline[0].x);
P0.y=IntFromFixed(pSpline[0].y);
P1.x=IntFromFixed(pSp