Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2008-364
$eventId
ID of event: wwdc2008
$eventContentId
ID of session without event part: 364
$eventShortId
Shortened ID of event: wwdc08
$year
Year of session: 2008
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2008] [Session 364] Font Manage...

WWDC08 • Session 364

Font Management and Core Text

Essentials • 1:06:41

Learn how the Core Text font APIs can simplify your applications' font management. If you've been managing fonts with QuickDraw, ATSUI, or ATS, you'll be impressed with how Core Text unifies and simplifies the use of fonts in your applications.

Speakers: Julio González, Nathan Taylor

Unlisted on Apple Developer site

Downloads from Apple

SD Video (812.2 MB)

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good morning. My name is Julio González. I'm the manager of the talk group at Apple. Today, I want to give you a bird's-eye view of the Text system in Mac OS X. It's going to be great for you if you're new to Mac OS X, but I'll also mention some of the new features that we have in Text in Snow Leopard. I will talk, I will try to just touch on the APIs that you would commonly use and areas that might interest you. I will not go into very deep details in each one of the Text systems, otherwise this could take far too long.

I'll also point out some of the pitfalls that you might run into and some special catches when you deal with the Text system. I'll also talk about fonts. There are many ways that our users have to install fonts in the system and when to make them available. And there are some gotchas, too, that you might fall into when you're dealing with fonts.

So, up on the slide, we have all the major text subsystems in Mac OS X. I want to point out to you that if you go on the online text documentation, or you pick up your favorite book and programming map for Mac OS X, you're going to see other text or systems that deal with text. I strongly encourage you to stay away from those. You have no need to get into those to write a successful Mac OS X application. So, the bottom layer is Quartz. Quartz is our glyph rendering engine.

The middle sits Core Text. Core Text does all the font file management, font access, and Unicode text layout for the system. And on top sits Cocoa. Cocoa is the whole package. If you're dealing with text, this is where you want to be. It covers input, covers layout, covers everything. It can handle everything automatically for you, or it's highly customized. possible.

Now fonts. OS X ships with a large amount of, or collection of fonts. Over 100 font families and 200 font faces. This allows us to support the major writing systems and major languages. And we support all the major font formats: TrueType, PostScript, OpenType, and some legacy font formats as well.

Now, in OS X, users, as I said before, have many ways to install fonts in the system. And this is something you, as a developer, need to be aware of. Because if you deal with fonts in your application, and you have some sort of font menu that you handle, you need to be aware that the font set that your application starts with is not static. The user may change this at any time.

The most common ways for users to make fonts available to the system is to install them in one of the known font locations to the system. At the bottom is the system font location. This location is for fonts that are fundamental to the OS. We strongly discourage any applications to install fonts here or for the users to install fonts in this location, and especially not remove them.

The next location is the local location, library fonts, and these fonts are also available to everybody in the system and every process of the system. The difference is that this is the location where we encourage you as an application developer to install fonts that users will use for content creation. So it's not only available to your apps, but it's also available to other apps that might need the font for their content.

Next is the network location. And typically this location is only available to those users that are in a network file system whose network administrator has enabled this location. These fonts are available to everybody, everybody who has access to the network and every process that is actively using it.

Finally, there is the user location. It's in your home directory library fonts. And this is the location where users would install fonts that they purchase or that otherwise acquire for personal use. Now, you as an application developer might want to install fonts in this location if you know that you're dealing with a setting, say a university setting, where many users will be sharing the computer and your font licenses for your applications do not cover multiple users. One thing to note about these locations.

If, as part of your application or as sort of your bundle, you have what we call a daemon process, a process that runs outside of the user session, those processes do not have access to all the fonts. They only have access to the system and to the local fonts. You won't have access to the user fonts. Now, if you have a background process that's what we call an agent, runs within the user session, you have the same fonts, access to the same fonts that the rest of the processes do.

Another way for users to install fonts is to use font management applications. Typically, users of these applications will create sets or libraries of fonts that they enable or register and unregister on demand. OS X ships with such an application. It's called FontBook. But there are many third-party applications that have actually an enhanced set or have more features than FontBook does and do a good job at it. Applications may install their own fonts as well.

There are APIs that I'll show you later that allow the application to register fonts. They can even register them privately so that it cannot be seen by the rest of the system. I'll show you an example of that. And finally, fonts may be auto-activated on the user's behalf. This is something that has been present in the OS for many releases now.

And it was only enabled if you use a third-party font management application. Starting with Snow Leopard, this is on by default. So the way it works, if Spotlight can find a font file in one of your disks, it will be made available to any application or document that requests this.

So, before we get into the text architecture, let's just get some fundamentals out of the way. Before we can draw text on the screen, we need fonts. And fonts, from a high-level point of view, is basically a collection of glyphs that same as similar design pattern or purpose.

A glyph is a graphical representation of a character. So, typically the simple fonts have one glyph per character, typically Western fonts. But, that's not to say that the more complex modern fonts can't have multiple representations. Up on the slide, we have Zapfino, and you can see that it has multiple glyphs with the capital letter A. Now, fonts supporting complex writing systems such as Arabic, it's a must that they have multiple glyphs that represent a single character.

Now, what are the fundamental font types that you're going to be dealing with OS X? Up on the slide, we have them. We have on the top the Cocoa font types and the bottom the Core Text font types. I must warn you again, if you go to the online documentation or you pick up your favorite book on programming for OS X, you will see other font types. Stay away from those. They're just for legacy. You don't need them to program in OS X.

