Good afternoon, welcome to Session 226 CoreText and Fonts. My name is Ned Holbrook, I’ll be your tour guide for this afternoon. We’ve got a quite a few things to speak about, so let’s get started. We’re going to be discussing a number of things this afternoon. First of all, we’re going to be discussing new features provided by CoreText in Mountain Lion and iOS 6. The two big ones are new API for accessing line bounds and we’re going to be discussing baseline alignment. We’re also going to be touching on a number of individual techniques. We’ll be giving a quick overview of vertical text.
We’ll be talking about a number of font topics and along the way we’ll also be mentioning some advice for you to keep in mind while working with CoreText in order to avoid any common pitfalls. First, an overview of CoreText, CoreText is the fundamental framework for Unicode text layout and fonts on OS X and iOS. By fundamental, we mean a couple of different things. One is that CoreText is built to live at a very low level in the framework stack. This means that we have provided all the information in a way that’s built to integrate with Quartz 2D or Core Graphics very directly. If you need to drop down even to that lowest level, the information is available to you in the most convenient format possible.
It also means that it has a C interface, so that it’s callable from any sort of application code that you might be invoking it from. But it also means that it serves as the core for a number of higher-level frameworks. This is something that I’m going to be bringing up several times in the talk as well, but essentially what this means is that CoreText is going to be invoked whenever you need high-quality typography through a high-level framework. If you find that your needs are fulfilled by one of those higher-level frameworks, then we encourage you to take advantage of CoreText indirectly, that is don’t worry about coding to the metal or anything, just get your work done in the best way possible.
In particular, CoreText is available in a number of higher-level frameworks. AppKit on OS X of course uses CoreText and presents a wide range of flexibility and power through the Cocoa text system. Core animation makes use of CoreText in order to implement CA text layer for styled text, static text. I’d like to call your attention, especially to UIKit as in iOS 6, UIKit now offers some really great support for attributed strings. The reason I call this out is because there might be some people in this room who are looking at CoreText because previously there was no real UIKit level mechanism for dealing with attributed strings. We are really delighted to have that available in iOS 6.
If you are here just because of that then I encourage you to check out the UIKit sessions on attributed strings. There was one just now that you can catch on video later, I’m sure and there will be another advanced session tomorrow, so you can check your schedule for that. Of course, CoreText is the heart of complex text layout on WebKit as well. This talk assumes that you have used CoreText before. We are going to be talking specifically about CoreText, but again if you are not comfortable dealing with it directly, then please talk to [inaudible 00:03:57]. CoreText of course has been available on OS X since Leopard and iOS 3.2. Basically what that means is that if you are targeting any sort of modern platform at this point, CoreText will be there.
CoreText itself is a top-level framework on iOS, meaning it lives in system library frameworks and that’s where you link to it and also on Mountain Lion, so previous to Mountain Lion CoreText was a part of the application services umbrella framework, which meant that in order to use CoreText, you had to link to application services. But, as I mentioned on Mountain Lion, it is now also a top-level framework. Your existing code will continue to function just fine, but for new OS X projects, we encourage you to go ahead and link to CoreText directly in system library frameworks. [inaudible 00:04:48] if I didn’t point out that ATSUI and ATS for text layout and font management on OS X are still incredibly deprecated.
If you have any legacy code that is still using either of these frameworks, now is definitely the time to plan your exit strategy. In particular some ATS functionality has only relatively recently been moved into CoreText. If you are kind of on the edge there with making the move, we think everything is in place for you now, so if you have any questions about making that transition, please come see us at our lab tomorrow and we’ll be glad to help you with that. The text nerd in me is very excited to be able to talk about some of our new features. This first slide is one of a number on line bounds. When I say line bounds, so of course CoreText takes an attributed string as input and gives you a line with positioned glyphs and all the relevant style information.
When I say line bounds, I mean the measurements that pertain to that CT line object as it’s been laid out. These are the measurements or metrics, we sometimes call them for that laid out line. What I’ve done in this slide is I’ve taken the results of calling an existing API, CTLineGetTypographicBounds on this attributed string or I’ve set this text using the [inaudible 00:06:33] text font. What I’ve done is I’ve constructed a bit of a diagram showing what those values represent. Of course, the width of this rectangle would be the width as returned by the API. Near the lower left, there is a sort of an orange blob, which indicates the line origin that’s kind of a reference point for all the measurements in this particular line.
Then, for this slide, I’ve also indicated the baseline on which the text sits, so basically it’s y=0 across the line there. Of course, the amount of the box below the baseline is the descent and the amount above would be the ascent of the line. One thing to note about this particular example is that the way the font is constructed, you’ll note that there is not quite enough room here. This is kind of a way that some older fonts were constructed, but imagine if this line had an accent above the capital letter here or one of these other letters with ascender. There would be no room for it in the line bounds and so I call this out because internally what CoreText has done in the past when you’re filling a frame using a CT frame setter.
CoreText has applied an adjustment factor in order to pad out the lines to give space for those accented capital letters, because they’re incredibly common in other Latin-based languages, so not in English, you probably wouldn’t see many but for other languages, you certainly would. We need to provide that room so that the text won’t regularly be falling outside of the frame that you supplied. Now, instead I’d like to call a new API. This is available on Mountain Lion and iOS 6, CTLineGetBoundsWithOption. Right now, I am calling this particular API with no options that’s the zero.
I’ll be touching on some options in just a moment, but the one thing that I hope you will note is that compared to the previous results, there is two things. One is that the result, you can’t see on the slide but it is actually returned as simply a CG rectangle or CGRect, since it’s generally a lot easier to deal with a single value being returned from a function than a number of output parameters. That’s with the older function. Also, the default result of calling this new API includes that adjustment that we had previously applied internally that you could sort of deduce by reverse engineering where the line end up in the frame, but now you can simply access that directly. If you needed to match that [inaudible 00:09:18] for whatever reason, then it’s available to you through this new API. Now, as I advance to the next few slides, I want to call your attention in particular to the left and right sides of this rectangle on screen because I’m going to start passing some different options to this API and it’s going to have an effect on either side. Let’s go ahead and advance now as I invoke use optical bounds. This is a very slight difference here, but you may have noticed that the edges of the box have been pulled in a little bit here. What’s going on here is that optical bounds are very closely related to the typographic bounds, the regular measurement of the line.
But, in this case, the font designer has specified that the way that the font is likely to be perceived by our eyes means that they don’t line up exactly with just the glyph measurements. The optical bounds in this case have been designed to pull in on either of these curly quotes here because the way our eyes see rounded shapes. It’s a bit different than the way we see straight lines, so the font designer has compensated for that by providing us information in the font. The next option we’re going to see is going to be a very much more obvious change, as we use hanging punctuation. This is an option, it’s sometimes seen in types of pages, Gutenberg did some of it, but it kind of fell to the wayside.
Well, computers can make this a lot easier. Hanging punctuation is the process of letting the insignificant punctuation in a line hang off of either margin in a frame or on a page. Of course, this requires knowing that that can possibly happen and so not simply clipping the text to the immediate bounds of the frame, but this is certainly a pretty interesting example. One thing I would note is that of course not every glyph can hang off either side. Some of them are limited to just the right or left for instance. This information can come from the font, the AAT prop table has can hang bit that the font designer can set indicating that they want a particular glyph to hang on one side or the other.
But, in the absence of that information since that’s not super common yet, so CoreText also has a list of characters that are appropriate for hanging on the correct sides for standard Roman typography. That’s something you can play with even without a particular font. The last example I’m going to show you how you can combine these two options. Another subtle thing here, but watch on the left side of this box as I advance and you’ll see there the effect of applying both hanging punctuation and optical bounds. What’s happened here is that the font designer has set the cap J so that of course it snug up against that curly quote there.
But, the font designers also decided that when set against the left of margin that cap J should get a little bit of extra space, so that the tail isn’t hanging completely out as it would otherwise. That’s an example of how options can be combined. Another variant of calling this API is to use glyph path bounds, so previous to the availability of CTLineGetBoundsWithOptions and still available is an API called CTLineGetImageBounds. But, it was a bit of a misnomer in that it was doing exactly what this option is doing, which is simply computing the minimum bounding rectangle of all of the glyphs pads in the line. It was also pretty difficult to actually use, if you’ve tried to use it, it’s rather cumbersome.
We wanted to make it available through this new API. It’s a lot simpler to use, but I also wanted to call out the fact that these glyph path bounds are not generally relevant when dealing with typography. Since, as you can imagine it depends greatly on what the particular glyphs in a line are, so you wouldn’t want to use these glyph path bounds when determining how to set two lines one after the other, on top of each other because if one of the lines didn’t have any descenders for instance, which can happen, then of course you wouldn’t see anything below the baseline whatsoever.
This value is more appropriate for input to some other process, maybe you are implementing a drawing application and need to know the coverage of the glyph paths or maybe the glyph paths themselves are part of a graphical conversation that you are using in your application or document handling. But, this is available as another option for the new API. Now it’s all fine and good, I mean information is good but another way to make use of this is to actually apply it and that you can do that automatically using a new paragraph style specifier, which is used by CT frame setter to effect the line edges during frame filling. For instance, if you specified the option for using hanging punctuation and set that on a paragraph style, CT frame setter would automatically hang that punctuation and vary the line lengths appropriately to make that effect possible very easily. The other big feature that we wanted to call your attention to is baseline alignment. This is kind of a case of back to the future. This technology has been around for a while, but it’s been a bit neglected.
But as we expand our global coverage in Apple, one of the things that we learned is that the naïve way of doing things wasn’t sufficient when dealing with mixed scripts or writing systems because some of them have very different typographic conventions relative to Roman text. I wanted to give you some examples of how this is actually useful or why it might be interesting. Certainly, it’s interesting to us and you might have some ideas as to how to put it to use in your application as well. In this example, we have hello world, but world is set in Han characters, so if you speak Chinese for instance it might make sense [inaudible 00:15:54] rough translation there.
This is the layout that you would currently get from CoreText or any higher level framework. It looks okay, what I’ve done is I’ve set that strings in myriad, but of course since myriad the font doesn’t contain either of those Han characters, we have font fallback occurring here. This is a different font that has the Han characters. It looks okay, everything is set on this blue baseline here, which I’m going to call the natural baseline. This is just placing the each glyph origin at Y=0. But, native speaker of Chinese perhaps might note that their baseline actually should sit a bit lower than the standard Roman baseline. By enabling baseline alignment here to let those Han characters sit on the ideographic baseline, a native speaker would feel that this has much better appearance.
This is a bit of a subtle example and so I wanted another example that would make things a bit more obvious. Here’s another hello world, this part in Hindi. What’s interesting about the Devanagari script is that it actually operates on a different notion of a baseline completely. It uses what’s called the hanging baseline. Rather than natively setting on top of a baseline such as this natural baseline here, you’ll see that there is a crossbar from which the letters hang and so a native speaker would expect that when you change the point size of that text that you would actually, if you made it larger, it would actually extend down from that hanging baseline rather than sitting high up as we are used or we English speakers are used to.
I’m going to increase the point size by quite a bit to emphasize the effect, but this is actually the expected behavior for a script that uses a hanging baseline. You’ll see here that even though the line itself still has the expected natural baseline, the larger point size of that Devanagari text causes it to hang down. That’s great but maybe you’re not localizing your application into a language that requires this type of special treatment. The other neat thing about baseline alignment is that you can use it for some more fun effects maybe or something else. We’ll find out what you all can come up with. In this particular example, I’m just going to implement some simple drop caps like you might see at the beginning of a children’s storybook or maybe a magazine that you read uses an effect similar to this. But this example, I’m going to make use of that hanging baseline from the previous example, but I’m just going to apply it manually to these capital letters. In this case, I override the baseline for the Roman glyphs here and set them on the hanging baseline as I change their size. How do you actually do this? Well, each font has multiple baselines. A baseline is essentially a vertical offset relative to that natural baseline I was showing you. There are a number of them that I’ve shown you already, the Roman which in most fonts corresponds to the natural baseline, [inaudible 00:19:23] hanging in there a couple of others for certain purposes. Each glyph in a font is associated with a default baseline, one of those types of baselines is appropriate for each glyph by default. Either the font can specify that or will use the character coverage, the character range in which that character comes from to determine what the baseline should be by default. Then the process of alignment is simply taking two adjacent runs of text, either with different fonts or different attributes. One of them is going to be a reference that is it’s going to stay put and the other one is going to move up or down so that we can pick the same type of baseline from each of those runs and match them up. That’s what baseline alignment is going to be doing. We do this by specifying those alignment parameters using string attributes. The most important one is the reference, which is specified using the reference info attribute and this is what activates baseline alignment. By default that’s disabled because A, we don’t want to be affecting the layout of text that you previously expected to see it in a certain way and also because well, it would be rude.
You need to specify that in some way and then some options are to also give some special definition to the baselines being moved and also overriding which particular baseline in the set of baselines is going to be aligned, otherwise will use the default baseline. This is what it looks like in its simplest form. This is how I implemented both of the hello world examples. What I’ve done is, I have a mutable attribute string. I’m adding my reference info to it and that’s dictionary containing various keys and values, but the important one in this case is the reference font. This defines the set of baselines relative to which I’m going to move anything that might need moving. This will be applied to any fallback fonts for instance and we can also use it in the case of the point size changes. Since a CT font has an inherent point size of course in the Hindi example when we change the point size, the reference font remained unchanged. I didn’t change that in that example at all and so it used the hanging baseline from the original point size. Another slight modification of that example, you’ll note the meat of that code is the same, but then in this case, I’m overriding which baseline is used for the alignment. This is how I would implement the hanging caps example or drop caps. In this case, I’m still specifying my original font as the reference but for those ranges where I want to change that point size in the Hindi Devanagari example, of course I wouldn’t need to do any of this work because those glyphs are naturally associated with a hanging baseline. But, in this case since I want to override the baseline being used, I would simply specify the baseline class attribute indicating that it should be using the handling baseline class. Then I apply it to the appropriate range for those large caps and they hang down. But, in that last example, perhaps the actual height to which those caps were aligned wasn’t quite right and so I could have also modified that by overriding the value that we automatically would use.
But, in this case I’m saying, “Look, I know you had a hanging baseline class all set that was great, but in this case, I think I really want it to be five points above the baseline, the natural baseline and so that’s how I could tweak this.” These values come automatically for the most part for the baseline offsets but of course every one of them is overridable in case you need to specify things more finely. This next class is not a new class at all. It’s been in CoreText since nearly the beginning, but CT font collection received a number of improvements in the Lion timeframe on OS X. I wanted to just remind you of those if you haven’t taken notice before. CT font collection is used for gathering fonts together essentially. It’s a specialized collection class that makes it a lot easier for dealing with fonts, rather than simply putting them in say an array or a set or something like that. But, in Loin, we did improve it. Previously, it had only been available in an immutable variant, now since Lion it’s had a mutable version. We made it easier to cross reference different members of the same font family within a single font collection. These two things together make a lot easier to implement that type of UI that you might see in the OS X font panel for instance. As I mentioned previously about using the highest level framework possible, you may be doing this all from the AppKit level and so AppKit also added NSFontCollection in Lion and of course that’s toll-free bridged with CTFontCollection. Instances of either class can be used interchangeably with either API, either CoreText’s or AppKit’s. It remains the preferred way to enumerate fonts, so if your application needs to get a list of fonts available to it while it’s running, then CTFontCollection is the most efficient way to access that information. Another feature pertains to typographic features. CoreText supports two font formats, both AAT Apple Advanced Typography and OpenType. Both of these font formats have what are called typographic or layout features. There are special rules essentially in the font that change the layout, so a simple example would be a ligature where two glyphs appearing next to each other would get combined into a ligated glyph.
But, there are lots of other typographic features that fonts might offer. Since CoreText’s API is modeled after the AAT font specification, there were some OpenType features that weren’t easily accessible. That is that you couldn’t activate those features in code very easily at all. They were all available through the OS X typography panel, but of course that doesn’t help users on iOS. The way things were is that if you saw an AAT feature specified in our header, SFNTlayouttypes.h and it had a natural equivalence with an OpenType feature, then requesting that AAT feature for an open type font would do the right thing. But, there were quite a few OpenType features that didn’t have a natural correspondence with an existing AAT feature specification. What we have done in Mountain Lion and iOS 6 is we’ve added new AAT features that naturally correspond to one of these OpenType features that was previously inaccessible. In this example, I’m enabling petite caps, which is under the pcap lookup in an OpenType font. We’ve added this new AAT feature in order to activate the OpenType layout for this particular font. This is something we’ll be revisiting in the future. We may add a new API for direct access, but in the meantime, this should get you going with nearly all of the commonly requested OpenType features to enable in your fonts. On a bit of trivia, I would note that as of OS X Lion, AppKitt added NSWritingDirection for specifying bidirectional embedding or overrides. I’m not going to go into it now, but sufficed to say that it’s now implemented at the CoreText level as well, which makes [inaudible 00:27:52] much no difference on OS X, but of course it means that now this feature is available on iOS as well. If you have been making use of that, now you can do so on iOS. Okay, well, we got the easy stuff out of the way, right. Now, this next section is not so much advanced topics as it is perhaps a bit of a grab bag. We hear a number of questions from developers repeatedly and so we thought that we’d address some of these common questions that seem to come up as we talk to you and we also wanted to call out some new tidbits that you might be interested in.
The first is vertical text, perhaps the trickiest thing with vertical text is just figuring out where to start and so I’m not going to delve a lot into vertical text, but I would like to give just a quick overview of what that means from a layout perspective. There are two steps in enabling vertical text. One is getting the right layout that is selecting the proper glyphs for vertical layout and the other is getting the line to go in the right place. Naturally, instead of sitting horizontally across of frame or page or whatever that needs to go vertically. Well, the good news is those two steps are pretty much unrelated other than in the way that they are used. We can demonstrate what it means to enable vertical text by following those two steps in action.
The first thing we’re going to do is we are going to enable those vertical glyphs or activate vertical layout for this line. We’re going to do that by setting a string attribute to a Boolean value of YES and essentially what that does from the line’s perspective, line doesn’t really care what it’s doing here, but if you look at it in a horizontal perspective, it kind of looks like all the [inaudible 00:30:00] line on the sides. Now, all of these glyphs are simply rotated, but in some cases they might require slightly different glyph forms or they might get different metrics or whatever, but for this simple example, I’m just going to show them being rotated.
That’s great, but of course it’s still not very legible and so what we need to do next is we simply just need to rotate that line into place. You’ll note that these are somewhat unrelated, but they’re both necessary for actually making use of vertical text. It’s pretty easy to do that but it’s also not because there’s a lot of rotation involved, some things go one way and other things go the other and the way that our graphic system is based makes it fairly complicated to keep track of all these various transforms that are in flight at one time, so use a higher level framework. If possible, you should check out NSTextView on OS X, it has really great support for vertical writing.
We’d urge you to go that route if at all possible, you’ll get all the benefits of NSTextView besides, if you can’t or don’t want to do that, then CTFramesetter has an option that you can set when creating a frame that will do the rotation for you and take into account the proper bounds for vertical writing. Then of course the vertical glyphs are simply just enabled by the string attribute. But if you are not using one of those, like I said it’s surprisingly complicated and so I would urge you to come talk to us during our lab or grab us some other time and we can talk about what it means and get you going with that.
Font names, so fonts have lots of names. Most fonts have a lot more names than I can show on this slide in fact. If you’re curious, you can take a look at what you can find in font book on OS X, where you’ll see most, if not all of the names in a particular font. But, in this case I wanted to use a particular example of Times New Roman italic. The first name on the slide is the most important. It’s called the PostScript name. We use it internally as a sort of identifier or unique token for each font that is installed on the system. What’s special about this name is, well for one, certain characters are illegal in it. That’s simply a specification thing, so you’ll know there is no spaces, that’s a good giveaway that it’s a PostScript name. But also crucially it’s not localized. Most, if not all other font names can be localized, so Times New Roman might not be Times New Roman in every language. Another thing to note is that although it looks like the full or display name depending on the terminology is unique. You will note that these other two names, the family and style names, those are almost definitely not unique. In particular, the family name is probably shared among other fonts in the same family, so Times New Roman bold for instance would have the same family name. Likewise, the style name is probably that same thing for lots and lots of other fonts on the system. Why does this matter? Well, there is a function that I’m almost positive that you know of, having used CoreText, called CTFontCreateWithName.
This function was designed to accept just the PostScript name, but we made the decision a while ago in order to be a bit more generous and accept any of these names. But the problem is that on a more constrained environment like you would find on an iOS device, this can be quite costly to actually provide a reasonable result for anything other than PostScript name. As I mentioned, you have the case of localized names to deal with, you could also specify the family name, in which case we try to do something consistent. We try to consistently give you the standard weight of that family but that of course means we need to figure out what all of the members in that family are. There is a lot of processing that’s going on and so we got a number of scenarios brought to us by developers, where there’ve been simply creating a font and things kind of just grind to a halt and that’s because we are trying to be nice. We’re going to stop being so lenient, so in a future release of OS X and iOS, we’re going to only accept post script names as the parameter to CTFontCreateWithName because it’s just simply not workable to allow arbitrary names when selecting a particular font. Rest assured, this behavior is going to remain in its current state for any of your applications until they are linked against that future OS, but now is a good time to start updating your code to make sure you’re supplying the right kind of name to CTFontCreateWithName.
What we’ve done in iOS 6, is we added some logging. In this case, someone has inadvertently specified , I don’t know it’s probably the family name for Neue Helvetica, when in fact the PostScript name obviously is going to not have a space for one, but the developer in this case can set a break point on this function in the second log statement and they can check to back trace and see what code is responsible for using the wrong name. You might be asking yourself, “Well, what am I supposed to do if I want to use one of those other names?” Well, we’ve always had a way of doing that. It’s just that it wasn’t really needed because you could just do it the easy way instead.
But, basically what you would want to do in that case, maybe you have a document format that specifies a different type of name or maybe you are even getting data from the Internet, where you can’t really know in advance that it’s going to be PostScript name necessarily. In this case, what you can do is, you can use a font descriptor as a sort of a query. In this case, the attributes specify a family name of Times New Roman and by using that particular attribute when creating matching font descriptors, then you’re telling CoreText that it’s only to consult family names that it knows about in order to find an appropriate font or fonts. There are other attributes, for instance the display name and the style name and you can use those as appropriate. Basically, by signaling your intent by telling us exactly which name you’re trying to find a matching font for, we can do a much better job of not grinding to a halt. Font fallback, some would say is a crucial component to Unicode text layout because up until recently, it’s been impossible to construct a single font that covers all of Unicode and besides doing so would be prohibitively costly and time-consuming. Basically, Unicode wants you to be able to specify any character in the standard and it’s entirely unlikely that you are going to try to adjust the font for every particular character in that string. It’s very important to be able to rely on having a fallback mechanism in place. Our default mechanism for that we call the system cascade, which is a list of fonts that will consult if the specified font does not cover some or one or more of the characters in the string that you asked to layout. But, in some cases developers have asked for a way to modify the behavior of the system cascade. Well, the mechanism we’ve had in place since the beginning of CoreText, is to use this attribute to specify the cascade list or user cascade list as opposed to the system cascade list. What that is is a list of fonts that you can specify as an attribute to either a font or a font descriptor. We will consult those in order, whenever we need to search for fallback prior to consulting the system cascade.
One thing you could also do with mechanism like this is to find out when you want to, some developers have asked us that they don’t want to consult the system cascade at all, they just want to use their own fallback fonts. They want to be able to detect when they have run out of those fonts effectively. All you need is a font that covers every character in Unicode, probably isn’t going to be able to do anything useful with that, but it at least claims to support every character in Unicode. Both of our platforms have a font for that property. It’s called last resort and so if you specify that, it will act as a terminator in the use of fallback cascade list. You can detect that that’s occurred by checking the run attributes on the line and see that that has been the case.
Now, I did say that up until recently, you couldn’t construct a font that covered all of Unicode. Well, Mountain Lion adds support for a new ISO IEC Standard for composite font references. This is an XML standard or XML specification that allows you to define a single font as being built up of multiple component fonts and there’s a lot of attributes and fine-tuning that you can do on that. If you have a very specific fallback functionality to be implemented on Mountain Lion, you could check out the composite font DTD on the Mountain Lion install. A lot of you are embedding fonts in your application bundle most likely by sticking an OpenType or true type font, whatever in your app bundle, maybe in the resources directory somewhere else.
But, some of you have noted that you’ve talked to font vendors and the vendor has a licensing requirement that says that they don’t want you doing that, they don’t want you to be able to just put a font file in your bundle where someone could come along and just snoop it and find it and take it out. I wanted to note that you don’t need fonts to be in their own files in order to activate them for use in your application. Thank you, this has always been the case but we’ve added a lot of the permutations and so you should have a lot of flexibility in being able to do that now. One example would be maybe you want to take the font data and compile it into your application somehow or maybe you want to take a bunch of font files and want to splice them together into a single big file that doesn’t look like a font file on its own, but you know how to extract the individual font pieces out of that. There’s a number of ways to do this. Once you have found the data for the font that you want to activate in your application, one way to do it on Mountain Lion or iOS is to create a graphics font, we call it, or a CGFontRef with that data. Then in this particular example, I’m going to register that graphics font using CTFontManagerRegisterGraphicsFont and by registering it, what that does is it means that I can go ahead and access that font using any of its names.
For instance, if I could use CTFontCreateWithName using the PostScript name on that particular font that I had registered and access it that way. Alternatively, I could create a CT font directly from that graphics font using CTFontCreateWithGraphics. Then on Lion or higher, there is another option that you have, which is to create a font descriptor from that data. That’s another way of doing this. It’s a bit interesting because by doing that, you make that font not available via its names, you need to have that font descriptor on hand in order to create a font from it, same as if you had created a CT font from the graphics font. That way if you for some reason wanted to know exactly what part of your code was making use of that font, then you’d have to hand around this font descriptor, a reference to it in order to create a font from it. We do have some sample code, which we have posted [inaudible 00:43:20], which has an application that demonstrates one technique for doing this. It demonstrates having some fonts that are bundled up, not in the wrong files but bundled up in an application, showing you how to activate that, one way to activate it anyway and also demonstrates using those fonts in a user cascade list. You can see both of these last two slides, there’s a code sample available to you that you can pull down and take a look at.
Emoji, Emoji are these great little graphics, these images that are text, but they’re also colorful and exciting and people have really really gotten into Emoji since they first appeared on iOS and then were adapted to be part of the Unicode specification. We have seen incredible adoption of these, I’m sure you sent or received a few of these guys yourself and many others besides. But there are a few notes to be made when dealing with Emoji. One is that we’ve ended up with sort of a case of Emoji soup. The problem that many people ran into when first trying to make use of Emoji, whether as a developer or as a user is that many of these Emoji characters had been unified as they are called with existing Unicode characters.
In this particular example, if I had a document or a message or something, where I sent it to some other platform and open it up and read it there, I couldn’t be guaranteed whether I would see the text representation, the sort of like my pictograph there are on top or the Emoji representation, which in Lion and iOS 5 was completely different glyph. We have tweaked some things to make some of these problematic lists less problematic, but there are still cases where you may need to programmatically identify which particular representation of one of these unified characters you need. The solution specified by Unicode is to define variation sequences, so these are essentially character tags that you can apply that indicate that one of these particular representations is to be preferred.
If you simply sent that heart character, you wouldn’t be guaranteed any particular appearance. In particular, due to historical constraints, some platforms prefer the text representation, some prefer the Emoji style presentation. But, using a variation sequence for this particular character, the middle example I’ve specified the text variation selector and so if possible, the system will give me the text representation. Of course, the last example there is the Emoji style presentation and so you can control that using those variation sequences. These are supported on both Mountain Lion and iOS 6. In particular, some cases may be your user-interface designer has used a glyph as part of a user interface element and all of a sudden things blew up when things changed due to the Unicode specification. In this case, you can specify exactly what you need. When it comes to drawing color glyphs, the font has to be different in order to carry this color information around with it and so simply using the lowest level function in order to draw glyphs from that font, it is not going to work. But, basically again it comes down to a case of using the highest level framework. If you are simply drawing a string using AppKit, UIKit, whatever, everything will work just fine. If you are using one of the standard CT drawing functions, CT frame draw, line draw, run draw, again that will work just fine. You’ll end up with the standard glyphs or the colored glyphs as necessary. But if you’re trying directly into a CG context yourself, the solution is to use CTFontDrawGlyphs. You can use this on any font. It doesn’t have to be a font with color glyphs. This will do the right thing whether or not it’s a black and white glyph or a color glyph. Simply use that, it’s analogous to that CGContextShowGlyphsAtPositions function and you’ll get the correct behavior. You might also have instances where your font is displaying text using some fancy graphical treatment and that treatment may not work properly in the presence of color glyphs.
If you need to identify that a glyph itself has color data, you can do so by consulting the CTFontSymbolicTraits and if a font supports color glyphs, then you can check for an individual glyph, whether or not it has an outline. The absence of an outline would signify a color glyph. Speaking of drawing into a CGContext, another question that comes up is, “Well, how do I have control over the drawing parameters for that context.” As I mentioned, CoreText was designed to be easily interoperable, directly accessible for use with CGContext drawing if necessary. One instance might be you have some sort of fancy display, where you need to stroke the glyphs with different parameters. You might do it once in one stroke with, then again with another stroke with, but you want to reuse those glyphs that layout between both those drawing operations. You say, [inaudible 00:49:34] I don’t have to specify a different string attribute and then get a new line and draw it, well that’s not necessary. The goal here is that CoreText should only set what it needs to and it should respect what was otherwise set. Let me explain what that means. Most string attributes correspond to a particular drawing parameter that is there is a stroke with stringed attribute and if you specify that, it should take [inaudible 00:50:04] whatever was said in that CGContext that you are going to draw into. But if it’s absent and since it’s defined as being unset, it doesn’t affect the drawing parameter for the [inaudible 00:50:15], then you should be able to specify that directly as a context drawing parameter and then make sure that that attribute isn’t present in the string that you are laying out. That way, you can set it to your first value, draw the string and then set it to the next value and draw the string. CoreText will respect that because of course it’s just drawing through core graphics itself, but that way you will have very fine [inaudible 00:50:37] control over what is getting set in that context. One exception to the rule of course is the foreground color, as was mentioned in the attributed strings introduction, just previous to this session. That attribute has a default value of black and so if you want to modify the foreground color between drawing a line, then of course you will need to specify foreground color from context attribute name. It take a Boolean and when that’s set to true, CoreText will not touch that drawing parameter either.
Finally, one more oldie but goody, CoreText will not synthesize missing font styles and by missing, I mean you might expect coming from other platforms or older technologies that you can simply request a bold font and get a bold version of whatever font you are using. Well, CoreText has always taken the approach that it should prefer the information given to it by the font. The font designer hasn’t gone to the trouble of drawing a bold version of the font, then CoreText is not going to take upon itself to try to make [inaudible 00:51:50]. But, there are some developers who need to be able to bold arbitrary fonts, perhaps they have some document format that requires that they indicate a bold font or some other reason.
You can certainly implement your own synthetic styles in your application, but this is something that CoreText is still not going to ever do, so one approach for instance for synthesizing an italic would be just simply skew the font matrix and that would give you a slanted appearance, not a true italic appearance, but that might be one way. For bolding, there’s really no one [inaudible 00:52:31], there is no one great way of doing that. Of course if you need any more information, there are number of nice links here to Jake Behrens who is the evangelist. He can help you locate information if you are having a hard time with that. Otherwise, of course there is the standard documentation and interface guidelines.
Developer forums are very very helpful resource for finding out from your peer developers how to make use of this technology more effectively and also Apple engineers. Again, very very interesting stuff given in the UIKit sessions on attributed strings. You will have already missed the introduction to attributed strings session as it’s passed now, but you’ll be able to catch it on [inaudible 00:53:16] I’m sure. Also, the advanced attributed strings session is going on tomorrow morning at 10:15, so I urge you to check that out. There’s going to be some really neat stuff discussed there. With that I’d say thank you very much and have a wonderful rest of the conference.