tmighty tmighty - 3 months ago 20 Question

Flaw in centering function

I have a function that draws a text centered, but I have a math flaw somewhere in there that I just don't spot.

enter image description here

As you can see the font is offset to the bottom and to the right, and part of the shadow is cut off although I thought I accounted for it.

The bigger the rect, the more obvious the flaw gets.

Perhaps it is even a flaw in my usage of the Graphics.DrawImage function because to me the function looks fine.

Does anybody see my mistake?

Thank you for the help!

Public Sub pDraw(ByVal uGraphics As Graphics, ByVal uText As String, ByRef uRect As Rectangle, ByVal uFont As Font, ByVal uStringFormat As StringFormat)

'I have established nice values using a font size of 50. So if we project them onto other font sizes, we will use these templates and percentages
Dim cstOutlineThickness As Integer = 4
Dim cstShadowX As Integer = 1
Dim cstShadowY As Integer = 4
Dim cstDefaultFontSize As Integer = 50

Dim nPngOutlineText As New PngOutlineText()
Color.FromArgb(56, 106, 150),
Color.FromArgb(255, 0, 56, 113),
Color.FromArgb(255, 0, 56, 113),

'we can add the border and shadow sizes later. These are fixed values!
Dim fDestWidth As Single
Dim fDestHeight As Single
SetGoodFontSize(nPngOutlineText, uGraphics, uText, uFont, uRect, fDestWidth, fDestHeight, 4000)

Dim sngPerc As Single = modConversions.Percent(cstDefaultFontSize, uFont.Size, False)

Dim iOutlineThickness As Integer = (sngPerc * cstOutlineThickness) / 100
Dim iShadowX As Integer = (sngPerc * cstShadowX) / 100
Dim iShadowY As Integer = (sngPerc * cstShadowY) / 100

uGraphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
uGraphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic

Dim m_PngOutlineText As New PngOutlineText()
Color.FromArgb(56, 106, 150),
Color.FromArgb(255, 0, 56, 113),
Color.FromArgb(255, 0, 56, 113),

Color.FromArgb(10, 0, 0, 0),
New Point(iShadowX, iShadowY))

Dim fDestWidth2 As Single = 0
Dim fDestHeight2 As Single = 0
Dim sngStartX2 As Single = 0
Dim sngStartY2 As Single = 0
m_PngOutlineText.MeasureString(uGraphics, uFont.FontFamily, uFont.Style, CInt(uFont.Size), uText, New Point(0, 0), StringFormat.GenericDefault, sngStartX2, sngStartY2, fDestWidth2, fDestHeight2)

'center it. There is no good way to specify the aligning in the font-drawing
Dim r As Rectangle = Rectangle.FromLTRB(0, 0, fDestWidth2, fDestHeight2)
CenterRect(uRect, r)

Dim m_clrBkgd As Color = Color.FromArgb(255, 255, 255)
m_PngOutlineText.SetShadowBkgd(m_clrBkgd, fDestWidth2, fDestHeight2)

Dim m_pPngImage As Bitmap = New Bitmap(CInt(fDestWidth2), CInt(fDestHeight2), System.Drawing.Imaging.PixelFormat.Format32bppArgb)
Dim gradientBrush As New LinearGradientBrush(New RectangleF(0, 0, fDestWidth2, fDestHeight2), Color.FromArgb(56, 106, 150), Color.FromArgb(37, 119, 178), Drawing2D.LinearGradientMode.Vertical)
m_PngOutlineText.TextGradOutline(gradientBrush, Color.FromArgb(255, 0, 56, 113), Color.FromArgb(255, 0, 56, 113), iOutlineThickness)
m_PngOutlineText.DrawString(uGraphics, New FontFamily(uFont.Name), uFont.Style, uFont.Size, uText, New Point(0, 0), uStringFormat)

uGraphics.DrawImage(m_pPngImage, r)

End Sub

Public Sub CenterRect(ByVal uMain As Rectangle, ByRef uRectToCenter As Rectangle)

Dim iMainLeft As Integer = uMain.Left
Dim iMainTop As Integer = uMain.Top
Dim iMainWidth As Integer = uMain.Width
Dim iMainHeight As Integer = uMain.Height
Dim iDestW As Integer = uRectToCenter.Width
Dim iDestH As Integer = uRectToCenter.Height
Dim iDestX2 As Integer = iMainLeft + ((iMainWidth - iDestW) / 2)
Dim iDestY2 As Integer = iMainTop + ((iMainHeight - iDestH) / 2)

Dim nPoint As New Point(iDestX2, iDestY2)
uRectToCenter.Location = nPoint

End Sub

Here is another screenshot from debugging:
As you can see, the image is drawn at X=22, Y=-11, Width=212, Height=278, but as you can see from the screenshot, that is not how it looks like in the end.

That is why I was asking if it might be a mistake in Graphics.DrawImage.

enter image description here

Edit 3:
I have filled the m_pPngImage with Color.Red so that I can see where it is actually drawn. This looks fine to me, so I guess the problem is not in CenterRect or similar.

enter image description here



Briefly, given a rect r:

centerX = (r.Left + r.Right) / 2;
centerY = (r.Top  + r.Bottom) / 2;

To center it a rect about its local, well, center:

r.Left -= r.Width / 2;
r.Right -= r.Width /2;
r.Top -= r.Height / 2;
r.Bottom -= r.Height / 2;

Really, that's all there is to it.


Based on your update / new screenshot, I'm convinced that either the character cell contains the margin, or MeasureString is adding it. Either way, your output is correct.

Also, you may find this thread helpful.