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

WWDC05 • Session 213

Harnessing the Power of PDF

Graphics and Media • 1:13:58

Understanding how to take advantage of Mac OS X's PDF capabilities is important for all application developers. Learn how Quartz 2D and PDF Kit benefit your application by giving easy access to the robust graphics and final form document capabilities of the PDF format. Also learn how Mac OS X's PDF-based printing architecture can increase the features and capabilities of your application via its PDF Workflow feature. Don't miss the opportunity to harness the power of PDF in your application.

Speakers: Paul Danbold, Richard Blanchard

Unlisted on Apple Developer site

Transcript

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

Good morning and welcome to the PDF session. Paul Danbold, one of Apple's evangelists. I'm going to start this session with a little bit of an overview of all the PDF services in the OS. The goal here is to make sure you get the big picture. You know, what we've done in the OS to support PDF, why we designed the APIs the way we did that, the various tools and things we built upon those APIs.

And you can see what we've done manifested in many of our applications like Preview and other PDF-savvy apps. Most important, of course, is we want you to get the message that you should support PDF in your applications and software products and try to make sure you understand where you can tap into the OS at what level in order to provide PDF functionality.

Does anybody in the room not know what PDF is? Stand up and wave your hands if you don't. Uh, I was, uh, "We'll take care of you later." Okay, so we're not gonna talk about the details of the PDF specification, but, uh, we'll take just one slide, basically to remind you why PDF exists.

Uh, I'll let you read this quote from John Warnock, uh, and then just make the simple point that when we designed our APIs to support PDF, uh, the model we had in mind was true to the original spirit of PDF. Uh, basically as a container for, you know, text, graphics, images, uh, that's sufficient, uh, high fidelity, device independent, et cetera. Um, and so when you look and evaluate our APIs, that's what you should bear in mind.

So I'm not here talking about T-Raw or some other file format. We're talking about PDF today. And we picked PDF because it met our requirements. And I've just got a couple of things to say about the ways in which PDF meets our requirements, and I think it hopefully meets yours. One thing that almost goes without saying is that PDF is a proven technology.

If anybody here is from the Acrobat team, thank you very much. Your product is coming up for 12 years old. I think actually sometime next week. And the PDF spec itself is a little older than that. It's been around for about 13 years. So it's well established. Pretty much anybody on the planet knows that if you want to create a document that may be viewed on other computers and printed, etc., and appearance matters, then PDF is the choice. It's definitely the best choice. So, Another thing we like about PDF is that the spec is public.

Go to adobe.com any day and download the specification. You don't have to sign a license agreement or do any NDA stuff. You can read about PDF in detail and go write products that use PDF. Not quite sure the same is true of Metro, but we'll see. And talking about that, or sort of tying into that, another thing we really like is that PDF is cross-platform. You know, you can create a PDF on any computer system, and that PDF might be viewed on any other computer, and it might end up on paper, and modulo the capabilities of the target device. It's going to look the same.

Another thing we like about PDF, because there's lots of PDF documents in the world, is that it's a compact and efficient file format. You know, if you have an image appearing multiple places in a document, only one instance of that image can be stored in the file. And the same goes for other things that tend to take up a lot of space, like, you know, fonts and color spaces. So it's an efficient file format. And then if you're security conscious, a nice thing about PDF is that you can encrypt and password protect PDF files.

So all those things are good for us and good for you, good for customers. That quote that I had a couple of slides back from John Warnock had the word "paper" in it. And we like to think of PDF as digital paper. And there's some interesting aspects to that. Unlike, say, HTML, when you create a PDF file, you as a creator control what that PDF file is going to look like. It's formatting.

So regardless where that PDF is viewed, on somebody else's screen, on paper, the format should be preserved. All that information is stored inside the PDF file itself. And then when it's drawn on screen or goes to paper, then it can be drawn with the highest fidelity and the best color accuracy possible for that target device.

And it is page-oriented, which means you as the creator of the PDF file, you have some say in where the page breaks are, and for every page size, you control the margins, et cetera. And it's random access. So kind of unlike PostScript, the viewer of a PDF file can go to any page in any order and display it, print it, et cetera. As spotlight shows, and as you can do in applications like Preview, et cetera, you can search PDF files. That's pretty easy.

I mentioned last slide, it's encryptable. So you can password protect a PDF file. If you open it up with the owner password, you've got unlimited privileges to go as far as changing the content of the PDF. If you open it up with a user password, you have limited privileges. And so you can usually view it, but you may not be able to copy the file or print it.

Last, PDF was never designed for inline editing, like you can edit an RTF file, etc. But if you want to circulate a PDF document for review, those other people can circle things they don't like, add little text stickers, etc. to the document. They can't fix your spelling mistakes, but it's an excellent format for groupware and things like that. So put all that stuff together. Basically, PDF is great for a lot of purposes.

It's a lot of purposes that are important to us. That's why, you know, for printing, it's our default spool file format. That's why it's a native file format for our graphics stack. And it's why we make it so easy to create PDF on the platform. You can do it from the print dialog for any application.

So here's where you come into the picture. What can you do with PDF? And I guess the answer ranges from nothing, in which case, I don't know why you're in this session, but to everything that you can do in apps like the ones we provide, like Preview. Safari is a good PDF client as well. Generally speaking, the more your application deals with text, vector graphics, images, et cetera, the more PDF functionality you should build into your application.

I'll let you read this list. I just want to make a couple of points. The first one is, if you provide the functionality to open up a PDF from the file system or somewhere on the network, we really think you should be able to open up PDF from the PaceBoard.

