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-430
$eventId
ID of event: wwdc2007
$eventContentId
ID of session without event part: 430
$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 430

Manipulating PDF Content in Your Application

Graphics and Imaging • 57:54

PDF Kit makes it easy to harness the capability of the PDF document format in your application. Learn how PDF Kit's Cocoa classes objectify the structure and content of PDF documents and allow easy editing and annotation. See how you can minimize your development time by using a PDF Kit view to display and navigate even the most complex PDF documents. A great session for any developer who is interested in PDF.

Speaker: John Calhoun

Unlisted on Apple Developer site

Transcript

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

Hi. So, I'm going to tell you about how to use PDF in your application in this session, and we're going to talk about PDF kit, and I'm John Calhoun (phonetic), I'm the engineer on PDF kit, and here's kind of what we're going to do in this session.

I'm going to give you kind of a brief overview of the framework, the PDF kit framework, but then I'm going to go right into how you would use PDF kit in your application, and I'm actually going to give you four examples of how you might use PDF kit, it sounds like a lot, but I'm actually, I'm going to spend most of my time on the first two examples, and go over the last two a little quickly. Okay, well let's get started on PDF kit, the framework.

So PDF kit is a framework, and it's essentially a suite of Cocoa classes, so if you're are writing an application in Cocoa, and you include the PDF kit, the framework, then in addition to all the Cocoa classes, you get an additional 20, 30 or so odd classes, that PDF kit provides and obviously these have focus on PDF.

It's, it uses Cocoa, so it uses a lot of the same Cocoa types like NSdictionary, and NSArray, but it sits on top of quartz 2D or core graphics. So, if you're familiar at all with sort of the PDF API that's in core graphics, that's where PDF kit gets all of it's functionalities, but in a way it extends it quite a bit, and I show you examples of that in the session.

PDF kits used in preview, if you've opened a PDF in preview, you've seen PDF kit, if you've used the default plug-in in safari, and visited a site with a PDF, that's also PDF kit, and now in Leopard, quicklooks is using PDF kit, mail, if you send and PDF attachment, their using PDFview directly inside your mail message and a few other places as well.

So PDF kit the framework is part of the Umbrella courts framework, so if you go to system library frameworks, courts framework inside courts frame are a number of sub frameworks, PDF kit's one of them, the new image kit is one, courts filters, courts composer, so that's where it's located.

And if you want to use some of the new, if you want to use of the PDF classes in your interface, and you're using the old interface builder then you're going to need to add the PDF kit palette to interface builder, and the PDF kit palette is located in developers extra's palette, so you'll have to point the, your old interface builder to that, in order to get the PDF kit classes. The new interface builders, their not called palettes, their called plug-ins, and the plug-ins themselves are stored inside the frameworks resources directory, but I think, I'll show you an example of how you go about adding that to the new interface builder a little later.

So PDF kit was introduced in Tiger, and in Leopard, we've extended it, and to give you kind of, I guess a simplification of the differences between Tiger PDF kit and the Leopard kit, the focus in Tiger was to be able to display PDF content, allow the user to interact with that PDF content, to select text, to click on links, what we tried to in Leopard is kind of extend it to more of the editing capabilities, and like PDF content creation, and again, I guess maybe to simplify it even further, you can think of the Tiger PDF kit, who is pretty immutable and we tried to add mutability where we could in the Leopard PDF kit.

So here are the classes, I've highlighted in yellow the new ones for Leopard, PDFview, PDFthumbnailview, that's new for Leopard, PDFdocument, PDFpage, annotation, annotation is a class that has a number of subclasses, so I show only the two new annotation subclasses in Leopard, PDFannotationpopup and stamp, but Tiger had though, probably another 10 or 12 inklines, links, circle, square, a handful of others. PDFaction is a new class for Leopard, and it also, like PDFannotation has a number of subclasses, so there's a GoTo, PDFaction GoTo, represents the GoTo type of action, there's names, there's URL, reset form, a few others.

In PDFoutline, PDFdestination, PDFselection, PDFborder, so one way, I guess to digest all these classes and get to sort of, I guess get a handle of them, is to really separate them in to two groups, I'm going to pull the first two out, and call these the view classes, PDFview and PDFthumbnailview, and that kind of makes sense because they have the word view in them, their subclasses of NSview, so all the sort of things that Nsview inherits like, it can become first responder, it has a draw method, you can drop them into a window, resize them, those kinds of things, the PDFview and the thumbnailview, they inherits all of those attributes.

The rest of the, the PDFview is the main view, I think that you're familiar with, if you've opened up a document in Preview, of PDF, that sort of main content where the PDF is displayed, is the PDFview. And on Leopard preview, in the sidebar, when you're displaying thumbnails, that's the PDFthumnailview, so the rest of the classes, I'm just going to lump together and call the base classes, these aren't subclasses of Nsview, their subclasses of Nsobjects, so in that sense these are more primitive classes, but I kind like to think of the foundation classes upon which the PDFview and the PDFthumbnailview sit, I should point out though, just because I'm kind of characterizing them as just base classes or foundation classes, it doesn't meant that you can't use them independent of the PDFview and thumbnailview, in fact, in Leopard, there's a handful on new automator actions that we've added that deal with PDFcontent like extracting the text from PDF or counting the number of annotations in a PDF, all of these new automator actions were actually written using PDFkit, using strictly these base classes, no PDFview or thumbnailview was used, so you can take advantage of PFD kit and only use these base classes.