So, first let's start with the font. By the way, these fonts, the Cocoa fonts and the Core Text fonts, are what we call toll-free bridge. So, you can interchange them in either layer. So, let's start with the font. A font is a concrete font reference, a strike, if you will, into the font family.

So, the font is what you will use when you need to draw something on the screen. It's what you will use if you need to get, say, glyph information. You need to get font metrics information. You need to get some glyphs. You need to get some character mappings. That's the reference that you will use.

A font descriptor is a way for you to establish what font you want to use. It is sort of an abstract representation of a font. If you come from the Windows world, it's akin to a log font. So, you specify a bunch of attributes that best describe the font that we want to use, that you want to use, and the system will get that for you.

Mac OS X is built entirely using Unicode. The fundamental type to represent Unicode on Mac OS X is using the string. CFString if you're using Core Foundation, NSString if you're using Cocoa. And there are many ways that you can create the strings. You can create them directly by using Unicode, UTF-8, 16, 32. You can create the strings using some of the standard encodings. There are conversion APIs that NSString provides for you to use those.

And also, there are APIs given to you so that if you're dealing with an external file system or I should say you're dealing with another file system or architecture, you don't need to worry about things such as byte order mark or decomposition. The APIs will handle this for you.

Now, our Core Text engine and Cocoa Text engines use a higher level construct to operate. And that's the attributed string. The attributed string is basically the base string, the Unicode string for all intents and purposes, and a set of attributes that define what you want to do on that string. Think of it as a rich text representation.

The neat thing is if you're at the Cocoa layer, you can have a set of APIs that allow you to construct the strings from standard font documents, such as HTML, or I should say file formats, etc. And finally, typically if you are a good programmer, a good citizen, you're not going to be hard coding strings into your application. You're going to be dealing with some form of strings file, some sort of resource strings that can be localized. So, let's talk about the core code.

So, let's get into the text architecture. At the very bottom is Quartz. Quartz, as I said, is a glyph rendering engine. It has no idea about doing text layout. What it does is to layout glyphs. So, if that's the case, why should you use Quartz at all? And by the way, you might catch me as lip-syncing. Core graphics is the same thing as Quartz. Anyhow.

You might have some valid reasons for using Quartz, and that is if you have a very specialized text layout engine, you're working outside of the norm, you're not handling Unicode. You might want to be in this space. You have a set of code from many, many years ago where you control everything. You can then be at the Quartz level if you need to. Another reason might be speed. You are at the lowest level of the text architecture. You want to have that speed.

There might be reasons to be in Quartz. Now, I must warn you, both Core Text and Cocoa are highly optimized for speed. So unless you want to take some of the shortcuts that I'll mention in the next few slides, that speed that you might gain by using Quartz might not be necessarily what you want.

Now, seriously, why shouldn't you use it? Well, most of your users are not going to be feeding glyphs to you. You're going to be dealing with text, and typically Unicode. So Quartz has no idea about how to deal with Unicode text. It has no idea how to do layout.

It just knows how to deal with glyphs. Finally, it has no knowledge on how to do font substitution. If you're dealing with a font and it can't render one of the glyphs that you need, you'll just guess a box for that glyph. So, given that, here are some of the APIs that you can use at the Quartz level. This first one, CGContextShowTextAtPoint, is sort of a deceiving API. You see this API and you say, "Oh, I can be drawing text using Quartz." Well, if you take note of the fourth parameter, it's a char string. It's not a unichar string.

What it knows how to do is draw basically ASCII text. And, as I'll show you later, it won't even do a good job at that. But now, if you are dealing with... You have full knowledge of fonts and how to get glyphs out of fonts. There are some APIs that you can use to lay out your text, and here are two APIs that you can use to do that.

So, let me give you some examples of trying to use Quartz for text rendering. Here up on the screen, I have a simple example of drawing the word waffle using two different fonts. On the top, we have what happens when you draw it with Quartz, and in the bottom, what happens when you draw it with Core Text and Cocoa.

First thing I want to show you is Quartz has no idea how to properly do any kerning. So, you can see how much nicer it looks when you draw it with Quartz. Next thing is Quartz, once again, has no idea how to deal with ligatures. So, both of these fonts have the FFL ligature, and you can see how much nicer it looks using Quartz and Cocoa. This is the way the font designer intended the text to look.

Now, you could say both kerning and ligatures are fancy typographical features. I really don't need it. I want to have all the speed that I can monster for my application. Well, let me give you an example where that doesn't apply. Here I have a French string and an Arabic string that I'm going to use two fonts to draw it with. And the first thing you'll notice is how Quartz doesn't know how to properly place the accent on top of the capital letter E.

Now, you could say, "I can live with that." Well, if you're dealing with a complex writing system such as Arabic, you can see how horrendously Core Graphics or Quartz does to handle this text. You can notice that it doesn't apply the necessary ligatures. And not only that, if you know how to read Arabic, you will notice that those glyphs are not ordered in the right way. They're not ordered right to left.

Another thing that I want you to take a cue from this slide is that I cheated using this slide. If you notice, I didn't write it in the right order. I didn't use the show text at point API. I used the show glyphs at point API. So how did I get those glyphs? I had to go up to Quartz to get those glyphs to be able to render with them.

Finally, here's a sample of font substitution. Typically, as a developer, you're going to be given a stream of Unicode or text to render. You have no idea what font will be able to handle that text. So you say, "I'll just pick the system font, Lucida Grunt, to draw it." And you can see what Quartz does and what Core Text does. Quartz has no idea where to get the Arabic glyphs. Lucida doesn't have it. Whereas, Core Text and Cocoa apply the necessary font substitution.

