There should be a name for that feeling you get when moving house and you discover yet another forgotten microcomputer from the 1980′s. ZX81… BBC B… Commodore 64… BBC Master… Hey a SPARCstation 2! Isn’t that from the 90′s?
Oh look, another Model B.
hacking habits
There should be a name for that feeling you get when moving house and you discover yet another forgotten microcomputer from the 1980′s. ZX81… BBC B… Commodore 64… BBC Master… Hey a SPARCstation 2! Isn’t that from the 90′s?
Oh look, another Model B.
Adding sound to Curly Logo was a bit of a challenge, but it now has a beep command. I’m sorry the beep is not very pleasing; it was easy for me to write a Python program to synthesize the .wav file, and it compresses very well.
The beep command works by creating an HTML embed element that specifies a sound file, then creating a span element to contain the embed element, then displaying the span element. The act of displaying the span causes the sound to play. Without additional styling that also causes a great big ugly span containing an embedded play controller to appear. So I style the span before displaying it:
span.style.position = "absolute" span.style.visibility = "hidden" span.style.top = '0px'
Giving it «position: absolute» removes the span from normal flow, so its appearance doesn’t affect the position of anything else. Giving it «visibility: hidden» makes it invisible. Normally it makes something invisible whilst still preserving their effect on normal flow; that text will still flow around an invisible floating image for example. I use «position: absolute» so the element has no effect on normal flow anyway.
Contrast this with «display: none» which means that the element is not displayed, as opposed to being displayed outside of normal flow and invisible. Whilst this might seem like mere semantics, the difference is crucial. Using «display: none» will not make the sound play, whereas «position: absolute;visibility: hidden» does play the sound.
«top: 0px» avoids a bug in Safari where it expands the drawn area and adds a scrollbar even though it doesn’t draw anything there. Firefox seems to have a similar bug that I haven’t worked round.
Playing the sound again involves a little trick. First I tried «span.style.display=’none’» followed by «span.style.display=’inline’». This works when done “by hand” but fails when put into a function and called. Presumably Gecko needs to trigger a reflow between the two assignments, otherwise it just observes that nothing has changed so no redisplay is necessary. So what I do is throwaway the current span containing the embed element and create a new span. This is a good justification for having the span/embed pair, we can throwaway and recreate a relatively lightweight span, but the more heavyweight embed element is reused.
The original plan was to put the .wav file on the server and refer to it, and fetch it, via HTTP. Currently everything on amberfrog.com is compressed for transfer (“Content-Encoding: x-gzip”) which is a big win for HTML and JavaScript. For most audio formats it wouldn’t be so useful because they’re compressed already, but my current beep.wav file compresses from 41e3 octets to 551 octets. A huge win. Unfortunately embed elements playing sound files don’t work with “Content-Encoding: x-gzip” and I’m too miserly to store and transfer the uncompressed file.
I simply encode the entire 41e3 octet .wav file as a “data:” URL and stick it in the JavaScript as a string (I don’t get to gzip my “data:” URLs). It works just fine, despite the RFC’s assertion that «The “data:” URL scheme is only useful for short values». Well, it works just fine in Safari, Firefox doesn’t do RFC 2397 for audio embed elements and that’s bug 404780.
[Update: 2008-01-10: Now I use MIDI not .wav; this is better in several ways. I still use the RFC 2397 encoding.]
Of course I should be using an object element not an embed element, as embed is not standard. Couldn’t get object elements to work in Safari. Hush now.
A new feature of Curly Logo is the SETTBG command to Set Text BackGround colour. settbg "#850c sets the background to be a nearly fully opaque brown. Note that you can set the alpha (opacity) channel. As I mention in an earlier article the background for this (XHTML) div element is a 1×1 PNG. In order to implement SETTBG I have to create a 1×1 PNG containing an arbitrary 4-channel colour value, in JavaScript.
Gareth Rees wrote a very useful post on making very small PNGs that does most of the work of showing which bits should go where in a PNG file. Unfortunately the IDAT chunk in a PNG file is required to be compressed with zlib/deflate. That means I have to take my 32-bits of data (RGBA), prepend a 0 octet (for PNG’s scanline filter) then compress those 5 octets into zlib format.
I haven’t written a fully general zlib encoder in JavaScript, so what I do is use the feature of the deflate format that allows uncompressed blocks.
Let’s say my pixel has colour value #c5005c6d (that’s in RGBA order). My PNG scanline requires a 00 to be prepended, so I need to zlib encode the 5 octets 00 c5 00 5c 6d. Here’s what the encoded zlib data looks like:
78 9c 01 05 00 fa ff 00 c5 00 5c 6d 04 3e 01 8f
Which breaks down like this:
In the same style as Gareth’s Python here’s some JavaScript:
// Create a PNG chunk. Supply type and data, length and CRC are
// computed.
chunk: function(type, data) {
return be32(data.length) + type + data +
be32(this.crc(type + data))
},
// Create binary data for a 1x1 4-channel PNG. The colour is specified
// by the number n: 0xRRGGBBAA
unit: function(n) {
var d = '\x00' + be32(n) // PNG scanline data.
return '\x89PNG\r\n\x1A\n' +
this.chunk('IHDR', be32(1) + be32(1) + '\x08\x06\x00\x00\x00') +
this.chunk('IDAT',
'\x78\x9c\x01\x05\x00\xfa\xff' + d + be32(this.adler32(d))) +
this.chunk('IEND', '')
}
These fragments are embedded inside an object, hence the object literal syntax to declare the functions and the use of this to refer to other functions defined alongside. be32 is a function to encode an integer in 4 octet (32-bit) big-endian format.
Getting all this data correctly inside a PNG requires two checksum algorithms: Zlib format uses a simple Adler checksum (at the end, see above); PNG uses a conventional 32-bit polynomial residue checksum for each of its chunks. I had to implement both of those in JavaScript.
JavaScript is actually a pretty nice language for bit-twiddling. Sure the performance is bound to suck but that’s a feature of the implementations not the language itself. Not that I actually measured the performance, but I Just Know. In any case performance is not an issue for encoding this trivial amount of data. JavaScript has all of C’s bit-twiddling operators, and it has a bonus feature that C doesn’t have: 32-bit operation guaranteed. Generally the way that an operator like «x ^ y» works in JavaScript is that both x and y are converted to 32-bit signed integers then the operation is performed as if on 32-bit signed integers and the result is converted to a JavaScript number (which is an IEEE double). In C you might have to worry about those 36-bit or 64-bit architectures that have “funny” widths for their types. Not in JavaScript.
Here’s the CRC code in C from the PNG Spec Annex D:
unsigned long update_crc(unsigned long crc, unsigned char *buf,
int len)
{
unsigned long c = crc;
int n;
for (n = 0; n < len; n++) {
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
}
return c;
}
Here’s my JavaScript version:
crc32: function(buf, crc) {
if(crc === undefined) {
crc = 0xffffffff
}
var i
for(i=0; i<buf.length; ++i) {
crc = this.crctable[(crc^buf.charCodeAt(i)) & 0xff] ^ (crc >>> 8)
}
return crc
},
The core code inside the “for” loop has hardly changed. Instead of «buf[i]» I have to write «buf.charCodeAt(i)»; JavaScript doesn’t have a character type so conversions from characters to their internal representation are more explicit. Note that in JavaScript the shift is «crc >>> 8». JavaScript doesn’t distinguish signed and unsigned integers (or indeed integers and floats) so it can’t tell which sort of shift is required by inspecting crc. Like Java JavaScript has two right shift operators, «>>» for preserving the sign bit, and «>>>» for clearing the sign bit. Using the wrong one was a bug in an earlier implementation of mine.
is that it’s not commutative. That means that when the SVG spec says in the documentation for the multiply method in the SVGMatrix DOM “this matrix is post-multiplied by another matrix” it really does matter which way round you do the multiplication of the two matrices.
In the call «A.multiply(B)», A is this and should be post-multiplied by B. In the usual mathematical convention the result should be AB.
Safari computes BA, Firefox computes AB. Oopsy.
This is a confusing area; when I was first getting the turtle motion in Curly Logo going (on Firefox initially) I remember a bit where the turtle’s motion was wrong, and I realised that I had some matrix multiplication the wrong way round. Happens all the time regardless of how much thinking I do beforehand about which way round matrices ought to be multiplied, so I thought nothing of it and simply swopped my arguments. As I was writing the first draft of this article I thought Firefox had it wrong and Safari had it right, turns out that’s not right, it’s the other way round.
Regardless of who is right, anyone wanting to use the routine has to do something to work around it.
So here’s what I do. I perform a trial matrix multiplication using SVGMatrix.multiply and determine whether the multiplication was performed the correct way round or the wrong way round.
Consider the matrices L, a flip, and R, a projection:
LR, that is «L.multiply(R)» as it should be:
What happens if the implementation swops its arguments:
In JavaScript (well, SVG DOM really) the entries of a matrix are assigned to properties like this:
Note that the two result matrices (above) only differ in their e and f entries. Specifically when «L.multiply(R)» is computed correctly (following the specification) the result’s e property is 0; when computed with the matrices swopped (incorrectly) the result’s e property is 1. How convenient.
Here is some JavaScript to detect if SVGMatrix.multiply is wrong:
matmulwrong = function() {
var g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
g.setAttribute('transform',
'matrix(0 1 1 0 0 0) translate(1 0)')
var l = g.transform.baseVal.getItem(0).matrix
var r = g.transform.baseVal.getItem(1).matrix
return l.multiply(r).e
}
There is a lot of faffing around creating a pointless g element just so I can attach two matrices to it. That really was the most convenient way I found to create two matrices.
We can use matmulwrong to select one of two definitions for our own matmul function to multiply two matrices:
// matmul(A, B) computes AB
matmul = matmulwrong() ?
function(a, b) { return b.multiply(a) } :
function(a, b) { return a.multiply(b) }
Now we should only use matmul and avoid using SVGMatrix.multiply. Defining it like this means we decide once, when the JavaScript is loaded, and not every time that we call matmul. Notice how this simply tests whether SVGMatrix.multiply is swopped or not and acts accordingly; it doesn’t care whether you’re using Safari or Firefox, it’s more in the spirit of object detection, not browser sniffing. As soon as bug 16062 gets fixed in FirefoxSafari the code will detect it as being fixed. Life is good again and Curly Logo works on both browsers.
PS: Opera agrees with Firefox.
PPS: Guess which WordPress feature I used today that I thought I’d never find a genuine use for.
I finally got sick and tired of Firefox and knuckled down to make Curly Logo work on Safari. So now it does. Safari version 3.0.3 anyway (sorry, it really does need SVG so anything earlier is a no go). Let me know if you see anything that looks like a bug.
Getting it working on Safari just entailed smoothing over a few differences between Firefox and Safari:
I was looking for a way to create packaged versions of Curly Logo. For example it would be nice if you could create a version of Curly Logo that already has your favourite SQUARE and FATPEN procedures defined. One way would be to take the served pages (some XHTML and JavaScript) edit it them and host them yourself. How tedious.
Then I thought that Curly Logo could examine the URL, see if it contained a suitably encoded Logo program and execute the program if so. This is useful because «http://www.amberfrog.com/logo/», «http://www.amberfrog.com/logo/?foo», and «http://www.amberfrog.com/logo/#foo» are different URLs that happen to load the same resource. Because it’s exactly the same resource my server can serve cached copies, and in fact your browser can use the ETag header to not even bother getting the same object again. Wins all round.
So what Curly Logo does is decodeURI everything past the ‘#’ in its URL (available in «window.location») and execute it as Logo as if it was typed in. I call this technique URL scraping.
The pedagogic value for Curly Log is obvious. It means I can supply versions of Curly Logo that show a simple triangle being drawn, how to draw glasses on Ingrid Bergman, and draw rainbow-ripple star. All inside a (quite long) URL; no server change necessary. These custom versions of Curly Logo are bookmarkable and exchangeable (via e-mail, chat, and so on).
Aside: Firefox makes the turtle bug-eyed when I use a «#» in the URL. I have no idea why. Surely it’s a bug?
The advantage of URL scraping is that nothing changes on the server, so everyone benefits from caching and in some cases it would also open up the possibility of serving static HTML (as I do). There’s no reason that the JavaScript doing the scraping has to use the «#» part of the URL, it was just convenient for me. You could have a server side rewrite rule that maps /foo/red/ and /foo/blue/ to the same object (thereby still gaining the benefits of caching) and have the JavaScript sense the last directory component of the URL; it could pick a CSS theme using that value for example, meaning that different URLs give your users different themes on the same site, but the server transmits the same object in either case. The possibilities are endless.
Following on from my discovery of RFC 2397 I realised that we would be able to manipulate the “src” property of the “img” element in JavaScript and thereby change the image being displayed. The Base64 encoding is conveniently handled by JavaScript’s (non-standard but ubiquitous in the browser) btoa function (2008-05-10: ubiquitous apart from Opera, that is). I chose OS/2′s BMP image file format as being suitably simple to manipulate.
The result is BME (BitMap Editor). Note that all the work is done by client-side JavaScript, there’s no server side programming or communication at all (that would be madness!).
Bi-level any-colour-you-like-as-long-as-it’s-grey-and-blue at the moment. I suggest you right-click to save.
This use of RFC 2397 shows up some bugs and misfeatures of the OS X user interface. For example, dragging the image onto Mail.app opens a new mail message containing the contents of the URL as text rather than an image.
Curly Logo has a text area with a transparent background (maybe you haven’t noticed, but you can move the turtle “underneath” the purple text area and it is still visible, try «bk 333»). Support for colours with alpha channels (a CSS3 feature) was limited when I tried, so I ended up implementing this using a transparent 1×1 PNG which is repeated across the background.
That PNG file is 95 octets big. That’s no big deal, but the HTTP 1.1 headers that are transmitted before the file are about 400 octets. I’m paying to transmit the headers to you, and it takes time. Receiving the header takes 4 times as long as transmitting the file. Time is Money. [edit: 2007-11-16 I do pay to transmit headers, I was wrong when I said I didn't.]
If I could somehow bundle the PNG file inside the only file that uses it (it’s used in a CSS background-image property in an XHTML file) then you could avoid downloading the extra header. Win! This would be a win even if the bundled PNG was slightly larger. Even if the overall transmitted octet count was a bit higher it would probably be a win in elapsed time because we avoid having to do another HTTP round trip for the extra file (and on some browsers that might mean another TCP/IP connexion, so we save all that too). It turns out we can bundle the PNG file inside the CSS.
We use the apparently obscure “data” URL scheme from RFC 2397. It works by having URLs like this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgAQMAAADYVuV7AAAABlBMVEUAAAD///+l2Z/dAAAAIUlEQVQ4jWP4DwMMQDDKIZHDAAGjnFEO7TkMcDDKIZYDAAVlPd9Ahj+EAAAAAElFTkSuQmCC
(this example is actually a graphic from my earlier article on anti-aliasing, paste it into the location field of a browser to try it out)
“image/png” is optional but defaults to “text/plain” so you probably need to specify it for almost any practical application.
“;base64″ is also optional but if you don’t use it then you need to use the standard %xx URL encoding for non-ASCII octets. For binary data it’s probably saner to use “;base64″. Conceivably there might be binary files for which it was shorter to not use “;base64″.
The comma, “,”, is not optional.
So my CSS changes from:
background-image: url(ts.png);
to
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEXFAFxSw3SuAAAAAXRSTlNu6uyUOQAAAApJREFUCJljYAAAAAIAAfRxZKYAAAAASUVORK5CYII=);
Once I’ve gzip’d everything (which I used to not do, but is a big win for XML and JavaScript) I end up with an extra 19 octets. Which I pay for to store and transmit. So I’m 19 octets worse off, but you guys lose an entire header so you’re well over 300 octets better off plus an entire round-trip. How good is that?
Naturally RFC 2397 is implemented in Safari (3.0.3), Firefox, and Opera.
Now looking at the Base64 encoded version of the 1×1 PNG I can see that the PNG file is mostly overhead. Maybe I can get rid of some of those obviously unused header fields or chunks? Maybe there is some other image file format that would have less overhead for very tiny images (must be able to store at least 1 pixel to 8-bit precision for each of 4 channels). It’s 1-pixel GIFs all over again. Sorry.
Happily uuencode turns out to support Base64 (on OS X and Single Unix Specification).
(includes bugfix!)
#!/bin/sh
# $Id: //depot/prj/logoscript/master/code/dataurl#1 $
# Convert anything to a data URL.
# See http://www.ietf.org/rfc/rfc2397.txt
# Base64 is always used.
# dataurl [filename [mimetype]]
m="$2"
if test "$1" != "" && test "$2" == ""
then
case "x$1" in
*.png) m=image/png;;
*.gif) m=image/gif;;
esac
fi
if test "$1" = ""
then
uuencode -m foo
else
uuencode -m "$1" foo
fi |
{ echo data:"${m};base64," ; sed '1d;$d;' ; } | tr -d '
'
I didn’t know the length property on JavaScript functions was obscure.
Curly Logo uses the length property to decide the arity of its procedures.
Consider a Logo program like «fd prod 10 5». How does Logo know that it should evaluate (prod 10 5) producing 50, and then evaluate (fd 50)? Consider the similarly shaped program «prod minus 10 5»; this evaluates (minus 10) first, to produce -10, then evaluates (prod -10 5) to produce -50. The evaluation of Logo is directed by the arity of the operators.
Logo knows that “prod” takes 2 inputs and that “minus” takes 1 input, so it doesn’t evaluate a call to “prod” until there are 2 inputs to consume.
Curly Logo implements “prod” as a JavaScript function that takes 2 arguments. The execution of Curly Logo proceeds by using the length property of the “prod” JavaScript function to decide how many inputs it requires. Curly Logo has a magic “javascript” command which adds a javascript button. Now you can type either Logo or JavaScript and have it evaluated using the appropriate button. Evaluating «logo.global.prod.length» as JavaScript will yield 2, «logo.global.fd.length»
yields 1 (all of Logo’s globals are stored in the logo.global JavaScript object). This feature allows built-in Curly Logo procedures to be implemented as natural JavaScript functions. I suppose Apple would call it a Curly Logo JavaScript bridge.
In fact “prod” can be coerced into taking any number of arguments by using Lisp style calling syntax, «(prod 1 2 3 4) ⇒ 24». This is a standard Logo feature and not special to Curly Logo.
JavaScript can be used to “peek under the hood”, once you’ve turned the javascript button on you can use it to inspect the implementation of “prod”: «logo.global.prod ⇒ function (multiplicand, multiplier) {
var a = 1, i;
for (i = 0; i < arguments.length; ++i) {
a *= arguments[i];
}
return a;
}».
Consider the following Logo program:
home rt 43 fd 100
In Curly Logo this draws a lovely anti-aliased line from the turtle’s home position to some point between 2 and 3 o’clock (there’s nothing special about the angle of 43 degrees that I chose, it’s arbitrary).
Now, if I execute this again:
home rt 43 fd 100
Then I should get exactly the same line drawn so the display should not change. What actually happens is that the line gets a bit thicker, a bit bolder. On the left is the original line, on the right is the same line drawn 3 times in total:

