Carbon • 59:09
Apple Type Services for Unicode Imaging (ATSUI) enables the rendering of Unicode-encoded text wit advanced typographic features. This session explains the concepts behind ATSUI, explores its performance, and discusses new additions to the current ATSUI API set.
Speakers: Xavier Legros, Tom Madden, Aaron Haney
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Hi everybody. This is not a French lesson, so you don't have to repeat every time I'm saying something. My name is Xavier Legros, and I work in the Worldwide Developer Relations, and my job is to evangelize our international and macro-standard technologies in general. I'd like to welcome you to this session about drawing UniCode text with ATSUI, ATSUI, which is Apple Type Services for UniCode Imaging. If we can do a quick test, how many of you, and you could raise your hand, have been using or looking into using ATSUI? Excellent. So I guess I can just quit right now and go directly to the new features.
Anyway, we still have a quick introduction about what ATSUI is and a set of the current features and some of the concepts. A lot of people, a lot of developers have been coming to us and saying, you know, ATSUI does a lot of things for me, but there are a couple of things I don't understand, which are because we're doing so many things and the way ATSUI is handled and architecture is very different than Quick Draw. I'm going to go quickly today around these concepts, hopefully giving you a better idea on how to make the best use of ATSUI.
So what is ATSUI? ATSUI is at the heart of the drawing system on Mac OS X. When you see the finder drawing static text, the menu manager at one point or another, it's ATSUI text being drawn. And that's very important to understand because in order to make Mac OS X a truly international system, we had to go through a Unicode. And the only way to display Unicode on the system is to use ATSUI.
The main feature is the support for UniCode 3.2. And this support is for actually what we call our layout technology, our layout engine. And the concept of layout is actually pretty important if you want to support correctly languages, international languages. So the nice thing with ATSUI is that through one set of APIs, you're going to be able to render virtually all languages.
You heard in the keynote, for instance, with Scott Forstall about all these new languages that we're going to be supporting. All the Arabic, Hebrew, for Baidai, all the Indic scripts, even Hawaiian. In order to support these languages, you have to use UniCode. And on the Carbon application, you will have to use directly or indirectly ATSUI.
ATSUI is going to enable you to support combining characters and complex scripts. And, best, it's going to enable you to support languages that before on Mac OS 9 you couldn't access. Because of the limitation of Word Script 1 and Word Script 2, and the way encodings work, you never were able before to access the languages. Using ATSUI and UniCode is the solution for this need. Another nice thing, another nice feature that ATSUI offers is the font substitution support.
ATSUI has this concept of fonts, and ATSUI will know what font to display, what font to use to display certain characters. And you can see this behavior, for instance, when you use the Draw Theme Text Box APIs. Use a theme font ID, which is kind of a conceptual font, and with the same font ID, you're going to be able to actually display Japanese and Roman text in the same color. That works because of two things. Because you're passing UniCode, and the second part, It's because that's who he knows about this concept of phone fallbacks.
There is another point in ATSUI that maybe not all of you are aware of, or maybe not all of you want to use, but the second part is advanced typography. And ATSUI, with that regard, is very, very powerful. ATSUI is going to enable you to support things such as kerning, optical alignment, variation fonts, ligature, leaf alternatives, which is a new feature that we're actually adding in Mac OS X Jaguar, baseline adjustment, and there are many, many other style attributes that are not supported in Quick Draw Text. Things like, for instance, displaying a chemical equation. Now with ATSUI, it's a matter of setting a style attribute. It's very easy and straightforward. I encourage you to look at the documentation.
Of course, one of the main features for CGK users is vertical text. And here, ATSUI, once again, supports very easily vertical text through two type attributes. One through the style, where you're going to be able to set a style attribute to say that the glyph has to be vertical. And the second one is by enabling developers to do variation rotation of the layout to display vertical text at an angle.
Another set of features that come with ATSUI APIs is a set of editing, what we call editing APIs. These APIs are here to help you manage the cursor, manage click inside text, do highlighting. And it gets very, very important because cursor movement in a true multilingual environment is not, you know, you don't move a cursor one byte, one character. Because, for instance, with Chinese, it's going to be different. With Arabic, it's going to be completely different. Well, ATSUI, through like one easy set of APIs, will enable you to manage actually cursor movement for all the languages that we support.
And of course, the most visible thing that everybody at the beginning wanted is the Quartz support, which is the main difference between people using Quick Draw Text and ATSUI. The integration between Quartz, our powerful 2D rendering engine, and ATSUI, our UniCode layout, is very, very well done. And you can use both of the feature sets together to get to some very amazing results and some very, very amazing display of text. And I'll show you that in the demo. I think it will be better.
So once again, quickly, ATSUI and Quartz are fully integrated. The first thing you see, of course, is the anti-aliasing. But the second part of that is that by combining CG and ATSUI, you're going to be able to access all the spatial effects, I would say, that you can set in the CG context.
So things such as color space, where you're going to be able to pass a color space to your CG context. And ATSUI will respect that. Things like, for instance, transformation of the matrix for rotation, scaling, skewing, that you can do with a CG context. ATSUI will respect all these things. And the very nice thing is that you get results there that were very, very difficult to achieve before with Quick Draw Text.
Here, for instance, we have a nice example of a line of text that has different encodings. And with a simple call to ATSUI, you're going to be able to actually display these scripts. And here we have Roman, UniCode. This is Japanese. I think we have Inuktitut and Georgian, if I'm not mistaken, at the end.
And here, the second example is like, you know, the support for advanced typography. Here, we have the Zapfino font, which is a very cursive font, and the only way to display it correctly is to use ATSUI. You can see the ligatures between the P and the F. Oops, sorry about that.
So here we have some kind of a diagram that shows you the architecture and where ATSUI resides in the system. ATSUI is part of the application services framework. And at one point or another, most of the toolbox is going to be coding in it. So the menu manager, or it could be directly on a Carbon application. So let me take you quickly through how you could use ATSUI. You have different levels, once again, to use ATSUI. As a Carbon application, you could actually link directly against the application services and use all the ATSUI APIs.
That's the solution. The second solution is to use higher-level APIs, such as DrawThemeTextBox, which has a set of APIs to measure and draw Unicode text. The DrawThemeTextBox APIs, for instance, use ATSUI, or wrappers, or what ATSUI calls. The Finder, for instance, uses the toolbox and ATSUI directly. If you're a Cocoa application, it's important to understand that if you need fine control on the layout, you have two solutions. You could use the Cocoa Text Engine, which one point or the other will code into ATSUI, will call into AdSuite, or you could use it directly from your Cocoa app.
Another thing that is important to understand is that ATSUI has been around for a long time. On Mac OS X, it really blossoms and it really takes advantage of all this advanced architecture that we have. But you still have a choice of using Quick Draw for rendering, if you wish. I would not encourage you to do so because of such a nice integration between a quads rendering or 2D rendering.
And just because the fact is that if you go for Quick Draw, you won't get as much like such a nice NTSSing. And then the default, and what we encourage you to use, of course, is to use ATSUI and Core Graphics. And at the bottom, of course, you have ATS, Apple Type Services, which has all the management for fonts. And we had a session this morning. Hopefully you went to see that.
So, when should I use ATSUI directly? As a developer, it's very important for you to understand what technology you need to use in your application, what makes more sense. If you need fine control on the glyph positioning, if you need to display specific features, text at an angle or text on a path, for instance, if you want to do your own line positioning, if you want to access directly advanced typography, if you have very specific needs for markets such as Chinese and Japanese and do vertical text, you will have to use ATSUI directly. ATSUI would be the answer for you.
The second point is if you need, as I said, advanced typographic features for text positioning, for instance, or ligatures, swashes, you will have to use ATSUI directly as well. And of course, if you're writing your own text engine and MLT, the multilingual text engine, is not enough for you, you will have to use ATSUI directly as well.
I'm going to go through a couple of concepts very quickly on how ATSUI works and what are the main pieces you need to use. Let's see. So first, what we have most of the time is that we have a flow of text. So we have a pointer on UniCode text, or we could have a CFString with UTF-16 text inside.
The first thing you create is a text layout. An ATSUI text layout has to represent, or should represent, I should say, a paragraph. Why a paragraph? A paragraph because in order to do, for instance, buy-die reordering, we need to have this concept of paragraph. If you display buy-die scripts, for instance, such as Arabic and Hebrew, the text will not be displayed correctly if you do the drawing style by style. So the concept of paragraph is very important for you to remember. And here, for instance, we have three different paragraphs. We created three different ATSUI text layouts.
The UniCode buffer, as I said, you pass it to the layouts. Very, very important. You own the text buffer. The text buffer is UTF-16, two byte UniCode, and ATSUI doesn't make a copy. It just keeps a pointer on, you know, a part of the text. and then of course we have three different styles. And here we have, you know, you can see that the style has been reused between the first and the second layout. And I'll go in more details about these concepts.
So what's an ATSUI style? An ATSUI style is an OPAC object that represents a collection of stylistic attributes. And once again, remember, you can reuse, if you wish, an ATSUI style. If, let's say, you're using Geneva 9 Italic in different parts of your document, you don't have to duplicate that ATSUI style, okay? You can just reuse it in different layouts.
So, of course, in the style, we store things such as the font, the size, the color. But then, as I said before, ATSUI supports way many more features than what we used to have in a quick draw text, for instance. So in there as well, you could have things such as is the text vertical, things such as kernel, optical alignment, hanging punctuation, width and cross-stream shift, which are very specific to ATSUI.
In the style as well -- I'm sorry -- are stored font features. And once again, these font features are stored in the font. So the style will say if, you know, ligatures are on, if you want caps, if you want swashes, if you want variant glyphs, and font variations, which are another aspect of the advanced typography that ATSUI supports.
That's sweet text layout. You have to understand that sweet text layout is the heart of all your drawing. That sweet text layout is going to combine your text pointer and your styles. And it's going to have a set of features to cache information about the text. So, ATSUI is going to store in the layout all the information it needs in order to display the text correctly.
So, it's going to store a reference to your pointer on the text, and then it's going to store as well references to the styles. It's going to combine them together. It's going to track as well the soft breaks and the tap stops for you. And there is another set of features that are supported through the layout, which are layout and line controls. And I'm going to go into details about what I mean by line controls.
Line controls are attributes such as width, rotation of the layout, justification, flushness, baseline. And the important thing to understand is that these attributes don't have to be assigned to the whole paragraph. They can be assigned to a line. It's very, very powerful and I encourage you actually to look into the details of how all the attributes, line controls, that ATSUI supports. But, it seems all of you already know all the concepts around ATSUI and have been looking into that. Let me show you a quick demo. If we can switch to my PowerBook here.
Okay, great. So, first thing, main advantage in ATSUI is that it's UniCode layout and rendering. It gives you access to, for instance, all the character sets we put in the Ragino font. 22,000 glyphs. The only way to access this is to do UniCode. If you're a common application, you have to use ATSUI. If you're a Cocoa application, you could use actually the already existing infrastructure that actually will do the correct thing and use ATSUI at one point of your layout. Here you can see, for instance, some of the characters are available only, only through ATSUI.
There is another thing that is very important because we say it gives a great advantage if you have markets in CGK. If you're shipping an application right now for Japan, China, and Korea, ATSUI will give you definitely an advantage, an edge on the competition. Because you're going to be able to access, of course, all these glyphs that nobody else has been able to display before. And here we have a couple of examples actually from names with variants in it that nobody else could use before we introduced this technology.
But what does that mean, for instance, for a current font like a font like Chainscree that all of us have been using? What does it mean to do UniCode layout? Well, here you can see I'm going to start typing, and you probably all see this demo. I've been around for like years now. And here you can see the combining of the L's.
The next thing I can go is what I said. What does that mean, advanced typography? Well, advanced typography means actually I can change the way the text is displayed. I don't change the back storage, but I change it the way it's displayed. And here, I'm sorry, but I don't really like English. I prefer French.
So here I can change, for instance, the graphism, which is like the design level. And here you can see I get the nice wash between the L and the O. Oh, it looks very nice. Actually, if I go back here, and for those of you that want to see what that means in Japanese, I can put it in Japanese if you prefer.
Unicode Support and Advanced Typography. I'm following a couple of mailing lists and one of them is CarbonDev and if you're an ADC member you're probably one of them. And I had this person, his name is Nick Nalik, and wanted to write some kind of Unicode applications and he wanted to find more about ATSUI.
And he saw one of my demos and he liked Vortex and he said, "Hey, you know what, I'd like to do the same thing and really show how cool the integration between Quartz and ATSUI is." So he wrote this application which is called Quartz Draw. I'm trying to get him to change to be ATSUI Draw, but you know, marketing is not my forte. So here I can actually select my text.
A nice thing, as I said, is that ATSUI supports vertical text, and here with a quick flag, I'm going to switch the vertical text. I'm going to copy that. I'm going to go in quarts here. I'm going to copy and paste. So here, in fact, it's using ATSUI.
Here, what do I have? This is a Carbon application that is using core graphics to do the rendering, and is using ATSUI to do the text display. Well, the cool thing is that through the CG context, I get support for many things. So I can actually switch all the characters, and this is from my PowerBook. You know, I have 256 meg of RAM. I mean, it's pretty fast. Probably doesn't look right anymore for, like, the pure linguist. I can scan. I can translate. I can rotate very easily. And here, for instance, we're going to do 90 degrees. That should be enough.
And here, very quickly, I have, like, you know, vertical text support. Okay, that's cool. No big deal here. Well, the nice thing with core graphics is that it supports PDF. So what about we put a PDF in there? Okay, so I'm going to put a PDF. This file is one megabyte. Bye, bye, bye.
So I have one file, one megabyte, okay, that's cool, no big deal. I'm going to scale that 50% just so we can see the tour Eiffel and the text. Well, the nice thing is that here we have a concept of layers and the text is drawn below. Let me bring it forward if I'm not mistaken.
And you can see that ATSUI is still displayed on top. There is no prime. ATSUI supports all the CG context attributes, so it's not going to do any arrays. ATSUI's business is to draw international text as quickly and as best as possible. That means for that, with a simple set of APIs, what we want is you guys to be able to support all the languages that are on the planet, as long as you have appropriate font. So here, ATSUI is not in the business of erasing the background and stuff like that. It just wants to display the text. So I can do that. The nice thing is that I can go back and copy a bunch of text if I wish.
I can move back the text. And here, the important thing is that it's the integration, to show you the integration between the cross-rendering and ATSUI. It's seamless. I can do all the changes, rotation. I can sketch the text. It's just up to you to find out what you want to do. And you know what's the cool thing with that? The cool thing is that because ATSUI is completely integrated with Core Graphics, I can actually just save the text as a PDF file.
I save the file, everything is going to be embedded in a PDF, you can send it to the printer, or you can send it to a Windows machine, the font is going to be embedded, you're going to have high resolution PDF, everything is going to be vectorized, and you don't have to change your code.
There is one thing that people actually always ask is like, how do you get all these drop shadows? Well, let me show you how you get the drop shadows. I can actually put like, I don't know if it's very easy here to see. I can change the height of the shadow.
Can you see the text? I can change the way the text is displayed on the shadow. So everything is happening in real time. And if you saw the demo on Monday morning about quartz compositing, well, by default, you're gonna get that for free because everything here goes through the CG context. You're gonna get the support and the hardware acceleration when you're gonna be drawing using CG context. And here are the cool things that I can continue to type. Here I can type "Tokyo" and see everything's happening very quickly. Okay, if we could switch back to the slides.
But we've got a lot of feedback on what ATSUI does and how you guys are using it. And this year for Jaguar, we've been doing a lot of progress and a lot of improvements, not only on the feature point of view, but the way you guys are going to be able to use, and I would say abuse, ATSUI. And to talk about the new features we've been working on in Jaguar, I'd like to introduce Tom Madden, who has been working actually on ATSUI and is going to be talking about all these features we put in the system.
As he said, my name is Tom Madden. I'm here mainly because there was this rumor floating around that you could only demo ATSUI if you were French. But that turns out to be not true, and I'm actually going to go through some of the new features we have planned for Jaguar.
So the new features list is: we have new features for batch line breaking, tab support. We have a new feature called direct access, which I'll go into a little bit more. We have new style flattening options. We have a new option to show variant glyphs. We have some new options to specify font fallbacks. We have some more information on thread safety, as well as some new text measurement attributes.
So the first new feature we have is this batch line breaking. And this will allow you to use ATSUI in a much more paragraph-based form as we've been telling you to use it. It can reduce the overall line breaking time by up to 50 percent and you'll actually end up executing less code than ATSU break line. It's a single API to do all your line breaking.
So, previously to using batch breakline, we had this breakline loop. You basically looped on ATSU breakline until you set all the breaklines, and then you could get the number of breaklines you actually set at the end by calling @su.getsoft.breaklines. This works pretty well, and you still need to do it in some cases.
The new API is called ATSU Batch Breaklines. There's no looping involved. We'll do the looping for you, and this actually helps save some time because ATSUI can better optimize itself for the text it's breaking. ATSU Batch Breaklines can only be used if the maximum line break width for all the lines is the same. This is very handy for breaking text into neat little rectangles or breaking it down alongside a window. But if you're doing something a little bit more advanced, such as wrapping the text around an object or doing odd-shaped lines, you'll still need to loop around ATSUI Breakline.
The next new feature we have is tab support. Now this will simplify the task of implementing a ruler in your ATSUI document. Tab stops can now be set in an ATSUI text layout object, and we've provided two new APIs to set and get those. The new data types for tab support include the ATSUI tab, which basically specifies where the tab is and what the tab type is. We're supporting left, right, and center flush tabs.
The next new feature we have to support is called ATSUI Direct Access. ATSUI Direct Access is a little bit different. Today I'm going to go through exactly what it is, what it can be used for, and how do I use it, as well as I'll have a little bit of a demo showing some of the stuff you can do with it.
What is Direct Access? Well, Direct Access is a new set of APIs. It will allow you to directly access the glyph data during the layout process and will allow you control over the layout process through the use of callbacks. You can totally override one of ATSUI's layout operations or you can just let it go.
So what can I use Direct Access for? Well, you can use it for finer control over the layout metrics. You can tweak just about any sort of glyph data you can imagine. You can use it to override ATSUI's internal layout operations, and you can even use it to replace glyphs during the layout process.
So, how do I use Direct Access before I introduce the API? To use Direct Access, you would just install this callback on the operations you wish to override. You are allowed to install one callback and you need to pick the operations that you want. We have a new operation override tag that you use with the ATSU Set Layout Controls API and use that to set the callback that you wish to use. Then you simply call ATSUI normally to measure and draw and then your callback will be invoked every time ATSUI needs to relay out that line.
This is kind of like, I don't know if you guys watch late night TV, you know, Ronco, set it and forget it. So, ATSUI's layout operations include, we have linguistic operations, and these are necessary for proper display in many languages, as well as they provide some nice features in English. These linguistic operations include the bidirectional level calculation and the glyph morphing.
This is to form ligatures and contextual forms and whatnot. Beyond that, we also have kerning, tracking, baselines, and justification. So, which one of those can I override with direct access? You can override justification, morph, kerning, baseline, tracking, and in addition we're allowing you to override what's called the post layout. And that's going to allow you to access the glyph data after ATSUI has done all its work. So you can tweak things in the final process.
Notably absent from this list is ByteEye. You can't override ByteEye. So the callback implementation looks like this. You basically just have to implement something that looks like this. And your task will be first to determine the reason why that callback was triggered. And we have this parameter that's passed into you called iCurrentOperation. That's simply a bit field and you just and it with the various operations for which you've installed the callback. As I said before, you only get one callback and it gets called for all these operations. So it's up to you to determine why it was called.
If you only installed it for one operation, then you don't have to pay attention to that. Then you can use this second parameter called ilineref to actually get the glyph data. And I'll go into that next. There's an API that can be used to get direct access to the glyph data.
You can then tweak the glyph data in whatever means you wish to do. And then you return it to the glyph data. And you can see that it's now in the OCallbackStatus parameter. And there's two options for status right now, which basically says continue to process the data or do nothing. And that's just a key to Atsui to tell it what to do next. So if you still wanted ATSUI to run that operation, you can if you decide not to handle it yourself.
So, as I mentioned before, you use that ilineref parameter. You can use that to get the data from inside the callback. And we provided an API to do this. This is called atsu-direct-get-layout-data-array-pointer -from-lineref. Pretty long. And it returns a direct pointer to the data. So you can change it, you can mess with that pointer, you can change any of the data in it, and there's a couple different pointers you can get, which I'll go into soon. Because it returns a direct pointer to the data, it's pretty fast. I mean, most of the stuff will return in constant time. There's a couple that will return in order-end time.
Based on the number of glyphs in that line. But you must dispose of this data pointer by calling this other API, @SUDIRECT_RELEASE_DATA_ARRAY_POINTER, and that will serve not only to release any possibly dynamically allocated memory, but will also serve as a key to @SUI that you're done with this data, and if it needs to do any merge operation to merge any changes you've done to the array.
So, you might be wondering, okay, I set up the callback and... I don't want to set up a callback, but I still want to get the data. Well, we've provided another API called @SUDIRECT_GIT_LAYOUT_DATA_ARRAY_POINTER_ FROM_TEXT_LAYOUT. And this one will return a copy of the data. It doesn't return a direct pointer, but it will allow you to access that data outside of the callback. This means you can't change anything when you're outside the callback. Just like the previous API, you still need to dispose of it by calling the @SUDIRECT_RELEASED_LAYOUT_DATA_ARRAY_PO INTER API.
So, what data makes an ATSUI glyph? In other words, what can I tweak? Well, ATSUI data is all based on a baseline, and well, general layout data is all based on the baseline. And I have some glyphs up on the screen. And the first thing that, or actually this is the final thing that makes up an ATSUI glyph, and that's the real position. The real position is the actual laid out position of the glyph. And this is actually calculated during the layout stages, the late layout stages, and why we provided the post layout callback.
So you can tweak this real position. The other things that make up an ATSUI glyph include this advanced delta. The advanced delta is set by various processes such as justification and other things. And it's basically the difference between the next glyph's real position and the previous glyph's advance.
The final piece of data is the baseline delta. The baseline delta is any adjustment above or below the baseline. These are all signed values, so you can actually set them negative if you want the glyphs to collide or if you want them to hover below the baseline or whatever.
So the actual data structures that kind of make up the glyph are the ATS layout record, and that's kind of like the core, the atom of what a glyph is. This includes the actual real position, which, as I said, is calculated in the later layout stages. That's the position of the final layout glyph, the glyph ref, the actual glyph ID of the glyph, some various flags, which, if you look through the headers, some of them are kind of interesting, and I'll kind of show you one interesting use of them in the demo.
And the original offset, which is the offset in the Unicode array that originally spawned this glyph. Beyond that, we have the baseline delta, which was introduced before, the advanced delta, the style index, which is an index into another parallel array, which will get you actually the style of that glyph. And a device delta, which is kind of available for tweaking.
The position after the layout is done to fit it into device space and whatnot. So, I'd like to introduce-- I have a little bit of a demo, kind of showing you what you can do. So I wrote this little app. and I will be joined by Tom Madden, Tom Madden, Aaron Haney, and David Keefe.
The first thing we are going to do is to go to the demo, which is obviously enough called Direct Access Demo. Basically, you can take...you have your ATSUI rendering this kind of plain string, and so you can do kind of mundane things to it. Like, you can play with...you can override the justification routine and change the advanced deltas to stretch and to shrink the line.
Or you can even do more advanced things like you can use a combination of the call to do a simple whitespace replace. And this was actually very difficult to do previously without upsetting the line metrics. This one actually just grabs the glyph array and swaps glyph IDs with another layout that just includes this dot character. And so you can change things.
You can even say lay out things on a sine wave if you override the apply baselines routine. and just change the baseline and of course you can change the font, whatever. And all the standard ATSUI features work. For instance, you can rotate the text. and it's still shown as a sine wave. And you can type.
It's kind of hypnotic. And you can also do the whitespace replace. That's kind of hard to see. Yeah, so it just kind of works with all the ATSUI features, including caret positions and hit testing, because you're messing with the actual ATSUI layout. All right, can you bring back the slides? Beyond direct access, we have some new APIs to flatten style run data to stream and then go ahead and reconstruct that data from a stream.
This was kind of hard to do before, and it was even harder if you tried to parse the pasteboard data coming out of MLTE to stick in your own ATSUI app. So we've provided APIs to do that for you, and they all work based on the standard pasteboard format for UniCode-styled text, which is called the USTL version 2.0.
And this is used by MLTE, and it's understood by Cocoa applications, and it's totally defined publicly, which means if you don't think we're doing a good enough job flattening these things and restoring them, you can parse them yourself. You can actually store more data in these USTL versions of the ATSUI API.
So we've provided APIs to do that for you, and they all work based on the standard pasteboard format for UniCode-styled text, which is called the USTL version 2.0. And so if you want to do more USTL structures than ATSUI currently recognizes, which you may want to do, you can store advanced layout data. You can store your line breaks in there if you want. But ATSUI will only recognize the style data portion of the structure.
So to flatten the styles, we have the new API, Flatten Style Runs to Stream, and this is used to flatten multiple style runs into a stream of data. You just need to pass your ATSUI style objects and an array of run links and an allocated buffer, and you get back a filled allocated buffer that has these styles and runs flattened to it.
Once you're on the other end, like if you're reading data from the pasteboard or whatnot, we have another API to reconstruct those streams, and that's the ATSUI unflattened style runs from stream. Now this returns the style objects and run information into separate arrays. This will also create ATSUI style objects on behalf of you.
You'll be responsible for disposing of any ATSUI style objects created by this call to avoid leaking memory. The caller is responsible also for matching up the style runs to the associated Unicode text. ATSUI is not going to create layouts for you. It's not going to actually tag any text with these runs. You actually have to do that yourself.
What this will return is where the style objects and where to put them in that Unicode run, in that Unicode buffer. So you can usually get this off the pasteboard. The Unicode text, the raw Unicode text, is usually exported as U-text data, and MLTE, for instance, will export alongside of that a USTL, and they match up perfectly. The runs in the USTL match up to the runs with the associated U-text data.
The next feature that we have, or we, the next feature that is proposed for Jaguar is for variant glyph access. This one's kind of interesting in that it will, it lets you display glyphs that do not have an explicit Unicode character to glyph mapping, but are rather variants of a glyph that does have an explicit Unicode to glyph mapping. This will allow you access to characters in the fonts that otherwise would not be accessible.
[Transcript missing]
There are lots. Our Hiragino fonts have lots of these variants in them. So to support variant glyphs, we have a new style tag. You basically just apply the style to the character that you want to have a variation on, or the character which when converted to a glyph will be variented. And we have a new attribute structure.
This attribute structure will let you choose the variant glyph by either a font-specific glyph or even a CID. And you can get this information from the input method via the Text Services Manager. And we have a new event parameter, the event param text input glyph info array event parameter. And this is available to just about any of the events that return UniCode text. You do have to kind of set up TSM, your TSM document a little bit to tell it that you're willing to get these characters. But that information is available in the TSM header.
The next new feature, which is actually in 10.1, but we've never really been able to present it until now, is the use of font fallbacks objects. Font fallbacks objects allow you to specify a search order for font substitution. As Xavier said before, ATSUI has this great feature of substituting a font if the current font doesn't have the character that you're trying to display.
This list is basically just a reference to a list of ATSUI font IDs. And then you take this list and you attach it to an ATSUI text layout object. This is safer than relying on the global font fallbacks list. ATSUI always allowed you to change this font fallbacks list, but it was always on a global basis. Global meaning application-wide.
As more and more things start to use ATSUI, they start to use their fallbacks list. This includes toolbox things and possibly even other threads in your application. If you're always using this global font fallbacks list, you'll run into unexpected results, possibly, if it gets changed out from under you. Beyond that, it will also cache information about what fonts can display what glyphs.
We have new APIs to create, destroy, and manage these objects. They're all up there: ATSUI Create, ATSUI Create Font Fallbacks, ATSUI Dispose Font Fallbacks, and a couple to set the Font Fallbacks in the object. And these Font Fallback objects should be shared if possible. They're not tied to any specific layout. You can set them in all your layouts. You can set them in just one layout. But as I said before, they do cache some information. So if you're continually destroying and creating these, then you'll definitely have a bit of a performance penalty.
Now I'd kind of like to talk about ATSUI's thread safety. Previously we've said that at suey style objects and at suey font fallback objects are thread-safe and that the APIs are thread-safe. The only thing that wasn't thread-safe was the text layout object. In Jaguar, all the at suey objects are now thread-safe, but you still need to be careful with the global font fallbacks list because, as I said before, another thread can change it out from under you and may cause unexpected results. It won't cause a crash or anything. It will just cause the text to be rendered in fonts that maybe you didn't want.
We also have some new options for text measurement. And before I go into that, a little bit of a review is in order, because we always get a lot of questions about the various text measurement APIs in ATSUI. The first thing that I'd like to review is typographic-first image bounds, because there's various APIs in ATSUI that provide for this measurement.
So, as you can see, the image bounds is kind of the box around the area in which ATSUI will draw the text. It doesn't have any slack for anything. It's just a solid box around the text that's going to be drawn. The typographic bounds, on the other hand, includes space for any possible ascenders or descenders. As you can see from the top example, the image bounds and the typographic bounds are pretty different.
The typographic bounds includes any space, because there's no descenders on that line. It includes kind of a little bit of a space there. Now, this space is actually specified by the font and not picked out of the air by ATSUI. The bottom text, the image bounds, begins to approach the typographic bounds as the descenders are applied, in terms of the double P there. the double P there.
The first text measurement API, this isn't anything new, but we thought that we should probably review this, is @SUGitGlyphBounds. This API returns the typographic bounds of the final line. This will return the bounds in terms of trapezoids, which is kind of scary in the beginning, but it's not as nice as dealing with the boxes, but you can calculate height pretty easily if you rely on your high school geometry. This is useful for laying out line after line of text.
This is really useful if you're doing, for instance, a text editor or a word processor, where when you're typing, you don't want the text to bounce up and down every time an ascender or a descender is added. This will, because it's the typographic bounds, it leaves enough room for that.
The next API we have is ATSUI Measure Text Image, and this one simply returns the image bounds of the final laid-out line. This returns the bounds in terms of a rectangle, and it's aligned on integer boundaries because it's designed for screen. It's useful for figuring out the exact area in which ATSUI would draw, as I mentioned before.
The third one is probably the most abused and How should I say this nicely? This one is used a lot mainly because people see that it returns an ascent and a descent in the parameters list. And so they get all excited. It's like, oh, it's an API that returns the ascent and the descent. I don't have to do any math.
The problem with that is this API returns the typographic bounds of a line prior to final line layout, which means that if ATSUI has already laid out the line, for instance, if you've already done a draw or another type of measurement operation on the line, this guy will go ahead and remove that line and go ahead and lay it out again without many of the features turned on. This is useful mainly if you want to calculate your own line breaking. As I said before, it'll ignore any previously set line attributes such as flushness, justification, rotation and that's why it'll force in an extra layout.
The new options are we have an ascent tag and a descent plus letting tag. And the ascent tag is the KATSU line ascent tag and there's a descent tag too. And you simply use these with the ATSU Git line control and ATSU Git layout control API to get the ascent and descent. These were previously in ATSUI. It's just that now even if you don't set them, they'll return the actual values. Before they would only return values if you had set them.
These will return the values that ATSUI is using to lay out the line. There's also, it's not on the slide, but supposed to be, or it's planned for Jaguar, there's going to be a set of tags that are similar like this where you can get the ascent and descent of a style. So you can actually query the style to get that information, which means you don't even have to have a layout.
That kind of concludes the new features for ATSUI that are planned for Jaguar. I'd like to bring up now Aaron Haney, who's going to go through some tricks and tips on how to better optimize your ATSUI code. Aaron? Thanks, Tom. In this part of the presentation, we're just gonna give you a few little tips and tricks to get the most out of ATSUI. Some of these are specific to certain releases of Mac OS X or Mac OS 9. And when they are, I'll specify that. Otherwise, you can assume that these apply everywhere on all releases. So diving right in. Come on.
To start with, don't create a layout for each word, style, run, or line. This is very common for people who are moving their code over from Quick Draw Text where you drew each style run individually. It's easy to just rip that code out and put a layout for each one of those runs. Don't do that because you'll get very poor efficiency.
And also, Etsui will not be able to do its own by die analysis, which you get for free, which is really nice. What you want to do is create a layout for each paragraph. Because then you get by die for free, it will give you much better performance, and also it will make your life easier. Your code will be a lot shorter.
Secondly, don't throw your layouts away when you change the text. We provide some APIs for changing the text within a layout without throwing it away. You can use TextInserted and TextDeleted whenever a user types or deletes text. And if you want to completely replace all the text in the layout, you still don't have to throw the layout away. You can say setTextPointerLocation to point to a totally different buffer.
Also, don't use multiple layouts to flow text around shapes. You can still use the single layout per paragraph paradigm even when you're doing line wrapping around boxes. ATSUI has a built-in mechanism for embedding graphics and text, but what it gives you is something like the diagram there on the left where it's just a single line wrapped around the graphic.
If you want something like the diagram on the right, you can use multiple lines to achieve that. There's nothing that says lines have to be over and under each other. They can actually be side to side or anywhere you want. Because when you call ATSUI DrawText, you give it a set of coordinates. So you can simply vary the line width. Depending on which side of the box you're on, you can pass in a line width to ATSUI break line that's appropriate for that little segment.
When you're line breaking, don't use ATSUI Breakline anymore. You want to use the new Batch Breaklines call. As Tom mentioned, this can cut the time that's necessary to break your text into lines in half. You'll get much greater efficiency and it requires a lot less code. Now, for situations like I just mentioned, wrapping text around a box, sometimes you still have to use the ATSUI break line call, and you have to loop over it.
When you're doing that, don't set the soft breaks manually. Do pass true as the Boolean flag to ATSUI break line that tells it whether or not to set the line break for you. There is a small performance penalty if you call ATSUI break line and then immediately manually set the soft line break after that. Unless you're gonna set it to something different than what it returns you, just go ahead and pass true and let it set it for you.
When using styles, don't recreate style objects for each draw. Do create a single style and keep it around as long as you're gonna need it. This is very common if you've got a lot of UI text in your application that's all drawn in a common style. If you recreate the same style every time and then you look at the performance of your app in Sampler, you may find that you're actually spending most of your time simply recreating that same style over and over again. So it's much better to just create that style once once at the beginning and keep it around.
When you're drawing through CG, don't create and destroy the CG context around each ATSUI DrawText operation. You don't want to wrap that inside the beginning and end CG context. What you want to do is create the context once, do all your draws, and then dispose of it when you're done.
You can keep it around for the life of the application if you need to. It's much, much better to do it that way. There is a large performance penalty if you're constantly creating and destroying the CG context over and over again. Again, I encourage you to use Sampler to take a look at how much time you're spending doing these operations.
Also, when CG drawing, there's an old call in Quickdraw.h called CreateCGContextReport. The preferred API actually now is QDBeginCGContext and QDEndCGContext. These are available starting in Mac OS 10.1. There's a block comment in the header in Quickdraw.h right above QDBeginCGContext that explains in more detail why these APIs are preferred. They support printing, they can be nested and they actually do return a little faster.
And as Tom mentioned, when you're measuring text, if you just want to know how to space out your lines, you just want to know how far do I scoot down to draw the next line, don't use ATSUI MeasureText for that. Do use ATSUI GetGlyphBounds, or if you're on Jaguar, you can use the Ascent and Descent tags to get that information.
ATSUI MeasureText can cause ATSUI, in some cases, to perform an extra relay out internally, and that incurs a performance penalty. Whereas GetGlyphBounds and the Ascent and Descent tags return in constant time always, as long as the layout has already been performed, which, if you're going to draw, it has to be done anyway.
Starting in 10.1, we've got these new fontfallbacks objects, so you do not want to use the global fontfallbacks mechanism anymore. You do want to use these new fontfallback objects, which is kind of a misnomer for me to say that it's per layout, because actually you can set the same fontfallbacks objects in multiple layouts. They're just like styles. You can share them across all your layouts if you want.
And these fontfallbacks objects contain caches that Itsui keeps a record of which characters appear in which fonts. And that gets built up gradually over time as you're drawing text. So you want to keep those fontfallback objects persistent. So don't throw them away. Keep them around as long as possible. The same thing applies to these objects as with other Itsui objects. It's much more efficient to keep them persistent as long as possible. Share them between layouts. Unless you have different settings, just use a single fontfallback's objects every single one of your layouts.
When it comes to object sharing between threads, you don't want to share ATSUI Text Layout objects between threads unless you're running on Jaguar. As Tom mentioned, starting in Jaguar, ATSUI Text Layout objects are thread-safe and you can share them. On previous systems, ATSUI Style and ATSUI Fallback objects are thread-safe, so you can always share those. You don't have to worry about thread safety when it comes to that. And now for the summary, I'd like to bring Zabia back up on stage, and then we'll have the Q&A session.
we're running a little bit short, but there is one thing that I really want you guys to understand is like, ADSui brings you not only advanced typography, but it gives you as well access to all these languages that were before very difficult and you had to deal with different encodings and scripts. It gives you the advanced Unicode text drawing, the advanced typography, and the support for new languages.
But ADSui with these new features, we didn't get there just by sitting around and saying, hey, we're going to fix that for the Finder. We've been getting a lot of feedback from you guys since we started in 10.0. And ADSui has been around since Mac OS 9. But you have to understand that with Mac OS X, ADSui has been really shining and that's thanks to you guys.
And we've been getting a lot of feedback on the APIs, features that you wanted, things for instance like direct access APIs. That comes from developers that said, you know, the current set of APIs, that's not good enough for me. I need way more control because my application does this and that. And this is really important for you to understand, which is that's kind of a synergy here between you and our team, which is to make these things better, we need your feedback.
And you have all of you have like now the Jaguar CD. You can put your hands on these new features. Try the new break line APIs. I think you'll be very happy with what you've been doing and you'll see great performance. Try the direct access APIs and tell us how you feel about it.
Quickly, I'll go through the documentation. The new version for ATSUI 1.2 is actually covering the tech pubs. If you go there on this URL, you get information. The best thing is actually to know that this summer we'll have the new ATSUI book coming out. And you can comment if you have any questions about the content.
Thank you. The roadmap. On Thursday in room A2 we'll have MLT. It's the multilingual Unicode text engine which is actually built on top of ATSUI. If you need more information and you have specific needs for like text editing, I encourage you to go to this session. We have like very cool new features, once again, that have been driven last year from developers. There's a great session if you're looking into international markets and you're not sure how to approach them. We'll be talking actually about going international with Mac OS X on Friday.
Tonight at 7:30 in room N, if I'm not mistaken, there is the Birds of Fever. Fever? Anyway, it's a gathering of developers and engineers from Apple. And if you want to know more about ATSUI, if you have any problems, if you want to have questions about how you should handle Japanese maybe or Chinese, or if you want to do advanced typography, come by there. We'll be downstairs where the labs are. It's going to be very cool. You're going to be able to talk about what problems you have or maybe give us some feedback.
Should you have any questions that could happen, or maybe an announcement request you'd like us to consider, please send me an email. That's my job. I talk directly with the OSVIS team to find out how we can improve and how we can make things better for ATSUI and our international technologies. My email is [email protected] and I'll have some cards around if you guys want to come by.