Working with Fonts

In this section we will concentrate on fonts. The discussion starts with a description of the types of fonts in the Windows operating system, followed by a little background material on fonts. After these basic concepts are covered, the discussion turns to how fonts are handled in GDI+ and .NET.

5.3.1 Font Types in Windows

Windows supports two types of fonts: GDI fonts and device fonts. Device fonts are native to output devices such as a monitor or a printer. GDI fonts are stored in files on your systemnormally in the WindowsFonts directory. Each font has its own file. For example, Arial, Arial Black, Arial Bold, Arial Italic, Arial Black Italic, Arial Bold Italic, Arial Narrow, Arial Narrow Bold Italic, and Arial Narrow Italic are different fonts in the Arial font family, and each one has its own file (see Figure 5.5).

Figure 5.5. Fonts available in Windows

GDI fonts can be further divided into four major categories: raster, stroke, TrueType, and OpenType. The raster and stroke fonts are the oldest way to display text (they pre-date Windows 3.1!). Raster fonts (also known as bitmap fonts) store each character in pixel format. Each raster font is designed for a specific aspect ratio and character size, which are generally not scalable to other sizes. The main advantage of raster fonts is high performance because rendering a raster font usually just requires copying it to video memory. Raster fonts support boldface, italics, underlining, and strikethrough formatting.

Stroke fonts (also known as vector fonts) are defined as a series of lines and dotsin much the same way that characters are drawn with a pen plotter. Stroke fonts are thus quite scalable (they can be increased or decreased to any size), and they can be used with output devices of any resolution. Examples of stroke fonts include Modern, Roman, and Script. Like raster fonts, stroke fonts support boldface, italics, underlining, and strikethrough formatting.

Next we come to TrueType fonts, which were developed by Apple and Microsoft and are supported by many manufacturers. TrueType fonts are also called outline fonts because the individual characters are defined by filled outlines of straight lines and curves. Altering the coordinates that define the outlines provides great scalability. The original 13 TrueType fonts were

  1. Courier New
  2. Courier New Bold
  3. Courier New Italic
  4. Courier New Bold Italic
  5. Times New Roman
  6. Times New Roman Bold
  7. Times New Roman Italic
  8. Times New Roman Bold Italic
  9. Arial
  10. Arial Bold
  11. Arial Italic
  12. Arial Bold Italic
  13. Symbol

Adobe and Microsoft announced yet another format in 1997, called OpenType. It is a combination of TrueType and the Type 1 outline format of Adobe's page-description language. Windows 2000 installs 82 fonts, including TrueType fonts, OpenType fonts, and other types. The TrueType fonts are represented by a "T" icon, and OpenType fonts are represented by an "O" icon in Windows Explorer, as shown in Figure 5.6.

Figure 5.6. Font icons represent font types

The file extension of both TrueType and OpenType fonts is .ttf. If you double-click on the Verdana OpenType font file, it displays the information shown in Figure 5.7.

Figure 5.7. An OpenType font

The Arial Black Italic TrueType font file, on the other hand, looks like Figure 5.8.

Figure 5.8. A TrueType font

In 1998, Microsoft announced a new display technology called ClearType. ClearType increases the readability and smoothness of text on existing LCDs (liquid crystal displays), such as laptop screens, flat-screen monitors, and Pocket PC screens. In normal displays, a pixel has only two states: on and off. ClearType technology adds additional information to a pixel besides the on and off states. With ClearType, the words on the display device look almost as sharp and clear as those on the printed page.

Note

To learn more about Microsoft's ClearType technology, visit http://www.microsoft.com/typography/cleartype/default.htm.

 

5.3.1.1 Attributes or Styles

In typography, the combination of a typeface name (sometimes referred to as a face name) and a point size (sometimes referred to as the em size) represents a font. A typeface name is a combination of a font family and the font style (also referred to as font attributes). Each typeface belongs to a font family such as Times New Roman, Arial, or Courier. The Courier family, for example, includes the typefaces Courier New, Courier New Bold, and Courier New Italic.

