Monday, February 15, 2010

Processing.js – Some bits for 0.6 in time for midterm season

The Foundations of the Universe are based upon certain Truths, like: as the time to March break/reading week approaches zero, the frequency of exams and due dates sky rocket. Coincidence? There's got to be a formal proof somewhere on the Internet...

But before the coming crunch time gets real bad, is 0.6! From a developer's standpoint, the big improvement for 0.6 is unit testing. Now, just testing return values no longer requires cobbling together a full Processing program, and the tests may be more easily reused and modified by other developers. Yes, this means “pretty pictures" will appear far less frequently now., but on the whole is that really a bad thing? (Using canvas and Processing just to spit out numbers and letters doesn't do justice to either.)

char(), float(), and str()

First up: enhancing a trio of conversion functions. They may now handle the range of primitive type and array arguments they are supposed to.

While the functions themselves don't do anything particularly remarkable, their behaviour helped uncover a bug in Pjs. When user code is parsed, Pjs converts chars into numbers. The relevant code is inside the Processing.parse() function:
// Force characters-as-bytes to work.
aCode = aCode.replace(/('(.){1}')/g, "$1.charCodeAt(0)");


The parser finds single characters flanked by single quotation marks and calls charCodeAt() on those characters. What this means is overloading Pjs functions to handle both arguments of type Number and characters (essentially one-character Strings in JavaScript) becomes... difficult.

Take str('A'). This should return the string “A". But because of the parser what actually gets processed is str(65) (the number 65), returning the string “65". Without jumping additional hoops, you can't tell str() whether that 65 is supposed to be a number 65, or if you actually mean that 65 to be representative of the char 'A'.

This causes some str() tests to fail. char() tests are affected although they all pass. For example:
int i = 65;
_checkEqual('A', char(i));

This is evaluated as _checkEqual(65,65), not _checkEqual('A', 'A'). The parser's fudging is masked by the passing tests.

I've filed a ticket with the suggestion that the parser not convert chars to Numbers, and leave functions to do this by themselves. With unit testing now rolling it'll be easier to find which functions rely on the parser's current behaviour. I may very well pick up the ticket for 0.7.

normal()

normal() takes three numeric arguments representing a vector and saves them to global variables. Oh, and it changes a flag. All of these (variables and flag) are supposedly used by other functions, but none of those uses have been implemented yet. (“What came first, normal() or the code that uses normal()?")

Since normal() has no return value, the unit tests content themselves with checking the correct number and type of arguments are present.

smooth()/noSmooth()

char(), float(), str(), and normal() are the good news. Alas, smooth() and noSmooth() fall somewhat short of that mark and probably won't appear in 0.6.

smooth() and noSmooth() are intended to toggle anti-aliasing on and off when painting. Canvas has no built in facility for this. sephr found a Mozilla-only CSS property image-rendering applicable to the canvas tag, and perhaps able to achieve what was desired.

Unfortunately, while image-rendering is good for raster images it doesn't work the same magic on canvas drawings. For the time being, it seems smooth() and noSmooth() will go into hibernation.

Sunday, February 7, 2010

Processing.js - It's a long way to 0.6

“But my heart's right there", or so the song goes. Indeed, it looks like my work is laid out for me. So for this short update, I'll just list what I hope to get done for February 19th (in no particular order):
  • Port normal() (Ticket)
  • Complete porting smooth() and noSmooth() (Ticket)
  • Upgrade char(), float(), str() to accept a multitude of argument types (Ticket)
This will also be the first release where we'll be using automated tests! I wonder if I still have Minefield stashed away somewhere...

Friday, February 5, 2010

Processing.js – int() and Release 0.5

int(), the late passenger

A long time ago, in the forest across the river, where fiery leaves danced upon the crisp winds of pseudo-winter (or in other words: back in the 0.2 release) I finished porting boolean(), a function that converted primitive types to either true or false, over to Processing.js (Pjs). As it transpires, boolean() was just one a gaggle of conversion functions, many which continue to seek the company of a code monkey willing to give them a boost over the wall from Java-land into JavaScript-land.

Yesterday evening, at the behest of The Powers That Be, and against the questionable judgement of my lazy self, I tentatively picked up the rest of these converters. And as I told Anna, the recently promoted Fearless Leader, I'd try to get one of them done for 0.5, whose deadline is today. So, without further ado, I present to you int() for Pjs.

Who wants to write the thousand words?

Lo, see now int() in action in Pjs, and compare it to how the same code renders in Processing:



Your eyes do not deceive you: Pjs' int() fails a test. But don't break out the torches and pitchforks just yet! There's a good reason for this. int() may take a byte or an array of bytes as an argument. In Processing, a byte may have a value from -128 to 127, but more importantly: byte is a static type. Through overloading this allows Processing methods, written in Java, to behave differently to accommodate different variable types.

Things are not so simple in JavaScript. In Pjs a Processing byte and int gets converted into a JavaScript 'number'; effectively there is no distinction between a byte and an int in Pjs. Since there's no distinction, int() cannot be tailored to behave differently when it receives bytes. (floats and doubles are different since you can always check if there's a decimal point in there somewhere.) Therefore, the test fails.

A possible solution may be to add a second parameter to int(), a flag called 'isByte' or something. That might be something to bring up in next week's telephone conference.

int() links



A Quick Recap of 0.5
Just for the record, here are the links to the rest of the stuff I did for 0.5:



I'll be making a (hopefully) shorter post soonish outlining what I hope to accomplish for 0.6. But for now, it's time to switch gears and call it a morning.

Tuesday, February 2, 2010

Processing.js – nf()

Closer to release 0.5

With a little luck, this should be my the last piece for the 0.5 release of Processing.js (Pjs) . The nf() function should now be able to handle arrays of numbers to be formatted, and float formatting.

There's a few interesting things going on here that the Processing documentation doesn't allude to, but those are more easily revealed once we see the code in action.

A few pixels

Here's the first batch of tests in Pjs (hah, there's no way I'm trying to minify that for the post!) and here's what Processing generates for the same code:



And here's the second batch of tests (arrays) in Pjs, and here's what Processing generates for the same code:



Note the tests use String::equals() which I recently completed and is not yet in the public release.

Also, while the documentation says all arguments should be positive integers, Processing's nf() does handle arguments with values zero or less. So I've coded Pjs' version to do the same.

It's supposed to do that? behaviour.

There are two weirder-than-normal things going on.

In the tests 19 to 32 in the first batch you'll find that depending on whether the one's digit is odd or even, the 'rounding' is different. This required a bit of extra code to replicate.

In the second batch, nf() processes values in the int array “incorrectly"; running through the ints individually results in the expected results. Strangely enough, my code was able to replicate this behaviour right off the bat.http://wobblyretroaction.blogspot.com/2010/01/processingjs-stringequals-or-how-i.html

Links