Core Text Programming Guide
Core Text Programming Guide
Contents
Introduction 4
Organization of This Document 4 See Also 4
Common Operations 15
Simple Paragraphs 15 Simple Text Labels 16 Columnar Layout 17 Manual Line Breaking 20 Font Creation and Storage 21 Accessing Font Metrics 25 Creating Related Fonts 27
Common Operations 15
Listing 2-1 Listing 2-2 Listing 2-3 Listing 2-4 Listing 2-5 Listing 2-6 Listing 2-7 Listing 2-8 Listing 2-9 Listing 2-10 Listing 2-11 Listing 2-12 Listing 2-13 Typesetting a simple paragraph 15 Typesetting a simple text label 17 Performing columnar text layout 18 Performing manual line breaking 20 Creating a font descriptor from a name and point size 21 Creating a font descriptor from a family and traits 21 Creating a font from a font descriptor 23 Serializing a font 23 Creating a font from serialized data 24 Calculating line height 26 Getting glyphs for characters 26 Changing traits of a font 27 Converting a font to another family 28
Introduction
Core Text is an advanced, low-level technology for laying out text and handling fonts. It is designed for high performance and ease of use. The Core Text API, introduced in Mac OS X v10.5, is accessible from all Mac OS X application environments. It is also available in iOS 3.2. The Core Text layout engine is designed specifically to make simple text layout operations easy to do and to avoid side effects. The Core Text font programming interface is complementary to the Core Text layout engine and is designed to handle Unicode fonts natively, unifying disparate Mac OS X font facilities into a single comprehensive programming interface. This document is intended for developers who need to do text layout and font handling at a low level. If you can develop your application using higher-level constructs, such as NSTextView, then you should use the Cocoa text system, introduced in Text System Overview . If, on the other hand, you need to render text directly into a Core Graphics context, then you should use Core Text. More information about the position of Core Text among other Mac OS X text technologies is presented in Mac OS X Text Technologies (page 6). Important This document has not been updated to address the use of Core Text in iOS 3.2.
See Also
In addition to this document, there are several that cover more specific aspects of Core Text or describe the software services used by Core Text.
Core Text Reference Collection provides complete reference information for the Core Text layout and font API. CoreTextTest is a sample code project that shows how to use Core Text in the context of a complete Carbon application. CoreTextArcCocoa is a sample code project that illustrates the use of fonts, lines, and runs in a Core Text Cocoa application. Core Foundation Design Concepts and Core Foundation Framework Reference describe Core Foundation, a framework that provides abstractions for common data types and fundamental software services used by Core Text.
The following documents provide entry points to the documentation describing the Cocoa text system.
Text System Overview gives an introduction to the Cocoa text system. Text Layout Programming Guide describes the Cocoa text layout engine.
The Core Text framework is an advanced, low-level technology for laying out text and handling fonts. Designed for high performance and ease of use, the Core Text layout engine is up to twice as fast as ATSUI (Apple Type Services for Unicode Imaging). The Core Text layout API is simple, consistent, and tightly integrated with Core Foundation, Core Graphics, and Cocoa. The Core Text font API is complementary to the Core Text layout engine. Core Text font technology is designed to handle Unicode fonts natively, bridging the gap between Carbon and Cocoa font references, and providing efficient font handling for Core Text layout. Core Text brings the capabilities and coherent design of Cocoa text and fonts to a broader, lower-level client base.
If you can, use Cocoa text. The NSTextView class is the most advanced, full-featured, flexible text view in Mac OS X. For small amounts of text, use NSTextField. To display web content in your application, use Web Kit. If you need to use Carbon only, consider using NSTextView with HICocoaView.
If you need a lower-level API for drawing any kind of text into a Quartz graphics context (CGContext), consider using Core Text directly.
Generally speaking, Core Text is for applications that need a low-level text-handling technology correlating with the Core Graphics framework (Quartz). If you work directly with Quartz and you need to draw some text, use Core Text. If, for example, you have your own page layout engineyou have some text and you know where it needs to go in your viewyou can use Core Text to generate the glyphs and position them relative to each other with all the features of fine typesetting, such as kerning, ligatures, line-breaking, and justification.
A comprehensive, unified set of text-layout and font APIs High performance and ease of use Tight integration with Cocoa, Core Foundation, and Core Graphics (Quartz) Native Unicode handling 64-bit application support Clean, simple, consistent API design Simple interfaces for simple operations A flexible interface to layout and glyph data A predictable cost structure and rational division of labor
A primary design goal of Core Text layout is to make simple things easy to do. So, for example, if you want to draw a paragraph of text or a simple text label on the screen, you dont need much code. A corollary principle of the Core Text design is that clients are not required to pay for features they dont use. The objects defined by Core Text opaque types provide a progression from simplicity to complexity, in terms of their use and interface. That is, higher-level objects do more for you, and so they are easier to use (although they may be more complex internally). For example, the highest-level object in Core Text is the framesetter, which fills a path (defined by a CGPath object representing a rectangle) with text. The framesetter object uses other Core Text objects, such as typesetter, line, and glyph run objects, to accomplish its work: creating frame objects, which are lines of glyphs laid out within a shape. Clients who simply need to lay out a paragraph need only work with the framesetter. Clients who need to intervene in the text layout process at a lower level can deal with lower level objects, such as line objects. Line objects can draw themselves individually or be used to obtain glyph information. With Core Text you use the highest-level object you can to get your job done.
Moreover, the correspondence between characters and glyphs is not one to one, and the context within which a character appears can affect the glyph chosen to represent it. For example, in many fonts an f and l appearing side-by-side in a character string are replaced by a ligature, which is a single glyph depicting the letters joined together. Figure 1-2 shows two examples of individual characters and the single-glyph ligatures often used when they are adjacent. Character-to-glyph conversion is a complex and difficult task that Core Text performs quickly and efficiently.
Figure 1-2 Ligatures
+ +
= =
Layout Objects
Layout objects make up the Core Text layout engine. This section discusses the primary layout objects: framesetter, frame, typesetter, line, and glyph run objects. In addition this section briefly discusses the other Core Text layout objects: paragraph styles, text tabs, and glyph info objects.
CFAttributedString
CTTypesetter
CGPath
The framesetter applies paragraph styles to the frame text as it is laid out. Paragraph styles are represented in Core Text by objects storing attributes that affect paragraph layout. Among these attributes are alignment, tab stops, writing direction, line-breaking mode, and indentation settings.
10
Its advantageous to use the framesetter to perform the common operation of typesetting a multiline paragraph because it handles all of the details of producing frames, instantiating other objects, such as the typesetter, as needed. The CTFramesetter opaque type provides functions to create a framesetter with an attributed string, to create frame objects, and to return its typesetter. As with all Core Text objects, CTFramesetter can also return its Core Foundation type identifier.
Typesetters
A typesetter performs the fundamental text layout operations of character-to-glyph conversion and positioning of those glyphs into lines. That is, it determines which glyphs to use and where to place them relative to each other, producing line objects. Typesetters are represented by the CTTypesetter opaque type. The typesetter also suggests line breaks. It finds how many glyphs can fit within a single line within a given space. It then determines the length of the line by using word breaks, word wrapping, or finer-grained cluster breaks. Simple word wrapping is the default method of creating line breaks. The framesetter instantiates a typesetter and uses it to create the line objects used to fill a frame. You can also use a typesetter directly, as described in Manual Line Breaking (page 20).
11
runs. Glyph runs can draw themselves into a graphic context, if desired, although most clients have no need to interact directly with glyph runs. Figure 1-4 shows the conceptual hierarchy of a frame object containing line objects that, in turn, contain glyph-run objects.
Figure 1-4 A frame object containing lines and glyph runs
CTRun CTLine
CTFrame
CTLine has a convenience method for creating a freestanding line independent of a frame, CTLineCreateWithAttributedString. You can use this method to create a line object directly from an attributed string without needing to create and manage a typesetter. Without a typesetter, however, theres no way to calculate line breaks, so this method is meant for a single line only (for example, creating a text label). After you have a line object, you can do a number of things with it. For example, you can have the line create a justified or truncated copy of itself, and you can ask the line for pen offsets for various degrees of flushness. You can use these pen offsets to draw the line with left, right, or centered alignments. You can also ask the line for measurements, such as its image bounds and typographic bounds. Image bounds represent the rectangle tightly enclosing the graphic shapes of the glyphs actually appearing in the line. Typographic bounds include the height of the ascenders in the font and the depth of its descenders, regardless of whether those features appear in the glyphs in a given line. Like a frame object, a line object is ready to draw. You simply set the text position in a Core Graphics context and have the line draw itself. Core Text uses the same placement strategy as Quartz, setting the origin of the text on the text baseline. In Quartz, 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, that is, the matrix actually used to draw the text on the page.
12
Font Objects
Font objects are those Core Text objects dealing directly with fonts: the font reference itself, font descriptor objects, and font collection objects.
Fonts
Fonts provide assistance in laying out glyphs relative to one another and are used to establish the current font when drawing in a graphics context. The Core Text font opaque type (CTFont) is a specific font instance that encapsulates a lot of information. Its reference type, CTFontRef, is toll-free bridged with NSFont. When you create a CTFont object, you typically specify (or use a default) point size and transformation matrix, which gives the font instance specific characteristics. You can then query the font object for many kinds of information about the font at that particular point size, such as character-to-glyph mapping, encodings, font metric data, and glyph data, among other things. Font metrics are parameters such as ascent, descent, leading, cap height, x-height, and so on. Glyph data includes parameters such as bounding rectangles and glyph advances. There are many ways to create font references. The preferred method is from a font descriptor using CTFontCreateWithFontDescriptor. You can also use a number of conversion APIs, depending on what you have to start with. For example, you can use the PostScript name of the typeface (CTFontCreateWithName), an ATS font reference (CTFontCreateWithPlatformFont), a Core Graphics font reference (CTFontCreateWithGraphicsFont), or a QuickDraw font reference (CTFontCreateWithQuickdrawInstance). Theres also CTFontCreateUIFontForLanguage, which creates a reference for the user-interface font for the application youre using in the localization youre using. Core Text font references provide a sophisticated, automatic font-substitution mechanism called font cascading. This mechanism takes font traits into account, so it does a better job than previous schemes of picking an appropriate font to substitute for a missing font. Font cascading is based on cascade lists, which are arrays of ordered font descriptors. There is a system default cascade list (which is polymorphic, based on the user's language setting and current font) and a font cascade list that is specified at font creation time. Using the
13
information in the font descriptors, the cascading mechanism can match fonts according to style as well as matching characters. The CTFontCreateForString function uses cascade lists to pick an appropriate font to encode a given string. You specify and retrieve font cascade lists using the kCTFontCascadeListAttribute property.
Font Descriptors
Font descriptors, represented by the CTFontDescriptor opaque type, provide a mechanism to describe a font completely with a dictionary of attributes. CTFontDescriptorRef is toll-free bridged to NSFontDescriptor. The attributes are properties such as PostScript name, family, and style, and traits such as bold, italic, and monospace. The font descriptor can then be used to create or modify a CTFont object. Font descriptors can be serialized and stored in a document to provide persistence for fonts. Figure 1-5 illustrates the font system using a font descriptor to create a specific font instance.
Figure 1-5 Creating a font from a font descriptor
CTFont Font System
CTFontDescriptor
A font descriptor can also be considered as a query into the font system. You can create a font descriptor with an incomplete specification, that is, with one or just a few values in the attribute dictionary, and the system will choose the most appropriate font from those available. The system can also give you a complete list of font descriptors matching your query via CTFontDescriptorCreateMatchingFontDescriptors.
Font Collections
Font collections are unions of font descriptors, that is, groups of font descriptors taken as a single object. A font collection is represented by the CTFontCollection opaque type. Font collections provide the capabilities of font enumeration, access to global and custom font collections, and access to the font descriptors comprising the collection. You can, for example, create a font collection of all the fonts available in the system by calling CTFontCollectionCreateFromAvailableFonts, and you can use the collection to obtain an array of all of the member font descriptors. There is also a function that takes a callback parameter used to sort the returned array of font descriptors.
14
Common Operations
This chapter describes some common text-layout and font-handling operations and shows, through portions of sample code, how they can be accomplished using Core Text. In addition to the code fragments in this chapter, see the following sample code applications that use Core Text:
CoreTextTest shows how to use Core Text to typeset blocks of text with varying attributes in the context of a complete Carbon application. CoreTextArcCocoa illustrates the use of Core Text fonts, lines, and runs in a Cocoa application that sets type along an arched path.
Simple Paragraphs
One of the most common operations in typesetting is laying out a multiline paragraph within an arbitrarily sized rectangular area. Core Text makes this operation easy, requiring only a few lines of Core Textspecific code. To lay out the paragraph, you need a graphics context to draw into, a rectangular path to provide the area where the text is laid out, and an attributed string. Most of the code in this example is required to create and initialize the context, path, and string. After that is done, Core Text requires only three lines of code to do the layout. Listing 2-1 uses Cocoa to simplify initialization of the graphics context. To see how that operation is done in Carbon, see the CoreTextTest sample code or Graphics Contexts in the Quartz 2D Programming Guide .
Listing 2-1 Typesetting a simple paragraph
// Initialize a graphics context and set the text matrix to a known value. CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; CGContextSetTextMatrix(context, CGAffineTransformIdentity);
// Initialize a rectangular path. CGMutablePathRef path = CGPathCreateMutable(); CGRect bounds = CGRectMake(10.0, 10.0, 200.0, 200.0); CGPathAddRect(path, NULL, bounds);
15
// Initialize an attributed string. CFStringRef string = CFSTR("We hold this truth to be self-evident, that everyone is created equal."); CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), string);
// Create a color and add it as an attribute to the string. CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); CGFloat components[] = { 1.0, 0.0, 0.0, 0.8 }; CGColorRef red = CGColorCreate(rgbColorSpace, components); CGColorSpaceRelease(rgbColorSpace); CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 50), kCTForegroundColorAttributeName, red);
// Create the framesetter with the attributed string. CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString); CFRelease(attrString);
// Create the frame and draw it into the graphics context CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); CFRelease(framesetter); CTFrameDraw(frame, context); CFRelease(frame);
16
Listing 2-2 omits initialization of the plain text string, font, and graphics context, but it shows how to create an attributes dictionary and use it to create the attributed string. To see how to create a Core Text font, see Font Creation and Storage (page 21).
Listing 2-2 Typesetting a simple text label
CFStringRef string; CTFontRef font; CGContextRef context; // Initialize string, font, and context CFStringRef keys[] = { kCTFontAttributeName }; CFTypeRef values[] = { font };
CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, (const void**)&values, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryCallBacks, &kCFTypeDictionaryValueCallbacks);
// Set text position and draw the line into the graphics context CGContextSetTextPosition(context, 10.0, 10.0); CTLineDraw(line, context); CFRelease(line);
Columnar Layout
Laying out text in multiple columns is another common typesetting operation. Strictly speaking, Core Text itself only performs the layout of one column at a time and does not calculate the column sizes or locations. You do those operations before calling Core Text to lay out the text within the rectangular path area youve calculated. In this sample, Core Text, in addition to laying out the text in each column, also provides the subrange within the text string for each column.
17
Listing 2-3 mixes Cocoa method calls in Objective-C with function calls into Carbon frameworks and Core Text. It includes an implementation of the drawRect: method of NSView, which calls the local createColumns function, defined first in this listing. This code resides in an NSView subclass in a Cocoa document-based application. The NSView subclass includes an attributedString accessor method, which is not shown here but is called in this listing to return the attributed string to be laid out.
Listing 2-3 Performing columnar text layout
- (CFArrayRef)createColumns { CGRect bounds = CGRectMake(0, 0, NSWidth([self bounds]), NSHeight([self bounds])); int column; CGRect* columnRects = (CGRect*)calloc(_columnCount, sizeof(*columnRects));
// Start by setting the first column to cover the entire view. columnRects[0] = bounds; // Divide the columns equally across the frame's width. CGFloat columnWidth = CGRectGetWidth(bounds) / _columnCount; for (column = 0; column < _columnCount - 1; column++) { CGRectDivide(columnRects[column], &columnRects[column], &columnRects[column + 1], columnWidth, CGRectMinXEdge); }
// Inset all columns by a few pixels of margin. for (column = 0; column < _columnCount; column++) { columnRects[column] = CGRectInset(columnRects[column], 10.0, 10.0); }
// Create an array of layout paths, one for each column. CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, _columnCount, &kCFTypeArrayCallBacks); for (column = 0; column < _columnCount; column++) { CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, columnRects[column]); CFArrayInsertValueAtIndex(array, column, path); CFRelease(path);
18
- (void)drawRect:(NSRect)rect { // Draw a white background. [[NSColor whiteColor] set]; [NSBezierPath fillRect:[self bounds]];
// Initialize the text matrix to a known value. CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CFIndex pathCount = CFArrayGetCount(columnPaths); CFIndex startIndex = 0; int column; for (column = 0; column < pathCount; column++) { CGPathRef path = (CGPathRef)CFArrayGetValueAtIndex(columnPaths, column);
// Create a frame for this column and draw it. CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(startIndex, 0), path, NULL); CTFrameDraw(frame, context);
// Start the next frame at the first character not visible in this frame. CFRange frameRange = CTFrameGetVisibleStringRange(frame); startIndex += frameRange.length;
19
CFRelease(frame); } CFRelease(columnPaths); }
double width; CGContextRef context; CGPoint textPosition; CFAttributedStringRef attrString; // Initialize those variables.
// Find a break for line from the beginning of the string to the given width. CFIndex start = 0; CFIndex count = CTTypesetterSuggestLineBreak(typesetter, start, width);
// Use the returned character count (to the break) to create the line. CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, count));
// Get the offset needed to center the line. float flush = 0.5; // centered double penOffset = CTLineGetPenOffsetForFlush(line, flush, width);
// Move the given text drawing position by the calculated offset and draw the line. CGContextSetTextPosition(context, textPosition.x + penOffset, textPosition.y); CTLineDraw(line, context);
20
CTFontDescriptorRef CreateFontDescriptorFromName(CFStringRef iPostScriptName, CGFloat iSize) { assert(iPostScriptName != NULL); return CTFontDescriptorCreateWithNameAndSize(iPostScriptName, iSize); }
The example function in Listing 2-6 creates a font descriptor from a font family name and font traits.
Listing 2-6 Creating a font descriptor from a family and traits
CTFontDescriptorRef CreateFontDescriptorFromFamilyAndTraits(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits, CGFloat iSize) { CTFontDescriptorRef descriptor = NULL; CFMutableDictionaryRef attributes;
assert(iFamilyName != NULL); // Create a mutable dictionary to hold our attributes. attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); check(attributes != NULL);
21
CFNumberRef symTraits;
// Create the traits dictionary. symTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &iTraits); check(symTraits != NULL);
if (symTraits != NULL) { // Create a dictionary to hold our traits values. traits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); check(traits != NULL);
if (traits != NULL) { // Add the symbolic traits value to the traits dictionary. CFDictionaryAddValue(traits, kCTFontSymbolicTrait, symTraits);
// Add the traits attribute to our attributes. CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits); CFRelease(traits); } CFRelease(symTraits); } // Create the font descriptor with our attributes and input size. descriptor = CTFontDescriptorCreateWithAttributes(attributes); check(descriptor != NULL);
22
The example function in Listing 2-7 creates a font from a provided font descriptor. It calls CTFontCreateWithFontDescriptor, passing NULL for the matrix parameter to specify the default (identity) matrix.
Listing 2-7 Creating a font from a font descriptor
// Create the font from the font descriptor and input size. Pass // NULL for the matrix parameter to use the default matrix (identity).
The example function in Listing 2-8 creates XML data to serialize a font for embedding in a document. Alternatively, and preferably, NSArchiver could be used. This is just one way to accomplish this task, but it preserves all data from the font needed to re-create the exact font at a later time.
Listing 2-8 Serializing a font
check(iFont != NULL);
// Get the font descriptor for the font. descriptor = CTFontCopyFontDescriptor(iFont); check(descriptor != NULL);
if (descriptor != NULL) {
23
// Get the font attributes from the descriptor. This should be enough // information to recreate the descriptor and the font later. attributes = CTFontDescriptorCopyAttributes(descriptor); check(attributes != NULL);
if (attributes != NULL) { // If attributes are a valid property list, directly flatten // the property list. Otherwise we may need to analyze the attributes // and remove or manually convert them to serializable forms. // This is left as an exercise for the reader. if (CFPropertyListIsValid(attributes, kCFPropertyListXMLFormat_v1_0)) { result = CFPropertyListCreateXMLData(kCFAllocatorDefault, attributes); check(result != NULL); } } } return result; }
The example function in Listing 2-9 creates a font reference from flattened XML data. It shows how to unflatten font attributes and create a font with those attributes.
Listing 2-9 Creating a font from serialized data
CTFontDescriptorRef descriptor;
check(iData != NULL);
// Create our font attributes from the property list. We will create // an immutable object for simplicity, but if you needed to massage
24
// the attributes or convert certain attributes from their serializable // form to the Core Text usable form, you could do it here. attributes = (CFDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorDefault, iData, kCFPropertyListImmutable, NULL); check(attributes != NULL);
if (attributes != NULL) { // Create the font descriptor from the attributes. descriptor = CTFontDescriptorCreateWithAttributes(attributes); check(descriptor != NULL);
if (descriptor != NULL) { // Create the font from the font descriptor. We will use // 0.0 and NULL for the size and matrix parameters. This // causes the font to be created with the size and/or matrix // that exist in the descriptor, if present. Otherwise default // values are used. font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL); check(font != NULL); } } return font; }
25
check(iFont != NULL);
// Get the ascent from the font, already scaled for the font's size lineHeight += CTFontGetAscent(iFont);
// Get the descent from the font, already scaled for the font's size lineHeight += CTFontGetDescent(iFont);
// Get the leading from the font, already scaled for the font's size lineHeight += CTFontGetLeading(iFont);
return lineHeight; }
The example function in Listing 2-11 demonstrates how to get glyphs for the characters in a string with a single font. Most of the time you should just use a CTLine object to get this information because one font may not encode the entire string. In addition, simple character-to-glyph mapping will not get the correct appearance for complex scripts. This simple glyph mapping may be appropriate if you are trying to display specific Unicode characters for a font.
Listing 2-11 Getting glyphs for characters
void GetGlyphsForCharacters(CTFontRef iFont, CFStringRef iString) { UniChar *characters; CGGlyph *glyphs; CFIndex count;
26
// Allocate our buffers for characters and glyphs. characters = (UniChar *)malloc(sizeof(UniChar) * count); assert(characters != NULL);
// Get the characters from the string. CFStringGetCharacters(iString, CFRangeMake(0, count), characters);
// Get the glyphs for the characters. CTFontGetGlyphsForCharacters(iFont, characters, glyphs, count);
27
CTFontSymbolicTraits traitMask;
// If we are trying to make the font bold, set the desired trait // to be bold. if (iMakeBold) desiredTrait = kCTFontBoldTrait;
// Mask off the bold trait to indicate that it is the only trait // desired to be modified. As CTFontSymbolicTraits is a bit field, // we could choose to change multiple traits if we desired. traitMask = kCTFontBoldTrait;
// Create a copy of the original font with the masked trait set to the // desired value. If the font family does not have the appropriate style, // this will return NULL.
The example function in Listing 2-13 converts a given font to a similar font in another font family, preserving traits if possible. It may return NULL.
Listing 2-13 Converting a font to another family
CTFontRef CreateFontConvertedToFamily(CTFontRef iFont, CFStringRef iFamily) { // Create a copy of the original font with the new family. This call // attempts to preserve traits, and may return NULL if that is not possible. // Pass in 0.0 and NULL for size and matrix to preserve the values from // the original font.
28
Notes Added this document for iOS 3.2. Removed links to deprecated documents and sample code. Revised Figure 1-3 "Text layout data flow" to show that a CGPath object is provided in the creation of a CTFrame object. Fixed bad link to sample code in Introduction. Made minor editorial corrections. New document that explains how to perform text layout and font-related operations using the Core Text programming interfaces.
29
Apple Inc. 2010 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apples copyright notice. The Apple logo is a trademark of Apple Inc. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 .Mac is a registered service mark of Apple Inc. Apple, the Apple logo, Carbon, Cocoa, Mac, Mac OS, Macintosh, Objective-C, Quartz, and QuickDraw are trademarks of Apple Inc., registered in the United States and other countries. Helvetica and Times are registered trademarks of Heidelberger Druckmaschinen AG, available from Linotype Library GmbH. IOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license.
Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED AS IS, AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state.