3

必要がある:

  1. テキストを正確に測定します。
  2. グラフィックス コンテキストに適用される変換とスケーリングの変換が存在する場合に、テキストを 1 行ずつ画面のグラフィックス コンテキストにレンダリングします。
  3. ヒット テスト: マウスまたは表示されたキャレットを使用してテキストを正確に選択できるようにします。
  4. 必要に応じて、プリンターでできるだけ正確に結果を印刷します。注:これは二次的なものです。画面のレンダリングとヒット テストが主です。
  5. Windows XP 以降のオペレーティング システムで実行します。

グラフィックスと画像を同じグラフィックス コンテキストにレンダリングする WinForms アプリケーション内。

私たちが遭遇した4つのテクノロジーがあります。最初の 2 つを使用してみましたが、数か月にわたって説明されている問題に遭遇しました。

GDI+

解像度に依存しないとされるテキスト。ただし、この質問(およびその他の情報源) によると、この技術は品質の問題があるため避けるべきです。

MSDNは、Graphics.MeasureString を呼び出して 、正確な文字列測定値StringFormat.GenericTypographicを生成すると述べています。TextRenderingHint.AntiAliasしかし、私たちの経験と他の人の経験では、これは当てはまりません。正確な弦の測定値は得られません。

  • 長所:速い
  • 短所:弦の測定が不正確。

結果: 弦の測定が不正確なため使用できません。

TextRenderer 経由の GDI

これは、GDI+ の制限を克服するために導入されました。ただし、これには独自の制限が導入されました。

  • 非常に遅い
  • グラフィック変換では機能しませ

結果: これらの理由により使用不可

p/invoke 経由の GDI

GetTextExtentExPointテキストの測定とDrawText/ DrawTextEx/ExtTextOutレンダリングの呼び出し。

これはまだ試していません。

ダイレクトライト

これは、GDI/GDI+ を含む他のテクノロジと相互運用できるため、有望に思えます。おそらく、グラフィックス レンダリングの残りの部分は変更されないでしょう。ただし、Windows Vista 以降の Windows バージョンでのみ使用できます。Windows XP には依然としてかなりのインストール ベースがあるため、これは現在問題になっています。

質問

要件を考慮して、これらのテクノロジのうちどれを機能させることができますか?

注: このトピックについては多くの誤った情報が飛び交っているため、この分野の専門知識がある場合にのみ、この質問に回答してください。また、WPF を提案しないでください。これは、使用を検討しているものではありません。

4

3 に答える 3

4

おそらく、MeasureCharacterRanges関数はより正確ですMeasureString

于 2012-05-25T00:31:52.780 に答える
3

同様の要件があり、テキストのレンダリングとスケーリングで同じ問題に遭遇しました。WPF (.NET 3.5) での私の試みでさえ、多くの理由で悪夢でした。

graphics.DrawString「非推奨」であるにもかかわらず、正確なテキスト測定値を取得するための面白いトリックを使用して、 GDI+ を使用することになりました。

static public RectangleF MeasureInkBox(Graphics graphics, string text, Font font)
{
    var bounds = new RectangleF();
    using (var textPath = new GraphicsPath())
    {
        textPath.AddString(
            text,
            font.FontFamily,
            (int)font.Style,
            font.Size,
            new PointF(0, 0),
            StringFormat.GenericTypographic );
        bounds = textPath.GetBounds();
    }
    return bounds;
}

スピードもクオリティも満足のいくものになりました。また、graphics.DrawStringwinforms でテキストを印刷するための推奨される方法です。

カーニングのために個々の文字位置を測定するのは難しい場合がありますが、この方法のもう少し複雑なバージョンでうまくいくと思います。たとえば、"Hello" の場合、"H"、次に "He"、次に Hel" などのように測定されます。特に、単語のクリックを受け取ったときにフライで実行する場合は、パフォーマンスが大幅に低下することはありません。

于 2012-06-29T04:02:31.497 に答える
3

画面とプリンターの両方をターゲットにする必要がある場合は、使用するレンダリング エンジンを決定する前に、アプローチについていくつか決定する必要があります。以下にいくつかの可能性を示します。

  1. 画面単位でレイアウトし、プリンターに最適な近似を行います。
  2. プリンタ単位でレイアウトし、画面を可能な限り近似します。
  3. 理論上の高解像度空間にレイアウトし、プリンターとスクリーンの両方について可能な限り最善の近似を行います。

いずれの場合も、各ステップで非常に慎重に近似を行うことで、可能な限り最良の近似を行うことができます。これにより、マッチングの精度を犠牲にして各デバイスに最高の忠実度を与えることができます。または、ビットマップにレンダリングしてデバイスに合わせてスケーリングすることもできます。忠実度は低くなりますが、他の空間への可能な限り最良の近似が得られます。

GDI を使用してハードコアな印刷プレビューを実行しました。難しいですが、通常のレイアウトでは可能です。しかし、任意の変換、特に +/-90 度以外の回転を処理している場合、それはほぼ不可能です。

微妙な間違いを犯して、返された測定値が間違っていると思い込んでしまうのは非常に簡単です。

  • フォント ヒンティングは、ストローク幅が dpi と同じ桁数である場合、フォント スケーリングを非線形にするため、wテキストの幅を取得した場合、フォントのサイズを 2 倍にした場合の幅は正確に2*w.

  • フォントの置換は、多くのプリンター ドライバーで一般的です。TrueType または OpenType フォントを選択しても、画面に表示されたものと同じフォントがプリンターに表示されない場合があります

  • 一部のプリンターでは、正方形以外のピクセルが一般的です。これらは、軸が揃っていないことをしているときに、まともなラスタライザーでさえ台無しにする可能性があります。

  • カーニングは驚くべきものです。width('a') + width('b') == width("ab") と仮定しないでください。

  • 丸め誤差は簡単に発生します。基礎となるラスタライザーで使用される丸め規則を知っておく必要がある場合があります。

  • 間違った文脈で測定することはあまりにも一般的です。画面のコンテキストで測定して、変換を適用してプリンターの単位を取得しようとしないでください。プリンター単位が必要な場合は、プリンター コンテキストで測定します。

私は今日、印刷プレビューだけが必要な場合は、ページに合わせたサイズのビットマップにプリンター単位でレイアウトし、DPI の比率に基づいてビットマップを画面に合わせてスケーリングする必要があると考えています。それが最も簡単で、良い結果が得られます。しかし、優れたハードコピーと印刷プレビューが本当に求めているものかどうかは明らかではありません。

于 2012-05-25T00:16:14.643 に答える