- 2013-04-17 10:47
- 作者:袁永福
- 来源:中国数字医疗网
电子病历文本编辑器是一种非常复杂的图形软件,涉及到的很多开发技巧和软件结构都是传统的数据库程序开发中所从未应用的,因此掌握相关技术的人是非常的少的。在其中文字断行及排版算法是编辑器开发中的核心算法之一。如果没有掌握这个算法,那只能在开源软件的基础上小打小闹了。本文就讨论一下编辑器中文档断行及排版算法。
文字排版大致分为以下几个步骤:
1.测量各个字符的宽度和高度。
2.计算文档容器的客户区宽度。比如设置的纸张宽度减去左页边距和右页边距的宽度。这里的文档容器不仅仅指大的正文区域,还包括单元格、文本框之类的文档结构。
3.断行,也就是将各个字符从左到右,从上到下的依次放置在文档容器中。产生一行行文本,实现一种流式排版。
4.行内排版,也就是在文档行中进行字符排版,特别是为了完成文档内容两边对齐功能。
5.分页。
测量字符大小
排版的第一步就是计算文档中各个字符的宽度和高度。笔者是使用C#开发的,因此可以调用System.Drawing.Graphics.MeasureString方法来测量字符的宽度和高度。由于文档中字符个数很多,比如几万个,则一个个测量是非常消耗时间的,为此需要采用很多优化手段来加速测量。
说到测量字符,就涉及到等宽字体和比例字体的概念了。等宽字体就是使用该字体绘制字符,字符的宽度是一样的,比如“宋体”,它就是等宽字体,用它来测量和绘制字母“W”和“i”,其宽度是一样的。比例字体就是使用该字体测量和绘制字符,其宽度是不一样的,比如“Times new roman”,用它来测量字母“W”和“i”,其宽度是不一样的。
对于等宽字体,可以事先测量一个字符的宽度,比如“W”,则以后遇到其他字符就使用这个已经测量好的宽度;而对于比例字体,则需要进行实时的测量。
不过一般来说,对于等宽字体和比例字体,中文符号的宽度还是一致的。因此可以实现测量一个中文字符的宽度,以后遇到中文字符就采用这个事先测好的宽度。
这里带来一个问题,如何判断一个字符是否为中文字符,那就需要参照GB3212,GBK等计算机字符集的标准来判断了。一般来说Unicode编码范围从19968至40869的字符为中文字符,当然为了进一步的优化,可以知道一些全角符号,它们的宽度也等于中文字符。
不过仅仅依照UNICODE编码来判断是否是中文字符是不可靠的。因为不同的UNICODE字符在不同的字体中其意义可能是不一样的。
比如对于字体“Wingdings”,所有的字符在这个字体中完全变味了,就表示一个个特定的符号,判断是否是正文就毫无意义了;另外对于条码字体也有这种情况。
最为保险的做法就是直接解析字体二进制文件(扩展名为ttf或ttc),获得其中的字体轮廓信息,然后根据字符的UNICODE编码值来计算出字符的宽度,这样做是最为准确可靠的。笔者猜测Graphics.MeasureString方法内部也可能采用这种方法。不过编辑器自己解析字体二进制文件进行字符测量,绕过底层诸多的调用层次,其速度可以非常的快,可以在几十毫秒内完成几万个字符的测量。
不过解析字体二进制文件信息还是要花掉不少时间的,比如对于宋体,其字体文件名simsun.ttc,文件大小15MB,含28762个字符轮廓信息。但分析所得的结果信息量很小,只有1424 字节,为此需要将分析结果保存在一个临时文件中,下次就无需分析这个字体二进制文件了。
共6页: 1 [2][3][4][5][6]下一页 [查看全文] |