So, that's a great sort of solution for getting PDF from one app to another. Another thing is, although we provide PDF generation from the print dialog, something you should think about is whether your users are going to think to go there if they want to create PDF. So, you should think maybe about adding a save as or an export item under the file menu. If your application is, you know, let's say a music application or deals with a lot of numbers or video, for example, then maybe export makes more sense than save as. Anyway, something to think about.

I mentioned the fact that PDF isn't designed for editing, interactive editing, but there's nothing to stop you writing a software product that can modify PDF files for very useful purposes. For example, a printed position program is going to relay out the pages in a PDF document for maybe printing a booklet. So we'll get into all the other things mentioned on this slide later on in the session.

I've got a diagram here, PDF services, just to give you the big picture for what you can do with PDF. And the gist of this diagram is that Quartz 2D is the mothership. If you want to go down for the finest brain control over PDF processing, the Quartz APIs provide that for you. You may well want to go down there to implement the functionality you want, but something we're going to focus on in this session are the things that are on the second layer.

I'll get into those a little bit later, and then we'll really go into depth on things like PDF Kit. The important thing for you coming out of this session is to know that if you want to add PDF functionality, yes, Quartz may be the place to go, but then there are the higher level services that may make your life easier.

So we'll start with Quartz, Quartz 2D. It contains basically a comprehensive set of APIs for working with PDF. PDF creation, opening up, drawing PDF, etc. The good thing is that we've done the heavy lifting for you. All the APIs, easy to use, very well documented, lots of sample code. So if you want to add PDF functionality, you're very welcome to read the PDF specifications. It's about 1,200 pages long. But you don't really need to do that. You know, look at our documentation, start using our APIs, and you'll be off to the races pretty quickly.

Definitely not in this session going to give you the full set of PDF APIs out of Quartz 2D. I've just got two slides here with a small sampling of the PDF APIs. Just want to make a couple of points. I'll repeat the point about the pasteboard. Down on that third bullet item, I want to make the important point.

You know, we enable you to open up protected PDF files, but it's an honor system. So if you open up a password-protected PDF file, it's your duty to honor the privileges that are in that PDF file. So you should call the APIs that we provide, and I haven't listed them here, but, you know, we provide a function to check if it's okay to print the PDF file. And in fact, even if the password string is blank in the PDF, you should always check the privileges before you enable any type of functionality on the PDF document that's being opened up.

And I'm going pretty quickly through this slide, but just looking down at the bottom bullet item, we have, especially in Tiger, we've provided full functionality for PDF. You can get at everything. And there are lots of APIs for getting information out of a PDF document once you've opened it up. There's document-oriented APIs, page-oriented APIs. So we're really giving you full access to the PDF.

When it comes to creating PDF, that's also extremely easy. If you already know how to use our drawing APIs to draw into a window context, you can use that same code and draw the same content into a PDF context, and you've got a PDF file. So it's really easy. You should also enable writing PDF to the pasteboard, like I keep mentioning.

In Tiger, we've added a couple more things just to sort of keep up with the latest capabilities of PDF. You can create links from the document you're creating. I haven't shown the API to do this, but you can create a link to a web page. The two functions I've listed here enable you to create a link between one rectangular area on a page to somewhere else, to a point somewhere else in the document.

The last thing we did in, the last thing mentioned on this slide that we put into Tiger was really to give you 100% access to the content of the PDF. So you can now get into the page content stream. This is the point, if you need to do this, where you really do need to start reading the PDF specification. Once you know about PDF operators and the whole imaging model, if you need to, and again this is only for very specialized purposes, you can get down into the contents of every page.

We can never talk about PDF without somebody getting up and saying, where are we with respect to the latest specification? And the simple answer is, we're up to date. Generally speaking, any PDF document you find should be rendered correctly by Quartz 2D. It should look good in preview and any other application that uses it. If you run into a document that doesn't render correctly, send it to us. File a bug report.

We've got a couple of known exceptions, knockout groups and some oddball shaders. So there's a few things that we may fill in in the future, but basically we're up to date with the latest spec. When it comes to writing out PDF, you don't want to assume that everybody who reads your PDF supports the latest spec. So compatibility is the important thing. We start off with 1.3, the 1.3 spec. That's our baseline. And then only when we need it do we start using it. We're not using things out of 1.4 or 1.5. So we use some 1.4 stuff for transparency, etc.

Okay, just want to make one more point before I move off from Quartz, and that is to say, you know, to remind you, all the features are there, easy to use, well designed, well documented. The other thing you shouldn't forget is it's free. You know, you've got the Quartz framework, or rather the Core Graphics framework. All those APIs are there for you.

Now it's these other things that we're going to cover in more detail in this session, so I'm not going to steal the thunder from the folks who are going to take over after me. Just to take you through the layers quickly. PDF Kit, if you've got a Cocoa app running on Tiger or later, PDF Kit is probably your answer. Very easy to use and just look at what you can do in Preview, Mail, even Xcode, definitely Safari. If that kind of functionality for PDF meets your needs, then PDF Kit is your answer.

You know, we've got all the APIs to generate PDF, but sometimes you want to repurpose PDF. You might want to generate PDFX3 for sort of print, for sort of pre-press print applications. PDFX3 is a subset of PDF where you want to control the type of PDF generated, you know, just to make sure you don't have nasty surprises when the PDF goes to the press. And you can do that with a Quartz filter.

