The sample code for this chapter includes a program called Sunset, which arranges the word Sunset on a semi-circle. As each glyph is drawn, it is also used as a clipping path, and a shaded background is drawn inside the clipped path. The output of the program is shown in Figure 11.4. Figure 11.4. The Output of the Sunset Sample
For this sample, ATSUI is used to convert the characters into glyphs and typeset those glyphs along a line. Instead of drawing the glyphs as ATSUI has arranged them, however, the code will use Quartz 2D to arrange and draw the glyphs in a context. The sample code contains the complete code for the Sunset sample, two routines are examined here. The first is the routine that extracts glyph information from the ATSUI layout. The second is the routine that arranges and draws the glyphs on the context. Listing 11.1 is the routine that extracts glyph information from ATSUI. Listing 11.1. Obtaining Glyphs for the Sunset Sample
This code sample creates an ATSUI text layout that contains the string "Sunset" and stores that layout in the global gTextLayout where it can be used repeatedly. The code treats the text as a single, long line. The first thing this routine does is measure the width of the text. The width returned is the width of the drawn glyphs as they would appear before the computer applies justification (e.g., center justification) to them. We will use this width to space the glyphs in their corresponding positions on an arc that subtends 180 degrees. After measuring the text, the computer needs to get the positions and glyph IDs of each glyph that ATSUI has typeset. It calls ATSUGetGlyphInfo twiceonce to figure out how much data the routine will return and once to retrieve the data itself. ATSUGetGlyphInfo returns a lot of information about the layout of text. The only information being used here is the positions of the glyphs on a line. After getting the glyphs, the code loops over each glyph and uses the glyph's position and the width of the layout to determine the position of each glyph on the arc. The code records the glyph positioning information in a global array. A more complete program would probably allocate this array dynamically rather than using a fixed-size, statically allocated data structure. After recording the drawing information, the computer needs to draw that information in a context. The routine that draws the glyph info is given in Listing 11.2. Listing 11.2. Drawing the Sunset Sample
After creating the text layout that will arrange the text, this code needs to set the font attributes of the context. To create a CGFont, the computer needs an ATSFontRef and obtains it by converting the ATSUFontID used by the ATSUI layout. After setting the font and size of the context, the code sets the text drawing mode to kCGTextStrokeClip. As mentioned earlier, this means that when you draw text it will be outlined with a stroke but also added to the clipping region of the context. You then enter a loop that iterates over the glyph drawing information you've calculated. This code rotates the y axis of the context to the angle calculated for the particular glyph you are drawing and draws the glyph centered on the y axis. As the computer draws each glyph, it fills in the clipping area inside each with the background pattern. For our sample, the background image is drawn using a short chain of Core Image filters that give a pleasing gradient effect. This sample shows one simple example of using Quartz to create a complex text effect. For mundane text drawing needs, your application should rely on ATSUI, Cocoa Text, or similar high-level text technologies. These technologies insulate you from a lot of complex processing that the computer must do when rendering text. However, if you are willing to work more intimately within the complexities of the text rendering process, the low-level text drawing routines in Quartz 2D can be very effective tools. |