文字の見栄えを良くしたいときや、背景の画面と文字の色が近い場合には、 縁取り文字を使うとよい[1]。
下に、プログラム例とその実行結果を示す。
using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; class Halo : Form { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Halo(); form.Text = "Halo Test"; // フォームのタイトル Application.Run(form); } protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; using (Image img = Image.FromFile("c:/gisdata/tiles/osmx/12/3638/1612.png")) { g.DrawImage(img, 4, 4, 256, 256); } //アンチエリアス SmoothingMode initialMode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.HighQuality; //レンダリング品質 CompositingQuality initialQuality = g.CompositingQuality; g.CompositingQuality = CompositingQuality.HighQuality; GraphicsPath gp = new GraphicsPath(); gp.AddString("ふちどりテスト", new FontFamily("MS Gothic"), (int)FontStyle.Regular, 16.0F, new Point(10,10), StringFormat.GenericDefault); gp.AddString("東京都", new FontFamily("Meiryo UI"), (int)FontStyle.Regular, 14.0F, new Point(100,100), StringFormat.GenericDefault); //パスの線分を描画 Pen drawPen = new Pen(Color.White, 1.0F); g.DrawPath(drawPen, gp); //塗る Brush fillBrush = new SolidBrush(Color.Purple); g.FillPath(fillBrush, gp); drawPen.Dispose(); fillBrush.Dispose(); //念のため元に戻しておきます g.SmoothingMode = initialMode; g.CompositingQuality = initialQuality; } }
地図システムで使うため、再実験をした。
Mapnikで生成したタイル地図(左図)に "兵庫県三木市"を3行上書きした。
前節の方法でこの例の大きさの文字を描画すると、なぜか、色が薄くなる。 そのため、縁取りは上の方法で行い、文字描画は普通に行ってみた(右図)。
下から二番目の文字は縁取りなしで普通に描画したものである。 一番上と一番下は縁取りした。
縁取りの線の太さは 3.0 としている。 縁取りのフォントサイズは 上が11.0、下が 10.0 で、文字のフォントサイズは 上が 8.0、下が 7.5 である。
縁取りのフォントサイズは「文字のフォントサイズ+縁取り線の太さ」が目安となる。
このような方法を採れば、小さい文字でも、Mapnikに比べて、 それほど見劣りしない文字が描画できそうである。
using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; class Halo : Form { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Halo(); form.Text = "Halo Test"; // フォームのタイトル Application.Run(form); } protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; using (Image img = Image.FromFile("c:/gis/896_406.png")) { g.DrawImage(img, 4, 4, 256, 256); } //アンチエリアス SmoothingMode initialMode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.HighQuality; //レンダリング品質 CompositingQuality initialQuality = g.CompositingQuality; g.CompositingQuality = CompositingQuality.HighQuality; GraphicsPath gp = new GraphicsPath(); gp.AddString("兵庫県三木市", new FontFamily("Meiryo UI"), (int)FontStyle.Regular, 11.0F, new Point(6,10), StringFormat.GenericDefault); gp.AddString("兵庫県三木市", new FontFamily("Meiryo UI"), (int)FontStyle.Regular, 10.0F, new Point(6,60), StringFormat.GenericDefault); //パスの線分を描画 Pen drawPen = new Pen(Color.White, 3.0F); g.DrawPath(drawPen, gp); //塗る Brush fillBrush = new SolidBrush(Color.Black); Font font = new Font("Meiryo UI", 8.0f, FontStyle.Regular); g.DrawString("兵庫県三木市", font, fillBrush, 7, 10); g.DrawString("兵庫県三木市", font, fillBrush, 7, 40); g.DrawString("兵庫県三木市", new Font("Meiryo UI", 7.5f, FontStyle.Regular), fillBrush, 7, 60); drawPen.Dispose(); fillBrush.Dispose(); //念のため元に戻す g.SmoothingMode = initialMode; g.CompositingQuality = initialQuality; }
縁取りの太さを halo としたとき、文字の描画位置を x, y とすると、縁取り位置は x-halo, y-halo とすべきであろう。 線分の太さは halo か halo*2 のどちらだろう。 大きなフォントサイズで試行錯誤で適切な値を探るのがいい。
試行錯誤の末、現在(2019.6)は次のようにしている。
SmoothingMode initialMode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.HighQuality; // アンチエリアス CompositingQuality initialQuality = g.CompositingQuality; g.CompositingQuality = CompositingQuality.HighQuality; // レンダリング品質 GraphicsPath gp = new GraphicsPath(); gp.AddString(name, new FontFamily("Meiryo UI"), (int)FontStyle.Regular, (float)(fsize*96/72), new Point(rc.X, rc.Y), StringFormat.GenericDefault); Pen drawPen = new Pen(Color.FromArgb(160,255,255,255), (float)(halo*2)); g.DrawPath(drawPen, gp); // パスの線分を描画 drawPen = new Pen(Color.FromArgb(120,rx,gx,bx), 0.1f); g.DrawPath(drawPen, gp); // パスの線分を描画 g.FillPath(brush, gp); // 線分の内部を塗る drawPen.Dispose(); g.SmoothingMode = initialMode; // 念のため元に戻しておく g.CompositingQuality = initialQuality; // 同上