You can also do things like repurpose PDF for viewing on the web where you don't want very high resolution images. So the place to go to create those Quartz filters is the ColorSync utility. You can go there, create Quartz filters, look at the ones that Apple provides, you know, pre-canned for you, test them out and apply them. So you can repurpose your PDF files with Quartz filters. And they're accessible from Preview and the Print dialog.

To state the obvious, the printing system knows all about PDF. We have code that will turn PDF into PostScript, PDF into Raster data. We have code to turn PostScript into PDF. And what we'll get into, and what Richard Blanchard touched on in the previous session, was we allow you to hijack the PDF coming out of the print dialog and send it to your code, your application's tools or scripts, whatever, and use this mechanism to create PDF workflows.

Something else we'll cover later on in this session, Automator, which I assume you all know about, it has a set of PDF actions, and we'll be showing you how to create your own PDF actions to extend what you can do with PDF in automotive workflows. And since Panther, there's been Quartz bindings for Python, so you can now generate, modify, and do other things with PDF in Python scripts.

I just got one last thing before I hand over to talk about, and that is that PDF is a great solution for legacy formats. So if your software is used in places where people insist on continuing to use EPS graphics and things like that, then PDF is a great solution. Of course, PDF shares the same imaging model with PostScript. So when you're handling EPS, for example, using our PDF APIs, you don't lose any of the information in the graphic text. The text stays as text, lines stay as lines, et cetera.

If you use the APIs, some of them listed here, then what you can do is you can render the EPS with full fidelity onto the window and print it correctly. You don't have to see the, you know, the jaggy preview images either on screen or print. So for Carbon, Cocoa, and even down at the BSD layer, we let you handle, you know, PostScript-based, what I call legacy file formats using PDF. And the same thing really applies for Quickdraw, which also is deprecated. So if you want to bring in, you know, Quickdraw data, picked files, et cetera, you know, to screen or out to print, you can do that as well, both from Cocoa or Carbon. Okay.

So that's the whistle-stop tour of everything we've done with PDF in the OS. Just a quick summary, and then I'm going to hand over. So if you're in any doubt, think about the PDF functionality you need to put into your application or software product. If you need the fine-grained control, Quartz 2D is your answer.

All the APIs are well-designed, documented, et cetera. Lots of good sample code. But if you want to use PDF and you're running Tiger or Later and you're Cocoa, then pay attention to the next part of this session, because PDF Kit is just great. Gives you almost all the PDF functionality you're likely to want.

And for the last part of this session, we're going to get into PDF in the workflow. There's a lot of things you can leverage that's sitting on top of Quartz 2D that will make your life a lot easier. So with that, I'm going to hand over to John Calhoun. Let's talk about PDF Kit. Take it away, John. Thanks. Hi.

Okay, so PDF Kit is a new framework in Tiger. There's actually a new framework called Quartz Framework in System Library Frameworks, and that's kind of an umbrella framework. PDF Kit's one of the frameworks inside Quartz. And I mention that because if you want to write a Cocoa application today, you're going to have to manually add the Quartz Framework to your application to get the PDF Kit framework support.

And also while I mention it, if you're using Interface Builder, one of the things you might want to use from PDF Kit is PDF View, and that's inside a PDF Kit palette, which is under Developer Extras Palette. So you'll have to add that to Interface Builder, and then that'll give you the PDF View that you can add to your application.

[Transcript missing]

Okay, so here's the first sort of little architectural slide. PDF Kit is essentially a suite of these PDF class-- NS object or App Kit, Cocoa classes. You can see that the one in yellow, the PDF view, is going to be the more complicated one. It's subclassed off NS view, so all the sort of things that NS view has and inherits, like a view, hit testing, events, a draw method, PDF view has as well. And most of the talk that I give will sort of focus around PDF view, but I don't want you to think that you have to have a view-based app to use PDF Kit.

The other classes that you see in blue are-- I call them kind of utility classes, PDF border, destination. They don't require a view, and you could just use these if you wanted to search for text in a PDF or get the position of each character on a page, that sort of thing.

I'll talk more about these classes later. And then I'll talk about the other classes that are more complicated as they come up. The only thing I wanted to point out, though, was the other sort of utility classes are all just subclasses of NS object, so they're more-- they're simpler, I guess. And then the one class at the bottom, PDF annotation, is a virtual class. So all the real work, for the most part, it happens with those subclasses.

So a PDF annotation could be a circle or free text or a link, and so that's where some of that functionality is going to come in. So I already explained this, that there's the high level view and then the utility classes. So let me just show you then a little app I wrote. and back on demo machine one. I guess I didn't get that turned off.

[Transcript missing]

Let's see if it turns off this time. It's supposed to be command+F5. So this is PDF Linker, and this is available-- all the sources for this are available. You'll see the URL at the end. It's available from DTS, should be up on the website now. But I'm just gonna first thing just open up a PDF, and you'll notice that we borrowed a lot from Preview here. There's a toolbar at the top.

There's--at the bottom, I don't know how well you can read that, especially in the back, but there's some UI. There's some radio buttons that are grayed out. A drawer has opened on the right side. But the main part of the window is the PDF view, so you see the PDF content here. So I'll switch back to the slides and show you.

How you first get the document to come up. And this is only, this is like I said, this is the two or three lines of code that Safari really had to do in order to get a PDF to display in the PDF view. This is where the first utility class comes in. A PDF view needs to have a PDF document associated with it. So what the code does in PDF Linker is it allocates a PDF document and then there's a method called init with URL.

