2

This is a follow-on to a question I asked here: WinForms: Measure Text With No Padding. The question is, given this code ...

    protected override void OnPaint(PaintEventArgs e) {
        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        DrawIt(e.Graphics);
    }

    private void DrawIt(Graphics graphics) {
        var text = "123";
        var font = new Font("Arial", 72);
        // Build a path containing the text in the desired font, and get its bounds.
        GraphicsPath path = new GraphicsPath();
        path.AddString(text, font.FontFamily, (int)font.Style, font.Size, new Point(0, 0), StringFormat.GenericDefault);
        var bounds = path.GetBounds();
        // Find center of the form.
        var cx = this.ClientRectangle.Left + this.ClientRectangle.Width / 2;
        var cy = this.ClientRectangle.Top + this.ClientRectangle.Height / 2;
        // Move it where I want it.
        var xlate = new Matrix();
        xlate.Translate(cx - bounds.Width / 2, cy - bounds.Height / 2);
        path.Transform(xlate);
        // Draw the path (and a bounding rectangle).
        graphics.DrawPath(Pens.Black, path);
        bounds = path.GetBounds();
        graphics.DrawRectangle(Pens.Blue, bounds.Left, bounds.Top, bounds.Width, bounds.Height);
        // This rectangle doesn't use the positioning from Translate but does use the same size.
        graphics.DrawRectangle(Pens.Red, cx - bounds.Width / 2, cy - bounds.Height / 2, bounds.Width, bounds.Height);
    }

... why don't the rectangles overlap?

enter image description here

Clearly, when I'm translating the path, I'm not translating by the same units that I'm later drawing them in, but I'm at a loss how to fix it. Any ideas?

BoCoKeith
  • 817
  • 10
  • 21
  • Looks pretty much like the padding you wanted to get rid of. Reza explains why.. – TaW Jun 24 '18 at 06:12

1 Answers1

3

You have a wrong assumption about Bounds of the path. Since you added the string to the path, starting from point (0,0), you are assuming the location of the bounds of the path is (0,0). That's not correct.

The following illustration shows the relation between the origin that you added string, (0,0) and bounds of the path, blue rectangle:

enter image description here

To fix it, after adding the string and getting its bounds, store the location of the bounds:

var p = bounds.Location;

And then after applying the transformations, draw the rectangle this way:

graphics.DrawRectangle(Pens.Red, 
     p.X + cx - bounds.Width / 2, p.Y + cy - bounds.Height / 2, 
     bounds.Width, bounds.Height);
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Perfect! Thanks @Reza (and @TaW). Since what I wanted was to center the text at a specification location, I only needed to change `xlate.Translate(cx - bounds.Width / 2, cy - bounds.Height / 2);` ... to ... `xlate.Translate(cx - bounds.Location.X - bounds.Width / 2, cy - bounds.Location.Y - bounds.Height / 2);` ... and all is good. (A similar adjustment needs to be made to the blue box location, but it was only there to help me debug.) – BoCoKeith Jun 24 '18 at 15:28
  • Great. You're welcome. In fact the post tries to show the padding and let you draw the red rectangle in expected location. You know the fix you need. – Reza Aghaei Jun 24 '18 at 15:41
  • How to do it with any rotation? Things get weird trying to compute the position for any angle. This transformation by moving the origin by GetBounds().Location works only with Rotation = 0 – user3625699 Jul 25 '22 at 10:02
  • @user3625699 You need to calculate the offset and apply it to the matrix. You can see an example in here: [GraphicsPath text rendering issue (empty space between) - how to rotate around a point?](https://learn.microsoft.com/en-us/answers/questions/939696/graphicspath-text-rendering-issue-empty-space-betw.html?WT.mc_id=DT-MVP-5003235) – Reza Aghaei Jul 25 '22 at 10:16