Configure player

Close

WWDC Index does not host video files

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

URL pattern

preview

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

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

WWDC08 • Session 711

2D Graphics and Animation for iPhone and Mac

Media • 58:45

Quartz and Core Animation are the 2D drawing and animation engines at the heart of iPhone OS and Mac OS X. See how to create, stroke and fill shapes, display bitmap images and draw vector illustrations in amazingly flexible ways. Learn how to provide a dynamic graphical experience by animating composited surfaces and constructing smooth transitions with Core Animation. Understand when and how to go beyond the higher-level interfaces in Cocoa or Cocoa Touch and directly access the rich capabilities of Core Graphics and Core Animation.

Speakers: Derek Clegg, Joel Kraut

Unlisted on Apple Developer site

Downloads from Apple

SD Video (715.9 MB)

Transcript

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

Welcome to WWDC. This is session 711, a very auspiciously numbered session. I'm sure you're all eagerly waiting for 711, just like I am. Today I'm going to talk about 2D graphics and animation on iPhone and Mac, along with my colleague Joel Kraut. to get started. My name is Derek Clegg, and I'm going to ask you first why you're here.

The key thing about this session is we're going to talk about stuff that's a little bit at a different level than some of the other sessions you may have seen. So just to set the stage, one reason you might be here, of course, is because you want to use Core Graphics to draw some really beautiful things in your applications.

Here's an example of some of the things that you can draw with Core Graphics. Of course, there's the text, there's the guitar, sort of faded out a little bit, a little translucent. Various patterns and so on. You've got some interesting non-Roman text in the bottom left-hand corner, some line art, some little funky oscilloscope-type diagram, the pie chart. All those things are drawn in Core Graphics. All of those are sort of, you use the power of Core Graphics to get really interesting look and feel for an application.

Of course, that's just part of the story. Core Graphics lets you draw stuff, but once you have drawn it, you might want to use it to move things around. That, you'd use Core Graphics to do the cool core animation. Of course, most of you have seen the Cover Flow demos that we have. Here we're using Core Graphics to do all the artwork drawing, but of course, Core Animation to do the cool Cover Flow motion.

And the important part of why you might be here is that you have requirements that you really can't get met at a higher level. The higher-level frameworks do a great job at tons and tons of stuff. They're really powerful. They're great to use. And a lot of times, using those frameworks, UIKit, Cocoa, is exactly the right place to be.

There are times, though, when you need to drop down a level, and when you need to drop down a level and do something that maybe requires a little bit more power, maybe you're at the limits of some of the higher-level frameworks, you want to drop down to using Core Animation and Core Graphics natively. So I'm going to talk about those two things today and give you some idea of when you might want to switch to those parts of the system and also what we can do at that level.

So what is Core Graphics? It's also called Quartz 2D. You'll see that in a lot of the literature that we make available. The key thing is that, you know, it's really sort of the fundamental lowest-level part of the system that does drawing for both Mac OS and iPhone. So it's the heart of what we call Quartz. Quartz is a larger umbrella that contains a lot of pieces, but it's really at the bottom level, the heart of the whole thing.

It's a 2D drawing engine. You know, because it's a 2D drawing engine, it has the standard things you'd expect, vector geometry, so path-based lines and strokes. Once you've drawn a path, you can fill them with various solid colors, patterns, gradients, that type of thing. Of course, it has support for text.

It's the native text drawing engine, images naturally. And unlike some other platforms, Core Graphics has built-in full fundamental support for PDF, so that gives you a lot of power that you don't have necessarily in other platforms. Of course, it's used by the higher-level parts of the system, both AppKit, Cocoa, of course, and UIKit, and it's available through the Core Graphics framework.

Core Animation, of course, though, gives you more of the full animation experience that you would want in your application. It's super easy to use. It's an amazingly powerful system that does a lot of complicated stuff that doesn't require you to do too much work at all. So in that sense, it's fantastic. It's an amazing piece of work.

And it really allows you to use animation to do interesting things in terms of the way your app responds. In fact, I remember when I first saw the iPhone with the little scroll thing that you thumb down to do motion, I was blown away because it's so powerful.

It's such a simple idea, but it gives you a real feel that you're actually working with something real, not just something animated. That's all Core Animation doing that work for you. Of course, on a slightly more mundane level, you can use animation to do state changes and just maybe pop up the visual presentation of your application so it really stands out and shines.

And the important point though, I can't emphasize this enough, you use Core Graphics and Core Animation when you're willing to trade the flexibility you get for the power, the flexibility and power you get from this lower-level part, from the simplicity you get at the higher-level frameworks. High-level frameworks are even easier to use, have lots of support using the Cocoa APIs and the UIKit APIs to do almost everything you need. So there really is this point where you need to decide, well, do I really want to have something complicated?

That's when you want to go down to the lower levels, when you've reached the limits of what you can do at that high level. In fact, the usual thing that we say is stick there until you find you really can't do the thing you want to do, the cool thing you want to do, and then see if you can do it in Core Graphics, Core Animation. Probably you can.

So today I'm going to focus on Core Graphics. My colleague will come up later to talk about Core Animation. So let's just go through a little bit of some of what Core Graphics has available for you. Get an overview. Of course, you know, like a normal graphic system, there's standard support for basic primitives, points, lines, arcs, curves, rectangles, grids, filled and stroke types of shapes and so on. All sorts of standard things you'd expect.

