OpenType 変数フォント
このトピックでは、OpenType 変数フォント、DirectWrite および Direct2D でのサポート、アプリでの使用方法について説明します。
- OpenType 変数フォントとは
- DirectWrite での OpenType 変数フォントのサポートの
- OpenType 変数フォントを使用する
OpenType 変数フォントとは
OpenType フォント形式仕様のバージョン 1.8、OpenType Font Variationsと呼ばれる形式に新しい拡張機能が導入されました。 これらの拡張機能を使用するフォントは、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 ファミリ モデルでは、ファミリ内の光学サイズバリアントを使用できないため、光学サイズの区別はファミリ レベルの区別のように扱う必要があります。 次の表は、Sitka 文字体裁ファミリのフォントの選択が WSS ファミリ モデルでどのように扱われるかを示しています。
文字体裁ファミリ モデル
WSS ファミリ モデル
家族
顔
家族
顔
シトカ
標準テキスト
Sitka テキスト
レギュラー
シトカ
バナー太字
Sitka バナー
ボールド
シトカ
キャプション斜体
Sitka Caption
イタリック
文字体裁ファミリ モデルから 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 モデルに投影されます。 これは、軸値サブテーブルを含む "style attributes" ('STAT') テーブルを含む可変フォントに依存します。DWrite は、重み、ストレッチ、またはスタイル属性を指定する顔名トークンを、バリエーションの他の軸に関連するトークンと区別するために使用します。
OpenType 仕様の変数フォントに必要な変数フォントに 'STAT' テーブルが含まれていない場合、DirectWrite は既定のインスタンスのみを含む非変数フォントとしてフォントを扱います。
フォントに 'STAT' テーブルが含まれているのに、適切な軸値サブテーブルが含まれていない場合、同じ顔名を持つ複数の顔があるなどの予期しない結果が発生する可能性があります。 現時点では、このようなフォントはサポートされていません。
OpenType 仕様では、グリフ アウトライン データを、TrueType アウトライン形式とヒント形式を使用する 'glyf' テーブルを使用するか、コンパクト フォント形式 ("CFF" ) 表現を使用する 'CFF' テーブルを使用する 2 つの形式のいずれかで表すことができます。 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 メソッドを使用して、特定の変数フォント名付きインスタンスに対してフォント セットをフィルター処理できます。 ただし、GetMatchingFonts familyName を受け取るオーバーロードを使用する場合、指定された 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 の重み軸のスケールでは、1 ~ 1000 の範囲の値が使用されます。これは fontWeight でもサポートされています。 したがって、バリエーションの重み軸の値から fontWeight への変更は比較的軽微です。名前付きインスタンスに対して報告される fontWeight は、フォント内で名前付きインスタンスを定義するために使用される正確な値から丸められる場合があります。 DirectWrite fontStretch と OpenType の幅軸スケールの違いは大きくなります。DirectWrite では、OpenType OS/2 テーブルの usWidthClass 値に続く 1 から 9 の値が使用され、OpenType の幅軸のスケールでは、通常の幅の割合を表す正の値が使用されます。 OpenType 仕様の usWidthClass ドキュメントでは、値 1 から 9 と標準のパーセント値の間のマッピングが提供されています。 名前付きインスタンスに対して報告される fontStretch 値は、幅軸の値から変換するときに丸めを伴う場合があります。
IDWriteTextFormatを作成するときは、フォント コレクションと WSS 互換のフォント プロパティ (ファミリ名、重み、ストレッチ、スタイル) を指定する必要があります。 これは、IDWriteTextLayout テキスト範囲にフォントの書式設定プロパティを設定する場合にも適用されます。 プロパティは、IDWriteFontFace3 オブジェクトから、または特定の名前付きインスタンス を表す IDWriteFontFamily および IDWriteFontFamily オブジェクトから取得できます。 前述のように、GetWeight メソッドと GetStretch メソッドによって返される値は、名前付きインスタンスの定義に使用される実際の軸値の丸められた近似値になる場合がありますが、DirectWrite はプロパティの組み合わせを目的の名前付きインスタンスにマップします。
同様に、アプリ IDWriteFontFallbackBuilder を使用してカスタム フォント フォールバック データを作成する場合、WSS 互換のファミリ名を使用して文字範囲マッピングにファミリが指定されます。 DirectWrite 内のフォント フォールバックは、DirectWrite がフォールバック ファミリ内のバリアントを選択するファミリに基づいており、これは開始ファミリのバリアントに最も近い一致です。 重み、ストレッチ、スタイル以外のディメンションを含むバリアントの場合、DirectWrite は現在、カスタム フォールバック データを作成して、特定の WSS 以外の属性 ("Caption" 光学サイズバリアントなど) を持つファミリにフォールバック マッピングを提供しない限り、フォールバック ファミリ内でそのようなバリアントを選択することはできません。