2010/02/18

[C#]文字のアウトラインを描く

このエントリーをはてなブックマークに追加

文字のパス情報を取得する


GraphicsPathクラスにあるAddStringメソッドを使います。
AddStringメソッドを使うと、指定の文字のパスを、GraphicsPathに追加することができます。

// using System.Drawing;
string str = "Hello World!";

Graphics g = this.CreateGraphics();
g.SmoothingMode = SmoothingMode.HighQuality;

PointF point = new PointF(5.0f, 15.0f); // 文字を描画する原点(左上)
StringFormat format = new StringFormat();

GraphicsPath path = new GraphicsPath();
path.AddString(str, new FontFamily("Arial Black"), (int)FontStyle.Regular, 36.0f, point, format);

g.DrawPath(Pens.OrangeRed, path);

g.Dispose();


上記コードの実行結果です。「Hello world!」の文字列のアウトラインを描いたもの。

GraphicsPathクラスには、Graphicsクラスの描画メソッドと類似のメソッドがたくさん用意されています。
矩形を追加したり、円をパス化したり、大体のメソッドは、引数も同じで使用するのに違和感はないのです。
なのにAddStringだけ、GraphicsのDrawStringとは引数の仕様が異なっているようです。
  • 文字のサイズ指定の方法が異なっている。
  • 書体の指定がフォントファミリになっている。
  • FontStyleの指定をintegerにしないといけない。

厄介なのは文字サイズ。文字サイズというより文字の高さを指定してあげるという方式らしいので、フォントのSizeプロパティをGraphicsPath.AddStringに指定すると、Graphics.DrawStringで単に文字を描画するのよりも文字が小さく出力されます。

→補足エントリを書きました。2016/04/05
[C#]Graphics.DrawStringとGraphicsPath.AddStringのサイズを合わせる
http://devlabo.blogspot.jp/2016/04/fittingdraw.html

フチ文字を描く


フチ文字を作るには、アウトライン文字に、通常の塗りつぶし文字を重ねてあげます。
パスを作って線を太らせただけだと字形がつぶれてしまうので、上から白文字で抜いてあげます。

// using System.Drawing;
string str = "Hallo World!";

Graphics g = this.CreateGraphics();
g.SmoothingMode = SmoothingMode.HighQuality;

PointF point = new PointF(5.0f, 15.0f); // 文字を描画する原点(左上)
StringFormat format = new StringFormat();

GraphicsPath path = new GraphicsPath();
path.AddString(str, new FontFamily("Arial Black"), (int)FontStyle.Regular, 36.0f, point, format);

g.DrawPath(Pens.OrangeRed, path);

g.Dispose();

実行結果。


4.0ptの線は、中心から外に2.0pt、内に2.0ptに広がっています。
内に広がっている2.0ptを塗りつぶしたことになるので、フチ文字は2.0ptの太さ。
下記は、白で塗りつぶす前の線を太らせただけの文字。字形がつぶれてしまいます。

2 件のコメント :

  1. emSizeの指定がDrawStringやMeasureStringと違うのが厄介なのですが
    以下の方法でDrawStringのサイズと一致してくれました

    float emSize = font.Height * font.FontFamily.GetCellAscent(font.Style) / font.FontFamily.GetEmHeight(font.Style);
    GraphicsPath path = new GraphicsPath();
    path.AddString(Text, font.FontFamily, (int)font.Style, emSize, pos, stringFormat);

    返信削除
    返信
    1. コメントありがとうございます。
      環境によるのかフォントによるのか、ご指摘のコードではうまくいかず…。
      深みにはまりながら調べてみたところ、どうもfont.HeightはGetLineSpacingに対応するようで、

      float emSize = (float)font.Height * font.FontFamily.GetEmHeight(font.Style) / font.FontFamily.GetLineSpacing(font.Style);

      でぴったりに収まってくれました。

      削除