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: wwdc2004-425
$eventId
ID of event: wwdc2004
$eventContentId
ID of session without event part: 425
$eventShortId
Shortened ID of event: wwdc04
$year
Year of session: 2004
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC04 • Session 425

Modern Text Layout and Editing for Carbon Applications

Application • 58:50

Using Carbon Text? If so, you should view this session. We discuss the API options for rendering, laying out, and editing text in your Carbon application, and help you decide on the best approach. We discuss how to use the MLTE API for objects bound to an HITextView, work with monostyled text, "chat" text fields, and much more. You'll get performance tips and tricks to optimize API usage when setting up an MLTE object and adding large amounts of styled text or pictures to it, as well as other common usage scenarios. Finally, we discuss the internal enhancements to MLTE and ATSUI that will benefit your applications without changes to your code.

Speakers: Giulia Pagallo, Tom Madden

Unlisted on Apple Developer site

Transcript

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

Good afternoon, everyone. Please welcome, from Apple Computer, Manager of Text Input and Fonts, Giulia Pagallo. Welcome to session 425. I hope you guys are having an excellent conference this year. When we were putting the session together, we were wondering what percentage of the developers attending the session would be new to the area of Carbon Text and what percentage would be returning developers. So let me start by asking, how many are new to this area? Any? Anybody? All right.

Good. How many of you are already using some of the Carbon Text APIs for Mac OS X? Excellent. We have a session that is packed with information for both you, the new developers, so that you can quickly orient yourself in this area, and for you, the developers who have been using our APIs release after release.

In particular, I'm going to start by giving you an overview of the Carbon Text API landscape. And I'm going to talk about the APIs for static text, as well as the APIs for editable text. After that, I'm going to turn my attention to the HITextView APIs, and the MLT APIs for editable text. And then I'm going to turn the presentation to Tom Madden, one of the engineers in the ATSUI team. And he's going to talk to you about ATSUI, which are the APIs you use for laying out text.

So say that a lot of the applications have a need for static text, either for your labels and your controls, for your text and your dialogues, or some bits and pieces in general of text. And for static text, there are basically four components that play a key role in this area.

So at the bottom of my diagram is Quartz, the Apple 2D drawing engine, which provides beautiful, crisp, anti-aliased text on the screen. A client of Quartz is at SUI Apple Type Services for Unicode, which is the component responsible for positioning the glyphs correctly on your documents. And also breaking the lines of text correctly. Whatever language you are using at the time, whether it is Japanese, Chinese, or Roman language, at SUI does the right job.

The next level up is either the Appearance Manager in the high-level toolbox or the MLTE APIs, which stands for Multilingual Text Engine. In 95% of the cases, 99% of the cases, the API that you should use for static text that we recommend you use is the HITheme Text APIs.

However, there are situations in which you need control over rotated text, in which you need control over the graphic context, or you need to use fonts other than the ones the HI theme fonts provide. In that case, we recommend you look at the two APIs that MLTE provides for static text. Is that not enough? You need additional control for your static text? Then you should look at the ATSUI APIs. Tom Madden Tom is going to talk to you about them in the second portion of this presentation.

The same components that play a role for static text play a role for editable text, and you see them on the screen. Now, let's say that you have a mail-like application where you have some small text fields on the top of your window, say, for your recipient or your subject of the email, and some large text areas for the content of your email.

Which APIs should you use? So for the small text fields, we recommend you use the Unicode controls. And those are being available in the system since the first version of Mac OS X. For the large text area, if you have an application currently running Mac OS and you are using the system APIs, you're probably using MLT directly, which is good.

However, we recommend that for Tiger and beyond you transition to use the HITextView APIs in conjunction with MLT. And I'm gonna tell you why in a second. But before I move on, I also want to point out that if you are developing your own text engine, in that case, you want to use the ATSUI APIs directly. And again, Tom is gonna talk to you about that.

In summary, if you have static text, for most cases, take a look at the HIT theme text box APIs if you need additional control over styles. The graphic context, you need to rotate your text. Take a look at TXN draw CFString text box API and those are in the MLT header.

And if you need additional control over how your text is rendered, please look at the For edited text, for text fields, as I said, use the Unicode Control, and that the API that is on the screen is the API create Unicode Edit Text Control is the API you call to create one such text field. And for text areas, again, for target and beyond, we recommend you start using HITextView in conjunction with MLTE.

Now, I'm hearing some of you back in the room saying, I have an application. I'm using the MLT API for my text area. They work beautifully. Why should I move on and transition to HITextView? And here are six reasons. And there will probably be more in the future.