Paths can be complicated or simple. Here you see a dotted path, for example, on the upper left-hand corner. Just a regular stroke path, plain old thing, not closed, not filled, just stroked. On the right, the two circles are actually a path constructed from two circles where we just filled the interior.

So there's a path that's made up of two sub-paths. The state of California, relatively complicated path, no problem in Quartz, Core Graphics. You just, you know, build the path up from the outline and then you can fill and stroke it the ordinary way. Paths can self-intersect, as with a star, they have complicated shapes like the spiral.

Of course, paths give you a lot of what you want, but really, in most applications, images are the primary thing that really convey your user experience in effective ways. So Core Graphics builds in native support for all the standard image types on the desktop and most of the standard image types on the phone.

But of course, the ones that matter for most people in terms of web development and stuff like that, PNG, JPEG, GIF, TIFF as well sometimes shows up on the web. So those are the primary formats that we have super optimized, very high performance. Other formats are also supported, but we expect most people will want to stick with those standard types.

As I mentioned, PDF is built in, both support for single-page documents, multi-page documents, really the same thing. You can use Core Graphics to draw your PDF content. Some people, in fact, rather than using images specifically for their UI, will build a PDF and that PDF may contain images, it may contain vector art, but they'll use that for their UI pieces.

For example, you may not know it, but on Dashboard, the little clock, all of those little hands and everything, all of those are small, tiny PDF files that are rendered once per second to sort of change the time as you go around. And that's a really effective way to get resolution-independent type of drawing using something other than just an image, but using a PDF. So that's something to consider, since we do have it built into Core Graphics as a fundamental type. It gives you a lot more flexibility.

Text, I'm not going to focus on too much, but on both the Mac and iPhone OS, text is at the bottom level drawn by Core Graphics. We do a lot of, we have a lot of support for complicated text, sorry, complicated scripts, colors, any of the sort of things you can do with paths, you can do with text.

But really, in most cases, you're going to stick, in terms of drawing the text, stick with a higher level framework such as Core Text on Mac. And on iPhone, you would use UI kits, text support. Those are really the right level of working with text, because text is a complicated problem. It's really hard to go from Unicode to Glyphs unless you know a lot about typography.

So to give you an idea of how the architecture works, it's a little different on the iPhone and the Mac. There's two slightly different models. Same basic idea though. On Mac, we have Cocoa at the top, which sort of cuts across everything. It's a framework you use to do most of your app work. That lives directly on top of Quartz. And Quartz is sort of a big package. It's not just Core Graphics. It's a lot of pieces. That whole wad lives on top of OpenGL, lives on top of the graphics hardware.

And so Quartz really breaks down into a lot of different pieces. We have sessions about a number of these areas. In this, on the Mac architecture, Core Animation sort of lives on top of Core Graphics. Core Animation is really like a peer of Quartz Composer. PDF Kit, there was an interesting yesterday about PDF Kit, Image Kit.

All of those pieces live right on top of Core Graphics, Core Image, Core Video, which are a little lower level in that sense. And then that lives on top of OpenGL. iPhone, slightly different model. Of course, at the top, the analog to Cocoa is UI Kit. Lives right on top of Quartz, which lives on top of the graphics hardware. And here, there's a bit of an inversion.

Core Animation is really sort of on top of Core Graphics as a client of Core Graphics on the iPhone. This doesn't really make much difference to you in terms of your application. You'll do the same types of things, but it gives you sort of an idea of how we sort of stack things up.

So the key features of Core Graphics and some of the reasons why we think it's really cool. Of course, it's a modern 2D graphics API. I mean, it was modern. It's been around for now many, many years, but we designed it up front to be high-performance, modern, and so on, and it stayed that way. We keep extending it.

So, as device independent up front, the reason that's so important, you now see when you have your desktop and your phone, you write the same code using Core Graphics. You don't have to do something special because the device is a different device in terms of what you actually write for Core Graphics code because we handle sort of things on the back end so that we make that work. So, you don't have to think about what your end device is going to be. Clearly important in this type of market.

Resolution independence, also built in from the very beginning. For many, many years, people didn't quite understand what the point was. Now, it's pretty clear. We have two different devices, Mac, desktops, for example, and iPhones, different resolutions. If you had to worry about, oh, the phone is this resolution, the Mac is this resolution, that would be a pain. We do that for you. So, you just write the same code.

It's resolution because Core Graphics is built to be resolution independent. You don't have to do anything special to handle that. Of course, high performance necessarily these days. The anti-alias graphics and text. It's what makes things really beautiful when you look at the small screen of the iPhone or the big screen of the desktop.

The anti-aliasing makes things, gives you those smooth edges. You don't get those blocky, chunky, ugly stuff that you see on some other devices. Wide supported image format array, just as I mentioned earlier. Built-in color management, very important for people who are concerned about the way colors appear on the devices. And, of course, built-in PDF support, fundamental part of Core Graphics, really, really useful.

So that's sort of the big picture of Core Graphics. It's built up of a number of smaller pieces. And what we do in Core Graphics, because I have an Objective-C background, and because object-oriented programming is obviously the right thing to do in the future, we build up Core Graphics, even though it's a C API, as though conceptually we sort of model it as though it were an object-oriented type thing. So we do have what we call them primitives, but they sort of have analogs to objects on the other frameworks.

So, for example, CG Image Ref is the primitive, the object, if you will, that represents an image in Core Graphics. It sort of parallels UI image or NS image on Mac. Colors are represented by an abstract type called CG Color Ref, which has its parallel to UI color and NS color on the other platforms. Interestingly, paths are a little different.

The Core Graphics primitive is the CG Path Ref on iPhone. They said, well, that's good enough. So that's their primitive for paths there too. Mac, for historical reasons, Cocoa has always had an NS Bezier path. And so that's sort of the type you use at that point. But you sort of get the idea. They're all object-like, real objects that are used as sort of in an object style. For getting information in and out of Core Graphics, use a CG data provider. That's common across all three frameworks.

And for working with document, for PDF documents, the Core Graphics level, there's a CG PDF document type. iPhone has the same thing. Mac, interestingly, has a whole kit that's devoted to PDF support, PDF kit. There was a session yesterday about that. And there you have a PDF document. But not only that, you have a lot of additional classes that let you do lots of interesting things. So that's a very cool thing to check out on Mac if you're not familiar with it.

So as I said, it's object-like in that we have sort of the same style of working with the types. So for example, the same way in Cocoa you do an alloc init to create an object. In Core Graphics, you use CG image create to create the object. There's accessors, conceptually accessors. Their functions, of course, are not methods. But, you know, CG image get width, get height returns the width and height of an image. And then you can do things to the object. You can, in this case, we're going to draw an image.

CG context draw image lets you draw an image into a destination. Similar types of things with colors. Paths, there you can create a mutable path that can be modified. And you have sort of the analog of a setter, CG path ad rect. It's not quite a setter, but sort of the idea is the same. So we really follow that same style. And that allows you to maybe not think so much about how you work with the Core Graphics APIs because it really fits into the same style of the APIs you've used at a higher level.

Of course, the important thing about objects is once you have them around, you've got to make sure you don't leak them. You don't want to lose track of them, otherwise your app will crash because you're using too much memory. So object ownership is really important. The nice thing is, though, is that we follow the Core Foundation, the Cocoa, the UIKit, the same model that they follow. If you create an object, you're an owner of it.

You may not be the only owner. There's ways to have multiple owners, but if you create it, you are an owner. So you need to do something about it since you're the owner. You have responsibility. You must release the object when you're done with it. So the key thing is that when you create it, you own it. You release it to get rid of it.

Say, I don't want it anymore. Eventually, it will go away. The way you release it is the standard Core Foundation style. If you're familiar with Core Foundation, CF release. For historical reasons, we have type-specific release functions, CG image release, for example, in this case. So that's an important part of creation is that you're an owner. You must release it.

On the other hand, if you're not the owner, usually the style in Cocoa and UIKit and for us is when the method has a get as opposed to a create in it, create or copy. If it has a get in the name of the function of the method, you're not really an owner.

So that means that since you're not the owner, you're just sort of hanging on to it for a little bit. You shouldn't release it. There are times, though, when you want to hang on to it for a period of time longer than you might allow for it to disappear.

Because someone else might release it. So you need to retain it if you want to keep it around for a while. So to retain, similarly, in the way that you may be familiar with Core Foundation, call CF retain. We'll retain the object. For historical reasons, we have the object-specific retain function, CG image retain, for example. So this is sort of the standard model that's used throughout Cocoa and UIKit to work with objects.

And assuming you're not using garbage collection, of course. And we follow that pretty closely. So again, you don't have to think too much about Core Graphics isn't special in any way in that sense. Now, another thing that's important about Core Graphics is the way we work with coordinate systems.

Coordinate system in Core Graphics may be different from other platforms you're familiar with. Because what we do is we say, well, look, you know, we often want to draw the same object in multiple ways. We want to rotate it or we want to do something special to it.

But it's really expensive to create the object in a different form. One approach is to change your way of thinking from. Let's change the object to let's change the coordinate system. So we have a model where the objects tend to stay static. They're immutable. They don't change. But the coordinate system changes to allow you to do interesting effects.

So here we have an image that we draw. Origins lower left. We just draw the image. What can you do to a coordinate system to change things so it looks different? Well, there's some standard things. There's more than this. But this is some of the standard stuff. You can scale the coordinate system. You can make the coordinate system larger. You imagine you're drawing on a piece of plastic. You stretch the plastic. You stretch the plastic out. The coordinate system gets bigger. And that makes the content drawn in it larger. You could rotate it.

You can translate it, move it around. Those are some of the standard things you can do to a coordinate system. That's sort of built into the way core graphics works. And it's part of the whole model of how we work with coordinates. So, for example, scaling. Here's the same image we drew before. But what we're doing now is we just imagine we're squashing in the vertical direction, maybe by a factor of two. So now the image. When it's drawn will be squashed down. Even though it may be the same image that we started with, it will appear squashed down.

Same thing with rotation. We're just going to rotate the coordinate system, draw the same image the same way. And now because the coordinate system is rotated, the image is rotated. Flipping, you know, sort of inverting is a little trickier. It requires both a flip and a translation. Because, you know, if you just flip something here, it ends up in the wrong place. You've got to slide it back over. So that's a little bit of a trickier operation.

Now, one thing that's important about the coordinate systems set up for you when you use them, often you don't end up with a coordinate system that you've created using Core Graphics. It's sort of given to you, provided to you through the higher-level frameworks. That's pretty typical. The default coordinate system in Cocoa is, as Descartes intended, on the lower left-hand side with the y-axis going upward.

On the other hand, as many people prefer, on UIKit, it's opposite the upper left-hand corner is the origin and the y-axis goes downward. So those are two things that are different about the systems by default that's set up. Because Core Graphics is pretty flexible with the coordinate system, you can modify that. But you need to know that if you just start playing around with things up front, trying to do Core Graphics drawing.

And so, as I mentioned, the important concept here is that we are working not on the object, but on the coordinate system in order to change it. So here, for example, we have a trivial example. We have two rectangles. Someone said, I want you to draw the blue rectangle and then draw the same rectangle green, or larger rectangle green in a different position. Well, you could create two different rectangles and, you know, work with that.

But, you know, if it's not a rectangle, but an image or a PDF page and like that, that's going to be a lot of work to create two different forms of the same thing, excuse me, at different sizes. The nice thing about Core Graphics is that you don't have to create different objects.

In this case, we imagine that, you know, we're going to draw the object first at 0, 0 and 100, 100 is the width and height. So how might we draw it at this other position at this other size? Well, we just change the coordinate system. We translate the coordinate system over by a certain amount. We scale it up and then we draw the same exact rectangle. So that translation and scale has ended up drawing the result that we want without actually creating a brand new object.

So this is a really powerful mechanism for doing drawing in Core Graphics that lets you do a lot of complicated things without really using a lot of system resources to do them. Because, again, on our side, we'll take care of all the magic to get to the right size and the right scale factor and the right position and everything. But your objects sort of stay the same.

So that's good. That's sort of a big picture, you know, abstraction of what goes on in Core Graphics. So let's talk about some of the primitives and some of the primitive ideas as well. The first thing is that Core Graphics uses, from a very old PostScript model, it's a great model, the painter's model. The idea there is we build up from back to front. So you sort of draw content from the back of the thing to the front of the thing and anything that's opaque, obscure, anything that's translucent will have some stuff shown through it.

So, you know, you might imagine a blank canvas, you put on a gradient, you put another image on top of it, it's going to obscure the stuff behind it. You put this little logo up in the upper right-hand corner because it's translucent, some of the content will show through.

Maybe you put a little PDF file on top of that. So you're building up from back to front and that's sort of, that's a fundamental way Core Graphics does its drawing, handles its drawing model. Well, that's good, but then you might think, well, okay, so I can draw, but where can I draw to?

There's a bunch of different drawing destinations. As I mentioned before, we're device independent. So you use the same type of code to draw to different destinations for your application. Of course, obviously, drawing to a window, NSVU type thing on Mac is pretty standard. You can draw to a Core Animation layer if you're interested in using Core Animation directly. Bitmap context, good for off-screen rendering.

PDF, very important for preserving your drawing content. Of course, naturally, you're going to be printing occasionally. So a printer would be one destination. On the iPhone, a little different. Instead of NSVU, of course, you have a UI view, different model, different framework. Of course, Core Animation is the same, so you can draw to a Core Animation layer. Bitmap context, PDF. None of the other destinations make sense right now. So that's basically what you have on iPhone.

And in order to allow you to think about or write your code that will end up at these different destinations, we don't necessarily want you to say, well, I'm going to draw to a printer, so let me create a printer thing and draw to that. No, we sort of abstract all of those different destinations in a single type called a CG context.

CG context is the abstraction of any destination you might be going to. So again, your code is not changing because you happen to be printing or you happen to be going to a Core Animation. You happen to be drawing to a UI view or something like that. Your code's the same.

We handle behind the API boundary all the work that's necessary to make the destination match up with where you want it to end up going. So you write the same type of code using the CG context as your abstract data type for the destination, and we'll do the work to send it to the right place.

So if you were using Cocoa and you want to get a CG context, use this slightly Baroque method. It's more historical than anything else. Of course, I'm sure most of you know in Cocoa you're going to have an NSView for your drawing. Your NSView will have a draw rect. In your draw rect you'll do your drawing. Core Graphics is what you use to draw. Of course you can use the higher-level frameworks to draw as well, obviously. But if you were using Core Graphics, you'd want to get a Core Graphics context to draw to.

So the way you do that is you first call NSGraphicsContext currentContext. That's going to return the current NSGraphicsContext. You might think that's the same as a CG context. No, not at all. For historical reasons, you need to then ask that context for its graphics port, which is the actual real CG context.

And from that, you can then use all the CG APIs you're going to see today. On the phone, on UIKit, a little simpler. There's a function, UIGraphics, getCurrentContext that just does the right work for you. And so you don't have to worry too much about that. That's very straightforward.

Okay, so CG Context is this abstraction of the drawing destination, but it's more than that. It's not just sort of that one piece. In addition, there's a set of state parameters that you use when you are drawing. So some APIs might say in order to fill a rectangle, you call some function that you specify the rectangle and its color and whether it's bordered and what the border color is. You know, a whole slew of parameters in the one function.

Core Graphics is different. In the context itself, we keep a current state of all the parameters that are used to affect drawing operations like the fill color, obviously, the stroking color. The transformation matrix, as you saw before, that's very important in terms of how things show up. Other parameters affect line drawing and so on.

So all these things are part of the graphic state. So you set those in the context and then you can sort of reuse that state implicitly each time you draw. And when you want to change things, you just change that state. the one parameter of the state, you don't necessarily change everything else.

So that's really good and that's a powerful model because you're not always setting state just to draw a single line or a rectangle. But the problem is that sometimes you want to just change one thing and then return back to what you had before. You're sort of temporarily changing the color of something, for example. And then you want to return back to the state you had before because you're done with that.

So in addition to the state itself, we have a stack of graphic state, the graphic state stack. And that works by allowing us to sort of push and pop graphic states on the stack inside the context. So here's a sort of a trivial example where we have a graphic state, let's imagine, with just two things, a stroking color and a filling color.

And that's our current state. And suppose we want to draw a rectangle, but we want to make it green, not blue. You sort of saw that example a little earlier. So the first thing you do is call CGContext saveGState, which will copy the current state and push it on the graphic stack, just like here. Now we have two states that are hanging around, and we can change the current one, change its fill color to green.

So now we change the fill color to green, and we can draw our rectangle, the rectangle will be green now. And now we say, okay, well, we're done with that. We don't want to do that anymore. So let's revert back to what we had before. So CGContext restoreGState will take the current state, pop it off the stack and discard it, and return us back to the original state. So in this simple example, you may not get a real sense of why that's so powerful, but it turns out it's incredibly powerful. And you're using it, for those of you who do Cocoa programming, all the time, implicitly, you may not realize it.

Every time your drawRect method is called, Cocoa will call CGContext saveGState in order to save the current state, call your drawRect method, and allow you to do anything you want to to the graphic state. You can make, you know, crazy decisions and do really interesting things, and when you're done and returned, Cocoa doesn't have to sort of track all the changes you made. It doesn't have to worry about, you know, remembering what was there before or anything.

Instead, it just calls CGContext restoreGState, and we're back to where it was. So this is used all the time in Cocoa, and it's a really powerful mechanism for sort of temporarily modifying content of drawing to get a different effect, and then returning back to what you had before.

Okay, so, so far, so good. We've talked a lot about Core Graphics and we haven't done a thing in terms of actually drawing. So now we need to really put something on the page. So let's look at a really simple thing. Suppose we just want to fill a rectangle. Turns out that's so simple I'm actually going to cheat and have another thing as well, which is filling an ellipse or a circle.

The context is, as I said, the abstraction of the drawing destination. So you tell the context you want to draw things. You tell the context what to draw. Here we have an example of two APIs for filling a rectangle and stroking a rectangle. CG Context Fill Rect, CG Context Stroke Rect. So pretty simple. Those will take the rectangle you provide, CG Rect is the type that we use to represent a rectangle, and fill it or stroke it.

Same way, if you think about it, an ellipse is just a curvy rectangle. So there we take an ellipse and we can fill the ellipse. And of course it's going to be tangent to the sides of the rectangle. So we have a Fill Ellipse in Rect, Stroke Ellipse in Rect. Two very simple functions that let you do, you know, boxes, circles.

To sort of walk you through some of the code that you might write if you were-- and again, this is a really simple example. We're going to draw two rectangles, but just give you a flavor of what the code looks like to use Core Graphics directly. Here we have a function with-- let's imagine we've gotten a context from, you know, UI Kit or Cocoa Somehow in your draw routine. And we have a function, CG-- sorry, do stroke and fill directs. It's going to fill and stroke some rectangles.

So the first thing we do, we're going to make the rectangle that we want to fill our stroke. And CG Rect Make takes the origin 1010, width and height 130, 100. And we imagine there's some function that returns a CG color, we mentioned that earlier, that's blue. My get blue color will return a CG color. Because it's a get function, we're sort of following the naming conventions that are standard. We're not going to have to release it or worry about that.

We're not really the owner. We're just going to get the blue color, set it in the context as the fill color. That's going to set the fill color in the graphic state to blue. Now we're going to fill the rectangle. Pretty simple. There's our filled rectangle, the right position, right width and height.

Now we're going to stroke it with a different color, in this case, my get green color, we imagine, returns a green color. And we're going to set that in the graphic state. And now we're going to call CGContact stroke rect with width. The width is going to be the border of the stroking around the rectangle. In this case, it's going to be 10 units. And here's our stroked rectangle.

Now one of the subtleties, or at least something that's worth being aware of, when you stroke paths in Core Graphics, the stroke appears on both sides of the path. So we put half of it, in this case five units on one side and half on the other side, so it sort of straddles the whole path.

So that's a key thing to know about, and sometimes people get confused about what goes on when we're stroking, and that's the basic idea there. So now we're going to do the same thing again, but we're going to switch the order. This will illustrate two things. First, we're going to save the graphic state, because what we want to do is draw the same rectangle, but we're going to shift it over. This next line moves, translates the coordinate system over by 200 units in the X direction. So we just move things over.

Because we don't want to worry about, because we don't want to essentially undo that operation ourselves, that's what we're going to call save G state in order to save the graphic state for us. Next, we're going to stroke the rectangle, same way. Now, notice that because we have a graphic state, the fact that we've set the fill color and the stroking color before persists. It's now using the same things because we haven't changed it. And so we're going to get a green rectangle stroked at the position that we specify.

and now we're going to call fill rect. This is going to take the rectangle and it's going to fill it with blue because that was a fill color we set before. And notice in this case, it's now on top of part of the stroked path because as I said, the stroke path is inside and outside, so we're covering part of the stroke path. So that sort of illustrates how the stroking path works. And now we're going to recall CG Context Restore's G-State because we want to undo the change to the coordinate system that we did before. Now the coordinate system is going to move back over to the original position.

And then we can keep drawing anything else we want to. Paths are, as I mentioned at the very beginning, paths can be both simple and complex. The basic idea is that you begin a path, you can add some primitives to it. We support obviously line segments but also Bezier cubic and Bezier quadratic curves.

We have some convenience functions that let you add an entire shape to a path, such as a rectangle or a circle. If you want to, you can close the path if you're going to fill it or something like that. And then you can paint it, you can either stroke it or you can fill it.

And you'll notice that in the illustration we have a couple of examples of open paths and closed paths, which are simple. But the multiple subpath case where we have, in that case we have four subpaths that make up a single path, they don't all have to be open, they don't all have to be closed. So you can make paths that are pretty complex to work with in Core Graphics depending on your needs. So the next thing we want to do is perhaps draw some image content.

Images are interesting. There's two pretty distinct ways of working with images. This is one of the places where there is a dissimilar feel on iPhone and on Mac. On Mac, there's the Image.io framework, which you use to do most of your input-output of image content. That's the C API that's sort of the peer of the standard Core Graphics API. At the higher level, you have Cocoa and you have the native NSImage type, which you can use to do object-oriented image manipulation. iPhone, it's a little different.

The type there is UIImage and it's built on top of CGImage, but you don't have quite the same direct interaction with Image.io, certainly not NSImage, that you do on Mac. So it's a little different. But I'm not going to talk so much about the iPhone case. The interesting case in this talk will be Mac, because that's closer to what Core Graphics directly uses.

So in Mac, with Image.io, the important part about drawing an image is that there's a basic type, CG image source, which is effectively the abstraction of the file on disk. So you can think about an image source as like there's, you know, foo.tiff or, you know, mybestfriend.jpg, some file on disk that you can work with. And you create an image source using CG image source create with URL. There's a couple of other APIs that also let you do this.

And then once you have the image source, you can get the images out of it. Now, the API, a CG image source, create image at index, which is a little odd because if you think about a file and disk, you don't always think, oh, well, there's multiple images in it.

Turns out some formats are special. They can have multiple images in them. So we do need a function that lets you ask for the image at a particular index. Normally, though, lots and lots of the time, the index will be zero because it's the very first, the only, the very first image in the file.

[Transcript missing]

The other type that we have built in, of course, is PDF. In this case, it follows the same model that we follow with images, slightly different variation because it's up front a little different. A PDF document is the abstraction of a PDF file. Of course, PDF documents normally contain multiple pages, so there's a PDF page, CG PDF page, which is the abstraction of the page in the document for historical reasons and I guess because print books do this, pages start at one. It's a small difference. There's a number of functions that let you work with PDFs.

I'm not going to go into them too much, but basically, same way you create a PDF document with URL, like you create an image. Once you have a document, you can get the number of pages from it. You can, of course, get a page from the document to draw and then you can draw the page.

CG Context PDF draw a PDF page will let you draw the page in your context. So that sort of gives you a flavor of the way PDF stuff works. So that's sort of a broad and quick overview of Core Graphics, give you a flavor of what's available. As I mentioned earlier at the beginning, and because I've worked on Core Graphics from the beginning when we first created it in Mac OS X, we designed it up front to be very sophisticated and do a lot of stuff for you without you having to do too much work.

So we built it to make things easy for you guys. And you guys also includes all the developers internal to Apple who really do come to my office and complain about things. So we try to keep the complaints down. So we built it from the beginning to be sophisticated and powerful, naturally device and resolution independent.

That's fundamental in today's world. We can't get away from performance. That's critical for the phone in particular, but also critical for every other system that we have available. We wanted to have really rich and complicated and powerful support for obviously images, but PDFs very fundamental to our system, naturally text and so on. And it gives you really beautiful results with the anti-alias rendering.

Just the way we spent a lot of time getting things looking superb because in the long run you're going to be looking at it on something like your phone. And you want it to look great. So we spent a lot of effort making sure that that's true. So that's sort of Core Graphics. Now I'm going to turn things over to my colleague, Joel Kraut, who's going to talk to you about Core Animation.

Thanks, Derek. Hi, everyone. I'm Joel Kraut. We're going to talk about Core Animation. We're just going to get our toes wet a little bit. We've just heard a lot of talking. I'm going to talk a lot more. So let's start things off with a demo to keep you interested. So if I could get the demo machine.

I'm just going to show you what Core Animation can do, a little bit of what Core Animation can do. Here we see a grid of images. Each one of these is a Core Animation layer. We see that they have some nice pseudo-3D transform effects. And we can actually move them around in 3D space.

We can do real 3D transforms on these layers. We can do fog effects. We can make them big, do nice swooping transitions, bring that out. And if you've been to previous WWDCs, you might have seen this before, but we can do actually fairly sophisticated 3D effects with these guys. And we can have a fairly enormous number of them on the screen with no degradation, lots of really smooth animation going on. And of course, all the images are preserved and looking beautiful.

So there we have it. That's Core Animation. Can we go back to the slides, please? So you probably want to know how to do that. So we're not going to do exactly that, but we're going to talk on a high level about what core animation is. So here's exactly what we're going to do today. We're going to talk about what core animation is, what it can do for you, and in fact, how we use it in our system with some examples and why we use it.

Then we're going to move on to the basic element of core animation, which is the CA layer. We're going to talk about how you make them, how you use them, what you can do with them. And then, of course, animation is a big part of the API. We're going to talk about the animation aspect of core animation.

And lastly, we're going to touch on why you might not want to use core animation at all, because it turns out that 90% of what you're going to want to do with core animation layers, you can do with NSViews via the animator proxy. And during the course of this talk, I'm going to use NSViews and UIViews interchangeably. Everything I'm going to say applies to both of them. So this is both on the desktop and on the phone.

So Core Animation on a high level is a foundation for compositing animation. We'll talk about what that means. If you know Objective-C, you're in luck because that's the native language. If you don't, this is a very good reason to learn it. We're going to talk about all these things later. I will point out here that although the API is mainly shared between the desktop and the phone, there are some things that are on the Mac only. Those will be called out with a little purple icon like so.

So going down a little bit deeper, Core Animation is an engine for compositing. And if you don't know, compositing just means slapping together a bunch of graphics and getting rendered on the screen what you expect. So that means if you have some stuff with transparency in it, if you want to do some sophisticated layering and masking, you can put all of that together and you'll get what you want with Core Animation with a minimum of effort.

So it's also an engine to bring together all of the graphics technologies on the system. So that means you can have a layer with QuickTime content, even QuickTime capture. You can have a layer with Quartz 2D drawing, leveraging all of the power that Derek just talked to you about. And you can even have layers with Core Image content and filters on them.

And on top of that, of course, there's the animation aspect. So I'm going to talk more about these things in a little bit. What you need to know is that all of the animation in Core Animation follows a set-it-and-forget-it model. There's explicit and implicit. They're both really simple. The key part of all of them is that you never have to write code that's going to run at the frame rate, moving your layer along or changing your background color. All that stuff is handled for you. You never have to worry about the hard part of animation.

So why do you want to use Core Animation? Well, we know already that animation gives you these nice benefits in the user interface. But animation can be a real time hog. And if you're going to animate your entire user interface yourself, it can turn out to be a huge pain. But of course, you want to do it because you get these benefits. So you might as well use Core Animation that makes all of this stuff easy for you, as shown here.

So Core Animation makes it easy to do interfaces like, for instance, iChat, where animation is used to seamlessly transition between states without a jarring visual jump that you might expect in kind of a more traditional UI for this kind of thing. Also Cover Flow, in which animation is used to give a sense of tactile feel to moving around in this list and also help the user keep track of where he is in the list.

Time Machine, where animation and Core Animation in particular are used to denote an actual time-based interface, which if you think about it is a pretty natural fit for animation. And of course the iPhone UI itself is entirely built on Core Animation and this is vital to having the user feel that the interface is responding directly to his touch.

So let's look at that one in a little bit more detail. What we see here is a piece of the iPhone interface. Now the important thing here is that everything you're seeing on the screen is layers. All of these interface elements are layers. The picture itself is a layer, and this little alert that comes up is a layer.

And what does that give us? That lets us get all these really nice, smooth transitions between interface elements, which is what you're seeing here. Everything slides up, slides down, fades in, fades out. So nothing is abrupt, and everything kind of feels nice and smooth and good to the user. If you look at that in a little bit more detail still, what we're going to see here is two different pieces of UI, one big, one small, different shapes, different sizes.

But the transition between them is absolutely seamless. Let's look at that again. Seamless transition because they're animated in and out rather than just appearing and disappearing. So that's the kind of thing that we can easily do with Core Animation. So in general, we're using animation and Core Animation in particular to make it easy for the user to figure out what's going on, to track the action on the screen.

So you might not want to use animation if, for instance, you find that it's not adding any more data, if it's not giving the user anything, if it's not helping the user do what he wants to do, or if it's repetitive or distracting, it's probably not helping. So there's been a lot of research on why you might want to or might not want to use animation in an interface. I encourage you to check some of these out. I think these are listed in the session notes. And of course, start with the Apple Human Interface Guidelines as that's the canonical source for anything.

So now we kind of have an idea of what Core Animation is. We're going to move on to, as I said, the basic element of Core Animation, which is the CA layer itself. We're going to talk about what it is, what you can do with it, and how you can use it.

So on a low level, animation, I mean, layers, sorry, are basically 2D planes, pieces of geometry that have no depth themselves but can be stacked up and arranged with depth and kind of a 3D space. So here we have a conceptual illustration of three layers. This is what we, the programmer, know to be the case, that we have these three layers stacked up. What the user is going to see is something more like this, where they flatten to an image that appears to be two-dimensional. And this is one of the things that you can do with layers, stacking them up like this.

So in a little bit more depth, you can think of a layer as a two-dimensional piece of geometry that you fill with stuff. So here's the most basic layer, right? It's a white square and nothing in it, not really doing anything. But we can mess with this a lot. We can change its geometry. We can rotate it. We can put a little border on it.

We can put a drop shadow, although you can't see it because it's on black, but I assure you it's there. We can fill it with some visual content if we want. And we can put a Core Image filter on top of that. Of course, that's Mac only. And I should also say that each layer potentially has a tree of child layers because Core Image is a -- I mean, Core Animation, sorry, is a tree-based API. And some things that you do to the parent layer will affect the children, like position, transformation, that kind of thing.

So although the layers themselves are two-dimensional, they can be transformed in 3D, as you saw with the demo. And depth sorting, of course, is supported automatically. Intersections, as you can see here, happen as you would expect. And we recommend not using layer intersections if you don't need them because it increases render time. But if it's necessary for your UI, you can put that in, and it'll work as you would like.

So where do you get the contents of the layer? You can use a Quartz image, which is what you were just seeing, and I should say, by the way, that all of the demos you're going to see inside of this presentation are actually Core Animation. I just rendered out a movie of Core Animation stuff running. So that's the kind of visual quality you can get.