So usually your application has a URL like if you're in a document-based app, you can ask the document for its file name and that will give you a path. Or if the user has just brought up an open panel, you can ask for the URL. But there's another method in PDF Kit for creating a document from data itself. So once you have this PDF document object, you tell the PDF view set document. And then once you do that, the view is going to retain the document so the last line of code just releases it.

So that's all there is to associate in a document with a view. So I'll show you just a few of the attributes then of the PDF document. You can ask the document for the number of pages. Oh, I should point out, once you call set document on the view and release it, you can always ask the view for its document back.

So the reason you might want to do this is for some of these attributes. You may want to query the document and find out how many pages are in the document. The way that you get back the pages is to ask the document for one of these PDF page objects. And I'll talk more about that later.

Certain document information, like the author of the document, the title, subject, keywords, those sorts of things you'll get from the PDF document object. Searching actually happens within the document itself. That allows the document to kind of search across pages. If the PDF document has an outline associated with it, it's from the PDF document that you'll ask for that outline. And I'll show you that in a minute. And then finally, if you want to save the document, save the PDF, the PDF document class has the save methods in it.

Okay, so back to the demo. So how about navigation? So within the PDF view, I've got a toolbar at the top and you see the next button. There's a previous button that's disabled. If I click on the next button, it obviously tells the PDF view go to the next page and you see now that the previous button is enabled. I can click next, next, previous, previous. Let me turn something off here.

And And you also see that within the PDF, when there are links, like if I click on this link here, it takes me to page 24. That happens for free. The PDF view is handling that. But the PDF view is also maintaining a history. So as the user navigates and goes to the next page, previous page, or traverses links, the PDF view is maintaining a history so that I'm able to very trivially put a back and forward button in the toolbar.

And have the PDF view navigate through the history. Also, another way to navigate is to type in an explicit page number, like I typed in page 20, and then the PDF view will go to page 20. Something I'll just show you is you may not have, or you may have noticed that as I've been kind of moving through this document, this page number field here has been updating. So what I'll do is show you in code how that's done, and show you frankly how easy that is to do. Back to the slides.

So, in order to go to the next page, you just tell PDFU go to next page. Go to previous page. I told you that the PDFU is maintaining a history, so you can just say go back, go forward. And then there are sort of helper methods like can go back and can go forward that return boolings so that you're able to enable or disable UI elements in your app. Then the last method of navigating where I typed in a page number, there's a method on the PDFU called go to page, and it takes a page object.

And remember I said that you get back page objects from a PDF document. So, you would ask the PDF document for the page that corresponds to an index. And since we're zero-based internally, if the user typed in page 20, you'd ask for the index for the page corresponding to index 19.

So, I subtract one, I ask the document to give me back that page object, and then the view has a method go to page. I pass it that page object, and the right thing just happens. The view updates, goes to page 20, and that's added to the history.

And then as far as how your application can show what current page the user is on, there's a notification in the PDF view. So every time the view changes page, either as a result of you calling, go to next page, go back, go forward, or the user actually clicking on a link internally within the view, a page change notification comes up.

There's other notifications at the document level. PDF view has other notifications as well. So I'm just kind of going over the surface of it in my little session. You can always check the documentation and find out a lot more than I'm going over here. So back to the demo app.

So I'm going to be brief here because Preview does a much better job of this, but there are a number of display options, and I already showed you a number of those in Safari, that you always have this contextual menu. And one of the things I added to this PDF Linker app is I put in a little toolbar item that allows a user to select between, I just picked three various display modes.

So here we're in, you know, sort of the single page continuous mode where I can scroll through the entire PDF, or I can switch on, by clicking this toolbar item, I can switch to the one single page mode here without the scroll bar, and the user has to navigate this way. Or the two up, facing pages mode like that. And if you look at, I'll switch back to my slides.

In order to control that, to control how the view displays the PDF, there's just a real simple call, PDF view set display mode, and we have a number of defines for one up, one up continuous, facing pages, facing pages continuous. So it's real trivial for me in the toolbar item to just call one of those, set one of those display modes in the PDF view.

But like I said, I'm not going to go over all the other display modes. You can play with preview to get kind of a sense of what some of them are or look at the documentation. But you can specify what box to use for the PDF to display, whether to use its crop box or its media box. You can turn on and off page breaks. You saw that you can change the scale that the PDF is displayed at. For more esoteric things, you can set the text greeking threshold, turn on and off anti-aliasing, that sort of thing. So back to the demo again. Outlines.

So this document I happened to open up has an outline. Not all PDF documents have them, but you know it has an outline because the PDF Linker application checked that there was one and opened up the drawer automatically. And inside the drawer here, you see that there are four items. There's contents, three other items, and one of them, the third one here, Quartz 2D Reference, has a disclosure triangle. If I twist that down, I see that that item has four sub-items.

And then some of those have sub-items, etc. And clicking on any of these items, the PDF view is updating. The view itself that's in the drawer is just an NS outline view, so there's nothing PDF Kit specific here. But I'll show you then how that's all accomplished. And this does take a little bit more code. So back to the slides.

So the PDF outline is one of these new utility classes. And like I said, not all documents have it, but if the PDF document has an outline, you just ask the PDF document, "Give me the outline root." And if it returns an object, then your PDF has an outline. And that root object is a PDF outline object. So I'll show you then the next utility class, PDF Outline.

Here are some of the attributes. The outline item can have children, and as you saw, the root item is the one-- we actually never display the PDF outline root, but that root for that PDF that I showed you had four children. So when I ask that outline root for the number of children, it returns four. Then for--I can index over each of those and ask and get the array of-- I can get back the PDF outline children, and then each of those children, as you saw, could have children as well.

