在數(shù)字化的計算機(jī)系統(tǒng)中呐馆,文字一般被拆分為兩個部分進(jìn)行處理狞尔。其一是文字彼此區(qū)分的能力丛版,其二則是文字的具體寫法和樣式。第一個部分偏序,通過數(shù)字編碼處理页畦,讓不同的字符與不同的數(shù)字一一對應(yīng),這樣人眼中的不同字符在計算機(jī)中被映射為不同的數(shù)字進(jìn)行處理(ASCII研儒, Unicode 等就是這樣的映射方案)豫缨,文本的數(shù)字化也就成了可能。但問題在于端朵,經(jīng)過這樣的數(shù)字化之后好芭,文字的圖形屬性完全丟失了,變成了純粹抽象的東西冲呢。如果想把編碼成數(shù)字的文本還原為文字圖形舍败,就需要額外的信息——也就是說要告訴計算機(jī)和顯示設(shè)備(或者打印設(shè)備)每個字怎么寫。包含這些額外信息的文件就是所謂的“字體文件”敬拓。
字體文件本質(zhì)上就是一個圖集邻薯,圖集中的每張圖都附帶一些說明來指定它和哪個字符(或者說字符的編號)對應(yīng)。當(dāng)一段數(shù)字化的文本要顯示或者打印時乘凸,計算機(jī)就根據(jù)文本中的字符編號去字體文件中尋找對應(yīng)的圖厕诡,然后依照圖顯示或者打印。
字體文件格式
對于日常能接觸到的絕大多數(shù)計算機(jī)設(shè)備翰意,對字體文件的使用和管理是其操作系統(tǒng)(或者說“圖形化操作系統(tǒng)”)的基本功能木人。由于不同系統(tǒng)的具體實現(xiàn)和操作千差萬別信柿,這里無法一一介紹到冀偶。但是,一些系統(tǒng)為了開發(fā)和使用的穩(wěn)定渔嚷,以及在一定的范圍內(nèi)讓字體文件具有可以移植性进鸠,規(guī)定了一些字體文件格式標(biāo)準(zhǔn)。這里簡單介紹幾種常見的字體文件格式形病。
OpenType
早期的字體格式是相對來說比較雜的客年,目前來說霞幅, OpenType 在一定程度上把雜亂的字體格式做了一層封裝打包(盡管并不太成功)。在 OpenType 之前量瓜,主要有 Adobe 開發(fā)的 PostScript Type 1 和 Apple 與 Microsoft 開發(fā)的 TrueType 兩種字體文件格式司恳。后來 Microsoft 和 Adobe 又聯(lián)合開發(fā)了 OpenType。
OpenType 雖然是一個標(biāo)準(zhǔn)但是包含兩種格式風(fēng)格绍傲,即 TrueType 風(fēng)格的和 PostScript Type 1 風(fēng)格的扔傅。雖然 OpenType 的這兩種風(fēng)格現(xiàn)在大體上能替代各自對應(yīng)的老字體格式,但是兩種風(fēng)格本身并不能彼此并不具有互換性烫饼。也就是說 TrueType-flavored OpenType (一般和 TrueType 一樣以 .ttf
為后綴猎塞,簡稱“TTF”)可以看作 TrueType 的升級, PostScript-flavored OpenType (一般用 .otf
為后綴杠纵,簡稱“OTF”)可以看作 PostScript Type 1 的升級荠耽,但是這同一框架下的兩種風(fēng)格格式卻不能彼此替換。有的程序?qū)?OTF 支持更好比藻,有的則僅僅支持 TTF铝量。關(guān)于這幾種字體格式之間的關(guān)系,可以參考以下資料:
- https://zhuanlan.zhihu.com/p/386035885
- https://www.reddit.com/r/typography/comments/ci4nwk/comment/ev1jy42/
- https://learn.microsoft.com/en-us/typography/opentype/
不過對于一般用戶來說银亲,直接選 TTF 字體是最保險的選擇款违,因為其支持比較全面。只是一些需要用到 Adobe 創(chuàng)意套件的用戶可能需要注意 OTF 的問題群凶。
另外插爹,TTF 有合集形式的文件格式,后綴為
.ttc
请梢, OTF 也對應(yīng)有合集赠尾,后綴為.otc
。所謂合集其實就是多個字體文件打包成了一個字體文件毅弧。
OpenType 中的 TTF 和早期的 TrueType 縮寫一樣气嫁,都是“TTF”,而且文件后綴名也一樣都是
.ttf
够坐。但在實際使用中寸宵,很少需要區(qū)分兩者≡可以簡單把 OpenType 中的 TTF 當(dāng)作是一個高版本的加了更多功能的 TrueType梯影。
Web Open Font Format
簡稱“WOFF”,目前有兩個版本—— WOFF 1.0 (有時候直接叫“WOFF”)和 WOFF 2.0庶香。 WOFF 2.0 是 WOFF 1.0 的升級甲棍,所以沒有特殊理由一般選最新的 WOFF 2.0 就行。需要注意的是,這個文件格式兩個版本的后綴不同该肴, WOFF 1.0 的后綴是 .woff
废酷, WOFF 2.0 的后綴是 .woff2
眯牧。
相比 OpenType 和更老的字體格式來說富岳, WOFF 主要增加了壓縮功能进副,使得字體文件可以更小民轴,因而在網(wǎng)頁和瀏覽器領(lǐng)域應(yīng)用廣泛解滓。但是目前來說咱士,一些其他程序和比較舊的瀏覽器可能不支持疫鹊。
字體風(fēng)格
所謂“字體風(fēng)格”是一個很模糊的說法,因為字體的特征可以分很多個維度討論司致。由于本文僅僅是一個關(guān)于字體知識的簡單介紹拆吆,所以在這個模糊的標(biāo)題之下籠統(tǒng)做一點(diǎn)簡單的介紹。
襯線和無襯線
一般來說脂矫,常見的印刷體(或者屏幕顯示字體)根據(jù)是否加入裝飾襯線分為襯線體(serif)和無襯線體(sans-serif枣耀,簡稱“sans”)。襯線字體一般在筆畫起止處有裝飾線庭再,且筆畫粗細(xì)變化較多捞奕;無襯線體則一般沒有裝飾線,線條簡單拄轻,粗細(xì)均勻颅围。在平面設(shè)計上對兩者的使用有很多研究和講究,這里就不具體展開了恨搓。對應(yīng)到常見的漢字字體來說院促,明宋體(就是一般說的“宋體”)屬于襯線字體,而黑體則是無襯線字體斧抱。
這種分類不是簡單二分的常拓,在這兩種之外還有更像手寫體的 script font 和其他各種奇奇怪怪的藝術(shù)字。襯線和無襯線之間也不是非此即彼的辉浦,有一些字體的設(shè)計介于兩者之間弄抬,所以也不好直接歸為哪一類。例如在代碼顯示之類的場景中宪郊,為了增加 “0Oo” 或者 “1lI” 之類易混淆字符的辨識度掂恕,即便是無襯線字體也會加一些襯線字體的設(shè)計以方便字符區(qū)分。
顯示代碼用的字體一般還有一個特殊要求弛槐,就是不同字符寬度要統(tǒng)一(滿足這類要求的字體也叫等寬字體懊亡, monospaced font)。這對漢字來說很自然丐黄,但是對于拉丁字母來說并不自然斋配。例如“i”的寬度就是要比“m”小很多孔飒。程序員要求代碼中不同字母寬度一樣一方面是早期終端機(jī)習(xí)慣的遺留灌闺,另一方面也出于實用考慮:一者艰争,不同的 ASCII 字符,不論怎么寫桂对,其所占用的存儲空間是一樣的甩卓,因此完全相同的寬度有助于直觀估計字符串或者文本的存儲空間;二者蕉斜,嚴(yán)格對齊的行列有助于矩陣框選等比較復(fù)雜的文本操作逾柿。
當(dāng)代碼中混有多種語言的字符時,強(qiáng)行把拉丁字符拉到和漢字一樣寬不好看宅此,所以此時又會把字符分為全角和半角兩類(還有零寬度字符机错,但是不常見)。拉丁字符是半角字符父腕,漢字是全角字符弱匪,兩種字符各自等寬,全角寬度和半角寬度之間則維持一個固定的比例(一般是 2:1)璧亮。
粗體萧诫、斜體、粗斜體和可變字體
在襯線和無襯線這樣的大分類下枝嘶,就是一款款具體的字體帘饶。由于文字在經(jīng)過數(shù)字化編碼的時候并不保留寫法或圖像信息,所以對計算機(jī)來說群扶,字體做成什么樣都是可以的及刻。但對于人來說,字體還是得符合一定的規(guī)范竞阐,看起來才舒心提茁。例如說,通常的正文字體應(yīng)當(dāng)筆畫粗細(xì)適中馁菜,方正豎直茴扁。而整體傾斜的斜體字體,筆畫統(tǒng)一加粗的粗體字體或者疊加了加粗和傾斜效果的粗斜體等特殊字體則穿插其中用作突出強(qiáng)調(diào)或表示其他附加信息汪疮。
但就整體的排版風(fēng)格而言峭火,斜體,粗體智嚷,粗斜體等特殊字體又應(yīng)當(dāng)和正文字體有一定的統(tǒng)一性卖丸。所以,很多字體制作者會制作配套使用的多款字體打包在一起稱為一個“font family”盏道。例如西文字體名“Arial”其實就是一個 font family name稍浆,涵蓋了普通正文用的字體和斜體、粗體等配套使用的變種字體。
當(dāng)然也有時候字體作者沒有把同一個字體微調(diào)很多遍的耐心衅枫,就會只給出 font family 的一兩個變種嫁艇,剩下的情況由基礎(chǔ)字體經(jīng)過程序自動調(diào)整變形得到。說到這里弦撩,稍有編程思維的人可能都很容易想到步咪,這類機(jī)制其實可以推而廣之變成一種參數(shù)化設(shè)計——字體設(shè)計師在設(shè)計字體的時候不直接給定具體的尺寸值,而是給出尺寸之間的依賴關(guān)系益楼,這樣在使用時用戶就可以自行調(diào)整字體的筆畫粗細(xì)猾漫、傾斜程度、字符間距等值感凤。這就叫做可變字體(variable font)悯周。這是一個非常好的設(shè)想,但這種功能需要字體渲染引擎等程序的支持陪竿,而比較老舊的系統(tǒng)或者引擎是不支持這種功能的队橙。另外就是字體文件本身得是按可變字體的格式制作的,但此前的舊字體文件自然都不是按這種標(biāo)準(zhǔn)制作的萨惑。所以可變字體目前還在普及的過程中捐康。
連字
在手寫或者排印中一個字符的寫法不一定是一成不變的,有可能根據(jù)前后文字有所調(diào)整庸蔼。例如手寫體中的連筆牽絲和英文排印中的“fi”合印字符就屬于這種現(xiàn)象解总,英文叫做“l(fā)igature”,漢語可翻譯為“連字”姐仅。
在手寫時花枫,無論連字還是合寫字都能輕松地靈活處理。但是對于印刷來說就需要特殊處理掏膏,在活字印刷時代劳翰,可以把需要連寫或者壓縮空間合寫的若干個字符的字形調(diào)整后合刻在一個鉛字上解決。但如果在字符編碼時也使用這種方式馒疹,窮舉并編號所有可能的合字或連筆字形顯然會浪費(fèi)大量的編碼空間佳簸。因此 Unicode 的大致處理方式是已經(jīng)收錄的連字或合字不做改動,后續(xù)更新的時候盡量不收錄連寫或者合字造成的新字形(當(dāng)然存在一些例外颖变,例如合字本身已經(jīng)逐漸固定成一個專門符號)生均。而連字效果交給字符渲染程序去處理,讓渲染程序根據(jù)上下文調(diào)整字符字形腥刹。
但是和可變字體類似马胧,早期的字體引擎和字體文件格式都是不支持這種特性的。因此衔峰,雖然現(xiàn)在有了一些支持連字顯示的軟件和一些帶連字的字體佩脊,但總體上連字功能還在普及的過程中蛙粘。
連字不僅僅能用于模仿手寫的字體中。一些編程字體也利用這一特點(diǎn)美化代碼顯示威彰。例如 ASCII 中沒有大于等于號出牧,所以一般用
>=
表示。而如果使用支持連字的字體抱冷,就可以把>=
自動替換顯示成“≥”(但是編碼仍舊是>=
兩個字符的編碼崔列,只是顯示效果改變)梢褐。
阿拉伯文字母的連寫變形和各種類似的手寫字體變形以及連用多個橫線符號的連接等其實都應(yīng)該用連字來實現(xiàn)旺遮。但是由于這個功能出現(xiàn)得很遲,所以有的字符連接就一直將錯就錯現(xiàn)在反而成了一種排版風(fēng)格盈咳。例如中文破折號其實應(yīng)該是一條連起來的長線耿眉,但是很多字體和渲染程序中是斷開的兩段橫線,久而久之很多人反而習(xí)慣了這種顯示方式鱼响。有的則用了其他的處理方式鸣剪,例如阿拉伯文的字母變形。阿拉伯文字母的原型和連寫變形被分別在 Unicode 的不同號段編號丈积,在保存文字時一般僅保存原型的組合筐骇,但顯示的時候由渲染程序自動映射成變形形式根據(jù)變形字體渲染顯示。阿拉伯文的這套變形處理機(jī)制不依賴于現(xiàn)在的連字功能江滨,所以不支持連字的瀏覽器和字體也可能能正確顯示阿拉伯文铛纬。
替換字形
有時候同一個字符會有多種不同字形,而且不同人在不同場景下會對這些字形有不同的取舍唬滑。比較舊的字體通過打包不同版本的字體文件來實現(xiàn)個別字體的替換告唆,這是一種相對低效且復(fù)雜的辦法。現(xiàn)在的一些字體會直接把所提供的各種字形變體和普通字形一起打包在同一個字符文件中晶密,在調(diào)用時使用字形參數(shù)進(jìn)行替換(需要應(yīng)用程序支持這一功能)擒悬。
這種通過字形參數(shù)選擇替換字形的方法參考: https://github.com/tonsky/FiraCode/wiki/How-to-enable-stylistic-sets。
Unicode 覆蓋
Unicode 為幾乎所有已知的人類文字符號分配了編碼稻艰,但它本身并不提供字體懂牧。而字體的制作者往往是針對某一個具體的語言環(huán)境去制作字體,因此只會為 Unicode 中的一部分字符制作字形尊勿。目前據(jù)我所知還沒有完全覆蓋 Unicode 全部定義編碼的字體归苍。因此,在后續(xù)介紹字體時运怖,我們會按照字體的覆蓋范圍進(jìn)行大致的分類拼弃。
PUA 覆蓋
這里的 PUA 不是“pick-up artist”的意思,而是指“private use areas”摇展,也就是 Unicode 中預(yù)留出來讓用戶自己或其他機(jī)構(gòu)約定用法的區(qū)域吻氧。由于這個區(qū)域的用法不是統(tǒng)一約定的,所以不同使用者的使用方式可能是不同的乃至有沖突的。不過對于一個具體的系統(tǒng)內(nèi)部來說盯孙,只要內(nèi)部的約定統(tǒng)一鲁森,是不存在沖突的。例如程序員們約定了幾個 PUA 碼位用于繪制虛擬終端命令行的特殊符號振惰,而一些語言文字愛好者則用 PUA 來表示一些尚未被 Unicode 收錄的非自然語言文字符號歌溉。這兩套系統(tǒng)的規(guī)則是不同的,但是它們各自內(nèi)部是沒有沖突骑晶,可以正常使用的痛垛。
由于 PUA 區(qū)域的用法并不是 Unicode 指定,所以覆蓋這一區(qū)域的字體并不能簡單互換桶蛔,而要看它們支持的是哪些 PUA 協(xié)議匙头。在后續(xù)的介紹中, PUA 協(xié)議和支持這些協(xié)議的字體也會依照大致的使用范圍分類介紹仔雷。
本文源碼采用 MIT 協(xié)議開放蹂析,托管于: https://github.com/ZhiZe-ZG/ZZToolLibrary
如果覺得本文內(nèi)容對您有用,希望您能在能力和意愿范圍內(nèi)給我一些資助碟婆。我不以此為生电抚,但我也是個普通人。