Generally, when we talk about a font, we are referring to more than just one component. A typical font is a combination of three components: font family, font style, and font size. Figure 5.9 shows the components of a typical font.

Figure 5.9. Font components

A complete example of a font is "Times New Roman, size 10, Bold|Italic". Here the font family is Times New Roman, the size is 10-point, and the style is both bold and italic.

5.3.1.2 Font Height and Line Spacing

The size of a font is expressed in points, where a point is usually 1/72 (0.013888) inch. The measurement of the size of a font is a little confusing because characters have different heights. If all alphabetic characters had the same height, it would be easier to calculate the size of a font. For example, consider the characters b and q. Technically they have the same height (or size), but they are situated in different locations along a straight line. In other words, the character's size may not be the same as the point size, also called em size. The font size is related to the line spacing. We will discuss line spacing in more detail in Section 5.3.4.

5.3.2 Fonts in .NET

Before we use fonts and draw text, let's see what classes GDI+ provides related to text and fonts, and how to use them.

Typography Namespaces

In the .NET framework library, two namespaces define the font-related functionality: System.Drawing and System.Drawing.Text. The System.Drawing namespace contains general typography functionality, and System.Drawing.Text contains advanced typography functionality. Before using any of the typography-related classes in your application, you must include the appropriate namespace. We will discuss advanced typography in Section 5.6.

The Font class provides functionality for fonts, including methods and properties to define functionalities such as font style, size, name, and conversions. Before we discuss the Font class, we will introduce the FontStyle enumeration and the FontFamily class, which we will use to create Font objects.

5.3.3 The FontStyle Enumeration

The FontStyle enumeration defines the common styles of a font. The members of FontStyle are described in Table 5.4.

5.3.4 The FontFamily Class

The FontFamily class provides methods and properties to work with font families. Table 5.5 describes the properties of the FontFamily class.

Table 5.4. FontStyle members

Member

Description

Bold

Bold text

Italic

Italic text

Regular

Normal text

Strikeout

Text with a line through the middle

Underline

Underlined text

Table 5.5. FontFamily properties

Property

Description

Families

Returns an array of all the font families associated with the current graphics context.

GenericMonospace

Returns a monospace font family.

GenericSansSerif

Returns a sans serif font family.

GenericSerif

Returns a serif font family.

Name

Returns the name of a font family.

Note

The GetFamilies method of the FontCollection class returns all families, as we will discuss in Section 5.6.

Table 5.6 describes the methods of the FontFamily class.

Table 5.6 introduces some new terms, including base line, ascent, and descent. Let's see what they mean. Figure 5.10 shows a typical font in Windows. As you can see, although the letters b and q are the same size, their starting points and ending points (top and bottom locations) are different. The total height of a fontincluding ascent, descent, and extra spaceis called the line spacing. Ascent is the height above the base line, and descent is the height below the base line. As Figure 5.10 shows, two characters may have different positions along the base line. For some fonts, the extra value is 0, but for others it is not.

Figure 5.10. Font metrics

Table 5.6. FontFamily methods

Method

Description

GetCellAscent

Returns the cell ascent, in font design units, of a font family.

GetCellDescent

Returns the cell descent, in font design units, of a font family.

GetEmHeight

Returns the height, in font design units, of the em square for the specified style.

GetFamilies

Returns an array that contains all font families available for a graphics object. This method takes an argument of Graphics type.

GetLineSpacing

Returns the amount of space between two consecutive lines of text for a font family.

GetName

Returns the name, in the specified language, of a font family.

IsStyleAvailable

Before applying a style to a font, you may want to know whether the font family in question supports that style. This method returns true if a font style is available. For example, the following code snippet checks whether or not the Arial font family supports italics:

 

