1. 字体分类
字体根据数据存储的格式一般把字体分为两类,一类是点阵字体,一类是矢量字体。
点阵字体:
也叫位图字体,格式一般是 .fon 简单来说就是把文字保存为一张图片。一般早期的电脑使用这种方式显示文字。优点是显示速度相当快,比如使用cpu渲染的时候,只需要一次memcopy 就可以把字体显示出来。缺点也很明显,只能清晰的显示在对应的字号下,放大了就会变得失真。
矢量字体:
矢量字体一般格式为.ttf,保存文字的矢量信息,比如一个笔划的起始、终止坐标,半径、弧度等等。在显示、打印这一类字库时,要经过一系列的数学运算才能输出结果,但是这一类字库保存的汉字理论上可以被无限地放大,笔划轮廓仍然能保持圆滑,打印时使用的字库均为此类字库。
2. 矢量字体分类
目前主流的 矢量字体格式有3种:Type1, TrueType和 OpenType,这三种格式都是与平台无关的。
Type1
全称PostScript Type1,是1985年由Adobe公司提出的一套矢量字体标准,由于这个标准是基于PostScript Description Language(PDL),而PDL又是 高端打印机首选的打印描述语言,所以Type1迅速流行起来。但是Type1是非开放字体,Adobe对使用Type1的公司征收高额的使用费。
TrueType
是1991年由Apple公司与 Microsoft公司联合提出另一套矢量字标准。Type1使用三次 贝塞尔曲线来描述字形, TrueType则使用二次贝塞尔曲线来描述字形。所以Type1的字体比 TrueType字体更加精确美观。一个误解是,Type1字体比TrueType字体占用空间多。这是因为同样描述一个圆形,二次贝塞尔曲线只需要8个关键点和7段 二次曲线;而三次贝塞尔曲线则需要12个关键点和11段三次曲线。然而实际情况是一般来说 Type1比TrueType要小10%左右。这是因为对于稍微复杂的字形,为了保持平滑,TrueType必须使用更多的关键点。由于现代大部分打印机都是使用PDL作为打印描述语言,所以Type1字体打印的时候不会产生形变,速度快;而 TrueType则需要翻译成PDL,由于曲线方程的变化,还会产生一定的形变,不如Type1美观。
OpenType
则是Type1与 TrueType之争的最终产物。1995年,Adobe公司和 Microsoft公司开始联手开发一种兼容Type1和TrueType,并且真正支持 Unicode的字体,后来在发布的时候,正式命名为OpenType。OpenType可以嵌入Type1和TrueType,这样就兼有了二者的特点,无论是在屏幕上察看还是打印,质量都非常优秀。可以说 OpenType是一个三赢的结局,无论是Adobe、Microsoft还是最终用户,都从OpenType中得到了好处。Windows家族从Windows 2000开始,正式支持OpenType。
对比
这么说来,Type1应该比 TrueType更具有优势,为什么如今的计算机上TrueType反而比Type1使用更广泛呢?
这是因为第一:Type1由于字体方程的复杂,所以在屏幕上渲染的时候,花费的时间多,解决方案是大部分Type1字体嵌入了 点阵字体,这样渲染快,但是边缘不光滑,比较难看。很多ps文档和ps转换的pdf文档都是这样,在计算机上浏览的时候字体很难看,但是打印出来很美观。TrueType则渲染比较快,可以平滑的显示在屏幕上,看上去很美观。
第二个原因是Type1的高额使用费,使得Type1没有被所有的操作系统所支持。Windows家族只有OS/2和windows 2000及之后的版本从操作系统级别开始支持Type1。由于这个问题,Adobe只好在其所有的产品中嵌入Adobe Type Manager(ATM)作为渲染引擎。
在UOS 上字体基本都是 TrueType,打开字体管理器,右键点击字体查看信息,UOS字体类型基本都是TrueType类型。
3. Qt 中字体绘制原理。
Qt采用第三方开源库 freeType 实现字体渲染。freeType 提供提供字体的轮廓、轮廓关键点解析、上层图形API 通过这些接口进行图形绘制。上层利用freeType 不仅可以使用CPU 绘制,同时也可以使用opengl 进行绘制。FT库使用C语言编写,采用了面向对象的思想,将对应类型封装为结构体或者结构体指针类型。
字体渲染在 Qt中非常复杂,这里做简单的介绍,有兴趣可以深入研究TrueType 库字体渲染,该库在很多图形界面绘制中都会用到。下面通过代码对整个字体绘制大致流程说明。
1. 传入一个字体后,首先初始化 FT_New_Face,使用一个FT_New_Face 打开一个字体文件
2. 设置一些绘制的参数,比如字体大小什么的。
3. 遍历需要绘制文字,通过文字的unicode获取文字所在的index,并保存到glyph中。在绘制的时候通过这个glyph获取字体的轮廓字槽信息。
4. 在绘制的时候,通过glyph获取轮廓字槽。FT_Load_Glyph 把字体信息加载到face的glyph 中。
5. 至此、字的轮廓信息完全存储在outline中,下面的代码就是拿来解析,并渲染轮廓的。
在Qt 中,字体渲染分为了两种,当渲染的字体大于 64 号的时候,Qt会强制不加载字体的点阵图,采用讲字体轮廓转化成点的方式,然后通过我们平时drawpath的方式进行渲染,保证了大字体的情况下不会失真。
然后通过 addGlyphsToPath 将 outline 中的轮廓添加到 path 中,然后中fill的方式将文字渲染出来。这种方式同样使用于opengl 渲染。网上有很多这样的例子。
另一种方式当字体大小小于 64 的时候,是通过 freeType 获取字体对应的位图来渲染。在showDrawCacheGlyphs 函数中会对字体的大小进行判断,小于64的时候会通过drawCacheGlyphs 通过位图渲染
同样的从slot 中获取位图数据,通过memcpy 拷贝到 glyph_buffer 中,最后Qt中绘制图像的函数绘制到界面上。文章来源:https://www.toymoban.com/news/detail-671266.html
Qt 中字体的绘制流程大致到这里,字体绘制比较复杂,有兴趣可以研究 trueTypel库,很多图形项目都会用到它。文章来源地址https://www.toymoban.com/news/detail-671266.html
到了这里,关于Qt 字体绘制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!