So if you attended the high-level toolbox session during the conference this year, you heard that the high-level toolbox team is working hard, has been working hard in modernizing the Carbon toolbox and being transitioning to a hierarchical view model. If you use HITextView, your text area will belong to the hierarchy. And the advantage of that is that then internally we can take We can use that information to optimize, for instance, the rendering of your objects. In addition, the order of the Carbon events is well defined if your text area is an HITextView.

Also, throughout the conference, we've been pointing out the importance of supporting accessibility so that your application is available to a wider set of customers. If you use HITextView, accessibility is built in in your text area. There is no work that you need to do in order to make your text area accessible. Compositing is also supported in HITextView. And in addition, it's very easy to create an HITextView using the tools that Apple provides.

And I'm going to show you how to do that in a minute. Last but not least, if you have an HITextView, the MLTE object is available to you so that you can extract that object from the HITextView and you can reuse all of that code that you already have in customizing your text area using the MLTE APIs.

Now, let me take a quick detour for those of you who are new to the area of Carbon Text and tell you what are the advantages of using MLTE. What does MLTE provide? So, MLT is a full Unicode layout and edited engine. And what that does mean to you is that your text area are gonna support all of the languages the Mac OS X supports. You don't need to worry about the upgrades to the Unicode standard. You don't need to worry about learning about how bidirectional text works. That is there for you.

In addition, because we leveraged at ZUI, we have advanced typography. I suggest you go and use the typography panel in conjunction with MLT in Tiger to see how you can take advantage of all the rich features that we have in the fonts to produce some beautiful text. Of course, we have anti-alias text. And MLT also provides built-in support for multimedia, which is important because these days it's very rare the document that contains text only.

Another advantage of MLTE APIs is that they provide support for the basic functionality without requiring for you to write any code. So, for instance, you get input, text input, from any of the input methods in the system, whether they are character palettes, keyboard layouts, input methods, ink, they just work.

Selection, drag and drop are built in, and we also added support for the document access, which are new Carbon events that were introduced in Panther. Now, if that is not enough, if you need customization for your text area, MLTE provides a simple set of APIs that allow you to customize the text area to your needs.

And I'm going to show you how to do that in a second. But most important, I think, MLT is an evolving and growing set of APIs. We've been listening to your feedback, and we really thank you for that, of what are the areas that are important to you. What are the areas where you need new APIs to customize your text area? And so, I like to think of the improvement in MLT in two areas. On the one hand, we have the improvement that we do under the hood.

That's the work that we do at Apple, so that your application provides richer and richer behavior without you making any changes whatsoever to your code. And I'm going to give you an example of that. On the other hand, we have new APIs based on your feedback that allow you to customize your application and deliver to your customers the functionality they need.

So let's talk a little bit about what we've been working on. What are the areas where you can see enhancements in MRT? As there are more and more Carbon and Cocoa applications in the system, we think it's important that the users get a consistent behavior as they switch from one application to the other. So we've been working closely with the Cocoa team to provide a consistent behavior. This is work in progress, but you can notice that there has been some improvements in this area.

the customers are there are more and more multilingual. So we've been working on improving the multilingual experience in your text areas. In particular, I want to point out that we have added support for Glyph Variants in Tiger, so that for instance, you can use the typography panel, use one of the fonts that has Glyph Variants built in, and you can choose the glyph that you want to represent your name. This is for instance, important to our Japanese users. You can see on the second line on my screen is three of the spellings for the last name Watanabe.

The second character is different in each of the ways they spell it, and this is important to Japanese users. In addition, the Kotori team has been working on improving the conversion accuracy of their input method, and the way they did that is by leveraging some new Carbon events that allow the input method to get access to the context in your text area. We added that support in MLTE so that your text areas get better conversion accuracy for Japanese.

At the feedback session yesterday, we heard that it's important to many of you improvements in Arabic support. And I wanted to point out that we've been working on improving our bidirectional text in MLTE. For instance, in Panther, we improved how the character moves at the boundaries between Roman and Arabic text. We're not there yet, we know, but we are making progress.

Also, as Mac OS X evolves, we've been involved in the implementation of MLT. You heard at the conference that Quick Draw APIs have been deprecated. We had removed that code path in MLT so now that you get ATSUI and CG only. In addition, we transitioned our implementation to use QuickTime importers so that now you have a wider set of file formats that you can import into your the Maltese text area.