So of these base classes, I'm just going to focus on four, I think, I'm going to call these the core classes, PDFdocument, PDFpage, PDFannotation, and PDFoutline, PDFdocument, that's going to represent the file on disk, or maybe if you're in a browser, you've just got the file as NSdata, that PDFdocument represents that file, the PDFpage, when a document is created, when a PDFdocument object is created, it creates a PDFobject for each page that is in that document, so if you had for example, a ten page PDF, you would have a single PDFdocument that represents that ten page PDF, and there would be ten PDFobjects that that document creates, one for each page in the PDF.

Some PDFpages can have annotation on them, the example in this slide here, you see a yellow highlight at the top, that would be a highlight annotation, there's a red eclipse at the bottom, that might be a circle annotation, if a page has annotations, then each one of those annotations is going to be represented by and PDFannotation object, probably the most common annotation that you're likely to run into in a PDF is a link annotation, they don't draw, they don't make for good slides, but when the user clicks on a link and it take them to page 14, for example, that's probably the most common annotation that you run across, and PDFoutline, not all PDF's have outlines, usually it's the bigger, more richer PDF's that have an outline, but when a PDF has an outline, in preview that's what shows in the sidebar, that looks like, in fact, that's actually an Nsoutlineview there, I've heard this called the table of content, Adobe calls these bookmarks, you see this one has contents, tables, figures, and listings.

Each one of these element will be represented as a PDFoutline object, and it's kind of a tree structure, so this particular PDF may have, you know, I'll have to twist down some of those, but it may well have 20, 30, 40, @ 50 different PDF objects, each one kind of having children, and like I say, it's kind of a whole, kind of like a tree like structure, and I'll talk a little bit more about that later, and if wasn't kind of apparent, I'll just make it real explicit here, there is a kind of hierarchy here, the document is the single object, it can own pages, it'll own PDFpage object for each page, pages if they have annotations will allocate and own any number of PDFannotation objects, if there is an outline, there will be a root outline object, the document will own, then that outline object can own children and those children can own children, so I kind of represented it, yeah, as a bunch of nested boxes up there.

So there is this sort of hierarchy, so I probably should point out to that sort of extensibility or mutability that we tried to add in Leopard means that you can insert and reorder and remove these page objects, you don't have to just take them as they come off the disk, you can insert, reorder, remove the outline objects, and the annotations, as well, and I'll show you a few examples of that today. So that's enough kind overview, I guess of the framework, let's get straight to what you might want to use PDF kit for, and obviously, I think probably the most common usage of PDF kit is going to be display a PDF.

So if you, I don't know if you've took a look at the headstart code for this session, where there was an application called PDF kit viewer, and it's kind of like, I guess it's kind of like the PDF half of preview, it's kind of a poor man's PDF, half of preview, and I'm going to show you how you would go about writing an application like that, we want our application to open PDF and display them, we want the user to be able to select text, click on links, you know kind of interact with the PDF, if there is an outline, let's display that, and let's allow searching as well, so if the user wants to search for a word in the PDF, they can do that in this application.

So the way that we're going to do that is, we're going to go interface builder, and we're going to use the PDFview, and since the PDFthumbnailview is new in Leopard, we're throw that in as well, why not, and for all that other functionality, like the searching, and the outline, we'll go ahead and use PDF kit to do the rest of that.

So the first step, I'll just go over to this demo machine, I'll show you how you would actually set up the interface, so I'm going to bring up interface builder, and I'll go ahead and create a new application, presumably I should probably pause for a second here, I'm assuming you probably, you went into Xcode and you're creating a new Cocoa application, probably Nsdocoment base, I'm guessing, so we're going to create a window here and let me show you real quick, how you would go and add the PDF kit in ID plug-in.

If you go into interface builder's preferences, there's plug-in panel's here preferences, and I've already added PDF kit here, normally it wouldn't show up in this list on the left, but you'd hit the plus button, and then it's going to bring up the, it's going to bring up the Nsopen panel and you'd go to system library frameworks, and the way ID or the way interface, the new interface builder works is you would just select the umbrella framework, select courts.framework and then as soon as I select this, interface builder looks in all of the sub frameworks and looks for ID plug-ins and then adds them to interface builder, so over here if I scroll down through all the library of objects, towards the bottom here, there is a PDFview and there is the PDFthumbnail view, so I'll go ahead and drag the PDFthumbnailview into my empty window here, and there's some PDF content already for you, and I'll drag the thumbnailview in as well, and I'll just place it over here, and if I go over to the inspector, you see that there's already a number of perimeters that I can just, I can set within interface builder itself, I can turn on automatically resizing or I can turn on the change the display mode, if I want to display two up or two up with the scroll bar, I'll just leave it in single page continuously, let me just go ahead why I'm here and set the strings.