Now, you still say, I still want to use Quartz for my rendering. I've got my own layout engine. Quartz does provide some ways for you to access font data, so you can get at the glyphs, get at the metrics. So up on the slide, I have some of the APIs, sample of the APIs that you can find in Quartz. There are more in Quartz that you can use.

The only thing that I want to warn you is that these APIs are workable only for a subset of the formats out there. They work for TrueType fonts. They will not work for PostScript fonts. You would need to know how to parse those. And even in the case of TrueType, even though it gives you access to the font data, you still need to know how to parse that font data. There's no APIs that will interpret that data for you.

If you want to be in that space or not have to do that, this is where you want to be. You want to be in Core Text. Core Text, like I said before, it provides all the font management for the system. It provides font access. It not only handles all the font formats out there, but it provides APIs that let you get at the font data and APIs that actually interpret the font data for you. And finally, it gives you access to, or it has capabilities of doing Unicode text layout. It's our base Unicode text layout engine for the system. So.

Before we start drawing text, we need to have a font. And here is how you can create a font to use with Core Text. Fonts are specific instances, and if you must create one directly, what you need to pass to the font APIs is a PostScript name. Note, do not pass a family name. That's a performance degradation.

The other thing that you need to know is please pass a proper PostScript name. Font names are case sensitive. If you pass the wrong font name, the system is going to try very hard to find that font in the system. Typically, when you are dealing with font instances, you're in the space of your UI.

Core Text has a nice API, the Create UI Font for Language API, which allows you to create a font for any element in the UI that you might need. So the first parameter it takes is the element you can get. You can pass a font for a button, give me the font for a button, for drawing a label, for placing in a menu. This API will return the exact font that you will need to use for your application. The last parameter is the language. Typically, you pass "no" saying, saying I wanna use the default language the user is using.

And then, if you know exactly the font that you want to use, this is a way that you can use it or create it. You create with name and pass it a PostScript name. And lastly, I have an example of another API that allows you to convert from one face to another. In this case, we're converting from the bold face that we had before to an italic face.

Now, font descriptors. This is the recommended way that we have for you to create font references. Once again, these are references that are abstract in nature. You can create a font reference that says, "Give me a font. Give me any, say, italic font in the system. That's all I need." Or you can create a font reference that says, you know, it's very specific. You specify a family name, a weight, compression ratio, color, any number of attributes, and the system will provide the best matching font for you to use.

Now, given that, this is a recommended way that we provide for you to store font references in your documents. Given that we create a font reference from a list of attributes, this list of attributes can be serialized into your documents as well. And I'll show you an example.

I'll show you an example of that later. And finally, font substitution is -- you get for free with Core Text. It's on by default. But if you need to override it, there are ways for you to override it. And one way to do it is to pass your own font substitution list or cascade list, as we call it, to the descriptor to override the system behavior.

So here's an example of -- or the recommended examples that we have for you to create font references. If you have a PostScript name, you can use the first API and you pass it a PostScript name, and it will give you that exact font descriptor reference. But most of the time, new developers are dealing with font family names and weights.

This is very typical in the CSS web space and also typical for developers that present ways to select fonts by their users. They typically use a family name and a weight. So this is the way we recommend that you create your font reference. Don't try to create a direct font reference using a family name. Create a font descriptor using an attribute, and the attribute is a dictionary basically stating what you need. And the two attributes that you need are the family name attribute and the face attribute.

So, up here on the screen is a more abstract example of how to create a font descriptor. Say you have a terminal application, and terminal applications typically deal with monospace fonts, and you want to provide an interface for users to pick what font to use in the case where we need to display some bold characters in the terminal application. So, you want to create a font descriptor that basically says, "Give me all the fonts that can be monospaced and can be bold." So, the way to create a font descriptor is first you create your list, or let's say dictionary of attributes.

And in this case, the dictionary of attributes will only have one element that we care about, and that's a traits attribute. The traits attribute in itself is another dictionary of attributes, and the only attribute that we care about, or trait that we care about, is the subject. Symbolic trait. And that, in this case, is a bold and monospace. So, once we have our dictionary defining what we want, we can create the font descriptor with it.

Now, at this time, we've just created the font descriptor. We haven't resolved the font descriptor. If, to make an analogy with SQL, or SQLite to be precise, at this point in time it would be like if you had executed the SQL prepare statement. You haven't executed. You haven't solved it. So, let's say you just want to have one font that can be monospaced and bold.

Well, you can get a direct font reference using the create with font descriptor. And now the system will get you one reference, one font that can handle both of these attributes. But like in the example I said, you want to provide a list for your users to pick. You can do the same and resolve it in a way that it gives you a list of fonts that can handle both attributes.

And you can use the create matching font descriptors to do that. It will give you an array of font descriptors that can handle both the monospace and bold in this case. Then font descriptors is the way we recommend that you use to store your font references. And the reason being, as you can see, is the font descriptor is a list of attributes, if you will, that describe what font you want to use.

So, once you have the list, the best way is to grab this list and serialize it to this. So, if you're starting from a font, you can always get the best descriptor for that font. So, you call the copy font descriptor API. Once you have your descriptor, you can copy the dictionary of attributes for that descriptor.

Now, once you have this dictionary, you can use any number of APIs to serialize or flatten this data out to this. Here, I'm showing you a core foundation. You can see that this is a foundation API that gets -- that flattens it out as XML data. So, you can write this out to this.

