Fonts and Text


Text Output Functions

The operating system has quite a few functions for drawing text in a device context. The various text output functions are shown in the table below.

text_out Draws text at the current position or at a specified position.
tabbed_text_out Draws text with embedded tabs.
extended_text_out Draws text with inter-character spacings.
draw_text Draws text within a specified rectangle.
draw_text_extended Draws text within a specified rectangle (extended form).
gray_string Draws gray text with a callback.

The most commonly used of the text output functions is the first one in the table - text_out. The text alignment for a device context may be

When the text alignment flag text_alignment_flag::position_update is set, the current position is used and updated by a call to the function text_out.

Attributes that Affect Text

Apart from the current font (to be discussed shortly) attributes that affect the appearance of text are shown in the table below.

Attribute To Set To Get
text alignment set_text_alignment get_text_alignment
background mode set_background_mode get_background_mode
background color set_background_color get_background_color
text color set_text_color get_text_color
text character extra set_text_character_extra get_text_character_extra
text justification set_text_justification

Fonts

The function get_standard_object allows for the creation of the standard fonts found in the enumeration standard_font. Standard fonts include a font denoted by the identifier FontSystem. This font is a proportional font that is used in system menus, dialog boxes, message boxes and window title bars. Also amongst the standard fonts is standard_font::fixed_system. This is a fixed-pitch (monspaced) font. A fixed pitch font is a font in which all characters have equal width. A proportional font is a font in which individual characters vary in width.

When a new font has been selected, the function get_text_metrics may be used to ascertain the height and average character width of the font. For proportional fonts, the average character width is the average width of characters in the font - where individual characters vary in width. For a fixed-pitch font, characters do not vary in width so that the average character width is the width of each character in the font.

Types of Fonts

Windows supports two categories of fonts: graphics fonts and device fonts. Graphics fonts are stored on disk; whereas, device fonts are native to the associated output device. For example, printers have builtin device fonts (stored in read-only memory of the device).

Graphics fonts are either raster fonts, vector fonts or TrueType fonts. A raster font is a bitmap font where each character is stored as a bitmap in the font file. Raster fonts are designed for a particular size and aspect ratio. Raster fonts may be scaled by dropping rows or interpolating rows - but suffer from the same scalability problems as bitmaps.

Vector fonts are fonts where the glyphs of the fonts are defined using outlines consisting of a series of points. Vector fonts are scalable without loss of precision.

True Type Fonts

TrueType is an outline font technology that is supported by many font manufacturers. TrueType fonts are scalable, vector fonts that use 'hints' in the font file to facilitate improved scaling. The operating system scales TrueType by altering the coordinates that define the outlines. TrueType fonts are suitable for video displays and printers. True type fonts use a simplified Bezier spline algorithm to define the outlines.

When a program makes use of a TrueType font of a particular size, the font is rasterized at that size. The rasterized font is then cached for future use. Windows has 13 builtin TrueType fonts:

Courier is a fixed-pitch font that emulates the output of a typewriter. Times New Roman is a clone of the Times font, which was originally designed for the newpaper Times of London. Arial is a clone of the font Helvetica - which is a sans serif font. A sans serif font is a font without the small turns placed at the end of font strokes.

Traditionally, a font is specified by its type face name and its size. The size of a font is measured in points, where a point is 1/72 of an inch. Usually, the type face size is measured from the top of the ascenders to the bottom of the descenders.

Easy Fonts

To gain experience with font selection, an example of such is given via defining a 'simplified' font selection mechanism. The simplified mechanism will be referred to as 'easy font' selection. This sample demonstrates how to select a TrueType font with minimal overhead in a manner consistent with traditional typography. To select a font, the name of the font, its dimensions and its attributes will be supplied. The supported font attributes are shown in the enumeration below.

struct easy_attribute
{
 enum
 {
  bold      = 1,
  italic    = 2,
  underline = 4,
  strikeout = 8
 };
};

The declaration of the new font function is shown below.

handle easy_create_font(handle device_context,
                        const character* face_name,
                        int height,
                        int width,
                        int attributes,
                        bool logical_resolution);

See also the full source code listing. The value returned is the handle of the newly created font. Once returned, the font may be selected into a device context; where, its actual dimensions may be queried via function get_text_metrics or get_outline_text_metrics. The parameter face_name (above) indicates the type face name of one of the installed TrueType fonts. The parameter height specifies the height of the font in units of 1/10 of a point. Usually, the third parameter is set to zero or set to be equal to the height parameter; however, a TrueType font with a wider or narrower size may be created by setting this parameter to a different value. The parameter Width is the 'em-width' of the font and it specifies the width of the font in points. In typography, the letter 'M' is as wide as it is high - hence the term 'em-square' came into being. When the em width is equal to the em height (that is, the point size of the font) the character widths are as the font designer intended.

The function easy_create_font creates an instance of the class logical_font, sets its members, then calls the function create_font_indirect.

One task of the function is to convert the specified point size into logical units so that it may be supplied in the correct form in the class logical_font. This is done differently depending upon the specified value of the parameter logical_resolution. In either case, the function get_device_capabilities is used as shown in the source code listing. Ultimately, the dimensions of the font are converted from device units to logical units via the statements shown below.

 point point_font(width  * horizontal_resolution/72,
                  height * vertical_resolution/72);

 device_points_to_logical_points(device_context,&point_font,1);

The logical font structure is then initialized using the code shown below:

 logical_font font_information;

 font_information.height     = - (int)(fabs((double)point_font(1))/10.0 + 0.5);
 font_information.weight     = attributes & easy_attribute::bold      ? 700 : 0;
 font_information.italic     = attributes & easy_attribute::italic    ?   1 : 0;
 font_information.underline  = attributes & easy_attribute::underline ?   1 : 0;
 font_information.strikeout  = attributes & easy_attribute::strikeout ?   1 : 0;

 copy_string(font_information.face_name,face_name);

after which, a font is created using the statement shown below.

handle font_handle = create_font_indirect(&font_information);