TweetFollow Us on Twitter

The Perils Of PostScript

The Perils Of PostScript

SCOTT "ZZ" ZIMMERMAN

Letting your application rather than the LaserWriter driver convert QuickDraw commands into PostScript is simple in most cases, yet when you use direct PostScript to print documents, subtle interactions between the QuickDraw and PostScript imaging models can cause problems. This article will help you in two important areas: using a font from PostScript while selecting it using QuickDraw and preserving your PostScript state while using QuickDraw to select fonts.

When selecting a PostScript font from QuickDraw, an application first calls GetFNum (see Inside Macintosh, volume I, page 223 [IM I-223]) to get the Font Family ID for a particular font. It then calls TextFont (IM I-171) to actually select it. The name passed to GetFNum is the name of the font as seen in the Font menu (for example, Helvetica).

In PostScript, fonts are selected by name using the findfont (see PostScript Language Reference Manual, page 156 [PLRM 156]) and setfont (PLRM 215) operators. If the application attempts to select a font named Helvetica®, however, it will find that this font doesn't exist. This is because the LaserWriter performs a special operation on the font called encoding. Font encoding is the process of mapping missing characters into another font.

For example, a character like ø may not exist in the standard Helvetica font. In order to provide that character, the LaserWriter driver will modify the Helvetica font, inserting a reference to the ø character in the Symbol font. Once this is done, the font is no longer standard Helvetica, so it is renamed. The actual name is something like |_____Helvetica, but this naming convention is not standard and could change in the future.

So if you don't know the font's name, how can you select it? Simple, let QuickDraw do it. When you select a font via TextFont and then use it via one of the QuickDraw text drawing routines (such as DrawChar or DrawString [IM I- 172]), the LaserWriter driver handles the complex task of selecting an appropriate font on the PostScript device. This includes downloading and encoding the font if necessary. Using QuickDraw to select the font not only saves you a lot of work, but also improves compatibility. The process of font downloading and character encoding could change in the future, and if your application does it internally, it will have to be revised. If you use QuickDraw to download the font, your application will be immune to changes in the font downloading mechanism.

PICK A FONT, ANY FONT

Now let's look at the code to actually select a font. The following procedure will select a font for any device, QuickDraw or PostScript:
PROCEDURE  SetFont;(fontName: Str255; fontSize: INTEGER;
    fontStyle: Style);
VAR
    theFontID:  INTEGER;
    thePenLoc:  Point;
BEGIN
    GetFNum(fontName, theFontID);   (* Get the font ID. *)
    TextFont(theFontID);    (* Set it *)
    TextSize(fontSize); (* Set the size *)
    TextFace(fontStyle);    (* ...and the style. *)
    GetPen(thePenLoc);  (* Save the current pen position. *)
    DrawChar(' ');  (* Draw a space so the font gets downloaded.*)
    MoveTo(thePenLoc.h, thePenLoc.v);   (* Restore original pen *)
                (* position. *)
END;

