System.Drawing.Font - 更改字母间距?

时间:2011-10-20 09:38:14

标签: .net fonts drawing system.drawing

使用System.Drawing.Font,有没有办法更改字母间距,就像您可以更改字体大小一样?

我希望增加字母间距以适应特定的宽度。

如果无法做到这一点,是否有其他方法可以达到预期效果?例如,是否有一种简单的方法可以使多个图形适合我的特定宽度?

2 个答案:

答案 0 :(得分:4)

我不认为DrawString会允许你指定任何像字符之间的间距那样详细的东西,但我会创建一个辅助函数,根据所需的宽度计算间距,然后绘制每个字符以适应。

试试这个,看看你是如何进行的......

    public void DrawSpacedText(Graphics g, Font font, Brush brush, PointF point, string text, int desiredWidth)
    {
        //Calculate spacing
        float widthNeeded = 0;
        foreach (char c in text)
        {
            widthNeeded += g.MeasureString(c.ToString(), font).Width;
        }
        float spacing = (desiredWidth - widthNeeded) / (text.Length - 1);

        //draw text
        float indent = 0;
        foreach (char c in text)
        {
            g.DrawString(c.ToString(), font, brush, new PointF(point.X + indent, point.Y));
            indent += g.MeasureString(c.ToString(), font).Width + spacing;
        }
    }

您可以对此进行优化,以便每个字符只调用一次MeasureString。或者甚至使用MeasureCharacterRanges来获得一个数组(我认为无论如何都更准确)

修改:以下是使用MeasureCharacterRanges的示例...

    public void DrawSpacedText(Graphics g, Font font, Brush brush, PointF point, string text, int desiredWidth)
    {
        //Calculate spacing
        float widthNeeded = 0;
        Region[] regions = g.MeasureCharacterRanges(text, font, new RectangleF(point, new SizeF(desiredWidth, font.Height + 10)), StringFormat.GenericDefault);
        float[] widths = new float[regions.Length];
        for(int i = 0; i < widths.Length; i++)
        {
            widths[i] = regions[i].GetBounds(g).Width;
            widthNeeded += widths[i];
        }
        float spacing = (desiredWidth - widthNeeded) / (text.Length - 1);

        //draw text
        float indent = 0;
        int index = 0;
        foreach (char c in text)
        {
            g.DrawString(c.ToString(), font, brush, new PointF(point.X + indent, point.Y));
            indent += widths[index] + spacing;
            index++;
        }
    }

答案 1 :(得分:0)

此代码支持文本中的新行并返回Image对象。

public static Image ConvertTextToImage(String text, Font font, Color textColor, int spacing = 0)
{
    var textParts = SplitOnBreakLines(text);
    // dummy image, just create drawing
    var img = new Bitmap(1, 1);
    var drawing = Graphics.FromImage(img);
    // calculate width, height
    var width = 0.0F;
    foreach (char c in text)
    {
        width += drawing.MeasureString(c.ToString(), font).Width;
    }           
    width = (width + spacing * (ClearBreakLines(text).Length - 1))  / textParts.Length;
    if (width <= 0)
        width = 1;
    var height = font.Height * textParts.Length;
    // clear and create new objects
    img.Dispose();
    drawing.Dispose();

    img = new Bitmap((int)width, (int)height);
    drawing = Graphics.FromImage(img);

    //Adjust for high quality
    drawing.CompositingQuality = CompositingQuality.HighQuality;
    drawing.InterpolationMode = InterpolationMode.HighQualityBilinear;
    drawing.PixelOffsetMode = PixelOffsetMode.HighQuality;
    drawing.SmoothingMode = SmoothingMode.HighQuality;
    drawing.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

    //paint the background
    drawing.Clear(Color.Transparent);

    //create a brush for the text
    var textBrush = new SolidBrush(textColor);
    //write text
    var indent = 0.0F;
    var point = new Point();            
    foreach (var textPart in textParts)
    {
        foreach (char c in textPart)
        {
            drawing.DrawString(c.ToString(), font, textBrush, new PointF(point.X + indent, point.Y));
            indent += drawing.MeasureString(c.ToString(), font).Width + spacing;
        }
        indent = 0.0F;
        point.Y += font.Height;
    }
    drawing.Save();
    textBrush.Dispose();
    drawing.Dispose();
    return img;           
}

public static string ClearBreakLines(string s)
{
    return Regex.Replace(s, @"\r\n?|\n", string.Empty);
}

public static string[] SplitOnBreakLines(string s)
{
    return Regex.Split(s, @"\r\n?|\n");           
}