トップC# > 縁取り文字を描く

縁取り文字を描く

1.縁取り文字を描く(1)

文字の見栄えを良くしたいときや、背景の画面と文字の色が近い場合には、 縁取り文字を使うとよい[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;
    }
}

2.縁取り文字を描く(2)[2019.4.12]

地図システムで使うため、再実験をした。

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;      // 同上

A.リファレンス

[1] 【.NET】文字を縁取りして描画する