Why Mac programmers should learn PostScript

2007-04-07 11:21:55 UTC

I’ll follow this up with a tutorial called “PostScript for Cocoa programmers”, but today brings my list of reasons why you should care in the first place.

  1. You already know it!

    Yes, that’s right. You’re an OS X programmer, so you’re already about halfway there.

    Most of us know that OS X is the successor to OpenStep. OpenStep’s graphics system was based on Display PostScript, and its graphics API mapped entirely to PostScript commands (except for flow-control, which of course was handled natively). Display PostScript is gone from the OS, but its design is still evident throughout Cocoa’s graphics APIs, since Cocoa descends straight from the OpenStep APIs.

    OS X, while inheriting Cocoa, replaced DPS with Quartz. Quartz is based around PDF. Guess what PDF is based on?

    PostScript!

    PDF is a file format that can contain, among other things, a simplified subset of PostScript: no flow-control, only drawing commands. So all of the graphics concepts from PostScript apply equally to PDF. That means that Quartz also demonstrates the PostScript influence, though it’s second-hand and has some things not found in PostScript.

    (Before you ask: No, this has nothing to do with Cocoa not having an API for shadings. Those are in PostScript too. I don’t know what’s up with that.)

    So if you can do graphics in Cocoa or Quartz, then you already know the graphics concepts of PostScript. That’s half the battle; all you have left is the language.

  2. PostScript is source code.

    It’s versionable (and remember, version control is mandatory). It’s diffable. It’s mergeable. It’s compilable. It’s human-readable and it’s human-editable.

  3. Writing a PostScript program is easier than writing Cocoa or Quartz graphics code.

    PostScript is made for drawing vector graphics. This is a big advantage over general-purpose languages like C and Objective-C: PostScript is made for writing vector images, so it’s optimized for that purpose to the exclusion of others. (The same advantage applies to Core Image: Compare a CI kernel program to an equivalent pixel-munging program written in C. Which one is easier to read?)

    If you want an example, I suggest comparing the PostScript snippet in the Beads how-to to the equivalent snippet of Quartz code a few paragraphs later.

    The other advantage is that PostScript is garbage-collected; you never have to worry about retain counts. Of course, you’ll get this in Cocoa in Leopard, but you can have it in PostScript now (and even in Leopard, if your existing code is in pure Quartz rather than Cocoa).

  4. Vector art is the way of the future.

    When resolution-independent UI comes, your raster art will look like crap. Maybe not right away, but as screen resolutions go up, your raster art will come to look blocky and ugly. (Daniel Jalkut provides an excellent example.)

    Vector art scales up cleanly to any resolution; raster art doesn’t. Plan for the future: Use vector art.

  5. EPS/PDF output from graphics apps sucks.

    In my experience, hand-written EPS files can be 1100 the size of an equivalent machine-generated EPS. And that size suck implies efficiency suck—that is, machine-generated vector art will not render as quickly as vector art that is hand-written.

    (In fairness, Inkscape’s EPS output is actually quite good. But it’s still not as good as hand-written, and Inkscape on OS X is slow and ugly.)

  6. For a Mac programmer, EPS is better than SVG.

    You probably started thinking several paragraphs ago: “OK, so I should be using vector art—but why not use SVG? Why should I use PostScript instead?”

    The reason is simply that SVG isn’t supported natively by Mac OS X.

    Sure, you could use Jonathan Wight‘s PettySVG library, but the SVG dialect that it supports is “an absolutely microscopic subset”, so there’s no guarantee that you’ll be able to make your drawing app of choice work with it. WebKit will support SVG, but that’s not here yet. Either solution requires an external dependency, unless you’re patient enough to wait for SVG-in-WebKit to arrive in some future version of Mac OS X.

    You could convert the SVG to an EPS or PDF, but the output would suck (see #5 above). Also, tools to do that don’t come with OS X. This is bad for open-source programs because only those with the converter tool can work on your graphics, and bad for every such contributor because they’d have to reinstall such tools when moving to a new Mac or reinstalling.

  7. Though PostScript is a programming language, you’ll rarely ever need to worry about programming in it.

    This is more like a counterpoint to a reason not to use PostScript.

    PostScript is a programming language, which makes it complex: it has flow-control, variables, and procedures.

    As in any other programming language, these features can help promote code reuse. But 90% of the time, you don’t need to worry about that complexity; you can just write a graphic. The programming-language features are there for when you need them, but most of the time, you don’t.

  8. It’s fun!

    Wisely suggested by Paul Kim in the comments below. ☺


UPDATE 22:50: Added #8.

11 Responses to “Why Mac programmers should learn PostScript”

  1. John Labovitz Says:

    Yes, totally. Having learned PostScript in the mid-1980s when it first appeared, I found learning Quartz and the Cocoa drawing classes to be really easy. Sometimes I do miss the simplicity of “100 100 moveto (Hello world) show” (although I always forget that I have to set the font first).

  2. ssp Says:

    Hmmmm. I haven’t actually programmed PS on the Mac. But wasn’t one of the main drawbacks (or speed advantages) of PDF and Quartz that they cannot handle the full complexity of PS? Like those tiny files of PS code which will draw a Mandelbrot set, say

    Otherwise I guess the question comes down to how much you actually need to draw. I hardly ever needed to draw more than a few lines or shapes which standard NSBezierPaths did just fine (although not too quickly I might add – although I think this may have improved since X.2)

    And I keep being sceptical about the UI scaling argument. Yes, in _some_ situations, like Daniel’s example, vector graphics may work well for use in the UI but in other situations, particularly at small sizes, hand-optimised graphics will just look better.

  3. Peter Hosey Says:

    Hmmmm. I haven’t actually programmed PS on the Mac. But wasn’t one of the main drawbacks (or speed advantages) of PDF and Quartz that they cannot handle the full complexity of PS? Like those tiny files of PS code which will draw a Mandelbrot set, say

    Yes; the idea was to make PDF more attractive for embedded systems (mainly printers and PSCs) that probably don’t have the processing power to efficiently implement a full interpreted programming language. A Mac is not such a machine: it can handle full PostScript easily.

    As for Quartz, that’s what CGPSConverter is for.

    And I keep being sceptical about the UI scaling argument. Yes, in some situations, like Daniel’s example, vector graphics may work well for use in the UI but in other situations, particularly at small sizes, hand-optimised graphics will just look better.

    What I want is an NSImage subclass that DTRT for multiple representations. You could have a NSImage with a 24-px raster representation and a 48-pt vector representation, such that it would use the raster representation on low-resolution displays and the vector representation on high-resolution displays. Eventually, when nobody has a low-enough-resolution display to encounter the raster rep anymore, you delete that rep and go vector-only.

    I tried writing a category that easily grabs all the representations of a file from a specific bundle and stuffs them into one NSImage, but it didn’t work, as NSImage did the exact opposite of the right thing: it used my 48-pt vector rep for the 24-pt image well, and my 24-px raster rep for the 48-pt and 128-pt image wells. (This is with the same NSImage in all three wells.)

    I’m open to sharing the code, if anybody wants to hack on it (perhaps by reimplementing -drawInRect:fromRect:operation:fraction:).

  4. Paul Kim Says:

    Ah, reminiscing about my days using DPS (Display PostScript). IIRC, chunks of the NeXT windowserver were written in PS making it especially interesting to dissect and hack. I also just noticed that ‘pswrap’ is still around (for DPS on X11).

    I think reason #8 should be “It’s fun”. Maybe it’s just me but I thought programming in PostScript to be pretty nifty. Something about playing with the stack. In a certain way, PostScript is like Logo for “grown-up” programmers.

    Is there an interactive PS interpreter available? Something like NodeBox? I guess I should start playing with the DPS implementation on X11.

  5. Peter Hosey Says:

    I think reason #8 should be “It’s fun”. Maybe it’s just me but I thought programming in PostScript to be pretty nifty. Something about playing with the stack. In a certain way, PostScript is like Logo for “grown-up” programmers.

    Totally. Consider it added.

    Is there an interactive PS interpreter available?

    Yup: GhostScript. You’ll need X11 installed and running to use it. It provides a live interpreter, as well as its own implementation of pstopdf and a few other PostScript-related utilities.

    I’ll be sure to mention that in the tutorial post.

  6. David LaVallee Says:

    OSX preview.app will render PostScript files, such as the following:

    %!PS-Adobe
    /Times-Roman findfont 80 scalefont setfont
    10 600 moveto (Hello World) show

    Adobe Illustrator CS2, CS3 are also able to render postscript. I’m planning on using this to do algorithmic drawing with Postscript, and then use the output directly in Illustrator and Flash.

  7. Peter Hosey Says:

    David LaVallee: Yup, but it’s not interactive, which is really handy when you’re debugging a complex PS program.

    As it happens, I’m working on the tutorial today. I doubt I’ll have it out today, but I am making progress.

  8. Samuel Goodwin Says:

    So where’s the tutorial you said you’d write? I’m interested :)

  9. Peter Hosey Says:

    It’s still not finished. ☺

    I will finish it; please be patient.

  10. Josh Says:

    Since Quartz is based on Postscript through PDF, is it possible (or feasible) to render the postscript directly, without converting it to PDF? It would be nice to have a subclass of NSView which directly renders the PS.

    Another strange thing I don’t understand; why does ps2pdf produce much better looking PDFs than Preview?

  11. Peter Hosey Says:

    Since Quartz is based on Postscript through PDF, is it possible (or feasible) to render the postscript directly, without converting it to PDF?

    PDF’s vector-graphics language is derived from PostScript, but isn’t PostScript exactly; in particular, flow-control is missing, and many command names are different (abbreviated).

    It would be nice to have a subclass of NSView which directly renders the PS.

    Indeed it would, but that’s possible now. Hint: Start with NSScanner. ☺

    Another strange thing I don’t understand; why does ps2pdf produce much better looking PDFs than Preview?

    I haven’t observed that. Both go through the same API, so they should always produce exactly the same results. (Easy way to check would be saving the PDF from Preview, then comparing the PDFs to see if anything is different, and if so, what.)

Leave a Reply

Do not delete the second sentence.