Let's go to the thumbnailview and set the strings, there's one thing here that's pretty important here to do, I want to associate this thumbnail view with the PDFview without having to write any code, so if I control click and drag from the thumbnailview to the PDFview, when I let go on the mouse, you see I've got a contextual menu, and one of the outlets is the PDFview, I'll click that, and by doing that, I've now told the thumbnail view this is your PDFview and the thumbnailview is pretty much automatically just going to respond to the PDFview, and I'll show you how that works in a second.

I select both of these views, and I'll go ahead and embed them in a, nope wrong one, I'll embed them in a split view, and set the strings on the split view, and now if I just test the interface, stimulate the interface inside interface builder, here's our window, we've got the, the thumbnailview has populated itself and from this PDFdocument that's inside this PDFview, the thumbnailview automatically went and fetched, got the number of pages, generated thumbnails for each of those pages, and you'll see to, as I'm scrolling through this PDFview, the thumbnailview is listening to that PDFview's notifications, and one of the notifications that PDFview sends out is a page changed notification, so the thumbnailview listens for paged changed and updates the current selection appropriately, I can inside the PDFview select text, if there is, let me go up to the top here, find a good link, here's a whole screen of link annotations, if I just hover over a link annotation, there's a tool tip you get for free, if I go to page nine, if I click on the tool tip or on the link and hold down, you see the highlight as soon as I let go, it goes to page nine, and again the page change notification fires off, the thumbnail view tracks and you're displaying to the user their own page nine.

There's a similar and just as a sort of, the thumbnailview responds to the PDFview, the thumbnailview can also drive the PDFview, so if I click on difference pages over here, you'll see that it's instructing PDFview to go to this page, go to the page represented, by page six, by page seven, by page eight, and I can do certain operations like you see at the beginning of this document we have the title page and then Apple legal, legalese, I click over to the thumbnailview, I can actually drag page two in front of page one, and it's reordered the document for us, so now the legalese's are at the front, and there's the title page, Undo is built in, I can hit command Z, and it's got the page back in order, I'll show you something else that's kind of fun, I've got, you can drag in PDF's and other file types, I've got some images here, so if I just drag a photo in between here, page three and four, the thumbnailview created a new PDFpage from that image and inserted it into the document, and now if I saved out this PDF or printed it, this new page would show up right between pages three and four, and again, Undo.

So, I think that's all I really wanted to show you in this, so I'll go back to the slides then, so that was step one, create your nib, and I showed you how to add a PDFview, well first how to add the ID plug-in, so that interface builder has the PDFview and the thumbnailview, how to add the PDFview, the thumbnailview, connect that outlet, so that the thumbnailview knows about the PDFview, that it's going to respond to, and since I'm talking a lot about PDFview, and I'm not really going to show you the headers or all the methods, I thought I'd at least kind of talk on them, just for a second, an in fact, you can actually go to PDF kit, go to the PDF header, and I think frankly, it's pretty self explanatory, you can look at the methods and guess what most of them do, just in sort of broad, sweeping terms, there are methods for dealing with navigation, if you want to say go next page, go previously page, go to page N, there's methods to deal with display attributes on the view, do you want to see single pages, two pages, hide/show pages, page breaks, turn on and off, (inaudible) set the background color, that kind of thing, you can zoom in, zoom out, turn on auto sizing, I showed you that in interface builder, go to a specific scale factor like, go to two x, three x, you can get the current text selection, the user selects text, and there's a notification for that, you can set the current text selection, you can print the document, you can save the document, there's some conversion routine in PDFview that I'll talk about a little later, that allow you to basically map from the PDFview to the page and back and I'll explain those in a little bit later in this session, I told you that were a whole suite of notifications and much more, so just go and look at the header, and I think you can, like I said, it's pretty self explanatory.

Let's go back to our application, I was sort of cheating in interface builder, actually PDF kit cheats, when a PDFview is created and it recognizes that it's inside interface builder, it kinds of pony up that phony PDFdocument, but your application, you're going to have to actually provide that PDF content yourself, and the way that you do that, is to tell the PDFview to associate a PDFdocument with the PDFview, so you'll going to have to create a PDFdocument object, this was that, kind of probably the most core of core base classes, create that PDFdocument, and tell the PDFview display this PDFdocument, and here's all the code that you need, the first line in yellow, document equals, PDFdocument, Alex, that's going to allocate storage for the PDFdocument object, and the PDFdocument has a method called (inaudible) with URL, and I'm going to assume that you've got some code that brings up the NSopenpanel, and you've allowed the user to select a PDF, so you get the URL from the open panel, and now you just saw PDFdocument, end it with URL, and you pass on that URL, and if that URL represents a valid PDF file, then you're going to get back a PDFobject document, that's what the document value return here is, then I'm going to assume also that you have an outlet in your application to that PDFview that we added in interface builder, an outlet called my PDFview, so my PDFview, there's a method called set document, you pass at the PDFdocument, and that's all you need to do, as soon as you do that, all the machinery kind of kicks in, it gets the number of pages, it sizes it views, it sends out a notifications, the thumbnail view, finds out the number of pages, start loading thumbnails, it all just kinds of happens at that point, and one of the other thing that the PDFview does, is it retains the document, so that last line of code, I can just go ahead and release the document, forget about it, later if I want to get back that PDFdocment for whatever reason, there's an accessor (phonetic) on PDFview that'll return that document.