And also we've been working on performance. Performance, performance, performance was our mantra during the Panther release. And what I show you on the screen is some of the results that we have between improvements that we have between 10.2 and 10.3. For instance, reading in a text document, the performance of that operation is 400 times faster. Scrolling text is 250 times faster. And if you select all the text in your document and change the style, it's 160 times faster.

I want to point out that these improvements are not only the result of the effort of the MLTE team. We work closely with the CG and the ASUI folks and the rest of the engineers at Apple. So this is the result of the combined effort. The performance improvement that you have in the current Tiger build are very much comparable to the Panther GM results. And, and we've been working on that. So I do expect that by the time we ship Tiger, those numbers are going to look even better.

That's old. What's new? What is new in Tiger? So I'm very happy to announce that we were able to implement all of the commonly requested APIs in MLT for Tiger. So let me start on that list. First of all, we have undo groups. And what an undo group is basically is a sequence of actions that are bracketed between a begin and an end API so that you can give the illusion to your users when they go and click on the undo item that all of those actions are undone as a single one.

And the reason why that is important to some of you is because some... There are situations in which you want to initialize your text object with some text, change the style, add some pictures, but then you want your user to undo all of those operations as one. Take a look at the APIs that are in the headers. There are also some related APIs that are used so that you can correctly handle the undo menu or let MLTE handle the undo menu correctly.

Let's talk about scrolling. By default, MLTE scrolls. And some of you love it, and some of you hate it. And the reason why some of you don't like that default behavior is because it's not suited for your application. So let's say that you have an application that writes status results to your text window as it runs. One of your users is looking at the window and is reviewing the results.

In the meantime, the application is adding data to the bottom of your text area. Well, MLTE is going to scroll. And that might be a disconcerting behavior. So for Tiger, we added some new tags that you can control the scrolling behavior the way you like it. You can have it as it is by default. You can make MLTE behave like the terminal in the scrolling behavior, or you can tell MLTE, don't scroll at all until I ask you to do so.

As I mentioned before, if you're using HITextView, you get accessibility support for free. However, if you need to continue, your application needs to work on back to Panther, or for whatever other reason, and you want to continue to use the MLTE API, we're providing you an API to add accessibility support to your text areas.

the TXN save and the TXN read APIs were showing their age. They used some old data structures. On the one hand, on the other hand, we wanted to add support for RTFD. We added support for RTF during the bantered release. In JAGWARE, we wanted to extend the support and be even more compatible with the Cocoa stack and add RTFD support.

In addition, some of you have been asking for APIs that allow them to save and retrieve information from memory. So for TIGER, we added two APIs to read and write to CFData and two APIs to read and write from CFURL. In addition, there is an auxiliary API that allows you to decide what is the best file format that you need to use in order to save your data without losing any information. And that is important, for instance, if you want to decide whether to use RTF or whether to use RTF or plain text.

Another API that we added, actually, two APIs, we added to set and get the event target. There's been some confusion in the past of where MLT installed their Carbon event handlers, and so -- although I haven't seen any feedback on that area recently -- there was an outstanding request for APIs that allow you to set and get the target event -- the target for the Carbon events in MLT, and those are there in MLT. We also added better ways for you to turn on HI command handling, and I'm going to go in some detail on the -- about those APIs in a minute.

Two more things. We added support for spell checking, and we added support for the font panel. So now, with very few lines of code, spell checking is working in your text area. And with very few lines of code, the font panel is also working. And not only the main font panel, but the color subpanel, the character palette, the typography panel. And if some of you have tried to do it, that's quite a fair amount of work. So we have simplified that implementation.

All right. So two words of caution. One is as Steve mentioned, we're showing you Tiger soon a lot earlier than other releases. So the APIs are there, the basic implementation is there, but we're still working on that. So the second word that I wanna say is, please give them a try. We've been implementing them in response to your request. We love to hear what you have to say and whether there are things that we need to tweak.

So what I want now to do is a more hands-on approach. I'm going to show you how to build an HITex view to show you that even managers can do it, and how to actually customize it, and then I'm going to move on and give you some tips and tricks about optimization. So can I have the demo machine please? The other demo machine. Thank you. So I have Interface Builder running.

Thank you. So I'm going to create a Carbon app with the menu, made with the menu bar. And just for the purpose of this demonstration so that you can see the contrast between the background and the text area, I'm going to make it metal. And now I'm going to drag and drop from the Carbon palette the text area. I'm going to resize it. Oops.

