June 96 - Print Hints: The Top 10 Printing Crimes Revisited
Print Hints: The Top 10
Printing Crimes Revisited
DAVE POLASCHEK
They say some things never change. Although it's been four years since Pete
"Luke" Alexander wrote about the top 10 printing crimes in develop, people are
still committing some of the same crimes. There are also a few new crimes to
add to the list. So, here they are, the updated top 10 printing crimes (ordered
on a combined frequency and hideousness scale):
10. Having insufficient free memory at print time.
9. Coloring outside the lines.
8. Misusing the PostScriptHandle picture comment.
7. Calling PrintDefault or PrValidate before PrOpen.
6. Avoiding the print dialogs, especially PrJobDialog.
5. Accessing undocumented fields in the print record.
4. Not checking error return values.
3. Making low-level Printing Manager calls.
2. Not using QuickDraw GX print dialogs if QuickDraw GX is present.
1. Adding printing to your application last.
Now let's look at how
to avoid these crimes. The solutions are relatively easy.
10. Having insufficient free memory at print time.
Some printer drivers use a lot of memory. When a driver runs out of memory, the
results are usually pretty bad, so you should give printer drivers as much
memory as possible. Unfortunately, memory requirements vary from driver to
driver, so it's hard to predict how much memory a driver will need.
Solution: Unload all unneeded code and resources before printing.
9. Coloring outside the lines.
Many applications draw outside the printable area of the page when printing.
This can happen if the user has extended objects beyond the printable area.
Drawing unneeded objects causes extra work for the driver and the printer,
which affects performance. In some cases, the driver also needs to allocate
extra memory to hold the objects or the enclosing rectangle.
Solution: Draw only the portions of objects that will appear on the page. This
can be determined by looking at the rPage field in the printer information
record (which is in the prInfo field of the print record).
8. Misusing the PostScriptHandle picture comment.
The PostScriptHandle picture comment is designed to add
PostScript (TM) code to a page containing QuickDraw graphics. It's
not designed to send multiple pages of pre-generated PostScript code to a
printer (for that, you need to use the Pap.WorkStation.o library).
Solution: Use the PostScriptHandle picture comment only to draw a
self-contained image, which will be added to any QuickDraw graphics already on
the page. If the PostScript code needs to change the graphics state, it should
save and restore the state. Think of the picture comment as a way to include an
EPS image, with all the restrictions placed on EPS by Adobe (TM) (as
specified in Appendix H of the PostScript Language Reference Manual, second
edition). The PostScript code should be compatible with both Level 1 and Level
2 PostScript, and you should include a QuickDraw version of the graphic so that
your users can print to a non-PostScript printer.
For more information on how to use the PostScriptHandle picture comment, see
Technote 1032, "Mixing QuickDraw & PostScript Printing from Your App: Some
Gotchas," and Appendix B of Inside Macintosh: Imaging With QuickDraw.*
7. Calling PrintDefault or PrValidate before PrOpen.
The documentation for the Printing Manager (Chapter 9 of Inside Macintosh:
Imaging With QuickDraw) mentions that you need to call PrOpen before calling
any other Printing Manager functions. Unfortunately, the descriptions for
PrintDefault and PrValidate don't repeat this warning.
Solution: Always call PrOpen before calling any other Printing Manager calls.
6. Avoiding the print dialogs, especially PrJobDialog.
Some applications try to avoid print dialogs because either user interaction
isn't possible or the developer thinks the user will make a mistake. Because
all of the many options for the current drivers, most notably LaserWriter 8,
cannot be stored in the print record, you need to call PrJobDialog so that the
driver can read in the options from where they're stored (usually in the
preferences file). If you don't call PrJobDialog, the driver can't set up the
print record correctly, and you might not get the output you expected. The
solution should be to call PrJobMerge, but in many drivers PrJobMerge does a
less than perfect job.
Solution: Call PrJobDialog before printing to set up your print record
correctly, or use QuickDraw GX, which supports dialog-free printing.
5. Accessing undocumented fields in the print record.
Many of the fields in the print record are undocumented or documented as
private. Printer drivers can use these fields however they choose. What works
for one driver might cause another to crash or to print zillions of pages you
don't want.
Solution: Use only the fields in the print record that are documented as public
in Chapter 9 of Inside Macintosh: Imaging With QuickDraw.
4. Not checking error return values.
After any call to a Printing Manager function, you should check PrError. If
you're calling PrGeneral, you should also check the iError field in the
TGnlData structure. Be aware that newer drivers return errors that older
drivers didn't. For example, PrStlDialog in LaserWriter 8 can return an error
if the preferences file is missing or corrupted; many applications don't check
for this error, and later crash when they've pushed the driver completely off
the cliff.
Solution: Always check and handle printing errors. See the Macintosh Technical
Note "A Printing Loop That Cares..." (PR 10) and the article "Meet PrGeneral"
in develop Issue 3.
3. Making low-level Printing Manager calls.
The low-level Printing Manager routines, such as PrDrvrOpen, are obsolete and
unsupported.
Solution: Never call the low-level routines.
2. Not using QuickDraw GX print dialogs if QuickDraw GX is present.
When you call the classic Printing Manager functions and QuickDraw GX is
active, the user gets the old-style "compatibility dialogs," which lack many of
the features that are provided in the QuickDraw GX print dialogs. There are two
problems with this: the user doesn't have access to all of the QuickDraw GX
features; and when some applications call the QuickDraw GX print dialog
functions and others don't, two very different printing experiences are
presented to the user.
Solution: Call the QuickDraw GX print dialog functions in your print loop if
QuickDraw GX is present. For help, see the article "Adding QuickDraw GX
Printing to QuickDraw Applications" in develop Issue 19. The complete
documentation can be found in Inside Macintosh: QuickDraw GX Printing.
1. Adding printing to your application last.
Four years later, this is still the number-one printing crime. A lot of
developers leave printing until near the end of the product development cycle.
When problems are encountered, Developer Technical Support gets messages like:
"My application can't print, and I've got to ship today. Please answer as soon
as possible."
Solution: Hook up your print loop as early as possible. As you add each new
feature to your application, print a page or two. Make sure that things are
still working as expected. When you take this approach, any features that cause
printing problems get noticed early, and you'll have time to fix them.
If you're committing any of the crimes on this list, your customers are
probably seeing things they don't like when they print. This list is also far
from comprehensive, as people continue to find new and unique ways to abuse the
Macintosh print architecture.
Looking ahead, printing will be changing in a big way. Mac OS 8 will use
QuickDraw GX as the printing model. As changes occur, there will be Technotes,
develop articles, and other sources of information. So keep your eyes open, and
remember, don't commit too many printing crimes. Crime doesn't pay.
DAVE POLASCHEK supports printing and font-related issues in Apple's Developer
Technical Support group. Dave was last seen wandering the halls muttering,
"This will all be better in Mac OS 8" and laughing maniacally.*
Thanks to Pete "Luke" Alexander, Paul Danbold, Dave Hersey, and Jim Zandee for reviewing this column.