So since we're talking about PDFdocument, I thought I'd feel you in a little bit more about what this class has, is capable of, since it does represent the file, since it is kind of the lowest level of this sort, this sort of hierarchy, it's at this level, the PDFdocument level, that you would ask, for example, the number of pages, so there's method page count, that tell you how many pages there are in a document, also the PDFdocument allocate and creates the PDFpage objects, so it's from the PDFdocument, you would say, give me the page at index zero, for example if you wanted the first page, and the PDFdocument would return you a PDF page that represents the first page in the document. There's API in PDFdocument for adding pages, removing, reordering, probably want surprise you that that's what the PDFthumbnailview is calling, it's calling these API's on the PDFdocument when the user is dragging the pages around and inserting the images.

Certain meta data, like subjects, authors, keywords, you get from the PDFdocument class as well, searching we're going to wire up our searching, using the PDFdocument class, I also mentioned that the root outline, you can get from the PDFdocment, so for our outline, we're going to ask the document for that, and then finally, there's a lot, several API for dealing with saving the PDF's, so for example, if the user has reordered the pages, and inserting pages, cropped pages, added annotation or done anything like that, you can call these methods on PDFdocments, write the PDF out to disk and it will write out, flatten out a new PDF file that represents all these changes, all these edits that you've done.

And there's a lot more, there's a lot more too, there's all kinds of notifications that the PDF has, there's delicate methods, etcetera, again, I think if you look at the headers, you can figure most of this out, or sample code, there's going to be lots of sample codes from this session, and if you go to the wwc site for this session, you can find all those.

So, I'm not going to go a lot into how you sort of setup the PDFoutline, the headstart application shows you in detain how to do this, but I will give you just a brief overview, in order to get the outline root, that's the sort of the first step in presenting the outline of the PDF, there's a method on PDFdocument called outline root, and you'll see this line of code in yellow, my outline, that's this PDFoutline object, I'm going to get back hopefully, my PDFview document, so there's that outlet to the PDFview, document simply returns that PDFdocument that I had passed in originally, so essentially I'm asking the PDFdocument, give me the outline root, now if that PDF has an outline, then outline root method will return a PDFoutline object, if it return null, then there's no PDFoutline, there's no outline in that file, so you'll have to figure out how to handle that in your UI.

What you do with this outline root though, is in the sample application and in fact, in preview itself, is populate and NSoutlineview, we didn't need to add an outline view like we did for the thumbnail view because there's already a perfectly good NSoutline view and if you've ever used an NSoutlineview, it uses delicately methods, so you make some object in your application a delicate in a NSoutline view and then it's going to ask things like how many children to display, give me the children, child at index, you know, I, an there are methods on PDFoutline that perfectly mirrors these kinds of delicate calls that the NSoutlineview is going to call for, and if you look at the sample code, you'll see how that's implemented, I think, honestly I think it's probably six lines of codes or something like that, and here are the attributes for PDFoutline, number of children, you want to know for a given outline item, how many children it has, and for the outline root that you get from a PDFdocument, it's got to have children, if it doesn't have children, it's not very interesting because the root is never displayed, it's the first sort of children of that that root, it's the first level that you see in the actually outline view, so if you take an example of, imagine a PDF that has an outline, that has like ten chapters in it, chapter one, chapter two, chapter three, you would expect then, when you get that outline, you'd expect to get back an outline root, first of all from the document, and you would expect that if you asked that outline root for a number of children, you should get back ten, and then there's also a method on PDFoutline, that say, okay give me the child at index zero, if you wanted that first item, and you should get back a new PDFoutline item, and this new item will respond to the third and fourth method up here, label and action, label is what gets displayed, so I would expect for the first child, the label chapter one, that'll be a string that I'll get back from that, and then action is, what happens when the user clicks on that. So if chapter one begins on page seven, for example, you would expect the action that you get back from that first child to be a Goto action, that says to go to page seven or something like that.

If that's all there is, if there's only just the ten chapters, then you would expect, if you asked that child in chapter one for it's number of children, you should get back zero, but it is a tree like structure, you could have subchapters or subsections, so chapter one could have several subsections, so it would give each of those children, etcetera.

So the last stop is searching, there's a couple of different ways in PDF kit to search, there's a couple of different methods in PDFdocument that you call to search, if you want to say, you know, find me the next instance of this word, like find me the next instance of the word, Bob or find the previously instance of the word, Bob, there's methods for that, I'm showing up here, I guess, it's kind of like the google method, it's more like just find me all the instances of the word, find me all the instances of the word, Bob, and the method looks like this, my PDFdocument, again that's going to return a PDFdocument object, begin fine string, so you'll pass in a search string, maybe it's the word, Bob or whatever the user typed in, with options, and I've got up here, NS case insensitive search, and this is just a constant defined by app kit, and there's a number of other ones, like literally search, search backward, and you can use any of these flags in PDF kit to do your search, but you might noticed that it doesn't return anything because actually this call happens (inaudible), when you say begin fine search, or sorry, begin fine string, the PDFdocument just goes off (inaudible) and starts doing this fine.