Now, font substitution, like I said, is free in Core Text. And it's not only free, it's a pretty sophisticated font substitution engine. It's not quite lame to say, okay, my font is missing this glyph, just give me any other font out there that has this glyph. No, it is language-specific. It takes into account precedence order of fonts. It takes into account traits. So if you're dealing with a bold font, it's going to give you another bold font.

It looks into things like compression ratio of the font. So if a font is condensed, it's going to look for another font that has similar features. So it tries very, very hard to come up with a font that looks very similar to the base font that you have started with.

Now, it is on by default, so if you want to override it, as I said, you can do so by passing your own list of, your own cascade list when you create the descriptor, and you use the attribute you use as a font cascade list attribute to define your own list.

Now, if you're dealing with Quartz directly, and like I said before, Quartz has no idea how to pick up the right font to, doesn't know how to pick the right font to render any appropriate text, you can come back to Core Text and Core Text has an API, the CT font create for string API, that given a range of text, it'll tell you the best font to render the set text. Julio González, Nathan Taylor Now, new for OS X Leopard is font management. Core Text will now handle all the font management for the system. This replaces legacy functionality in another text system.

It provides all the features that the old legacy system had, plus some added functionality that you developers have been requesting. Now, this is not documented elsewhere. The only place that we have any documentation on this is in the header. You can find it in the Core Text framework in the headers, ctfontmanager.h. So this is the perfect time for you, if you're interested in font management, to peruse what's in the header and give us any feedback.

But now I'll talk about the new things that we provide with font management. The first thing is registration APIs. Now, what does it mean to register a font in the system? Registering a font means that any of the font creation APIs that I just showed you will be able to get access to that font.

Or, it means that a user will be able to see this font in the font picker, for example. Okay? So, there are different ways for you to make fonts available. You can make your fonts available only to your own process. For that, you use the scope process. You can make the font available to every process in the system. And for that, you use the scope user. And the last one is the same. It makes the font available for every process in the system. But once the user logs out or reboots, the system forgets about that font.

That's the scope session. So, there are two APIs to register fonts. The fonts for URL and fonts for URLs. The first one takes a font reference. Or, a font reference. I should say. And the scope. The second one takes an array of font file references. And the scope.

Every time a font is registered with the system, the system will notify the processes that something has changed. So you can register with the distributed notification manager to listen to these notifications. And this is the string that you would use to register for notifications. Now, as I showed you, there are two ways to register fonts. Every single time a font is registered, a notification is sent out.

However, if you use the second API that I just showed you, the Fonts for URL, only a single notification will be sent out when all the fonts that you pass in the array have been registered. Obviously, there are similar APIs to unregister the fonts with similar names. Finally, there is a way for you to enable and disable the font descriptors that are available from each one of the APIs, typically something that font management applications will like to do.

Now, we have new enumeration APIs. Unlike the old legacy APIs, now you get all the fonts at once. No need to create an iterator. And also, the nice thing about this enumeration APIs is that the list of font names that you get is sorted in the same order that the font panel has them sorted, that the system has them sorted. Now, let's say that you have your own family names that are not registered with the system, and you want to present them to the user in the same order fashion that the system provides. You can use the Compare Font Families API to do just that.

There is an API that enumerates all the font files that are registered with the system, something that font management applications typically want to do. And this last one, it's a neat API. They create font descriptors from URL. It enumerates all the descriptors that a font file can handle.

Now, this is typically something that font management application might want to use, but It's also neat. You might want to use this API for your own applications. The reason is because this is how you can use a font in your application and hide it from the rest of the system, your own private registration.

Basically, you pass it in an arbitrary font file. It gives you the font descriptors that it can handle, and you hold on to those font descriptors, and you can pass those font descriptors to Core Text and Cocoa APIs to render text with them. If another framework tries to create or look up for that font, it won't find it because it hasn't been registered with the system.

Finally, we have Auto Activation Services. This is a new API. It's a mouthful. "Ct Font Manager. Create Font Request. Run Loop Source." And this is an API that you would use if you want to implement your own auto activation. Notice it takes the new Blocks API to implement callbacks. And I must warn you, this API is on the developer Snow Leopard seed that you received in the conference, but it's not currently active.

So just look at it in the header and provide us any feedback that you might have. Now, like I said, since Mac OS X Leopard, auto-activation is on by default. And there are ways for you to control the auto-activation features of the system. This is how you go about it.

You can enable it, disable it, or prompt the user before the auto-activation can take place. And you use this API, the Set Auto-Activation Setting API. It takes two parameters, a bundle identifier and a setting. The bundle identifier, typically, you will pass to your own apps bundle identifier and the settings will only apply to your own app. But if you want to turn it off for the whole system, you use the CT font manager bundle identifier string or identifier to apply the setting to the whole system.

Now, let's get to the exciting part about Core Text and that's its layout capabilities, the Unicode Text layout capabilities. So, like I said, the Core Text takes for input an attributed string, so your base string and a set of attributes that define it. And the first thing that happens is you deal with two objects that do all the heavy lifting in Core Text. These are the frame setter and the type setter.

The Frame Setter basically holds all the text, and it works in conjunction with the Type Setter to basically position the glyphs, suggest lines, and look at paragraph settings to just properly lay out the text. So how do you go about drawing them? It is quite simple using Core Text. There's a couple ways. You can use a line object or a frame object or a glyph run. The line object is the simplest way. You just create a line object from an attributed string.

