MeasureString and DrawString difference
Graphics.MeasureString, TextRenderer.MeasureText and Graphics.MeasureCharacterRanges all return a size that includes blank pixels around the glyph to accomodate ascenders and descenders.
In other words, they return the height of "a" as the same as the height of "d" (ascender) or "y" (descender). If you need the true size of the glyph, the only way is to draw the string and count the pixels:
Public Shared Function MeasureStringSize(ByVal graphics As Graphics, ByVal text As String, ByVal font As Font) As SizeF
' Get initial estimate with MeasureText
Dim flags As TextFormatFlags = TextFormatFlags.Left + TextFormatFlags.NoClipping
Dim proposedSize As Size = New Size(Integer.MaxValue, Integer.MaxValue)
Dim size As Size = TextRenderer.MeasureText(graphics, text, font, proposedSize, flags)
' Create a bitmap
Dim image As New Bitmap(size.Width, size.Height)
image.SetResolution(graphics.DpiX, graphics.DpiY)
Dim strFormat As New StringFormat
strFormat.Alignment = StringAlignment.Near
strFormat.LineAlignment = StringAlignment.Near
' Draw the actual text
Dim g As Graphics = graphics.FromImage(image)
g.SmoothingMode = SmoothingMode.HighQuality
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
g.Clear(Color.White)
g.DrawString(text, font, Brushes.Black, New PointF(0, 0), strFormat)
' Find the true boundaries of the glyph
Dim xs As Integer = 0
Dim xf As Integer = size.Width - 1
Dim ys As Integer = 0
Dim yf As Integer = size.Height - 1
' Find left margin
Do While xs < xf
For y As Integer = ys To yf
If image.GetPixel(xs, y).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
xs += 1
Loop
' Find right margin
Do While xf > xs
For y As Integer = ys To yf
If image.GetPixel(xf, y).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
xf -= 1
Loop
' Find top margin
Do While ys < yf
For x As Integer = xs To xf
If image.GetPixel(x, ys).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
ys += 1
Loop
' Find bottom margin
Do While yf > ys
For x As Integer = xs To xf
If image.GetPixel(x, yf).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
yf -= 1
Loop
Return New SizeF(xf - xs + 1, yf - ys + 1)
End Function
MeasureString() method had some issues, especially when drawing non-ASCII characters. Please try TextRenderer.MeasureText() instead.