So this method actually returns immediately, so you may be wondering how do you get notified then, how do you find out that the word, Bob was found, well there's two different ways, one is with notifications, at the bottom, I've got the list of, PDFdocment did find match notification, so if you listen for those, every time it finds the word Bob, you'll get a notification, I actually kind of prefer the other method, just above that, did match string, if you make some class in you application a delicate of PDFdocument, then every time it finds the word, Bob, it's going to look to see if it's delicate, your class implements a method called, did match string, so if you implement this, then every time it finds the word, Bob, your get match string will get called, and this PDFselection object that's passed is going to represent where in that document that instance of the word was found, and there's a lot of things that you can do with that PDFselection, I'll show you in the demo here.

Yeah let me go ahead and switch to the demo machine, and I'll just show you, PDF kit viewer, so if you did download and run this, headstart application, you'll run this, this is our little PDFviewer, and I did write this for Tiger, timeframe, so I didn't have a chance to modernize it or might have added a thumbnail view, I might have got rid of the draw too, preview's got rid of the draw, over on the left, obviously the large content is the PDFview, you see on the right, the sidebar at the top, is, this document happens to have an outline, so there's our outline, and it's very easy to listen for a change page notification, and update that NSoutline view, so that you can basically track the current page, where it is in the outline tree, and also as I click on various items in this outline tree, you can see that it goes to that specific part of the PDF document over here, and if I do a search here, I'll search for the word color (inaudible), this is just a standard NStableview, PDFdocument, and did the search, if I, it's probably going to be too quick, now, let me try searching for something else, like PDF, yeah you see, I can kind of still interact with the document, well it's done now, no it's still going, while it's searching, an actually that's kind of interesting because one I start resizing and starting basically taking over the run loop, the PDFdocument kind of stalled it search and waited until the run loop was free again, and just with the PDF selection object that's passed into my did match string method, I'm able to get things like the page that the instance was found on, page nine, I'm able to get the section that that corresponds to inside the outline, I've able to get all kinds of information, I've even able to tell the PDFview to go and select that text and scroll to that. So if you look at the code for this, and again you can download it, it's associated with this session, you can see how all this is implemented, and it's not a lot of code, so I'll go back to the slides.

Okay, so this is the next kind of, how to, so that was kind of a simple app, where we just kind of reusing PDF kit, kind of the way you would expect it to be used, the way it was intended it to be used. But now let's say we want to kind of extend it a bit, and what we're going to try to do, is generate our all content on top of the PDFcontent, we want to do like an overlay, and we want to display something on top of the PDFcontent and allow the user to be able to interact with that.

So the way, that we're going to do that actually, is simply to subclass PDFview, and I'll show you on the demo machine here, this application that I wrote, it's called PDFviewsubclasser, and this actually is a PDFview, the big region on the top, and I'm loading a PDF from my resources, and I've got a PDF that is just a map of Europe, a just a gray scale map of Europe, but that push pin that's in the middle, with that like Indigo circle, that's the part that I'm actually overlaying onto the PDFcontent, and I can go in, and I can zoom in for example and place that push pin right on Warsaw, Poland, and you'll see that even as I zoom out, or as I scroll that I'm able to pretty, I'm able to very accurately track that PDFcontent and put that push pin right where I want it too, inside the PDFview, so I'll show you now how you do that.

So the first step, sorry I didn't even see that, thank you, the first thing we need to do is, so we're going to subclass PDFview, and we need to handle user input, so that we can track the user grabbing and dragging the push pin around, and obviously we also need to handle displaying that push pin on top of the PDFcontent, so the way we're going to handle the first part, the user end put is, I told you that PDFview is a subclass of Nsview, so it inherits NSresponder's mouse down method, so we're going to override mouse down, and be able to get that mouse down, so that we can detect if that user has clicked on our push pin, but I should point out that PDFview also implements mouse down, all that sort of text selection and clicking on links and that sort of things, that's handled inside PDFview's mouse down, so if I subclass PDFView and I override mouse down, if I don't call Super, then all that functionality isn't going to happen, now maybe for this application, I don't really care, I don't care if the user can select text, and there's no links in this particular map of Europe, so I don't need to call Super mouse down, but I do want to point it out, you know, that if you want your application, if you want to still be able to select text, you're going to have to call Super.

Now the only trick though, with PDFview is that it comes, it becomes very handy actually to be able to sort of map from the mouse down in the view to some specific point on the page, on a specific PDFpage and that's where all these methods in PDFview from mapping the view to the page and from the page back to the view come in, and I guess, I call these, I call the coordinates, that are in the view's coordinates system, the view space and the coordinates that are in the pages coordinates, page space, so here's kind of a one slide explanation of those, I've got in the blue box here, that's suppose to represent the PDFview, itself, and you know with standard app kit, that probably the lower left corner of this PDF kit is zero, zero, but that's not necessary going to correspond to anything particular in the PDFdocument, the user can zoom in, the user can zoom out, they can, in this case, there's actually three pages shown here, there's a little silver of a page at the top, and a little silver on the bottom, and in the main page in the center, so what we want to find is if the user clicks on some arbitrary page in the view, what page does that corresponds to, and then in page space, in that pages coordinates, where does that point corresponds to, and the reason why this is important is, all of PDF kit, with the exception of these methods, I'm going to show you here, all the rest off PDF kit deal strictly in page coordinates, in page space, so the pages bounds, it's going to return you the bounds in points, that's the way Adobe defines the PDF back, it's always points, seventy two points per inch, if there's annotations on the page, and you asks for the annotations bounds, it's going to return you the bounds again in page coordinates, that means that regardless of whether the user zooms in, zooms out of the, that the page coordinates are always going to be the same, it's the view coordinates, or you know mapping from the view to the page coordinates that will change. So, I guess the example that I'm giving here is that yellow cross is like the origin of the page, that might mean, let's say zero, zero on the page, but that's obviously not going to be zero, zero on the view.