There are two important things to note in the SetFont procedure above. First, the procedure uses the GetFNum trap to get the Font ID. This is essential to make sure that you get the correct font. (See Technical Note #191, Font Names for more information.) Second, the SetFont procedure calls DrawChar to draw a space. This is required to force the font selection on PostScript devices, since the TextFont call only changes the txFont field of the GrafPort. By actually using the font (via DrawChar) the LaserWriter driver's StdText GrafProc is called, and selects the font on the printer. Subsequent calls to the PostScript show (PLRM 222) operator will use this font. Since DrawChar will change the pen position, it is saved (via GetPen [IM I-169]) and restored (via MoveTo [IM I-170]).

ON WITH THE SHOW

Now that we have a font selected, we need to actually draw something with it. For now, as an example, let's say that we want to draw some text with the show operator. We'll send our PostScript using the following procedure. Although convenient for sending PostScript in our example, this method is very inefficient and should not be used in an application. Here's the code:
PROCEDURE SendPostScript(theComment: Str255);
    VAR
        PSCommand   : Str255;
        CommandHdl  : Handle;
        CRString    : Str255;
        theError    : OSErr;
    BEGIN
        CRString := ' ';
        CRString[1] := CHR(13);
        PSCommand := theComment;
        PSCommand := CONCAT(PSCommand, CRString);
        theError := PtrToHand(POINTER(ORD(@PSCommand) + 1),
            CommandHdl,LENGTH(PSCommand));
        if theError <> noErr THEN BEGIN
            (* Handle the error! *)
        END;
        PicComment(PostScriptHandle, 
            LENGTH(PSCommand), CommandHdl);
        DisposHandle(CommandHdl);
    END;

The procedure simply takes a string of text, adds a carriage return at the end of it, and converts it into a handle. The handle is then passed to the PostScriptHandle picture comment, which actually sends it to the printer. Since this procedure created the handle, the procedure also disposes of it. Again, this is not how a normal application would do it, but it keeps things nice and localized for this example. So now that we can send PostScript, consider the following:

SetFont('Helvetica', 14, [bold]);
PicComment(PostScriptBegin, 0, NIL);        
        (********************************************)
        (*** QuickDraw representation of graphic. ***)
        (********************************************)
    (* These calls are only executed by QuickDraw *)
    (* (i.e. non-PostScript) devices.   *)
        MoveTo(50, 50);
        DrawString('This is some gray text.');
        PenPat(ltGray);
        MoveTo(100, 100);
        LineTo(300, 300);
        (*********************************************)
        (*** PostScript representation of graphic. ***)
        (*********************************************)
    (* These calls will only be executed by PostScript devices.*)
    SendPostScript('50 50 moveto (This is some gray text.) show');
    SendPostScript('.10 setgray');
    SendPostScript('100 100 moveto 300 300 lineto stroke');
PicComment(PostScriptEnd, 0, NIL);

In this fragment, the call to SetFont sets the PostScript currentfont to be Helvetica. The PostScriptBegin comment is used to suppress QuickDraw calls on PostScript devices, and vice versa. When the LaserWriter sees PostScriptBegin, it ignores all QuickDraw drawing calls, and just executes picture comments. When a PostScriptEnd is received, the LaserWriter will once again interpret QuickDraw calls. The LaserWriter driver will ignore the QuickDraw representation, and begin executing the SendPostScript calls. The first one draws a string of text, the second one changes the default gray level of the printer from 100% black to 10% black using the setgray (PLRM 216) operator, and the third one draws a diagonal line using the new gray level. Note that the QuickDraw representation for a gray level is handled by using PenPat (IM I-170).

SAVE THE POSTSCRIPT STATE

The fragment we just looked at illustrates a good method for sending both QuickDraw and PostScript. It also demonstrates a new problem. When the PostScriptBegin comment is sent, the LaserWriter driver performs a PostScript gsave (PLRM 166) operation. This saves the current graphics state required for QuickDraw printing. The application can then do what it needs to the state without having to worry about side effects on the QuickDraw environment. When the LaserWriter driver receives a PostScriptEnd comment, it performs a grestore (PLRM 165) operation to restore the QuickDraw state. Normally this is exactly what you would want. But there are cases when an application may want to execute some QuickDraw commands without losing the PostScript state is has setup.

For example, the above code fragment set the gray level of the printer to 10%. At the time we did the PostScriptEnd comment, the gray level was restored to 100%. If we then want to change the font size, and redraw the text, we would have to resend the setgray operator. It would look like this:

   (* Change the font size.*)
    SetFont('Helvetica', 24, [bold]);
    PicComment(PostScriptBegin, 0, NIL);        
        (********************************************)
        (*** QuickDraw representation of graphic. ***)
        (********************************************)
        (* These calls are only executed by QuickDraw *)
        (* (i.e. non-PostScript) devices.*)
        (* The QuickDraw state is unaffected, so there's *)
        (* no need to call PenPat again. *)
        MoveTo(250, 50);
        LineTo(750, 50);

        (*********************************************)
        (*** PostScript representation of graphic. ***)
        (*********************************************)
        (* These calls only executed by PostScript devices. *)
        (* Since the PostScript state was cleared, we need *)
        (* to resend the setgray operator. *)
        SendPostScript('.10 setgray');
        SendPostScript('250 50 moveto 750 50 lineto');
    PicComment(PostScriptEnd, 0, NIL);

Although resending the setgray operator isn't difficult, an application may have set a lot more attributes. To avoid the overhead of resending this state, a new comment may be used. This comment is #196--PostScriptBeginNoSave.

When PostScriptBeginNoSave is used with PostScriptEnd, the gsave and grestore operations are not performed. This means that the application is completely responsible for the graphics state of the printer. If you are doing all of your imaging via PostScript this is not a problem. If you plan on mixing PostScript and QuickDraw, you must be very careful. Changes to attributes like line width and the transformation matrix will have a significant effect on QuickDraw drawing operations. If the comment is used for the above example, the code will look like this:

   (* Now illustrate the use of the PostScriptBeginNoSave  *)
    (* PicComment. *)
    PicComment(PostScriptBeginNoSave, 0, NIL);
        PenPat(ltGray);
        SendPostScript('.10 setgray');
    PicComment(PostScriptEnd, 0, NIL);
    
    (* At this point, the gray level of the device is 10% black *)
    (* Now draw something using this state. *)
    (* Draw a light gray line using QuickDraw. *)
    MoveTo(50, 400);
    Line(100, 100);
    
    (* At this point, the gray level is still 10%, so we must *)
    (* reset it  to black. *)
    PicComment(PostScriptBeginNoSave, 0, NIL);
        PenPat(black);  (* Reset QuickDraw gray level.  *)
        SendPostScript('1.0 setgray');  (* Reset PostScript gray*)
                                (* level.   *)
    PicComment(PostScriptEnd, 0, NIL);

Note that instead of sending PostScriptBegin as the first operation, we now send PostScriptBeginNoSave. We then change the gray level to light gray in the QuickDraw world, and 10% black for PostScript. Since we used PostScriptBeginNoSave, sending PostScriptEnd does not effect the state of the printer (i.e. the gray level remains at 10%). Now we want to draw something with the new state. We first send the PostScriptBegin comment, which saves the state we set up, as well as disabling the QuickDraw calls on PostScript devices.

We then send a QuickDraw representation of the line, followed by PostScriptEnd. On QuickDraw devices, the line will be drawn using the ltGray pen pattern. On PostScript devices, the line will be drawn using 10% black. After the line has been drawn, we need to reset the state of the device for subsequent drawing operations. This is done by once again sending the PostScriptBeginNoSave comment, followed by the commands to reset the gray level, as well as any other attributes of the printer.

In summary, we have looked at two ways of avoiding the perils of PostScript. The first was how to use a font from PostScript while choosing it using QuickDraw. The supported method for this was demonstrated by the SetFont procedure. The second was how to preserve your PostScript state while still using QuickDraw to select fonts.

Scott "Zz" Zimmerman is a DTS printing guru. (He's particularly impressed with the strictly enforced dress code at Apple.) In his spare time he sails, scuba dives for lobsters, and plays the piano, guitar, and saxophone. His doorway is adorned by a melted gummy rat, a good luck charm from his Intel days. At home, atop his monitor is perched a rare Asian black scorpion (behind glass, we hope). His other cuddly pets include two geckos and an iguana. *

 
AAPL
$441.00
Apple Inc.
-1.94
MSFT
$34.88
Microsoft Corpora
-0.21
GOOG
$906.85
Google Inc.
-1.68

MacTech Search:
Community Search:

Software Updates via MacUpdate

KeyCue 6.5 - Displays all menu shortcut...
KeyCue helps you to use your OS X applications more effectively. Just hold down the Command key for a while - KeyCue comes to help and shows a table of all currently available keyboard shortcuts.... Read more
Cobook Contacts 1.2.6 - Intelligent addr...
Cobook Contacts is a better address book that makes contact management enjoyable for millions of people every day. Find contacts faster and organize them with tags. Get integrated social profiles... Read more
AppDelete 4.0.7 - Delete your unwanted a...
AppDelete is an uninstaller for Macs that will remove not only applications but also widgets, preference panes, plugins and screensavers along with their associated files. Without AppDelete these... Read more
OnyX 2.6.9 - Maintenance and optimizatio...
OnyX is a multifunctional utility for OS X. It allows you to verify the startup disk and the structure of its System files, to run miscellaneous tasks of system maintenance, to configure the hidden... Read more
Apple iTunes 11.0.3 - Manage your music,...
Apple iTunes lets you organize and play digital music and video on your computer. It can automatically download new music, app, and book purchases across all your devices and computers. And it's a... Read more
Spotify 0.9.0.133. - Stream music, creat...
Spotify is a new way to enjoy music. Simply download and install. Before you know it you'll be singing along to the genre, artist, or song of your choice. With Spotify you are never far away from... Read more
JollysFastVNC 1.46 - Fast VNC client. (S...
JollysFastVNC is a VNC client which aims to become the best VNC client on the Mac. When I started ScreenRecycler I thought that there are enough VNC clients out there to support it. When the program... Read more
Skitch 2.5.2 - Take screenshots, annotat...
Skitch allows you to take screenshots on your Mac, edit them and share them with others. It makes the sharing process seamless by making it a natural workflow to send the image (with edited arrows... Read more
Backblaze 2.1.0.608 - Online backup serv...
Backblaze is an online backup service, available fo $5/month for unlimited storage. With half of the founding team heralding from Apple, Backblaze is deeply committed to the Mac platform. The... Read more
The Cave 1.0.0 - Adventure game featurin...
The Cave is an adventure game that offers a unique blend of fast-paced action, mind-bending puzzles, and winning humor. Assemble your team and embark on a journey into the shadowy underworld. Once... Read more

Fire & Forget: The Final Assault Rev...
Fire & Forget: The Final Assault Review By Rob Rich on May 21st, 2013 Our Rating: :: MY CAR IS FIGHTUniversal App - Designed for iPhone and iPad Fire & Forget: The Final Assault is one crazy post-apocalyptic ride.   | Read more »
Appy Geek Updates With Enhanced Design a...
Appy Geek Updates With Enhanced Design and Customizable Home Screen Posted by Andrew Stevens on May 21st, 2013 [ permalink ] | Read more »
What’s the Deal with rymdkapsel?
rymdkapsel made a bit of a splash when it was released on the PlayStation Vita a few weeks ago. And in another couple of months this excessively minimal and abstract strategic base building “sim” will be making its way on to the App Store for... | Read more »
Star Command Getting Exploding Ships, Sp...
Star Command Getting Exploding Ships, Spreading Fires, and Away Teams In Future Updates Posted by Andrew Stevens on May 21st, 2013 [ permalink ] | Read more »
Catch a Ninja Review
Catch a Ninja Review By Jordan Minor on May 21st, 2013 Our Rating: :: CATCH AND RELEASEiPhone App - Designed for the iPhone, compatible with the iPad It turns out ninjas aren’t that much tougher than fruit.   | Read more »
The Portable Podcast, Episode 186
On This Episode: Carter and Kurt Bieg of Simple Machine talk about his studio’s new release, Tomb Breaker, how it spawned from a nearly-complete prototype of another game, and how it fits in with his other titles, Circadia and Twirdie. Break into... | Read more »
Flickr Upgrades Its Free Users To 1 Tera...
Flickr Upgrades Its Free Users To 1 Terabyte Of Photo And Video Storage Posted by Andrew Stevens on May 21st, 2013 [ permalink ] | Read more »
NonoCube Review
NonoCube Review By Rob Rich on May 21st, 2013 Our Rating: :: CUBE LOVEUniversal App - Designed for iPhone and iPad Nonograms in 3D are just as awesome as they are in 2D.   | Read more »
Khan Academy Review
Khan Academy Review By David Rabinowitz on May 21st, 2013 Our Rating: :: LEARN ANYTHINGUniversal App - Designed for iPhone and iPad Khan Academy is a popular and free online collection of education videos. The app is a quick and... | Read more »
Street Fighter IV Is Part Of Capcom’s Su...
Street Fighter IV Is Part Of Capcom’s Summer Kickoff Sale, Now Only $0.99 Cents Posted by Andrew Stevens on May 21st, 2013 [ permalink ] | Read more »

Price Scanner via MacPrices.net

Apple MacBook Orders To Rise 20% Sequentially In 2...
Digitimes’ Aaron Lee and Joseph Tsai say that with Apple ready to release its new MacBook products in the near future, sources from the upstream supply chain have revealed that orders for MacBook... Read more
Trial Production of 5th-Generation iPad To Begin R...
Digitimes’ Max Wang and Adam Hwang report that trial production of Apple’s 5th-generation 9.7-inch iPad will begin soon with volume production to begin in July, and monthly shipments ramping up to 2-... Read more
Dell’s $100 Thumb-Sized Android PC To Ship In July...
9to5google.com says that Dell’s Project Orphelia, a thumb-sized drive that turns any display with an HDMI port into an Android PC, is to start shipping in July at a price of around $100 according to... Read more
MacBook Airs (Apple refurbished) available startin...
 The Apple Store has Apple Certified Refurbished 2012 MacBook AIrs available for up to $240 off MSRP, with models starting at $849. An Apple one-year warranty is included with each model, and... Read more
Updated Mac Pro, iMac, and Mac mini Price Trackers
We’ve updated our Mac Pro Price Tracker, iMac Price Tracker, and Mac mini Price Tracker with the latest information on prices, bundles, and availability from Apple’s Authorized Internet/Catalog... Read more
Updated MacBook Price Trackers
We’ve updated our MacBook Price Trackers with the latest information on prices, bundles, and availability on MacBook Airs, MacBook Pros, and the MacBook Pros with Retina Displays from Apple’s... Read more
15″ 2.3GHz MacBook Pro on sale for $1659 w/free bu...
B&H Photo has the 15″ 2.3GHz MacBook Pro on sale for $1659 including free shipping. Their price is $140 off MSRP. B&H will include free copies of Parallels Desktop, Bento Database, and LoJack... Read more
15-inch Retina MacBook Pros on sale for $200 off M...
 B&H Photo has 15″ Retina MacBook Pros on sale for $200 off MSRP including free shipping. B&H will also include free copies of Parallels Desktop, Bento Database, and LoJack for Laptops... Read more
Apple refurbished iPad minis available starting at...
The Apple Store has a full lineup of Apple Certified Refurbished iPad minis available starting at $299 – up to $40 off new models. Apple’s one-year warranty is included with each mini, and shipping... Read more
MacBook Air Inventory Shrinking In Leadup To Apple...
Appleinsider’s Neil Hughes reports that with Intel’s next-generation Haswell processors set to launch in a couple of weeks and Apple’s Worldwide Developers Conference (WWDC) coming next month,... Read more

Jobs Board

Class 1 District *Apple* Technician -...
QUALIFICATIONS: High School diploma Associate Degree in Technology preferred. Apple Certified Support Professional Mac OS X 10.5, 10.6, 10.7, 10.8 Apple Certified Read more
*Apple* Infrastructure Engineer II - Ba...
39964 Apple Infrastructure Engineer II Full Time Regular posted 04/22/2013 San Ramon, CA San Francisco, CA Requirements What sets Bank of the West apart from other banks Read more
*Apple* Retail - Manager - Apple (Unite...
Job SummaryKeeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, youre a master of them all. In the stores fast-paced, dynamic Read more
*Apple* At-Home Team Manager - Apple (U...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more than Read more
*Apple* Retail - Manager - Apple Inc. (...
Job SummaryKeeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you're a master of them all. In the store's fast-paced, dynamic Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.