共用方式為


OpenType 變數字型

本主題描述 OpenType 變數字型、其在 DirectWrite 和 Direct2D 中的支援,以及如何在應用程式中使用這些字型。 

什麼是 OpenType 變數字型?

OpenType 字型格式規格的 1.8 版 引進了稱為 OpenType 字型變化格式的新延伸模組。 使用這些延伸模組的字型稱為 OpenType 變數字型。 OpenType 變數字型是單一字型,可透過在不同設計之間使用連續插補點來表現得像數個字型的單一字型,全都定義於單一字型內。

OpenType 變數字型可以定義其設計沿著一或多個獨立軸的連續變化,例如粗細或寬度:

 

使用字母 'G' 顯示 OpenType 變數字型,並沿著水平寬度軸和垂直粗細軸顯示不同的變化。

字型開發人員會決定一組要用於指定字型的變化軸。 這些座標軸可以包含一組已知的(或「已註冊」)變化軸,例如粗細和寬度,但也可能包含字型開發人員所定義的任意自定義變化軸。  

藉由選取字型的一組變化軸,字型開發人員會定義字型設計變化的抽象 n 維空間。 文字引擎可以在該連續空間內指定任何位置或「實例」,以便配置和轉譯文字。 

字型開發人員也可以選取並指派名稱給設計變化空間內的特定實例;這些稱為「具名實例」。 例如,粗細變化的字型可能支援非常輕和非常重的筆劃之間的連續變化,而字型開發人員則選取了該連續專案的特定粗細,併為其指派名稱,例如 “Light”、“Regular” 和 “Semibold”。 

OpenType 變數字型格式會使用傳統 OpenType 字型中找到的數據表,以及描述不同實例各種數據項值如何變更的特定其他數據表。 格式會將一個變化實例指定為「預設實例」,它會使用傳統數據表來取得預設值。 所有其他實例都相依於預設數據和其他差異數據。 例如,『glyf』 數據表可以有名義圖像圖形的 Bezier 曲線描述,這是用於預設實例的圖形,而 『gr』 數據表將描述 Bezier 控制點如何調整其他實例的 Bezier 控制點。 同樣地,其他字型值可以有名義值加上差異數據,描述這些值如何針對不同的實例變更;例如,x 高度和其他全字型度量,或圖像特定的標記錨定位置和刻度調整。 

因為變數字型可以支援任意的一組變化軸,所以它們需要一個可延伸的字型系列模型,更直接地反映字型設計工具如何建立字型系列:字型系列是由家族名稱和某些設計特性所定義,且具有任意數位(由字型開發人員決定),設計可能會有所不同的方式。 一個字型系列可能會以變數來建立,但不同的字型系列可能會以 x 高度、serif-size、“funkiness” 或任何字型開發人員想要的變體來建立。 在此模型中,最好使用一般或「慣用」或「印刷」、系列名稱加上一組索引鍵/值組來描述字型臉部選取,每組都代表一種變化和特定值,一般變化種類為可延伸集合。 這個字型系列的一般概念可以套用至傳統、非變數字型,以及變數字型。 例如,在此一般印刷系列模型中,系列 「Selawik VF」 可能會有重量、光學大小和 Serif 設計的變化,例如“Semilight Banner Sans”。 

不過,某些現有的軟體實作,包括現有的 DirectWrite API,可能會設計成更有限的字型系列模型。 例如,某些應用程式可能假設字型系列最多可以有一般、粗體、粗體、斜體和粗體斜體變體。 現有的 IDWriteFontCollectionIDWriteFontFamily 介面假設權數/延展/樣式 (“WSS”) 系列模型,讓系列內的變體可以使用 DWRITE_FONT_WEIGHTDWRITE_FONT_STRETCHDWRITE_FONT_STYLE 列舉來指定為參數。 以先前的範例為例,光學大小和 serif 軸不會被視為 WSS 模型中變化的家族內部軸。 

