文字显示4——创建并使用字体

这个系列前三文章:

文字显示1——字符与编码

文字显示2——C++字符串与字符编码

文字显示3——字体

 

创建并使用字体

创建字体

通过High-Logic FontCreator软件可以很容易的创建我们自己的字体。

字体绘制区域

如上图所示我们在设计字体时只能在一定区域内设计字符,如果超出范围字符显示时会与其他文字重叠。绘制范围如上图所示,上下不能超过WinAscent/WinDescent,左右不能超过标尺的白色区域,也就是上图中的0-1500左右的范围。

字体所有字符上下范围都是一致的,左右范围时可以不同的,因为字体可以是变宽字体。左右宽度可以在Transform窗口的Beraings中设置,一般Left side需要设置为0,Right side可以更改,如下图:

 

High-Logic FontCreator默认会帮我们创建一些字符,包括未定义字符。以下是一个我创建了只有8个字符的字体,

 

High-Logic FontCreator允许从一个字体中复制一个字符然后粘体到新创建的字体中,这个功能可以让我们把一个字体中用到的字符全部提取到一个新的字体中,从而减小字体的大小,这在一些程序中非常有用。

 

使用字体

在windows中我们直接安装我们创建的字体到系统中,让后通过系统函数调用就行了。在win32程序中可以通过函数CreateFont来使用字体。在win32中还提供了一个函数GetTextExtentPoint32来获取字符串的宽度,因为在变宽字体中每个字符的宽度都可以不同,所以无法通过字符个数来计算字符串宽度,需要用函数GetTextExtentPoint32获取字符串宽度。

 

直接使用字体文件

有时候我们并不能确定系统中是否安装了字体,所以不能直接用系统的函数去绘制文字。为了解决这个问题,我们可以自己解析字体文件,从字体文件中取出图形符号,然后显示。

 

解析字体文件需要用到一个开源库FreeType,通过这个库可以很容易的从字体文件中获取到字符的位图。FreeType是一个C语言的库,支持各个平台,其提供了CMake编译,可以通过CMake软件转换成VS的工程,这里我已经编译好了VS2017中FreeType静态库的DebugRelease版本。

 

FreeType使用也比较简单,这里给一个大致的步骤,详细的可以参考官方文档。

  1. 调用FT_Init_FreeType初始化FreeType库
  2. 调用FT_New_Face使用字体文件创建字体
  3. 调用FT_Select_Charmap设置映射字符编码,默认字符编码是Unicode,通常不用设置,因为大部分字体只支持Unicode和一种Apple平台的老编码。
  4. 调用FT_Set_Char_Size设置字符大小,设置字体大小时要设置字号和DPI,字号和平时用Word中字号类似,DPI是指显示设备像素密度,一般电脑显示器DPI在100左右,而手机在300左右,两者共同决定导出位图的大小。
  5. 调用FT_Set_Transform设置字体的缩放旋转和排版位置。如果想自己控制排版位置,一般可以省略这个步骤。
  6. 调用FT_Load_Char获取文字的位图信息,默认获取的是8位色深的位图,即每个字节代表一个像素。
  7. 绘制位图就可以显示文字了。

 

以下是用FreeType在控制台里面上一节我创建的字体。

程序是在VS2017下编译的,完整代码地址

字体中有8个字符,分别是“ABCabc中文”,程序使用这个字体显示“Ba中测”4个字符,因为‘测’字字体中没有,所以显示的是未定义字符。

 

以下是FreeType用宋体字体显示的例子,代码下载地址

 

文字边框

FreeType获取的位图是一张刚好包含文字的位图,不包含左右上下的空白信息。如果绘制文字时直接把每一张位图连接在一起,文字则会一个粘一个,不利于阅读,正常显示的文字上下左右都会有一定的间距。

如上图外面的大矩形框是显示中字时需要的位置,内部红色框是FreeType获取的位图。为了正确显示文字,需要六个位置信息,图中的Height、Width、OffsetX、OffsetY已经位图的长宽。

这六个信息可以通过以下方式获得:

  1. Height,当调用完FT_Set_Char_Size后,所有字符的高度都是一样的,在FT_Set_Char_Size设置文字大小后,可以通过fontFace->size->metrics.height/64获得,除以64说因为FreeType获取的字体高度单位的原因。
  2. Width,当调用完FT_Load_Char后,可以通过fontFace->glyph->advance.x/64,也需要除以64。
  3. OffsetX,当调用完FT_Load_Char后,为fontFace->glyph->metrics.horiBearingX/64。
  4. OffsetY,当调用完FT_Load_Char后,为(fontFace->size->metrics.height + fontFace->size->metrics.descender - fontFace->glyph->metrics.horiBearingY)64。
  5. Bitmap宽,当调用完FT_Load_Char后,为fontFace->glyph->bitmap.width。
  6. Bitmap高,当调用完FT_Load_Char后,为fontFace->glyph->bitmap.rows。

 

字体平滑

在Windows系统,此电脑->属性->高级设置,性能的设置里面有一个“平滑字体边缘”,如下图:

当选择选择和不选择“平滑字体边缘”时,会对系统文字显示效果有很大影响,如下图:

当未开启字体平滑时字体,文字显示如同点阵字体,显示粗糙不清晰,开启后字体饱满清晰,这个问题在低分辨率(PPI低)的屏幕下更加明显。

 

目前来说字体平滑有两个技术一个是灰度渲染,另一个是次像素渲染,灰度渲染平滑字体大部分手机操作系统中会使用,而次像素渲染一般用在PC电脑上。

 

灰度渲染

前面我们说过点阵字体,通过一个个在矩阵中的点来描绘一个字体。实际上显示器也相当于一个点阵,所有像素和矩阵一样排列好。对于这样的矩阵像素当显示平行或者垂直的直线是,线段可以很直,但是显示斜线时就会出现锯齿,斜线看上去不直,如下图:

灰度渲染技术可以让我们把倾斜的直线渲染得看上去很平滑,如下图:

同样是倾斜得直线,右边得直线看上去很直。通过右边的放大图片可以看出左边的直线要么全黑要么全白,右边的倾斜的直线有些像素是灰色的,这个灰色的比例事件上是按照直线划过像素面积计算的,这也就是灰度渲染的原理。显示文字时有大量曲线,通过灰度渲染会让字体看上去很平滑。

对于FreeType来说使用灰度平滑非常简单,因为像素可以通过RGBA表示,其中RGB为颜色,A为透明度,可以把RGB作为文字的颜色,而把FreeType获得的位图作为透明度A值,就可以实现灰度渲染平滑字体。

 

次像素渲染

下图是win10上记事本显示文字的截图,右边是文字放大的图片:

从图片中可以看到,文字放大以后边缘会出现彩色,实际上文字是黑色的,这是因为为了使得曲线更加平滑,系统会将曲线旁边的像素(次像素)设置成一个渐变色。

 

灰度渲染VS次像素渲染

以下图片是‘e’字符未开启平滑,灰度渲染,次像素渲染。

 

注意观察缩小的图片,如果你分辨率(PPI,像素密度)不高,可以看到灰度渲染的字体有些发虚,而次像素渲染字体更加饱满一些。次像素渲染主要是为PPI低的屏幕设计的,在这种屏幕上次像素显示的文字会更加饱满清晰。一般电脑显示器的屏幕像素密度PPI在100左右。对现在的智能手机来说,PPI一般都在三四百以上,一般都用不到次像素渲染,因为次像素在这种屏幕上显示的效果和灰度渲染差不多,而且次像素渲染会加重手机负担增加耗电。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值