So here's the method that we're used, here's our subclass of mouse down, that first line in yellow, view point equals self, convert point, event, location and window, from (inaudible), this is standard NSview subclass stuff, this is standard code that takes the NSevent that's been passed in, and maps it to the windows coordinates and from the window coordinates to your views coordinates. So this is just standard NSview subclasses that you would do that first line.

It's next two lines that are sort of the PDFview specific stuff, the first one, page near equals self, page per point, viewpoint nearest, yes page per point is the method that PDFview implements, that's says, I'm going to give you a point in view coordinates, and you give me back the page that the user clicked on, the PDF page object and if I passed in nearest, yes then, if the user didn't exactly hit a page, it will at least return something, the nearest page that the user clicked on.

So I get back PDF page object, and then now that I got a PDF page, I can call the next method in PDFview and say, okay, convert this point from view coordinates to this pages page coordinate, so self convert, view point, and it's still in view coordinates, to page, and then that page that we found that the user was nearest, and what's that's going to return is page point and I delivered name it that way, so that you know that this point is in the pages coordinated system, so at that point, you can do all your hit testing, I'm going to assume that that push pin for example, that were ever it's located on Warsaw, that you've got that position in page coordinates, and so then you can just do a real simple, you know, point in (inaudible) or something like that to determine if the user has clicked on that point and I didn't show you the all the dragging codes in here, you can look at the sample codes to see how that's implemented, but it's standard app kit stuff, and wasn't related to PDF, so I didn't show it here.

Okay, so the second part, we've been able to take the user's input, mapped it to the PDF page and pages space and able to determine if the user has clicked on the push pin and we handled the drag, now we want to be able to display the push pin, well you might think that since PDFview is a subclass of Nsview, that you would override Nsview's draw rect method, but you would be wrong, actually you could do that, but you wouldn't want to, because PDF kit or PDFview has a much more interesting method called a page, and I'll explain why this is interesting in a minute here.

First of all, draw a page, gets called for every visible page, so in that example I had where I showed you the view space to page space, there was those three pages visible, when that NS, sorry when that PDFview gets called to draw, it's going to call draw a page, three times, and each time it calls this method, it pass in the page that needs drawing.

And so that's the first interesting thing, if you know that your push pin is only on a specific page, you don't need to draw your push pin on every page, only the page when the page comes in that your push pin corresponds too, you can draw your push pin.

The other thing that's kind of interesting is that when, I guess I'm a little bit out of order here, but when draw page gets called, the graphical context has already been setup to be in the pages, in page space, in the pages coordinate system, so if the user has zoomed in or, you know, if they've scroll up a bit, and there's a bit of a translation, then the scale and the translate will already be set up into the graphical context, so that when draw a pages is called, you can just draw at, you know, let's say that Warsaw is, you know, at a hundred comma hundred, I don't know what that point represents in that document, but let's say that it did, then you can just go to position one hundred, comma one hundred, and draw your push pin, and it'll be at the right place and as you scale, as you scroll around, it'll just track because the graphical context has already been set up to be in page coordinates, and if you do everything in page space, then it just kind of work, I skipped over the super method there, I should point out that PDFviews implementation of draw page actually draws the page, draws the pages content, so this is a case where I don't thing you should skip the super, if I didn't call super, you wouldn't see the map of Europe, so the first thing I've got to do is call Super, so that the PDFview can draw it's content and then when that returns, I draw my push pin, and that's the way it all kind of gets composited together.

So I'm just going to mentioned this as a side, sometimes having the content setup to be in page space isn't always what you want, if you want if for example, to do a one pixel boarder around an annotation to show it's selected for example, you would kind of hate as the user zoomed in or out that that one picture pixel border would get fat or thinner.