Resize it. And I'm going to do one more thing. I'm going to give the TextView a signature and an ID so that later on I can retrieve it in my application. I'm going to give it the signature text, and the ID is 0. And I'm ready to go. So I have an HITextView with an MLTE object inside it. And I can type. Maybe. I can switch to Japanese and I can type Japanese, have written no line of code. I can bring up WordText and I can copy and paste.

So, all of that by just dragging and dropping in a few clicks. So what, can I have these slides? Thanks. So that shows you how to build your HITextView. But, and maybe the basic functionality is all you need. But say that you need to add some margins, you want to retrieve the text, you want to add some text programmatically.

Then in that case if you need to customize your HITextView, you want to use the MLT APIs. And if you have been doing so, that you can transition your creation of the text area to use HITextView and then take advantage of all the other code that you already have.

SO THIS IS MY DETOUR FOR THE FOLKS THAT ARE NEW TO THIS AREA. SO LET ME -- I'M GOING TO GIVE YOU SOME BASICS ABOUT MLT. IT IS VERY SIMPLE. MLT REPRESENTS YOUR TEXT AREA, YOUR DOCUMENT WITH A TXN OBJECT, WHICH IS AN OPAQUE OBJECT. IT USES OBJECT-WIDE CONTROLS, WHICH ARE CALLED OBJECT CONTROLS.

AND MLT USES THE CONCEPT OF STYLE ATTRIB UTES THAT ARE BY RAND. SO FOR INSTANCE, YOU CAN HAVE YOUR TEXT IS DIVIDED IN CHUN KS. SO FOR OFFSET 0 TO OFFSET 10, YOUR TEXT IS LUCIDA POINT SIZE 10 BLUE. FROM OFFSET 11 TO OFFSET 15 IS HOEFFLER TEXT POINT SIZE 18 GREEN AND SO ON AND SO FORTH.

Now another key concept to MLT is Carbon Events and I wanted to say four things about that. The first one is if you're using an HITax View MLT is going to install the Carbon event handlers on the owning view and it's going to install all of them at creation time. Some of them are going to be turned on, some are not going to be are going to be off.

But the important point here is they're all installed at the same time. The reason why that is important so you have a good picture of where in the stack of your Carbon events MLT has put its own event handlers. By default we turn on the input the text input events so that you can type in using any of the input methods and the document access events which are used by the input methods as well. In addition you can turn on support for the HI commands whether it's for your edit menu, for spell checking on the font or for the font panel.

But those are off by default and you can turn it on later. So that ends my detour. Now remember we had our HITax View and I'm going to show you how to extract the MLT object. So here it is. First of all we have a constant that allows us to identify that particular view in our hierarchy.

After that, I'm going to call some standard high-level toolbox APIs to find the root of the hierarchy and extract the particular view that I'm interested in, in this case, the HITextView. And once I have the HITextView, I can call hiTextView getTxnObject, and that gives me the MLTE object. Now, I'm good to go.

All right. So to show you how to use the MLTE APIs, I'm going to-- Demonstrate how you can turn on spell checking. And it's going to be very simple. An MLT leverages the HICommand support that we added for Tiger to turn on spell checking. So let me remind you what are the HICommands. So we have two flavors of HICommands.

HICommand process events, which are the events that are sent when your user clicks on a menu item or selects a menu item or clicks on a control. And then there are the HIUpdate status events, which are the events that are dispatched to your application when a UI element needs updating. For instance, before your menu comes up, you get one of those events so that you have a chance to update the information in the look of the items in your menu.

We recommend that you handle all of the HI commands for the menu, or none of them, to avoid compatibility issues in the future. And that's actually the way we did it for MLTE. So for Tiger, we are introducing the TXN SetCommand event support, which allows you to turn on and off support for basically three groups of HI commands: for editing, for style checking, and for the font panel.

And those three flavors work for processing and update status. I'm not going to go through the details that you see on the table, but suffice it to say that you have three options that you can turn on, and those enable the handling of the HI commands in MLTE. So for instance, if you decide that you want MLTE to handle the edit command processing events, MLTE will do so, and it will handle the undo, redo, select all, and so on.

Now, how do we turn spell checking on? Very simple. We set the options for the HRI commands that we want, the spell checking in this case, and then we call txnSetCommandEventSupport with the MLTE object and the options that we set. And that's it. From that point on, spell checking is going to work.

Now, what is it going to--what is it that you're going to see in your application when you turn spell checking on? So if you have misspells, they're going to show up as red dotted underlines. In addition, we provide a contextual support for the contextual menu, and we added some APIs so that you can modify the content of that contextual menu if you choose to. So MLTE is going to handle the contextual menu, but we're going to give you a choice to modify it as you need.

