阅读:1434回复:0
[原创]TrueTypeFont文件中符号数据导出与绘制
TrueTypeFont文件作为流行的矢量形式字体文件,其中存储着大量的符号资源。为充分利用资源与达到数据共享目标,现以freetype2源代码为文件读取功能的支撑,导出TrueTypeFont文件中存储的符号并实现绘制。要注意的问题:
<P >1) 英文与汉字映射关系以Unicode编码为准。汉字为双字节,即宽字符。而符号以数字为索引依次读出。</P> <P >2) 为避免重复和加速,可预先做链表,将新创建的符号填入,以方便再次查询时直接读出。</P> <P >3) 使用De Casteljau 算法处理贝塞尔(Bezier)曲线。</P> <P><P> </P>附参考代码:</P> <P><P> </P>程序入口:</P> <P> Process()</P> <P> { const char* font_filename = "C:\\Windows\\Fonts\\WINGDNG3.TTF";<P></P></P> <P> fonts[0] = new FTGLOutlineFont( font_filename ); //矢量轮廓,以文件名称为参数<BR> const unsigned char* c = (unsigned char*)string[j];<BR> while( *c) //依次处理字符<P></P></P> <P align=left> {<BR> fonts[0]->CheckGlyph(*c);<BR> ++c;<BR> }<BR>}<BR>调用的函数:</P> <P align=left>bool FTFont::CheckGlyph(const unsigned int characterCode)<P></P></P> <P align=left>{<BR> if( NULL == glyphList->Glyph( characterCode)) //如果还没有添加进列表<P></P></P> <P align=left> {<P></P></P> <P align=left> unsigned int glyphIndex = glyphList->FontIndex( characterCode); //取得索引<P></P></P> <P align=left> FTGlyph* tempGlyph = MakeGlyph(glyphIndex); //调用子类中的这个函数,制作Glyph<P></P></P> <P align=left> if( NULL == tempGlyph) //返回值为空的话<BR> {<BR> if( 0 == err)<BR> {<BR> err = 0x13;<BR> }<BR> return false;<BR> }<BR> glyphList->Add( tempGlyph, characterCode); //添加到容器中<BR> }<BR> return true; //若已存在容器中直接返回true<P></P></P> <P>}<P></P></P> <P><P> </P></P> <P>//构建Glyph<P></P></P> <P align=left>FTGlyph* FTGLOutlineFont::MakeGlyph( unsigned int g)<P></P></P> <P align=left>{<P></P></P> <P align=left> FT_GlyphSlot ftGlyph = face.Glyph( g, FT_LOAD_NO_HINTING); //调用freetype函数 <BR> if( ftGlyph)<BR> {<P></P></P> <P align=left> FTOutlineGlyph* tempGlyph = new FTOutlineGlyph( ftGlyph, useDisplayLists); //以刚得到的ftGlyph为参数,新建FTOutlineGlyph,也为渲染函数建立需要的现实列表<P></P></P> <P align=left> return tempGlyph;<P></P></P> <P align=left> }<BR> err = face.Error();<BR> return NULL;<P></P></P> <P>}<P></P></P> <P><P> </P></P> <P>//读取顶点信息<P></P></P> <P align=left>FTOutlineGlyph::FTOutlineGlyph( FT_GlyphSlot glyp)<P></P></P> <P align=left>: FTGlyph( glyph)<P></P></P> <P align=left>{<BR> if( ft_glyph_format_outline != glyph->format)<BR> {<BR> err = 0x14; // Invalid_Outline<BR> return;<BR> }<BR> FTVectoriser vectoriser( glyph); //矢量化<BR> size_t numContours = vectoriser.ContourCount();<BR> if ( ( numContours < 1) || ( vectoriser.PointCount() < 3))<BR> {<BR> return;<BR> }<BR> for( unsigned int c = 0; c < numContours; ++c)<BR> {<BR> const FTContour* contour = vectoriser.Contour(c);<BR> iPolylineNumbers = iPolylineNumbers + 1;<P></P></P> <P align=left> geoAtomLine =(geoatom::CGeoAtomPolyline**)realloc(geoAtomLine,iPolylineNumbers*sizeof(geoatom::CGeoAtomPolyline*));<P></P></P> <P align=left> geoAtomLine[iPolylineNumbers-1] = new geoatom::CGeoAtomPolyline();//原子分配内存,由于数组从开始记数,标记总是比个数少<P></P></P> <P align=left><P> </P> for( unsigned int pointIndex = 0; pointIndex < contour->PointCount(); ++pointIndex)<P></P></P> <P align=left> {<BR> FTPoint point = contour->Point(pointIndex);<BR> geoAtomLine[iPolylineNumbers-1]->GetPtList()->add(fXaddition+iSize*point.X()/<ST1:CHMETCNV tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="64" unitname="F" w:st="on">64.0f</ST1:CHMETCNV>,fYaddition+iSize*point.Y()/<ST1:CHMETCNV tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="64" unitname="F" w:st="on">64.0f</ST1:CHMETCNV>);<P></P></P> <P align=left> }<BR> geoAtomLine[iPolylineNumbers-1]->SetClosed(true); //将线段形成的区域封闭起来<BR> geoSymPoint[iPointSymbolNum-1]->AddAtom(geoAtomLine[iPolylineNumbers-1]); //将各条线要素添加到这个符号中,一个点符号中可能有多条线<BR>}<BR>}<BR>原始字体文件中符号;<BR></P> <P><IMG src="http://www.cnblogs.com/images/cnblogs_com/wuhanhoutao/116501/r_original.JPG" border=0></P> <P><FONT face=新宋体>导出TrueTypeFont文件中符号数据与绘制:</FONT></P> <P><BR> </P><IMG src="http://www.cnblogs.com/images/cnblogs_com/wuhanhoutao/116501/r_symbolPlant.JPG" border=0> |
|