Core Text Overview
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.
OS X Text Technologies
The Macintosh operating system has provided sophisticated text handling and typesetting capabilities from its beginning. In fact, these features sparked the desktop publishing revolution. Core Text is the most modern text-handling technology on the platform. It is designed specifically for OS X and is written in C, so it can be called from any language in the system. It is positioned as a core technology to provide consistent, high-performance text services to other frameworks throughout the system, and the Core Text API is accessible to applications that need to use it directly. Core Text resides in the Application Services umbrella framework (
ApplicationServices) so that it is callable from both Carbon and Cocoa and has all of the lower-level services it needs.
Core Text is not meant to replace the Cocoa text system, although it provides the underlying implementation for many Cocoa text technologies. If you can deal with high-level constructs, such as text views, you can probably use Cocoa. For this reason, Cocoa developers typically have no need to use Core Text directly. Carbon developers, on the other hand, will find Core Text faster and easier to use, in many cases, than preexisting OS X text layout and font APIs.
To decide whether Core Text is the right OS X text technology for your application, apply the following guidelines:
If you can, use Cocoa text. The
NSTextViewclass is the most advanced, full-featured, flexible text view in OS X. For small amounts of text, use
To display web content in your application, use Web Kit.
If you need to use Carbon only, consider using
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 engine—you have some text and you know where it needs to go in your view—you 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.
Design Goals and Principles
Core Text is designed to provide the following benefits:
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 don’t need much code. A corollary principle of the Core Text design is that clients are not required to pay for features they don’t 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.
Core Text Features and Capabilities
Core Text performs text layout and font access. The text layout engine generates glyphs from characters and positions the glyphs into glyph runs, lines, and multiline frames. It also provides glyph- and layout-related data, such as glyph positioning and measurement of lines and frames. The API handles character attributes and paragraph styles, including various types of tab styles and positioning.
The Core Text font API brings to Carbon developers the same capabilities enjoyed by Cocoa developers through
NSFontDescriptor. The API provides font viewing and selecting. It provides font references, font descriptors (objects that encapsulate font data sufficient to instantiate a font reference), and easy access to font data. It also provides support for multiple master fonts, font variations, font cascading, and font linking. The Core Text font API is designed to be very complete, so that you don’t have to go to different layers to do what you need to do.
System Data Types and Services
Core Text uses system data types and services wherever possible, and you use the same conventions that pertain to the other core frameworks in OS X. So, for example, Core Text uses Core Foundation objects for many input and output parameters, enabling them to be retained, released, and stored in Core Foundation collection classes. Other objects handled by Core Text are provided by the Core Graphics framework, for example, CGPath objects. Moreover, because many Core Foundation objects are toll-free bridged with Cocoa Foundation objects, you can usually use Foundation objects in place of Core Foundation objects passed into Core Text functions. Use of these standard types and toll-free bridging ensure that you don’t have to perform expensive type conversions to get data into and out of Core Text.
Core Text is built to work directly with Core Graphics, also known as Quartz, which is the high-speed graphics rendering engine that handles two-dimensional imaging at the lowest level in OS X. Quartz is the only way to get glyphs drawn at a fundamental level, and, because Core Text provides all data in a form directly usable by Quartz, the result is high-performance text rendering.
Core Text Input
The input type most basic to Core Text is the Core Foundation attributed string, represented by
CFAttributedStringRef or its Cocoa counterpart,
NSAttributedString, which are toll-free bridged. The attributes are key-value pairs that define style characteristics of the characters in the string, which are grouped in ranges that share the same attributes. Examples of text attributes are font and color. The attributes themselves are passed into attributed strings, and retrieved from them, using CFDictionary objects. (Though
NSDictionary are also toll-free bridged, the individual attribute objects stored in the dictionary may not be.) The typesetting mechanism in Core Text uses the information in the attributed string to perform character-to-glyph conversion.
Characters and Glyphs
One of the most important capabilities of fine typesetting is character-to-glyph conversion. It is important to distinguish between characters and glyphs in discussing a text layout engine. Characters are essentially numbers representing code points in a character set or encoding scheme, such as Unicode, the character set used for all text in OS X. The Unicode standard provides a unique number for every character in every modern written language in the world, independent of the platform, program, and programming language being used.
A glyph is a graphic shape used to depict a character. Glyphs are also represented by numeric codes, called glyph codes, that are indexes into a particular font. Glyphs are selected during composition and layout processing by the character-to-glyph conversion process. There are any number of glyphs that correspond to a particular character. For example, the character “uppercase A” has different glyphs for different typefaces (such as Helvetica and Times) and type styles (such as bold and italic). Figure 1-1 shows various glyphs, all of which represent an “uppercase A.“
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.
Core Text Objects
Core Text objects are based on the corresponding opaque types defined by the framework. In the sections that follow, you learn how the primary Core Text objects interact to accomplish various client tasks.
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.
Framesetters and Frames
The framesetter is the highest-level object in the Core Text layout engine, represented by the CTFramesetter opaque type. A framesetter generates text frames by filling a path with text. That is, CTFramesetter is an object factory for CTFrame objects that are ready to draw.
The framesetter takes an attributed string object (CFAttributedString) and a shape descriptor object (CGPath) and calls into the typesetter to create line objects that fill that shape. The output is a frame object containing an array of lines. This array of lines is a paragraph, a multiline layout. The frame can draw itself directly into a graphic context. You can also retrieve the lines to manipulate before drawing. For example, you might adjust their positioning. Figure 1-3 shows the data flow among objects performing text layout.
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.
It’s 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.
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.”
Lines and Glyph Runs
A line object represents a line of text and is represented in Core Text by the CTLine opaque type. A CTLine object contains an array of glyph runs. Line objects are created by the typesetter during a framesetting operation and, like frames, can draw themselves directly into a graphics context. Line objects hold the glyphs that are the result of the text layout process, created from text and style information.
A line corresponds to a range of characters. It could be miles long or, more often, one of a series of lines contained within a paragraph. The paragraph is represented in Core Text by a CTFrame object, which contains the paragraph’s line objects. Accordingly, you can retrieve line objects from their frame object.
A line object contains glyph-run objects, represented by the CTRun opaque type. A glyph run is a set of consecutive glyphs sharing the same attributes and direction. The typesetter creates glyph runs as it produces lines from character strings, attributes, and font objects. That is, a line is constructed of one or more glyphs 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.
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, there’s 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.
Other Layout Objects
In addition to the framesetter, frame, typesetter, and line objects, Core Text provides other objects to complete the text layout process: paragraph style, text tab, and glyph info objects.
Paragraph style objects encapsulate paragraph or ruler attributes in an attributed string and are represented by the CTParagraphStyle opaque type. A paragraph style object is a complex attribute value in an attributed string, storing a number of subattributes that affect paragraph layout for the characters of the string. Among these subattributes are alignment, tab stops, writing direction, line-breaking mode, and indentation settings. The CTTextTab opaque type represents a tab stop in a paragraph style, storing an alignment type and location. The CTGlyphInfo opaque type enables you to override a font's specified mapping from Unicode to the glyph ID.
Font objects are those Core Text objects dealing directly with fonts: the font reference itself, font descriptor objects, and font collection objects.
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). There’s also
CTFontCreateUIFontForLanguage, which creates a reference for the user-interface font for the application you’re using in the localization you’re 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 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
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.
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
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.
© 2010 Apple Inc. All Rights Reserved. (Last updated: 2010-03-03)