-
Notifications
You must be signed in to change notification settings - Fork 14
Blank Canvas JavaScript
Blank Canvas can be used to generate JavaScript for use outside the direct interaction. We try share generated code idioms between the server/client model, and the stand alone model.
Definition | Meaning |
---|---|
Client-side | Code executing a JavaScript engine |
Server-side | Code executing on a Haskell process |
Generator-side | Part of the code-generation phase |
Offline | Client-side + pre-generated code |
Online | Client-side + Server-side together |
So, we have two modes, Online, where the code is generated on the fly, and Offline, where we pre-compute blocks of JavaScript. We have to be careful, so that the blocks of code cooperate within there own mode.
As a top-level concern, we generate code of the form:
"function(bc) { .. } "
bc is a JavaScript object that contains the following values.
Arrays:
- canvas[] -- The are all the available contexts, contexts[0] is the default/start
- images[] --
- gradients --
- patterns --
Q: how do we allocate the specific elements? Client (dynamic) or Server (static)?
bc also contains the following methods
- getImage(String url, Function k) { .. }
k
, the last argument, is the continuation.
Most code is straight line. For example
...
moveTo(100,200)
...
Translates to
function(bc) { ...; bc.canvas[0].moveTo(100,200); ... }
The interesting things happen when the BlankCanvas API has a non-() return value.
There are two cases, client-side things, and generator/server-side things.
Consider createLinearGradient
CanvasGradient createLinearGradient(...)
Because CanvasGradient is abstract, we can use it as a handle into the gradients
array in bc, and allocate the location at code generation time. (Hmm, this assumes non-reentrancy)
Consider isPointInPath
boolean isPointInPath(float x, float y)
This is a computation that must be performed on the client, and:
- In Online mode, the reply that must be returned to the server; and
- In Offline mode, the reply must be passed somehow to the next command (which is an open-ish problem.)
For online-generated code, methods like isPointInPath
will always be last.
Q: how will the result be communicated? Via a continuation? Via a return (this would not allow having built-in delays for things like loading images.)
It is not directly possible to generate isPointInPath
in Offline specific mode.
(About the handle/control flow version, that does allow it)
function(bc,k) { ...; return k(bc.canvas[0].isPointOnPath()); }
Images are tricky. They take time to load, and you might want to do other things while waiting. Blank Canvas has the simple "wait till loaded" model. We can improve on this in various ways. For now, we continue to wait for the result.
// Client-side allocation
function(bc,k) {
...;
var img = new Image(...);
ix = bc.images.push(img);
img.onload = function() { k(ix); }
}
// Server-side allocation; can do things after the allocation
function(bc,k) {
...;
var img = new Image(...);
var ix = <<PREALLOCATED LOCATION>>;
bc.images[ix] = img;
img.onload = function() {
// ix is in scope, and can be used
...
((Code AFTER newImage))
}