一張圖理解字體渲染中的大小及其轉(zhuǎn)換


在研究ImGui的字體渲染方式時順帶研究了關(guān)于字體渲染中如何從字體字形的單位轉(zhuǎn)換到渲染后的像素單位。每個字體渲染或排版引擎的實現(xiàn)方式不同,以下介紹是基于ImGui來講述的,應(yīng)該是相對正確的。

字體字形的單位度量
上圖中,左下角為一個字形(Glyph),字形帶有Ascender和Descender屬性,是拉丁字母中的升部位置和降部位置,在普通字體中一般代表了的字形可能達(dá)到的最高處和最低處,因此升部位置減去降部位置就可以得到字體的最大高度,在一些字體渲染中,以ImGui為例,假設(shè)字體大小處在以最大高度為邊長的正方向內(nèi),因此就以升部位置減去降部位置作為字體大小的度量。此時,字體的度量單位為unit(我認(rèn)為unit就是用來制作輪廓字體的最小單位),因此這個大小也稱為UPM(Units Per eM,欲知em為何物,請看后文)。
unit單位沒有實際大小,你不能說100unit等于100英寸,這時需要我們對unit這個單位進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換為實際的大小。
光柵化后的字體大小度量
右上角部分為光柵化后,也就是渲染為像素后的文字,光柵化后的每個文字都會放入圖中正方形框體中,這個框體稱為Em Square,長寬定義為1 em。在以往使用金屬活字的時候,一塊正方形活字稱為Em,其長寬就定義為1個em,em是一個相對的單位,需要用例如英寸這樣實打?qū)嵉膯挝粊矶x大小,而在金屬活字中,一般用“點(Point或簡稱pt)”來度量Em的大小,例如上圖右上角的等式中假設(shè)了這一個em大小為252pt。然而一個點的長度又是多少呢?點的長度定義可以說是五花八門的,比較普及的點為“美式點(American point)”,因此在計算機(jī)中常采用的,是接近美式點的“DTP 點”,一個DPT點大小為72分之一英寸,上圖中的一個em為252個DPT pt,因此真實大小就是252/72英寸。獲得了英寸單位的大小后,我們可以通過屏幕的DPI(Dots Per Inch)來計算出像素為單位的大小,正如其名,DPI的含義即為一英寸中的像素點個數(shù),因此直接用DPI乘上英寸為單位的大小,就能得到像素為單位的大小(這里的大小也就是指Em Square的邊長),這個大小也稱為PPM(Pixels Per Em)。
兩者的轉(zhuǎn)換
我們通過字體文件讀取到的字體大小都是unit為單位的,而pixel為單位的光柵化后大小我們可以通過自定義或者用戶規(guī)定的pt值來進(jìn)行計算,兩者之間只差一個系數(shù),這個系數(shù)就是
UPM / PPM
這兩者的值我們在前文都進(jìn)行了求取,因此我們現(xiàn)在完成了從字體字形大小到光柵化后大小的轉(zhuǎn)換。

(之前研究的時間有些短,應(yīng)該有不少舛錯,請隨意指正)
主要參考:
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/