LaTeX 中字體調用機制是怎樣的?


TeX底層的字體機制  TeX底層調用字體的部分就很原始,了解下即可。想折騰的可自行找參考書折騰。字體相關命令:

  • /。此命令用於義大利體斜體字體的校正,是在正文中是進行手動校正的。
  • font。此命令即為字體調用的本尊。最早的TeX只支持讀取tfm文件,這個文件是字體的一部分。一個完整的TeX字體(MetaFont生成的)為一個tfm文件和pk文件,前者負責字體的抽象部分(如ligature,kern等),後者負責描述字體的實體部分(即字體的glyph具體長什麼樣子)。TeX最早出現的時候Adobe都沒出現呢,之後在列印的時候讓印表機讀取那些pk字體,後來一些開發者將這些MetaFont的字體轉換成PostScript的字體,通過dvips或者dvipdfm將dvi轉換成ps或者pdf文件。XeTeX的font命令可以支持直接使用TrueType、AAT或者OpenType字體。LuaTeX的font並不直接支持使用這些字體,需要使用內建的callback庫來調用。
  • fontdimen。這個命令可以調整tfm中內建的一些參數。
  • fontname。這個命令會返回一個字體名稱。

  • ullfont
    。這個命令是提供了又一個沒有字元的字體。在設定數學字體的時候會將未定義的字體定義為
    ullfont。

  對於數學字體,還有些特殊的命令:

  • fam。fam定義數學字體族。按照TeX本身的設計,數學字體的尺寸分為四個級別:textstyle( extfont),displaystyle,scriptstyle(scriptfont)和scriptscriptstyle(scriptscriptfont)。原始的TeX中只可以定義16個字體族,但是在XeTeX等引擎中沒有這個限制。fam調用的是一個數值,這個數值代表編號好的字體族,在數學模式下會得到處理。

  pdfTeX/LuaTeX是可以直接生成pdf的,在這後面是調用了pdfTeX預先定義好的pdftex.map文件,這個文件就是給每個tfm文件指定一個Type1字體或者TrueType字體。在使用的時候,可以在原文件中直接插入一個命令:

  • pdfmapline。如pdfmapline{cmr10 CMR10 &

  pdfTeX中還有個命令,是控制pk字體的解析度的(沒有cmr10.pfb的情況下就是使用pk字體的):

  • pdfpkresolution。控制調用的pk字體的解析度。

LaTeX中的字體調用機制

  LaTeX下的字體調用使用了一套複雜的宏來完成的,歸根到底還是上面的那些命令的套嵌使用。但是在LaTeX下面,用戶要做的僅僅是選用自己喜歡自己的字體。

  LaTeX下面的字體調用機制叫做NFSS(New Font Selection Scheme)。TeX Live用戶可以執行texdoc fntguide讀取LaTeX2e自帶的說明文檔。NFSS將正文的文本字體定義了五個屬性:encoding,family,series,shape和size。對於數學字體,NFSS也將之分為幾個比較詳細的屬性。

  NFSS定義的字體原本是為西文設計的,在1995年左右,日本的pTeX給NFSS打了補丁,讓NFSS支持pTeX本身的jfont, font和jfam等命令。使用NFSS定義,如果沒好好看文檔,容易出錯,所以不推薦新手直接動。使用NFSS定義的場合建議是一些長期不動的穩定的包或者文檔類。

  LaTeX下面還有個基於NFSS的字體調用宏:OFS(Olsak』s Font System)。這個包定義字體的風格類似於ConTeXt。喜歡ConTeXt風格的可以玩玩。可執行texdoc ofsdoc-e查看文檔。

  其實,最好用的還是fontspec包,這個可是懶人福音。不過fontspec在XeTeX下和在LuaTeX的效果不太一樣,畢竟兩個引擎的字體處理還有些不同。xeCJK和LuaTeX-ja都對這個包進行了一部分擴展。可執行texdoc fontspec查看文檔。


@Clerk Ma 同學最近邀請上癮了,繼續不感謝這話癆~( ̄▽ ̄)~

其實他在命令層面上已經講得很清楚了,我繼續加一些歷史細節就可以。就補充一些東亞文字的部分吧。

默認情況下,TeX 系統的字體選擇機制很直接,就是直接讀源代碼中的 ASCII 碼,看到反斜杠(「」)則開始理解為控制命令。最初的 TeX 系統是為西文設計的,所以它認為字符集只需要八個比特就可表示(最初是七個比特用於表達128個字元的ASCII,後來 Knuth 老頭子把它擴展到八個比特),正好和ASCII 編碼和後來的擴展,ISO8859-1 相吻合。所以處理拉丁字符集時,這一招遊刃有餘。但就是這個限制,導致了後來 TeX 在國際化排版時吃了無數的苦頭。

第一個苦頭就是東亞文字的字體。因為 TeX 假設一個字體文件的內容最多不超過 256 個字元,這一碰上東亞文字,就完蛋了。為了規避這個問題,TeX 前輩們引入了字體分區的概念,也就是把東亞文字和 Unicode 字體集分成若干個 256x 256的區塊,每個字的索引用兩個控制命令表示——是的,很接近 UTF-16 的表示概念。所以最初用 LaTeX 將 TTF 字體轉換為 Type1 格式的同學們可能都會注意到,從單個 TTF 轉換而來的 TFM 文件總是有一大串。

註:雖然 LaTeX 宣稱其支持 TTF 字體,但我沒用過,也不知細節,@Clerk Ma 同學,你怎麼看?

字體有了,怎麼表示呢?由於 TeX 總是假設字體編碼為一個位元組,直接用多位元組編碼的 TeX 源代碼文件是無法識別的。所以當 LaTeX 的 CJK 擴展第一次開始著手解決中日韓字體問題時,它加了個抽象層。簡單地說,就是在 TeX 引擎處理中文字元之前引入一個預處理的步驟。當預處理器看到東亞字元時,它就將這個字轉換成一段連續的控制命令。這樣生成的中間文件再轉交 TeX 引擎處理。引擎看到控制字元時就會按照預定義的命令索引正確的字體。

當年王垠同學的一篇文章解釋了 CJK 的工作原理:http://www.math.zju.edu.cn/ligangliu/latexforum/tex_cjk.htm

這個方法雖然簡單有效,但麻煩很多。最主要的問題就是它讓調試變得不方便。因為 TeX 引擎直接看到的並不是源代碼,一旦代碼出錯,TeX 列印的錯誤信息將完全不可讀。另一點是,由於設計上的限制,CJK 沒有把「編碼」和「語言」這兩個概念分開。需要知道文本的編碼才能正確排版,而且它對不同語言的排版規則(主要是斷字、縮進、行尾行頭標點行為等)並不統一。比如它遇到 Shift-JIS 時會自動啟用日文的排版規則,而 GB2312 則啟動中文排版規則。如果一篇文章里又有中文又有日文,它就傻眼了。雖然從編碼上我們可以選擇 UTF-8 ,但排版規則卻又變得不倫不類。

所以實際上,大家並不喜歡這個解決方案。但 LaTeX 畢竟只是一個擴展包,受限於 TeX 本身這個引擎,我們都做不了什麼,只能這麼湊合。ConTeXt 是另一個擴展包,做法和 LaTeX 不同,但背後的原理是差不多的。

這個時候群眾的呼聲是:神啊,換一個支持 Unicode 的引擎吧!

第一個改革者出現了,Omega。這個項目最初也是從擴展包開始,但很快就露出了兇殘的真面目:它打算重寫整個 TeX 引擎使其支持雙位元組 Unicode 編碼,還附帶一個 LaTeX 的等價擴展包,lambda。但後來不知為何,開發漸漸慢下來,直到最後偃旗息鼓,居然就這麼悄無聲息地不見了。ConTeXt 雖然很牛,但作者偏安荷蘭(它的代碼里甚至有一部分都是荷蘭文注釋,完全沒法看),也沒什麼太大的消息。其它的小打小鬧,比如 CTeX,則基本上是 CJK 擴展的擴展,沒有著眼於根本。日子似乎就這麼過下去了。

[註:本段內容有誤。XeTeX 最初的引擎已經完整支持 Unicode,默默無聞了很久的唯一原因,是因為其第一個版本只支持 Mac,相對影響力較低。感謝@江疆 指出。]

但救世主總是在不起眼的角落漸漸成長。正當大家以為咱們就得守著 CJK 過一輩子的時候,2004年 XeTeX 橫空出世。坊間傳言,XeTeX 是從 Omega 項目的代碼發展而來,之後默默無聞地混了很久,直到真正重寫了整個排版引擎讓其支持 UTF-8 編碼。所以 XeTeX 出現後,人們可以直接用它解讀 UTF-8 編碼的源代碼文件。配合上 LaTeX ,不需要 CJK 的預處理器也可以正確顯示東亞文字(注意:顯示和排版還是有距離的,顯示是引擎的能力,但排版規則還是需要 CJK 多年積累的規則)。

但這還沒完,XeTeX的另一大貢獻才真正解決了字體問題。XeTeX 添加了新的字體調用介面,支持直接讀取系統的 TTF 文件,這一下我們不用轉換也可以直接用 TTF 文件排版了。善莫大焉。

另一個真正根正苗紅的好漢紙是 @Clerk Ma 同學用的 LuaTeX。按說,它才是從 Omega 代碼而來的,當然的正統繼承者。甚至 XeTeX 的作者都曾說過,他很願意等 LuaTeX 開發完畢,那時候他就考慮停止 XeTeX 的開發。可善良的願望被殘酷的事實打擊得粉碎:LuaTeX 這貨開發速度太慢。本來它的開始時間 XeTeX 差不了許多,但等到XeTeX 從只支持 Mac 到全平台支持完畢,LuaTeX 居然還沒有大規模實用化。像我這種急性子顯然就等不到了。雖說它引入了很多不錯的機制,比如嵌入了 Lua 腳本語言進行擴展,但俺們這種俗人,還是安靜地用 XeTeX 吧。

以上。


推薦閱讀:

有沒有比latex更加好的寫作排版軟體,或者怎麼解決latex邊寫作還要邊編代碼的問題?
CTeX 2.0有哪些新功能?
如何在LaTeX數學模式中更好地使用粗體?
手機上怎麼使用LaTeX編輯呢?
LaTex怎麼下載?該下什麼版本

TAG:字體 | LaTeX | LaTeX排版與設計 |