在研究ImGui的字体渲染方式时顺带研究了关于字体渲染中如何从字体字形的单位转换到渲染后的像素单位。每个字体渲染或排版引擎的实现方式不同,以下介绍是基于ImGui来讲述的,应该是相对正确的。
【资料图】
字体字形的单位度量
上图中,左下角为一个字形(Glyph),字形带有Ascender和Descender属性,是拉丁字母中的升部位置和降部位置,在普通字体中一般代表了的字形可能达到的最高处和最低处,因此升部位置减去降部位置就可以得到字体的最大高度,在一些字体渲染中,以ImGui为例,假设字体大小处在以最大高度为边长的正方向内,因此就以升部位置减去降部位置作为字体大小的度量。此时,字体的度量单位为unit(我认为unit就是用来制作轮廓字体的最小单位),因此这个大小也称为UPM(Units Per eM,欲知em为何物,请看后文)。
unit单位没有实际大小,你不能说100unit等于100英寸,这时需要我们对unit这个单位进行转换,转换为实际的大小。
光栅化后的字体大小度量
右上角部分为光栅化后,也就是渲染为像素后的文字,光栅化后的每个文字都会放入图中正方形框体中,这个框体称为Em Square,长宽定义为1 em。在以往使用金属活字的时候,一块正方形活字称为Em,其长宽就定义为1个em,em是一个相对的单位,需要用例如英寸这样实打实的单位来定义大小,而在金属活字中,一般用“点(Point或简称pt)”来度量Em的大小,例如上图右上角的等式中假设了这一个em大小为252pt。然而一个点的长度又是多少呢?点的长度定义可以说是五花八门的,比较普及的点为“美式点(American point)”,因此在计算机中常采用的,是接近美式点的“DTP 点”,一个DPT点大小为72分之一英寸,上图中的一个em为252个DPT pt,因此真实大小就是252/72英寸。获得了英寸单位的大小后,我们可以通过屏幕的DPI(Dots Per Inch)来计算出像素为单位的大小,正如其名,DPI的含义即为一英寸中的像素点个数,因此直接用DPI乘上英寸为单位的大小,就能得到像素为单位的大小(这里的大小也就是指Em Square的边长),这个大小也称为PPM(Pixels Per Em)。
两者的转换
我们通过字体文件读取到的字体大小都是unit为单位的,而pixel为单位的光栅化后大小我们可以通过自定义或者用户规定的pt值来进行计算,两者之间只差一个系数,这个系数就是
UPM / PPM
这两者的值我们在前文都进行了求取,因此我们现在完成了从字体字形大小到光栅化后大小的转换。
(之前研究的时间有些短,应该有不少舛错,请随意指正)
主要参考:
https://zh.wikipedia.org/wiki/%E9%BB%9E_(%E5%8D%B0%E5%88%B7)
https://help.fontlab.com/fontlab-vi/Font-Sizes-and-the-Coordinate-System/