So an NS outline view just kind of allows you to kind of traverse that tree, and it'll automatically take care of the disclosure triangles for you. So that, like I say, is not part of PDFKit. What PDFKit gives you are the PDF outline objects to, you know, populate that outline view. An outline object that has a label associated with it, that's what's displayed in the outline view. So contents, for example, was the label for the first child.

And a PDF outline object has a decimal, and it has a destination associated with it. So when the user actually clicks in the outline view and picks one of these destinations, there's a method--and again, I didn't show you every method-- but there's a PDF view method called goToDestination where you pass it this destination, and the view just goes to that destination and again maintains it in its history, its navigation history.

There we go. Okay, searching. So as kind of we go on here, back to the demo machine, kind of as we go in, what's happening is the amount of code that would be required to write is increasing. We started out with one line of code here, one line of code there.

Searching is a little more complicated. So what I can do is, for example, Safari actually, they did have to write quite a bit of code to get this working, or I shouldn't say quite a bit. They had to write more than two or three lines of code to get this working.

But let's say I bring up a find panel. Now I had to provide my, my application had to provide that find panel. And the user types in a word, like Quartz, say. And I've got a checkbox here I can turn on and off, whether or not to ignore case.

When I click on the next button, the view that you provide has, tells the, tells the PDF view to find this word. And I can click next, next, next, next. And you see that the PDF view finds the next in. So I can click on the next instance, next instance, previous, previous.

So this is kind of the standard find method, I guess. This, I call it the Safari style because they implemented it with PDF kit. But there's another way to do a search. And this is more like, I guess, the preview style or, or maybe the Google style. That I type in a search term.

And now it goes out, and you see that the window, I've kind of -- it's turned into a split view. And the top half of the split view is dropped down to show an NS table view. And in this table view, you see all the instances of the word "quartz" that were found in this document.

I've got the page number over here. I've got the section that it corresponds to, and that would be the outline item over in the drawer. And then I have a little bit of, I want to call it sample text, that surrounds where that instance of the word was found in the third column of the table. So go back to the slides.

[Transcript missing]

I'm having problems with this clicker. OK, so now it gets more complicated. Back to the-- demo machine here. So this is probably, you saw that even the searching was maybe a handful of lines of code to do. This is a little more complicated. For this application, PDF linker, I wanted to show you how you could do something sort of beyond just viewing a PDF. So I've got this item up in the toolbar you may have seen called test links and edit links. Now, if I switch to edit links, you'll see that, okay, here we are. I don't know how well this shows in the back.

All these link selections, and I'll just toggle it on and off, all these link selections, when I'm in edit mode, I can draw a little gray border around these annotations. And the way I did this was by subclassing the PDF view. And I'll show you how that's done in code. Back to the slides.

So I subclassed the PDF view and there's a method on the PDF view called draw page. Now you don't usually call draw page or you shouldn't call draw page from your application, but it's called internally so that every time a new page is displayed and needs to be drawn, this method inside PDF view gets called per page. So if you subclass a PDF view, you can override this draw page method and do your own drawing.

It's, if you're lazy like I was in this app and you want the PDF view to handle most of the PDF view, you can do that. You can do that by just calling super. So I call super, PDF view draws the PDF page, any current selection, that sort of thing. But then I can now come in after it's finished and I can do post drawing.

In this case, I want to draw gray rectangles around all the link annotations. So how do I do that? Well, I should take a break and point out some of the attributes of a PDF page. I've talked about it a few times already. So a PDF page is what's passed into this draw page method.

Some of the attributes you can get at the PDF page level are you can find out the document that owns the page, you can find out the bounds of the page-- and this is going to depend on whether you want to know-- you can ask for the media box, the crop box, that sort of thing.

You can also find out if the page is rotated and what its rotation is. And you can also get back, if the page has annotations, you can get back an array of these annotations. And I'll be calling this method, of course. You can also get back the text for the page. And the page has a draw method, and that's what the PDF view is actually calling in order to display the page in its own draw page method.

So I was interested in the annotations. So when draw page gets called, I call super, let the view do the drawing, but then I want to come in afterwards and see if there are any annotations on the page. So the page was passed to my method. All I need to do is say, ask that page for its annotations. And if it has any annotations, it'll return me an array of these. So then I can, in my app, walk through each of these PDF annotation objects and see if any of them are links.

So what are some of the attributes of a PDF annotation? PDF annotation has a type associated with it. So since I'm only interested in link annotations, I can ask for the annotation type and see if it matches type link. But you can also find out for any given arbitrary PDF annotation object, the page that it's associated with. You can find out its bounds in that page's coordinate system. It has a draw method as well. So when a page is being drawn by PDF view, the page also draws its annotations associated with it.

And then the various subtypes, the subclasses of the PDF annotation have their own attributes. Like a PDF annotation link obviously is going to have a destination associated with it. So what my code does then is walks through each of those annotations that's in that array and calls type and finds out if the type is equal to string link. So I'm only interested in the link annotations.

[Transcript missing]

That's how, I guess, the point of that, I guess, when I was doing the hit testing, I needed to convert from the view space and determine if you were actually over an annotation. So I had to convert that into the pages space and then walk through the annotations, ask for their bounds, and see if the point corresponded to any of those bounds. So the next step in my demo is after I created the link annotation is I needed to make it a proper annotation by giving it a destination.

So to create a PDF destination, and this is another one of those utility classes, I needed to use some of that, use some of the transformation methods in the PDF view in order to figure out where the top left corner of the view was. So I can get the top left corner of the view in view space just by asking for its frame and creating a point that corresponds to the top left corner.