And also, we provide support for the spelling panel. So if the HRI command for the spelling panel is sent, MLTE will react to that and show the spelling panel so that your users can select the dictionary, learn a new word, spelling, and so on. If that looks familiar to you, that is because we implemented the same UI as Cocoa. So we were talking about the consistency between Carbon and Cocoa, and we wanted to, you know, enrich that. So the UI is exactly the same. You use the same spell checking engine and the same set of to be able to dictionize.

All right. So with that, I showed you how to create your HITextView, how to extract the MLTE object, how to customize it. Now, as important as that to use the APIs, it's important also that you use them correctly. And I'm going to give you some tips that we learned over the recent months by working with developers and analyzing the performance of their application.

So the first one is, There are cases in which you don't need all of the rich style text that MLT supports. What you really need is mono style text. In that case we recommend you use KTXN mono style text mask when you create your object. That allows us to optimize the break line operations because the height, the height of the text is constant.

For Tiger we introduced the KTXN disable layout and draw tag, which is useful when you do multiple sequential modifications to your MLT object. So basically what you want to do is you want to set the mask on, modify your object, turn it off and draw. And that way MLT will not draw and break lines in between operations. That is the same behavior as the KTXN visibility tag. But the name was really confusing so we decided to introduce a tag that has a name for what it really does.

If your text ends with carriage returns then you want to use the KTXN word wrap state tag and set it to not wrap. That way we can avoid doing unnecessary line breaks, which could be an expensive operation in the case of Unicode and text. As important as the do tips are the things that you should not do. The model in MLT and HA TextView is that MLT reacts to changes to the object by redrawing.

So in most cases you do not need to call TXN draw. One exception is if you use the TXN disable layout and draw tag after you re-enable layout and draw tag. You want to call TXN draw. And that is because that was implemented a long time ago that way and we didn't want to change it to avoid performance impact.

Also, unless you really do need it, do not use the KTXN Always Rapid View Edge mask. What that mask does is keeps your destination rectangle of your text pinned to the view rect of your window. So as you resize your window, your text, we're crazily breaking lines and redrawing your text.

And that, sometimes, is not the behavior you want. So keep an eye on that. If you need it, feel free to use it. We improved the performance of that operation quite a bit. But if you didn't need it, don't set it. All right. And with that, I'm going to give you a quick demo of the KTXN.

The new APIs working on Tiger. Let me clean up. So what I have here is MLTE Showcase. That's an application that we put together. One of the engineers in the team wrote for WWDC. You have it in your SDK. Feel free to play with it and give us feedback.

So what you see is the large text area is an HITextView with an MLTE object. The small text area on top of that is a Unicode control, and we put some radio buttons to control the behavior because one of the feedbacks that we heard is that you want to be able to manage the behavior of your text objects from any kinds of controls, not only from menus. So the first thing I'm going to do is I'm going to turn on spell checking, and I am going to start typing. And I have practiced this so well that I cannot make a typing mistake.

There you are. So as I type, the red dotted underline comes up, and all of the lines, of course, are the code that have been executed as the one that I showed you. We don't have contextual menus still working yet in this application, but it will be there soon. And there it is. Okay, let me move on to the font panel. And I'm going to select this paragraph. I'm going to change the font.

[Transcript missing]

As you see, I have all of the different options for changing the style from the font panel, working with MLTE objects. I can even bring up the color palette and change the color. I can Strike through? I can underline. So all of the different palettes just work.

And again, this is by turning off the HI command event support in MLTE. We have here a way to show you how the undo groups work, but I'm not going to have time to go into that. And so let me just show you the no scrolling in action. So let me copy, copy. All right. Never mind. As I said, this is work in progress. Let me copy the text, and let me put my instruction point at the bottom.

And now I'm going to paste it. And as you see, as I paste the text, MLT is going to scroll. So now I'm going to turn no scrolling. And I'm going to start pasting. Nothing happens. As you see, the scroll bar is getting smaller, because the size of my text object is increasing. And actually, the text is being pasted at the bottom of the object.

But there is no scrolling, actually. Next to Write Your Buttons is going to show you how to use reading and writing to a CFURL. And you can take a look at that and, again, give us feedback. And with that, I'm going to end up the MLT session. And I'm going to turn the presentation to Tom Madden. Thank you. How's everybody doing? Good conference? So my name's Tom Madden. I'm an engineer. And I've been working at SUI for a little while now. Well, let's get started.