It internally creates a Type Setter, and it is ready to draw. Before you draw, you can apply a set of calls to it to measure it, truncate it, adjust it, in whatever way. Now, you can also, instead of drawing a line, you can draw paragraphs, and that's using a frame.

And I'll describe that in the next slide. And finally, if you're dealing with Core Graphics or Quartz directly to lay out your glyphs, you have access to the position glyph runs. So this is one way that you can... use Core Text and Quartz to lay out your text directly.

So, let me give you an example of what you would typically do if you want to lay out a paragraph. First, you start with your attributed string. And the first thing you do is create a frame setter object. The only input to the frame setter object is your attributed string. It internally creates a Type Setter to help it do all its layout.

Next, you define a CG path, the shape, which, by the way, we only support rectangles, that defines where you want to lay out your text. So, at this point in time, once it has the rectangle, the frame setter and the Type Setter go to work and start doing the appropriate layout.

The Type Setter positions the glyphs, does the glyph runs, suggests the line breaks, positions all the lines, all taking into account the attributes that you pass and the attributed string to the Find Paragraph settings, and also takes a look at, you know, say, the directionality of the text. Now, let's say that you, this frame did not fit all the text that you wanted to draw.

Well, at that point in time, you can use the same frame setter object, give it another rectangle, and the process will start all over again within the frame setter and the Type Setter to lay out the remaining text. Thus, you can chain your frames, and you can repeat this process until you exhaust the text.

So, how do you go about coding this? Let's first start with the attributed string. Like I said, the attributed string is first your base string. Here, up on the slide, I have what I would call a hard coding of a string. It's using the CFSCR macro, and it just takes a Unicode string. But typically, you wouldn't be hard coding strings into your apps unless it's for debugging. So, typically, you want to get a localized string. So, here, this API, or this string, is a local string. This macro shows you how to get an appropriate localized string.

So, once you have your base string, next thing is you want to define the set of attributes that you want to apply to this string. We definitely want a font, so I'll pick Lucid Grunt 96. And we'll just keep it simple. That's the only attribute that we're going to apply to the text, but you can well imagine that you can define other things, just such as alignment, line spacing, and so forth, different paragraph styles.

So, now, we're going to create our text. And we're going to create our dictionary, which will have all the attributes that we need. Once again, it's a pretty simple one. It's only the font. So, once we have our dictionary and our base string, we can create our attributed string.

So, once we have this attributed string, it's quite simple to draw with Core Text. In this example, we're just going to draw a line, a simple label. So, simple call, create with attributed string, create line with attributed string, and At this point, once the line object is created, it has internally a typesetter that has layered all the text in the proper way, it is ready to draw.

Now, one thing that... The first thing that you should always do before you draw any text is make sure that your text matrix and your context is set up properly. You don't know how many times this bites people and they say, "Oh, why is my text not drawing?" Well, somebody has modified the text matrix from underneath you.

So, at this point, like I said, the line object is ready to draw, but you can make any number of other calls in Core Text that allow you to manipulate the line. You might want to truncate the line, for example. If not, you just position your line and you're ready to draw. Just draw it. Now, drawing frames. Simple again. You're starting with the same attributed string. The only other thing that you need now is

[Transcript missing]

So the first thing you do is you create a framesetter object. It only takes an attributed string.

Next, once you have your Framestarter object, you pass it in the shape, the rectangle path that you want to use, and the range of text that you want to lay out. In this case, I'm saying just the whole text. Once again, at this point, you can set up your text matrix, or make sure your text matrix is set up properly.

And also, there are a lot of calls in Core Text that can help you adjust the layout that we've suggested. Once you've done that, you're ready to draw. So now, let me invite up to the stage Nathan Taylor so he can give you a demo of how to use Core Text.

Thank you, Julio. I've got a couple short demos to show you today. I'm going to show you one right now. It gives Julio a chance to catch his breath. And this demo is going to show you drawing of text as Julio showed with Core Text in frames. And it's in a simple Cocoa application. So let me show you the application real quick. All right. It's launched. You don't see anything. I'm going to open up a document.

Let's make the window a little bit bigger here. You can see that the text flows automatically, and I've got it wired up so that if we click it, add frames. So I've got it now in three columns, and you can see it flow to the columns as I resize it.

And as you can see, Core Text handles pretty much all the same styles that you can get out of TextEdit. We have multiple style text, multi-language text, multiple fonts in this document. And Core Text handles it all within a single attributed string. Now, let me show you how we got this attributed string and how we drew the text.

So this application is an NSDocument-based application, and as such, we have NSDocument subclass, myDocument, and all we really did is take the boilerplate code and set it up to when reading from a URL to create our attributed string. So read URL of type error creates our attributed string, and NSDocument handles the open dialogue and everything we need for us.

Once we have this attributed string, we then can pass it to our Core Text view, which does the drawing. As you can see, we have drawRect here, and this gets the graphics port and then initializes the frame setter, and so I'll show you where we create it down here. CTFrameSetter, create with attributed string.

We get our attribute string, create a frame setter, and then we create our columns. Let's take a look at those. As Julio said, we start by getting our column rectangles, creating our column rectangles, and then for each rectangle, we create a path, add the rectangle, and insert it to our array. And then this is going to be passed back, and we'll use that to-- oops, let me close this here.

In DrawRect, once we have our column paths, we're gonna iterate over each path, create a frame from the path and the frame setter, and draw each frame. It's really straightforward to draw text in frame paragraph styles, and Core Text handles all the typical paragraph styles that you would get from NS TextView or--and similar. So with that, I will give the stage back over to Julio so he can tell you about Cocoa.

