September 93 - DEVELOPING QUICKDRAW GX PRINTING EXTENSIONS
DEVELOPING QUICKDRAW GX PRINTING EXTENSIONS
SAM WEISS
With QuickDraw GX comes a new extensible printing architecture that simply invites
you to jump in and tinker. Writing printer drivers has never been easier. But with
the advent of printing extensions, you may never have to write a printer driver again!
This article tells you what you need to know to create QuickDraw GX printing
extensions.
Macintosh system software has long provided hooks that enable developers to add
system-level features in the form of INITs (now called system extensions) and cdevs
(control panels). QuickDraw GX extends the extension concept to printing viaprinting
extensions, plug-in software modules whose sole purpose in life is to modify the
behavior of printing. Want to stamp the word "Confidential" on every page printed to a
specific printer? Write a printing extension. Want to drive a sheet feeder attachment
to a LaserWriter? Write a printing extension. Chances are that if there's something
you want to do that the QuickDraw GX printing architecture doesn't already do, you can
do it with a printing extension.
In this article, I'll describe the steps you must take to create a QuickDraw GX printing
extension. By the end of the article we'll have a working, environmentally friendly
extension called 4-Up. As shown in Figure 1, the 4-Up printing extension maps four
document pages onto one physical page at print time, saving countless trees in the
process!
Notice that I referred to a printing extension as a "software module." I would love to
use the currently hip term "component," but I don't want to confuse the issue by
implying that printing extensions are implemented as Component Manager components.
In fact, printing extensions are a whole new sort of beast. QuickDraw GX includes a
new low-level software manager called the Message Manager, which it uses to
implement its extensible printing architecture. A printing extension is a client of the
Message Manager called amessage handler. The Message Manager manages the
construction of a hierarchy of related message handlers into a message class, allows
message objectsto be instantiated from message classes, and directs messages among
message handlers. I won't be going into too much detail about the Message Manager in
this article. But there are times when you'll have to call the Message Manager directly
from your printing extension, so you need to be aware of it.
Figure 1 4-Up at Work
Another new manager included in QuickDraw GX is the Collection Manager, which
manages the creation of lightweight extensible data structures calledcollections.
QuickDraw GX printing makes heavy use of collections. Although we won't need to call
the Collection Manager from the 4-Up extension, nearly all serious printing
extensions will need to do so.
THE QUICKDRAW GX PRINTING ARCHITECTURE
Before we jump into the technical details of writing a printing extension, it will be
helpful to have a general overview of the QuickDraw GX printing process. First, I'll
describe how the printing process occurs in several distinct phases, each responsible
for a specific subtask of the entire process. Then, I'll explain the flow of control under
QuickDraw GX printing, as contrasted with that of the Printing Manager. And finally,
I'll discuss how printing extensions fit into the picture.
THE FOUR SEASONS OF PRINTING
Under QuickDraw GX, printing occurs in four distinct phases:
Spooling, which takes place in the foreground under the control of the
printing application, results in a device-independent print file being stored to
disk. This print file is also known as aportable digital documentor PDD, and it
can be viewed using the version of TeachText included with QuickDraw GX.
Because the contents of the print file are stored in a device-independent
format, it can be redirected to a device other than the original target,
potentially even a different class of device, for actual printing. For example, a
print file originally targeted for a PostScript LaserWriter can be redirected
to an ImageWriter. The print file contains enough information to allow the
document to be rendered to the best of the printer's ability, regardless of the
originally intended target printer.
Despooling, which always occurs in the background under the control of
the PrinterShare GX background printing task, is the process of reading pages
from the print file for imaging. Despooling need not occur on the same machine
on which spooling occurred. PrinterShare GX sends print files over the
network when the target device is a remote server. Also, users may copy print
files to floppy disk, or otherwise manually move them to other machines for
printing.
Imaging also occurs in the background under the control of PrinterShare
GX. Despooling and imaging always happen together, but it's useful to
consider them as distinct phases since they accomplish different tasks. While
the despooling process is responsible for reading the correct pages from the
print file, the imaging process is responsible for translating the
device-independent graphics data contained in the file into a format recognized
by the target device. This would be PostScript code in the case of a PostScript
LaserWriter, and it would be device- resolution bitmaps and appropriate
escape sequences in the case of an ImageWriter.
Device communicationsencompasses the actual dialog that occurs between
the printer driver and the target device. This is a distinct phase, as it may
actually take place on a machine other than that on which imaging occurred.
For example, if the target device is a remote server, and PrinterShare GX
determines that certain necessary resources (such as fonts) aren't available
on the server, PrinterShare GX may opt to image the job locally into animage
file,which it sends to the server. By definition, image files are
device-dependent, nonviewable, and nonredirectable. The image file is
"played back" on the server during the device communications phase.
GO WITH THE FLOW
At the highest level, the flow of control under QuickDraw GX printing remains similar
to that in the existing Printing Manager. There are three major players: the
application, the printing API, and the printer driver. The printing application calls a
layer of printing API routines, each of which either performs some task or calls the
appropriate printer driver to perform some task. However, there are two major
differences in QuickDraw GX printing. First, the printing API has been greatly
expanded. And second, the way in which control is transferred from the API to the
driver is completely different. I won't be going into detail about the expanded printing
API -- but you'll need to understand the new flow of control in order to write printing
extensions.
The existing Printing Manager calls the driver simply by loading the appropriate
PDEF (code resource) from the driver, computing the offset to the specified routine,
and jumping to it. As shown in Figure 2, QuickDraw GX printing uses an intermediary,
the Message Manager, to transfer control to the driver. When the application makes a
QuickDraw GX printing call, and the printing API needs to call the driver, it does so by
calling the Message Manager to request that a message be sent to the driver. The
advantage of this approach is flexibility. The Message Manager allows message
handlers to be inserted between the printing API and the driver (which is itself a
message handler). Aha! The light goes on! This gives us the ability to extend the
behavior of printing, or even fix bugs, without modifying the driver's code. It also
serves as the foundation upon which the printing extension mechanism is built.