Notice how the line on the right is thicker.
What’s going on is that the edges of the line (which is notionally 2 pixels wide in these examples) are anti-aliased. When the line is considered as a narrow rectangle (drawn at an angle), pixels near the edge will overlap the rectangle partially. Obviously we can’t draw a partially filled pixel on the display, so instead we approximate the situation by assigning an intermediate colour value to pixels on the edge. The more of the rectangle they overlap the darker they should be.

Here I show how the rectangle is drawn, I’ve blown the pixels up to giant size and overdrawn in red an approximation to the ideal line shape that is being drawn (which has a semi-circular endcap because we use the SVG stroke-linecap=’round’ attribute). I might not have aligned the red rectangle exactly, but you get the idea.
How are these grey pixels written onto the display? Because they represent a partially filled pixel it would be incorrect to simply overwrite the existing screen pixel with the incoming grey pixel. Imagine we were drawing on a green background, a pixel from the edge of the black line that only just touches the black line will get a very light grey value assigned to it, when drawn on the green background the result should be mostly green and a little bit grey.
Porter–Duff compositing is used. This technique is outlined in a seminal paper [Porter1984] normally kept in an ACM prison but freed by Keith Packard. What it amounts to is pretty simple: choose a value of α (alpha) for each pixel that represents coverage (how much of the pixel is covered by the black line) and changing the background pixel B to be B×(1-α) + α×A, where A is the colour of the drawn object (black in our example). What happens on the screen is that the pixel colour moves towards A.
Choosing the blend amount, α, is something that needs to be done billions of times a second and is part of a fascinating multi-disciplinary area of computer science that involves graphics, the physics of light, the engineering of displays, numerical approximations, convolutions, optimisation in hardware and software, and human visual psychology. Don’t talk to me about gamma.
If we draw the same anti-aliased line over and over:
repeat 300 [ home rt 43 fd 100 ]