Thanks, Nathan. So you can see how easy it is to use Core Text to render paragraphs or simple lines. But the power of Core Text is in the adjustments that you can make. And I invite you to go online and check out the documentation of Core Text so you can see all the power that Core Text provides for you. By the way, this is the only place where you can find documentation of Core Text. And at the end of the slides, I'll provide you a link where you can go get the information. Now, Core Text, much like Quartz, is a building block in our text architecture.

So, If you're doing low-level text layout, all you need to do is text layout. And especially if you just, you have to confine yourself to doing procedural programming, Core Text is the place to be. Now, if you're dealing with text in general, well, you wanna be, this is where you wanna be. You wanna be in Cocoa. And the reason is, you just get the whole enchilada.

When you're dealing with text, up to now, we've just been talking about drawing glyphs and laying out text. But text is more than that. Our users expect text to be more than that. You need a way to actually be able to interface with your user. You need to be able to handle input of text. The users expect you to handle things such as file formats, be able to read and write 'em. So Cocoa does this for you, and it basically handles most of it for you so you don't have to worry about it.

Like the rest of the Cocoa system, Cocoa Text is built on the Model-View-Controller paradigm. So the model would be your storage, your fonts, your paragraphs that you want to manipulate. The controller would be your layout manager, the glyph setter, the type setter. Notice the keen resemblance on the classes to what Core Text has because Coco's layout engine is built on top of Core Text. And finally, View. There are many different View classes, and this is basically where the added value to our users is for text. It does all the input. It does all the dirty work that the users expect your application to handle.

So fonts in Cocoa, the font system in Cocoa is built on top of Core Text as well. Its type, as I showed you in a previous slide, are toll-free bridge with the Core Text types, so you can use them interchangeably, and you can expect to be able to create them in a similar fashion, only that you have the advantage of you dealing with Objective-C.

Now, Cocoa also deals or has a feature called the font collections. And collections are groups of fonts, if you will, that you as an application developer can provide for your users to use, or they can create these collections by themselves using the font panel, which is the user interface for the font system. And I'll show you that later.

Now, at the heart of the font system in Cocoa is the font manager. Let's not confuse the Cocoa font manager with the Core Text font manager. The Core Text font manager manages all the font files in the system. The Cocoa font manager makes fonts, font descriptors, font collections available to the user, manages those font collections.

It also manages the font panel, and it provides font conversion APIs. If we were to apply the Model View Controller to the fonts in Cocoa, your model would be the fonts, the descriptors, the collections. The controller would be the The font manager and the view would be the font panel.

So, the font panel is the standard UI in Mac OS X for users to pick fonts. It has a built-in collection font manager for the user, so that's where users can actually modify collections that are default in the system that you might have created and provided for them or that they create on their own.

But the font manager also provides the user the ability to create, to specify a lot of things about the fonts, not just what font to use and what size, but apply all sorts of different text effects. They can specify the opacity, they can specify a color. In essence, what the user is doing here for us is creating a font descriptor for us to use. Also, the font panel gives you access to the typography panel, which gives users access to high-end typography features of the font.

Finally, the font panel is very customizable, both by the user and the developer. The user, by being able to resize the font panel or hide things from the font panel to get up on the screen whatever pieces of the font panel that they want to use for their workflow. But as a developer, you can create also accessory views that can be used inside of the font panel.

So, if you're dealing with text in Cocoa and you want to draw it or edit it, which classes, where should you go? If you're just drawing small pieces of text, drawing labels, nothing beats Cocoa for that. You can have an NSString or an NSAttributedString and tell it to draw itself. No need to create another object or try to truncate stuff. It will do it automatically for you.

If you're handling small pieces of text that you want to edit, you can use the NSTextField or there are other controls that are similar in fashion. Now, when you want to deal with paragraphs, largest pieces of text, you want to be in the NSTextView or use the NSTextView. And finally, like I said, Cocoa can handle every single detail of the text for you.

But if you require precise control of how the text is to be laid out, you can do it within Cocoa. You can go directly to the Layout Manager. It builds on top of Core Text. So all the functionality you have in Core Text, you can also find inside of the Layout Manager in Cocoa.

Now, like Core Text, Cocoa prefers to deal with attributed string for drawing its text. And the neat thing about dealing with attributed strings in Cocoa is that you can get attributed strings very easily. As Nathan showed you on his demo, he created his attributed string using an RTF document to get a string from. He didn't have to go and code an attributed string like I did a few slides ago.

So, up on the screen shows you some of the font formats that you can create an attributed string easily from. But the strings APIs also provide a way for you, so if you have a format that it doesn't know about, you can provide a filter service so that it converts that format into an attributed string.

Now, string drawing, again, quite easy with Cocoa. If you have an NSString or an NSAttributedString, there are different methods that you can use to draw itself. Here are a couple of examples. The second one, the bounding rect with size, for example, if you specify a bounding rect, it will draw the string in there and it will automatically apply any truncation that needs to be applied. No reason for you to create a different object to handle this.

Now, it is quite easy, and one of the things that I must caution you when using the string APIs is that anything that is in the context, in the graphics context, is overridden by what you supply in the attributed string. So if your context was set to use Optima, say, but your attributed string says that it wants to use Arial, it will draw using Arial. It will draw using every single attribute that you had. Now, if you're dealing with a string which has no attributes, what Cocoa will do is will use the default font for the system, which is Helvetica, to draw.

