0

I'm working on a program that allows using a bitmap (in a PictureBox) as a text object. I have things mostly working, even word-wrap, all except for outlined text.

private void DrawOutlineString(string text, PointF pos)
{
    Graphics g = Graphics.FromImage(image);
    SolidBrush b = new(forecolor);
    Pen pen = new(outlinecolor, outlinesize);
    Pen p = pen;
    GraphicsPath gp = new();
    gp.AddString(text, fontfamily, (int)fontstyle, g.DpiY 
        * fontsize / 72, pos, new StringFormat());
    g.DrawPath(p, gp);
    g.FillPath(b, gp);
    gp.Dispose();
    p.Dispose();
    b.Dispose();
    g.Dispose();
}

For outlined text, I'm using a GraphicsPath object and adding the string with font info to it, then using DrawPath and then FillPath to draw it.

Note that DrawPath uses a pen and the pen's thickness determines how thick the outline is.

The problem is that the size of the text put to the bitmap that way is not the same as the size it would be with a DrawString. But it is not the same as simply adding the outline size to the g.MeasureString result.

private SizeF GetTextSize(string text)
{
    Graphics g = Graphics.FromImage(image);
    SizeF size = g.MeasureString(text, font);
    g.Dispose();
    return size;
}

private SizeF GetOutlineTextSize(string text)
{
    SizeF size = GetTextSize(text);
    size.Width += outlinesize * 2;
    size.Height += outlinesize * 2;
    return size;
}

I've tried adding the outline size (as defined in my pen) to the g.MeasureString size and I've tried doubling the outline size (since once on each side), but no such luck. Help!

Okay, after a cursory examination of the link provided by Jimi, here is my latest attempt:

        private SizeF GetOutlineTextSize(string text)
    {
        Graphics g = Graphics.FromImage(image);
        Pen p = new Pen(outlinecolor, outlinesize);
        GraphicsPath gp = new();
        gp.AddString(text, fontfamily, (int)fontstyle, g.DpiY * fontsize / 72, position, new StringFormat());
        RectangleF rect = gp.GetBounds(null, p);
        gp.Dispose();
        p.Dispose();
        g.Dispose();
        SizeF size = new(rect.Width, rect.Height);
        return size;
    }

I haven't had a chance to fully test this method yet, but it looks hopeful.

woodmage
  • 31
  • 5
  • Consider either removing the "guys" at the start of your post (it adds nothing to the content of your post and is exclusionary), or, at the very least, changing it to "Folks" – Flydog57 Jun 15 '23 at 18:11
  • Actually, that was originally "Hi, guys!", but for some reason got clipped. ?? But, yeah, ... Hi, Folks! ;') – woodmage Jun 15 '23 at 19:08
  • 1
    Just a guess: Fluffy salutations like "Hi" are frowned on on this site (they add no content. It could be that the site strips of the "Hi" you apparently started your post with – Flydog57 Jun 15 '23 at 19:27
  • 1
    Some actual code would be useful – Charlieface Jun 15 '23 at 21:26
  • 1
    [Properly draw text using GraphicsPath](https://stackoverflow.com/a/53074638/7444103) – Jimi Jun 15 '23 at 21:52
  • Okay, added some of the code for the internal helper functions. – woodmage Jun 16 '23 at 00:52
  • Thanks, Jimi. It looks pretty complicated to me, but I will study through it and maybe my answer is in there. – woodmage Jun 16 '23 at 01:03
  • Okay, I came up with a simplified function and edited my question to show it. If it turns out to be my answer, it's all thanks to Jimi for pointing me at it. ;') – woodmage Jun 16 '23 at 01:49
  • 1
    You should be using `using()` blocks for all of those GDI objects instead of manually calling `.Dispose()` - otherwise if an exception is thrown then you'll leak GDI resources. – Dai Jun 16 '23 at 01:51

0 Answers0