WACOM pens stirring Cocoa...
One of the presents I got on my last Birthday was a small WACOM tablet. It comes with an inductive mouse and a pressure-sensitive pen. Recently, I wanted to use this thing to do some vector graphics, and since I've been looking for a decent drawing app ever since ClarisDraw went the way of the Dodo, I went another round around the block to check out the offerings.
I got trial versions of Illustrator, Canvas, Intaglio (which imports ClarisDraw files), Eazydraw (looks a little gaudy to me), even the X11-based Inkscape. I also attempted to download OpenOffice.org with its Draw module. In the end, the only app who actually supported pressure-sensitive drawing seemed to be Freehand.
But Freehand is from Macromedia, and Adobe (maker of Illustrator) just bought them. Worse, Macromedia just took Freehand out of their Macromedia Studio package, which is a strong indication it's the one who may die. I'm not going to buy a drawing app just to risk it being discontinued again, leaving me with un-openable files and having to find and buy another program to use on any future Intel Macs... This also seems very likely considering that Adobe already sold Freehand before: Way back when they acquired Aldus (and with it PDF, Postscript and lots of other stuff).
So, in a quirk of fancy, I decided to look how involved it is to write one's own drawing program. I have a general idea because I wrote pixel and vector drawing programs on various projects before (as part of Resurrection's icon and PICT editors, as part of one of my various failed HyperCard cloning attempts, and two different implementations as part of a presentations program I wrote on contract). But so far, I'd never done any that did bezier curves or polled a tablet for pressure information.
Turns out it was rather easy: Since MacOS X 10.4 Tiger, Cocoa's NSEvent class has a -pressure field that can be queried. And even better, if you subclass NSApplication and override -sendEvent, you can check the subtype of an event to find out whether it's a proximity event which will tell you not only whether the user is using the pen's eraser or drawing tip end, but also whether he's using a pen or a mouse. There's some (rather involved) sample code on WACOM's developer site, but you typically only need the proximity events and pressure info.
Now that part was fairly easy. The only involved issue was that NSBezierPath and the rest of Quartz doesn't really support varying line widths. The whole path has to be drawn in the same width. So, what I had to do was split up the path into segments that have the same line width, and then draw them 100% opaque into an NSImage, making sure their rounded line endings overlapped so they appeared as a continuous line. Once I had them in an NSImage, I could draw that image at the desired opacity without the overlapping parts being twice as opaque as the rest.
Of course I still haven't really solved the problem of filling without having the lines and the fill partially overlap, but Matt Gemmell has source code to do something similar I might be able to adapt.
I'm not sure what I'll do with this critter yet, but since I've been using a hacked copy of Apple's Sketch sample code so far and I don't like hitting my head against the wall every time I have to fight its horrible (and occasionally broken) UI, I might actually turn this from a bezier-path-drawing (plus save/load documents) application into a more modular drawing app. Assuming I get around to at least adding Export to PDF...
|Chris Cockcroft writes:|
Not sure if you're still interested in Illustrator or not, but it does support pressure sensitivity, and is definitely the top drawing program out there (in my opinion of course).
Create a new doc, then go to your "Brushes" palette, and double-click on the first one. A window will open up with options. At the bottom is the "Diameter" settings - choose a diameter, choose a variation, and from the pop-up, choose "Pressure". That should do the trick.
If you have any problems, send me an email.
|Uli Kusterer replies: ★|
@Chris: Thank you! There are several other reasons that made me decide against Illustrator, and now I have Lineform, which is darn close to my ideal drawing app, but it's good to know Illustrator does pressure sensitivity, too. It would have been a big oversight if it didn't.
I haven't tried it, but I'm pretty sure the "right" way to handle varying pen pressure in vector drawings is to draw a strip-like shape, with lines on both sides that move closer or further apart as the pen pressure changes. (This would be similar to how the arcs of letters are drawn, when converted to shapes.) That way, you don't have to worry about having lots of overlapping line segments, unclosed shapes, and stairstep line widths.
|Uli Kusterer replies: ★|
@Anonymous: Good point. Of course, one would still need to determine the angle of the line oneself, so one could position both lines in parallel, but even I can do that without a book, so this must be very basic maths :-)