But to figure out what page that's on, I ask the view, page for point, I pass in the point, and it'll return me a PDF page. So I can get the page object that corresponds to, if you pass true for nearest, it'll return the page that most closely is nearest to that point.

So now I know what page corresponds, or I know rather what the top left corner of the view, I know what page the top left corner of the view corresponds to. But now I want it in page space, so I call convert point to page on the PDF view, I pass in that page and I pass in that point, and now I get back in that page's coordinate system and actually get back into the page.

So I can get the actual coordinate in page space. So the destination utility class has a method called initWithPageAtPoint. So I know the page, I've got the point now in page coordinates, so I can create this destination object, and then the last line just says to the PDF annotation link, and I mentioned that I have a notion kind of of what the current selected link is. I call setDestination on that, and I pass it that PDF destination.

I guess we're done. So there's a lot more documentation online. There's the sample code and there's stuff in here that I didn't cover. You can play with preview. So and then I guess from about noon on today I'll be in the lab. So thanks. I'll pass it to Rich.

Thank you, John. John's PDF Kit is incredibly exciting and You really shouldn't lose sight of that. Every day I use Preview and people give rave reviews to Preview for its speed and its power. And what PDF Kit lets you do is take all of that capability and put it in your applications.

And that's just amazing. It lets you make--and if you'll excuse me for the baseball analogy that I always use or one of them I always use--it lets you make a home run out of your application. It makes your applications into these great PDF handling applications. And below PDF Kit you can use Quartz or Cocoa to do the exact same thing.

So there's all these frameworks in the system to really help you make great applications. So of course that's not what I'm going to talk about at all. So the ideas, my ideas, you don't always need to write an application. You can handle PDF in ways that are maybe more suited to your smaller tasks. Command line tools, writing Automator plugins.

And again going back to the baseball analogy, these are the bunts and the sacrifices of PDF. So we're not going to do the PDF home runs. We're going to do little things, little things. We're going to do little base hits. So to start with, for a couple of releases now, Mac OS X has had Python bindings for Quartz. So you can write Python scripts to create PDF, which is very powerful. Starting with Tiger, you can now write Automator actions built on these scripts or written in Cocoa to analyze and also to create PDF.

Print dialog supports PDF workflow, so now you have a place once you've written these actions and these tools to host them where the user can get at them easily. And then you have PDF workflow API, so your applications, if you insist on writing these home runs, can actually execute some of these smaller pieces. So that's what we're going to look at here.

Ways you can create PDF, ways you can analyze PDF and do it simply and not really outside of an application or to be pulled into an application later. So again, the bindings have been there for a while so that you can use Python--use Quartz directly from Python. They're pretty much direct mappings.

If you want to learn Quartz, one of the great ways to do it is to start to use the Python wrappings. You can do it interactively, you can make direct calls, and the calls are pretty much the same, so that's terrific. The Python bindings also wrap up some higher level functionality, which is exciting. They let you render HTML into a Quartz context directly. That's not something Quartz does, it's one of the higher frameworks. Same with RTF.

And you can also handle a variety of image formats through these Python bindings. So there's a lot of power there through the Python scripts. So what do you want to use these scripts for? Experimenting is great. Writing tools are terrific. You can write great command line tools to do it. And then Once you've written these scripts, you can wrap them up inside of Automator and make them generally useful to people.

If you want to know where the API is for the Python bindings, it's hidden. It's in developer examples, Quartz, Python. I never remember where that is. And it's in a file called API summary, all uppercase for some reason. But that's where you can find it. You can go in there and you can see actually what the calls are in Python. And you can sit down, open up a Python interactive session, and just start typing them.

This is my sample that I always show when I talk about Quartz bindings. And I like it because it's small and it's very powerful. And it's a PostScript interpreter in Python. The idea here in this sample is two slides. This script's going to take in a PostScript file.

It's going to convert it to PDF. And from PDF, it's then going to render each page of the PDF into a raster bitmap and save that out as TIFF. So the first step-- that's what this slide is-- is being able to take that PostScript and create PDF. And all you have to do is create an image provider from the file that comes in on the command line.

Create a consumer, someplace to write it. And for this PDF, we're actually going to use this tiff file base, or tiff base name. And then you create a converter and you call convert. You've just written something that converts PostScript to PDF in a few lines of code. That's not what our goal is. Our goal is to go to the next step and actually go to raster.

And so what you end up with is the kind of loop that most of your scripts will have if you're writing using these Python bindings on top of Quartz, which is a loop that counts over the number of pages in the PDF document. And in this particular case, for each page, we create a raster context, an RGB raster context in this case. We render into it.

Once it's rendered, we then say, okay, now I want you to write out those bits as TIFF. And now you get one TIFF file for every page that was in the original postscript. It's very short, and this is the kind of powerful things you can write with these Python bindings.

But it gets more exciting than that. Because of these Python bindings, you can actually go look out there and find libraries, Python libraries, other people have written. And you can then integrate them into Mac OS X and in with Quartz. I usually go to Vaults or Parnassus. This is a great place for finding Python libraries and applications that have been written. And I browse around and I find something interesting. And I ask myself, well, how can I integrate that now in with Quartz and with Mac OS X? And there are a bunch of different things that are interesting.

One is website creation, content creation, with something like Zope or Plone, which are Python servers. And maybe you want to use Quartz to create a PDF document that you then stream down to the user, which, oh, by the way, Safari will handle in line, thanks to PDF Kit.