ATSUI is an acronym. It stands for Apple Type Services for Unicode Imaging. Today I'm going to cover kind of what it is and why you should use it. I'm going to cover some basic ATSUI constructs, some things you would need to know to get started using ATSUI. I'm going to cover how to do some line breaking, drawing. Then I'm going to cover some advanced features, and I'm going to give you some performance tips for those of you who are considering using ATSUI or have already adopted it.

So without further ado, what is ATSUI? Well, ATSUI is the low-level Unicode layout engine. ATSUI is used by all those things that Giulia just showed to actually take the Unicode text that's used as an input and display it on the screen. ATSUI provides layout services for all those things, plus it provides some services for AppKit. It provides services for Safari and a whole bunch of other apps.

So you might be asking yourself, what is layout? We've been using the word "layout" the whole presentation. Some of you may or may not know what it is. Well, layout is simply the process of taking the Unicode text and converting it to glyphs and positions, which get then fed into the Quartz rendering engine. The glyphs and the positions are determined by two things. First of all, the layout tables that are embedded in the font. atsui supports OpenType font layout tables, which are the gpos and the gsub table, as well as the aatfont layout tables.

It's always supported those. In addition to the layout tables, it also requires character properties. Unicode has a great character properties database where it can find all sorts of information about the characters. So it takes those two bits of data, munches them together, and out come the glyphs and the positions.

Besides the standard character to glyph mapping, reordering and stuff like that that's required by layout, Atsui also does a couple other things. The first is automatic font substitution. Automatic font substitution allows Atsui to substitute a new font should the font that you have selected not be able to map the characters that the user has input into Atsui. So for instance, let's say you have selected Times New Roman and then the user has input a Japanese text.

Times New Roman can't display Japanese, so ATSUI will go out and substitute a new font for it, most likely Hiragino. Additionally, ATSUI provides API for style management. There's an ATSUI style object, which I'll get into in a minute. It provides API for line breaking, which can be pretty tricky in the case of Unicode. And it also provides API to help you if you had an editable document.

So you've seen all the stuff that Julia has. You've seen the MLTE. You've seen the HITextView. You might be asking yourself, why should you use ATSUI directly? Well, if you need the ultimate control over the text, you would use ATSUI. With ATSUI, you can control the line breaks. You can control the exact position of the text. You can even go into the glyphs and change their positions directly. In addition, ATSUI provides broader options for tracking, justification, kerning, flushness, and all this other stuff that you may want to control directly.

In addition, if you have custom rendering paths, such as you want to go out to, say, an OpenGL context or something like that, you may want to use ATSUI as well. What ATSUI will also get you, switching to ATSUI directly, is speed. In a sense, those APIs that Julia mentioned and a lot of the other APIs in the system, their whole purpose is to feed ATSUI Unicode text and to manage the ATSUI objects for you. But if you can do a better job at doing that, then you will get faster operations, because these objects, in some cases, were designed for a more general case.

So you've decided, OK, I need to use ATSUI. So what do you need to know to get started? Well, the first is you need to know about Unicode. The Unicode text buffer that you provide to ATSUI must be in the UTF-16 format. ATSUI doesn't accept UTF-8, doesn't accept UTF-32, only accepts UTF-16. You can get your text in the UTF-16 format using CFString or Text Encoding Converter, whatever. It just has to be in UTF-16 format. The second thing that's very important is that you own the text buffer.

You can't free the text buffer out from ATSUI. If you do that, bad things will happen. ATSUI does not retain the text buffer. ATSUI doesn't do anything like that. You manage it. You own it. And likewise, if you should change any of the text in that text buffer, you have to notify ATSUI. So if you insert text, delete text, move the buffer around, you have to call an API, which I'll show you in a minute.

Finally, one important note that has tripped up more than one person is that the character to glyph mapping is not necessarily one-to-one, even in the case of simple ASCII English/Roman text. So, one of the most blatant examples is the FI ligature. You have an F character and an I character, which combine to form a single glyph. And so if your code makes assumptions that there will be one character for one glyph, it will break in a lot of cases.

So you have your Unicode Text Buffer. It's in UTF-16. It's ready to go. You want to do something with it. So what do you do with it? The first thing you have to do is tell ATSUI where it is. And you do that by creating an ATSU Text Layout. The ATSU Text Layout is simply an object that references your Unicode Text Buffer.

Inside that ATSUI Text Layout, it also tracks the style assignments. So you take a range of that buffer and you assign it to Helvetica, you assign it to Times, you assign it to different fonts or different styles. It also tracks the line breaks, it tracks the font fallbacks, which allow you to customize that font substitution behavior that I talked about earlier. And it also tracks the tab rulers and the tab stops.

