Font Metrics


The Graphics object’s MeasureString method tells you approximately how big a string will be when drawn on that object. Its MeasureCharacterRanges method enables you to get more information about the positioning of ranges within a string.

The FontFamily class provides some additional methods that a program can use to get more information about how characters are drawn. Before you can use these values, you must understand a bit of extra character anatomy.

Figure 22-12 shows how a font’s internal leading, ascent, descent, and external leading values help determine a character’s position.

image from book
Figure 22-12: How text is positioned depends on many font metrics, including internal leading, ascent, descent, and external leading.

The following table describes these font metrics.

Open table as spreadsheet

Value

Meaning

Internal Leading

Extra space left above the characters but considered part of the string

Em Height

The height within which the characters are drawn

Ascent

The part of the character cell above the baseline

Descent

The part of the character cell below the baseline

Cell Height

The height of the character area including internal leading

External Leading

Extra space left below one line and above the next

Line Spacing

The distance between one line and the next

From the figure, you can verify the following relationships:

  Cell Height = Ascent + Descent = Internal Leading + Em Height Line Spacing = Cell Height + External Leading 

The FontFamily object provides several methods for determining font metric values. These methods include GetCellAscent, GetCellDescent, GetEmHeight, and GetLineSpacing.

All of these methods return values in font design units. The key to converting them into some other unit is to realize that the Font object’s Size property returns the font’s em size in whatever units the font is currently using. For example, if you specify the font’s size in pixels, then Font.Size returns the em size in pixels.

Using Font.Size and the value returned by the FontFamily class’s GetEmHeight method, you can convert the other values into pixels. For example, the following equation shows how to calculate a font family’s ascent in pixels:

  Ascent Pixels = FontFamily.GetCellAscent * Font.Size / FontFamily.GetEmHeight 

The following code draws the font metrics for some text in three different fonts. It starts by defining some text, a layout rectangle, and a StringFormat object. Then, for each of three fonts, the code creates the font and calls subroutine MeasureCharacters to display the font metrics. Subroutine MeasureCharacters defines an array of CharacterRange objects and initializes them so that they each refer to a single character in the string. It calls SetMeasurableCharacterRanges and then MeasureCharacterRanges, as described in the section “MeasureString” earlier in this chapter. Next, the code calculates the font’s em height, ascent, descent, cell height, internal leading, line spacing, and external leading. The program then loops through the Regions returned by MeasureCharacterRanges. It converts each Region into a Rectangle and draws it. It then draws lines showing the internal leading, ascent, and descent values and fills an area representing the external leading space. The subroutine finishes by drawing the text.

  Private Sub Form1_Paint(ByVal sender As Object, _  ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint     e.Graphics.TextRenderingHint = _         System.Drawing.Text.TextRenderingHint.AntiAliasGridFit     Dim txt As String = "Mgfi"     Dim layout_rect As New RectangleF(0, 0, _         Me.ClientSize.Width \ 3, Me.ClientSize.Height)     Using string_format As New StringFormat         string_format.LineAlignment = StringAlignment.Center         string_format.Alignment = StringAlignment.Center         Using the_font As New Font("Times New Roman", 80, _           FontStyle.Bold, GraphicsUnit.Pixel)             MeasureCharacters(e.Graphics, the_font, txt, _                 layout_rect, string_format)         End Using         layout_rect.X += Me.ClientSize.Width \ 3         Using the_font As New Font("Comic Sans MS", 80, _           FontStyle.Bold, GraphicsUnit.Pixel)             MeasureCharacters(e.Graphics, the_font, txt, _                 layout_rect, string_format)         End Using         layout_rect.X += Me.ClientSize.Width \ 3         Using the_font As New Font("Courier New", 80, _           FontStyle.Bold, GraphicsUnit.Pixel)             MeasureCharacters(e.Graphics, the_font, txt, _                 layout_rect, string_format)         End Using     End Using ' string_format End Sub Public Sub MeasureCharacters(ByVal gr As Graphics, ByVal the_font As Font, _  ByVal txt As String, ByVal layout_rect As RectangleF, _  ByVal string_format As StringFormat)     ' Define an array of CharacterRange objects,      ' one for each character.     Dim character_ranges(txt.Length - 1) As CharacterRange     For i As Integer = 0 To txt.Length - 1         character_ranges(i) = New CharacterRange(i, 1)     Next i     ' Set the ranges in the StringFormat object.     string_format.SetMeasurableCharacterRanges(character_ranges)     ' Get the character range regions.     Dim character_regions() As Region = _         gr.MeasureCharacterRanges(txt, _         the_font, layout_rect, string_format)     ' Get the font's ascent.     Dim em_height As Integer = the_font.FontFamily.GetEmHeight(FontStyle.Bold)     Dim em_height_pix As Single = the_font.Size     Dim design_to_pixels As Single = the_font.Size / em_height     Dim ascent As Integer = the_font.FontFamily.GetCellAscent(FontStyle.Bold)     Dim ascent_pix As Single = ascent * design_to_pixels     Dim descent As Integer = the_font.FontFamily.GetCellDescent(FontStyle.Bold)     Dim descent_pix As Single = descent * design_to_pixels     Dim cell_height_pix As Single = ascent_pix + descent_pix     Dim internal_leading_pix As Single = cell_height_pix - em_height_pix     Dim line_spacing As Integer = _         the_font.FontFamily.GetLineSpacing(FontStyle.Bold)     Dim line_spacing_pix As Single = line_spacing * design_to_pixels     Dim external_leading_pix As Single = line_spacing_pix - cell_height_pix     ' Draw each region's bounds.     For Each rgn As Region In character_regions         ' Convert the region into a Rectangle.         Dim character_bounds As RectangleF = rgn.GetBounds(gr)         Dim character_rect As Rectangle = _             Rectangle.Round(character_bounds)         ' Draw the bounds.         gr.DrawRectangle(Pens.Black, character_rect)         ' Draw the internal leading.         gr.DrawLine(Pens.White, _             character_rect.X, _             character_rect.Y + internal_leading_pix, _             character_rect.Right, _             character_rect.Y + internal_leading_pix)         ' Draw the ascent.         gr.DrawLine(Pens.Yellow, _             character_rect.X, _             character_rect.Y + ascent_pix, _             character_rect.Right, _             character_rect.Y + ascent_pix)         ' Draw the descent.         gr.DrawLine(Pens.Orange, _             character_rect.X, _             character_rect.Y + ascent_pix + descent_pix, _             character_rect.Right, _             character_rect.Y + ascent_pix + descent_pix)         ' Draw the external leading.         gr.FillRectangle(Brushes.Red, _             character_rect.X, _             character_rect.Y + ascent_pix + descent_pix, _             character_rect.Width, _             external_leading_pix)     Next rgn     ' Draw the text.     gr.DrawString(txt, the_font, Brushes.Black, _         layout_rect, string_format) End Sub 

Figure 22-13 shows the result.

Note that the font metrics are not always rigidly followed. For example, sometimes a character may exted into the external leading space.

image from book
Figure 22-13: The FontFamily and Font classes provide the methods you need to calculate font metrics.




Visual Basic 2005 with  .NET 3.0 Programmer's Reference
Visual Basic 2005 with .NET 3.0 Programmer's Reference
ISBN: 470137053
EAN: N/A
Year: 2007
Pages: 417

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net