1、引言
傳統上的字模信息一般都是從點陣字體中得到的。然而,點陣字體有一個致命的缺點就是字模信息大小固定,放大字體將產生嚴重的鋸齒形失真。本文介紹了一種利用VC從TTF字體中直接獲取字符的字模信息的方法,所獲取的字模信息可以達到近似無限的分辨率,可選擇2級、5級、17級和65級等多種灰度級,最終將字模信息保存為BMP位圖文件格式,方便對字模信息的利用。
2、TTF介紹
TTF是Microsoft公司和Apple公司共同推出的一種輪廓字體。TTF的主要其設計思想是:用一系列點構造字型輪廓,在此基礎上用一系列指令調節,使輪廓線變的平滑,從而得到良好的顯示效果。TTF是一種矢量字體,可進行字體的無級放大,快速變形等,放大後的字體平常圓潤,沒有鋸齒形失真。利用矢量字庫進行字型變換,如平衡、縮放、旋轉、 傾斜等,速度快,失真小,效果好,可產生高質量的漢字輸出。由於windows操作系統的流行,TTF已成為字體顯示的主流,其資源相當豐富,就windows自身就帶有上百種TTF字體,網絡上可供下載的字體資源大部分也是TTF格式。而反觀傳統的點陣字體,由於其資源相對較少,字體大小固定單一,在放大縮小時很困難,效果也不好,速度慢,字體單調,鋸齒形失真嚴重,很難達到美觀的要求。因而,利用TTF字體來替代點陣字體,以期獲取更多種類、更多分辨率、更多灰度級的字模信息,滿足社會上對字模信息的多樣要求,便是十分必要的。
3、提取TTF字體中字符的字模信息
首先,把所要用的TTF字體庫選入當前的DC(Device Context)設備上下文中
CFont newfont;
newfont.CreateFont(m_intHeight,
0,
m_intAngle,
0,
m_intBold,
m_bCheckItalic,
0,
0,
DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS,
CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
m_strFontName); //m_strFontName為TTF字體名
//m_intHeight設置字體的高度,值越大,最終獲取的字模的分辨率越高。
//m_intAngle設置字體的旋轉角度,m_intBold設置字體的粗細程度
//m_bCheckItalic設置字體為斜體與否
CDC* pdc=m_ctlDisplay.GetDC();//獲取控件m_ctlDisplay的DC
CFont *poldfont=pdc->SelectObject(&newfont);//將TTF字體對象選入控件m_ctlDisplay的DC中
接下來主要是利用Win32的API函數GetGlyphOutline()來提取TTF字體的字模信息
DWORD GetGlyphOutline(
HDC hdc, // DC句柄
UINT uChar, // 要提取字模的字符
UINT uFormat, // 函數返回的信息格式
LPGLYPHMETRICS lpgm, // GLYPHMETRICS結構的指針
DWORD cbBuffer, // 接收緩存的大小
LPVOID lpvBuffer, // 接收緩存的地址
CONST MAT2 *lpmat2 // MAT2結構的指針
);
若接收緩存的地址設置為NULL則GetGlyphOutline()函數返回字模信息所需的存儲空間的大小。若返回的存儲空間大小nLen大於零,則可以獲取指定的字模信息,否則,表示返回失敗,需重新設置字體。對GetGlyphOutline()函數的第三個參數uFormat分別設置為GGO_BITMAP,GGO_GRAY2_BITMAP,GGO_GRAY4_BITMAP,GGO_GRAY8_BITMAP就可以獲取2級、5級、17級和65級灰度的字模信息。返回的字體信息是按行進行4字節對齊的,必須經過適當處理以獲取字模的大小對於2級灰度的字模信息,1位表示一個像素,所示字模的寬度(按字節計)為charLineW=(glpm.gmBlackBoxX/32+(glpm.gmBlackBoxX%32==0?0:1))*4;
// glpm為返回的LPGLYPHMETRICS結構體
對於5級、17級和65級灰度的字模信息,1字節表示一個像素,所以字模的寬度(按字節計)為
charLineW=(glpm.gmBlackBoxX/4+(glpm.gmBlackBoxX%4==0?0:1))*4;
4、字模信息的顯示與保存
所獲取的字模信息為一像素矩陣,可以用位圖來顯示與保存為了顯示和保存位圖,須構造位圖的信息頭結構體BITMAPINFO,該結構體在MSDN上有說明,主要是用來解析BMP格式的位圖文件的。根據字模信息的灰度級數,設定不同的顏色數,如果為2級則為黑白兩色。若是5級、17級和65級灰度,則在0~255中平均分配不同的灰度。顯示位圖時利用了顯示緩存來加快字體的顯示,即在內存中申請一空間,將字模信息繪於此空間,然後將其整個“貼”到顯示界面上。
CRect rect;
GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(&rect); //獲取顯示控件的大小
CDC memdc; //申請一顯示緩存的DC(Device Context,設備上下文 )memdc.CreateCompatibleDC(pdc);
CBitmap nbitmap,*poldbitmap;
nbitmap.CreateCompatibleBitmap(pdc,rect.Width(),rect.Height());
//創建合適的位圖
poldbitmap=memdc.SelectObject(&nbitmap); //將所創建的位圖選入顯示緩存的DC
::StretchDIBits(memdc.m_hDC,
-m_intScrollHPos,
-m_intScrollVPos,
m_intPixX,
m_intPixY,0,0,
m_intPixX,
m_intPixY,
pBuf,pbmpinfo,
DIB_RGB_COLORS,
SRCCOPY);
//將圖像數據繪於顯示緩存的DC上
pdc->BitBlt(0,0,rect.Width(),rect.Height(),&memdc,0,0,SRCCOPY);
//將顯示緩存上的圖像按顯示控件的大小”貼”到圖像顯示控件上
memdc.DeleteDC();//釋放顯示緩存的DC
如果要保存字模信息為bmp位圖文件,需構造位圖文件的文件頭結構體BITMAPFILEHEADER。 然後,新建一文件,寫入位圖的各種信息即可。 CFile cf;
5、程序的運行
cf.Open(strfile,CFile::modeCreate|CFile::modeWrite);
cf.Write(pfileinfo,sizeof(BITMAPFILEHEADER));//寫入文件頭信息
cf.Write(pbmpinfo,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*BITSTABLE[m_intBits-1]);
//寫入位圖的信息頭和顏色表
cf.Write(pBuf,charLineW*m_intPixY);//寫入位圖數據
cf.Close();
整個程序實現了從TTF字體中提取字模信息並最終保存為BMP位圖文件的功能。其中,TTF字體可以在字體列表中選擇,字模的高度、粗細、角度、斜體、反色和灰度級數可以選擇,適應了各種場合對字模信息的不同要求。字模信息最後保存為BMP位圖文件,方便後繼各種針對字模應用的處理,諸如字模顯示,字模處理等。
本文配套源碼