< Previous PageNext Page > Hide TOC

Text

This chapter describes the basic text support provided by Quartz and shows how to use Quartz 2D text in your application. Quartz 2D provides a limited, low-level interface for drawing text encoded in the MacRoman text encoding and for drawing glyphs. (See CGFont Reference.) If basic text support is all your application needs, then read this chapter. If you want to support user input of text, text editing, or you need precise control over text layout or access to font features, you may want to skip this chapter and instead read Getting Started with Text and Fonts and then investigate using one of the following:

In this section:

How Quartz 2D Draws Text
Controlling How Text Looks
Drawing Text
Measuring Text Before Drawing
Copying Font Variations
PostScript Fonts
See Also


How Quartz 2D Draws Text

Quartz 2D uses fonts, which are sets of shapes that are associated with characters, to draw text. A character abstractly represents the concept of, for example, a lowercase “b”, the number “2”, or the arithmetic operation “+”. You do not ever see a character on a display device. What you see on a display device is a glyph, the path that serves as the visual representation of the character. One glyph can represent one character, such as a lowercase “b”; more than one character, such as the “fi” ligature, which is a single glyph representing two characters; or a non printing character, such as the space character.

The mapping from a byte code (sometimes called a character code) to a specific character is specified by a text encoding. For example, you use the numeric byte code value 65 to specify an uppercase “A” from a font encoded using the ASCII text encoding.

When you want to print or display text, you generally refer to characters rather than glyphs. Quartz renders glyphs using font data provided by the Apple Type Services (ATS) framework.

You specify the location of text in user space coordinates. The text matrix specifies the transform from text space to user space. The text position is stored in the tx and ty variables of the text matrix. When you first create a graphics context, it initializes the text matrix to the identity matrix, thus text space coordinates are initially the same as user space coordinates.

Quartz conceptually concatenates the text matrix with the current transformation matrix and other parameters from the graphics state to produce the final text rendering matrix, the matrix actually used to draw the text on the page. The text matrix does not include the font size, which is always expressed in text space.

When Quartz draws the text, it retrieves the relevant glyphs from the ATS font server and paints them using the current parameters in the graphics state, such as fill color (if the text is filled) and stroke color. After a drawing operation, the text position remains at the last point used to image the text.

Controlling How Text Looks

Some of the settings in the graphics state that apply to painting paths also apply to text drawing. Stroke color and fill color are two such attributes. (See “Paths”) for other attributes and operations that affect text rendering.)

Several text drawing attributes apply only to text. You can set the values of these attributes using the Quartz functions listed in Table 17-1. Notice that the function CGContextSelectFont sets both the font and the font size. It also sets the text encoding. “Drawing Text” discusses the difference between using CGContextSelectFont and CGContextSetFont.

Table 17-1  Text attributes and the functions that control them

Attribute

Function

Specifies

Font

CGContextSetFont

CGContextSelectFont

Typeface.

Font size

CGContextSetFontSize

CGContextSelectFont

Size in text space units.

Character spacing

CGContextSetCharacterSpacing

The amount of extra space (in text space units) between character glyphs.

Text drawing mode

CGContextSetTextDrawingMode

How Quartz renders the individual glyphs onscreen. See Table 17-2 for a list of text drawing modes.

Text matrix

CGContextSetTextMatrix

The transform from text space to user space.

Text position

CGContextSetTextPosition

The location at which text is drawn.

The text matrix is a transform that operates similarly to the current transformation matrix (CTM), but only on text. You can apply transforms to the text matrix, using any of the affine transform functions to build as complex a transform as you’d like. When you draw the text, Quartz uses the text matrix you supply along with the CTM. When you draw anything other than text, Quartz uses the CTM and not the text matrix.

Table 17-2  Text drawing modes

Use this mode

When you want to . . .

Example

kCGTextFill

Perform a fill operation on the text.

Filled text

kCGTextStroke

Perform a stroke operation on the text.

Stroked text.

kCGTextFillStroke

Perform both fill and stroke operations on the text.

Filled and stroked test.

kCGTextInvisible

Get text positions for the purpose of measuring text but not display the text. Note that the text position (x, y) is updated, as with all of the drawing modes.

Invisible text.

kCGTextFillClip

Perform a fill operation, then add the text to the clipping area.

Filled text added to the clipping area.

kCGTextStrokeClip

Perform a stroke operation, then add the text to the clipping area.

Stroked text, added to the clipping area

kCGTextFillStrokeClip

Perform both fill and stroke operations, then add the text to the clipping area.

Filled and stroked text, aded to the clipping area

kCGTextClip

Add the text to the clipping area, but do not draw the text.

Test added to the clipping area, but not drawn

Drawing Text

When you use Quartz 2D to draw text, you need to perform these tasks:

Quartz 2D provides two ways to set the font and font size. You can call either the function CGContextSelectFont or the functions CGContextSetFont and CGContextSetFontSize. If your requirements are simple, you’ll probably want to use CGContextSelectFont. If your requirements are more complex, you can use the alternative functions, CGContextSetFont and CGContextSetFontSize. But instead of using CGContextSetFont and CGContextSetFontSize, you may instead want to use ATSUI or Cocoa to set the font and perform text drawing. That’s because Quartz has some limitations for drawing text. Here’s a closer look at the two Quartz 2D alternatives.

If setting the font to a MacRoman text encoding is sufficient for your application, use the CGContextSelectFont function. Then, when you are ready to draw the text, you call the function CGContextShowTextAtPoint. The function CGContextSelectFont takes as parameters a graphics context, the PostScript name of the font to set, the size of the font (in user space units), and a text encoding.