You modify this Hatsutext layout by setting layout and line controls on it, and there's a couple APIs that allow you to do that. And finally, and perhaps most importantly, the Hatsutext layout will store the cached lines of glyphs. And so if you're constantly creating these things and throwing them out, you're going to get rid of a lot of work, and your application will run slower, because that whole layout process that I had that graphic up there for, that can be an expensive process, because it has to read in font tables and interpret the characters. If you throw that work out and have to recreate it, your application is doing a lot of extra work.

So to create an ATSU text layout, it's pretty simple. We have an API called ATSU Create Text Layout. You just call ATSU Create Text Layout, and you have a layout. It's empty. It doesn't do anything yet. So you have to assign some text to it. We have an API called ATSU Set Text Pointer Location.

You call that to set-- you could assign the buffer to it. And then finally, we always recommend that you call ATSU Set Transient Font Matching. This will turn on the font substitution behavior, as I described before. It's off by default. If you don't turn this on, what will happen is, if you should encounter some text that your currently selected font can't render, you'll get ugly little boxes, and that's not pretty.

So you have your ATSU text layout, it's kind of boring. It doesn't really do anything yet. In fact, if you try and pass it to a draw API or a measurement API, you'll get an error because it doesn't know what to do yet. So to make it much more useful, you have to assign a font to it. You have to assign some style to it.

And so you do that with the ATSU style object, which is simply a collection of the stylistic attributes. It's the font, the color, the point size, all this stuff that you want to kind of stylize the text with. You take that ATSU style and you assign it to a range of text within that ATSU text layout.

Now an important point is that once it's assigned to an ATSU text layout, you can go ahead and assign it to as many other ATSU text layouts as you want. It's not tied to any specific text layout. You can reuse it over and over again. In fact, that's recommended because you'll be creating fewer objects.

So to create an ATSU text style, the first thing you do is you call @SU_CREATE_STYLE. and that creates a blank style. It's set up with all the defaults. In fact, you can use it right away. It's just maybe not what you want. I think it's set up with Helvetica, 12-point, and a couple other defaults.

So to get it into a shape that you would want to be able to use it in, you have to set some attributes to it. Here I'm setting the font tag, which will set a font, a specific font to that style, and a size tag, which will set a specific size to that style.

Once I have the tag set up, I call atsu set attributes with the tags and the values, and that will set everything up, and it'll be ready to go. So once you have your ATSUI style set up, you assign it to the text layout to arrange in the text layout using ATSUI's set run style.

So your text layout is all ready to go. You have the style set, you have all the text in it, but there's one problem. It's all one line. And so for some folks that may be OK, but if you have an application that requires line wrapping or line breaking, you need to call Atsui to do the line breaking for you. Atsui has two line breaking APIs.

One is called Atsui Batch Breaklines, and that's an API that is optimized for breaking constant width lines. And so for instance, if you were breaking inside a rectangle or if you were breaking down a constant width barrier, you could use Atsui Batch Breaklines. Atsui Breakline could be used for the situation pictured above, where you would want to vary the line width. In this case, we're trying to wrap around an object, so the line widths on this side are a little shorter than the line widths below.

So, ATSUI Batch Breaklines sets multiple breaklines at once, and it requires that you have a constant width, and so if you're breaking into a box. Atsu batch breaklines is used simple. The first thing we recommend is that you set the width in the object. You can specify a width to the batch breaklines API, but the problem is that width is only used for line breaking.

So if you go and apply a flushness or a centering or some other "If you have an API that requires a width, that width won't apply. So you would need to go and set the width anyway. So we recommend you just do it before. So you do @susetlayoutcontrols with that width, and then you simply call @subatchbreaklines, and it'll go down and set all the line breaks to that width you've specified." If you need to do non-constant width breaking, if you need to vary the line width, if you need to do other things like that, we have the ATSUI Breakline API, and that will let you set the width for every operation.

An important thing here is to let ATSUI set the line break once it's found it. ATSU break line can be used in a mode where it can just find the break for you, which may be what you want. But it's recommended that you let ATSUI set the break once it's found it, and you do that by passing in a parameter, which I'll show you in a minute. This is important because if you don't let ATSUI set the break, it will have to go back and re-figure out that break when you go and set it. So you'll throw out a little bit of work.

So this code up here does the same exact code as the batch break lines example that I showed you. It just uses the break line API. So like before, the first thing you do is you set the line width. In this case, we're using a constant width. The next thing you'll probably want to do is get the character count so you know where to stop breaking the lines. You set the break to start at the beginning. Then you call atsu break line in a loop until it's consumed all the characters.