FontFamily ff = new FontFamily("Arial"); if(ff.IsStyleAvailable(FontStyle.Italic)) // do something

 

For some fonts, line spacing is the sum of ascent and descent. Listing 5.6 creates a new font; uses get methods to get the values of line spacing, ascent, and descent; and calculates the extra space by subtracting ascent and descent from the line space. The following list identifies the get methods of a FontFamily object:

In addition to these get methods, the Font class provides GetHeight, which returns the height of a Font object.

As Listing 5.6 shows, we use GetLineSpacing, GetLineAscent, GetLineDescent, and GetEmHeight to get line spacing, ascent, descent, and font height, respectively, and then we display the output in a message box.

Listing 5.6 Getting line spacing, ascent, descent, and font height

private void Properties_Click(object sender, System.EventArgs e) { // Create a Graphics object Graphics g = this.CreateGraphics(); // Create a Font object Font fnt = new Font("Verdana", 10); // Get height float lnSpace = fnt.GetHeight(g); // Get line spacing int cellSpace = fnt.FontFamily.GetLineSpacing(fnt.Style); // Get cell ascent int cellAscent = fnt.FontFamily.GetCellAscent(fnt.Style); // Get cell descent int cellDescent = fnt.FontFamily.GetCellDescent(fnt.Style); // Get font height int emHeight = fnt.FontFamily.GetEmHeight(fnt.Style); // Get free space float free = cellSpace - (cellAscent + cellDescent); // Display values string str = "Cell Height:" + lnSpace.ToString() + ", Line Spacing: "+cellSpace.ToString() + ", Ascent:"+ cellAscent.ToString() + ", Descent:"+ cellDescent.ToString() + ", Free:"+free.ToString() + ", EM Height:"+ emHeight.ToString() ; MessageBox.Show(str.ToString()); // Dispose of objects fnt.Dispose(); g.Dispose(); }

Figure 5.11 shows the output from Listing 5.6. We get cell height, line spacing, ascent, descent, free (extra) space, and em height.

Figure 5.11. Getting line spacing, ascent, descent, free (extra) space, and height of a font

5.3.5 The GraphicsUnit Enumeration

You can define the unit of measure of a font when you construct a Font object. The Font class constructor takes an argument of type GraphicsUnit enumeration, which specifies the unit of measure of a font. The default unit of measure for fonts is the point (1/72 inch). You can get the current unit of a font by using the Unit property of the Font class. The following code snippet returns the current unit of the font:

 

Font fnt = new Font("Verdana", 10); MessageBox.Show(fnt.Unit.ToString());

 

The members of the GraphicsUnit enumeration are described in Table 5.7.

Table 5.7. GraphicsUnit members

Member

Unit of Measure

Display

1/75 inch

Document

1/300 inch

Inch

1 inch

Millimeter

1 millimeter

Pixel

1 pixel

Point

1/72 inch

World

The world unit (we'll discuss world coordinates in Chapter 10)

5.3.6 The Font Class

The Font class combines a font and methods and properties to define functionalities such as font style, size, name, and conversions. Table 5.8 describes the properties of the Font class.

The following code creates a Font object of font family Arial with size 16 and uses the Font class properties to find out the details of the Font object.

 

Font arialFont = new Font( "Arial", 16, FontStyle.Bold|FontStyle.Underline|FontStyle.Italic); MessageBox.Show("Font Properties = Name:"+arialFont.Name +" Size:"+arialFont.Size.ToString() +" Style:"+ arialFont.Style.ToString() +" Default Unit:"+ arialFont.Unit.ToString() +" Size in Points:"+ arialFont.SizeInPoints.ToString());

 

The Font class provides three static methods: FromHdc, FromHfont, and FromLogFont. These methods create a Font object from a window handle to a device context, a window handle, and a GDI LOGFONT structure, respectively. The GetHeight method returns the height of a Font object. The ToHfont and ToLogFont methods convert a Font object to a window handler and a GDI LOGFONT structure, respectively.

Table 5.8. Font properties

Property

Description

Bold

Returns true if the font is bold.

FontFamily

Every font belongs to a font family. This property returns the FontFamily object associated with a Font object.

GdiCharSet

Returns a string containing all characters.

GdiVerticalFont

Returns true if a font is derived from a GDI vertical font; otherwise returns false.

Height

Returns the height of a font.

Italic

Returns true if a font is italic.

Name

Returns the face name of a font.

Size

Returns the em size of a font in font design units.

SizeInPoints

Returns the size, in points, of a font.

Strikeout

Returns true if a font specifies a horizontal line through the font.

Style

Returns style information for a font, which is a type of FontStyle enumeration.

Underline

Returns true if a font is underlined.

Unit

Returns the unit of measure for a font.

In the following example, you must import the GDI library by adding the following code at the beginning of your class before using any GDI fonts, because we will be using GetStockObject:

 

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] private static extern IntPtr GetStockObject(int fnObj);

 

Listing 5.7 creates a font from a GDI handle and draws a string on the form. The FromHfont method creates a Font object from a GDI handle.

Listing 5.7 Using the FromHfont method

private void FromHfontMenu_Click(object sender, System.EventArgs e) { // Create the Graphics object Graphics g = this.CreateGraphics(); // Create a brush SolidBrush brush = new SolidBrush(Color.Red); // Get a handle IntPtr hFont = GetStockObject(0); // Create a font from the handle Font hfontFont = Font.FromHfont(hFont); // Draw text g.DrawString("GDI HFONT", hfontFont, brush, 20, 20); // Dispose of objects brush.Dispose(); hfontFont.Dispose(); g.Dispose(); }

Figure 5.12 shows the output from Listing 5.7.

Figure 5.12. Using the FromHFont method

5.3.7 Constructing a Font Object

A Font object belongs to the FontFamily class, so before we construct a Font object, we need to construct a FontFamily object. The following code snippet creates two FontFamily objects, belonging to the Verdana and Arial font families, respectively.

 

// Create font families FontFamily verdanaFamily = new FontFamily("Verdana"); FontFamily arialFamily = new FontFamily("Arial");

 

The Font class provides more than a dozen overloaded constructors, which allow an application to construct a Font object in different ways, either from string names of a font family and size or from a FontFamily object with font style and optional GraphicsUnit values.

The simplest way to create a Font object is to pass the font family name as the first argument and the point size as the second argument of the Font constructor. The following code snippet creates a Times New Roman 12-point font:

 

Font tnwFont = new Font("Times New Roman", 12);

 

The following code snippet creates three fonts in different styles belonging to the Verdana, Tahoma, and Arial font families, respectively:

 

// Create font families FontFamily verdanaFamily = new FontFamily("Verdana"); FontFamily arialFamily = new FontFamily("Arial"); // Construct Font objects Font verdanaFont = new Font( verdanaFamily, 14, FontStyle.Regular, GraphicsUnit.Pixel); Font tahomaFont = new Font( new FontFamily("Tahoma"), 10, FontStyle.Bold|FontStyle.Italic, GraphicsUnit.Pixel); Font arialFont = new Font(arialFamily, 16, FontStyle.Bold, GraphicsUnit.Point); Font tnwFont = new Font("Times New Roman", 12);

 

Note

As the code example here shows, you can use the FontStyle and GraphicsUnit enumerations to define the style and units of a font, respectively.

If you don't want to create and use a FontFamily object in constructing a font, you can pass the font family name and size directly when you create a new Font object. The following code snippet creates three fonts from the Verdana, Arial, and Tahoma font families, respectively, with different sizes and styles:

 

// Construct Font objects Font verdanaFont = new Font( "Verdana", 12); Font arialFont = new Font( arialFamily, 10); Font tahomaFont = new Font( "Arial", 14, FontStyle.Underline|FontStyle.Italic);

 

Категории