對變數字型的完整支援需要 API,才能使用可能由字型決定的數個參數來指定家族成員。 但是,現有的 API 設計可以藉由將變數字型中定義的具名實例投影到更有限的字型系列模型,來提供變數字型的部分支援。 在上一個範例中,“Selawik VF Semilight Banner Sans” 可以投影到 WSS 模型中,做為 “Selawik VF Banner Sans” 系列,而 “Semilight” 是重量變體。 

如需另一個範例,請考慮具有粗細和光學大小變化的印刷字型系列,例如 Sitka。 家族中的具名變體包括 Sitka Text Regular 和 Sitka Banner Bold (加上許多其他變數)。 印刷系列名稱是 「Sitka」,而印刷系列模型中這些變體的臉部名稱會是「文字一般」和「橫幅粗體」。 四成員和 WSS 系列模型不允許家族內的光學大小變異,因此必須像家族層級的區別一樣對待光學大小差異。 下表說明如何在 WSS 系列模型中處理 Sitka 印刷樣式系列中的字型選擇:

印刷樣式系列模型

WSS 系列模型

家庭

家庭

錫特卡

文字一般

Sitka 文字

定期

錫特卡

橫幅粗體

Sitka 橫幅

大膽

錫特卡

標題斜體

Sitka Caption

斜體的

 

從印刷系列模型到 WSS 系列模型的名稱投影可以套用至非變數字型,以及變數字型的具名實例。 不過,對於其他非具名實例而言,這無法從變數字型的連續設計變化空間完成。 基於這個理由,支援可變字型的完整功能,需要 API 設計來參考印刷樣式系列中的臉部,以不受限制的一組變化軸和座標軸值來參考。 

DirectWrite 中的 OpenType 變數字型支援

自 Windows 10 Creators Update 發行開始,OpenType 變數字型格式仍然非常新,而且字型廠商、平臺和應用程式仍在實作新格式的過程中。 此更新提供 DirectWrite 中此格式的初始實作。 

DirectWrite 內部已更新以支援 OpenType 變數字型。 使用目前的 API,這可支援變數字型的任何具名實例。 這項支援可用於完整的工作流程,從具名實例的列舉、具名實例的選取、在版面配置和成形中使用,到轉譯和列印。 為了受益於也針對特定作業使用 GDI 文字 Interop 的應用程式,現有的 GDI API 中也新增了類似的支援。 

在 Windows 10 Creators Update 中,DirectWrite 不支援使用可變字型連續變化功能的任意實例。

在許多作業中,變數字型具名實例的 DirectWrite 行為無法與非變數字型的行為區別。 而且,由於支援使用現有的 DirectWrite API,因此變數字型的具名實例甚至可以在許多現有的 DirectWrite 應用程式中運作,而不需要進行任何變更。 不過,在某些情況下,例外狀況可能適用:

  • 如果應用程式會直接處理特定作業的字型數據。 例如,如果應用程式直接從字型檔案讀取圖像大綱數據,以建立特定視覺效果。
  • 如果應用程式針對特定作業使用第三方連結庫。 例如,如果應用程式使用 DirectWrite 進行版面配置,則取得最終圖像索引和位置,但接著會使用第三方連結庫進行轉譯。
  • 如果應用程式將字型數據內嵌至檔,或以某種其他方式將字型數據傳遞至下游程式。

如果使用不支援變數字型的實作來執行作業,則這些作業可能不會產生預期的結果。 例如,字元位置可能會針對變數字型的一個具名實例計算,但字元可能會轉譯為假設不同的具名實例。 視應用程式實作而定,結果可能會在某些內容中運作,但不適用於其他連結庫可能使用的其他內容。 例如,文字可能會在畫面上正確顯示,但列印時可能不會顯示。 如果只使用 DirectWrite 實作端對端工作流程,則可以預期變數字型具名實例的正確行為。 

