Series 60 provides a wealth of functions for managing fonts and rendering text. Consequently, it is relatively straightforward to draw some simple text, and the following function, taken from the FontsAndText example, will perform such a task:
void CFontsAndTextBasicContainer::Draw(const TRect& aRect) const { // Obtain graphics context and clear it CWindowGc& gc = SystemGc(); gc.Clear(); // Set position of text relative to // the rectangle of the control TPoint textPoint(aRect.Width() / KHorizOffset, aRect.Height() / KVertOffset); // Use resource architecture to obtain localizable string TBuf<KTextMaxLength> text; StringLoader::Load(text, R_FONTSANDTEXT_LOCALIZATION_TEXT); // Gain handle to Normal font of the system const CFont* normalFont = iEikonEnv->NormalFont(); gc.UseFont(normalFont); gc.DrawText(text, textPoint); //Draw text gc.DiscardFont(); // Discard font }
Initially a handle to the system graphics context is acquired . It is cleared, and the point on the screen where the bottom left-hand corner of the text is to be placed is created. You then decide which font to use ”in this case the "Normal" font of the system. This represents an extremely simple way of getting access to a font, and a variety of similar system fonts will be discussed later in this section. Next, the font to be used by the graphics context must be explicitly set. The most important step follows with the call to the graphics context to draw the text. The first parameter is the text literal, and the second is the position of the text. Finally, the system is informed that the font in use is no longer required.
![]() | If a font type has not been set, the system will panic. However, this will not become evident until some time after the DrawText() function appears to have been called. This is because of the delay between function calls being made in code and the client-side buffer being dispatched to the Window Server. |
The display produced by the CFontsAndTextBasicContainer::Draw() function is shown in Figure 11-5.
In order to draw text with precision on the screen, you must have an appreciation of the character metrics and their roles and relationships with each other. These are highlighted in Figure 11-6 and Table 11-6.
This knowledge has practical applications, as there is an overloaded version of the CGraphicsContext::DrawText() function illustrated in the Metrics view of the FontsAndText example (Figure 11-7) that requires to be passed into it the text to be drawn, a rectangular area, the baseline of the text and a horizontal justification value.
Text can be drawn exactly in the center of a rectangle by calculating the baseline to be half the height of the rectangle (in this case it happens to be the rectangle of the screen, but potentially it could be any rectangular area), plus half the ascent of the font. The baseline is then passed into the DrawText() function.
[View full width]TInt baseline = (aRect.Height() / KBaselineDivider) + (titleFont>AscentInPixels() /KBaselineDivider); ... gc.DrawText(text, aRect, baseline, CGraphicsContext::ECenter);
Metric | Description |
---|---|
Baseline | Horizontal line on which text sits. |
Ascent | Distance above the baseline the font ascends. |
Descent | Distance below the baseline the font descends. |
Height | Distance between the ascent and the descent. |
Width | Horizontal distance occupied by a character. |
Left Adjust | Spacing distance before the character. |
Right Adjust | Spacing distance after the character. |
Move | The sum of the width, left adjust and right adjust. |
Numerous classes are provided for obtaining and using fonts. Interaction with fonts extends beyond just using them for drawing, and you need to communicate with the Font and Bitmap Server to derive information about the fonts available and ensure the fonts are used in as an efficient manner as possible. The key classes are listed in Table 11-7.
Class | Description |
---|---|
MGraphicsDeviceMap | Assists in mapping from real-world size perspective ”for example, from twips to ( device-based ) pixels. |
CTypefaceStore | Provides an abstract interface to the store of font typefaces . CFbsTypefaceStore is a concrete implementation of this and represents the typeface store of the Font and Bitmap Server. |
TTypefaceSupport | Provides essential information relating to a particular typeface, such as its name , its maximum and minimum heights, and whether it is scalable. |
TFontSpec | Specification of the font in terms of style, typeface and height. |
CFont | Provides an abstract interface to a font and has functions for obtaining baselines, ascents and text measuring. |
All of these classes are employed in the Device Fonts view of the FontsAndText example application, where the name of each font available is printed in that font, as shown in Figure 11-8.
In this example, the number of fonts present on the device is calculated, providing the counter limit for a loop to increment through the various fonts.
// Obtain the number of typefaces available // on this device. iNumTypefaces = iCoeEnv->ScreenDevice()->NumTypefaces(); ... TBuf<KMaxFontName> fontName; CFont* fontToUse; TRgb colorBlack = AKN_LAF_COLOR(KColorBlack); for (TInt i = iCurrentScrollNum; i < iNumTypefaces; i++) { // Get the i-th font on the device. iCoeEnv->ScreenDevice()->TypefaceSupport(*iTypefaceSupport, i); // Get the font name. fontName = iTypefaceSupport->iTypeface.iName.Des(); // Create font specification. TFontSpec fontSpec(fontName, KFontSpecSize); iDeviceMap->GetNearestFontInTwips(fontToUse,fontSpec); // Increment baseline to be 1.5 x height of font. textPoint.iY += (fontToUse->HeightInPixels() * KBaseLineIncrementer); // Use font with graphics context. gc.UseFont(fontToUse); gc.SetPenColor(colorBlack); gc.DrawText(fontName, textPoint); gc.DiscardFont(); iDeviceMap->ReleaseFont(fontToUse); }
Discarding and releasing the font are analogous. However, discarding is performed at the graphics context level, while releasing is performed by the screen device, completing the process of informing the Font and Bitmap Server that the application no longer requires the font. Forgetting to discard and release a font before an application exits will result in a panic. This panic is similar to a memory leak ”though in this case the term "resource leak" expresses the error more appropriately.
Another issue facing developers is that different Series 60 licensees can potentially provide different fonts as part of their customization of the platform. Consequently, fonts must be used in the most generic way possible ”via the application environment variable iEikonEnv . The following functions from the class CEikonEnv , found in \epoc32\include\eikenv.h in the root directory of your SDK, give access to device-independent fonts:
IMPORT_C const CFont* AnnotationFont() const; IMPORT_C const CFont* TitleFont() const; IMPORT_C const CFont* LegendFont() const; IMPORT_C const CFont* SymbolFont() const; IMPORT_C const CFont* DenseFont() const;
As mentioned earlier CCoeEnv provides the "Normal" font function ( NormalFont() ), and as CEikonEnv is derived from CCoeEnv , access is provided to this also. These functions are used in the FontsAndText example in the Effects view, as shown in the following code taken from CFontsAndTextEffectsContainer::Draw() :
... // Draw black vertical text in title font. const CFont* font = iEikonEnv->TitleFont(); TPoint textPoint(aRect.Width() / KLeftTextHorizAlign, aRect.Height() / KLeftTextVertAlign); gc.UseFont(font); gc.SetPenColor(KRgbBlack); gc.DrawTextVertical(text, textPoint, EFalse); gc.DiscardFont(); ...
A number of additional functions can be applied to change the appearance of text, ranging from rendering text with different colors, to changing the orientation of the text. Many of these are illustrated in the Effects view of the FontsAndText example application, as shown in Figure 11-9, and are graphics context functions.
Drawing text in different colors is simple to achieve ”the pen color of the graphics context is the color of the text to be drawn, and so code similar to the following should suffice in order to draw green text:
gc.SetPenColor(colorGreen);
Additionally, if underlined text and strikethrough are desired, the following functions will turn these effects either on or off:
gc.SetUnderlineStyle(EUnderlineOn); gc.SetStrikethroughStyle(EStrikethroughOn); gc.SetUnderlineStyle(EUnderlineOff); gc.SetStrikethroughStyle(EStrikethroughOff);
Text can also be drawn with a vertical orientation, in one of two ways: downward or upward. The DrawTextVertical() function performs this operation ”its third parameter is a Boolean value, which if set to false will draw the text downward, and if set to true will draw it upward:
// Draw text vertically downwards gc.DrawTextVertical(KHelloSeries60(), textPoint, EFalse); // Draw text vertically upwards gc.DrawTextVertical(KHelloSeries60(), textPoint, ETrue);