(I have gripes that I need to get out of my system. I think that documenting my approach to a coding task could demonstrate some points I want to make, and help me give some ideas solid grounding.)
Existing solutions for drawing graphics suffer from numerous technical, performance and usability flaws. (probably—I didn’t bother to check.) But I want to be able to draw things using a computer. I have an itch, so to speak, and I’m going to make a tool to scratch it.
So, I have decided to write a “useful tool” for building basic raster graphics. Like any “useful tool” worth its salt, it shall be designed for the environment of the 1970’s teletype. Might I just remark, that we are so lucky that the pinnacle of human-computer interaction was reached so early on in computing. No other technological invention can boast of such rapid mastery! For the decades since, we’ve been able to avoid wasting time on solved problems like “how to use the new-fangled computing devices”, letting us focus instead on what really matters—like writing “useful tools” to solve the real-world problems that we face right now.
It Must Have A Name
Because the tech of 1970, despite all its glory, made it undesirable to type very much, its name must be short and sweet. I’ll call it:
Wait, hmm, that looks odd. Verbose, perhaps. I don’t want to be typing four characters every time I want to paint a pretty picture! Ah, I know, I have to use some inexplicable abbreviation—how about:
drw. Yeah, that’ll do it.
I’m going to begin by considering how my life would be different after creating the
drw utility. What do I want to happen? First of all, I am faced with a blank line of paper. (well, such was the case for my spiritual ancestors back in the ’70s; sadly we have to make do with simulated paper these days.) I feel like I might type:
$ drw > smiley.png
What happens then? Interactive mode, I guess. I want to draw a simple smiley face, so probably start with something like…
$ drw > smiley.png # c 100 100 50
c stands for “circle” (obviously). The first two numbers are the x- and y- co-ordinates of the centre (obviously), in pixels, from the top left-hand corner (duh). The third parameter is the radius expressed in pixels (what else?). Oh, and the
# is the prompt for input. (it just felt like the right character to use.)
Hm, I should probably have that information easily accessible from the application itself. Here’s what my printout should look like after requesting
# h c c: circle Usage: c x y r #
Yeah, that should do it. I also realise something else I missed out. How is
drw going to do anything without knowing the dimensions of the image? They should have been passed in at the start.
$ drw -w 640 -h 480 > smiley.png # c 100 100 50 % outline of the head # c 85 85 8 % left eye # c 115 85 8 % right eye # bz 85 215 100 230 115 215 % mouth
Of course, any sensible language needs support for comments. This isn’t some hacker system where obscurity is a goal; no, far from it. We must always remember that code is used by humans to communicate their intentions to the computer.
Can you imagine how user-unfriendly computing would be, if we had to adapt ourselves to fit the machine instead of the other way round? Madness!
Next, if I want curvy shapes like the mouth, then there ought to be a command for Bézier curves. The three pairs of co-ordinates are just the three control points for a quadratic curve. There could be an optional extra argument for a cubic or something.
# h bz bz: Bezier curve Usage: bz x0 y0 x1 y1 x2 y2 [x3 y3] #
Great. But one huge thing I forgot about: colours! Ah well, there can easily be defaults. Initially the background is black and the foreground is white, just like my beloved teletype emulator! ❤
Then I should be able to send End-Of-File via Ctrl-D and see my picture in all its artistic brilliance!
... # c 115 85 8 % right eye # bz 85 215 100 230 115 215 % mouth # ^D Output written to stdout. $ pngvwr smiley.png
Ha! That’s funny. The mouth is all the way down there? Come to think of it, the face only goes from y=50 to y=150 (assuming I did my mental maths correctly—such clerical work is inappropriate for a scientific instrument), so why the hell did I think 215 and 230 were a good idea? And the scale is way too small. I want to make some adjustments…
Damn. I’ll have to go back and enter all the commands again! But wait: I could just write them in a file and pipe that to
stdin; I get scripting for free! Now that’s the power of the command line. Can you imagine how cumbersome this stuff would be in a GUI? Or with pencil and paper? 🙂
$ cat smiley.drw s 2.5 % scale the coord sys by 2.5 c 100 100 50 % outline of the head c 85 85 8 % left eye c 115 85 8 % right eye bz 85 115 100 130 115 115 % mouth (fixed!)
Commands to alter the coordinate system would be useful too. At minimum,
translate. (I was going to use
rectangle, but I still have capital R!)
$ drw -w 640 -h 480 < smiley.drw > smiley.png Output written to stdout. $ ls smiley.drw smiley.png $ pngvwr smiley.png
Right, that’s enough design for now. The next installments will use the coding of
drw as a springboard for concrete demonstrations of some ideas. And of course, more “features” will be tacked on as they come up. But regardless of how far this goes, some things are guaranteed:
- There will never be immediate feedback between creator and creation. The “spec” for the picture is written and compiled, and the result “viewed”, in separate, batch-mode stages; completely unlike “drawing” in any sense of the word.
- The program will be its own little untouchable universe. Functionality can only be added during the “fabrication process” of the next version. It will be as brittle as pottery.
- Worst of all, fundamentally visual concepts like position, size, shape, colour, angle etc. will remain brutally stuffed into the Language Box. The whole point of such a command-line utility is to use a thousand words to describe a picture. How is this anything other than outrageous?
6 thoughts on “Introducing drw: a “useful tool” to solve a “practical problem”.”
Poor Ivan Sutherland — with no drw available in the 60s, he had to invent some light-pen-based mumbo jumbo.
Regarding the smiley, you could also just use sed and an appropriate regexp to fix the mouth. Or just use the newer version that supports relative coordinates. It also supports an ASCII art output driver. Just edit the makefile to turn this on and recompile. Avoid negative numbers as they cause drw to write a 4GB output and segfault. There is a tool to sanitize the input to drw: sandrw.
cat smiley.drw | sandrw | drw > smiley.png
I usually create a simple bash script that wraps drw in sandrw. Sandrw creates some log files next to its input. I usually just add a cron job that deletes the sandrw log files once a week.
LikeLiked by 2 people
I just shed a tear at the beauty of what you wrote, Pavel. However, you don’t seem to be aware of the “keep_segfault_negative_numbers” config option under drw.pkg.config.conf.pkg-conf.parsing in your ~/.drwrc. After we fixed the issue in Roast Beef Dinner, a user complained that their Glurkle setup depended on this behaviour — it was set to interpret a rapid spike in disk usage as a trigger to enable sandrw — and it was just a quick change to make them happy.
It’s enabled by default, but you can disable it by setting it to “nope” (Stegosaurus dialect, but you knew that already) in the drwrc script and running make reconfigure. Good tips though, maybe we should add them to the readme — ahem, docs, sometime. I’ll stick it on my fridge when I get home.
This entire post is largely related to Brett Victor’s article on “Learnable Programming”:
I was going to agree with you; I do link to that essay an awful lot! However, I wouldn’t want to credit it with that here so much — what is being described here is not even a traditional animation but merely a static image! So while code may be appropriate for making it live, I suppose my real gripe here is that one should just be able to draw it, instead of drw it. I think of http://worrydream.com/DynamicPicturesMotivation/, where he shows the “tool” and “result” side-by-side. The domain of “static diagrams” does not even have the excuse that “we never had anything beyond code”.
So I half-agree with that association to Learnable Programming. I just think that stuff like TikZ, SVG markup, music programming languages etc. are unholy abominations that must be destroyed through obsolesence 😀 whereas the more “computed”-ness you need, the more understandable it is to have to rely on the only widespread mechanism that exists i.e. code — at present.
The part of “Learnable Programming” that relates to this is the “Create by Reacting” section, especially the “dump the parts bin on the floor” subsection (and *most* especially the punch-line that starts with “an objection may arise”)
(Edit: “book” –> “bin” as requested — Joel)
Ah, you’re right. Though unfortunately he doesn’t say book or even bin but “bucket” 😛 Are you not able to edit your own comments? I’ll see if I can turn it on somewhere…
Btw Dan, I enjoyed your recent explanatory posts on Cemetech. I am glad one of us is able to do that 🙂