【问题标题】:How to Draw a given Character in exact height?如何以精确的高度绘制给定的字符?
【发布时间】:2015-05-07 17:49:37
【问题描述】:

我正在使用 Graphics.DrawString() 方法绘制文本,但绘制的文本高度与我给出的不同。

例如:

Font F=new Font("Arial", 1f,GraphicUnit.Inch);
g.DrawString("M", F,Brushes.red,new Point(0,0));

通过使用上面的代码,我正在绘制高度为 1 英寸的文本,但绘制的文本并不完全是 1 英寸。

我需要在我给出的精确高度中绘制文本。提前谢谢..

【问题讨论】:

  • 您在测量什么以及如何测量?你的屏幕?打印出来的?
  • 文本将始终在上方和下方留下一点空间(前导)。要获得目标所需的大小,您应该循环测量它,直到找到最佳字体大小。使用 MeasureString 或 TextRenderer
  • 添加到我上面的评论:前导取决于字体,要测量的文本将确定返回的大小,因此 'x' 、 'X' 、 'Â' 和 'y' 将返回不同的高度!
  • @Cyber​​Dude 和@Taw:感谢您的回复,我在屏幕和打印中得到了相同的结果。如果我将文本高度输入为 1 英寸,则打印中的字符 M 应该正好是 1 英寸,没有任何上下空格。
  • 我已经编写了一个解决方案,向您展示如何通过两步过程将比例缩放到正确的大小..

标签: c# graphics


【解决方案1】:

最简单的解决方案是使用GraphicsPath。以下是必要的步骤:

  • 以像素为单位计算您想要的高度:要获得 1.0f 英寸,例如 150 dpi,您需要 150 像素。

  • 然后创建GraphicsPath,并使用计算出的高度,添加你要使用的字体和字体样式中的字符或字符串

  • 现在测量结果高度,使用GetBounds

  • 然后将高度放大到所需的像素数

  • 最后清空路径,用新的高度再次添加字符串

  • 现在你可以使用FillPath来输出像素了..

这是一个代码示例。它将测试字符串写入文件。如果你想使用它们的Graphics 对象将它写入打印机或控件,你可以用同样的方法;在计算高度的第一个估计值之前获取/设置dpi..

下面的代码创建了这个文件; Consolas 'x' 和 Wingdings 字体的第二个字符 (ox95) 一样高 150 像素。 (请注意,我没有将输出居中):

// we are using these test data:
int Dpi = 150;
float targetHeight = 1.00f;
FontFamily ff = new FontFamily("Consolas");
int fs = (int) FontStyle.Regular;
string targetString = "X";

// this would be the height without the white space
int targetPixels = (int) targetHeight * Dpi;

// we write to a Btimpap. I make it large enough..
// Instead you can write to a printer or a Control surface..
using (Bitmap bmp = new Bitmap(targetPixels * 2, targetPixels * 2))
{
    // either set the resolution here
    // or get and use it above from the Graphics!
    bmp.SetResolution(Dpi, Dpi);
    using (Graphics G = Graphics.FromImage(bmp))
    {
        // good quality, please!
        G.SmoothingMode = SmoothingMode.AntiAlias;
        G.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        // target position (in pixels)
        PointF p0 = new PointF(0, 0);
        GraphicsPath gp = new GraphicsPath();
        // first try:
        gp.AddString(targetString, ff, fs, targetPixels, p0,
                     StringFormat.GenericDefault);
        // this is the 1st result
        RectangleF gbBounds = gp.GetBounds();
        // now we correct the height:
        float tSize = targetPixels * targetPixels / gbBounds.Height;
        // and if needed the location:
        p0 = new PointF(p0.X  - gbBounds.X, p0.X - gbBounds.Y);
        // and retry
        gp.Reset();
        gp.AddString(targetString, ff, fs, tSize, p0, StringFormat.GenericDefault);
        // this should be good
        G.Clear(Color.White);
        G.FillPath(Brushes.Black, gp);
    }
    //now we save the image 
    bmp.Save("D:\\testString.png", ImageFormat.Png);
}

您可能想尝试使用校正因子来扩大Font 的大小并最终使用DrawString

还有一种方法可以使用FontMetrics 计算前面的数字,但我理解链接意味着这种方法可能取决于字体..

【讨论】:

  • 感谢 TaW.. 它工作得很好.. 但是如果要在相同的位置绘制不同的字体,文本不会绘制给定的位置。如何解决这个问题Taw先生
  • 你是对的;我完全忽略了该位置,但现在我添加了一条线来计算更正的目标位置p0..
  • 谢谢 Taw.. 抱歉延迟回复。它更有帮助。不错的TaW
猜你喜欢
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多