Jefimは彼自身の質問に正しく答えましたが、この特定の機能セットを使用したときにこの動作が発生する理由を説明したいと思います。Jefimは、これはWPFのバグであると示唆していますが、そうではありません。この問題は、WPFに不可能なことを実行するように要求した結果として発生します。あなたがこの不可能なことを求めたとき、それは妥協点を選ばなければなりません、そして結果はあなたが上に見たものです。
コメントには説明が少し長いので、別の答えに入れています。
この例では、WPFの2つの相互に矛盾する機能を使用しています。それらの機能は次のとおりです。
- あらゆるスケールで一貫してビジュアルをレンダリングする機能
- GDI32がテキストをレンダリングするのと同じ方法でテキストをレンダリングする機能
両方の機能を同時に使用することはできません。GDI32は、一貫して拡大縮小できない方法でテキストをレンダリングします。特定のフォントサイズの特定のテキストがたまたま200ピクセル幅である場合、フォントサイズに3を掛けて、同じフォントファミリで同じテキストをレンダリングする場合その新しいフォントサイズ、GDI32ではおそらく600ピクセルではないでしょう-それは近くなりますが、通常は完全に正しくありません。
GDI32は、テキストの明瞭さと鮮明さを高めるために、文字の形と幅をいじります。具体的には、文字を形から曲げて、文字の特徴が画面上のピクセルとよりよく一致するようにします。また、必要に応じて、個々の文字の幅を正確なピクセル数に調整します。この文字の曲げはすべて実際のピクセルに基づいているため、さまざまなフォントサイズでさまざまな方法でテキストを曲げます。
それはあなたに素敵なシャープなテキストを与えますが、あなたが徐々にスケールを変えようとするとそれは絶対に恐ろしいように見えます。この方法でレンダリングされたテキストのフォントサイズをアニメーション化しようとすると、明快さの名の下に行われた調整がフォントサイズごとにわずかに異なるため、物事はきらめき、震えているように見えます。アニメーション化していない場合でも、結果が悪くなる可能性があります。単一の書体が複数のサイズで表示されている場合、サイズごとにかなり異なって見える可能性があります。アプリケーションにズーム機能がある場合、ズームインおよびズームアウトすると、テキストの文字が大幅に変化するように見えることがあります。(レイアウトも同様です。MicrosoftWordを使用している場合、特定の単語の間に奇妙に見える非常に広いスペースが表示されることがあることに気付いたかもしれません。
そのため、WPFは、テキストレンダリングに対して異なるアプローチを提供します。つまり、フォントの元のデザインに可能な限り忠実な方法でテキストをレンダリングできます。これにより、テキストの歪みが少なくなり、拡大縮小しても不連続性が発生しなくなります。
欠点は、GDI32によってレンダリングされたテキストがどのように見えるかと比較して、テキストがぼやけて見えることです。(GDI32によって作成された歪みはすべて、明瞭さを向上させることを目的としています。)
そのため、WPF 4.0では、MicrosoftはGDI32と同じようにテキストをレンダリングする機能を追加しました。それが何をするかTextOptions.TextFormattingMode="Display"
です。
このオプションをオンにすると、「一貫したスケーリングは必要ありません。明瞭さが望ましいので、GDI32で実行したのと同じピクセルを生成します」と言います。次に、スケーラビリティを必要としないことをWPFに伝えて、スケーリングを適用し続けると、ひどい結果が得られます。WPFは、仕様に正確に一致するテキストのビットマップ表現を慎重に生成し、そのテキストを別の縮尺でレンダリングするように指示しました。そして、それはそれが何であるかのように見えます:異なる解像度のために生成されたいくつかのテキストのスケーリングされたビットマップ。
ここでは、WPFが別のことを行う可能性があると主張できます。GDI32でスケール変換を適用すると、さまざまな動作が見られます。前述のさまざまなスケールで不整合が見られます。WPFでその効果が本当に必要な場合は、フォントサイズを直接変更することで効果を得ることができます。ただし、WPFは同じ効果を優先しません。その目標は、本当に必要なときにGDI32スタイルの鮮明なテキストを取得できるようにし、デフォルトで一貫したスケーリングを提供することです。
そして、ここで遭遇しているのは「一貫したスケーリング」です。GDI32スタイルのテキストレンダリングをオンにしても、一貫したスケーリングが損なわれることはありません。スケール係数を適用すると(直接、を介して、ScaleTransform
または間接的にを介してViewbox
)、指定されたスケール係数でビジュアルのサイズが変更されます。新しく拡大縮小されたサイズにグリッドフィッティングしてテキストビジュアルを再生成すると、テキストは異なる幅で出力されます。それは実際にViewbox
問題を引き起こします:それはコンテンツの自然なサイズに基づいて、利用可能なスペースに合うように設計されたスケールファクターを適用します。ただし、スケーリング後にグリッドフィットを再実行すると、実際には幅が変更されます。GDI32テキストレンダリングの動作に固有の不整合のため、ViewBox
適切な縮尺を見つけるために-特定のフォントでレンダリングされたときに、幅が200ピクセルになることのないテキストを思い付くことができます。一部のフォントサイズでは、グリッドフィッティングに固有の丸めにより、サイズがたとえば198に下がる場合があります。フォントサイズを少しずつ増やすと、しきい値を超えるとジャンプする可能性があります。 202ピクセルまで。
Viewbox
テキストを強制的に200ピクセルに収めようとすると、それが問題になります。ただしViewbox
、そのようには機能しません。GDI32スタイルのテキストレンダリングが機能するフォントサイズを選択したポイントの下流で、WPFの一貫したスケーリングが使用されます。したがってViewbox
、設計されたとおりに常に実行できますが、それはGDI32スタイルのテキストレンダリングとは根本的に互換性のないタスクです。
つまり、WPFは、要求したフォントサイズのテキストをレンダリングしてから、結果をスケーリングします。
したがって、1つの機能だけを選択する必要があります。それは単純に不可能であるため、両方を選択することはできません。任意のスケール係数が適用される可能性のあるコンテキスト(たとえばViewbox
)でテキストをレンダリングしようとしないか、GDI32スタイルのテキストレンダリングをオンにしないでください。そうしないと、遭遇した奇妙なピクセル化されたテキストが表示されます。