印刷或者排版領域,關於字體的東西是一筆糊塗賬。這筆糊塗賬從鉛字時就開始了。在現在全是字體文件的時代,問題依然存在,簡單的,大多是譯名和基礎概念上的問題;複雜的,多是技術問題,能解決的人非常少。
不過,就算混亂,兩個人閒聊一會,大概也能互相了解個大概。所以模糊的東西模糊著說,不太有大的影響。是可以往細了討論的,但是顯得繁瑣,甚至在某種程度上說是掌握了一些無用的知識。
從排版軟件上說,字體實際上可以分成兩個部分:圖像部分,非圖像部分。圖像部分對於人最為重要,符號代表著意義,人通過符號獲取信息。但是,有些反常識的是,圖像部分對於排版軟件實際上是不太重要的。重要的是非圖像部分:一組抽象的信息。而這組抽象信息大多表現為數字,比如字的寬度,高度,等等。
TeX中讀的字體,是TFM(TeX Font Metric),就是非圖像部分的信息。最終的圖像呈現部分是可能用Type 1字體或者擴展名為pk的字體。
Type 1字體,是Adobe公司的格式,就是來封裝一組矢量圖像的。這個Type 1實際上算是內部命名,如同三年級一班一樣,沒有特別的含義。而且,Adobe還有Type 2,Type 3之類字體格式。值得一提的是,Adobe公司最近停止了在自家軟件中對Type 1字體的支持。不過問題不大,並不影響PDF文件中的Type 1字體。這對於以使用PDF文件為主的LaTeX用戶來說,也不太成問題。
搭配TFM和Type 1字體,那麼就可以見到最熟悉的LaTeX效果了。有些時候,甚至可以通過特徵字體來判斷某一本書是不是LaTeX做出來的。我們可以直接看字表,這就是LaTeX文檔中默認的cmr10的所有字符:
不過,這套東西很麻煩。我都覺得麻煩。配置起來極為繁瑣。還好,現在有直接支持OpenType/TrueType的引擎,省事多了。
近些年來,XeTeX和LuaTeX的使用基本成了主流,很大程度可能就是OpenType/TrueType的支持。尤其是2019年LuaTeX接入了harfbuzz之後,理論上的核心排版能力和質量其實已經能夠超過XeTeX了。
我覺得大部分人可能都或多或少地用過如下命令:
setmainfont{<blabla >} % usepackage{fontspec}
setCJKmainfont{<blabla>} % usepackage{xeCJK}
setmainjfont{<blabla>} % usepackage{luatexja-fontspec}
這幾個命令真是懶人救星。寫一寫頁面的效果就變了,中文或者漢字的支持就解決了。除了這條命令,實際上還有下面幾組對應的命令:
fontspec | xeCJK | luatexja- fontspec |
jfontspec | ||
setsansfont | setCJKsansfont | setsansjfont span> |
setmonofont | setCJKmonofont | setmonojfont |
ewfontfamily | ewCJKfontfamily< br> | ewjfontfamily |
enewfontfamily | —— |
enewjfontfamily |
setfontfamily | setCJKfamilyfont | setjfontfamily < /td> |
ewfontface | —— | ewjfontface | defaultfontfeatures | defaultCJKfontfeatures | defaultjfontfeatures |
addfontfeatures | addCJKfontfeatures | < td width='194' valign='top'>addjfontfeatures
這些命令大部分都比較好學,看看文檔就行了,不太好學的部分,實際上是*fontfeatures部分,對於普通用戶而言確實難得要領。
比如,我們手上有一個字體,要看看它文件內寫入了什麼feature,比如SourceHanSerifSC-Regular.otf,可以使用TeX Live自帶的命令:
otfinfo -f SourceHanSerifSC-Regular.otf
< /section>那麼終端輸出的部分如下:
- < li>
aalt Access All Alternates span>
calt Contextual Alternates
ccmp Glyph Composition/Decomposition
dlig Discretionary Ligatures
fwid Full Widths
halt Alternate Half Widths
hist Historical Forms
hwid < span class='code-snippet__string'>Half Widths
kern Kerning
liga span> Standard Ligatures
locl Localized Forms
palt Proportional Alternate Widths
pwid Proportional Widths
vert Vertical Writing
vhal Alternate Vertical Half Metrics
vkrn Vertical Kerning
vpal Proportional Alternate Vertical Metrics
vrt2 Vertical Alternates and Rotation
< /pre>
問題來了,什麼是feature呢?首先它是字體的一部分屬性。其次是,它可以看作是設計者預設的一些定向的排版優化。有些文章裡面把feature叫做特性,這是不太重要的翻譯,可以這麼叫,也可以說成是屬性。 OpenType內的feature一般是四個字母的縮寫形式。這個縮寫形式在TeX引擎底層是可以直接用的,尤其是在XeTeX中使用plain TeX格式:
- < li>
font-test.tex
fontfa='[SourceHanSerifSC-Regular.otf]'
fontfb='[SourceHanSerifSC-Regular.otf]:+aalt'< /span>
width 1ex height .88em depth .12em}}
lackrectfa “字體” lackrectpar
lackrectfb “字體”lackrectpar
ye
編譯方法:
xetex font-test.tex
輸出效果如下(引號部分被替換了):
這個時候,其實我們該引入glyph的概念了。 Glyph指的是什麼呢?圖像。只是一個圖像的概念。我們輸入到文件裡面的文本,都會轉換成glyph,然後顯示到屏幕上或者印出來。
在介紹glyph的時候,一般有一個經典的圖,用來表示一個unicode的表達的多樣性的。那就是骨頭的“骨”字:
輸入的都是“骨”字,但是因為不同地域使用習慣用的印刷體不同,會呈現不同的效果,大致相同,小處相異。題外話,這也是我們在多語種排版的時候(尤其是中文和日文混排),就算都是使用漢字的情況也需要根據不同類別的文本使用不同的字體(華東理工大學出版社前幾年出版的《日本語》就是一個比較糟糕的例子)。
但是glyph和unicode的關係還不是如此的簡單。比如還有一個unicode對應兩個glyph的情況,比如泰米爾語(Tamil)的u0B94:
還有多個unicode對應一個glyph的情況,這個,LaTeX用戶應該比較熟悉:
分別對應著:
ff fi fl ffi ffl
但是這個例子其實還可以說成是一個unicode對應一個glyph:
不過,可以並願意直接輸入這些字符的還是少數。
讓我們回到feature的話題上來。在OpenType裡面,有很大一部分feature都是用做glyph變換的,在TeX或者現代一點的排版軟件裡面,處理文本的流程中最簡單的是下面的這個過程(單個字符的變化,也是最簡單的情況,還有其他情況,本文暫不涉及):
那麼為什麼是從0到n呢?拿上面的aalt的例子舉例,用了一個字體,它默認有一個從unicode變換過來的glyph,通常會用一個數字來表示,那它就是glyph0,而使用了aalt,一旦覆蓋到了glyph的變化,那麼就會從glyph0變化為glyph1。 n的情況,也就是變化n次才得到最終的glyph,也是會出現的,尤其是漢語/西文之外的一些語言就會存在這種形式,不過一般不像我們上面手動開啟aalt的情況,因為它在某種程度上是自動的、預設的。
一個直接的例子是藏語的字體,比如我們可以看看Windows自帶的himalaya.ttf內的feature:
otfinfo --features --script=tibt c:windowsfontshimalaya.ttf
輸出為:
- < li>
abvm Above-base Mark Positioning
abvs Above-base Substitutions
blwm Below-base Mark Positioning
blws Below-base Substitutions
ccmp Glyph Composition/Decomposition
mark Mark Positioning
mkmk Mark to Mark Positioning
vert Vertical Writing< /code>
實際上我們是無法直接使用abvs/blws的,而且在某些情況下,就算用了,也不會產生實質性的影響。這是因為在漢語或/西文之外,有很多語言的文字在處理的是時候並不是平鋪直敘的從左到右或者從上到下的,而是需要變換成二維的形式。這些無法直接使用的feature大部分是為了做這些二維處理用的。
不過,能夠直接使用的feature還是很多的,fontspec包對於這些feature做了一定的分類,還做了一定的語義化封裝。比如:
- < li>
% font -test.tex
fontfa='[SourceHanSerifSC-Regular.otf]'
fontfb='[SourceHanSerifSC-Regular.otf]:+hwid'< /span>
fontfc='[SourceHanSerifSC -Regular.otf]:+fwid'
defsample{peninsula}
fasamplepar
fbsamplepar
fcsamplepar
< code>bye
效果如下:
那麼,在使用fontspec的時候,等價的代碼應該是:
- < li>
documentclass{article}
usepackage{fontspec}
begin{document}
defsample{peninsula}
fontspec {SourceHanSerifSC-Regular.otf}
sample
fontspec{SourceHanSerifSC-Regular.otf}[CharacterWidth=Half]
sample
fontspec{SourceHanSerifSC-Regular.otf}[CharacterWidth=Full]
sample
end{document}
這個CharacterWidth就是fontspec定義的一個語義化後的類別,它允許用戶使用不同的參數,當它等於Half的時候就會使相應的glyph變成hwid形式。
那麼舉一反三,如果我們想將這個feature設為LaTeX文檔的字體的默認屬性,那麼自然可以:
usepackage{fontspec}
defaultfontfeatures{CharacterWidth=Half} span>
詳細的歸類,fontspec中有一張表:
每個類別的用法,可以看fontspec的文檔。漢字字體的feature設計,其實普遍偏少,西文字體的feature設計的比較多。這些feature使用得當,文檔的呈現效果會相當豐富。一個例子,就是我們在排版一些代碼的時候,可以這樣:
- < li>
documentclass{article}
usepackage{fontspec}
setmonofont{FiraCode-Regular.ttf}[Contextuals=Alternate]
< span class='code-snippet_outer'>usepackage{pygmentex}
egin{document}
oindentsmall
egin{pygmented}[lang=hs]
qsort2 :: Ord a => [a] -> [a]
qsort2 [] = []
qsort2 (x:xs) = qsort2 lesser ++ equal ++ qsort2 greater
where code>
(lesser,equal,greater) = part x xs ([],[x],[])< /span>
part :: Ord a => a -> [a] -> ([a],[a],[a]) -> ([a],[a],[a])
part _ [] (l,e,g) = (l,e ,g)
part p (x:xs) (l,e,g) code>
| x > p = part p xs (l,e,x:g)
| x < p = part p xs (x:l,e,g)
| otherwise = part p xs < span class='code-snippet__params'>(l,x:e,g)
end{pygmented}
end{document}
pre>
效果如下:
對於某些fontspec分類沒覆蓋的feature,fontspec其實也可以支持,文檔中的示例(LuaTeX的例子):
- < li>
documentclass{article}
usepackage{fontspec}
directlua{
fonts.handlers.otf.addfeature {
< span class='code-snippet_outer'> name = 'oneb',
type = 'substitution',
data = { code>
['1'] = 'one.ss01' ,
}
}< /span>
}
setmainfont{Vollkorn-Regular.otf} [RawFeature=+oneb]
egin{document}
1234567890
end{document}
OpenType的feature,尤其是涉及到大量字符變體的部分,實際上和GUI結合地比較緊密,比如Adobe的軟件中就有一些動態菜單可以用來控制這些變化。但是這類工具,在TeX社區其實是很少的。
寫到這,我覺得有必要提一句我和我的同事們正在做的工作:一個字體預覽器。在設計目標上,除了能看字體支持了那些字符外,還能看OpenType裡面的這些個feature。但是研發道路漫長,有些關鍵性的內容還沒做完。等做完,我再另寫一篇文章介紹。
除此之外,fontspec還有一些其他技術支持,比如Apple的AAT技術,SIL的Graphite技術。這些技術主要是為了解決特定語言的排版難題的,漢字字體應用這兩類技術的其實不多。所以本篇也不打算介紹這兩個技術的內容了。我打算放在我目前的書裡面介紹一下,尤其是SIL的Graphite技術,在解決阿拉伯語排版和國際音標的排版有非常好的效果。
下一篇我會介紹一下LaTeX中的插圖。
歡迎分享並訂閱本公眾號。
文章為用戶上傳,僅供非商業瀏覽。發布者:Lomu,轉轉請註明出處: https://www.daogebangong.com/zh-Hant/articles/detail/Lets%20get%20to%20know%20LaTeX%20and%20fonts%20again.html
评论列表(196条)
测试