精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>电脑技术>>● Windows>>【文字处理与打印】>>编程绘制TTF字体外框!

主题:编程绘制TTF字体外框!
发信人: softlag()
整理人: justice(2000-08-22 02:14:27), 站内信件
void Paint(CDC* pDC);
void DrawTTFOutline(CDC* pDC, UINT uChar, int x, int y, int ascent);
int FixedToInt(FIXED f);
FIXED fxDiv2(FIXED fxVal1, FIXED fxVal2);

void Paint(CDC* pDC)
{
CFont curFont;
curFont.CreateFont(60, 0, 0, 0, 400, false, false, 0, 
DEFAULT_CHARSET, 
OUT_DEFAULT_PRECIS, 
CLIP_DEFAULT_PRECIS, 
DEFAULT_QUALITY, 
DEFAULT_PITCH&FF_SWISS, 
"黑体" );
CFont* pOldFont=(CFont*)pDC->SelectObject(&curFont);

TEXTMETRIC tm;
int x=0, y=0;

pDC->GetTextMetrics(&tm);

DrawTTFOutline(pDC, '软', 0, 100, tm.tmAscent);
DrawTTFOutline(pDC, '体', 120, 100, tm.tmAscent);
DrawTTFOutline(pDC, '垃', 240, 100, tm.tmAscent);
DrawTTFOutline(pDC, '圾', 360, 100, tm.tmAscent);

pDC->SelectObject(pOldFont);
}

void DrawTTFOutline(CDC* pDC, UINT uChar, int x, int y, int ascent)
{
GLYPHMETRICS gm;
MAT2 mat;
DWORD dwMemSize; //所需内存空间大小
HGLOBAL hMem; //内存句柄
LPSTR pdwMemBits; //分配的内存 字体外形信息就保存在这段内存中

//分配内存空词
dwMemSize=pDC->GetGlyphOutline(uChar, GGO_NATIVE, &gm, 0, NULL, &mat)
;
hMem=GlobalAlloc(GHND, dwMemSize);
if( hMem==NULL ) 
{
TRACE("分配内存失败!\n");
return;
}
//锁定内存 因为我们要读取这段内存中的数据
pdwMemBits=(LPSTR)GlobalLock(hMem);
if( pdwMemBits==NULL ) 
{
TRACE("锁定内存失败!\n");
return;
}
//获取字体外形信息
if( pDC->GetGlyphOutline(uChar, GGO_NATIVE, &gm, dwMemSize, pdwMemBit
s, &mat)!=dwMemSize)
{
TRACE("获取字体外形信息失败!\n");
return;
}

//设置pDC环境准备绘制uChar
CBrush curBrush(RGB(0, 0, 0));
CBrush* pOldBrush=pDC->SelectObject(&curBrush);
CPoint oldOrg=pDC->GetViewportOrg();
pDC->OffsetViewportOrg( x, y + ascent);

//以下是如何取得字体外形的代码
LPTTPOLYGONHEADER lpHeader;
LPTTPOLYGONHEADER lpStart;
LPTTPOLYCURVE lpCurve;
POINT Points[500];
int nOutlinePt[50]; //每个独立封闭框中的转折点数
int nTotal = 0; //转折点的共和.
int nInOutline; //当前外框曲线中的转折点数
int nOutline = 0; //字体外形中独立的封闭框的数目
int nFirstOutline; //第一条线的起始位置
int i;
POINTFX spline[3];

lpHeader=(LPTTPOLYGONHEADER)pdwMemBits;
lpStart=lpHeader;
     while((DWORD)lpHeader < (DWORD)(((LPSTR)lpStart) + dwMemSize))//循
环直到读完内存中的字形数据
{
if(lpHeader->dwType == TT_POLYGON_TYPE)
{
nInOutline = 0;
//得到第一个外框曲线的地址
     lpCurve = (LPTTPOLYCURVE)(lpHeader + 1);
nFirstOutline = nTotal;

while ((DWORD)lpCurve<(DWORD)(((LPSTR)lpHeader)+lpHeader->cb))//循环
直到取完当前外框中的点
     {
//直线
if (lpCurve->wType==TT_PRIM_LINE)
{
     for (i = 0; i<lpCurve->cpfx; i++)
     {
Points[nTotal].x=FixedToInt(lpCurve->apfx[i].x);
Points[nTotal].y=FixedToInt(lpCurve->apfx[i].y);
nTotal++;
nInOutline++;
  }
}
//曲线 (曲线是一个二次B样条)
else if (lpCurve->wType==TT_PRIM_QSPLINE)
{
spline[0]=*(LPPOINTFX)((LPSTR)lpCurve-sizeof(POINTFX));

     for (i = 0; i<lpCurve->cpfx;)
     {
spline[1]=lpCurve->apfx[i++];
if (i==(lpCurve->cpfx-1))
{
     spline[2]=lpCurve->apfx[i++];
}     
else
{
spline[2].x=fxDiv2(lpCurve->apfx[i-1].x, lpCurve->apfx[i].x);
     spline[2].y=fxDiv2(lpCurve->apfx[i-1].y, lpCurve->apfx[i].y
);
}

Points[nTotal].x=FixedToInt(spline[1].x);
Points[nTotal].y=FixedToInt(spline[1].y);
nTotal++;
Points[nTotal].x=FixedToInt(spline[2].x);
Points[nTotal].y=FixedToInt(spline[2].y);
nTotal++;
nInOutline+=2;

spline[0]=spline[2];
     }
}
else
; //除了直线和曲线还有什么线呢?出错!

//指向下一条线
lpCurve = (LPTTPOLYCURVE)&(lpCurve->apfx[i]);
}

     //增加一个点封闭当前外框.
     Points[nTotal].x = FixedToInt(lpHeader->pfxStart.x)
Points[nTotal].y = FixedToInt(lpHeader->pfxStart.y);
nInOutline++;
     nTotal++;
     Points[nTotal].x = Points[nFirstOutline].x;
Points[nTotal].y = Points[nFirstOutline].y;
     nInOutline++;
     nTotal++;
nOutlinePt[nOutline++] = nInOutline;

//指向下一个外框.
     lpHeader = (LPTTPOLYGONHEADER)(((LPSTR)lpHeader) + lpHeader->cb
);
}
else
; //出错!
}

     for (i = 0; i < nTotal; i++)
Points[i].y=0-Points[i].y;

//好了 点全部已经保存到Points中了 现在该做的是……
i=0;
pDC->SelectStockObject(BLACK_PEN);
for(int a=0; a<nOutline; a++)
{
pDC->MoveTo(Points[i]);
for(int b=0; b<nOutlinePt[a]; b++)
{
pDC->LineTo(Points[i]);
i++;
}
}

pDC->SetViewportOrg( oldOrg.x, oldOrg.y );
pDC->SelectObject( pOldBrush );

GlobalUnlock(hMem);
GlobalFree(hMem);
}

//一种将FIXED转换为INT最笨的方法
int FixedToInt(FIXED f)
{
int value=0x8000*2*f.value+f.fract;
value/=500;//这里的500为字体大小的比例因子 你可以改变它从而缩放字体

return value;
}

FIXED fxDiv2(FIXED fxVal1, FIXED fxVal2)
{
long l;

l = (*((long far *)&(fxVal1)) + *((long far *)&(fxVal2)))/2;
     return(*(FIXED *)&l);
}

--
写了这么多 但愿没有错别字 
http:://softlag.yeah.net

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 61.128.240.88]

[关闭][返回]