由於現有的 DirectWrite API 支援使用權數/延展/樣式模型進行臉部選取,因此使用其他變化軸的字型具名實例將從一般印刷系列模型投影到 WSS 模型,如上所述。 這依賴變數字型,包括具有軸值子數據表的「樣式屬性」(『STAT』)數據表,DWrite 會使用這個數據表來區分臉部名稱標記,這些標記會指定與其他變化軸相關的標記的權數、延展性或樣式屬性。  

如果變數字型不包含 『STAT』 資料表,OpenType 規格所需的變數字型,DirectWrite 會將字型視為只包含預設實例的非變數字型。  

如果字型包含 『STAT』 數據表,但不包含適當的座標軸值子數據表,可能會導致非預期的結果,例如有多個臉部具有相同臉部名稱。 目前不支援這類字型。 

OpenType 規格允許以兩種格式的其中一種格式來表示字元大綱數據:使用 'glyf' 表格,使用 TrueType 大綱和提示格式,或使用 'CFF' 表格,使用精簡字型格式 (“CFF”) 表示法。 在具有 TrueType 外框的變數字型中,會繼續使用 'glyf' 數據表,並以提供大綱變化數據的 'br' 數據表補充。 這表示具有 TrueType 外框之變數字型的預設實例只會使用舊版軟體不支援可變字型的傳統 OpenType 數據表。 不過,在具有 CFF 外框的變數字型中,『CFF』 資料表會取代 『CFF2』 數據表,它會封裝預設大綱數據和一個數據表中相關聯的變化數據。 CFF 數據是由用於 TrueType 數據的個別轉譯器處理,而 'CFF2' 數據表需要具有 'CFF2' 支援的更新 CFF 轉譯器。 舊版 CFF 轉譯器無法處理 『CFF2』 資料表。 對於具有 CFF 大綱數據的變數字型,這表示即使是預設實例也無法在舊版軟體中運作。 

在 Windows 10 Creators Update 中,DirectWrite 不支援使用 'CFF2' 數據表搭配 CFF 大綱數據的變數字型。 

使用 OpenType 變數字型

OpenType 變數字型很容易使用,請記住上述目前的限制:

  • 目前僅支援變數字型的具名實例。
  • 目前僅支援使用 TrueType 字元外框數據的變數字型(而非 CFF 外框)。 
  • 對於使用粗細、伸展或樣式以外設計變化軸的字型,具名實例會投影到 WSS 系列模型,這可能會導致某些具名實例顯示為個別系列(就像過去非變數字型一樣)。 若要支援此功能,變數字型必須有包含適當座標軸值子數據表的 『STAT』 資料表。
  • DirectWrite API 支援變數字型的具名實例,但如果某些作業是在不支援變數字型的較舊實作中執行,這些作業可能會產生不正確的結果。 
  • 某些 DirectWrite API 會在選取臉部時,使用 DWRITE_FONT_WEIGHTDWRITE_FONT_STRETCHDWRITE_FONT_STYLE 列舉來指定權數、延展和樣式屬性。 如果變數字型使用對應的變化軸,但有許多具名實例需要更精細的數據粒度,並非所有具名實例都可以在這些 API 中選取。

符合這些需求的OpenType變數字型可以從Windows殼層安裝,就像其他OpenType字型一樣,也可以在應用程式所建立的自定義字型集中使用。  

在系統中安裝時,變數字型的所有具名實例都會包含在呼叫IDWriteFontFamily3::GetSystemFontSet 方法所傳回的字型集中。 請注意,字型集是不含家族群組階層的一般清單,但集合中的每個專案都有以WSS系列模型為基礎的系列名稱屬性。 您可以使用 IDWriteFontSet::GetMatchingFonts 方法來篩選特定變數字型具名實例的字型集。 不過,如果使用 GetMatchingFonts 採用 familyName 的多載,則指定的 familyName 必須使用符合 WSS 字型系列模型的名稱。 使用 DWRITE_FONT_PROPERTY_ID_FAMILY_NAME,可以使用 IDWriteFontSet::GetPropertyValues 方法來取得字型集中所發生的 WSS 相容系列名稱完整清單。  

