Get font metrics in a WPF program using C#


[font metrics]

This example explains how to get font metrics in a WPF application. It’s actually not too hard, it’s just hard to figure out how to do it.

The font metrics are tucked away inside the FormattedText object and the Typeface objects. This example uses the following method to make getting the values easier.

// Get information about the text's dimensions.
private void GetTextMetrics(double x, double y,
    FormattedText formatted_text, Typeface typeface,
    double em_size,
    out double y_top, out double y_baseline,
    out double y_caps, out double y_lowercase,
    out double y_descent, out double y_bottom,
    out double x_origin, out double x_start,
    out double x_end, out double x_right)
{
    y_top = y;
    y_bottom = y_top + formatted_text.Height;
    y_baseline = y_top + formatted_text.Baseline;
    y_caps = y_baseline - typeface.CapsHeight * em_size;
    y_lowercase = y_baseline - typeface.XHeight * em_size;
    y_descent = y_bottom + formatted_text.OverhangAfter;

    x_origin = x;
    x_start = x_origin + formatted_text.OverhangLeading;
    x_right = x_origin + formatted_text.Width;
    x_end = x_right - formatted_text.OverhangTrailing;
}

This method takes as input parameters the X and Y coordinates of the text’s reference point, a FormattedText object representing the text to be drawn, and a Typeface object representing the font to be used.

The measurements are easy to understand if you look at the picture above as you step through the code. There’s really only one confusing issue, although it’s a doozy: the FormattedText object’s Width property is not really the width of the text. Instead it’s the horizontal distance from the text’s origin to the right edge of the text’s bounding rectangle (x_right in the picture).

If the text is left-aligned, this is the same as the text’s width. However, if the text is centered or right-aligned, it’s not.

If the text is centered, then FormattedText.Width is the distance from the center of the text to its right edge, which is roughly half of the total width. (It’s not exactly half of the total width because of the internal horizontal spacing between the edges of the text and its bounding rectangle. In the picture, the distance between x_end and x_right.)

If the text is right-aligned, then FormattedText.Width is 0 because the origin is at the right edge of the bounding rectangle.

The moral is: if you need to know the text’s position and width, use x_start, x_end, and x_right instead of x_orgin and FormattedText.Width.

Note also that a font isn’t required to obey its metrics strictly. For example, in the picture at the top of this post, the f, S, and j extend slightly above the y_caps line, and the g extends slightly above the y_lowercase line.

The example’s main program is reasonably straightforward, although it’s long so it isn’t shown here. It just draws lines showing the positions of the text’s various X and Y coordinate values. The yellow circle at (x_origin, y_top) shows the text’s origin. The program also uses the DrawString and DrawRotatedString DrawingContext extension methods described in the posts:

Download the example to see the details.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in drawing, geometry, graphics, wpf, XAML and tagged , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *