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

WWDC07 • Session 419

Printing with Style in Mac OS X

Graphics and Imaging • 1:04:44

The printing system in Mac OS X Leopard gives your application the ability to produce high quality WYSIWYG printed output. Learn how to properly color manage print jobs, extend print dialogs, create document previews and more. Come see the latest techniques that ensure your application is taking full advantage of what Mac OS X Leopard printing has to offer.

Speakers: Howard Miller, David Gelphman, Alan Beck

Unlisted on Apple Developer site

Transcript

This transcript has potential transcription errors. We are working on an improved version.

Okay. Welcome to the Printing Session. I am glad everybody could make it. The first big announcement it the weather you will see today in the park is not characteristic San Francisco weather. So you don't need to bring your sweater, which is really good. Okay, let me try and wake everybody up just a little bit, mostly myself.

How many people here are printer driver developers, middle-ware developers, counting packages, stuff like that? Okay. About three-fourths of the room. The good news is -- you know how to get up early? 9 o'clock tomorrow morning Michael Sweet is going to do a presentation on the Common UNIX Printing System, a.k.a. CUPS, which is the foundation of the printing system in Mac OS X. So I encourage you to come back at 9 o'clock, not this room, and see Michael speak.

Okay. How many people are application developers? All right. We've got something for you. How many of these applications are shipping and print really well? Thank you. And thank you. For the rest of you, today what we've got planned is a whole run through of the entire printing system from an application developer's perspective. We're going to provide information for the person whose never written printing code in their application all the way through some advanced stuff. So there should be something here for everybody.

Here's the agenda. I'm going give you a tour of the user experience for Mac OS X Leopard printing. We're going to get an overview of the printing APIs, try and point out maybe some of the important areas that you need to know about to make your application work. We're going to start at the beginning, only briefly. Since it's all available at the developer Web site. We're going to start with how to print from a Cocoa application.

We'll build from there. We'll show you how to customize the Print Dialog, and then we're going to get into some specific topics. We really want everybody to know how to print with high quality. There's a few things that happen in a lot of applications that are messing up color or messing up the fidelity of your print. We're going to show you how to avoid that. And then since there's a lot of documentation, we're going to do an overview of how we've changed some of the documentation for Leopard. So I'm going straight to demo. All right.

Of course I will show you my favorite printer shortly. Okay, the first thing that you need to see in Leopard is what you can't see. There is no longer a printer set up utility. If you have documentation that references, please change it. Everything now is in System Preferences. The print and fax pane.

Everything's now available in the side bar. Your printers and your faxes will all show up. A little bit of status will be provided there. The user probably doesn't have to go here. Because we figure about 90 percent of everybody's got one of these, a USB cable, and one of these, a USB printer. And the way they're going to add a printer is by plugging it in like this.

If Leopard does what it's supposed to do, it's gone through all 2300 drivers, it's found the appropriate driver for this printer. In this case, it's my Deskjet 460. It is configured, the printer options in the print queue. New in Leopard. There's now the ability for drivers to have a tool to auto set up every feature.

So the user should do nothing but plug that cable in. Okay, now if you're in the 10 percent of people who actually don't have one of these nice USB printers, like a network printer, we have a browser which will show some series of printers that it can find.

Somebody in this room is sharing a printer on Quinn's MacBook. There's a couple of printers that are over with Duarte, which was doing all of our slides. Of course my USB printer right here. The connect type will show up. We will discover all of the Bonjour printers, of course.

We also added some legacy support for an SNMP protocol that's in most HP printers to discover those as well. If AppleTalk had been turned on, it's off by default in your system. Those printers would show up. Courses I had earlier, you can still enter in a manual IP address.

I highly encourage you to know what protocol you're using, because many printers don't support IPP, especially if they're old. AppleTalk, Bluetooth, a lot of good stuff. That's how people are going to add printers. There are two ways to get to this. One is from the Print Dialog, one is from System Preferences. You can now open the print queue. Print queue from here.

We changed the look of the print queue. Mostly, it's UI so that people can more easily see what's going on and get to information that they may need. I show you the get info here. This sheet has all the basic stuff about your driver. You can change the name, you can change its location, you can change the drivers. If those automatically configured installable options didn't come out right you can also change them here.

Many printers provide you the tools that will give you the supplies level. There's a few things here which will help for debug. Log and history will take you to console and drop you in the appropriate logs. A lot of interesting stuff built into the desktop printer. You should take a few minutes, familiarize yourself with that.

Back in the System Preferences, I showed you earlier, but it's that same info sheet. So you can get to this from two places. Hopefully nobody will ever get lost. Let me jump into, let me jump into applications here. Again, most people are going to plug in their USB printer. They'll never have to know that the System Preferences is how you can manually add a printer. You plug-in a printer; it will be there.

Okay. Safari, looks good. Mac version here, of course. This is the new world of the print dialog. For all applications the first thing the user's going see when they print is these simplified print dialog. You can select from your, your array of printers or faxes. We've moved faxes up into that menu for configured faxes.

We've kept the PDF workflow menu. All the workflow items continue to be accessible. And of course the user can always hit preview, and launch preview.app, which will render this drawn page. So all of that is right at their fingertips. And of course command-P return will generate document on paper. The expanded print dialog looks like this. The first thing that you notice which is most striking is that there is an inline preview. It does represent what's actually on the pages.

And it's actually live. So paper orientation and scale. One thing of note here which I always like. Safari forever, you used to go to Safari, try and squeeze it down to the number of pages you want you had to go to Page Setup. But we give all applications now the ability to move Page Setup application, Page Setup items directly into the application.

So as an application developer you have a choice. You can add in paper size, orientation, and scale right into the primary print UI. And it is live again. So if I do my 80 percent, you see I've got my Safari document here down to two pages. Which is what I'm always trying to do is figure out how to get that last page out.

One of the subtle things that you might not notice right off is that the applications print pane is now put up by default. In this case, Safari's, put it right up there. This is a blessing and a curse for all of you who used application print panes and used it to shove a whole bunch of random settings that you thought users would never find. They're now going to see it. The blessing is if you have important settings, if you make this pretty, you can provide more than one and put your important ones in the first one.

For the print panes we've reorganized them. The system provided ones will show up right after the application ones. Makes it a little easier for customers to find. You can do the AV comparison with Tiger. We've changed a few of them, we've eliminated a few of them. All in the goal of simplifying. All the printer specific extensions are put below.

There's some constraints about how wide these can be and stuff that will get talked about later in the session. But from the user's perspective it should be easier to find stuff. The work flow is here. You'll notice, interestingly enough, there is no preview button here. The inline preview becomes your preview of choice in the expanded view. Of course, if you want to have preview, you'll notice that the first item here is to open PDF in preview.

The application also has a choice to eliminate the Page Setup dialog completely. So based on how you deal in your application with which options or print time options, you may no longer need a print, a Page Setup, if everything's put in your print dialog. Okay. So with all of that. That's the overview. Go look at the new System Preferences. Spend a little time with the print dialog and think about what you can do with your application to take advantages of some of these features in the print dialog. So we'll go back to slides.

And, let me introduce David Gelphman whose going to give you the overview of the printing APIs.

( Applause )

Thanks Howard. Hello everybody. Glad to see you today. I'm David Gelphman, I work in graphics and imaging. Mostly on printing. Sometimes on graphics. Sometimes I write. I'm going give you a really high level view of the printing APIs on Leopard. Your application sits at the top here. And you sit on top of a number of printing APIs that are available to you.

There's the Cocoa printing classes that are available as part of AppKit. There are the Carbon printing APIs that are available as part of Carbon. Those are 32-bit only. Both of those APIs sit on top of the core printing APIs. We'll talk about those in just a little bit. And everything sits on top of the Common UNIX Printing System, CUPS, and I'll give you an idea of what, the kinds of things that are in CUPS.

So, just talk about sort of a whole bunch of different pieces of API, and you might say, well, what should I use in my application, it looks like there's a lot of stuff. So to paraphrase a great philosopher Woody Allen, I want to try and give you a little tour and a little bit more detail of these APIs and give you some guidance about where you might want to head. And for most of your applications you're not going to be using all these APIs. You're probably going to be using just one of these pieces. But they are all available to you, and I want you to have an idea what's in them.

So I'm going to focus first on the Cocoa printing classes. If you are a Cocoa application developer, and I am assuming most of you are, you want to be using the Cocoa printing classes. These are the important classes to your application, NSPrintOperation manages the process of actually doing a print job. NSPrintInfo encapsulates all the printing information about a given print job, such as the kind of, the size of the paper for your document, the print settings themselves and so on.

NSPrintPanel and NSPageLayout are the objects that represent the print dialog and the Page Setup dialog, respectively, in their methods in order to configure those and show them. And NSPrinter represents the printer object itself. And in Cocoa you can query that to get some information about the printer characteristics.

Now the Cocoa classes provide what everything that a typical Cocoa application developer would need for printing. It's unlikely you're going to need anything else. We're going to talk about other things, but that's really where you would be focused. Now, as I mentioned before, the Cocoa printing APIs or classes are built on top of the core printing, and in Leopard, new in Leopard, we are giving you access to the Core printing objects that are underneath the Cocoa printing classes. So that if you need to do something that's not in Cocoa you can. That's not typical for an application, but it is something that we've added, so that you can get at that.

So let me talk about the Core Printing APIs a little bit. Now, Core Printing is a new terminology you might not have heard before. A lot of my colleagues in graphics and imaging, they've been encouraging us to try to figure out how to get printing to actually execute on the graphics chip itself. You've already heard about Core Image, Core Video, Core Audio, Core Animation. Well, that's not what we're doing here, of course. We're not rendering on the graphics chip.

But Core Printing is something that's always been part of the printing environment of Mac OS X. It's a framework that's part of the application services framework. It's a C procedural interface. It doesn't provide any user interface. It sits underneath all the pieces that do provide user interface, as everything else in application services is.

There's no user interface associated with it. The types, these are classes. They're opaque data types. PMPageFormat and PMPaper relate to the paper size of a particular document that you want to print, and the format, such as the orientation, whether it's, you have scaling on, that kind of thing.

The PMPrintSettings represent the print settings for a given print job. So, number of copies, collation, dupe indicates, that kind of thing. The PMPrintSession is just a way to encapsulate a printing operation so that, for example, you, multiple sessions going on at once might represent multiple print jobs happening. And then the PMPrinter is the lower level class, type, which represents the printer in the Core Printing API.

Now the Core Printing APIs are available to any application that runs on Mac OS X, whether you have the user interface or you don't have the user interface. If your're command line tool, for example, you could use those APIs. If you're a Cocoa application or a Carbon application, you can use those APIs. They're rarely needed by a Cocoa app, but in general, these are, these are functions that are available to any class of application that's running on Mac OS X. Now, the Carbon printing APIs as I mentioned are 32-bit only, as are other aspects of the UI in Carbon.

And only a Carbon applications developer would use these APIs. They're procedural APIs. C procedural APIs. And these functions provide the UI portion of printing for a Carbon application. For example, to bring up the print dialog, to bring up the Page Setup dialog. Or to begin a print -- a print loop or a printing operation which shows a status dialog.

So those would be examples of Carbon Printing APIs. And anyone who's using these APIs would be supplementing, for example, their print loop, with using the Core Printing APIs that represent the non-printing portions of the, of your printing operation. Such as getting the graphics context to draw in too, as part of your printing operation.

And then underneath everything is the Common UNIX Printing System. This, again, a C procedural API. And most of the clients of these APIs are either the printing system itself, which is implemented on top of the CUPS. Or printer driver developers who are implementing their driver processes as part of the printing process.

Applications can use it. And the most typical use of the use of CUPS for printing application would be to look at the data in a post-script printer description file that describes the given print queue that you're going to print to. But that's not typical. That would be, for example, an application that does some kind of printer management, or some specialized applications that need to know more about the actual printer itself.

Now, as I mentioned before, Michael's going to give a talk, Michael Sweet is going to give a talk tomorrow about the Common UNIX Printing System at 9:00AM. And if you're interesting, if you're driver writer, or if you're interested in the lower levels of the printing system, you want to be there.

Okay. So let's talk just a little bit about the very basics of doing printing in a Cocoa application. And when I say basics, I mean basics. Just to get you started. So this is sort of the typical, what you would do as a Cocoa application. You would first create an NSPrintOperation. This is the method you would use. Print operation with view, with printInfo. And once you have a print operation, you would run the operation.

And running the operation causes by default the print dialog to come up. The user would interact with the print dialog. And when the user clicks print, the run operation method will make decisions about pagination and call your drawRect method in order to cause the drawing for each page to actually occur. So really, all that you do as an application is create the operation, call runOperation, and then respond to the request to draw the pages.

And here's what it looks like in code. Or at least a little bit of code. As always, your drawRect method is supposed to draft contents of the rect that it is requested to draw. So that's what you do. And when your view is sent to print, when you invoke the print method on your view you would, so I talked about the drawRect. For the case where you're now going to print you begin, you create an operation by passing in the view that you want to print.

The print info that you've created in some way that you want to use. Either from a saved document, or if you're printing for the first time from this document, you create a new print, print info. And then run the operation. So this is a really simplified view of printing. But you really could have this much code and get printing to happen in your application. There's no print loop. The Cocoa run operation takes care of that.

Now, there's, of course, a lot of things you might want to do to tailor your application to your needs beyond who I've just talked about. For example, by default Cocoa is going to take the current paper size and the size of your view, and it's going to make some pagination decisions about how to actually take your view and cut it up into a series of rectangles that represent the pages. You may have a need to customize that. There's a number of ways to customize it, including a very specify customization that I am going to show you in just a minute.

I mentioned that new in Leopard is the ability to use the Core Printing APIs. And so I will give you an example of that. And then after that we're going to talk in detail about customizing the print dialog in the ways that Howard's talked a little bit about already; we're going to give you a lot more detail about it.

So let's talk about adding custom, custom pagination. So, the first method I have here knows page range. Gives you the opportunity to tell Cocoa how many pages, excuse me, how many pages this document will need in order to be represented in your print job. My very simple example here is just to say starting with page one, and its one page. Now, a more typical example would be examine the print info for the current print operation, and to make pagination decisions to determine how your pages will layout for that print info, that is the paper size. And then report that many pages.

The second method I have here, rectForPage, is a method that you can implement to tell Cocoa, okay, for a given page, here's the rectangle on my view that I want you to request my view be drawn with. So this gives you a way to make all kinds of decisions for a given page which portion of your view should be drawn. Now this particular example gets the print info from the current print operation that's in play; that's going on. And for that print info it finds what the paper size is, and just returns the rectangle which is the width and height of that page.

So, like I said, it's a one page document. It's a very simple pagination I am using here. More typically, you'd of course would be making decisions about how to paginate, but the important thing of this example is that you're getting the paper size for the current print operation. And that's important for the live preview, because if the user's changing the paper size in the print dialog, or changing the orientation or whatever, your pagination is going to change, potentially, and you want to reflect in your rectForPage method.

Okay. So let's go into something a little more advanced in talking about how to utilize the Core Printing APIs, even as part of the Cocoa application. So as I mentioned before, this isn't something that's typical for most Cocoa applications. It is in Leopard and later only. There's no Tiger implementation or earlier. And just to give you an idea of some of the possible deeds, because we've heard about this from a number of developers.

For example, some people want to change the print settings for a given print job programatically. Some print setting, maybe it's the number of copies, maybe it's duplex or collation, or the order of pages, to do reverse order or something like that, but just to do it programatically, for example, maybe in your special office you have a special application that always want to print to this printer using a particular paper size.

And the users don't want, you know, for your, assembling a document that you want to print and you programatically want to say use ledger paper, or use some specific size paper. Or in this example, the print settings, specific print settings. So I am going to give you an example of changing the print settings programatically.

Another example would be to chose the paper size programatically. We'll see how to do that. And then just the third example that I am not going to show you in code how to do it, but an idea of where sometimes applications want to use the Core Printing APIs is there's the ability to do direct submission of documents. So you already have a fully formed PDF or PostScript file, and you want to submit that to the printing system with a given set of settings, there's Core Printing API to let you do that. And you can do that from a Cocoa application now.

Okay. So here's the general idea. As I said before, NSPrintInfo is the Cocoa encapsulation of print job information. So it contains within it a print session, a page format, and print settings. These Core Printing objects. Now Cocoa has added new methods to the NSPrintInfo class to allow you to get these objects out of a given NSPrintInfo.

If you get the object out and you make changes to it, for example you change the page format, in order to have Cocoa recognize that the page changed inside of its print info you need to call the update from PMPageFormat method, and the corresponding method if you were changing the print settings.

Okay. So let's take a look. I've just got a real simple example here of just programatically setting the number of copies and turning on collation for a given NSPrintInfo. Well, the first thing, of course, is you get the print info that you want to modify. However, it's the one you stored with the document or a new one you've created, or whatever. Once you have that, you can call the PMPrintSettings method on the print info to get the settings that correspond to that print info.

Once you have the PMPrintSettings for the print info, now we can use the Core Printing API on the PMPrintSettings to make settings changes. For example, in this case we're changing the number of copies to 10, we're turning collation on. Now that we've done making the changes we wanted to make we call the update PMPrintSettings method on the print info to tell Cocoa or notify Cocoa that the print settings have changed. It's a real simple example. Here's one that's a little bit more involved. So now this example's going to programatically set the paper size that a given paper info corresponds to.

So the goal here was to chose one of the papers that's available for the target destination printer. The built in papers, the manufacturer supported papers that are available. For example, U.S. Letter, U.S. Legal, Ledger, whatever's available for that printer. So there's four steps involved, and we'll run through them in code.

But I wanted to give you an idea of them first The first thing you do is well, you want to find out what the currently selected printer is; what's the destination printer for the print job. Because you want to pick from the papers available from that printer. Once you do that, you can get the array of papers that correspond to the built-in papers, or the predefined papers for that printer.

Once we have that list of papers we're going to chose the one that we want. Either program, you can do that programatically. Look at the paper sizes and choose the one you want. And once you have that, you can make the paper be that, you can make the destination paper for the print info be that paper.

So let's look at it in code. Once again, the first thing, of course, we have to have the printInfo. And from that printInfo we can get the PMPrintSession that that print info correspondeds to. And from the session, excuse me, from the session we can get the current printer that is the destination printer for that session. So for example, when the print dialog goes down, that would be the destination printer.

Once we have the printer or the PMPrinter object, we can now get the list of papers, the CF array, or the NS array, of the papers that are available for the printer. Now I've got a little cheat here because I don't know what algorithm you want to apply to choose a paper from that list. I'm just getting the zero, the first paper in the list from my example here. But once we do that we have PMPaper object that's a Core Printing object that represents the destination paper that we're interested in.

Okay. So now we want to make that paper be the paper that's used by the NSPrintInfo. The way we do that is we take a paper, we need a page format because that's what Cocoa understands as its underlying Core Printer object. So, from the paper that we just obtained, we make a new page format by calling PMCreatePageFormat with PM paper. So we created a new Core Printing object, a PMPageFormat object, and what we want to do is we want to make that be the new page format object that's used by Cocoa.

So what we do is we obtain the original page format. That is the one that's already in the print info using the PMPageFormat method. And now we copy over our new format onto the original format. That is we've replaced the page format in the original format with our new one.

Okay. We've made changes in the page format. We need to tell Cocoa that we've made the changes in the page format. Now the last thing here is because we've created a new page format, we need to release it. Cocoa will retain whatever it needs. We need to release it because we created it. And for the Core Printing API, the way to release those objects is using the PM release method, or release function.

Okay. A little bit more involved, but it just gives you a basic idea. And the reason I use this example is we found out this is a particular thing a lot of people want to do. Okay. I want to give you just a short summary of what we talked about.

We talked about the high level printing APIs. We talked, we did a little basic Cocoa print programming, and we used the Core Printing APIs from the Cocoa application. So next is we want to talk about in detail customizing the print dialog. And I would like to introduce you to Alan Beck.

( Applause )

Thank you, David. So, as an application you probably do want to be customizing the print dialog. So that's basically what I'm going to be talking about. There's several ways of customizing the print dialog. One of them, the first being the simple and expanded print dialog.

This is something the user would probably do. It's nothing that the application has control over. Basically, as you can see, we have the two different states. And it is saved on a per application, per user basis. So, in other words, say a user is in Mail. They really don't care about what print settings they have. They just do command-P return.

So they would be the, the print dialog in Mail set to be the simple dialog. Let's say you're over in Safari, or in Word, or in Pages, and that user does care about some of these, always changing some of the settings that are there. So he would leave the print dialog in that application in the expanded state.

And so basically when he brings up Mail it will show up in the simple state. And every time he brought up Safari it would come up in the expanded state. And there's one thing that we;d like to tell you is this is user controlled item. You as an application developer, you do not have control over what state the print dialog will be coming up in Now let's talk about how you, the application developer, can customize the print dialog.

The first one that Howard alluded to is we're now allowing applications to add the Page Setup functionality to the print dialog. As you can see here, this dialog, the application has decided that paper size and orientation are the two things that they want the user to be able to change in the print dialog. We feel that these are probably the two most common items that applications will be adding, is the print dialog. You can also add scale if you feel that users need that ability.

We have some guidelines for when to use, when to add the Page Setup items to the print dialog. We feel that this is mostly for applications that are not document-based. In other words, the content of your window or your application is transitory. So, in other words, document-based application, usually it saves page format information along with the document.

So therefore the user does really need to change that information on the document itself, so therefore the Page Setup dialog box makes sense for them. For some, for applications such as Mail, Safari, that are transit, content is transitory in nature, it does make sense for you to add that to the print dialog.

As Howard mentions, it does reduce a number of Page Setup print dialog round trips. Just say, I don't know how many times I have done that on Safari to get the right number of pages. You as an application developer, you must opt in to get this functionality. I will show you a little bit later as to how you can actually do that yourselves. And as Howard mentioned as well, you as application developer can decide if you do need the Page Setup, you know, menu item. Or you can remove it if you feel you need to.

We are, added another option for the Page Setup functionality. You can actually put the Page Setup functionality in its own pane. Allows you to basically keep the clean print dialog while still removing the Page Setup menu item. It's an option that you pass into some of the APIs.

So here's a very simple example of adding the Page Setup functionality. First thing you do is you create your print operation. You give it the view and the print info. And from the print operation you just go ahead and get the print panel from that using the print panel method on the print operation. And this is where the real work gets done. Basically, we call the set options on the print panel. We get the current options, and in this case we're orient in, saying we want to show the paper size. And orient saying that we want to show the orientation.

inline preview in the print dialog. This is something we previewed at last WWDC and now, the BetA that you guys have in your hands has the full implementation of the preview. As you can see, it is, you know, it is a live preview. You can see the number of pages. You can scroll through the pages. And as you click items, the preview does change.

There is some caveats with inline preview. It is for Cocoa applications only. It works in conjunction with the print operation. As David mentioned, your drawRect methods will be called to draw each page that is shown in the preview. It's like when the dialog comes up we actually one through your document, we figure out how many pages there are, and we will actually draw each page into that, into that context. It is shown by default for mostly the Cocoa applications. There we have another caveat. If you're using the old-style set accessory view, then the preview will not be shown. That is one of the caveats that we do have for the inline preview.

Now we have an inline preview, we want to make sure that you don't forget that the print view is important to the users. Where possible, use your document window to show what you're going to print. Don't, you know, let the preview or the print dialog do it. It is small. There is no Expand. You can't magnify in.

So the user will, you know, user is going be missing something in that itty-bitty preview. Your print view, unless you use your format the page and edit the data that they're going to be printing, and it's a good format to print. It's a good format to show the users in. And let's not forget, WYSIWYG is still important to our users.

And here's some examples of what we're talking about, the print view. This is iPhoto the card. And what you see on the screen is what you get out in the, on the print out. Other examples are FileMaker pages Adobe Lightroom, they all have the, what you see on the screen is what, is exactly what comes out on the page.

Adding application panes. This is where you, the application developer, can do the most customizing of the print panel. As we said, your print panel is now the first pane that is shown. We've added, you know, we've moved the copies and pages above the lines. So, to allow room for the application pane to show. And it brings your important print options to the front. Every user will see those if they have extended dialog and they hit command P. Okay. Some guidelines for you to use.

Your print pane should be used to provide print options and not formatting options. The formatting options should be done in your print view and not in the print panel. Also, not every application needs a custom print pane. If you, there is an application for print pane, we will just show our layout panel as the first pane that the user has.

We have a new suggested width that the pane is going to show in. Given that we've added the preview to of the side of the print dialog, we've had to shrink the area that's available to your print pane. So right now the maximum width we have is 420 pixels.

They're, I want to tell you though, make your print, your print pane view as small as possible. We will take care of centering it and showing it in the print pane. So don't make it 420. Put it as small as you can get it, and we will take care of the centering it for you. And if yours print pane is larger than 420 pixels, we will then grow the print dialog for the rest of that print dialog's lifetime on the screen to the old Tiger width, which is 543.

As for suggested height, we were saying keep it as small as possible. Given that what has been added above, above the panel has, can grow and shrink. We were saying just keep it as short as possible. And if your pane is too tall, you may want to consider breaking your functionality over several print panes.

Now, there's several different print pane types that application developers can use. For Cocoa applications and Leopard we have the new NSViewController. It is Leopard only. And for older, for Tiger and before, we have the old-style, the old-style accessory views. For Carbon applications and print driver developers we have the Cocoa-based print dialog plug-ins which work on both Leopard and Tiger. And the Carbon, the old Carbon CFPlugin print dialog plug-ins are created and again are 32-bit only.

So I'm going talk a little bit more about the new Leopard style of the print, the print pane, which is the NSViewController. It's a very simple way for Cocoa applications to add panes to the print dialog. And Page Setup dialog. It allows for multiple panes so an application can have as many panes as they want in that little front section of the pane pop up.

And it allows, also allows you as the pane developer to specify the title and provide summary information that will show up in the summary pane of the print dialog. So just basically, a few steps of what you would need to idea to add a print accessory view controller is basically create a class. You sub class it off of the NSViewController, and adapting it to the NSPrintPanelAccessorizing protocol. You would then create your nib for your pane.

And there's several methods that are part of the protocol that you would need to implement. You would implement the keyPathsForValuesAffectingPreview methods. And that basically tells the printing system when values of these keys change it is time to redraw the preview. So therefore, if you say print headers and footers. It is like, the user would check that box. That key would be changed. And therefore we know that we would need to redraw the preview.

The next thing you would need to implement, the localizedSummaryItems to get the summary text showing up in the summary panel. You would, if you want to change the name of the tile for your pane, we will grab the application name any way we can get it. And that would become the title for your pane. If you don't like that name you can implement the title method and we will use that strain for the title of your pane. Then just add the accessory controller to the print panel.

So I'll just do a quick demo of adding, adding a print panel. So what I've done is I have sketch, a standard sample application on your CD. And I've added my own new class. It is, we have a print session view controller. You can see I've subclassed it off of NSViewController. And added the NSPrintPanelAccessorizing protocol.

The demo I have is I am going to have one check box in my pane. Basically allow, it's going to be, allowing the user to print a frame around the page if they want. So here I have one button, the check box, which is the print panes checked box. And I have one action, which is the togglePrintFrame which is what it will be called when the user toggles the check box. Next is, let's go ahead and create a nib for it. So this is a standard nib. Let me go down. Let's pick a view.

Here's my custom view. Let's make it just a little bit bigger. And now let's go in and add my check box. And it's called, print, let me get the right keys. printPageFrame. Frame. There we go. And okay, then let's make it a little bit better. As I said before, I am going make it as small as possible, that encompasses all my items.

So that's actually my view. Now let's go ahead and hook up some methods for it. So my files, I'm going, I'm going make this our print, our PrintingAccessoryView controller class. And from here you can say that we have the togglePrintFrame. You know, and we have the check box. Let's go ahead and hook up the method for it. So let's take, drag from here. Wonderful new features of IB 3. Let's just go ahead and drag this. This is the check box.

This is the view. Hooking up to view. And here's the action. And I'm going to hook that up. Drag from there and hook that up to my check box. So basically now my view is done. And save it. Now let's just go back over here and look at the implementation of my view controller.

Basically, here's my implementation of view controller. on awakeFromNib, I am going to set the state of my check box. And what I am doing is I am saving the value for whether they want the print, want to print the PageFrame or not in my user defaults preferences. So basically I am doing, I am reading the value of the page, PrintPageFramePreferenceKey, and basically on or off state.

So that's, on initialization, that will happen. Now this is what I talked about earlier. The keyPathsForValuesAffectingPreview. This basically returns a set of keys of that, the printing system will listen to as those values change, the preview will be updated. Then we also added the two KVO compliant methods for that key, which is print, printPageFrame. Which basically reads the values out of the defaults. And the setPageFrame, which basically writes the values out to the defaults.

Next, we have the togglePrintPageFrame method, which is basically when the user checks it, checks the check box on and off will basically set the PageFrame to be basically what it wasn't. Then next we have the localized summary items. Basically the printing system is inspecting an array of dictionaries for every item that you want shown in the summary pane. So basically here's an array. This had one item.

We have the, the name for the item. Which is Print Page Frame. Then whether we have it on or off, we should say on or off. There again, it's up to you the application developer to make this localizable as well. And lastly thing we have, the title. Which basically I'm just returning my Sketch Print Panel.

So that's all there is to the controller. Now let's go to the view, the actual view that does the rendering. And here's the drawRect method. It's giving a call for every page. And here's what I have added. Basically I go ahead and read the value out of the user defaults. And it says that they want to print the PageFrame.

I set the color to red and frame that, frame the bounds of the view. So that's all there is to the view. Now let's go to the document, which is the last portion of it. Let's go let's find the print operation. This is where the sketch document prints, sets up the print operation.

So basically here we create our print accessory view controller. We allocate it with our nib name. We add the AccessoryController with the AccessoryController method giving it our ViewController. And now that we've added it to the, now that we've added it, we can release it So let's go ahead and run this, and hopefully, let's make something, there we go. There we go. Let's just do a little face. There we go. Let's go ahead and hit print.

There it is. And there you can see, this is the check box I added. It is live. So you can see the, the red bounding box being drawn. And if you go to the summary pane, here is my sketch panel, which is the name of the panel that we added.

And basically here we have the printPageFrame that says its on. If you go back up here to my sketch panel, let's turn it off, go back to summary. And there it says that it is off. So basically you can see, it's very easy. Let's go back to slides.

See, it's very easy to add print panels to the print dialog. It would be the same thing, exact same thing would happen for the Page Setup dialog as well. I just showed an example in the print dialog. Use the NSPrintPanel or NSPageFormat, NS format, to add the AccessoryController. Use keyPathsForValuesAffectingPreview to keep your preview up-to-date. Basically return the list of keys of values that would affect the preview. Then you use the localized summary items to provide summary information.

Now in summary, highlight some of the things we're talking about with customizing the print dialog. Your application pane is now the first pane that is shown to every user. If your application is not document-based, you now have the option to remove the Page Setup menu and add to the controls of the print dialog.

Last thing I want to stress is you, the application developer, are now in control of what is shown in the dialog, in the print dialog. And it's up to you to decide what is right and what makes sense for your application. Now let's hand it back to David and he will talk about producing high quality output.

( Applause )

Thanks, Alan. So what do we mean by this? We're going to talk really about two specific topics here. One is as an application developer how do you leverage the system color management to the best, to your, in the best way for your application? And we're also going to talk about what it means to print with the highest quality representation of your data at print time.

So let's start by talking about the way color management, or the concept of color management and how it's built into Mac OS X. On the left here we have sort of the data content as it is on the screen, and as it is in the original data content.

And if you use device color, that is you don't use color management, when you print you may end up with something on the top, on the right. Or if you used device independent color at the time you render your color document, you will get color managed output at print time.

And we expect that to represent what you see on the screen or what the original content looks like. I have blown these up so you can see where we haven't done color management, we've changed the color of the water, we've changed the color of the jacket. Whereas when we've done color management now we're seeing something, color that's similar and equivalent to what you've gotten on the screen.

And you want to see that in your application when you print. You want to get high quality color and reproducible color when you print. So let's talk about the concept of device color versus device independent color. Device color is tied to the specific output device. For example, for RGB color, if you have red, green, and blue color values what you get with device color is going to be dependent on what device you look at those red, green, and blue values with.

Calibrated colors are device-independent colors. They contain additional information, in addition to the color values themselves, that allows you to take that color and reproduce it on another device. That is, those, the calibration data characterizes the color in a way that makes it reproducible on another device. Well, the message of all of this is you want to draw with calibrated colors.

Now Mac OS X printing color management, during the print, during the path of the printing your document through the printing system we preserve color information that you supply us at the time that your application prints. And this allows us to do a faithful reproduction of color. So here's sort of a, the way a printing application and data from that application passes through the printing system.

So on the left here we have your application. Which is going to generate color in one or more device independent or calibrated color spaces. The printing system will take the drawing that your application does and it will produce a PDF spool file from that. And that PDF spool file is going to be transmitted to the print server that will ultimately control the printing of your document. Now that print server, which is where the, that print server may be on the local Macintosh that your application is running on. Or it could be on some network somewhere very far away from your Macintosh, where the PDF document will be transmitted.

So this example that I'm using for raster printing, and for example, that raster printer will be potentially hooked up to the print server that you're actually printing to. Either your local one or the remote one. On that remote print server we're going to take the PDF data and we're going to turn it into bits that we're going to hand off to the raster printer driver.

And that's this process here. Where we're going to render the data from the PDF document into raster data. Now the printer driver supplies us with a profile that characterizes that printer, that describes how colors, how colors are reproduced on that printer. And that profile can be used by the process that converts, that rasterizes, to preserve the color so that it's matched to the destination printer device.

Once we have that raster that's passed onto the printer driver and the printer driver packages it up and sends it to the raster printer. So really the focus here though is on your application. What do you need to do to draw so that you're putting the right data into the pipeline, so that we're going to get color managered results on the end.

So here's a simple example of drawing with calibrated color using Cocoa. This particular example I am using the calibrated generic RGB color space. That's a color space that we provide in Mac OS X that represents sort of the typical Apple color monitor. Not a specific monitor, but the typical Apple color monitor and characterizes such a monitor.

That's a good choice for an application that doesn't already have some color profile data associated with the data that you're drawing. If you have tag data, for example, you have images that already have profiles, of course you're going to use those profiles when you draw your image. If you're bringing data over from Windows, for example, you may already have SRGB data associated with the drawing you're doing, and you would then draw using an SRGB color space. But if you don't already have color space associated with your data then this would be for Mac OS X a good choice. Okay. Let's take a look at what it looks like.

So the first thing we do is we, we create the generic RGB color space, or obtain it, rather. And once we have the generic color space as an NSColorSpace object, now we have a set of color components that represent the color that we want to set. In this case we have a red, green, blue, it's an RGB color with 50 percent alpha and 100 percent red.

Once we have the color components and we have the color space we can create and, CG color, excuse me, an NSColor object that represents that color. We can set that to be the current fill color on the current Cocoa graphics context. For example, the context that's in effect at the time your view is, your drawRect method on your view is called. And once we set the fill color we can fill a rectangle. So, you know, this is really a simple example. But just to give you an idea. It's easy to create color, calibrated colors, using Cocoa.

For those of you that aren't using Cocoa or, for example, Carbon developers, here's an equivalent example using Quartz directly. So in this example we're going to create a CGColorRef, which is just an object that represents a particular color to Quartz. We do that with the same red, green, blue alpha values. Using CGColorCreateGenericRGB, which is creating a color in a generic RGB color space.

We take that color and we make that the current fill color on the context. And of course, in Quartz, when you're drawing directly with Quartz, you specify the context directly to the function. There is no implicit context like there is in Cocoa. Now we fill the rectangle, and that will fill it with the current fill color that we've just set. Now because we created a Quartz object, we need to release it. So we can do that with CFRelease. So that's really just very simple drawing using calibrated color, but just to give you an idea about how you would go about it.

I want to talk a little bit about obtaining the maximum fidelity when you print. So the first thing in this step is to not make any assumptions about the destination printer characteristics at the time you're drawing your content for print. So the destination printer may not be what you think it is.

For example, users, once a print job is generated, can take print jobs out of one queue and drag it into other queue. Or they may be using the Save as PDF feature that's in the print dialog to create a PDF document. And you don't know what the destination for that document is. You really want to produce the highest quality rendering that you can that represents your original data at print time.

So correspondingly, you want to draw it at full resolution of your data. You don't want to downsample your data unnecessarily. If you have deep images, 16 bits per sample per component, or you have floating point data, or raw data, you want to preserve the depth of that data. You don't want to downsample or turn it into 8-bit data. In the printing path, supports deep pixel data.

So it supports 16 bits per component image data. That's what you have, that's what you want to be drawing at print time. You may make some other decisions for rendering on screen for performance reasons, but at the time you want to print, you want to get the maximum fidelity.

So just a couple of comments how you go about that. Now if you're already using Quartz for drawing your images, you're there. If you use CGImageSource or CGImageCreate, as long as the source data that you're providing to those functions is, represents the true data from the original content, and you draw using CGContextDrawImage, that will be captured in the PDF spool representation of your drawing. If you're using NSImage, you're okay there too. As long as you're not, for example, redrawing your image. So if you're just drawing your image, NSImage will draw at full resolution.

Just be careful. If you're locking focus on your image and drawing into your image to alter the image, at the current time NSImage is going to make an 8-bit representation of your image at that point in order to capture the drawing. So if you need to do some kind of image processing or drawing you might consider some other techniques.

For example, Core Image, this is something we introduced in Tiger 10.4, Core Image in its processing of your image data maintains the resolution and depth of your images as part of its processing. So what comes out will represent the maximum quality of the original image as it's being processed. Now if you're doing some kind of custom processing on your image using your own tools, just remember, certainly for what you're going to produce at print time, you want to maintain the original quality, depth, and resolution through your pipeline as you're doing that.

Okay. So one of the themes we've been giving here at WWDC is talking about 64-bit and 64-bit applications. So you know, the printing system's 64-bit ready. The printing APIs that we've talked about are available to 64-bit binaries. If you're a Cocoa application, the printing, Cocoa classes, the printing Cocoa classes are available, 64-bit applications. The Core Printing APIs that I talked about, they're available to 64-bit applications with the exception that those deprecated functions, or the functions we deprecated in both Tiger and Leopard, are only available 32-bit applica2tions. In the CUPS printing API, it's all available as 64-bit.

As I mentioned before, the Carbon printing APIs, along with the other HI aspects of Carbon are 32-bit only. 2 So what does the print dialog look like in your 64-bit application; what is the printing experience for your user? Well, it's going to look the same as a 32-bit application.

The possible exception is the print panes and the print dialog that are provided as plug-ins by third parties. For example, by printer driver vendors. The system-provided panes are all 64-bit ready. Many of the printer driver panes that are shipping with Leopard are 64-bit ready, but there are some that are not. And of course there are going to be some from other parties that aren't part of the Leopard, part of Leopard directly, that aren't 64-bit ready.

There's actually a couple aspects to what panes show up in the print dialog. The architectures of the application that's running and the plug-in that's being loaded have to match. And what that means is that the processor architecture has to match. If you're running a 64-bit application, the plug-in has to have a 64-bit aspecdt to it. And, for example, if your garbage collected Cocoa application, then the panes that are provided by the third parties that will load require the garbage collection is enabled on those.

Now here's what the print dialog will look like if, for example, there's a pane that would otherwise load but is not available that matches the architecture or, for the application that's running. And in that case, the pop up, the menu item and the pop up will have a line drawn through it and there's some explanatory text if the user visits that pane that says something about this aspect. Just wanted to touch on documentation, briefly.

So, in 10.4, the primary header files that were part of both Core Printing and the Carbon printing manager were two header files, PMCore.h and PMApplication.h. And those contained all the functions that were available, whether they were deprecated for not. And to make life easier for the application developers to find the right functions to use, we've split this up so that now there's two header files that correspond to the original header file that you saw in Tiger. So we have a PM CoreDeprecated.h that has all of the deprecated stuff. And we have a PMCore.h that has the modern APIs that we want you to be using in Leopard and going forward. And similarly, for the Carbon header files PMApplication.h has been split as well.

Another thing we've done, we've talked about the fact that we have this layer in the printing system now and the APIs that are available called Core Printing. We've taken the reference material, which used to be called the Carbon printing reference, which contained all of the Carbon APIs plus the Core Printing APIs that I've talked about. That used to be one document.

And because the Core Printing APIs applied to a lot of developers and the Carbon printing APIs are used for the smaller segment of developers, we split them into two so you don't go looking in Carbon documentation, when really what you're looking for is Core Printing. So now there's two document; a Core Printing reference, and a Carbon Printing Reference.

So related to documentation, these are sort of where I want to point you to. Print Programming Topics For Cocoa is really a useful resource for Cocoa programmers that talk about Cocoa printing in quite a bit of detail. On the seed that you have, the AppKit Release Notes have been updated for the 10.5 seed.

They contain a lot of the information that Alan talked about. How to do an NSViewController, what the new, well, the way to set the print panel up so that you actually get the different features if you want the Page Setup functionality in the print dialog. And then as I mentioned, the Core Printing reference and the Carbon printing reference as separate documents now. And they've within updated, so they contain the preliminary information for the Leopard seed, about Leopard.

Well, I have to talk about one other piece of documentation, which is sort of a shameless plug for a book that I wrote along with Bunny Laden on programming Quartz. So for you Quartz programmers, there's a reference that hopefully is useful to you. Thank you.

( Applause )

Thank you, I appreciate it. We've gotten some really good feedback on the Web and directory from people. And really nice comment from Michael Johnson from Pixar about the book.

So, also tomorrow for our printing lab, which is at 10:30AM, I hope to see you there. I am sure you will have lots of questions. And we'll have the whole printing team there. And I actually brought a couple copies of the book. So if you haven't seen the book it will be in the lab as well. It's actually there now. Been here all week now. M01:04:39