同樣地,變數字型的所有具名實例都會在IDWriteFactory::GetSystemFontCollection 方法傳回的字型集合中表示。 由於字型集合的元素是以 WSS 模型為基礎的字型系列,因此變數字型的具名實例可能會以兩個或多個字型系列的成員表示在集合中。 如果使用 IDWriteFontCollection::FindFamilyName 方法,familyName 參數必須是 WSS 相容的系列名稱。 若要從字型集合尋找所有與 WSS 相容的系列名稱,應用程式可以迴圈查看每個系列,並呼叫 IDWriteFontFamily::GetFamilyNames,不過可能更容易取得對應的字型集,並使用 GetPropertyValues 方法,如上所述。 

使用自定義字型時,自定義字型集 主題中所述的各種方法可用來建立字型集。 若要將變數字型新增至自定義字型集,建議使用 IDWriteFontSetBuilder1::AddFontFile 方法,因為它支援變數字型,並將在單一呼叫中新增變數字型的所有具名實例。 目前沒有任何方法可以使用 IDWriteFontSetBuilder::AddFontFaceReference 方法,將自定義變數字型的個別具名實例新增至字型集,因為無法建立字型參考,以指定變數字型檔案中的具名實例。 這表示目前無法將自定義字型的具名實例新增至已指派自定義屬性的自定義字型集。 這反過來又表示,自定義變數字型目前無法與遠端字型的 DirectWrite API 搭配使用。 不過,如果變數字型的具名實例包含在系統字型集中,則每個具名實例的字型臉部參考已經存在,而且這些字型可以新增至自定義字型集,包括使用自定義屬性值。 如需詳細資訊,請參閱自定義字型集主題。 

使用變數字型時,DirectWrite DWRITE_FONT_WEIGHTDWRITE_FONT_STRETCH 列舉會與 OpenType 規格中定義的粗細和寬度變化軸緊密連接,但不同。 首先,任何變化座標軸的數值小數字數一律支援分數值,而fontWeight和fontStretch則使用整數。 OpenType 粗細軸刻度會使用介於 1 到 1000 的值,字型Weight 也支援此值。 因此,從變化權數軸值變更為fontWeight相對較少:針對具名實例所報告的fontWeight可能會從用來定義字型內具名實例的精確值四捨五入。 DirectWrite fontStretch 與 OpenType 寬度座標軸小數位數的差別更大:DirectWrite 會使用 1 到 9 的值,遵循 usWidthClass OpenType OS/2 數據表的值,而 OpenType 寬度坐標軸小數位數則使用代表一般寬度百分比的正值。 OpenType 規格中的 usWidthClass 檔提供值 1 到 9 與正常百分比值的對應。 針對具名實例所報告的 fontStretch 值,在從寬度座標軸值轉換時,可能會涉及四捨五入。 

建立 IDWriteTextFormat時,必須指定字型集合和 WSS 相容的字型屬性(系列名稱、粗細、延展和樣式)。 這也適用於在 IDWriteTextLayout 文字範圍上設定字型格式設定屬性時。 屬性可以從 IDWriteFontFace3 物件,或從 IDWriteFontIDWriteFontFamily 代表特定具名實例的物件取得屬性。 如上所述,GetWeight 和 GetStretch 方法所傳回的值可能會針對用來定義具名實例的實際座標軸值四捨五入近似值,但 DirectWrite 會將屬性的組合對應回所需的具名實例。 

同樣地,如果應用程式使用 IDWriteFontFallbackBuilder 來建立自定義字型後援數據,則會使用 WSS 相容的系列名稱來指定字元範圍對應。 DirectWrite 內的字型後援是以 DirectWrite 在後援系列中選取變體的家庭為基礎,該系列與起始系列變體最接近相符。 對於涉及權數、伸展和樣式以外的維度的變體,DirectWrite 目前無法在後援系列中選取這類變體,除非特別建立自定義後援數據來提供具有特定非 WSS 屬性之家族的後援對應,例如 “Caption” 光學大小變體。