阅读:1153回复:0
[原创]TrueTypeFont文件中汉字的矢量化与绘制
<P><FONT face=宋体> 在</FONT> C:"WINDOWS"Fonts 文件夹下面有几个矢量字体文件,如SIMFANG.TTF,SIMHEI.TTF,SIMKAI,SIMSUN分别对应着仿宋体,黑体,楷体和宋体。希望首先提取文件当中的存储的汉字位置信息,接着完成矢量化处理后,然后采用DC或OpenGL进行绘制。从表面上看,这个工作也就是想实现Windows API中间的TextOut和wglUseFontOuline等函数所实现的功能。但自己编程实现汉字的矢量化,能在后续工作中获得更多的灵活性,比如将用户输入的汉字换行处理,根据用户的输入对汉字进行任意角度的倾斜,总之,主动性掌握在自己手里。完成矢量化工作后,对这些汉字的处理如同处理普通的矢量图形一样,相当方便,而再不仅仅受制于系统 API所能提供的功能。</P>
<P> 具体的步骤为:</P> <P >1) 根据Unicode编码标准,存储汉字的编码表 。</P> <P align=left>wchar_t Mystring[1001]; //存储准备显示的宽字符的编码</P> <P align=left> count = 0;</P> <P align=left> for (i=0;i<1000;i++)</P> <P align=left> {</P> <P align=left> Mystring[count] = 19968 + i; //十进制的对应着十六进制的e00 </P> <P align=left> count++;</P> <P align=left> }</P> <P> Mystring[1000] = '"0';</P> <P>上面的例子中只准备提取1000个汉字,其实可以让循环从4e00进行到9521(十六进制),代表十进制的19968和38176,分别对应着汉字:一,锠。</P> <P>2)采用FreeType2代码读取*.ttf文件,得到每个汉字的轮廓信息。</P> <P align=left>while( *c) //依次处理字符</P> <P align=left> {</P> <P align=left> fonts[0]->CheckGlyph(*c);</P> <P align=left> ++c;</P> <P align=left>}</P> <P> </P> <P>3)在上叙第2步当中,完成矢量化工作的过程中,可采用De Casteljau算法处理贝塞尔(bezier)曲线。</P> <P>矢量化工作的入口:</P> <P align=left>for( short contourIndex = 0; contourIndex < ftContourCount; ++contourIndex)</P> <P align=left> {</P> <P align=left> FT_Vector* pointList = ;outline.points[startIndex];</P> <P align=left> char* tagList = ;outline.tags[startIndex];</P> <P align=left> </P> <P align=left> endIndex = outline.contours[contourIndex];</P> <P align=left> contourLength = ( endIndex - startIndex) + 1;</P> <P align=left> FTContour* contour = new FTContour( pointList, tagList, contourLength);</P> <P align=left> </P> <P align=left> contourList[contourIndex] = contour;</P> <P align=left> </P> <P align=left> startIndex = endIndex + 1;</P> <P >}</P> <P >4)根据提取的位置信息,采用DC或OpenGL进行绘制。</P> <P >//采用DC绘制</P> <P align=left>for( unsigned int c = 0; c < numContours; ++c)</P> <P align=left> {</P> <P align=left> const FTContour* contour = vectoriser.Contour(c);</P> <P align=left> iPolylineNumbers = iPolylineNumbers + 1;</P> <P align=left> geoAtomLine =(geoatom::CGeoAtomPolyline**)realloc(geoAtomLine,iPolylineNumbers*sizeof(geoatom::CGeoAtomPolyline*));</P> <P align=left> geoAtomLine[iPolylineNumbers-1] = new geoatom::CGeoAtomPolyline(); //原子分配内存,由于数组从开始记数,标记总是比个数少</P> <P align=left> for( unsigned int pointIndex = 0; pointIndex < contour->PointCount(); ++pointIndex)</P> <P align=left> {</P> <P align=left> FTPoint point = contour->Point(pointIndex);</P> <P align=left> geoAtomLine[iPolylineNumbers-1]->GetPtList()->add(fXaddition+iSize*point.X()/64.0f,fYaddition+iSize*point.Y()/64.0f);</P> <P align=left> }</P> <P align=left> geoAtomLine[iPolylineNumbers-1]->SetClosed(true); //将线段形成的区域封闭起来</P> <P align=left> geoSymPoint[iPointSymbolNum-1]->AddAtom(geoAtomLine[iPolylineNumbers-1]); //将线要素添加到这个符号中</P> <P align=left> }</P> <P align=left> </P> <P >}</P> <P >//采用OpenGL进行绘制。</P> <P align=left>for( unsigned int c = 0; c < numContours; ++c)</P> <P align=left> {</P> <P align=left> const FTContour* contour = vectoriser.Contour(c);</P> <P align=left> </P> <P align=left> glBegin( GL_LINE_LOOP); //首尾相连接的多边形</P> <P align=left> for( unsigned int pointIndex = 0; pointIndex < contour->PointCount(); ++pointIndex)</P> <P align=left> {</P> <P align=left> FTPoint point = contour->Point(pointIndex);</P> <P align=left> // glVertex2f( point.X() / 64.0f, point.Y() / 64.0f); //提取顶点信息,绘制的落脚点</P> <P align=left> </P> <P align=left> }</P> <P align=left> // glEnd();</P> <P > }<BR><BR>输出的图形:<BR></P><IMG src="http://www.cnblogs.com/images/cnblogs_com/wuhanhoutao/116501/r_textout.jpg" border=0> |
|