Or maybe you find a useful graphics library. And the example I'm going to use today is PyChart, which is a GPL charting program. It's written in Python. And what it knows how to do is take data or take some Python code and generate charts, and PyCharts and scatter charts.

And all the fancy scientific charts. And what it can do is write these into a PDF file or even a PostScript file. But that's not exactly what I wanted. I wanted it to take this library and for it to be able to render into a Quartz context, so I could mix into that same Quartz context other rendering done with Quartz. So I can generate a page that has not only a chart on it, but maybe some HTML, in the case we're going to show, or maybe some RTF.

So PyChart's great because it renders vector drawings. Well, that's what we want with Python. I didn't want to be generating GIF charts or any of that. I wanted something that was high quality vector art. So we're going to extend PyChart. We're going to extend it. They have a concept of a canvas, and they have different canvases inside of PyChart.

And one of them is a PDF canvas, one's a PostScript canvas. And the interesting thing about that is both PDF and PostScript share the same imaging model, which, oh, by the way, is shared by Quartz. So conceptually, this is going to be very trivial to move over on top of Quartz.

First thing we had to do was create this Quartz canvas. And again, PyChart's all built around writing to a file. We needed to change that. So we take the normal init that's part of the canvas inside of PyChart, and we say, OK, hey, we might actually pass you, instead of a file name, a CG context, a Quartz context. And we're going to render into that. And all this code does is remember that Quartz context. Then we go implement all the methods inside of PyChart's canvas. And again, this was all written before Quartz, and just it's something completely different.

But because of the shared imaging model, you'll see the mapping's pretty much one-to-one. Move to becomes move to point. Line to, add line to point. Strokes, it's just that imaging model. So boom, all of a sudden, you've got this powerful graphics library ported over, drawing into a Quartz context. So now can we mix Quartz and PyChart? So can we render both of them together? And the idea was I wanted this output. Can I generate a PDF file with Quartz that had a PyChart output? vector output on top, and on the bottom, an HTML table.

And the answer, of course, is yes. I signed up for the session before I knew the answer was yes, but luckily it's yes. And the main driver looks something like this. There's some standard initialization. There's a call to one method that's going to draw the bar chart. And then there's another one that's going to draw the table.

And we're just going to look at that briefly. The Python isn't particularly interesting, but the bottom yellow lines are, which is after you set up the chart and you set up PyChart, hey, these are the kind of bar graphs I want. At the end, all you have to do is say, hey, draw it into this context. brought into this court's contest.

Similarly, on the other side of it, I want to draw the table. We're going to generate the HTML for a table based on some comma-separated values that were coming into the script. And then at the end, we're going to say, hey, render this HTML. And the result is that combination I showed you. It's everything put together under one context.

So you can go look for other Python libraries and integrate them the same way. The common imaging model is going to make it very easy to bring some very interesting things onto Quartz and Mac OS X. So that's just a script. It's creating a script in Python, maybe moving over a library on top of Quartz and make it useful to you.

So it seems like we're going to step away from it, but we're not really going that far. In Tiger now we have automator actions, right? And we ship a bunch of useful PDF automator actions, but you can create your own. If you haven't used automator much, this is an example of something a user can do just using the existing automator actions.

So this particular workflow lets the user take an album out of iPhoto and then renders all the pages, right? And then generates a contact sheet and opens up the PDF. So it's very simple for a user to do this, but it would be nice if there were some more actions.

So what you can do is take a Python script you've written, for example, the one I was showing earlier, the one based on PyChart, which takes these comma-scripts and writes them into a PDF format. And then it takes a Python script, puts the comma-scripts in, and then takes the comma-scripts and writes them into a PDF format.

And then it takes a Python script, puts the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in, and then takes the comma-scripts in. So this is a very simple way to do it. So this is a very simple way to do it.

Go in, put your script into that template, change the description so it properly describes what you have, tweak the nib, in this case actually remove a lot of stuff. I'm not a UI designer, so sorry. It's not very exciting. But now, boom, you've got an action that anybody can use to take comma-separated values like you might export out of Excel and generate PDF output.

But you can be a little more ambitious if you want. These actions can also be written in Cocoa. And again, if you go use them in Cocoa, then you're going to use Quartz directly. And it's very simple if you want to write them in Cocoa. You implement this one method, run with input from action error. You'll get your input file, which generally is going to be whatever you want.

Maybe it's going to be comma separated values. Maybe it'll be something else. In the example we're going to look at, it's going to be a PDF file. And then you use Quartz to manipulate the PDF file. And now you have an action that can do specific things. In our case, it's going to mean scanning a PDF and trying to come up with some analysis of what's inside of it.

So that's what I wanted to do. It turns out Tiger has this new scanning API inside of it. And just to give you an idea how that scanning API works that we're going to use, you start with a PDF document. You create the PDF document from a file you get. Once you have the PDF document, you have that loop that we looked at that loops over each page in the document. You get the PDF page representation for each page. You get the content stream for each page.

Then what you need to do is tell the scanning API what operators, what PDF operators you're interested in. And you do that by creating this operator table. You create the operator table and you start putting things in it. In this case, we're looking for images. To find images, we need to implement, or bottleneck, if you will, the DO operator inside of PDF. So we put that into this operator table. We create a scanner.

And then we say scan. And what Quartz is then going to do is it plays back your PDF whenever it sees one of these DO operators. It's going to call back into your code. And the code I have just says, oh, OK, you found an image. What page was I on? And it keeps a tally. It keeps a tally of that inside of it. And kind of coincidentally, once it has the tally, it generates comma separated values of those tallies. So now here we have an action that will do exactly that. It generates comma separated values.