Now, this class is sort of the nice feature for you as a developer because what this class is, the NS TextView class, is essentially a very powerful basic word processor, if you will. If you're familiar with the TextEdit application, anything that the TextEdit application can do, the NS TextView can do.

By the way, for those of you that don't know, you can find the source code to the TextEdit application in the examples directory in developer examples Cocoa. All the source code for the TextEdit application is there. Now, NS TextView does all the heavy lifting. It does all your input. It manages or handles all the input managers for different languages. It does all your cut, cut and paste, manages undo, drag and drop. It handles all the complex formatting.

So, if you want to have lists, tables, rulers, if you want to have attachments, you want to put some media into it such as a movie or a graphic, it handles that for you. It also has some form of detection like link URL detection and provides tool tips to those links automatically.

A lot of things that users come to expect for you to handle when dealing with text. It also has utilities such as spell checking and grammar checking built in. Now, new in Snow Leopard, some new features for NS TextView. Again, I want to caution you that these are available in the seed, in the headers, but they're not active in the seed. So, you won't be able to take advantage of them right away. The first one is data detectors.

So, what it will do is it will look at your text and it will be able to identify pieces of text such as email addresses, normal addresses. And what you can expect to happen is that we will, the Cocoa text system will be able to hook up automatically with the appropriate framework, say the address book, so that users can directly add contacts to their address book.

It will also have auto-correction for misspelled text, smart dashes, and text replacement. So you can imagine, like I show in this example, you're typing open paren, C, and close paren, and it'll turn that into a copyright sign. Something useful for our users that don't know how to go about using the option keys or the nice hidden keyboard control panel. So with that, Nathan, we'll give you a demo on use in Cocoa.

So I'm going to show you the second of my two demos here. And again, this is drawing with Core Text in a Cocoa application. If you were at last year's hands-on Core Text talk, you may have recognized this application. It's the Core Text ArcView. But I've translated it from a Carbon application into a Cocoa document-based application. And this application draws text on an arc using Core Text, but interfaces through the standard Cocoa mechanism with the font panel and the UI. So I have, you know, live update.

and I can control the font styles from some check boxes here. And it respects what the font's capabilities are, which is something that you should do with your UI. So let me open up the font panel. And we can see we have DDoS select, and it only has italic and bold faces. So if I choose bold, I get bold, and italic, italic, but I can't do bold, italic.

So let me bring up a new window, and I'll change the font in this window to Cochin, where we can now do bold and italic and go back with the font panel. And so what I will show you in the code is how we did the drawing, but more importantly, how I interacted with the font panel and other controls. Because if you have your own custom view that you want to display a font, you're going to want to be able to support multiple fonts, and this may be of interest to you. So let's take a look at the project.

Here we go. And I'm going to first start off by giving you a quick overview of the drawing. This is the Core Text Arc view. It does all the drawing here in DrawRect, and it's pretty straightforward. I have an attributed string, which I create a line from. I then process the line, extracting glyph information. I create my arc. And then through mathematical processes and transforms, I draw each glyph along the line with a CT run draw. Let me go down and just quickly show you that right here.

So let's take a look at how we interface with the font panel and the user interface and deal with fonts. So the first thing I want to show you is when-- The font panel changes the font. The message is sent to the first responder to change font, which I have selected here.

And my document, my NSDocument subclass, is the Windows delegate. So it eventually comes to my document. Here's where I handle it. I will convert the font from the font panel, which is the sender, using the old font and assign it back to the ArcView as the new font.

And then I'm going to update my display, which is probably what you'll need to do. When I switch windows, toggle between windows, what I do is I tell the font manager that this window, this controller is the new target for events. And I'm going to set the font for the font panel so that the font panel is updated live as the user switches between windows.

So if you noticed, the checkboxes were kind of respecting the font. And what they did is they looked at the font that we had, looked at what it was capable of, and then would set their state respectively. So first let's look at what we did when I clicked the bold checkbox. This made a font bold. And what I'm doing here in toggle bold is using the NSFontManager to convert the font to have the trait or, when I'm unchecking it, to not have the trait. And I'm asking for the bold trait here.

Now, how did I determine whether this should be enabled or not is... I implemented an NSFont category method. You can use however you want. CanToggleTrait. And what this does is it attempts to toggle the trait and then checks, you know, so I convert the font again, and then I take my test font and I'm going to take a look at its symbolic traits, compare it to the desired symbolic traits, and make sure that it is only different by my desired trait.

At the end, that's how we can control the user interface elements, you know, menu items, check boxes, if we want to have specific font controls so that they stay in sync with the font panel. If you're curious about how you can manipulate text in Cocoa directly, I want to point you to the Circle View example. It's in Developer, Examples, App Kit. CircleView. And this draws text on a circle using Cocoa. So with that, I'll give the stage back to Julio so he can finish up.

Thanks, Nathan. So that sort of concludes what I wanted to talk to you about, the high-level view of the tech system. So before I'm done, I want to leave you with some pointers that you might need while you're developing for Mac OS X. So the first has to do with storage.

Typically, all our strings are based on Unicode, and definitely that's what we recommend, that you store all your documents as, and some, you know, with Unicode as some form. So if you look at the NSString APIs in Cocoa, there are various calls that you can have in there or that you have available to you that do a lot of the work for you.

First, if you're reading from it, look-- if you know that you're dealing with files that you might be working with other systems that might have a different representation, say a byte order or Unicode decomposition, look for APIs such as this one, create external representation, and these are APIs that will handle all these automatically for you.