So there is a method and in the sample of PDFsubclassview, you can see where, I actually used both of these, I actually used both the draw a page and this new method, this other method to draw a page post, draw page post is just like draw a page, expect the context has not been set up in page space, it's been popped off, and as you might guess, it be called after draw a page, so in that view subclasser example, you may have noticed that the blue circle got bigger and smaller as I zoomed in and out, that was hooked up via draw page, the push pin never changed scale, I actually draw the push pin in draw page post, but there's a little extra work to do because you're going to have to map from the push pin coordinates to page coordinates because it hasn't been set up for you in the context, again look at this sample code, it's to confusing to even talk about, here's what all our methods look like, draw a page, we're going to call Super, again first line, call Super, let the PDFview draw the page for that, the content for that PDF, and then, you know, I've got this line if page equal page marker page, presumably we have some page marker pages that represent which page the push pin is on, then we do our drawing, okay, so by the way, well this next part here, has to do with how you would create your own PDF content, the last two parts I've really focused on the high level classes, PDFview in particular, but I wanted to spend a little time in this session talking about how you kind of can manipulate the lower level classes, the base classes, and last year, I did, if you saw my session last year, I did a little calendar application, again you can download that if you want, and it shows you how to basically programmatically generate calendar content and create a 12 page, 12 months in a year, PDF, but it wasn't a very practical example, I don't think anybody that wanted to write a calendar application would think let's use PDF kit and I kept having people come up to me and asking me can you use PDF kit to add watermarks to a page, so I thought this year, I'd show you how you can add watermarks to a PDF page.

What we want to be able to do is render on top of the PDF content, some kind of a watermark and, but here's the kind of the cavy, you might thing, well I could just subclass PDFview, like I did with the push pin and then I can implement draw a page and every time draw a page gets called, I can draw, I can call Super, and then draw my watermark, and that would work, the problem is, and this is kind of the fundamental differences between the two approaches we're going to take, the different approach we're going to take here is when we call, when we added that push pin, we wasn't adding it to the content of the PDF, we we're really just kind of overlaying it, inside PDFview, if I was to save that PDF out or print it for example, the push pin wouldn't be there, I want this watermark to actually be a part of the PDF itself, so I want to go down to PDFpage and subclass that, so that's how we're going to do this, we're going to subclass PDFpage, override it's draw method and draw the watermark at that level, the only difference now, I should say the only draw back that this has versus the last method is, PDFpage doesn't have a mouse down method, it's not a view class, it's like an NSobject subclass, so that kind of interactivity where the user wants to be able to move the push pin around, we want be able to do by subclassing PDFpage, but as you'll see there's some more interesting things that we can do. So let me go ahead and show you the application that I wrote; I'll switch over to the demo machine, and it's called, switch over to the demo machine, and it's called PDFwatermarker.

And this application, by the way, the, this is a PDFview here, but it gray because I don't have any, I haven't associated the PDF document with it, so I click this button, select PDF and I bring up and NSopenpanel, and we'll go ahead and let the user select a PDF, and I'll pick a small one because they save more quickly, and here's our watermark, the big red text confidential, and you'll see that it's displayed across every page and if I type in another watermark, "Do not print", now it's added the do not print to every page of the document, and if I save this, and this is really where, like the fundamental difference is, if I save this, this document that got saved, and I'll go ahead and throw it on the Adobe reader, so that you know that I have no tricks up my sleeve here, it's a real PDFdocument, and there's the text, and the reason why this is possible and the reason why it's possible by subclassing PDFpage is because PDFpage's draw method gets called, not only for displaying like this in the PDFview where a graphical context, a (inaudible) map is set up, and the page is told draw and by subclassing you can draw, you know your watermark, and it'll just show up in the PDFview, but you know when I click on save to save the PDF, the PDFpages draw method is called again but this time it's being recorded into a PDF context and written into file, or if I go to print this PDF, again the pages draw method gets called and this time into a print context and sent out to the printer. So that's the kind of the powerful part of subclassing PDFpage, so switch back to the slides and show you how you do that.

I switched back to the slides and I'm talking to fast. So the irony is, in order to subclass PDFpage, we have to actually subclass first PDFdocument, and the reason for that is, if you think about how I explained it, you know, if you point a PDFdocument to a file on disk, you've got a URL and you create a PDF document, the PDFdocument is going to go and create, let's say it's a 10 page PDF, the PDF document is going to go and then create and then allocate 10 PDF page objects and that's the problem, we don't won't the PDFdocument to create 10 PDFpage objects, we're going to subclass it, we're going to have a PDFpage watermark class, so we want to tell PDF document to create 10 PDFpage watermark classes, so there is a method in Tiger for a new method on PDFdocument called page class, and default implementation for this is simple to return PDFpage class.

So by subclassing PDFdocument and let's say we call it a PDFdocument watermark, that's going to be our subclass in PDFdocument, we're just going to implement this one class, this one method, page class and we're going to return PDFpage watermark class, now go and do an out PDFpage, sorry, we do a PDFdocument watermark Alex (phonetic), end it with URL, now this PDFdocument watermark is going to create 10 PDFpage watermark classes or objects, and this is what, oh I've got this page out of order, I guess, let me just, as and aside talk about PDFpage since we're subclassing PDFpage, so as I said, the document creates the pages, there's one thing you can do with the PDFpage is, you can, there's a week reference back up to the document that owns it, so you can get back to that document from the page, so there's a document method, I told you that PDFpage, you can ask for it's bounds and it's going to return the bounds, and page coordinates, of course, there's a rotation associated with the PDFpage, 09018270, their always in 90 degree increments, the PDFpage creates and own its annotations, so if there annotations on the page, you can ask for the annotations and it brings you back an array of those, the text, within a PDFdocument is actually broken across, and stored in each page, so you can ask the page for the text, and it'll give you the text that's on that page, it would actually be kind of painful for you, if you wanted to do a search to have to go to each page, get it's text, do the search, look for the word, go to the next page, get it's text, do the search, that's actually why we put that method in the document because we do that for you.

