void CHYTTFCharacter::InitTTPOLY()
{
if(0 == m_pTTPOLYData) // GetGlyphOutline提取到的字体轮廓数据
{
return;
}
TTPOLYGONHEADER* pTTPOLYGONHEADER = 0;
TTPOLYCURVE* pTTPOLYCURVE = 0;
STTTPOLYGONHEADER* pSTTTPOLYGONHEADER = 0;
STTTPOLYCURVE* pSTTTPOLYCURVE = 0;
unsigned int nTTPOLYDataLen = 0;
unsigned char* pTTPOLYData = m_pTTPOLYData;
unsigned int nCURVELen = 0;
unsigned char* pCURVE = 0;
int nTemp = 0;
while(nTTPOLYDataLen < m_nTTPOLYDataLen)
{
pSTTTPOLYGONHEADER = new STTTPOLYGONHEADER;
m_stTTPOLYGONHEADERVector.push_back(pSTTTPOLYGONHEADER);
pTTPOLYGONHEADER = (TTPOLYGONHEADER*)pTTPOLYData;
memcpy(&(pSTTTPOLYGONHEADER->m_TTPOLYGONHEADER), pTTPOLYGONHEADER, sizeof(TTPOLYGONHEADER));
pCURVE = pTTPOLYData + sizeof(TTPOLYGONHEADER);
nCURVELen = sizeof(TTPOLYGONHEADER);
while(nCURVELen < pTTPOLYGONHEADER->cb)
{
pTTPOLYCURVE = (TTPOLYCURVE*)pCURVE;
pSTTTPOLYCURVE = new STTTPOLYCURVE;
pSTTTPOLYCURVE->Init(pTTPOLYCURVE->wType, pTTPOLYCURVE->cpfx);
pSTTTPOLYGONHEADER->m_stTTPOLYCURVEVector.push_back(pSTTTPOLYCURVE);
memcpy(pSTTTPOLYCURVE->m_p_apfx, pCURVE + sizeof(TTPOLYCURVE) - sizeof(POINTFX),
sizeof(POINTFX) * pTTPOLYCURVE->cpfx);
nTemp = sizeof(TTPOLYCURVE) + sizeof(POINTFX) * (pTTPOLYCURVE->cpfx - 1);
pCURVE += nTemp;
nCURVELen += nTemp;
}
nTTPOLYDataLen += pTTPOLYGONHEADER->cb;
pTTPOLYData += pTTPOLYGONHEADER->cb;
}
}
void CHYTTFCharacter::Draw(HDC hDC, int nOffsetX, int nOffsetY) { int nXTemp, nYTemp, nXBegin, nYBegin; STTTPOLYGONHEADER* pSTTTPOLYGONHEADER = 0; STTTPOLYCURVE* pSTTTPOLYCURVE = 0; int nCountH = m_stTTPOLYGONHEADERVector.size(); int nCountC = 0; int i = 0, j = 0, k = 0; for(i = 0; i < nCountH; ++i) { pSTTTPOLYGONHEADER = m_stTTPOLYGONHEADERVector[i]; nXBegin = nOffsetX + FIXEDToInt(pSTTTPOLYGONHEADER->m_TTPOLYGONHEADER.pfxStart.x); nYBegin = nOffsetY - FIXEDToInt(pSTTTPOLYGONHEADER->m_TTPOLYGONHEADER.pfxStart.y); ::MoveToEx(hDC, nXBegin, nYBegin, NULL); nCountC = pSTTTPOLYGONHEADER->m_stTTPOLYCURVEVector.size(); for(j = 0; j < nCountC; ++j) { pSTTTPOLYCURVE = pSTTTPOLYGONHEADER->m_stTTPOLYCURVEVector[j]; // 这里可以根具线条的类型做样条曲线的绘制, 这样字体会绘制的比较圆滑.***********注意注意***************** // 我这里直接使用直线连接, 有些地方可能绘制的比较粗糙.************************注意注意****************** for(k = 0; k < pSTTTPOLYCURVE->m_cpfx; ++k) { ::LineTo(hDC, nOffsetX + FIXEDToInt(pSTTTPOLYCURVE->m_p_apfx[k].x), nOffsetY - FIXEDToInt(pSTTTPOLYCURVE->m_p_apfx[k].y)); } } ::LineTo(hDC, nXBegin, nYBegin); } }
void CTestTypeDlg::PaintType() { CClientDC dc(this); HDC hDC = dc.GetSafeHdc(); //创建字体 CFont font; VERIFY(font.CreateFont(70, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "宋体")); CFont *pOldFont = dc.SelectObject(&font); // 定义并初始化变换矩阵 MAT2 mat2; memset(&mat2, 0, sizeof(mat2)); mat2.eM11.value = 1; mat2.eM22.value = 1; GLYPHMETRICS metrics; // 保存字符相关信息 DWORD dwDataSize = 0; // 初始化字符数据缓冲区大小 //…… // 通过函数GetGlyphOutline()确定存储字符结构的空间 //char nChar = 'A'; wchar_t nChar = L'A'; ::TextOut(dc.m_hDC, 0, 0, "A", 1); //dwDataSize = pDC->GetGlyphOutline((UINT)nChar, GGO_NATIVE, &metrics, 0, NULL, &mat2); dwDataSize = ::GetGlyphOutlineW(dc.m_hDC, (UINT)nChar, GGO_NATIVE, &metrics, 0, NULL, &mat2); if ((dwDataSize != 0) && (dwDataSize != GDI_ERROR)) { CHYTTFCharacter hyTTFCharacter; hyTTFCharacter.InitTTPOLY(dwDataSize); dwDataSize = ::GetGlyphOutlineW(dc.m_hDC, (UINT)nChar,GGO_NATIVE,&metrics, dwDataSize, hyTTFCharacter.m_pTTPOLYData, &mat2); hyTTFCharacter.InitTTPOLY(); int nXOffset = 200; int nYOffset = 200; hyTTFCharacter.Draw(dc.m_hDC, nXOffset, nYOffset); } }
http://blog.csdn.net/kingstar158/article/details/7257347
HDC hDC = pDC->GetSafeHdc(); //创建字体 CFont font; VERIFY(font.CreateFont(m_iFontHeight, 0, 0, 0,FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS,m_sFontFaceName)); CFont *pOldFont = pDC->SelectObject(&font); //定义并初始化变换矩阵 MAT2 mat2; memset(&mat2, 0, sizeof(mat2)); mat2.eM11 = 1; mat2.eM22 = 1; GLYPHMETRICS metrics; //保存字符相关信息 DWORD dwDataSize = 0; //初始化字符数据缓冲区大小 //…… //通过函数GetGlyphOutline()确定存储字符结构的空间 dwDataSize = pDC->GetGlyphOutline(nChar, GGO_NATIVE, &metrics, 0, NULL, &mat2); if ((dwDataSize != 0) && (dwDataSize != GDI_ERROR)) { //创建保存字符数据缓冲区大小 LPBYTE pPixels = new BYTE[dwDataSize]; ASSERT( pPixels != NULL ); TTPOLYGONHEADER *pHeader = (TTPOLYGONHEADER*)pPixels; dwDataSize = pDC->GetGlyphOutline(nChar,GGO_NATIVE,&metrics, dwDataSize, pPixels, &mat2); while(dwDataSize > 0) { //计算字符轮廓的起点,转换坐标 int xOld = MapFXY(pHeader->pfxStart.x); int yOld = MapFXY(pHeader->pfxStart.y); //根据TTF字体结构获取字符轮廓 ::MoveToEx(hDC,iXpos + xOld,iYpos - yOld,NULL); TTPOLYCURVE *pCurrentCurve = (TTPOLYCURVE*)(pHeader + 1); int remainByte = pHeader->cb - sizeof(TTPOLYGONHEADER); while (remainByte > 0) { CPoint lpPoint[1000]; CPoint bezi[2]; int index; for (index = 0; index < pCurrentCurve->cpfx; ++index) { lpPoint[index].x = iXpos + MapFXY(pCurrentCurve->apfx[index].x); lpPoint[index].y = iYpos - MapFXY(pCurrentCurve->apfx[index].y); } switch (pCurrentCurve->wType) { case TT_PRIM_LINE: case TT_PRIM_QSPLINE: for (index =0; index < pCurrentCurve->cpfx; index++) { ::LineTo(hDC,lpPoint[index].x,lpPoint[index].y); } break; default: MessageBox(_T("字体不支持")); break; } int count = sizeof(TTPOLYCURVE) + (pCurrentCurve->cpfx -1)*sizeof(POINTFX); pCurrentCurve = (TTPOLYCURVE*)((char*)pCurrentCurve + count); remainByte -= count; } ::LineTo(hDC,iXpos + xOld, iYpos - yOld); dwDataSize -= pHeader->cb; pHeader = (TTPOLYGONHEADER*)((char*)pHeader + pHeader->cb); } delete [] pPixels; } }
TTF字体是一种矢量字体. 好处就是可以随便放大, 缩小, 旋转等. 例如做"仿射变换". 而对于位图字体, 如果位图字体很大时, 做这些变换都是对位图上的每一个点来操作的, 效率会很低. 而如果对矢量数据操作的话, 要操作的点是有限的(比位图操作的点要少很多). 所以当你提取到了TTF字体的轮廓数据后, 你想干嘛都可以了(做一些文字的二维处理, 三维处理等都可以)..
但有个问题: 当我提取了TTF字体的轮廓后, 我想填充这些轮廓, 不知怎么填充!!!!!!!!!! (暂时没深入了解,) Windows的API TextOut和DrawText是怎么填充的呢??????????