有大量(几百字到几百万字之间)文本需要快速排版,其中绝大部分为中文,这些文本上有多种字体。要正确的进行排版,偶必须知道文本中每个字符的高宽。偶知道使用DrawText/DT_CALCRECT可以获得字符在特定字体下的高宽,不过可能出现的数百万次的系统调用显然无法满足快速排版的需求,而且获得字符高宽之后缓存它们(因为窗口resize的时候重排还需要这些数据)也是很大的内存消耗。为了解决以上问题,偶做了一个假定,偶假定在相同的字体/字号下,所有的汉字字符都是等宽等高的,比如在宋体五号下“一、二、三...”等字符全部都是相同高宽。这样,针对每种字体/字号,我只需要一次系统调用,以后遇到相同字体/字号的任何汉字的时候通通以第一次调用获得的高宽为准。如此一来,所需的系统调用次数以及数据缓存空间仅仅和字体/字号组合数有关,而一般情况下,一篇文档所应用的字体/字号组合局限在几种到几十种之间,很少会突破百种。系统调用和存储空间都得到了极大的节省(呵呵,成千上万倍啊)。并且由于缓存数据极少,两层一般不超过10的map,获取指定字体指定字符的高宽也极其迅速。看上去很完美。不过,现实是残酷的。虽然偶所做的假定在绝大多数情况下是正确的,但是也有极少数情况下不正确,比如编码为“A1A1”的字符使用int _ismbblead( unsigned int c )判断会返回它是一个多字节字符,也就是说它是个汉字(或者日文/韩文),但是它在“幼圆”字体下的宽度和一般字符不同,在宋体下好像还是相同的。偶的假定失效。这个字符偶现在也不知道是个什么东东,它在win2k和winxp下用DrawText显示出来效果还不同,汗。错误的假定导致了一个排版错误,现在仿佛有一堆候选解决方案,比如禁止这个字符,比如特殊处理这个字符,比如不再使用原来的假定。不过都有问题,前面两个方案是基于经验的,但是偶不知道这类字符有多少,只能碰见一个抓一个。采用最后一个方案的话,偶必须要获得另外一个高效且无错误的获取字符高宽的方法,偶不知道有什么方法可以做到这一点。各位大虾看看有没有什么解决方案,share一个给我。不胜感激。
解决方案 »
- 0分贴,大家愿意回复吗
- 有没有好用又方便的开源的对zip格式的解压缩软件啊??(需要有源码才可以的)
- 怎样实现这种时间edit
- ATL是专门用来做com的吗?
- 键盘模拟输入
- 将AVI文件的音频解码转换成mp3格式,它的文件头会不会变化?
- 难:如何在垂直滚动时,让CScrollView的部分区域参加滚动,而其他区域不参加滚动?
- MajorVon()进来接分
- 请求各位了:帮我想想办法?很急,N急---》关于VC下控制台下书写程序的问题?
- 这个类的构造函数我不明白,谁能帮我解释一下:
- 怎样处理DLL中的资源和工程中的资源问题?
- 一个 CListCtrl 的既显示文本又显示图标的列,我可以在运行的时候让它只显示文本吗?
但记得有好的方法了告诉大家一声哦.....http://www.fengyuan.com/
呵呵,就是他,楼上各位应该都认识。
int FAR PASCAL _export GetStringWidth(LPSTR FontName,int FontSize,int Weight,LPSTR String)
{
HDC hDC;
HFONT hFont,hOldFont;
LOGFONT LogFont;
int StringLength; hDC=GetDC(NULL); LogFont.lfHeight=-MulDiv(FontSize,GetDeviceCaps(hDC,LOGPIXELSX),72);
LogFont.lfWidth =0;
LogFont.lfEscapement=0;
LogFont.lfOrientation=0;
LogFont.lfWeight=(Weight)?FW_BOLD:FW_NORMAL;
LogFont.lfItalic=0;
LogFont.lfUnderline=0;
LogFont.lfStrikeOut=0;
LogFont.lfCharSet=DEFAULT_CHARSET;
LogFont.lfOutPrecision=OUT_DEFAULT_PRECIS;
LogFont.lfClipPrecision=CLIP_DEFAULT_PRECIS;
LogFont.lfQuality=DEFAULT_QUALITY;
LogFont.lfPitchAndFamily=FF_DONTCARE|VARIABLE_PITCH;
lstrcpy(LogFont.lfFaceName,FontName); hFont=CreateFontIndirect(&LogFont);
hOldFont=SelectObject(hDC,hFont);
StringLength=LOWORD(GetTextExtent(hDC,String,lstrlen(String)));
hFont=SelectObject(hDC,hOldFont);
DeleteObject(hFont); ReleaseDC(NULL,hDC); return StringLength;
}