So the next thing you'll probably want to do is, now that you have your nice ATSUI text layout, you have all the lines broken, you have all the styles assigned, is that you'll probably want to draw it. AtSUI has a function called @SUDrawText, and the important point here is it draws one line at a time. So you'll have to draw those lines individually.

You should always specify a CG context, and you do that via a text or a line layout option or a line or a text layout option in the ATSUI text layout. You do ATSUI set layout attributes with the CG context, and then it'll be set in the text layout.

The reason why you do that, because if you don't set a text layout, ATSUI has a quick draw fallback mode. And so if you don't set a CG context, it'll have to go through and look up a CG context for you from the current quick draw port, which is a very expensive operation. So if you set that CG context beforehand, you'll avoid all that work. Another important thing to remember when you draw text is that you need to flush the CG context. If you don't flush the CG context, you probably won't see anything.

"But you should only flush it once. And so if you're drawing a whole paragraph worth of text, you want to flush it after you've drawn all the lines." So some of you have needs. You're writing a text editor, you're writing an application that has editable text. You'll need to use some editing APIs. ATSUI has hit testing and cursor handling APIs. I'm not going to go through those.

We have highlighting APIs to handle the highlighting and unhighlighting of text. And these are kind of useful because in Unicode text, the highlighted areas can be discontinuous depending on the directionality and such of the text. In addition, we have three APIs that will be required should you ever insert or delete or move text, and they're listed up there on the screen.

Some advanced features that ATSUI has that you may be interested in is we have the ATSU Glyph Selector to specify a glyph variant. You specify this ATSU Glyph Selector in the style, and that allows you to do the glyph variant support that Giulia showed you that MLTE handles for you.

ATSUI also has the ATSU Direct Access calls, and these allow you to get exact glyphs and glyph positions and all sorts of other information out of the layout for those of you who want to do your own positional manipulations or supply your own metrics. ATSUI also has some flattening APIs for pasteboard exports. This will allow you to take the ATSUI styles that you've set in the layout, flatten them all to a binary format so you can put them all up on the pasteboard or save them to disk.

And finally, ATSUI has some curve access APIs. And these are really cool because they allow you to get at the curves that ATSUI is giving to the graphics engine to draw the glyphs. So some applications, such as Motion, have used these. "I'm going to show you how to actually do animated text and other cool effects with those curves." So some folks have asked for some performance tips, besides some of the ones that have been given throughout the presentation. You should use the ATSU Git Glyph Bounds API for measuring the text whenever possible.

ATSUI provides several APIs for measurement, and this is the only one that's guaranteed not to upset any of the cached data. Some of the APIs require it to do some extra processing work to get the correct measurement, the measurement that you requested for. This will give you a typographic bounds that's guaranteed to not upset the cached layout.

Second thing, if you are getting the curves, you should call atsu.getNativeCurveType before accessing the curves and set up your curve callbacks according to the result of that. Some fonts have curves stored in cubics. Some fonts have curves stored in quadratics. And if you use the wrong type, ATSUI has to convert the cubes to quads and the quads to cubes.

And that's not an expensive process and may give you some ugly looking text if you go to draw those curves. Finally, if there's anything that you should take away from in terms of ATSUI performance, is that you should maximize the object lifetimes, meaning that you should not throw away these objects until you're absolutely done with them. Keep the text layout objects around. Keep the ATSU style objects around. Following that, you want to minimize the object creation. You want to create as few ATSUI styles as possible, and you want to create as few ATSUI text layouts as your application requires.

So that wraps up the ATSUI section of the session. And there's a couple things that you should take away. First is that you should use the HIThemeText API for static text. It makes things a lot easier. You can create these things in Project Builder. Second, use the Unicode Control API.

So that wraps up the ATSUI section of the session. And there's a couple things that you should take away. First is that you should use the HIThemeText API for static text. It makes things a lot easier. You can create these things in Project Builder. Second, use the Unicode Control API.

Fifth, use the API optimally for the best performance. That includes keeping objects around, not throwing them out, creating as few objects as possible, turning off visibility on your MLTE objects when you're doing lots of edits and stuff like that. And finally, you need to file bug reports should you see anything wrong.

We're doing our best to test these things, but every now and then, Well, I shouldn't say every now and then, but we get very good bug reports from you guys from the field, and we do fix those, and we do see those problems. So with that, I'd like to bring up Xavier for the wrap-up and the Q&A. Thank you.