iT邦幫忙

2023 iThome 鐵人賽

DAY 14
1

在上個禮拜裡,我們介紹了一些很常見的 feature,我們接下來看看如何在 OpenType 裡實現他們。

用來標記 feature 的「語言」其實並沒有統一的規定,如 Adobe 開發的 AFKDO(Adobe Font Development Kit for OpenType)、Microsoft 的 VOLT (Visual OpenType Layout Tool) 等等。

在這裡,我們會介紹最通用的 AFKDO 語言。

額外注意的是,AFKDO 僅僅是一種標記用的語言,跟 HTML 類似,他本身僅僅用來描述,並沒有辦法進行複雜的邏輯判斷。

取名原則

  1. 每個字符的名稱必須要小於 63 個字元。
  2. 只允許使用大小寫 AZ、數字、英文句點(.)、以及底線(_)命名。
  3. 字元名稱不能以數字開頭。
  4. 通常來說,位處 BMP 上的字符(四位數)會以 uniXXXX 開頭,而輔助平面上的(五位數的 Unicode)則為 uXXXXX
  5. 允許使用易讀的名稱命名字符。例如 $ 可以是 uni0024,也可以是 dollarΩ可以是 uni03A9,也可以是 Omega 可以是 uni3042,也可以是 a-hira
    • 通常來說,我們習慣使用 <parent>.<child> 來表示同字母的父子關係,例如 A.sc 就是和 A 有關。
    • <alphabet>-<script> 則用來表示同一種文字系統,例如「b-bopomofo)、p-bopomofo)」;「a-hira)、sa-hira)」;「ДDe-cy)、ЖZhe-cy)」,看得出來是同一家人。
  6. 除了用來標示缺字(也就是豆腐)的 .notdef 字符之外,字元名稱不能以 ,- 開頭。
    • 舉例來説,aKappaspacedollaruni60C5twodotsj.fullm_hungarumlautcomb 都是可用的字符名稱
    • 2dots.uni597D._.A 則無法使用

類別

  1. 隱式列舉:可以透過 [ ... ] 的方式將數個字符名稱包在其中,用空格分開,使其視為同一類別
    • 例如:space [endash emdash figuredash] space
    • 等價於 space endash spacespace emdash spacespace figuredash space
  2. 對於英文與數字、以及其字序列,可以透過 - 字符取得一定的範圍
    • 語法:[<firstGlyph> - <lastGlyph>]
    • 例如:[A.swash - Z.swash][a - z][0 - 9]
  3. 顯式列舉
    • 語法:@<name> = [ ... ]
    • 例如:透過 @dash = [endash emdash figuredash]; 進行 assign
    • 使用時:space @dash space
  4. 可使用巢狀結構
@Vowels.lc = [a e i o u];
@Vowels.uc = [A E I O U];
@Vowels = [@Vowels.lc @Vowels.uc];

# 等價於 
@Vowels = [a e i o u A E I O U];

基本特性編寫方式

feature <name> [useExtension] {
    # rules...
} <name>;

其中,<name> 為 feature 的名字。長度恆為四個字母,必須要和 OpenType 規格的定義相同,否則無法被軟體正確的讀取與啟用。當該區塊的規則超過 64 KB 時,可以透過 [useExtension] 語法拓展要寫入的規則。每行最後應該使用分號 ; 表示結尾。

例如以下是一個把 ff 處理成 f_f 連字的特性規則:

feature liga {
    sub f f by f_f;
} liga;

巢狀規則

feature <name> {
	…
} <name>;

等價於

feature <name> {
    lookup <label> {
        …
    } <label>;
} <name>;

這樣的好處,在於可以透過 label 更清楚標示我們要替換的規則,例如下方的 pnum 特性包裝了用於拉丁字母的 pnum_latin 跟阿拉伯字母的 pnum_arab

feature pnum {
    lookup pnum_latin {
        sub zero by zero.prop;
        sub one by one.prop;
        sub two by two.prop;
        ...
    } pnum_latin;

    lookup pnum_arab {
        sub uni0660 by uni0660.prop;
        sub uni0661 by uni0661.prop;
        sub uni0662 by uni0662.prop;
    ...
    } pnum_arab;
} sups;

甚至可以在不同的 feature 中引用同一組 lookup 規則,讓版面更好閱讀

lookup myAlternates {
    sub A by A.001; # Alternate form
    ...
} myAlternates;

feature salt { lookup myAlternates; } salt;
feature ss01 { lookup myAlternates; } ss01;

替換方式

從前面介紹的連字、上下文替代、文體集與字符組成等等,不難發現他們背後的邏輯都是「替換」(lookup)。在 OpenType 裡總共定義了八種替換方式,如下表所示:

Value Type 替換規則
1 Single 將一個字符換成另一個字符
2 Multiple 將一個字符換成多個字符
3 Alternate 將一個字符換成多個可能字符之一
4 Ligature 將多個字符換成另一個字符
5 Context 根據前後文替換多個字符
6 Chaining Context 根據串接的前後文替換多個字符
7 Extension Substitution 用於擴充
8 Reverse chaining context single 根據連續前後文反方向替換多個字符(通常用於阿拉伯文)

對應前幾天我們所介紹的 feature 們:

feature 中文 Lookup 預設
liga 標準連字 4 預設開啟,但可關閉的連字
dlig 可擇連字 4 預設不開啟
hlig 歷史連字 4 預設不開啟
smcp 小寫轉小型大寫字母 1 預設不開啟
c2sc 大寫轉小型大寫字母 1 預設不開啟
swsh 花飾字 1 預設不開啟
salt 預設文體替代字 1 預設不開啟,通常建議等於ss01
ss01-ss20 文體集 1 預設不開啟
calt 上下文替代字 6 預設開啟
vert 竪排 1 預設開啟
vrt2 竪排・改 1 預設開啟
ccmp 字符分解與組合 4, 2 強制套用

學習完基本語法後,我們會在明天繼續介紹如何編寫


上一篇
DAY 13|OpenType Feature (6):組合字符
下一篇
DAY 15|AFKDO (1):LookupType 1 ~ 3
系列文
一起成為新世紀文字藝術師:深入玩轉 Unicode 和 OpenType30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言