with how many images there are on each page. So can we put all these pieces together? And the answer, of course, is yes. So we're going to do... I'm going to show you a quick demo, but the idea here is we're going to take the Automator action that we have that scans the PDF file, generates the comma-separated values, and spits them out of an action.

We're going to hook into that another action which reads the comma-separated values, creates that PDF file, okay? We're going to do that in Automator. We're then going to use Automator's ability to create a print workflow item which gets saved directly into the proper place that the print dialog can find it.

We're then going to open up something in Safari. We're going to go to the print dialog, and we're going to invoke this action. Again, this is something that you can write these little actions, and then the user can put them together. So we're going to try this demo. Let's see how this works. This will be demo two. Wow. It's a good thing I explained how this really works.

Well, see, that was good because it happened before my demo. We're going to go back to the slides. That's actually good. It gives us more time for Q&A, which is what you really wanted. But so anyway, the demo, the important part of the demo was how to properly handle a kernel panic.

The important part of the demo was take these automator actions that you, the developers, can make. A user then strings them together in some useful way. The user then can easily save them where the print dialogue can pick them up. And then whatever application can drop a print dialogue, be it Safari, or TextEdit, or Pages, that workflow can then be run, the workflow the user created, can then be run to analyze or to create content based on that. So it's a very powerful way of taking these little bunts and singles that we talked about, letting the user hook them them together and then putting them right into the user's hand inside of the print dialog.

So that would have been the PDF Workflow is what I was going to show, the way that print dialog works. And then the next obvious point is, well, how can my application invoke those PDF Workflow items directly? And it turns out there's an API for it, luckily. If you want to actually invoke these workflows directly rather than from the print dialog, first you want to enumerate them. That's just called PM Workflow Copy Items. That'll give you an array of URLs where each URL represents one of these workflow items.

And then when you want to execute it, PM Workflow submit PDF with options. So you'll submit the workflow you want to execute along with the PDF and maybe a title, and it will execute. And the important thing about a workflow, PDF Workflow, is it takes PDF in and it does something with it on the outside. And you have no idea what happens to it. It might email it, it might turn it into TIFFs, it might turn it into comma-separated values. You don't know. So that's what happens with Workflow.

There's lots of different workflow items that are actually supported in the system. We support folders inside of your PDF services folder, which is where these things live, if you want to organize them hierarchically. We support folder aliases. If there's a folder alias workflow item, we just move the PDF right into there. Unix tools, Apple scripts, Automator Workflow was the big one for Tiger. You can put an application right in there, and the application will get an open event on the PDF document. And we support Quartz filters as well.

So what I really wanted was an application that would demo this. And I wasn't going to demo it apparently now. Luckily, I have the screenshot. So this is FlyMeet Software. These are the makers of VoodooPad. I'm a big fan of VoodooPad. And they have this thing called FlySketch, which is a screen capture utility. It will let you draw the window over a portion of the screen.

You can capture it, and then you can annotate the result. And what you have then is really a bitmap, but it's in a PDF form. And FlySketch had the ability to then do something with it, mail it or whatever. So I sent an email to Gus, and I said, hey, you know, it'd be kind of cool. We have these APIs that are workflows.

And if you could then use that workflow API to add anything that the print dialog can do, your application can now do with your PDF, that would be really great. I sent that mail and some other mail and answered some mail, and all of a sudden, it came back to me like this. And he had done it. I don't know what it took him, an hour, 30 minutes. It was great. So thank you, Gus, if you're out there. It was terrific. And it's a great example of how you can bring all this power right into your application.

So high level PDF, this is the takeaway. You can use Quartz directly to write Automator actions. But you can also use Python to write them even faster. And whether you write them in Cocoa or write them in Python, you can then wrap them in Automator to give to your users, to do useful little nuggets of information. The user can then wrap them into more useful workflows, and they can then invoke them from the print dialog. Or if you're a great developer like Gus, you can invoke them directly from your application.

Alright, so this is actually, I've got a couple minutes, this is actually the highlight for me of the conference. We have a new Quartz book coming out. It's coming from Morgan Kaufman. This is a terrific book. The author is somebody I've worked with for 16 years. He's a good friend of mine.

He's known for his attention to detail and this book shows it. If you need to learn Quartz, this is the book you're going to want to get. Now, Apple's publications group has done a great job of revving all the Quartz documentations for Tiger. So you can go out and see all this great reference material and it really is terrific.

But if you're the kind of guy like me who wants to sit down with a book that just says, hey look, here's how you do this and has great examples, this is going to be really terrific. So it's coming from Morgan Kaufman and if you don't believe me about the level of detail in this, there's a sample chapter that you can go get and go read that's available and I think you'll be incredibly impressed. And it actually came to my attention this week, there's another very respected, impressive Macintosh developer who's also working on a Quartz book. So I think those two books are going to mean very good things for Quartz here as we go forward.

So for more information, here's where the sample code is. Related sessions coming up. These are the Friday sessions. Moving from Quick Draw to Quartz. Definitely go to this if you have a lot of Quick Draw codes still sitting around. We want to get Quick Draw gone. Optimal 2D application graphics.

Obviously, if you're going to use Quartz, you get a lot of power and a lot of speed for free, but you can still go down the wrong path if you're not careful. This will tell you how to do that. And then the graphics and media feedback form, which is always pretty exciting. You should make sure you make that and find all the hard questions. Contact Travis Brown if you have any questions.