But, more importantly the PDFpage implements a draw method to draw the PDFcontent and that's what we're going to subclass, so here's what our draw method would look like, PDFpage draw method is called draw with box, so we implement our PDFpage watermark class, one method, draw with box, we're going to call Super, it's just like PDFview, if we don't call Super, the content doesn't get displayed, so we call Super, draw with box, pass the box to it, and then when that return, anything we draw, in this case, I've got something called watermark strings, some kind of a sting and I'm just calling a standard Nsstring call draw and rect, presumably I've got a destination rectangular, with attributes, you know, font size, font color, that gets composited, right after the PDF gets drawn, and like I said that gets composited when printing to the printer, that gets composited when saving to the PDFfile, and obviously when displayed in the PDFview, so that's it.

The last section here, I'm going to go over kind of quickly, it has to do with PDFannotations, so here's a list, oh actually something got cropped off, this is a list of all the annotations that PDF supports, the ones in yellow are the new ones are that we added for Leopard, you can see there's button widgets, circles, text, inkline, bunch of different types and if you actually go to Adobe's web page and download their PDF specs, they'll tell you everything you'd want to know about all these annotations.

One thing that the classes themselves have and the methods on these classes have in common though, are there's a type attribute, so you can ask the annotation for it's type and if it's a circle it'll return circle, etcetera, there's a page, again, a week's reference back up to the page since the page creates the annotation, you can ask the annotation for the page that it's on and from page you can go up to the document if you wanted, if for some reason if the annotation needed to know the document that it was a part of, a bounds method on the annotation, so again in page coordinates, it'll tell you what it's bound are on that page that it's apart of, and also it as well has a draw method, so the circle annotation knows how to draw a circle etcetera.

A PDFannotation could have an action, the link annotation most obviously example you would expect a link annotation to have an action like Goto page 14 or something like that, then the various subclasses of PDFannotation have a type specific attribute, so the circle will have color and the thickness of the line and whether the lines dashed or not or an arrow, sorry a line, annotation would have whether it has an arrowhead on the end, etcetera, and you can again look in the headers and you can, it's all pretty self explanatory.

So I'll you this annotation editor over on the demo machine that you can download and this is probably the most, I guess richest application that I'm going to show you today, so the sample code for this, I think is a real kind of treasure cove of things that you can do.

We're going to open a small PDF here, again it's easier, quicker to save, here's the standard PDFview and I've got a thumbnailview over here, as well, one thing this application does is add this annotation menu, and you see, I can go new circle and when I select that, what I'm doing is, I'm calling Alex (phonetic) and it will rect a new PDFannotation circle object, then I'm getting the current page from the PDFview and saying add this annotation, and just by doing that, when the PDFview redraw, it's going to redraw with this circle annotation here, I can move this around, it probably want surprise you that the red box around this circle annotation is being done by subclassing PDFview, I'm getting the, I've overriding the mouse down, so that if the mouse is inside the selected annotation, I can drag it around, I can resize it, and then this is kind of fun, over here on the side is a palette, and I've written that, depending on the type of annotation that's selected, gives you various attributes, access to some of these, so for example, I can set the thickness on the border to, let's say 12 points, I can set it to be dashed or not, I can bring up the color pixel here, and drag a color swatch to the border color, now I've called set color on that annotation and it just displays correctly here, go ahead and add another here, I'll add a link annotation, link annotation aren't very pretty, they don't draw anything, but let's go ahead, over hear on the annotation palette, go ahead and give it an action, let me give it a URL action, so I've created a link annotation, I've added it to the page, now I'm going to create PDFaction GoTo, or PDFaction URL, and by default, I've the URL to be apple.com, we'll just leave that, and then I call set mouse, up action on that annotation and pass at that action.

I'll show you one other interested annotation, the stamp annotation and what's interesting about this annotation is stamp annotation don't actually have a draw method, I mean they have a draw method, but they don't actually draw anything, you have to actually subclass the stamp annotation, and override that draw method and implement that, so what I've done here, is I get my bounds and draw, is I stretch out, I've got this little apple text that I draw and stretch it to fix, so I've go a link here, I've got a circle annotation here and a stamp annotation here, and if I go ahead and save this, I'll go ahead and open this up in Adobe reader again, just prove I'm on the up and up here, and here's that circle annotation, here's the stamp annotation, by overriding it's draw method, when that PDF gets written out to disk, the annotation draw method is called, it's recorded into an appearance string, and saved out into a PDFannotation, and up here, I see, yes there is a link annotation here, and if I click on it, it launches the browser and works. So those are some of the things that you can do, have to quick this to quit, these are some of the things that you can do with PDF kit, switch back to the slides, that's all I have for today.

So I've said this many times already, go to the session on wwc session, there's tons of demo apps, I do a couple every year, so we're up to quite a few new, there's documentation there as well, there's a couple of apps that we've written, go to Adobe's website and get the PDF spec, you can find out a lot of information about annotations for example.