Graphics • 57:24
The Mac OS X printing system is the integration point for many key technologies: Quartz, ColorSync, Rendezvous, and more. This session covers how these technologies combine to make a powerful and flexible printing architecture. Areas to be discussed include printing best practices, CUPS printer driver development, Cocoa PDEs, and PDF workflow. View this session to get the most out of the Mac OS X printing system.
Speakers: Paul Danbold, Alan Beck, 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.
- Okay, good morning. Welcome to the 2004 edition of the printing session. My name is Paul Zambold, technology manager, evangelist for printing. As always, we've got a lot of good stuff, so let's get started. We're gonna begin by looking at how far we've come and where we're going in Tiger with the printing system. See how we're doing in making things easy for you, making things easy for the customer.
We'll start with kind of the report card on where we stand with compatibility, mainly with printers, how many you can connect to the Mac, ease of use, functionality, and not just functionality for the user, all the bells and whistles in the print dialog, but the APIs that you use to interact with the printing system.
Compatibility. I want to start with a little bit of audience participation. Who's used one of these printers? Okay, so I know how many people are at least 30 years old or older. If you don't know, that's an image writer printer. That's actually an image writer 2. Image writer shipped first just over 20 years ago. And this is the image writer that I've got in my office. I don't know how old it is, but it works.
I went to Linux.org, downloaded the Fumatic driver, and I can print to it from 10. So, pretty good. And anybody here who played a part in writing that driver, thank you very much. I don't use it a lot. It's not very fast. It's 144 DPI in best mode, so it's not great, but it works.
Panther shipped with a little over 120 PPDEs for PostScript printers from the well-known vendors, close on 300 old-style so-called Tioga drivers from HP, Epson, Canon, Lexmark, and we got the GIMP print package in Panther that supports over 250 printers. So we're doing pretty well. We're planning on building on that list for Tiger, so you can expect that out of box, Tiger will ship with even more drivers, and we're working closely with the printer vendors to make sure that happens. So we think we're doing pretty well there on making sure that any user of Mac OS X can print to pretty much any printer, Direct Connect, network, et cetera.
On the ease of use topic, making things easy for the everyday user, professional user, I thought we'd look at four things that most people do from one time or another. Discovering printers, setting up cues, sharing those printers, and interacting with the printers through the print dialog and getting access to all the printer's features.
If you remember that old image rightly, remember that users used to have to think about the driver before they went to print. They'd have to pick the driver and then the printer. And then in Mac OS X, when we came out with Print Center, we decided that it was better for the user to think about the way the printer was connected to the Mac. So they picked the connection type, USB, rendezvous, et cetera, and then picked the printer.
And we had these browsers that were loaded by Print Center, Printer Setup Utility, that would provide support for those various connection types. Well, the only problem with that is it took a little while to find those browsers, load them, call them, and get the list of printers. And just a little movie I caught on my PowerBook back in my office, you can see that it would take about, on a good day, maybe about 10 or more seconds to load all those browsers. So we weren't too thrilled with it. that.
Now, coming up next is what we've done on Tiger. And we don't have a network of printers in Moscone, so I'm going to show you another movie that I caught back again in my office. As you can see, if you watch this, what we've done in Tiger is we've combined -- we've created a combo browser for all the standard connection types. And as you can see here, you can sort by name, you can sort by connection type, you can filter, as you see there.
And you So, it's a lot faster. Basically, there's no latency between clicking the add button and seeing a list of printers. Having done that, you can go and set up cues very easily. There's a separate, there's an icon, so you can go and set up your IP printer, because of course you can't browse for those so easily. And there's still access to the third party custom browsers. So, we've tried to cover all the bases, and overall we think that the user experience is going to be a lot better for the folks who have to go out on the network for testing.
For example, to set up a printer cue. That said, of course you know that even as far back as Puma 10.1, we had auto cue curation for some connection types. So, we're still expecting the user not to even have to worry about printer setup utility for things like USB and Rendezvous.
Next thing that people do a lot is they share their printers, or they share their printer queues, and we introduced that when we integrated CUPS into the printing system back in 10.2. The UI for it though gave you just one choice, share all your printers or none of them, and that was okay if you just had one printer queue for say a Direct Connect USB printer.
It wasn't so good if you had a lot of printer queues set up on your Mac, especially for network printers. So in Tiger, you'll see this when you install Tiger, we now have via the print and fax system preference the ability to list the printers you've got, the Direct Connect printers you've got, and selectively share them.
However, if you spot the little bit of red text on that, you'll see that we haven't quite hooked the UI up to the underlying functionality, so a future Tiger SEED will have that working. So I think users will appreciate that, the ability just to share. You know, the printer that you are happy to share, and that expensive printer that you like to use all the time with the expensive inks and papers, you can keep that to yourself.
Another thing that people do, especially in the world where people work with network laser printers, typically PostScript printers, when they discover the printer on the network, they have to configure it. They basically have to tell the host computer about the printer's capabilities. Now, it doesn't usually apply if you've got an AppleTalk printer because we can query the printer and get back its configuration. But for an IP printer, you have to do it manually. And this little movie again shows the steps involved in that.
Typing in the address of the printer, setting up the queue, and then having done that, you have to go to the installable options panel and tell the host computer that you've got that extra paper tray installed or you've got the duplexer installed, et cetera. So we're expecting a little more of the user than should be required. Just let that movie complete.
So this is what we're planning to do in Tigra. You won't see this when you install the seed that you have. But we are planning-- and we've already got some code in place-- to support SNMP as part of the printing system. And with SNMP queries embedded in a PPD file, we should be able to-- for an IP printer, we should be able to find out how it's configured and do that automatic setup that we do already for Apple Talk printers.
So again, that'll make life a little easier for the user. We'll also be using SNMP to monitor printer status during the execution of a print job. So for your LPR printers, you'll be able to see more about what's going on by querying the MIB during the print job.
Okay, one more thing in terms of ease of use is the functionality we provide all the bells and whistles in the print dialog. And what we did in Panther, as you probably all know, we added a bunch more panels, a lot of new features, things like printing cover pages, being able to schedule when you print, doing reverse order printing and printing odd, even sheets, et cetera.
That was all well and good, but it resulted in a lot of panels in the print dialog. So we've decided to do a little bit of cleanup and add -- and still add some functionality to the print dialog. And to show you that, we have our fearless demo guy here, Alan Beck, who's just going to come up and live show you the Tiger print dialog.
We could have demo one on the screen. So I'm just going to go ahead and bring up one of my favorite test documents, King Tut. Just bring up the print dialog. And here you'll see that we have somewhat rearranged these buttons on here. We've added a PDF button, a pop down command.
The Mac OS X printing system is a simple, easy-to-use, and easy-to-use software that combines the Save As PDF and the Save As PostScript. We have gotten rid of the output options PDE. Revamped the summary PDE to make it more useful so you can see the information that you want and hide the information you really don't care about. Like, I really don't care about copies pages, but I always really want to know what my layout is.
So one nice thing about this is it will remember what What PDE summaries you have opened on a per user basis. So next time I bring up the print dialog and show the summary, it will still come up in this configuration. So if we just go back to, let's go back to layout. Let's change it to end up with a double thin line border. And let's go to the summary pane. It shows that, okay, I'm now... The other thing that we have done is we have added Look at the paper handling PDE. We've added selecting the destination paper size.
Basically, it allows us to scale to fit to a certain paper size that you know that is currently in the printer. So if we do this, we know it's US letter, but we know, let's say, we only have envelopes in the printer. So what it'll do is it'll scale to fit.
This is our envelope with the Kingtat scale to fit. So we don't get the clipping, we don't lose. It's kind of a quick way of getting a printout if you don't have the correct paper size. So that's basically all that has changed in the print dialogue. I think everything else is basically the same right now. I'm not saying it won't change further by the time Tiger ships, but this is what was currently planned.
So let's move on to PrintCenter. Here I have one printer here. We actually do have a Rendezvous printer, so if I could just click the add button, and we actually is one Rendezvous printer, LaserJet 4300. I will select it. You'll see that it's gathering information from the printer.
Once it finds it, And it's using, then when it selects that PPD automatically, we just go ahead and add it if we wanted to. And that's the change to printer-type utility. Now if you just go to the printer proxy, one thing we have added is we have added another tab to show your completed jobs.
It'll tell you the, you know, the name of the job, how it finished, whether it be finished normally, canceled, or an error. And it'll tell you when it completed. As you can so tell, I was doing this final preparation of this demo a little bit early this morning.
Another thing that we have heard from you and other users is they want to, a held job, you want to resume on a certain page. So we've added that. If you go to the jobs menu, you can go to resume on page, and you can enter any page number that you want. The printer isn't really here, so I'm just going to go ahead and stop the job. The other thing you can do with that is you can, we've actually added another toolbar widget for it. Resume on page. So there.
[Transcript missing]
Thanks Alan. So just a quick summary. Things that we've done so far in Tiger, we've provided that integrated printer browser as you saw, we've got or will have soon the fine control over which printers you share, SNMP supports going in, scale to fit in the print dialogue, improved functionality in the desktop printers, and we're obviously working on more.
The point I want to make here is please test this stuff. You know, you've got the first -- your first build of Tiger, you'll be getting more, of course, and whether you're writing applications or writing printer drivers or printer utilities, whatever, I mean, please start testing as soon as you can. Obviously the overall quality of Tiger will depend a lot on your contributions.
And I'm sure everybody knows how to file bugs, so please feel welcome. I'll change gears a little bit now. We're going to talk about APIs. And for anybody writing applications, this stuff is going to be relevant for you. One thing that you might have noticed over the last few years, we've had some API creep in the printing system. We've got these two header files, PMApplication and PMCore to provide most of the low-level APIs for printing. Most of those APIs are used internally by the various CocoaPrint methods.
And as you can see, we're up over 200 APIs by obviously incrementally improving the printing system. We added things like PMPrinter APIs, the PMWorkflow APIs, et cetera, over the last few releases. We thought that we were a little too heavy on APIs, so what we've done for Tygo is we've deprecated 80 of them.
So if you are using any of the old ones, you can use the old ones. If you're using the old ones, you can use the old ones. If you're using the old non-session APIs, the legacy laser iterate printing APIs, any of the APIs that we're trying to write things out to do with the old print record, you will get, when you try to compile your code on Tygo, you'll get a very polite warning that you're using a deprecated API.
So that's your signal to go into the header file. And as you can see from a comment up here, we'll tell you for every single one of those 80 which one or ones you should be using instead. Deprecated doesn't mean your code will crash. It just means that you'll get a warning at compile time and a strong encouragement from Apple to move on to the recommended APIs. So please stop updating your application printing code as soon as you can and follow those guidelines.
And then I want to take a few minutes to talk about the APIs that I hope most of you are using directly or indirectly, indirectly if you're using Cocoa, to print. And we're going to start by looking at a bunch of APIs that are usually worth calling before you actually invoke the print dialog. So after the print menu is being clicked, these are some of the APIs you should be using and we'll explain why.
One of the things we recommend is that every time you hit the Print menu, you start a new print session, and you should create new print settings and default them. And the reason for that is that the user, every time you go to print a document, starts off with the default sensible set of values for the various print settings. And shown here is, if you call default print settings, obviously you reset copies back to one, the page range, et cetera.
And better that than reusing the print settings object and inheriting your last settings from the last print job to the next one. Users can get confused or annoyed when that happens. So try to use that call. Another one to call, if you're printing multiple page documents, is to set the page range. That explicitly tells our copies and pages print panel what the valid page range is. It stops the user typing in, you know, print to page 99. If you've only got a 10-page document. So pretty obvious why you should use that.
Enable printer presets. Not for everybody, but if your application prints images, it's a good idea to enable the driver installed presets for the printer. Presets, if you're not familiar with the ones that are bundled with drivers, are recommended combinations of things like paper types and resolution settings. And users will be better off using the ones defined by the printer manufacturer than going into the various panels and selecting ones that they think are appropriate. This is a convenient way of picking ones that will yield good results on paper.
So you can do this by calling, if you're a Carbon app, enable printer presets. There's an API to disable them if you need to. Cocoa apps can do this. There's a step job style hint that you can apply to the NS Print Panel to do the same thing. So if you're printing images, enable driver presets.
Setting the job name is another good thing to do. And a sprint operation does this for you automatically, so you don't have to worry about it if you're a Cocoa app. Well, of course, you need to have a meaningful window title. CarbonApp should call this API. This is actually a new API in Tiger, but there's an equivalent API for Panther and Jaguar. It's PM Print Session Set Job Name CFString.
So there's an API to do that. Basically, anything's better than seeing "untitled" in that list of printers that you see either in the desktop printer list or on the CUPS web page or in -- or, for example, when you print a disk, you want to be primed with a reasonable file name. And the other thing is this screenshot here shows if you're looking at a print server, it's useful to see what's being printed.
And So try to call that API. Another one that we've been talking about for years, if you're a Carbon app, you need to be doing this, or you should be doing this if you can display multiple windows. Use the display your print dialogs as a sheet. Everybody knows then which window they're actually printing.
This is the easy one. I don't really have to say anything about this. Bring up the print dialogue, having done all that preparation work. After the print dialog is being dismissed, there's a few APIs you might want to be calling. If your application has a panel or panels to the print dialog, you probably want to get the settings that the user selected in order to control the way you draw the content when you get into the print loop.
So this is the API you can use for that. And there's sample code explaining that. But we've added a new API in Tiger. This is the one PM Print Settings get value. This enables you as an application to get any print settings value. So don't abuse this, but you can see what the driver's PDEs have added to the print settings. You probably don't want to be altering the way you draw your document according to that, but you can get any setting out of the print settings object after the print dialog's been dismissed.
Paul Danbold, Alan Beck, Richard Blanchard After the print dialog is being dismissed, there's a few APIs you might want to be calling. If your application has a panel or panels to the print loop, you probably want to get the settings that the user selected in order to control the way you draw the content when you get into the print loop. So this is the API you might want to be calling. If your application has a panel or panels to the print loop, you probably want to get any setting out of the print settings object after the print dialog's been dismissed.
Paul Danbold, Alan Beck, Richard Blanchard After the print dialog's been dismissed, there's a few APIs you might want to be calling. If your application has a panel or panels to the print loop, you probably want to get the settings that the user selected in order to control the way you draw the content when you get into the print loop.
So this is the API you might want to be calling. If your application has a panel or panels to the print loop, you probably want to get the settings that the user selected in order to control the way you draw the content when you get into the print loop.
So now to the print loop. I'm sure everybody heard this week that Quickdraw is being deprecated. And I think there's a session tomorrow on moving to Quartz 2D. So if you haven't already heard all the good stuff about Quartz 2D, please go to that session. I think it's -- Somebody will have to remind me. Tomorrow afternoon.
Two o'clock. Thank you. So this is the old print loop, drawing everything with Quick Draw. That will still work, but obviously we want you to move on. Maybe by now you've already started to take advantage of Quartz 2D, and for a while now we've had these APIs enabling you to draw some content on your pages in a core graphics context, and the Begin and CG Context APIs enable you to do that, effectively to mix Quick Draw and Core Graphics, and remember the coordinate spaces are different.
So that was something that hopefully you've been doing. But there's an even better way in Tiger to explicitly tell the printing system you're going to exclusively use Core Graphics calls to draw everything on the page. And this API begins CG, document, tells the printing system, you know, you've got to do this. And you've moved to Quartz 2D.
You can do the same thing on Panther or Jaguar, but not with this API because it wasn't available then, but you can still set up a Core Graphics Context and draw everything in. But with Tiger, there's just a more convenient way to do that with this new API.
And talking about that, I have to plug our unified PDF imaging model. This is a slide lifted from last year. I'm not going to go into a lot of details, but I'm sure everybody knows by now that if you use the recommended PDF print path, you get a lot of benefits.
Print preview, you get to take advantage of the PDF workflow, and all the other things mentioned here. If, for whatever reasons, you are obliged to generate PostScript code, then our recommendation, this is the same recommendation we had last year, is to use the job submission APIs. So don't use the printing system to generate a PostScript print job. Generate the PostScript print job yourself, and then use the job submission APIs to send that PostScript job directly to the print queue.
I'm mentioning here on the bottom bullet item two new APIs that may remove one of the excuses you had for using the legacy laser iterate print path. You can now use these APIs to generate your PostScript font data and put them into your PostScript file that you will submit with the job submission APIs.
I should mention that not all applications choose to use the print dialog when you go to print. Some applications have their own UI. Some applications or tools don't need a UI, and they certainly don't want to see the spooling dialog displayed. So there's the so-called no-dialog variance of the PrintLoop APIs. And you can see them here. That's the old way.
Of course, now that you're moving to Course2D, there's a corresponding API to the beginCG document. There's a CG document no-dialog, which will tell the printing system, I'm going through the PrintLoop, but I don't want to see the spooling dialog. But, and this is no different from last year with Panther, there's a better way of doing that kind of thing, and that's the job submission API. It's very simple to do.
Our desktop printer code does it. If you drop a file onto a desktop printer, We... We check the printing system. We ask it, does the printer queue accept a file of this MIME type? If we get back an answer that says this MIME type supported, we submit the job.
And to show you how good that is, I ran a few tests on just my humble old PowerBook back in my office with a variety of documents. And as you can see, any document I print, if the file's already on disk, I can print it in a couple of seconds with the job submission API.
So you should be thinking about using this if your application has the ability to generate its own printer-compatible file format, PDF, PostScript, TIFF, GIF, et cetera. So strongly encourage you to explore that. And as you can see here, you can get huge performance benefits if you take that approach.
So at this point, I'm going to hand over to-- oh, no. I'm going to summarize these slides. And then I'm going to hand over to Alan. Deprecated. We've deprecated about 80 APIs. Watch for those when you compile your code. Use those recommended APIs before you bring out the print dialog so that everything works smoothly in the print dialog. Move away from Quick Draw. We've got APIs to help you do that. And last but not least, the job submission APIs. great way of speeding up printing from your application. And now for something new: Cocoa Print Panels. And here's Alan.
At Panthership last year, we were sitting around saying, "Okay, what part of the printing system has been rewritten in the past two and a half, three years?" And, oh, the print dialog code hasn't been rewritten yet. So basically what we've been working on is rewriting the print dialog code and page setup dialog code to enable the inclusion of Cocoa PDEs. So what I'm going to do is I'm going to build a simple PDE, Cocoa PDE, that Basically, this is the old code that's on your developer examples printing.
Now basically, if we go through here, we kind of see what we're doing. A lot of comments. And then we get to here, we have, oh, we have to define how big we are. Define is the, let's see what else we have. Oh, we have this whole IOWN known stuff, IOWN known instance.
And really, that's kind of hard to figure out sometimes. We have this contact stuff. We have, we have our prologue. This is, and we get into actually coding some of this stuff. IOWN known, ADREF. Not much having to do with printing when you're writing a Tioga-based PDE. So what we have done is we have allowed you to greatly simplify writing a PDE. So what I'm going to do is I'm just going to take that old PDF.
I'm going to show you how to use App SDK sample code. And I am going to-- first thing I'm going to do is add in a target. And I am going to-- Add a Cocoa loadable bundle. I'm going to name it "sampleapppde" and add it to this project.
Okay, first thing I want to do is set the properties. And being as we are a Cocoa class, I'm going to name it to be an NS... Principal Class. And what else do I need to do? Go to the build and we need to add our, this is my kind of cheat file right here, add our framework search paths. Print framework and our... I'm just going to add that into here.
[Transcript missing]
Now this is the fun part. I'm going to go to Interface Builder. I'm going to select an empty Cocoa nib. Let's see, what's next? Let's go ahead and save this as... Sample app PDE. I'm going to add it to the sample app PDE target. Okay. Now I'm going to, let's do this, get the subclass right. Let's take an NSObject. Where did NSObject go? Okay, there it is. And we're going to subclass this into BA sample app PDE.
And then go back to here, files owner, and custom class, go down here, sample app PDE. Okay. Now's the fun part. Let's go up here, let's just grab the view there, just a NS view. Let's make it a little bit bigger. Let's add a checkbox. Text only. There we go. Okay. Now let's go back over here, I guess. Now we need to add, let's get our connections in there. Some glass. Let's go to connections. Let's add some outlets.
[Transcript missing]
Let's add another one, which would be our button. Print selection button, which is a button. Okay, now let's just go ahead and connect these up. That's the app. The button. Okay, so everything's connected up. Everything's basically, the nib's done. Let's go ahead and select this and... Danblot PDE.
Let's generate the classes. Let's create the files for it. That's right in the basic print loop. Okay, let's go ahead and create those. Okay, so they should be created and they now should be, should have appeared over here in our project builder. So now, where did they go? Save.
I don't know where they actually went, but either any way... Basic Print Loop. Here they are. Basically, this is... Here's our .h file. So basically, what we want to do is... Let's go to my little cheat sheet over here. First thing I want to do is you want an import.
One thing we have provided you is a callback object that the PDE can call back into to get information that it needs about the printing system, like, say, your print session, your print settings, your page format, your current printer. There are a number of things that you can get back from the printing system while you're in your PDE, so you don't have to remember it. You can just call it whenever you need the information. The other thing we want to do is... The Cocoa PDEs are implemented as a protocol.
[Transcript missing]
Okay, now let's just go over to the .m file. And I will just, basically I'm just going to copy stuff over that we need as we go through. So we're going to include our Basically, we're going to include our interface for dialog extensions, get some of the keys we need out of there.
Okay, first thing we're going to do is we have three static methods. One of them is initialized class and terminate class. These are called when, When this bundle is going to be loaded for the first time, you can return yes or no from the initialized class if you fail on your initialized.
We pass you the bundle just for your reference so you can get it any other ways. In this case, Terminate class is called once when the plugin is not going to be used anymore. We don't do anything. Next part is the Get PDEs for Plugin Type. What this does is basically this is where you instantiate your PDE classes.
Basically, we do a get plug-in for PDE type. We pass you the PDE type, whether it be app for the print dialog or page setup. We also pass you in the current printer that is selected in the print dialog. So basically, we allocate an array. We do an alloc init on our sample app PDE, add it to the array, and basically, if we got anything back, we return that array or we return nil. Next thing we do is we initialize our class. And here, this is where we pass you the callback mechanism, the callback object. We pass it in, you just retain it, and you can use it throughout your other things. And then terminate is the same thing.
We just, when we're done, we're going to terminate the PDE. We're just going to basically release your reference to that. One thing new about the Cocoa PDEs, we only ask for your view when we're going to show your view. So there is no need to create your view, you know, during initialize or open. We will tell you when, we'll ask you for the view when we're ready for it.
So basically here we are just, we haven't initialized it yet, we just do a, we load our nib. Then we return the top view. Next thing is PDE name, PDE type, and PDE kind. These are fairly similar to what we had before in the Tioga stuff, but here it's like we call you when we need it. You have to know it up front.
And we just call it whenever you need it. And another change that we did was sync. Sync, you had to remember where you're going, where you're reading from the ticket, writing to the ticket, where am I at? So we actually separated out these two calls, and now we have write values to ticket, and read values to ticket. I'll do write values first.
Basically here we just go to write values to ticket, we get our button, we say it's state, create an NSData for that, and here we are using our callback methods to get the print settings. So we use the callback object, get the print settings, we get it back, and we're using the API that Paul just showed us, the PM Printing, CM Print Settings Set Value, which basically sets the app using your app key. And then read values from ticket is basically just the opposite of that.
The Mac OS X printing system is the integration point for many key technologies. View this session to get the most out of the Mac OS X printing system. Paul Danbold, Alan Beck, Richard Blanchard The Mac OS X printing system is the integration point for many key technologies. View this session to get the most out of the Mac OS X printing system. Paul Danbold, Alan Beck, Richard Blanchard Yeah.
Basically print selection only, yes, no. We get to create the dict with a summary and info. This is only one item, so we're adding an array and we're adding the item to the dict and returning that array. Show, hide, is basically what it was before. We call this right before we're going to show your PDE and hide, go hide right before we hide the PDE. Another thing we're doing, so that's those two.
And finally, we have Git-supported PPD option keys, which is basically for the PM printer module vendors. This is in a way of dynamically telling us what PPD options you are supporting in your PDE, so they won't show up in the other settings, the advanced settings of PDE pane. Rather than a static in your static in your info dict info p list, we can return the array right here.
And the other one here, the last one is PPD value change, something we're working on that's not quite implemented yet, dealing with PPD value constraint, constraint resolution. So basically, we're not really quite ready to talk about this yet because we're still in the process of figuring out exactly what, how we're going to deal with this. So let's go ahead and save this. Hopefully, I can build this.
[Transcript missing]
Okay, so basically, I will go to the summary slide while that reboots, and I will show you when that reboots, hopefully. Let's get the slides back on. This is a little summary of what we need for Cocoa PDEs. Basically, they're implemented as loadable bundles, so we don't have any of the CFBundle stuff with the I unknown, all that other stuff. The other thing is your class must conform to the PDE dialog protocol, plug-in protocol.
We've added the PDE callback object, which allows you to get information from the printing system, such as your print session, your print settings, your page format, your current printer. Also, in there at the end, it lets you tell us to do certain things. The two current methods are to resize the panel.
You want to tell us how high you want it to resize, you know, what size you want the new panel to be. So you can do a disclosure widget, and that way, we will, you can resize your view, then we'll resize the print dialog to reflect that view.
What I want to say is, you can use the full Cocoa functionality inside your PDE, such as the bindings. You can bind to a dictionary, and then in your right settings to ticket, you can basically use the bindings that way. And the other thing is, this sample code that I just did, plus showing the resize, is going to be available on the ADC Seeds Server. Are we back up yet? No, we are... Okay, I'll be back up in a little bit using for Richard.
and maybe I'll have time, maybe we'll be back up by then so I can show it to him. So here's Richard. Richard Blaenchard: Thank you, Alan. Not just for the demo, which Colonel Panic, that's pretty rare actually in printing, but actually for all that work. And if anybody's written plug-ins before for the print dialog, one of the first things you have to fight your way through is the CF plug-in, I unknown stuff, which I've done a couple times and it was well worth all the effort Alan did on this just so I didn't have to do that again. So thank you very much, Alan.
It probably helps you too, but we'll see. Last year, we spent an hour, I spent an hour with you talking about the two different printing paths we have in printing. We have our PDF printing path, our preferred printing path, and we have our LaserEyedR8 legacy printing path. We spent that hour really talking about all the benefits of the PDF printing path and doing a lot of begging, asking you, "Please don't use the legacy printing path." I'm here to beg a little bit more, no offense, but in the last year we've come up with another reason why we really want you to use the PDF printing path, and that's Automator, and it's Automator tied into PDF Workflow. So we're going to do a couple demos, and we're going to remind you, well, I think we're going to do a couple demos, and we're going to remind you what was in PDF Workflow. So PDF Workflow is a feature we added in 10.2.4.
It's been around for a long time, but it's always been hidden. You had to enable a special folder and put these PDF Workflow items in that folder before the print dialog changed to show you this new functionality. The important parts about PDF Workflow, well, PDF Workflow were two.
One, it allowed you to hook the print system on the user side. Normally when you print, we take the PDF spool file, we submit it via an IP connection to the print server, and then the print job takes place potentially on a different machine, but most certainly in a different context and running as a different user.
And so if you want to put -- make a back end or a filter that's going to present UI, you have a lot of difficulties. You may be on a completely different machine than the user submitted a job, bad, or you just may be in a different context and not be running as the same user, so you can't write to that user's folders.
Or access their files. So PDF Workflow avoids those problems by letting you do that all up front in the user's context, running as the user's ID. So that was one about PDF Workflow. The other important part about PDF Workflow is that we have this digital master concept. We ask all our applications when they print to please render in the full fidelity. Give us your high resolution bitmaps.
Give us as many vectors as you can. Don't give us rasterized images of your vectors. Give us the best fidelity you can. Give us the highest fidelity. And that's what we call digital master, digital master PDF. We dutifully capture all of your drawing. With Workflow, you can then write a tool to manipulate the full fidelity digital master from the application. So that's the idea behind digital -- or behind PDF Workflow. It's been there for a while.
We have it documented. You should go look at it if you've never looked at it. It's pretty exciting. It's enabled always now in Tiger, and this is a big deal. It's always been a great feature, but you had to know the secret. So now it's always there. And as Alan showed previously, it comes defaulting this way on your CD.
So you can see that it's always there. And then you can see it on your CDs with Save As PDF and Save As PostScript. But as you add your own Workflow items, this pop-up menu will grow. And if you're somebody like me who's written a few of these, it can grow quite a bit.
And you just start making things that are useful. You'll see applications drawn in there, so I can send my PDF documents over into things like Illustrator, which is great at handling PDFs, obviously, sending it to Acrobat or sending it to tools that'll break down PDF, rasterize the PDFs, anything you really imagine you can do with Workflow.
So what kind of things can you put in workflow? And again, this is the type of list that we've supported since really 10.2.4. You can put a folder into the PDF services folder, into the workflow folder. If you put a folder in there, that creates a hierarchical menu in your PDF workflow pop-up. So this allows you to organize your workflow items.
You can put a folder alias in there. A folder alias, when selected from that printer pop-up menu, will take the PDF spool file and just move it into the resolved alias of this folder. So I use this a lot for web receipts. This is an example I just happen to like. I make an alias of a web receipts folder I make in my documents folder. I put it in PDF services.
And now whenever I buy anything online, I go to my workflow menu and I say web receipts. And it just makes a copy of my receipt, stores it there. And now with Spotlight, it's easy to search. So the whole thing works pretty well together. Also, hot folders for applications like Distiller are good this way.
You can make aliases of applications, put them in there. When that's selected, we send an open event to the application with the PDF spool file. So you can use Mail or Photoshop's one I use a lot. You can use Apple scripts. And you can write your own tools. And the tools can be written in either C or Objective C or Perl or Python or anything you want.
But what's new now in Tiger is Automator. So we allow you to create an Automator pipeline, an Automator set of actions, an Automator script. The terminology is varying. Put that in your PDF service folder. Now users can make their own workflow. And this is incredibly powerful, and it's very exciting. I've been doing a lot of work on this.
For example, one of the ones you see a lot with PDF workflow is, hey, I want to take this PDF out of whatever application is printing, grab the PDF, and mail it to somebody. And there are a lot of different ways to do this. You can take an alias, a mail, and drop it in there. And then what you get when you select that is a new document comes up in mail, a new mail message. But it's not, it doesn't have a person you're sending to.
It doesn't have a destination. So here's an example of an Automator script where you can set it up and say, hey, whenever this gets selected, I always want to send it to this particular person. Here's the text I want, and add the PDF. And assuming that we're back up, we're going to go to demo one here. And I'm just going to show you that quick. Automator workflow example, because it is nice how easy it is to do. So if we go over into Automator.
Oh, I'm sorry. Back to the previous demo. Back to my previous mishap. So this is a Cocoa PDE. It is a print-selected-text-only. It does work. And here's showing the callback mechanism that allows the PDE to resize itself and do progressive disclosure. So it does work. OK, now back to Automator. So basically, what we're going to do is we are going to-- let's go to Mail. Let's get the new email.
Richard Blaenchard, Alan Beck, Richard Blaenchard, Let's say, stuff. Please, let's review. Okay, now I'm going to go ahead and save this. I'm going to put it in my PDF services and I'm going to say email and we're going to save it as an application. So let's go ahead and save that.
Now, okay. So now it is now in our PDF services. So let's go over here. Let's go to my documents and let's go to... The various little league schedule that Rich wanted to know about. So we're going to go to here. We're going to go ahead and try to print it. And lo and behold, there's our email.
And here is Winter Rich, and here is our PDF document that is attached to it. All right. Very simple. All right. Thank you. So we'll come back on over to the slides, please. And again, the idea is that's very easy for a user to do, right? They've just made their own workflow item.
Because we're so PDF-centric, we really want to provide a set of automator actions that will manipulate PDFs. We want users and new developers to be able to make powerful PDF manipulation automator tools, provide them via workflow, so that workflow menu becomes very powerful. So what we're doing, or what we've done actually, is we've written PDF action items to extract pages from PDFs, to join them, to watermark them, and we'll be doing a bunch more. I expect we'll have probably a dozen or two of these actions by default in the system in Tiger by the time we ship.
I wanted to show next, we'll go back to the demo machine, we'll see how these work together inside of another automator. Basically, let's go ahead and see if we can find our PDF items. Okay, here they are. We have three of them. So let's just go ahead and first one will be to, let's get our Audit and Even pages. Let's go ahead and put them in separate files. And then we're going to, let's try to watermark them.
So basically we're going to add, what should we add? Let's add a blue and a green apple. Basically, so the goal here is to put a blue apple on the odd pages and a green apple on the even pages. So let's go ahead and make the apple a little bit bigger. Let's make it show it's underneath. And let's just turn it just a bit and let's turn down the opacity of it.
[Transcript missing]
We want to go to the PDF services. Let's name this one, let's say, Watermark. We want to save it as an application. Save. Okay, now let's go open, let's look at all the schedules. So it has 39 pages in it. Let's go ahead and print this. Go to here, here's our watermark.
Launching the pipeline. Okay, here's the first page with the blue apple, green apple, blue apple, green apple, all the way through to the end. Thank you, Alan. So what I like about that demo is it's a non-trivial example of what you can do with Automator and Workflow. If somebody asked you to do that, I want you to watermark this document and have different watermarks on the odd and even pages.
I know how you can maybe do it manually, but if they wanted you to run through a set of documents, I wouldn't know where to start. I guess I would. I'd probably go to Python scripting and start writing some Python code, but maybe a user wouldn't. So if we can go back to the slides.
All right, so that's the power of Automator. That's the power of PDF workflow put together. So the question is, well, how can your applications take advantage of this integration? And it is simple. It's what we've always told you. Please use the PDF workflow path or the PDF printing path. You can do that by drawing with Quartz. That's the way we preferred you to do it. You can do it drawing with Quick Draw, even though that's deprecated. If you go through the normal Quick Draw printing path, you'll generate a PDF spool file.
What will not work is if you use the LaserWriter 8 legacy printing path. That path is not being expanded. It's not being supported anymore. It still exists. And I have a tough time with people here. We actually have a little time so I can do this analogy. Last year when I said, "Hey, we're deprecating this," I had five, six, seven application writers coming up to me and very worried. "That means you're taking out the LaserWriter 8 legacy printing path for Panther?" And they said, "No, we're not. We're not taking out.
It's just deprecated." I said, "Well, then it'll be taken out for the next version." They said, "No, we're not taking it out there." I said, "No, we're not taking it out there either." And you quickly lose any fear that you can put in anybody when you say, "Hey, it's deprecated," when you tell them, "Yeah, but it's not going away." So the idea is we have to balance two things.
We really don't want you to use this feature, but we have to maintain binary compatibility. And so I use this historical analogy of baseball. In 1920, Major League Baseball decided they didn't want spitballs around anymore, so they deprecated them. But they had this binary compatibility problem that they had pitchers who were still working and still working.
They were still in the field using spitballs. So what they decided to do was let those pitchers keep working. They supported them. But new pitchers could not use the spitball, could not use the deprecated spitball. So the point is, if you have a spitball application using the LaserWriter8 legacy path, we definitely will keep you running. We will. But if you're working on a new application, please don't use it.
Or if you're even revving your application, please sit down seriously and consider ways that you can get off the LaserWriter8 legacy printing path. And we'll help you. We've done new APIs like the submission dial or the print submissions APIs. We'll help you in any way we can. We did the font creation APIs for you. So let us know what you need, and we'll get you off that. And you can stop throwing those spitballs.
Just quickly going back to the PDF workflow, there are a couple APIs that are interesting if you really like the workflow and you want to maybe write an application that will master workflow in a different way than the print dialog does. So if you want to do what our print dialog does, here are the two APIs. PM workflow copy items will go look in the directories where the user can install the workflow items and will come back with a list. It's essentially an array of CFURLs that is all the workflow items this user has set up.
And if you need to run one, you just call PM workflow submit PDF with options, give the workflow item you want to run, the title of the document, a bunch of options, and the PDF file you want to process. And this is all our print dialog does. And so if you wanted to write something that was not Distiller but somewhat akin to Distiller and that you had a batch processing application that you were running workflows through, these two calls will let you do it.