2011年04月02日

メイリオの描画位置がずれる問題(C#)

メイリオに限った問題ではありませんが、GraphicsPathのAddStringを使ってメイリオの文字を描画すると、意図した位置からずれたところに描画されることがあります。
これはメイリオのフォント自体に定義されている描画位置が、少しずれているために起きるようです。

実際には、メイリオだけの問題ではありません。本当はMSPゴシックなどもずれています。
しかし、メイリオは行間を空けるために縦方向に大きくずれているため目立ちます。他のフォントであれば何もしなくても“目に見えないので問題ない”のですが、メイリオは調整してやらないと、“目に見えて変”な状態になります。

まずはどのくらいずれているのかを確認するため、下記のプログラムを実行してみて下さい。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // PictureBoxを生成しFormに追加
            PictureBox picture = new PictureBox();
            picture.Width = this.Width;
            picture.Height = this.Height;
            this.Controls.Add(picture);

            // Imageを生成してPictureBoxに割当
            Bitmap image = new Bitmap(this.Width, this.Height);
            picture.Image = image;

            // Imageに描画
            Graphics g = Graphics.FromImage(image);
            g.Clear(Color.Black);

            // アンチエリアス
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            // レンダリング品質
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

            // 描画する文字
            string text = "Aaあぁアァ亜宇";

            // メイリオでの描画
            {
                Font font = new Font("メイリオ", 24, FontStyle.Bold);
                Point pos = new Point(20, 20);

                // GraphicsPathの生成
                System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();

                // テキストをPathに変換
                gp.AddString(text, font.FontFamily, (int)font.Style, font.SizeInPoints,
                    pos, StringFormat.GenericDefault);

                // 文字の縁を描画
                g.DrawPath(new Pen(Brushes.Blue, 3.0f), gp);

                // 文字を塗る
                g.FillPath(Brushes.White, gp);

                // 描画位置にマーキング
                g.DrawLine(Pens.Pink, pos.X - 20, pos.Y, pos.X + 20, pos.Y);
                g.DrawLine(Pens.Pink, pos.X, pos.Y - 20, pos.X, pos.Y + 20);

                // Pathに内接する四角形を描画
                RectangleF rect = gp.GetBounds();
                g.DrawRectangle(Pens.Red, rect.X, rect.Y, rect.Width, rect.Height);

                // 終了
                gp.Dispose();
            }

            // MSゴシックでの描画
            {
                Font font = new Font("MS Pゴシック", 24, FontStyle.Bold);
                Point pos = new Point(20, 120);

                // GraphicsPathの生成
                System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();

                // テキストをPathに変換
                gp.AddString(text, font.FontFamily, (int)font.Style, font.SizeInPoints,
                    pos, StringFormat.GenericDefault);

                // 文字の縁を描画
                g.DrawPath(new Pen(Brushes.Blue, 3.0f), gp);

                // 文字を塗る
                g.FillPath(Brushes.White, gp);

                // 描画位置にマーキング
                g.DrawLine(Pens.Pink, pos.X - 20, pos.Y, pos.X + 20, pos.Y);
                g.DrawLine(Pens.Pink, pos.X, pos.Y - 20, pos.X, pos.Y + 20);

                // Pathに内接する四角形を描画
                RectangleF rect = gp.GetBounds();
                g.DrawRectangle(Pens.Red, rect.X, rect.Y, rect.Width, rect.Height);

                // 終了
                gp.Dispose();
            }
        }
    }
}

実行するとこのようになります。
meyrio-1.png
白っぽい十字の線が本来描画させたい位置ですが、実際には赤い四角形の位置に描画されています。
つまり、それだけ描画位置がずれているのです。

続きます。

良かったらクリックしてください
にほんブログ村 IT技術ブログ プログラム・プログラマーへ  人気ブログランキングへ

posted by among at 20:52 | Comment(0) | TrackBack(0) | C#

画像(イメージ)のトリミング(C#)

簡単にBitmapをトリミングする方法。

// イメージの生成
Bitmap image = new Bitmap( 200, 200 );

// イメージに描画
〜省略〜

// トリミングする範囲
RectangleF clipRect = new RectangleF(50, 50, 100, 100);

// トリミング実施
Bitmap clipImage = image.Clone(clipRect, image.PixelFormat);

CloneはImageのコピーを作成するメソッドですが、引数にRectangleまたはRectangleFを指定することで、指定した範囲のコピーを作成することができます。
またPixelFormatは元画像と合わせなくてもOKです。

良かったらクリックしてください
にほんブログ村 IT技術ブログ プログラム・プログラマーへ  人気ブログランキングへ

posted by among at 09:35 | Comment(0) | TrackBack(0) | C#