To set the font to a text encoding other than MacRoman, you can use the functions CGContextSetFont and CGContextSetFontSize. You must supply a CGFont object to the function CGContextSetFont. You call the function CGFontCreateWithPlatformFont to obtain a CGFont object from an ATS font. When you are ready to draw the text, you use the function CGContextShowGlyphsAtPoint rather than CGContextShowTextAtPoint.

The reason you cannot use CGContextShowTextAtPoint when you use CGContextSetFont is that Quartz needs a text encoding to map the bytes in the text string to glyphs in the font. By default, the text encoding is kCGEncodingFontSpecific, so there's no guarantee of what you'll get when you call CGContextShowTextAtPoint. Since there's no way to set the text encoding other than with a call to CGContextSelectFont you cannot draw text using CGContextShowTextAtPoint if you set the font with CGContextSetFont. If you set the font this way, you must also be prepared to use ATSUI, Cocoa, or your own code to map character strings to glyphs so that you can then call CGContextShowGlyphsAtPoint. It might be easier for you to simply use ATSUI or Cocoa to perform the text drawing, and not use any of the Quartz 2D functions.

Now that you understand some of the limitations of using Quartz to draw text, you can take a look some sample code that draws text when the font and font size are set using the function CGContextSelectFont. This function, although not recommended except for cases in which MacRoman encoding is sufficient, is fairly straightforward to use. Listing 17-1 shows a function—MyDrawText—that draws the text shown in Figure 17-1. A detailed explanation for each numbered line of code appears following the listing.

Listing 17-1  Drawing text

void MyDrawText (CGContextRef myContext, CGRect contextRect) // 1
{
    float w, h;
    w = contextRect.size.width;
    h = contextRect.size.height;
 
    CGAffineTransform myTextTransform; // 2
    CGContextSelectFont (myContext, // 3
                    "Times-Bold",
                     h/10,
                     kCGEncodingMacRoman);
    CGContextSetCharacterSpacing (myContext, 10); // 4
    CGContextSetTextDrawingMode (myContext, kCGTextFillStroke); // 5
 
    CGContextSetRGBFillColor (myContext, 0, 1, 0, .5); // 6
    CGContextSetRGBStrokeColor (myContext, 0, 0, 1, 1); // 7
    myTextTransform =  CGAffineTransformMakeRotation  (MyRadians (45)); // 8
    CGContextSetTextMatrix (myContext, myTextTransform); // 9
    CGContextShowTextAtPoint (myContext, 40, 0, "Quartz 2D", 9); // 10
}

Here’s what the code does:

  1. Takes as parameters a graphics context and a rectangle to draw to.

  2. Declares storage for the affine transform.

  3. Sets the font to Times Bold and the font size to the height of the page rectangle divided by 10. The font size is in text space units. In this example, the text is drawn to a resizable window. When the user resizes the window, the text resizes as well. The encoding is set to kCGEncodingMacRoman, but the only other choice is kCGEncodingFontSpecific.

  4. Sets the character spacing to 10 text space units. You call this function only if you want to add the additional space to the advance between the origin of one glyph and the origin of the next glyph.

  5. Sets the text drawing mode to fill and stroke.

  6. Sets the fill color to green with an alpha value of .5 for a partially transparent fill. Note that this is not a text-specific attribute. The fill color applies to the graphics state.

  7. Sets the stroke color to opaque blue. This is another attribute that is not text specific.

  8. Creates an affine transform that performs a 45 degree rotation. The MyRadians routine is an application-defined convenience function for computing degrees from radians. You either need to supply your own routine to convert degrees to radians, or you need to substitute this call with a value that specifies radians. Otherwise, this code example will not compile.

  9. Sets the text matrix to the transform created in the last step.

  10. Draws the text, passing the x- and y-coordinates in text space to start the drawing (40, 0), an array of characters to draw, and a value that specifies the length of the text array. In this case, you pass a C-style string and the value 9 to specify the number of characters.


Figure 17-1  Text drawn using Quartz 2D functions

Text drawn using Quartz 2D functions

Measuring Text Before Drawing

If text measurements are important to your application, it is possible to calculate them using Quartz 2D functions. However, you might first consider using ATSUI, whose strength is in text layout and measurement. ATSUI has several functions that obtain text metrics. Not only can you obtain after-layout text metrics, but in the rare cases you need them, you can obtain before-layout text metrics. Unlike Quartz, for which you must perform the calculations yourself, ATSUI computes the measurements for you. For example, you can obtain the image bounding rectangle for text by calling the ATSUI function ATSUMeasureTextImage.

If you decide that Quartz text suits your needs better than ATSUI (or Cocoa), you can follow these steps to measure the width of text before Quartz draws it:

  1. Call the function CGContextGetTextPosition to obtain the current text position.

  2. Set the text drawing mode to kCGTextInvisible using the function CGContextSetTextDrawingMode.

  3. Draw the text by calling the function CGContextShowText to draw the text at the current text position.

  4. Determine the final text position by calling the function CGContextGetTextPosition.

  5. Subtract the starting position from the ending position to determine the width of the text.

Copying Font Variations

A font variation is a setting along a variation axis that allows your application to produce a range of typestyles algorithmically. Each variation axis has:

The weight axis, for example, governs the possible values for the weight of the font—the minimum value produces the lightest appearance of that font, the maximum value the boldest. The default value is the position along the variation axis at which that font falls normally. Because the axis is created by the font designer, font variations can be optimized for their particular font. Not all fonts have variations.

Quartz provides three functions in Mac OS X v10.4 that let you work with font variations:

PostScript Fonts

Quartz provides several functions in Mac OS X v10.4 that support PostScript and allow you to:

If you need to work with PostScript fonts, see CGFont Reference for detailed information on the Quartz functions for PostScript.

See Also



< Previous PageNext Page > Hide TOC


© 2001, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-12-11)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.