mfc 绘制文字轮廓

来源:互联网 发布:敏捷地产 知乎 编辑:程序博客网 时间:2024/05/01 03:59
  CClientDC dc(this);
  dc.SetBkMode(TRANSPARENT);
  dc.SetPolyFillMode(WINDING);

   

  CFont hFont,*hOldFont;
  //创建字体及其大小
  if(hFont.CreateFont(256,0,0,0,
400,0,
0,0,DEFAULT_CHARSET,
OUT_TT_PRECIS,CLIP_TT_ALWAYS, 
PROOF_QUALITY ,DEFAULT_PITCH, 
"黑体")==0)
AfxMessageBox("创建字体失败");

hOldFont=dc.SelectObject(&hFont); 
dc.BeginPath();
dc.TextOut(0,0,"你好");
dc.EndPath();
int PtNum;
POINT *Pt;
BYTE  *PtType;

dc.FlattenPath(); 
PtNum=dc.GetPath(NULL,NULL,0);
Pt=new POINT[PtNum];
PtType=new BYTE[PtNum];

//此处可以得到文字的矢量信息
//PtType 每一个的类型,该做如何处理
//Pt 每一个点的坐标
//PtNum 点的数量
//可以输入m_TextStr形成自己的字库
dc.GetPath(Pt,PtType,PtNum);

dc.SelectObject(hOldFont); 
hFont.DeleteObject(); 

//------测试将得到的矢量信息显示出来-----
int i;
CString str;
for(i=0;i<PtNum;i++)
{
switch(PtType[i]){
case PT_MOVETO:
dc.MoveTo(Pt[i]);
//str.Format("%d",i); 
//dc.TextOut(Pt[i].x,Pt[i].y,str); 
break;
case PT_LINETO|PT_CLOSEFIGURE:
dc.LineTo(Pt[i]);
//str.Format("%d",i); 
//dc.TextOut(Pt[i].x,Pt[i].y,str); 
break; 
case PT_LINETO:
dc.LineTo(Pt[i]);
//str.Format("%d",i); 
//dc.TextOut(Pt[i].x,Pt[i].y,str); 
break; 
}

}
delete []PtType;

delete []Pt;




/ 提取Windows的TTF字体轮廓矢量数据
void CSampleDlg::OnOK() 
{
// TODO: Add extra validation here
//GetGlyphOutline()

UpdateData();

CDC *pDC = m_image.GetDC();

//pDC->TextOut(50, 50, m_str);

CFont font;
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfHeight = 48;
strcpy(lf.lfFaceName, "华文行楷");
font.CreateFontIndirect(&lf);
pDC->SelectObject(&font);

CRect rc;
m_image.GetClientRect(&rc);

int XSize = rc.Width() / m_str.GetLength();
int YSize = rc.Height();

//pDC->GetGlyphOutline(m_str[0],)

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
pDC->GetGlyphOutlineA(0x0b0a1, GGO_METRICS, &gm, 0, NULL, &mat2);

char *ptr = m_str.GetBuffer(0);
CRect TheRect;
for(int i = 0;i < m_str.GetLength();) 
{
int c1 = (unsigned char)*ptr;
int c2 = (unsigned char)*(ptr + 1);
UINT nChar;
TheRect.left = i * XSize + rc.left;
TheRect.top = rc.top;
TheRect.right = (i + 2) * XSize + rc.left;
TheRect.bottom = rc.top + YSize;
if(c1 > 127) 
{  // 当前字符是汉字
nChar = c1 * 256 + c2;
ptr += 2; i += 2;
}
else 
{   // 字母或数字
nChar = c1;
ptr++; i++;
}

// 获得当前字符数据的数组的大小
DWORD cbBuffer = pDC->GetGlyphOutline(nChar, GGO_NATIVE, &gmm, 0, NULL, &mat2);
if(cbBuffer == GDI_ERROR) break;
char *lpBuffer = (char*)malloc(cbBuffer);
if(lpBuffer != NULL) 
{
// 读入数据置缓冲区
if(pDC->GetGlyphOutline(nChar, GGO_NATIVE, &gmm, cbBuffer, lpBuffer, &mat2) != GDI_ERROR)
{
// 分析数据并绘制字符
int pos = 0;
for(;pos < cbBuffer;) 
{
int CurPos = pos;
TTPOLYGONHEADER polyheader;

int ptn = 0;
memcpy(&polyheader, lpBuffer + pos, sizeof(polyheader));
pos += sizeof(polyheader);
ptn++;
for(int j = 0; j < (int)(polyheader.cb - sizeof(polyheader));) 
{
WORD wtype,cpfx;
memcpy(&wtype, lpBuffer + pos, sizeof(WORD));
pos += sizeof(WORD);
memcpy(&cpfx, lpBuffer + pos, sizeof(WORD));
pos += sizeof(WORD);
pos += cpfx * sizeof(POINTFX);
j += sizeof(WORD) * 2 + cpfx * sizeof(POINTFX);
if(wtype == TT_PRIM_LINE) ptn += cpfx;
else ptn += (cpfx - 1) * 3 + 1;
}

CPoint *pts = new CPoint[ptn + 1];  // 存储多边形顶点
pos = CurPos;
ptn = 0;
memcpy(&polyheader, lpBuffer + pos, sizeof(polyheader));
pos += sizeof(polyheader);
CPoint pt0 = POINTFX2TPoint(polyheader.pfxStart, TheRect, &gm);
pts[ptn++] = pt0;
{
for(int j = 0;j < (int)(polyheader.cb - sizeof(polyheader));) 
{
CPoint pt1;
WORD wtype,cpfx;
memcpy(&wtype, lpBuffer + pos, sizeof(WORD));
pos += sizeof(WORD);
memcpy(&cpfx, lpBuffer + pos, sizeof(WORD));
pos += sizeof(WORD);
POINTFX *pPfx = new POINTFX[cpfx];
memcpy((void *)pPfx, lpBuffer + pos, cpfx * sizeof(POINTFX));
pos += 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[i],TheRect, &gm);
pts[ptn++] = pt1;
}
}
else 
{  // Bezier曲线
CPoint p0,p1,p2,p3,p11,p22,pp0,pp1,pp2,pt11,pt22;
int i;
for(i = 0; i < cpfx - 1; i++) 
{
pt11 = POINTFX2TPoint(pPfx[i], 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[i], TheRect, &gm);
pts[ptn++] = pt1;
}
delete pPfx;
}
}
pts[ptn] = pts[0]; // 封闭多边形

pDC->Polygon(pts, ptn);

delete pts;
}
}
free(lpBuffer);
}
}

m_str.ReleaseBuffer();

//pDC->TextOut(50, 50, m_str);

font.DeleteObject();
pDC->DeleteDC();

//CDialog::OnOK();
}

0 0
原创粉丝点击