Using BFont

A BFont object records a set of font attributes, such as the font's family, style, size, and so on. You can set most of these attributes to modify the font and then use the object to set the font of a BView. A BView's font determines how the characters that it draws (with the DrawString() and DrawChar() functions) will be rendered.

A BFont object can perform calculations based on the metrics of the particular font it represents. For example, it can tell you how much screen real estate it needs to display a given line of text.

To find which fonts are currently installed on the system, call get_font_family() and get_font_style().

Using a BFont Object

A BFont object by itself doesn't do anything. To be able to draw characters in the font, the object must be passed to BView's SetFont() function (or BTextView's SetFontAndColor()).
A BFont object is always a full representation of a font; all attributes are always set. However, you can choose which of these attributes will modify a BView's current font by passing a mask to SetFont() (or SetFontAndColor()). For example, this code sets only the font shear and spacing:
 BFont font; 
 font.SetShear(60.0); 
 font.SetSpacing(B_CHAR_SPACING); 
 myView->SetFont(&font, B_FONT_SHEAR | B_FONT_SPACING);
Alternatively, the BView's font could have been modified and reset as follows:
 BFont font; 
 myView->GetFont(&font); 
 font.SetShear(60.0); 
 font.SetSpacing(B_CHAR_SPACING); 
 myView->SetFont(&font);
Notice that we had to explicitly reset the view's font (through SetFont()) after changing the font's attributes.

System Fonts

The Interface Kit constructs three BFont objects (plain, bold, and fixed)for each application when the application starts up. The values of these fonts are set by the user through the FontPanel preferences application. You can get to these objects through global pointers :
const BFont * be_plain_font
The font that's used to display most gadgets in the user interface, such as check box labels and menu items. All BControl objects use this font.
const BFont * be_bold_font
The font that's used to display window titles and BBox labels.

const BFont * be_fixed_font
The font that's used to display fixed-width characters.

The global fonts are const objects that can't be modified by your application, and aren't updated by the system, even if the user changes their definitions while your app is running. The new values take effect the next time your application is launched.
To use a system font in a view, simply call SetFont():
 myView->SetFont(be_bold_font);
If you want to modify some attributes of a system font, you have to make a copy of it first (and modify the copy):
 BFont font(be_bold_font); 
 font.SetSize(13.0); 
 myView->SetFont(&font);
Applications should respect the user's choices and base all font choices on these three system fonts, rather than hard-code font names into the application. You should not try to predict the fonts that will be installed on the user's machine.

Escapements

A character's escapement measures the amount of horizontal space it requires. It includes the space needed to display the character itself, plus some extra room on the left and right edges to separate the character from its neighbors. The illustration below shows the approximate escapements for the letters 'l' and 'p'; the escapement for each character is the distance between the vertical lines:
font1.png

GetEscapements() measures the same space that functions such as StringWidth() and BTextView's LineWidth() do, but it measures each character individually and records its width in per-point-size escapement units. To translate the escapement value to the width of the character, you must multiply by the point size of the font:
 float width = escapementArray[i] * font.Size();
Because of rounding errors, there may be some difference between the value returned by StringWidth() and the width calculated from the individual escapements of the characters in the string.
The versions of GetEscapements() that use BPoints for the escapement value use the BPoint escapementArray to indicate a vector by which the pen is moved after drawing a character (this lets the escapement indicate both an X and a Y adjustment; the Y might need to be adjusted if the font is rotated, for example). The offsetArray is applied by the dynamic spacing in order to improve the relative position of the character's width with relation to another character, without altering the width.
The escapement value is scalable if the spacing mode of the font is B_CHAR_SPACING. In other words, given B_CHAR_SPACING and the same set of font characteristics, GetEscapements() will report the same measurement for a character regardless of the font size. You can cache one value per character and use it for all font sizes. For the other spacing modes, the reported escapement depends on the font size and therefore can't be scaled.
For most spacing modes, a character has a constant escapement in all contexts; it depends only on the font. However, for B_STRING_SPACING, each character's escapement is also contextually dependent on the string it's in. To find the escapement of a character within a particular string, you must pass the entire string in the input charArray.
In the B_BITMAP_SPACING and B_FIXED_SPACING modes, all characters have integral widths (without a fractional part). For these modes, multiplying an escapement by the font size should yield an integral value. In B_FIXED_SPACING mode, all characters have the same escapement.
if a delta argument is provided, GetEscapements() will adjust the escapements it reports so that, after multiplying by the font size, the character widths will include the specified increments. An escapement_delta structure contains two values:
float nonspace
The amount to add to the width of each character with a visible glyph.
float space
The amount to add to each whitespace character (characters like B_TAB and B_SPACE with an escapement but no visible glyph).
A similar argument can be passed to BView's DrawString() to adjust the spacing of the characters as they're drawn.

Edges

Edge values measure how far a character outline is inset from its left and right escapement boundaries. GetEdges() places the edge values into an array of edge_info structures. Each structure has a left and a right data member, as follows:
 typedef struct
 { 
    float left;
    float right;
 } edge_info
Edge values, like escapements, are stated in per-point-size units that need to be multiplied by the font size.
The illustration below shows typical character edges. As in the illustration above, the solid vertical lines mark escapement boundaries. The dotted lines mark off the part of each escapement that's an edge, the distance between the character outline and the escapement boundary:
This is the normal case. The left edge is a positive value measured rightward from the left escapement boundary. The right edge is a negative value measured leftward from the right escapement boundary.
However, if the characters of a font overlap, the left edge can be a negative value and the right edge can be positive. This is illustrated below:
Note that the italic 'l' extends beyond its escapement to the right, and that the 'p' begins before its escapement to the left. In this case, instead of separating the adjacent characters, the edges determine how much they overlap.
Edge values are specific to each character and depend on nothing but the character and the font. They don't take into account any contextual information; for example, the right edge for italic 'l' would be the same no matter what letter followed. Edge values therefore aren't sufficient to decide how character pairs can be kerned. Kerning is contextually dependent on the combination of two particular characters.
See also:
StringWidth(), SetSpacing()

Spacing Modes

There are four spacing modes:
B_CHAR_SPACING
Positions each character according to its own inherent width, without adjustment. This produces good results on high-resolution devices like printers, and is the best mode to use for printing. However, when character widths are rounded for the screen, the results are generally poor. Characters are not well-separated and can collide or overlap at small font sizes.
B_STRING_SPACING
Keeps the string at the same width as it would have for B_CHAR_SPACING, but optimizes the position of each character within that space. The position of a character depends on the surrounding characters and the overall width of the string. Collisions are unlikely in this mode, but because the width of the string constrains what can be done, characters may touch each other.
This mode is preferred when it's important to have the screen match the printed page - for example, to have lines break on-screen where they will break when the display is printed. As the user types new characters into a line of text, the application must redraw the entire line to add each character. The characters in the line may therefore appear to "jiggle" or jump around as new ones are added. New optimal positions are calculated for each character as the width and composition of the string changes.
B_BITMAP_SPACING
Calculates the width of each character according to its bitmap appearance on- screen. The widths are chosen for optimal spacing, so that characters never collide and rarely touch. This mode increases the B_CHAR_SPACING width of a string if necessary to keep characters separated. (For a small-sized bold font, it may increase the string width substantially.)
In this mode, the spacing between characters is regular and not contextually dependent. Character widths are integral values. This is the best mode for drawing small amounts of text in the user interface; it's the mode that BTextView objects use and it works for both proportional and fixed-width fonts. However, the spacing of text shown on-screen won't correspond to the spacing when the text is printed in B_CHAR_SPACING mode.
B_FIXED_SPACING
Positions characters according to a constant, integral width. This mode can only be used with fixed-width fonts (fonts with the B_IS_FIXED flag set); trying to use B_FIXED_SPACING on other fonts will result in B_CHAR_SPACING being used by default. All characters have the same escapement.
The B_CHAR_SPACING mode is the preferred mode for printing. It's also somewhat faster than B_STRING_SPACING or B_BITMAP_SPACING. In all modes other than B_STRING_SPACING, it's possible to change the character displayed at the end of a string by erasing it and drawing a new character. However, in B_STRING_SPACING mode, it's necessary to erase the entire string and redraw it. The longer the string, the better the results.

The B_STRING_SPACING and B_BITMAP_SPACING modes are relevant only for font sizes in a range of about 7.0 points to 18.0 points. Above that range, B_CHAR_SPACING achieves reasonable results on-screen and may be used even where one of the other two modes is specified. Below that range, the screen resolution isn't great enough for the different modes to produce significantly different results, so again B_CHAR_SPACING is used.
In addition, B_CHAR_SPACING is always used for rotated or sheared text and when antialiasing is disabled.

See also:
BView::DrawString(), GetEscapements()

Copyright 2005 by yellowTAB GmbH, Be Inc., Palm Source Inc. and their respective legal successors
All rights reserved.