Measure character positions in a drawn string in C#

The Graphics object's MeasureCharacterRanges method returns information about the regions where strings of characters would be drawn by the Graphics object's DrawString method.

The DrawStringWithCharacterBounds method shown in the following code uses MeasureCharacterRanges to draw a sample string with each character's position outlined in red.
// Draw the string and the bounds for its characters.
private void DrawStringWithCharacterBounds(Graphics gr, string text, Font font, Rectangle rect)
{
    using (StringFormat string_format = new StringFormat())
    {
        string_format.Alignment = StringAlignment.Center;
        string_format.LineAlignment = StringAlignment.Center;

        // Draw the string.
        gr.DrawString(text, font, Brushes.Blue, rect, string_format);

        // Make a CharacterRange for the string's characters.
        List<CharacterRange> range_list = new List<CharacterRange>();
        for (int i = 0; i < text.Length; i++)
        {
            range_list.Add(new CharacterRange(i, 1));
        }
        string_format.SetMeasurableCharacterRanges(range_list.ToArray());

        // Measure the string's character ranges.
        Region[] regions = gr.MeasureCharacterRanges(
            text, font, rect, string_format);

        // Draw the character bounds.
        for (int i = 0; i < text.Length; i++)
        {
            Rectangle char_rect = Rectangle.Round(regions[i].GetBounds(gr));
            gr.DrawRectangle(Pens.Red, char_rect);
        }
    }
}

The code makes a StringFormat object and draws the text. It creates a List of CharacterRange objects and adds one for each of the string's characters. In general a CharacterRange object indicates a first character and the number of characters that you want to measure. In this example, each of the object indicates a single character.

The code calls the StringFormat object's SetMeasureableCharacterRanges method to indicate the CharacterRange objects. Note that this method takes an array of CharacterRange objects as a parameter so the code calls the List's ToArray method to convert it into an array.

Next the program calls the Graphics object's MeasureCharacterRanges method to get an array of Region objects describing where the characters would be drawn. Finally the code loops through the Regions drawing red rectangles to show their bounds.

If you look closely at the picture you'll notice that the characters don't always remain inside their bounds as reported by MeasureCharacterRanges. For example, to make the characters close up nicely, this font makes the lowercase "f" extend to the right into the next character's bounds. Depending on the following character, the "f" may sometimes even touch that character (as in "fF"). Similarly many characters with descenders, including the italic lowercase "f," also extend to the left into the previous characters' bounds.

These sorts of adjustments vary from font to font, and I don't know of a way to determine when they will happen in code.

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.