And of course, they were running real time. So you can get images, as you just saw. You can get Quartz drawing in your layer. So you're just given a CG context in which to draw, and then you can do all the stuff that Derek just told you about. You can opt to be notified of layer bounds change and redraw on that. And you can even do this drawing with a delegate, so you don't even need to subclass anything. You just set a delegate to do the drawing for you.

And of course, this is just the basic CA layer. You also have these various sublayers that you can fill with other kinds of content. You can fill it with a rendered attributed string. You can get a callback to do OpenGL drawing in a layer. You can put a Quartz Composer project in there, and many more things. And of course, the OpenGL layer in particular is supported on the phone as well. as well.

So in a little bit more depth, on a layer you can change various geometry aspects. This is what happens if you change the bounds of the layer. And of course you get nice smooth animation no matter what you do. You can change the 3D position of a layer. And I should say here what's happening, you see the red layer popping on top of the yellow. That's because layers themselves are two-dimensional. Neither of these is rotated in space at all.

So the red layer is moving up to the front and back to the back. There's one frame when the red layer is completely behind the yellow and then one frame when it's completely on top. And if they had depth to them, then you would see a more gradual transition. But because they are in fact two-dimensional, there's no gradual transition there at all. So that's important to note. And of course you can change the 3D transform of a layer and do fun stuff like this.

And perfect. Yes. So there's a bevy of stylistic properties that you can set on layers as well. So here we can change the opacity, for instance, of a layer. We can change the background color. And even when you're changing something that's kind of semi-abstract, like color, you still get this nice animation between the two properties, between the two values, rather. And if we wanted to, we could change something like the width of the border.

And as well, there's the option to do Core Image filters on the content or the background of a layer. So here we have a Core Image filter running on the content of the layer. And of course, this is not masked out. You can opt, if you wish, to mask a layer to its boundary rectangle, in which case here you wouldn't see anything. But that's what's going on here.

In addition to these, there's the option to use a compositing filter. If you don't know what this means, you can think of compositing as providing a recipe. So given the color of the layer and the color of the background it's on top of, the compositing filter provides what color you're going to get on the screen in that place. And you can use these CI compositing filters as you would expect.

In general, the default filter is source over. If you don't know what I'm talking about, that's fine. This is what you want. It's going to do the right thing. If you do know what I'm talking about and you want to know more, there's another Core Animation session that goes into much more detail later today. Please check that out.

So now we have kind of an idea of what the layers are, what you can do with them, what you can put in them and on them, and what you can change about them. So that brings us to doing something with those layers, which is to say animation.

Now the thing to remember about animation in Core Animation is that you never have to do any of the hard work. What that means is you never have to write code that's going to run at the frame rate, that's going to move your layer or change properties, you know, interpolating or anything like that. If you're using implicit animation or explicit, you don't have to do any of the hard work.

So implicit animation, we'll talk about that first. This is as simple as could be. You just change a property. And here we changed the opacity to zero. So if we were in our code to reference that opacity later, even in the next line, we would see it to be zero in the code. As far as your program is concerned, it's changed instantaneously. However, what we see on the screen is a smooth interpolation between the old and new values.

And this happens because Core Animation keeps a render tree which is shadowed. It shadows all of your objects. You never have to deal with it. That's where all of the work happens. So we do everything for you behind the scenes. All you see is the clean front-facing thing where values change instantaneously just like your code would expect them to.

That's implicit animation. Explicit animation is only a little bit more complicated. Still, everything happens over in the render tree. You don't have to do anything hard. You just have to create an animation object. And you're going to do this when you want a little bit more control than you can get with an implicit animation.

So you can create one of a list of kinds of animation. For instance, keyframe lets you specify different values at different times. Transition is when you change the entire content of an object, that kind of thing. So this is an example of an explicit animation. This is just a keyframe animation with, I think, three keys, three keyframes. I just set them up, and I attached the animation to the object, and I let it run.

Again, I didn't have to tell it, now do this, now do this, now do this. I just set up the object, configured it with what property it was going to affect, in this case, the position. I told it to repeat, and then I added it, and I forgot about it. Everything works as you would expect.

[Transcript missing]

Anyone remember this?

What we're seeing is that very same demo I just showed you, almost in unchanged form. The code really just has a very few changes, mostly relating to the number of squares we're showing. Running perfectly on the phone. So we can do the same sort of 3D transition. We can do the same full 3D rotation.

We can do the same fog effect and big scaling up and transition, all that stuff. And we can even do this animation that you would expect is really pretty intensive. And we have around 300 layers flying around on the phone right now. It's all handled pretty much seamlessly, flawlessly, no problems whatsoever. That's the kind of power that you get with Core Animation running on the desktop or on the phone. Can you go back to slides, please?

Thanks. So to sum up the Core Animation section, Core Animation is what you want to use if you have complex composited scenes, if you want to bring together a bunch of graphics technologies on the platform you're working on, if you want to have a nice animated UI that provides various benefits to the user, that you all know about and of course, you're going to read more about.

But you don't necessarily need to use Core Animation to get all this stuff. In general, you can use NS View or UI View. It's just use them first, and if you find that there's something you need to do that you can't with them, that's the time to investigate core animation.

So we have been having a lot of fun giving this presentation. We hope that you will have a lot of fun applying what we have taught you. We are really excited to see what's going to come out of this and what this new crop of developers is going to bring to us both on the phone and on the desktop. For more information, you can contact these people, especially Alan Schaffer, who knows everything you'll need to know about anything.