C
cdvoice415
Unregistered / Unconfirmed
GUEST, unregistred user!
有个同学毕业设计涉及到关于win API函数GetGlyphOutline()的应用
由于这个API函数十分复杂,查了很多中英文资料还是很难写出程序,
在网上找到的一个程序,了解了程序的流程并编译通过,
但是一按按钮就出错,在变量ptn处,我不是高手,无法解决
敬请各位大侠帮忙!thx!!
程序如下:
#include <stdlib.h>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect ClipRect=Rect(0,0,Image1->Width,Image1->Height);
Image1->Picture=0;
StretchTextRect(Image1->Canvas,ClipRect,Edit1->Text);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StretchTextRect(TCanvas*pCanvas, TRect ClipRect, AnsiString Text)
{
pCanvas->Font->Size=100;
pCanvas->Font->Name="宋体";
pCanvas->Pen->Color=clBlack;
pCanvas->Pen->Mode=pmCopy;
pCanvas->Pen->Style=psSolid;
pCanvas->Pen->Width=1;
int XSize = ClipRect.Width() / Text.Length();
int YSize = ClipRect.Height();
MAT2 mat2;
// 转置矩阵,不用变换
mat2.eM11.value = 1;mat2.eM11.fract = 0;
mat2.eM12.value = 0;mat2.eM12.fract = 0;
mat2.eM21.value = 0;mat2.eM21.fract = 0;
mat2.eM22.value = 1;mat2.eM22.fract = 0;
GLYPHMETRICS gm,gmm;
// 首先获得字符的位置矩阵,存入gm
GetGlyphOutlineA(pCanvas->Handle,0x0b0a1,GGO_METRICS,&gm,0,NULL,&mat2);
char *ptr = Text.c_str();
TRect TheRect;
for(int i = 0;i < Text.Length()
{
int c1 = (unsigned char)*ptr;
int c2 = (unsigned char)*(ptr + 1);
UINT nChar;
TheRect.Left = i * XSize + ClipRect.Left;
TheRect.Top = ClipRect.Top;
TheRect.Right = (i + 2) * XSize + ClipRect.Left;
TheRect.Bottom = ClipRect.Top + YSize;
if(c1 > 127)
{ // 当前字符是汉字
nChar = c1 * 256 + c2;
ptr+=2;i+=2;
}
else
{ // 字母或数字
nChar = c1;
ptr++;i++;
}
// 获得当前字符数据的数组的大小
DWORD cbBuffer = GetGlyphOutlineA(pCanvas->
Handle,nChar,GGO_NATIVE,&gmm,0,NULL,&mat2);
if(cbBuffer == GDI_ERROR) break;
void *lpBuffer = malloc(cbBuffer);
if(lpBuffer != NULL)
{
// 读入数据置缓冲区
if(GetGlyphOutlineA(pCanvas->Handle,nChar,GGO_NATIVE,&gmm,cbBuffer,lpBuffer,&mat2) != GDI_ERROR)
{
// 分析数据并绘制字符
TMemoryStream *MBuffer = new TMemoryStream();
MBuffer->Write(lpBuffer,cbBuffer);
MBuffer->Position = 0;
for(;MBuffer->Position < MBuffer->Size
{
int CurPos = MBuffer->Position;
TTPOLYGONHEADER polyheader;
int ptn = 0;
MBuffer->Read(&polyheader,sizeof(polyheader));
ptn++;
for(int j = 0;j < (int)(polyheader.cb- sizeof(polyheader))
{
WORD wtype,cpfx;
MBuffer->Read(&wtype,sizeof(WORD));
MBuffer->Read(&cpfx,sizeof(WORD));
MBuffer->Position += cpfx * sizeof(POINTFX);
j += sizeof(WORD) * 2 + cpfx * sizeof(POINTFX);
if(wtype == TT_PRIM_LINE) ptn += cpfx;
else
ptn += (cpfx - 1) * 3 + 1;
}
TPoint *pts = new TPoint[ptn+1];
// 存储多边形顶点
MBuffer->Position = CurPos;
ptn = 0;
MBuffer->Read(&polyheader,sizeof(polyheader));
TPoint pt0 = POINTFX2TPoint(polyheader.pfxStart,TheRect,&gm);
pts[ptn++] = pt0;
for(int j = 0;j < (int)(polyheader.cb - sizeof(polyheader))
{
TPoint pt1;
WORD wtype,cpfx;
MBuffer->Read(&wtype,sizeof(WORD));
MBuffer->Read(&cpfx,sizeof(WORD));
POINTFX *pPfx = new POINTFX[cpfx];
MBuffer->Read((void *)pPfx,cpfx * sizeof(POINTFX));
j +=sizeof(WORD) * 2 + cpfx * sizeof(POINTFX);
if(wtype == TT_PRIM_LINE)
{ // 直线段
for(int i = 0;i < cpfx;i++)
{
pt1 = POINTFX2TPoint(pPfx,TheRect,&gm);
pts[ptn++] = pt1;
}
}
else
{ // Bezier曲线
TPoint p0,p1,p2,p3,p11,p22,pp0,pp1,pp2,pt11,pt22;
int i;
for(i = 0;i < cpfx-1;i++)
{
pt11 = POINTFX2TPoint(pPfx,TheRect,&gm);
pt22 = POINTFX2TPoint(pPfx[i+1],TheRect,&gm);
pp0 = pts[ptn-1];
pp1 = pt11;
pp2.x = (pt11.x + pt22.x)/2;
pp2.y = (pt11.y +pt22.y)/2;
p0 = pp0;
p1.x = pp0.x/3+2 *pp1.x/3;
p1.y = pp0.y/3 +2 *pp1.y/3;
p2.x = 2 *pp1.x/3 +pp2.x/3;
p2.y = 2 *pp1.y/3 +pp2.y/3;
p3 = pp2;
for(float t = 0.0f;t <= 1.0f;t + 0.5f)
{
float x = (1-t)*(1-t)*(1-t)*p0.x+3*t*(1-t)*(1-t)*p1.x+3*t*t*(1-t)*p2.x +t*t*t*p3.x;
float y = (1-t)*(1-t)*(1-t)*p0.y+ 3*t*(1-t)*(1-t)*p1.y+3*t*t*(1-t)*p2.y + t*t*t*p3.y;
pts[ptn].x = x;
pts[ptn].y = y;
ptn++;
}
}
pt1 = POINTFX2TPoint(pPfx,TheRect,&gm);
pts[ptn++] = pt1;
}
delete pPfx;
}
pts[ptn] = pts[0];
// 封闭多边形
pCanvas->Brush->Color = clWhite;
pCanvas->Pen->Mode = pmXor;
pCanvas->Pen->Style = psClear;
pCanvas->Brush->Style = bsSolid;
pCanvas->Polygon(pts,ptn);
delete pts;
}
delete MBuffer;
}
free(lpBuffer);
}
}
}
//---------------------------------------------------------------------------
TPoint __fastcall TForm1:OINTFX2TPoint(POINTFX pf,TRect TheRect,GLYPHMETRICS *gm)
{
TPoint point;
float fx,fy;
fx = pf.x.value + pf.x.fract / 65536.0f + 0.5f;
fx = fx/ (float)(gm->gmBlackBoxX + gm->gmptGlyphOrigin.x)* (float)TheRect.Width() + (float)TheRect.Left;
fy = pf.y.value + pf.y.fract / 65536.0f + 0.5f;
fy = ((float)gm->gmBlackBoxY - fy)/ (float)(gm->gmBlackBoxX + gm->gmptGlyphOrigin.x)* (float)TheRect.Height() + (float)TheRect.Top;
point.x = int(fx);
point.y = int(fy);
return point;
}
由于这个API函数十分复杂,查了很多中英文资料还是很难写出程序,
在网上找到的一个程序,了解了程序的流程并编译通过,
但是一按按钮就出错,在变量ptn处,我不是高手,无法解决
敬请各位大侠帮忙!thx!!
程序如下:
#include <stdlib.h>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect ClipRect=Rect(0,0,Image1->Width,Image1->Height);
Image1->Picture=0;
StretchTextRect(Image1->Canvas,ClipRect,Edit1->Text);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StretchTextRect(TCanvas*pCanvas, TRect ClipRect, AnsiString Text)
{
pCanvas->Font->Size=100;
pCanvas->Font->Name="宋体";
pCanvas->Pen->Color=clBlack;
pCanvas->Pen->Mode=pmCopy;
pCanvas->Pen->Style=psSolid;
pCanvas->Pen->Width=1;
int XSize = ClipRect.Width() / Text.Length();
int YSize = ClipRect.Height();
MAT2 mat2;
// 转置矩阵,不用变换
mat2.eM11.value = 1;mat2.eM11.fract = 0;
mat2.eM12.value = 0;mat2.eM12.fract = 0;
mat2.eM21.value = 0;mat2.eM21.fract = 0;
mat2.eM22.value = 1;mat2.eM22.fract = 0;
GLYPHMETRICS gm,gmm;
// 首先获得字符的位置矩阵,存入gm
GetGlyphOutlineA(pCanvas->Handle,0x0b0a1,GGO_METRICS,&gm,0,NULL,&mat2);
char *ptr = Text.c_str();
TRect TheRect;
for(int i = 0;i < Text.Length()
{
int c1 = (unsigned char)*ptr;
int c2 = (unsigned char)*(ptr + 1);
UINT nChar;
TheRect.Left = i * XSize + ClipRect.Left;
TheRect.Top = ClipRect.Top;
TheRect.Right = (i + 2) * XSize + ClipRect.Left;
TheRect.Bottom = ClipRect.Top + YSize;
if(c1 > 127)
{ // 当前字符是汉字
nChar = c1 * 256 + c2;
ptr+=2;i+=2;
}
else
{ // 字母或数字
nChar = c1;
ptr++;i++;
}
// 获得当前字符数据的数组的大小
DWORD cbBuffer = GetGlyphOutlineA(pCanvas->
Handle,nChar,GGO_NATIVE,&gmm,0,NULL,&mat2);
if(cbBuffer == GDI_ERROR) break;
void *lpBuffer = malloc(cbBuffer);
if(lpBuffer != NULL)
{
// 读入数据置缓冲区
if(GetGlyphOutlineA(pCanvas->Handle,nChar,GGO_NATIVE,&gmm,cbBuffer,lpBuffer,&mat2) != GDI_ERROR)
{
// 分析数据并绘制字符
TMemoryStream *MBuffer = new TMemoryStream();
MBuffer->Write(lpBuffer,cbBuffer);
MBuffer->Position = 0;
for(;MBuffer->Position < MBuffer->Size
{
int CurPos = MBuffer->Position;
TTPOLYGONHEADER polyheader;
int ptn = 0;
MBuffer->Read(&polyheader,sizeof(polyheader));
ptn++;
for(int j = 0;j < (int)(polyheader.cb- sizeof(polyheader))
{
WORD wtype,cpfx;
MBuffer->Read(&wtype,sizeof(WORD));
MBuffer->Read(&cpfx,sizeof(WORD));
MBuffer->Position += cpfx * sizeof(POINTFX);
j += sizeof(WORD) * 2 + cpfx * sizeof(POINTFX);
if(wtype == TT_PRIM_LINE) ptn += cpfx;
else
ptn += (cpfx - 1) * 3 + 1;
}
TPoint *pts = new TPoint[ptn+1];
// 存储多边形顶点
MBuffer->Position = CurPos;
ptn = 0;
MBuffer->Read(&polyheader,sizeof(polyheader));
TPoint pt0 = POINTFX2TPoint(polyheader.pfxStart,TheRect,&gm);
pts[ptn++] = pt0;
for(int j = 0;j < (int)(polyheader.cb - sizeof(polyheader))
{
TPoint pt1;
WORD wtype,cpfx;
MBuffer->Read(&wtype,sizeof(WORD));
MBuffer->Read(&cpfx,sizeof(WORD));
POINTFX *pPfx = new POINTFX[cpfx];
MBuffer->Read((void *)pPfx,cpfx * sizeof(POINTFX));
j +=sizeof(WORD) * 2 + cpfx * sizeof(POINTFX);
if(wtype == TT_PRIM_LINE)
{ // 直线段
for(int i = 0;i < cpfx;i++)
{
pt1 = POINTFX2TPoint(pPfx,TheRect,&gm);
pts[ptn++] = pt1;
}
}
else
{ // Bezier曲线
TPoint p0,p1,p2,p3,p11,p22,pp0,pp1,pp2,pt11,pt22;
int i;
for(i = 0;i < cpfx-1;i++)
{
pt11 = POINTFX2TPoint(pPfx,TheRect,&gm);
pt22 = POINTFX2TPoint(pPfx[i+1],TheRect,&gm);
pp0 = pts[ptn-1];
pp1 = pt11;
pp2.x = (pt11.x + pt22.x)/2;
pp2.y = (pt11.y +pt22.y)/2;
p0 = pp0;
p1.x = pp0.x/3+2 *pp1.x/3;
p1.y = pp0.y/3 +2 *pp1.y/3;
p2.x = 2 *pp1.x/3 +pp2.x/3;
p2.y = 2 *pp1.y/3 +pp2.y/3;
p3 = pp2;
for(float t = 0.0f;t <= 1.0f;t + 0.5f)
{
float x = (1-t)*(1-t)*(1-t)*p0.x+3*t*(1-t)*(1-t)*p1.x+3*t*t*(1-t)*p2.x +t*t*t*p3.x;
float y = (1-t)*(1-t)*(1-t)*p0.y+ 3*t*(1-t)*(1-t)*p1.y+3*t*t*(1-t)*p2.y + t*t*t*p3.y;
pts[ptn].x = x;
pts[ptn].y = y;
ptn++;
}
}
pt1 = POINTFX2TPoint(pPfx,TheRect,&gm);
pts[ptn++] = pt1;
}
delete pPfx;
}
pts[ptn] = pts[0];
// 封闭多边形
pCanvas->Brush->Color = clWhite;
pCanvas->Pen->Mode = pmXor;
pCanvas->Pen->Style = psClear;
pCanvas->Brush->Style = bsSolid;
pCanvas->Polygon(pts,ptn);
delete pts;
}
delete MBuffer;
}
free(lpBuffer);
}
}
}
//---------------------------------------------------------------------------
TPoint __fastcall TForm1:OINTFX2TPoint(POINTFX pf,TRect TheRect,GLYPHMETRICS *gm)
{
TPoint point;
float fx,fy;
fx = pf.x.value + pf.x.fract / 65536.0f + 0.5f;
fx = fx/ (float)(gm->gmBlackBoxX + gm->gmptGlyphOrigin.x)* (float)TheRect.Width() + (float)TheRect.Left;
fy = pf.y.value + pf.y.fract / 65536.0f + 0.5f;
fy = ((float)gm->gmBlackBoxY - fy)/ (float)(gm->gmBlackBoxX + gm->gmptGlyphOrigin.x)* (float)TheRect.Height() + (float)TheRect.Top;
point.x = int(fx);
point.y = int(fy);
return point;
}