what happens is that we end up with a big fat ugly jaggy line. Any pixel that overlapped the narrow rectangle at all has been drawn into enough times that it eventually becomes all black. There are only black or white pixels in the resulting image, no intermediate greys. It’s a parody of 1981.
This happens because the screen pixel doesn’t know that it was drawn into because it was just part of the edge of the rectangle, and it doesn’t know that exactly the same part of the rectangle is being drawn again. It would be correct to not change any of the screen pixel values the second time the line is drawn, but none of the pixels store any geometry information so they can’t tell.
There are quite a few approaches to improve the situation. The most obviously authentic approach would be to store all displayed images as polygonal geometry, clip polygons based on their z-value, and compute a colour for each pixel based on the frontmost visible polygons that intersect that pixel. Bonus points for handling translucency.
A more pragmatic approach is to use sub-pixels. For each screen pixel instead of storing just one colour, store 4 (say). We can imagine splitting the pixel into 4 sub-pixels and storing a colour that represents the colour of the sub-pixel at its centre. The colour of the screen pixel is a function of the colours of its 4 sub-pixels (for example, the average of its 4 sub-pixels, but it could be any function really).
How does this improve things? It looks like we’re paying to store and compute all these extra sub-pixels and then throwing most of them away!
Consider our anti-aliased line again. Now we are drawing into the sub-pixels, not the screen pixels directly. When we draw the line over and over again the individual sub-pixels will get saturated with black, but a pixel near the edge may have only some of its sub-pixels as fully black and some white. The result will be that pixels near the edge of the rectangle will assume one of 5 values according to how many of its sub-pixels are black (0 to 4), so the line will be always look a bit anti-aliased. We can simulate this by drawing everything at a larger scale and rescaling:

-> 
In fact we don’t have to have 4 sub-pixels, we can have any number we like, and we don’t have assign the sub-pixels to be the centres of symmetric squares within the pixel, we can put the points corresponding to the sub-pixels wherever we like (you could even assign the positions randomly, but that would be madness, a straight swop of aliases for noise). When computing the screen pixel from its sub-pixels the function need not be symmetric over the sub-pixels, some sub-pixels could be assigned more weight than others. This may lead to further improvements in our example because fully saturated sub-pixels could give rise to more than 5 different values of screen pixel. Taking this any further requires more sampling theory than I know.
References
[Porter1984] “Compositing Digital Images”; T. Porter & T. Duff; Computer Graphics Volume 18, Number 3 July 1984 pp 253-259.