Now, when you go store fonts, like I said before, store the font descriptor attributes. Don't store a font reference. The reason being is this way you're guaranteed that you have all the attributes that the user was actually using when displaying the font. Like Nathan showed you, typically the way the UI, for the user to create font references, is using the font panel. And the font panel has many ways for the user to tinker with the representation of the font.

So by you getting the descriptor, you get every single one of those attributes, and it's easy to flatten them out. In fact, if you use Cocoa, Cocoa has some nice serialization APIs for you. And finally, if you're just storing plain text documents, starting in Leopard, we could tag plain text in there. So if you look at the NSString APIs, the write to file API, I believe, will allow you to, will automatically tag the document with the right encoding.

Core Text, if you need to be in this space, you're in procedural programming, you're doing procedural programming, and you're laying out your text, I want to encourage you to use the right objects. If you're dealing with paragraphs, use a frame setter. You could do paragraphs in any other ways because Core Text has many APIs that give you control. But we encourage you to use the APIs that are designed for the particular task.

We use the objects, especially the typesetter and the framesetter. These are the objects that do the heavy lifting, all the layout. So hold on to them as long as possible. And finally, The text matrix, setting up the text matrix. I can't mention this enough. This, I'm sure if you're new, it will bite you at some point.

As soon as you don't see text on your screen, that's the first thing that you should come to mind. I didn't set up my text matrix. So do that. And finally, don't make any character to glyph assumptions. Let the layout engine, let Core Text handle that for you using its APIs.

And Cocoa. It is our recommended layer or API of choice if you're dealing with text. Reason being is because it handles every single aspect of text for you. It is built on top of Quartz and Core Text, so it has all the capabilities of these layers and more. So unless you have some particular needs, such as doing procedural programming, you should be in the Cocoa space.

So just a little reminder of what you need to look for in for text in Cocoa. If you're doing some custom drawing and you just want to display some small label, you might want to use an NSText field because with that you get text editing for free as well. If you need any text editing and you're just looking for speed, well, use these string APIs for that. And again, if you want to do some really customized layout, you need some precise measurements, you always have access to the Layout Manager.

And finally, for text input, use the NSText view or an editable control. And this is one area that we recommend that you don't typically override. The reason being is once you start writing text editing, it opens up all sorts of kind of worms for you. And basically, you might break existing features that we have. Or in the future, if we come up with some new features, you might not be able to take advantage of. So don't reinvent the wheel when it comes to text. to text input.

And finally, fonts. Fonts should be quite simple to use, and they are for the most part, but we do provide a lot of flexibility in OS X when it comes to fonts. And the first thing that hits our users is the precedence order. So as you saw before in this slide, there are many places where users can install fonts or even make them available. So the lowest precedent, surprisingly, is the system location. And the highest precedent is the application. By the way, auto-activated fonts have the same precedence as application fonts. So the closer you are to the user, the higher the precedence.

Typically, where users run into trouble is when they go in and install a font that overwrites one of the system fonts or your application fonts that you ship. Unfortunately, there is not much that we can do about that. But you as an application developer, especially if you're installing fonts, there is something that you at least need to be aware of.

If you have an installer application to install fonts, your application must look first to see if any fonts that you're about to install are going to overwrite either an older version or a newer version of the font. If you don't do this, you're just asking yourself for trouble for you and your users.

Creating font references. I alluded to this earlier. If you are dealing with font family names and weights, please create a font descriptor. Do not attempt to create a font from a direct font reference using a font family name. It's a performance issue. On the same performance issue, again, font names are case sensitive.

Don't use the correct font name. The reason being is, like I said, since OS X Leopard, auto-activation is on by default. If you pass the wrong font name, first we're going to look in our... database, if you will, of fonts that are registered, look for that font. If it's not there, we're going to dig through the fonts and try to find them.

And even if we can't find them there, then we're going to go try to hit Spotlight or hit the third-party font management utility to try to find that font. We really want to provide a good user experience for our users and have the fonts available whenever they are. So once again, make sure you use the proper font names. That way, you don't get this performance hit.

And finally, font substitution. Font substitution is great for us developers and for our users. We don't have to worry about what font to use. However, you can abuse it. And the way you can abuse it is, say, you have your application and you specify a font that you want to use, and font substitution kicks in and picks up a glyph that is not on the font that you specified. And typically, this is the case for developers when they want to use a font that they want to use. So if you want to use some symbol or dingbat to show on their user interface, well, be aware, the user can override your fonts.

So if they override your fonts, they can potentially override the font substitution mechanism. So if you want a glyph to be displayed on the screen, make sure that you specify that font that uses that glyph. Otherwise, if you depend on font substitution, you're going to be out of luck. So that concludes my talk.

If you want to leave, I want to point at you this link at the bottom where you can get all information about text and fonts. This is the only place where you're going to find core text documentation other than on the headers. There will be some sessions later on today related to text, internationalizing your software, and text input on the iPhone. And luckily for you guys, you're going to be able to hit us with questions multiple times. So if you have any questions, please feel free to reach out to us. There's three labs where you'll be able to find some of us, or if not most of us.

Later on this afternoon, some of us will be there at the internationalization lab. Tomorrow, there'll be a Cocoa open lab where Cocoa engineers will be there to help answer any questions you have with Cocoa text. And they might even be able to help you with some core text questions as well. And then on Friday, we'll have a core text lab where you'll be able to hit us for core text questions or cords or even Cocoa text questions.