C#で文字のアウトラインを取得する方法

このブログはいろいろな話題がごちゃ混ぜ&超絶ニッチな話題ですがご愛嬌・・・。

C#でフォントのアウトラインをとる方法、ウェブ上にあまり情報がないのでまとめておきます。

DLL Importして作らなければいけないかしら、めんどうくさいなあと書いてみました。こういう時、サンプルが豊富なpinvoke.netのページが参考になります。

が!.NET Framework 3.0からは「GlyphTypeface.GetGlyphOutline」なるメソッドがあるじゃないですか。このメソッドを使うと、2バイト文字の扱いで、うがーとなる箇所も、かなりすっきり書けます。ネット上には昔の情報が多くてなかなかGetGlyphOutlineにたどり着けなかった・・・(^^;

こんな感じでどうぞ!というpseudo codeを貼っておきます。

System.Windows.Media.GlyphTypeface gt = new System.Windows.Media.GlyphTypeface( new Uri( @"C:\Windows\Fonts\msmincho.ttc"));
char ch = 'あ';
ushort glyphIndex;
gt.CharacterToGlyphMap.TryGetValue((int)ch, out glyphIndex);

// アウトラインがほしい文字のインデックス、縦横の大きさを指定して、形状をもらう
Geometry geom = gt.GetGlyphOutline(glyphIndex, 12d, 12d); 

// アウトラインのもとになるpath geometryを取り出す
PathGeometry pg = geom.GetOutlinedPathGeometry();

// figures の中に閉じたパスの figure がいっぱい入っているので、ひとつずつ処理する(「い」の左の縦棒と右の縦棒を順次処理する感じ)
foreach (PathFigure pf in pg.Figures)
{
       // figure の最初の点
       System.Windows.Point prev = pf.StartPoint;

       // figure は「LineSegment」「PolyLineSegment」「BezierSegment」「PolyBezierSegment」の集まりとしてできているから、これまたひとつずつ処理する
       foreach (PathSegment ps in pf.Segments)
       {
              String pathType = ps.GetType().Name;
              
              // よい書き方じゃなさそうな気がしますが、ご愛嬌(^^;  
              if (pathType.Equals("PolyBezierSegment"))
              {・・・ // 点の情報を格納したり、線を引いたり、好きな処理をどうぞ!}
       else if (pathType.Equals("LineSegment"))
              {・・・}
              else
              {//}
       }
}

省略してある部分ですが、ラインセグメントは始点と終点が簡単に取れます。ベジェ曲線で表されるセグメントの時は、端点と制御点をもとに、ストロークが通過する点を計算してあげればOK。それぞれのクラスに応じて、通過する点を計算するのに必要な情報を取得するためのメソッドが用意されています。ベジェ曲線については以下のページn説明がとてもわかりやすいです。

で、できました。OKO、満足満足。

漢字のアウトラインをとってみたよ