OpenType 変数フォント
このトピックでは、OpenType 変数フォント、DirectWriteおよび Direct2D でのサポート、およびアプリでの使用方法について説明します。
OpenType 変数フォントとは
OpenType フォント形式仕様のバージョン 1.8 では、OpenType フォント バリエーションと呼ばれる形式の新しい拡張機能が導入されました。 これらの拡張機能を使用するフォントは、OpenType 変数フォントと呼ばれます。 OpenType 変数フォントは、1 つのフォント内で定義されているすべての異なるデザイン間の連続補間を使用して、複数のフォントのように動作できる 1 つのフォントです。
OpenType 変数フォントでは、1 つ以上の独立した軸 (太さや幅など) に沿ってデザインの継続的なバリエーションを定義できます。
フォント開発者は、特定のフォントで使用するバリエーション軸のセットを決定します。 これらの軸には、太さや幅など、よく知られている (または "登録済み" ) 一連のバリエーション軸を含めることができますが、フォント開発者によって定義された任意のカスタム軸のバリエーションを含めることもできます。
フォントのバリエーション軸のセットを選択することで、フォント開発者はフォントのデザイン バリエーションの抽象的な n 次元空間を定義します。 テキスト エンジンは、テキストをレイアウトしてレンダリングするために、その連続した空間内の任意の位置 ("インスタンス" ) を指定できます。
フォント開発者は、デザインバリエーション空間内の特定のインスタンスに名前を選択して割り当てることもできます。これらは"名前付きインスタンス" と呼ばれます。 たとえば、太さのバリエーションを持つフォントでは、非常に軽いストロークと非常に重いストロークの連続したバリエーションがサポートされる場合があります。一方、フォント開発者は、その連続体に沿って特定の重みを選択し、"Light"、"Regular"、"Semibold" などの名前を割り当てます。
OpenType 変数フォント形式では、従来の OpenType フォントに含まれるデータ テーブルと、さまざまなデータ項目の値が異なるインスタンスに対してどのように変化するかを記述する特定の追加テーブルが使用されます。 この形式では、1 つのバリエーション インスタンスを "既定のインスタンス" として指定します。これは、従来のテーブルを使用して既定値を取得します。 他のすべてのインスタンスは、既定のデータと他の差分データに依存します。 たとえば、'glyf' テーブルには、既定のインスタンスに使用される図形である名目グリフ図形のベジエ曲線の説明を含めることができます。一方、'gvar' テーブルでは、グリフのベジエ コントロール ポイントが他のインスタンスに対して調整される方法が記述されます。 同様に、他のフォント値には、呼び出し値と、それらの値が異なるインスタンスに対してどのように変化するかを記述する差分データを含めることができます。たとえば、x-height やその他のフォント全体のメトリック、グリフ固有のマークアンカー位置やカーニング調整などです。
可変フォントは任意のバリエーション軸のセットをサポートできるため、フォント デザイナーがフォント ファミリを作成する方法をより直接的に反映する拡張可能なフォント ファミリモデルが必要です。フォント ファミリは、ファミリ名と一定の特定のデザイン特性によって定義され、デザインが異なる方法の任意の数 (フォント開発者によって決定されます) で定義されます。 1 つのフォント ファミリは重み付け用のバリアントで作成できますが、x-height、serif-size、"funkiness" 、またはフォント開発者が望む任意のバリアントを使用して別のフォント ファミリを作成できます。 このモデルでは、フォントの顔の選択は、一般、つまり "優先" または "文字体裁" を使用して、ファミリ名とキーと値のペアのセットを使用して最もよく説明されます。それぞれにバリエーションの種類と特定の値が表され、一般的なバリエーションの種類は拡張可能なセットです。 フォント ファミリのこの一般的な概念は、従来の非変数フォントだけでなく、可変フォントにも適用できます。 たとえば、この一般的な文字体裁ファミリ モデルでは、ファミリ "Selawik VF" には、"Semilight Banner Sans" などのインスタンスを使用して、重量、光学サイズ、セリフの設計にバリエーションがある場合があります。
ただし、既存のDirectWrite API を含む一部の既存のソフトウェア実装は、フォント ファミリのより限られたモデルを想定して設計される場合があります。 たとえば、一部のアプリケーションでは、フォント ファミリには、通常、太字、斜体、太字の斜体のバリアントを含めることができると仮定する場合があります。 既存の IDWriteFontCollection インターフェイスと IDWriteFontFamily インターフェイスは、重み/ストレッチ/スタイル ("WSS") ファミリ モデルを前提としているため、 DWRITE_FONT_WEIGHT、 DWRITE_FONT_STRETCH 、または DWRITE_FONT_STYLE 列挙をパラメーターとして使用してファミリ内のバリアントを指定できます。 前の例では、光学サイズ軸とセリフ軸は、WSS モデルのバリエーションのファミリ内部軸として扱われません。
可変フォントを完全にサポートするには、フォントによって決定される複数のパラメーターを使用してファミリ メンバーを指定できる API が必要になります。 ただし、既存の API 設計では、変数フォントで定義されている名前付きインスタンスを、より限定的なフォント ファミリ モデルに投影することで、可変フォントの部分的なサポートを提供できる場合があります。 前の例では、"Selawik VF Semilight Banner Sans" は、重量バリアントとして "Semilight" を持つ "Selawik VF Banner Sans" ファミリとして WSS モデルに投影できました。
別の例として、太さと光学サイズのバリエーションを持つ Sitka などの文字体裁フォント ファミリを考えてみましょう。 ファミリ内の名前付きバリエーションには、Sitka Text Regular と Sitka Banner Bold (その他多数) が含まれます。 文字体裁ファミリ名は "Sitka" ですが、文字体裁ファミリ モデルのこれらのバリエーションの顔名は "Text Regular" と "Banner Bold" になります。 4 メンバーおよび WSS ファミリ モデルでは、ファミリ内の光学サイズバリアントは使用できないため、光学サイズの区別はファミリ レベルの区別のように扱う必要があります。 次の表は、WSS ファミリ モデルで Sitka 文字体裁ファミリから選択したフォントがどのように扱われるかを示しています。
文字体裁ファミリ モデル
WSS ファミリ モデル
ファミリ
Face
ファミリ
Face
シトカ
テキスト標準
Sitka テキスト
通常
シトカ
バナー太字
Sitka バナー
太字
シトカ
キャプション斜体
Sitka キャプション
[斜体]
文字体裁ファミリ モデルから WSS ファミリ モデルへの名前のプロジェクションは、非変数フォントと、可変フォントの名前付きインスタンスに適用できます。 ただし、これは、変数フォントの連続したデザインバリエーション空間の名前のない他のインスタンスでは実行できません。 このため、可変フォントの完全な機能をサポートするには、バリエーション軸と軸値の制約のないセットの観点から、文字体裁ファミリ内の顔を参照するように設計された API が必要になります。
DirectWriteでの OpenType 変数フォントのサポート
Windows 10 Creators Updateのリリース時点では、OpenType 変数のフォント形式はまだ非常に新しく、フォント ベンダー、プラットフォーム、アプリはまだ新しい形式を実装中です。 この更新プログラムは、この形式の初期実装をDirectWriteで提供します。
OpenType 変数フォントをサポートするように、内部DirectWriteが更新されました。 現在の API を使用すると、変数フォントの名前付きインスタンスがサポートされます。 このサポートは、名前付きインスタンスの列挙、名前付きインスタンスの選択、レイアウトとシェイプでの使用、レンダリングと印刷など、完全なワークフローに使用できます。 特定の操作に GDI テキスト相互運用機能も使用するアプリの利点として、既存の GDI API にも同様のサポートが追加されています。
Windows 10 Creators Updateでは、DirectWriteでは、可変フォントの連続バリエーション機能を利用する任意のインスタンスはサポートされていません。
多くの操作では、変数フォントの名前付きインスタンスのDirectWriteでの動作は、非変数フォントの動作と区別できません。 また、既存のDirectWrite API を使用してサポートが提供されるため、変数フォントの名前付きインスタンスは、変更なしで多くの既存のDirectWrite アプリでも機能します。 ただし、特定の状況では例外が適用される場合があります。
- アプリが特定の操作に対してフォント データを直接処理する場合。 たとえば、アプリがフォント ファイルからグリフ アウトライン データを直接読み取り、特定の視覚効果を作成する場合です。
- アプリが特定の操作にサードパーティ製ライブラリを使用している場合。 たとえば、アプリがレイアウトにDirectWriteを使用して最終的なグリフのインデックスと位置を取得する場合、レンダリングにはサードパーティ製のライブラリを使用します。
- アプリがフォント データをドキュメントに埋め込む場合、または何らかの方法でフォント データをダウンストリーム プロセスに渡す場合。
変数フォントをサポートしていない実装を使用して操作を実行すると、これらの操作によって予期される結果が生成されない可能性があります。 たとえば、グリフの位置は、変数フォントの 1 つの名前付きインスタンスに対して計算される場合がありますが、グリフは別の名前付きインスタンスを想定してレンダリングされる場合があります。 アプリケーションの実装によっては、結果が一部のコンテキストで機能する場合がありますが、他のライブラリを使用できる他のコンテキストでは機能しない場合があります。 たとえば、テキストが画面に正しく表示される場合がありますが、印刷時には表示されません。 DirectWriteのみを使用してエンド ツー エンドのワークフローを実装する場合は、変数フォントの名前付きインスタンスの正しい動作が期待できます。
既存のDirectWrite API では、重み/ストレッチ/スタイル モデルを使用した顔の選択がサポートされているため、他のバリエーション軸を使用するフォントの名前付きインスタンスは、前述のように、一般的な文字体裁ファミリ モデルから WSS モデルに投影されます。 これは、軸値サブテーブルを持つ "スタイル属性" ('STAT') テーブルを含む可変フォントに依存します。DWrite は、重み、ストレッチ、またはスタイル属性を指定する顔名トークンを、バリエーションの他の軸に関連するトークンと区別するために使用します。
OpenType 仕様の可変フォントに必要な 'STAT' テーブルが変数フォントに含まれていない場合、DirectWriteは、既定のインスタンスのみを含む非変数フォントとしてフォントを処理します。
フォントに 'STAT' テーブルが含まれているが、適切な軸値サブテーブルが含まれていない場合、同じ顔名を持つ複数の顔があるなどの予期しない結果が発生する可能性があります。 現時点では、このようなフォントはサポートされていません。
OpenType 仕様では、グリフ アウトライン データを 2 つの形式のいずれかで表すことができます。TrueType アウトラインとヒント形式を使用する 'glyf' テーブルを使用するか、コンパクト フォント形式 ("CFF") 表現を使用する 'CFF' テーブルを使用します。 TrueType アウトラインを持つ変数フォントでは、'glyf' テーブルは引き続き使用され、アウトラインのバリエーション データを提供する 'gvar' テーブルで補完されます。 つまり、TrueType アウトラインを持つ変数フォントの既定のインスタンスでは、変数フォントがサポートされていない古いソフトウェアでサポートされる従来の OpenType テーブルのみが使用されます。 ただし、CFF アウトラインを含む変数フォントでは、'CFF' テーブルは 、既定のアウトライン データと関連付けられたバリエーション データを 1 つのテーブルにカプセル化する 'CFF2' テーブルに置き換えられます。 CFF データは、TrueType データに使用されるラスタライザーとは別のラスタライザーによって処理されます。'CFF2' テーブルには、'CFF2' をサポートする更新された CFF ラスタライザーが必要です。 'CFF2' テーブルは、古い CFF ラスタライザーでは処理できません。 CFF アウトライン データを含む可変フォントの場合は、既定のインスタンスでも古いソフトウェアでは機能しないことを意味します。
Windows 10 Creators Updateでは、DirectWriteでは、'CFF2' テーブルを使用した CFF アウトライン データを含む可変フォントはサポートされていません。
OpenType 変数フォントの使用
OpenType 変数フォントは、上記の現在の制限事項に留意して、使いやすい場合があります。
- 現時点では、変数フォントの名前付きインスタンスのみがサポートされています。
- 現時点では、TrueType グリフ アウトライン データ (CFF アウトラインではなく) を使用する可変フォントのみがサポートされています。
- 太さ、ストレッチ、スタイル以外のデザインバリエーションの軸を使用するフォントの場合、名前付きインスタンスは WSS ファミリ モデルに投影され、名前付きインスタンスの一部が個別のファミリとして表示される可能性があります (非変数フォントの場合と同様)。 これをサポートするには、変数フォントに、適切な軸値サブテーブルを含む 'STAT' テーブルが必要です。
- 変数フォントの名前付きインスタンスは、DirectWrite API でサポートされていますが、変数フォントをサポートしていない古い実装で特定の操作が実行されると、正しくない結果が生成される可能性があります。
- 特定のDirectWrite API では、顔を選択するときに重み、ストレッチ、スタイルの属性を指定するために、DWRITE_FONT_WEIGHT、DWRITE_FONT_STRETCH、およびDWRITE_FONT_STYLE列挙を使用します。 変数フォントで対応するバリエーション軸を使用しているが、細分性を必要とする名前付きインスタンスが多数ある場合、それらの API ではすべての名前付きインスタンスが選択できるわけではありません。
これらの要件に準拠する OpenType 変数フォントは、他の OpenType フォントと同様に Windows シェルからインストールでき、アプリによって作成されたカスタム フォント セットでも使用できます。
システムにインストールすると、IDWriteFontFamily3::GetSystemFontSet メソッドを呼び出すことによって返されるフォント セットに、変数フォントのすべての名前付きインスタンスが含まれます。 フォント セットはファミリ グループ階層のないフラット リストですが、セット内の各項目には WSS ファミリ モデルに基づくファミリ名プロパティがあることに注意してください。 IDWriteFontSet::GetMatchingFonts メソッドを使用して、特定の変数フォントの名前付きインスタンスに対してフォント セットをフィルター処理できます。 ただし、familyName を受け取る GetMatchingFonts オーバーロードを 使用する場合、指定された familyName は WSS フォント ファミリ モデルに準拠する名前を使用する必要があります。 フォント セットで発生する WSS 互換ファミリ名の完全な一覧は、DWRITE_FONT_PROPERTY_ID_FAMILY_NAMEを使用して IDWriteFontSet::GetPropertyValues メソッドを使用して取得できます。
同様に、変数フォントのすべての名前付きインスタンスは、IDWriteFactory::GetSystemFontCollection メソッドによって返されるフォント コレクションで表されます。 フォント コレクションの要素は WSS モデルに基づくフォント ファミリであるため、変数フォントの名前付きインスタンスは、コレクション内で 2 つ以上のフォント ファミリのメンバーとして表すことができます。 IDWriteFontCollection::FindFamilyName メソッドを使用する場合、familyName パラメーターは WSS 互換のファミリ名である必要があります。 フォント コレクションから WSS 互換のファミリ名をすべて検索するには、アプリで各ファミリをループ処理し、 IDWriteFontFamily::GetFamilyNames を呼び出すことができますが、対応するフォント セットを取得し、前述のように GetPropertyValues メソッドを使用する方が簡単な場合があります。
カスタム フォントを使用する場合は、「 カスタム フォント セット 」トピックで説明されているさまざまな方法を使用して、フォント セットを作成できます。 カスタム フォント セットに変数フォントを追加するには、 IDWriteFontSetBuilder1::AddFontFile メソッドが推奨されます。これは、変数フォントをサポートし、変数フォントのすべての名前付きインスタンスを 1 回の呼び出しで追加するためです。 現時点では、 IDWriteFontSetBuilder::AddFontFaceReference メソッドを使用してカスタム変数フォントの個々の名前付きインスタンスをフォント セットに追加する方法はありません。これは、変数フォント ファイルから名前付きインスタンスのどれを指定するフォントフェイス参照を作成する方法がないためです。 つまり、現在、カスタム プロパティが割り当てられたカスタム フォント セットにカスタム フォントの名前付きインスタンスを追加する方法はありません。 つまり、カスタム変数フォントは現在、リモート フォント用の DirectWrite API と組み合わせて簡単に使用することはできません。 ただし、変数フォントの名前付きインスタンスがシステム フォント セットに含まれている場合、各名前付きインスタンスのフォント顔参照は既に存在し、カスタム プロパティ値の使用を含め、カスタム フォント セットに追加できます。 詳細については、「カスタム フォント セット」トピックを参照してください。
可変フォントを使用する場合、DirectWrite DWRITE_FONT_WEIGHTとDWRITE_FONT_STRETCH列挙体は、OpenType 仕様で定義されている太さと幅のバリエーション軸に密接に接続されますが、同じではありません。 最初に、任意のバリエーション軸の数値スケールでは常に小数部の値がサポートされますが、fontWeight と fontStretch では整数が使用されます。 OpenType 太さ軸スケールでは、fontWeight でもサポートされている 1 ~ 1000 の範囲の値が使用されます。 したがって、バリエーションの太さ軸の値から fontWeight への変更は比較的軽微です。名前付きインスタンスに対して報告される fontWeight は、フォント内で名前付きインスタンスを定義するために使用される正確な値から丸められます。 DirectWrite fontStretch と OpenType の幅軸スケールの違いは大きくなります。DirectWriteは、OpenType OS/2 テーブルの usWidthClass 値に続く 1 から 9 の値を使用し、OpenType 幅軸のスケールでは、通常の幅の割合を表す正の値を使用します。 OpenType 仕様の usWidthClass ドキュメントでは、値 1 から 9 と標準のパーセント値の間のマッピングが提供されています。 名前付きインスタンスに対して報告される fontStretch 値は、幅軸の値から変換するときに丸め処理を伴う場合があります。
IDWriteTextFormat を作成するときは、フォント コレクションと WSS 互換のフォント プロパティ (ファミリ名、重み、ストレッチ、スタイル) を指定する必要があります。 これは、 IDWriteTextLayout テキスト範囲にフォント書式プロパティを設定する場合にも適用されます。 プロパティは、 IDWriteFontFace3 オブジェクト、または特定の名前付きインスタンスを表す IDWriteFont オブジェクトと IDWriteFontFamily オブジェクトから取得できます。 前述のように、GetWeight メソッドと GetStretch メソッドによって返される値は、名前付きインスタンスの定義に使用される実際の軸の値の丸められた近似値になる場合がありますが、DirectWriteはプロパティの組み合わせを目的の名前付きインスタンスにマップし直します。
同様に、アプリで IDWriteFontFallbackBuilder を 使用してカスタム フォント フォールバック データを作成する場合、WSS 互換ファミリ名を使用して文字範囲マッピングにファミリが指定されます。 DirectWrite内のフォント フォールバックは、フォールバック ファミリ内のバリアントを選択DirectWrite、開始ファミリのバリアントに最も近いバリアントを選択するファミリに基づいています。 重み、ストレッチ、スタイル以外のディメンションを含むバリアントの場合、DirectWrite現在、"Caption" 光学式サイズバリアントなど、特定の WSS 以外の属性を持つファミリにフォールバック マッピングを提供するためにカスタム フォールバック データが作成されていない限り、フォールバック ファミリ内でそのようなバリアントを選択することはできません。