0

さて、私はしばらくの間何かに取り組んでいて、テキスト レンダリングの部分を計画するところまで来ました。

テキストの文字列を 2 つの方法で描画できます。DrawString と TextRenderer.DrawText。TextRenderer.Measure text を使用すると、テキストの測定がより正確になるため、DrawText を好みます。

私はクラスを持っています:

public class Character 
{
public string character {get; set; } 
public Font font {get; set; }
public Point position {get; set; }
} 

そして、押されたすべての文字のリスト:

public List<Character> chars = new List<Character>();

今私の問題は、実行時に、選択した特定の文字または単語に別のフォントと色、太字または斜体を設定できる必要があることです。そのため、文字列全体を描画することはできません。ユーザーが変更するために選択した各文字に個別のフォント設定を設定する方法がないためです。

したがって、文字ごとに異なるフォントスタイル情報を保存し、それらをすべてリストに追加して、それぞれを調べて、描画する必要があるように描画できるようにする必要があります(つまり、各文字には独自のスタイルがあります) .

このソリューションは私にとってはうまくいきます。そして、これに関する情報を何ヶ月もどこにも見つけることができなかったので、完全に立ち往生しています.

私の主な問題は、文字ごとに描画しているため、各文字が以前に描画された文字 (カーニング) からどれだけ離れているべきかがわからないことです。

入力 (テキスト ボックス) コントロールの場合、テキストをカスタム描画し、ユーザーが単語の一部を青色にし、単語の残りの半分を別のサイズ、色、スタイルにすることができるようにするにはどうすればよいでしょうか。カーニング設定?

各キャラクターをどこに描くべきかをどうやって知るのですか?

人々は、文字列全体を一度に再起動し続けると言っています。しかし、それは私の最初の問題を解決しません。フォント情報を保存できるように、各文字を 1 つずつ描画できるようにする必要があります。

4

1 に答える 1

2

カーニング文字間隔は異なります。コードの印刷内容を完全に制御したい場合は、両方を実装する必要があります。

最初に出力例を見てみましょう:

画像 1は、カーニングなしで 1 ピクセルの文字間隔を追加した直接出力を示しています。 ここに画像の説明を入力

画像 2にはカーニングが適用されていますが、カーニング ペアは 3 つだけです。 ここに画像の説明を入力

文字ごとのテキスト測定の結果も描画することで、物事をより明確にしようとしました。また、パネルの BackgroundImage としてタイル化された 1 ピクセルのラスターがあります。(png ファイルをダウンロードすると見やすくなります!)

private void panel2_Paint(object sender, PaintEventArgs e)
{
   string fullText = "Text;1/2' LTA";
   StringFormat strgfmt = StringFormat.GenericTypographic;
   Font font = new Font("Times", 60f, FontStyle.Regular);
   float x = 0f;
   using (SolidBrush brush = new SolidBrush(Color.FromArgb(127, 0, 127, 127)))
   {
        for (int i = 0; i < fullText.Length; i++)
        {
            string text = fullText.Substring(i, 1);
            SizeF sf = e.Graphics.MeasureString(text, font, 9999, strgfmt );
            e.Graphics.FillRectangle(brush, new RectangleF(new PointF(x, 0f), sf));
            e.Graphics.DrawString(text, font, Brushes.Black, x, 0, strgfmt );
            x += sf.Width + 1;  // character spacing = +1

            //if (i < fullText.Length - 1) doKerning(fullText.Substring(i, 2), ref x);
        }
   }
}

void doKerning(string c12, ref float x)
{
    if (smallKerningTable.ContainsKey(c12)) x -= smallKerningTable[c12];
}

Dictionary<string, float> smallKerningTable = new Dictionary<string, float>();

void initKerningTable()
{
    smallKerningTable.Add("Te", 7f);
    smallKerningTable.Add("LT", 8f);
    smallKerningTable.Add("TA", 11f);
    //..
}

背景の作成方法は次のとおりです。

public Form1()
{
   InitializeComponent(); 
   Bitmap bmpCheck2 = new Bitmap(2, 2);   
   bmpCheck2.SetPixel(0, 0, Color.FromArgb(127, 127, 127, 0));
   panel2.BackgroundImage = bmpCheck2;
   panel2.BackgroundImageLayout = ImageLayout.Tile;
   //..
 }

カーニングを使用する場合は、より長いカーニング テーブルを作成する必要があります。

実際のタイポグラファーやフォント デザイナーは、手作業でグリフをよく見て、見栄えがよくなるまでカーニングを微調整しています。

これはかなり高価であり、それでもフォントの混合には対応していません。

だからあなたはどちらかをしたいかもしれません

  • 結局、カーニングを使用しないでください。弦の測定と描画の両方にオプションを使用してください。 StringFormat.GenericTypographic
  • 「L」、「T」、「W」、「V」、「A」など、特に問題のある文字の一部については、小さなカーニング テーブルを作成します。
  • 必要なすべてのペアの完全なカーニング テーブルを作成するコードを作成するか、..
  • すべてのペアに

カーニング テーブルを作成するコードを記述するには、次のようにします。

  • キャラクターごとにビットマップを作成する
  • すべてのペアを反復し、
  • 非透明/黒のピクセルが衝突するまで、2 番目のビットマップを左に移動します。
  • 移動は、たとえば幅の半分を超えてはなりません。それ以外の場合は、距離を 0 にリセットする必要があります。これは、一部の文字ペアがまったく衝突せず、カーニングが必要ないためです。たとえば、'^_' や '.- '

フォントや FontStyle を混在させたい場合は、カーニング テーブルのキーを拡張して、文字が持つ 2 つのそれぞれのフォントとスタイルの ID を含める必要があります。

于 2015-03-13T16:12:22.520 に答える