commit ed6c91fe87a5316e691af991c4a1d551ee334d65
parent 6f9bd88894ebf146a8a1af7728545026aa3a5153
Author: tomas <tomas@logand.com>
Date:   Sat, 23 Jan 2010 14:48:41 +0100
Changes from 2009-06-30
Diffstat:
| M | index.org |  |  | 1895 | ++++++++++++++++++++++++++++++++++++------------------------------------------- | 
1 file changed, 869 insertions(+), 1026 deletions(-)
diff --git a/index.org b/index.org
@@ -1,285 +1,565 @@
-* Postscript interpreter
+#+options: author:nil num:nil creator:nil timestamp:nil
 
-- S :: stack
-- F :: function dictionary
+PostScript and PDF interpreter in JavaScript
+
+PostWeb \\
+WebScript
+
+TODO reuse parsed wps.wps
+
+QQQ
+
+Everything is interpreted.  Compilation is translation to lower
+abstraction level or precomputing.
+
+psi/z-matrix.c
+Resource/Init/opdfread.ps
+
+* PostScript interpreter
+
+- stack
+- function dictionary
+- data types
+- reader
+- interpreter/evaluator
+- native bindings (JavaScript FFI)
+- PostScript and PDF API
+
+PDF is stateless?
+
+PostScript is stateful?
+
+#+begin_html
+<style>
+tt {background-color:#fdf}
+canvas {width:12em;height:12em;border:1px dashed black}
+/*canvas {width:10em;height:10em;border:1px dashed black;position:relative;top:0;left:0}*/
+</style>
+#+end_html
+
+#+html: <div id="wps" style="display:none">
+#+include "wps.wps" src text
+#+html: </div>
+#+begin_html
+<script type="text/javascript" src="wps.js"></script>
+<script>
+function $(Id) {return document.getElementById(Id);}
+function $$(Id) {return $(Id).textContent;}
+</script>
+#+end_html
 
 ** Trivial example
 
+#+html: <div id="example1">
+#+begin_src js2
+function example1() {
+   // define stack and operators
+   var Os = [];
+   var Sd = {};
+   var Ds = [Sd];
+   Sd["+"] = function() {Os.push(Os.pop() + Os.pop());};
+   Sd["="] = function() {alert(Os.pop());};
+   // compute 1 2 = 3 + =
+   Os.push(1);
+   Os.push(2);
+   Sd["="]();
+   Os.push(3);
+   Sd["+"]();
+   Sd["="]();
+}
+#+end_src
+#+html: </div>
 #+begin_html
 <script>
 function ex1() {
-   var S = [];
-   var F = {};
-   F["+"] = function() {S.push(S.pop() + S.pop());};
-   F["."] = function() {alert(S.pop());};
-
-   S.push(1);
-   S.push(2);
-   F["."]();
-   S.push(2);
-   F["+"]();
-   F["."]();
+   eval($$("example1"));
+   example1();
 }
 </script>
 <button onclick="javascript:ex1()">Eval</button>
-"<tt>1 2 . 2 + .</tt>" from stack
+"<tt>1 2 = 3 + =</tt>" from harcoded stack
 #+end_html
 
-** Example with simple reader
-
+** Example with PostScript reader
+
+#+html: <div id="example2">
+#+begin_src js2
+function example2(T) {
+   var Os = [];
+   var Sd = {};
+   var Ds = [Sd];
+   var Es = [];
+   Sd["+"] = function() {Os.push(Os.pop() + Os.pop());};
+   Sd["dup"] = function() {var X = Os.pop(); Os.push(X); Os.push(X);};
+   Sd["="] = function() {alert(Os.pop());};
+   ps0(T, Os, Ds, Es); // read and interpret code T
+}
+#+end_src
+#+html: </div>
 #+begin_html
 <script>
-function PdfT(V) {
-   this.V = V;
-   return this;
-}
-function isPdfT(V) {
-   return V.constructor == PdfT; // TODO better test
+function ex2() {
+   eval($$("example2"));
+   example2($$("ex2"));
 }
+</script>
+<button onclick="javascript:ex2()">Eval</button>
+"<tt id="ex2">12 34 + dup = 56 + =</tt>" from string
+#+end_html
 
-function ps(L, F, S) {
-   var N = L.length;
-   var I = 0;
-   if(!S) S = [];
-
-   function member(C, L) {return 0 <= L.indexOf(C);}
-   function peek() {return I < N && L[I];}
-   function char() {return I < N && L[I++];}
-   function skip() {while(I < N && member(L[I], " \t\n")) I++;}
-
-   function comment() {
-      while("%" == peek()) {
-         while(peek() && "\n" != peek())
-            char();
-         skip();
-      }
-   }
-
-   function text() {
-      char();
-      var L = [];
-      var N = 1;
-      while(0 < N && peek()) {
-         var C = char();
-         switch(C) {
-            case "(":
-               N++;
-               break;
-            case ")":
-               N--;
-               if(N <= 0) C = false;
-               break;
-            case "\\":
-               C = char();
-               switch(C) {
-                  case "(": break;
-                  case ")": break;
-                  case "\\": break;
-                  case "n": C = "\n"; break;
-                  case "r": C = "\r"; break;
-                  case "t": C = "\t"; break;
-                  default:
-                     C = false;
-               }
-               break;
-         }
-         if(C !== false) L.push(C);
-      }
-      return new PdfT(L.join(""));
-   }
-
-   function symbol() {
-      var C = char();
-      var N = member(C, "+-0123456789.");
-      var F = "." == C;
-      var L = [C];
-      while(peek() && !member(peek(), "%/[]{}<>( \t\n")) {
-         C = char();
-         L.push(C);
-         if(N && !member(C, "0123456789")) {
-            if(!F && "." == C) F = true;
-            else N = false;
-         }
-      }
-      L = L.join("");
-      if(1 == L.length && member(L, "+-.")) N = false;      
-      return N ? (F ? parseFloat(L) : parseInt(L, 10)) : L;
-   }
-
-   function code() {
-      char();
-      var L = [];
-      while(peek()) {
-         var T = token();
-         if("}" == T) break;
-         if(T || T == 0) L.push(T);
-      }
-      return L;
-   }
-
-   function token() {
-      skip();
-      switch(peek()) {
-         case false: return undefined;
-         case "%": return comment();
-         case "[": return char();
-         case "]": return char();
-         case "{": return code();
-         case "}": return char();
-         case "(": return text();
-         default: return symbol();
-      }
-   }
-
-//   function quoted(T) {
-//      return typeof T == "string" && "/" == T.charAt(0);
-//   }
-
-   function parse(E) {
-      var G = true;
-      while(G && peek()) {
-         var T = token();
-         if(T || T == 0) {
-            if(typeof T == "number" || typeof T == "object" || quoted(T))
-               S.push(T);
-            else {
-               if(F[T]) F[T]();
-               else throw "Unknown operator '" + T + "' " + typeof T;
-               if(E == T) G = false;
-            }
-         }
-      }
-      return S;
-   }
-
-   return parse();
-}
+** Example with recursion
+
+#+html: <div id="example3">
+#+begin_src ps
+% based on the example from
+% http://en.literateprograms.org/Fibonacci_numbers_(PostScript)
+% 0, 1, 1, 2, 3, 5, 8, 13, 21
+
+%0.1 1.2 2.3 4.5 3 {pstack} repeat
+%0.1 1.2 2.3 4.5 3 {pstack} .repeat
+
+%/fibonacci{0.1 1.2 2.3 4.5 pstack 3{pstack}repeat pstack}def
+%fibonacci
+
+%/fibonacci{0.1 1.2 2.3 4.5 3{1 add pstack}repeat}def
+%fibonacci
+
+%0 1 1 4 {add} for pstack clear % 10
+%1 2 6 { } for pstack clear % 1 3 5
+%3 -.5 1 { } for pstack clear % 3.0 2.5 2.0 1.5 1.0
+
+4 {(abc)} repeat pstack clear % (abc) (abc) (abc) (abc)
+1 2 3 4 3 {pop} repeat pstack clear % 1 % Pops 3 values (down to the 1)
+4 { } repeat pstack clear % % Does nothing four times
+mark 0 {(will not happen)} repeat pstack clear % mark
+
+%false false or =
+%true false or =
+%false true or =
+%true true or =
+
+% from http://www.math.ubc.ca/~cass/graphics/manual/pdf/ch9.pdf
+
+/factorial { 1 dict begin
+  /n exch def
+  n 0 eq {
+    1
+  }{
+    n n 1 sub factorial mul
+  } ifelse
+end } def
+
+%5 factorial pstack clear
+
+% args: array a of numbers
+% effect: sorts the array in order
+/bubblesort { 4 dict begin
+  /a exch def
+  /n a length 1 sub def
+n 0 gt {
+  % at this point only the n+1 items in the bottom of a remain to be sorted
+  % the largest item in that block is to be moved up into position n
+  n {
+    0 1 n 1 sub {
+      /i exch def
+      a i get a i 1 add get gt {
+         % if a[i] > a[i+1] swap a[i] and a[i+1]
+        a i 1 add
+        a i get
+        a i a i 1 add get
+         % set new a[i] = old a[i+1]
+        put
+         % set new a[i+1] = old a[i]
+        put
+      } if
+    } for
+    /n n 1 sub def
+  } repeat
+} if
+end } def
+
+%[5 4 3 2 1 0] bubblesort pstack clear
+
+%{1 2 add {2 mul}} pstack exec pstack exec pstack clear
+
+%1 2 1 {add {(hi)} dup} repeat pstack clear
+%1 2 {} pstack clear
+%1 2 {} exec pstack clear
+
+%(de repeat (N . B)
+%   (when (gt0 N)
+%      (run B 1) )
+%   (when (< 1 N)
+%      (repeat (- N 1) B) ) )
+
+%/fibonacci { % n --
+%  1 sub
+%  1 1 3 2 roll
+%  { 2 copy add 3 2 roll pop pstack} repeat
+%} bind def
+
+%0 fibonacci = % 0
+%1 fibonacci = % 1
+%2 fibonacci = % 1
+%6 fibonacci = % 8
+
+
+% http://en.wikibooks.org/wiki/Transwiki:Fibonacci_number_program#PostScript
+
+%/fib1 {
+%  1 dup
+%  3 -1 roll {
+%    dup
+%    3 -1 roll
+%    dup
+%    4 1 roll
+%    add
+%    3 -1 roll
+%  } repeat
+%} def
+
+%5 fib1 pstack clear
+
+/fib2 {
+  dup dup 1 eq exch 0 eq or not {
+    dup 1 sub fib2
+    exch 2 sub fib2
+    add
+  } if
+} def
 
-function quoted(T) {
-   return typeof T == "string" && "/" == T.charAt(0);
-}
+%5 fib2 pstack clear
 
+#+end_src
+#+html: </div>
+#+begin_html
+<script>
+function ex3() {wps(null, [$$("wps"), $$("example3")]);}
+</script>
+<button onclick="javascript:ex3();">Eval</button>
+#+end_html
 
+* The interpreter
+
+A few initial ideas:
+
+- Learn and implement a Forth like language.  PostScript seems a great choice:
+  - It has the right syntax and stack based evaluation.
+  - It is practical and widely used.
+  - It has long sucessful history in print and publishing.
+  - It is a predecessor of PDF.
+  - Almost everything (e.g. editors, pictures, documentation) can be
+    reused to a great extent.
+  - It is ideal for HTML 5 canvas experiments because from the
+    PostScript point of view, canvas is just another low level device.
+- Flexibility and simplicity first.
+  - Optimize for fast change, not for raw running speed.  Keep the
+    code small and regular if possible.
+  - Can JavaScript be used as a portable assembler for web?  Is
+    building scripting languages on top of JavaScript feasible and
+    efficient enough for real-world use?  If not, why?  Find the
+    limits.
+- Keep the language/environment specific core as small as possible.
+  - Allow to port the interpreter to other languages on both
+    client and server side.
+  - Be open for the possibility of running "the same code" on both the
+    client and server side.
+- Can PDF documents be displayed in web browsers without server-side
+  image rendering?
+  - Implement a canvas based version of PDF page contents in [[http://ondoc.logand.com][OnDoc]].
+- Investigate the possibility of implementing a Lisp interpreter
+  suitable for production use in web applications.
+
+Operators beginning with dot are non-standard low level operators
+which are subject to change.
+
+** PostScript data types
+
+| category  | type        | executable | example                | spec               |
+|-----------+-------------+------------+------------------------+--------------------|
+| simple    | boolean     |            | true false             |                    |
+|           | fontID      |            |                        |                    |
+|           | integer     |            | 42 -123 0              |                    |
+|           | mark        |            |                        |                    |
+|           | name        | Y          | draw /draw             |                    |
+|           | null        |            | null                   |                    |
+|           | operator    | Y          |                        |                    |
+|           | real        |            | 3.14 1e-10             |                    |
+|           | save        |            |                        |                    |
+| composite | array       | Y          | [1 /hi 3.14] {1 2 add} |                    |
+|           | condition   |            |                        | Display PostScript |
+|           | dictionary  |            | <</a 1/b 2>>           |                    |
+|           | file        |            |                        |                    |
+|           | gstate      |            |                        | Level 2            |
+|           | lock        |            |                        | Display PostScript |
+|           | packedarray |            |                        | Level 2            |
+|           | string      | Y          | (hi) <a33f>            |                    |
+
+** Low level data types
+
+| category  | type       | direct | literal | executable |
+|-----------+------------+--------+---------+------------|
+| simple    | boolean    | Y      | Y       | -          |
+|           | number     | Y      | Y       | -          |
+|           | mark       | -      | Y       | -          |
+|           | name       | -      | Y       | Y          |
+|           | null       | Y      | Y       | -          |
+|           | operator   | Y      | -       | Y          |
+| composite | array      | Y      | Y       | -          |
+|           | proc       | -      | -       | Y          |
+|           | dictionary | Y      | Y       | -          |
+|           | string     | Y      | Y       | -          |
+
+All types are represented directly in JavaScript except:
+
+| type            | representation  |
+|-----------------+-----------------|
+| mark            | unique object   |
+| literal name    | quoted symbol   |
+| executable name | unquoted symbol |
+| operator        | function        |
+| proc            | quoted array    |
+
+*** exec
+
+pop any, case:
+
+| type            | result            |
+|-----------------+-------------------|
+| executable name | exec value        |
+| operator        | apply operator    |
+| proc            | exec each element |
+
+otherwise push the original value
+
+*** cvx
+
+| from         | to              | how     |
+|--------------+-----------------+---------|
+| literal name | executable name | unquote |
+| array        | proc            | quote   |
+| string       | proc            | ~ parse |
+
+** Stack
+
+
+
+* Drawing with PostScript
+
+Measuring angles:
+
+| language/device | unit |
+|-----------------+------|
+| canvas          | rad  |
+| PostScript      | deg  |
+| PDF             | rad  |
+
+** Bowtie example
+
+#+html: <canvas id="xbowtie"></canvas>
+#+html: <div id="bowtie">
+#+include "bowtie.wps" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xbowtie"), [$$("wps"), $$("bowtie")]);
+</script>
+#+end_html
 
-var Msie = 0 < window.navigator.userAgent.indexOf("MSIE"); // :-(
-if(!Msie && !HTMLElement.prototype.innerText) {
-   HTMLElement.prototype.__defineGetter__("innerText",
-      function () {return(this.textContent);});
-   HTMLElement.prototype.__defineSetter__("innerText",
-     function(V) {this.textContent = V;});
-}
+** Digital clock example
 
-function ex2() {
-   var S = [];
-   var F = {};
-   F["+"] = function() {S.push(S.pop() + S.pop());};
-   F["dup"] = function() {var X = S.pop(); S.push(X); S.push(X);};
-   F["."] = function() {alert(S.pop());};
-   ps(document.getElementById("ex2").innerText, F, S);
-}
+#+html: <canvas id="xclock"></canvas>
+#+html: <div id="clock">
+#+include "clock.wps" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xclock"), [$$("wps"), $$("clock")]);
+</script>
+#+end_html
+
+** Analog clock example
+
+#+html: <canvas id="xclock2"></canvas>
+
+Click on the clock to start/stop it.
+
+#+html: <div id="clock2">
+#+include "clock2.wps" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xclock2"), [$$("wps"), $$("clock2")]);
 </script>
-<button onclick="javascript:ex2()">Eval</button>
-"<tt id="ex2">12 34 + dup . 56 + .</tt>" from string
 #+end_html
 
-#+begin_src text
-{ /category (COOKING) }
+** Tiger example
 
-: sum
-1 2 + ;
+Text drawing in canvas is not working in Firefox and Opera, works in
+Chrome.
 
-1 (sdfsdf) /Tf
+Firefox throws error about linecap and linejoin not being supported.
+However, it does not throw error about missing support for text
+drawing.
 
-12 34 (cooking is fun) /Tf
+#+plot: title:"tiger.eps drawing times" ind:1 deps:(2) type:2d with:histograms set:"yrange [0:]" set:"xlabel 'browser'" set:"ylabel 'time [s]'" set:"style histogram gap 1" file:"tiger.png" set:"term png size 400, 300"
+| browser | time [s] |
+|---------+----------|
+| Chrome  |      3.8 |
+| Opera   |     13.4 |
+| Firefox |     19.5 |
 
-{ /key (value) }
-#+end_src
+file:tiger.png
 
-* PDF drawing
+** Fern example
 
+from http://www.pvv.ntnu.no/~andersr/fractal/PostScript.html
 
-#+html: <div id="wps">
-#+include "wps.wps" src ps
+#+html: <canvas id="xfern"></canvas>
+
+#+html: <div id="fern">
+#+include "fern.wps" src ps
 #+html: </div>
+#+begin_html
+<script>
+//wps($("xfern"), [$$("wps"), $$("fern")]);
+</script>
+#+end_html
 
-#+html: <div id="bowtie">
-#+include "bowtie.wps" src ps
+** Tree example
+
+from http://www.pvv.ntnu.no/~andersr/fractal/PostScript.html
+
+#+html: <canvas id="xtree2"></canvas>
+
+#+html: <div id="tree2">
+#+include "tree2.ps" src ps
 #+html: </div>
+#+begin_html
+<script>
+//wps($("xtree2"), [$$("wps"), $$("tree2")]);
+</script>
+#+end_html
 
+** Other
 
+1 0 0 0 setcmykcolor    % 100% cyan \\
+0 0 1 0 setcmykcolor    % 100% yellow
 
+** Fill example
 
+#+html: <canvas id="xfill"></canvas>
+#+html: <div id="fill">
+#+include "fill.wps" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xfill"), [$$("wps"), $$("fill")]);
+</script>
+#+end_html
+
+** Chessboard example
 
+#+html: <canvas id="xchess"></canvas>
+#+html: <div id="chess">
+#+include "chess.eps" src ps
+#+html: </div>
 #+begin_html
-<pre id="ex3x">
-1 2.3 + -5.6 + .
-</pre>
-<pre id="ex3">
+<div id="ychess" style="display:none">
+0 0 180 180 .gbox
+%1 0 0 -1 0 180 cm
+</div>
+<script>
+wps($("xchess"), [$$("wps"), $$("ychess"), $$("chess")]);
+</script>
+#+end_html
 
-%%% ps operators
+* Drawing with PDF
 
-/setlinewidth {/lineWidth gput} def
+PDF documents have the origin of the coordinate system in the bottom
+left corner while HTML 5 canvas int the top left corner.  Thus, some
+of the following pictures are displayed upside down (unless an
+explicit coordinate transformation was added which is not part of the
+visible example code).
 
-/setlinecap {/lineCap gput} def
+** Heart example
 
-/setlinejoin {/lineJoin gput} def
+#+html: <canvas id="xheart"></canvas>
+#+html: <div id="heart">
+#+include "heart.wpdf" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xheart"), [$$("wps"), $$("heart")]);
+</script>
+#+end_html
 
-/setmiterlimit {/miterLimit gput} def
+** Rectangle example
 
-/setgray {255 mul dup dup rgb /fillStyle gput} def
+#+html: <canvas id="xrect"></canvas>
+#+html: <div id="rect">
+#+include "rect.wpdf" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xrect"), [$$("wps"), $$("rect")]);
+</script>
+#+end_html
 
-%%% examples
+** Triangles example
 
-1 0 0 -1 0 446 cm % 0,0 in bottom left corner
+#+html: <canvas id="xtriangles"></canvas>
+#+html: <div id="triangles">
+#+include "triangles.wpdf" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xtriangles"), [$$("wps"), $$("triangles")]);
+</script>
+#+end_html
 
-% E1
+** Smile example
 
-q
-0 0 m 0 0 150 150 re f
-q
-0 150 255 rg
-0 0 m 15 15 120 120 re f
-q
-255 255 255 rg
-%0.5 alpha
-0 0 m 30 30 90 90 re f
-Q
-0 0 m 45 45 60 60 re f
-Q
-0 0 m 60 60 30 30 re f
-Q
+#+html: <canvas id="xsmile"></canvas>
+#+html: <div id="smile">
+#+include "smile.wpdf" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xsmile"), [$$("wps"), $$("smile")]);
+</script>
+#+end_html
 
-% E2
+** Star example
 
-q
-255 0 0 rg
-0 0 m 10 10 55 50 re f
-0 0 200 rg
-0 0 m 30 30 55 50 re f
-Q
+#+html: <canvas id="xstar"></canvas>
+#+html: <div id="star">
+#+include "star.wpdf" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xstar"), [$$("wps"), $$("star")]);
+</script>
+#+end_html
 
-% E3
+** Squares 2 example
 
-q
-1 0 0 -1 50 200 cm
-0 0 0 rg
-%BT
-(serif) 24 Tf
-%1 0 0 1 260 254
-(Hello World) Tj
-%ET
-Q
+#+html: <canvas id="xsquares2"></canvas>
+#+html: <div id="squares2">
+#+include "squares2.wpdf" src ps
+#+html: </div>
+#+begin_html
+<script>
+wps($("xsquares2"), [$$("wps"), $$("squares2")]);
+</script>
+#+end_html
 
-q
-0 0 255 rg
-4 0 0 4 315 204 cm
-  0 5.5 m
--4 -5.5 l
- 6 1    l
--6 1    l
- 4 -5.5 l
-f
-Q
+** Junk
+
+#+begin_html
+<pre>
+
+1 0 0 -1 0 446 cm % 0,0 in bottom left corner
 
 % Ex4
 
@@ -321,45 +601,8 @@ Q
 b
 Q
 
-% E5
-
-1 0 0 1 100 100 cm
-
-255 255 255 rg
-75 50 m
-100 75 l
-100 25 l
-f
-
-% http://developer.mozilla.org/samples/canvas-tutorial/2_2_canvas_moveto.html
-%0 0 m
-%75 75 50 0 pi 2 * true arc
-%110 75 m
-%75 75 35 0 pi false arc
-%65 65 m
-%60 65 5 0 pi 2 * true arc
-%95 65 m
-%90 65 5 0 pi 2 * true arc
-%S
-
-% http://developer.mozilla.org/samples/canvas-tutorial/2_3_canvas_lineto.html
-
-1 0 0 1 100 100 cm
-
-25 25 m
-105 25 l
-25 105 l
-f
-
-125 125 m
-125 45 l
-45 125 l
-h S
-
 % http://developer.mozilla.org/samples/canvas-tutorial/2_5_canvas_quadraticcurveto.html
 
-1 0 0 1 100 100 cm
-
 %75 25 m
 %25 25 25 62 5 c2
 %25 100 50 100 c2
@@ -369,70 +612,12 @@ h S
 %125 25 75 25 c2
 %S
 
-q % heart (bezier)
-1 0 0 -1 0 0 cm
-255 0 0 rg
-75 40 m
-75 37 70 25 50 25 c
-20 25 20 62.5 20 62.5 c
-20 80 40 102 75 120 c
-110 102 130 80 130 62.5 c
-130 62.5 130 25 100 25 c
-85 25 75 37 75 40 c
-f
-Q
-
-
-/triangle {
-  255 255 255 rg
-  75 50 m
-  100 75 l
-  100 25 l
-  f
-} def
-
-/triangle2 {
-  255 0 255 rg
-  75 50 m
-  100 75 l
-  100 25 l
-  f
-} def
-
-triangle
-1 0 0 1 100 -100 cm
-triangle2
-1 0 0 1 100 -100 cm
-triangle
-
 %3 8 div 6 add .
 %6 3 8 div add .
 
 %8 7 3 mul sub .
 %7 3 mul 8 exch sub .
 
-7.2 36.0 m
-14.4 7.2 l
-S
-14.4 43.2 m
-0 -21.6 l
-S
-
-1 0 0 1 27.0 36.0 cm
-0 72 m
-72 0 l
-0 -72 l
--72 0 l
-4 setlinewidth
-h S
-
-/pi 3.141592653589 def
-%pi .
-%pi 2 mul .
-
-/inch {72 mul} def
-%5 inch .
-
 /box {
   0 0 m
   72 0 l
@@ -453,623 +638,46 @@ box
 
 % TODO not, and, or, xor
 % TODO for loop exit
-
-/factorial %stack: n --- n! (after)
-{ dup 1 gt
-  {dup 1 sub factorial mul} if
-} def
-
-%5 factorial .
-
-% https://developer.mozilla.org/samples/canvas-tutorial/4_1_canvas_fillstyle.html
-
-%  for (i=0;i<6;i++){
-%    for (j=0;j<6;j++){
-%      ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' + 
-%                       Math.floor(255-42.5*j) + ',0)';
-%      ctx.fillRect(j*25,i*25,25,25);
-
-%0 2 6 {.} for
-
-1 1 6 { %% i
-  dup 255 exch 255 6 div mul sub %% i ii
-  1 1 6 { %% i ii j
-    dup 255 exch 255 6 div mul sub %% i ii j jj
-%    fillstyle
-%    fillrect 25 j mul | 25 i mul | 25 | 25
-  } for
-} for
-
-
-% https://developer.mozilla.org/en/drawing_graphics_with_canvas
-
-/bowtie { % fillStyle
-  200 200 200 0.3 rgba /fillStyle gput
-  -30 -30 60 60 fillRect
-  /fillStyle gput
-  1.0 /globalAlpha gput
-  newpath
-  25 25 moveto
-  -25 -25 lineto
-  25 -25 lineto
-  -25 25 lineto
-  closepath
-  fill
-} def
-
-/dot {
-  gsave
-  (black) /fillStyle gput
-  -2 -2 4 4 fillRect
-  grestore
-} def
-
-0 -100 translate
-
-45 45 translate
-
-gsave
-(red) bowtie
-dot
-grestore
-
-gsave
-85 0 translate
-45 pi mul 180 div rotate
-(green) bowtie
-dot
-grestore
-
-gsave
-0 85 translate
-135 pi mul 180 div rotate
-(blue) bowtie
-dot
-grestore
- 
-gsave
-85 85 translate
-90 pi mul 180 div rotate
-(yellow) bowtie
-dot
-grestore
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 </pre>
+#+end_html
 
-<script>
-function min(X, Y) {
-   return X < Y ? X : Y;
-}
-
-function max(X, Y) {
-   return X < Y ? Y : X;
-}
+/MediaBox [0 0 612 446]
 
-function ex3() {
-   var S = [];
-   var F = {};
-   var W = document.getElementById("c");
-   var C = W.getContext("2d");
-
-   W.setAttribute("width", 612);
-   W.setAttribute("height", 446);
-
-   // basic operators
-
-   F["neg"] = function() {S.push(- S.pop());};
-   F["add"] = function() {S.push(S.pop() + S.pop());};
-   F["sub"] = function() {F["neg"](); F["add"]();};
-   F["mul"] = function() {S.push(S.pop() * S.pop());};
-   F["div"] = function() {
-      var X = S.pop();
-      S.push(S.pop() / X);
-   };
-   F["idiv"] = function() {
-      var X = S.pop();
-      S.push(Math.floor(S.pop() / X));
-   };
-   F["mod"] = function() {
-      var X = S.pop();
-      S.push(S.pop() % X);
-   };
-   // TODO sqrt, exp, ceiling, sin
-   F["exch"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      S.push(Y);
-      S.push(X);
-   };
-
-   F["dup"] = function() {var X = S.pop(); S.push(X); S.push(X);};
-   F["clear"] = function() {S = [];};
-   F["pop"] = function() {S.pop();};
-   // TODO roll
-
-   F["eq"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      S.push(X == Y);
-   };
-   F["ne"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      S.push(X != Y);
-   };
-   F["gt"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      S.push(X > Y);
-   };
-   F["lt"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      S.push(X < Y);
-   };
-   F["ge"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      S.push(X >= Y);
-   };
-   F["le"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      S.push(X <= Y);
-   };
-
-   F["if"] = function() {
-      var B = S.pop();
-      var C = S.pop();
-      if(C == true) run(B);
-   };
-   F["ifelse"] = function() {
-      var N = S.pop();
-      var P = S.pop();
-      var C = S.pop();
-      if(C == true) run(P);
-      else run(N);
-   };
-   F["repeat"] = function() {
-      var B = S.pop();
-      var N = S.pop();
-      for(var I = 0; I < N; I++) run(B);
-   };
-   F["for"] = function() {
-      var B = S.pop();
-      var L = S.pop();
-      var K = S.pop();
-      var J = S.pop();
-      if(K < 0) {
-         for(var I = J; L <= I; I += K) {
-            S.push(I);
-            run(B);
-         }
-      } else {
-         for(var I = J; I <= L; I += K) {
-            S.push(I);
-            run(B);
-         }
-      }
-   };
-
-   F["."] = function() {alert(S.pop());};
-   F["=="] = function() {alert(S[0]);};
-   F["pstack"] = function() {alert(S);};
-
-   function run(C) {
-      if(!C.length) S.push(C);
-         else {
-            var M = C.length;
-            for(var I = 0; I < M; I++) {
-               var T = C[I];
-               if(typeof T == "number" || typeof T == "object" || quoted(T))
-                  S.push(T);
-               else {
-                  if(F[T]) F[T]();
-                  else throw "Unknown operator '" + T + "' " + typeof T;
-               }
-            }
-         }
-   }
-
-   F["def"] = function() {
-      var C = S.pop();
-      var N = S.pop();
-      if(quoted(N)) F[N.substring(1)] = function() {run(C);}
-      else throw "Wrong operator name " + N;
-   };
-
-   // html5 graphic operators
-
-   //transform
-   //setTransform
-   //createLinearGradient
-   //createRadialGradient
-   //createPatternI
-   //createPatternC
-   //createPatternV
-   F["clearRect"] = function() {
-      var H = S.pop();
-      var W = S.pop();
-      var Y = S.pop();
-      var X = S.pop();
-      C.clearRect(X, Y, W, H);
-   };
-   F["fillRect"] = function() {
-      var H = S.pop();
-      var W = S.pop();
-      var Y = S.pop();
-      var X = S.pop();
-      C.fillRect(X, Y, W, H);
-   };
-   F["strokeRect"] = function() {
-      var H = S.pop();
-      var W = S.pop();
-      var Y = S.pop();
-      var X = S.pop();
-      C.strokeRect(X, Y, W, H);
-   };
-   //quadraticCurveTo
-   F["rect"] = function() {
-      var H = S.pop();
-      var W = S.pop();
-      var Y = S.pop();
-      var X = S.pop();
-      C.strokeRect(X, Y, W, H);
-   };
-   //isPointInPath
-   //fillText
-   //strokeText
-   //measureText
-   //drawImageI1
-   //drawImageI2
-   //drawImageC1
-   //drawImageC2
-   //drawImageV1
-   //drawImageV2
-   //createImageData1
-   //createImageData2
-   //getImageData
-   //putImageData
-
-   // html5 utility operators
-
-   F["gput"] = function() {
-      var K = S.pop();
-      var V = S.pop();
-      C[K.substring(1)] = isPdfT(V) ? V.V : V;
-   };
-   F["gget"] = function() {
-      var K = S.pop();
-      S.push(C[K.substring(1)]);
-   };
-
-   F["rgb"] = function() {
-      var B = S.pop();
-      var G = S.pop();
-      var R = S.pop();
-      S.push(new PdfT("rgba(" + R + "," + G + "," + B + ")"));
-   };
-   F["rgba"] = function() {
-      var A = S.pop();
-      var B = S.pop();
-      var G = S.pop();
-      var R = S.pop();
-      S.push(new PdfT("rgba(" + R + "," + G + "," + B + "," + A + ")"));
-   };
-
-   // ps graphic operators
-
-   F["gsave"] = function() {C.save();};
-   F["grestore"] = function() {C.restore();};
-   F["scale"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      C.scale(X, Y);
-   };
-   F["rotate"] = function() {
-      var A = S.pop();
-      C.rotate(A);
-   };
-   F["translate"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      C.translate(X, Y);
-   };
-   F["newpath"] = function() {C.beginPath();};
-   F["closepath"] = function() {C.closePath();};
-   F["moveto"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      C.moveTo(X, Y);
-   };
-   F["lineto"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      C.lineTo(X, Y);
-   };
-   F["arcto"] = function() {
-      var R = S.pop();
-      var Y2 = S.pop();
-      var X2 = S.pop();
-      var Y1 = S.pop();
-      var X1 = S.pop();
-      C.arcTo(X1, Y1, X2, Y2, R);
-   };
-   F["arc"] = function() {
-      var A = S.pop();
-      var E = S.pop();
-      var S = S.pop();
-      var R = S.pop();
-      var Y = S.pop();
-      var X = S.pop();
-      C.arc(X, Y, R, S, E, A);
-   };
-   F["fill"] = function() {C.fill();};
-   F["stroke"] = function() {C.stroke();};
-   F["clip"] = function() {C.clip();};
-
-   // pdf graphic operators
-
-   F["w"] = function() {C.lineWidth = S.pop();};
-   F["J"] = function() {C.lineCap = S.pop();};
-   F["j"] = function() {C.lineJoin = S.pop();};
-   F["M"] = function() {C.mitterLimit = S.pop();};
-   F["d"] = function() {
-      var P = S.pop();
-      var A = S.pop();
-      alert("TODO d");
-   };
-   F["ri"] = function() {alert("TODO ri");};
-   F["i"] = function() {alert("TODO i");};
-   F["gs"] = function() {alert("TODO gs");};
-
-   F["q"] = function() {C.save();};
-   F["Q"] = function() {C.restore();};
-   F["cm"] = function() { // TODO fix cm
-      var Dy = S.pop();
-      var Dx = S.pop();
-      var M22 = S.pop();
-      var M21 = S.pop();
-      var M12 = S.pop();
-      var M11 = S.pop();
-      //alert(M11 +"|"+ M12 +"|"+ M21 +"|"+ M22 +"|"+ Dx +"|"+ Dy);
-      //C.setTransform(M11, M12, M21, M22, Dx, Dy);
-      C.transform(M11, M12, M21, M22, Dx, Dy);
-   };
-
-   F["m"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      C.beginPath(); // TODO only if not m previously
-      C.moveTo(X, Y);
-   };
-   F["l"] = function() {
-      var Y = S.pop();
-      var X = S.pop();
-      C.lineTo(X, Y);
-   };
-   F["c"] = function() {
-      var Y3 = S.pop();
-      var X3 = S.pop();
-      var Y2 = S.pop();
-      var X2 = S.pop();
-      var Y1 = S.pop();
-      var X1 = S.pop();
-      C.bezierCurveTo(X1, Y1, X2, Y2, X3, Y3); // TODO the right c method
-   };
-//   F["c2"] = function() { // not in pdf
-//      var Y3 = S.pop();
-//      var X3 = S.pop();
-//      var Y2 = S.pop();
-//      var X2 = S.pop();
-//      var Y1 = S.pop();
-//      var X1 = S.pop();
-//      C.bezierCurveTo(X1, Y1, X2, Y2, X3, Y3); // TODO the right c method
+#+begin_html
+<script>
+function xreq(Url, Cb, Er) {
+//   var req = new XMLHttpRequest();
+//   alert(Url);
+//   req.open('GET', Url, true);
+//   req.onreadystatechange = function (e) {
+//      if(req.readyState == 4) {
+//         if(req.status == 200) Cb(req.responseText);
+//         else if(Er) Er();
+//      }
 //   };
-   F["v"] = function() {alert("TODO v");};
-   F["y"] = function() {alert("TODO y");};
-   F["h"] = function() {C.closePath();};
-   F["re"] = function() {
-      var Y2 = S.pop();
-      var X2 = S.pop();
-      var Y1 = S.pop();
-      var X1 = S.pop();
-      C.rect(X1, Y1, X2, Y2);
-   };
-
-   F["S"] = function() {C.stroke();};
-   F["s"] = function() {F["h"](); F["S"]();};
-   F["f"] = function() {C.fill();};
-   F["F"] = function() {C.fill();};
-   F["f*"] = function() {alert("TODO f*");};
-   F["B"] = function() {F["f"](); F["S"]();};
-   F["B*"] = function() {F["f*"](); F["S"]();};
-   F["b"] = function() {F["h"](); F["B"]();};
-   F["b*"] = function() {F["h"](); F["B*"]();};
-   F["n"] = function() {alert("TODO n");};
-
-   F["W"] = function() {C.clip();};
-   F["W*"] = function() {alert("TODO W*");};
-
-   F["BT"] = function() {alert("TODO BT")};
-   F["ET"] = function() {alert("TODO ET")};
-
-   F["Tc"] = function() {alert("TODO Tc");};
-   F["Tw"] = function() {alert("TODO Tw");};
-   F["Tz"] = function() {alert("TODO Tz");};
-   F["TL"] = function() {alert("TODO Tf");};
-   F["Tf"] = function() {
-      var N = S.pop();
-      var F = S.pop();
-      C.font = N + "pt " + F.V;
-   };
-   F["Tr"] = function() {alert("TODO Tr");};
-   F["Ts"] = function() {alert("TODO Ts");};
-
-   F["Td"] = function() {alert("TODO Td");};
-   F["TD"] = function() {alert("TODO TD");};
-   F["Tm"] = function() {alert("TODO Tm");};
-   F["T*"] = function() {alert("TODO T*");};
-
-   F["Tj"] = function() {
-      var T = S.pop();
-      //alert(T.V);
-      //if(C.strokeText) C.strokeText(T.V, 0, 0);
-      if(C.fillText) C.fillText(T.V, 0, 0);
-   };
-   F["TJ"] = function() {alert("TODO TJ");};
-   F["'"] = function() {alert("TODO '");};
-   F["\""] = function() {alert("TODO \"");};
-
-   F["d0"] = function() {alert("TODO d0");};
-   F["d1"] = function() {alert("TODO d1");};
-
-   F["CS"] = function() {alert("TODO CS");};
-   F["cs"] = function() {alert("TODO cs");};
-   F["SC"] = function() {alert("TODO SC");};
-   F["SCN"] = function() {alert("TODO SCN");};
-   F["sc"] = function() {alert("TODO sc");};
-   F["scn"] = function() {alert("TODO scn");};
-   F["G"] = function() {alert("TODO G");};
-   F["g"] = function() {alert("TODO g");};
-   F["RG"] = function() {alert("TODO RG");};
-   F["rg"] = function() { // TODO color spaces
-      var B = S.pop();
-      var G = S.pop();
-      var R = S.pop();
-      C.fillStyle = "rgb(" + R + "," + G + "," + B + ")";
-   };
-   F["K"] = function() {alert("TODO K");};
-   F["k"] = function() {alert("TODO k");};
-
-   F["sh"] = function() {alert("TODO sh");};
-
-   F["BI"] = function() {alert("TODO BI");};
-   F["ID"] = function() {alert("TODO ID");};
-   F["EI"] = function() {alert("TODO EI");};
-
-   F["Do"] = function() {alert("TODO Do");};
-
-   F["MP"] = function() {alert("TODO MP");};
-   F["DP"] = function() {alert("TODO DP");};
-   F["BMC"] = function() {alert("TODO BMC");};
-   F["BDC"] = function() {alert("TODO BDC");};
-   F["EMC"] = function() {alert("TODO EMC");};
-
-   F["BX"] = function() {alert("TODO BX");};
-   F["EX"] = function() {alert("TODO EX");};
-
-   ps(document.getElementById("ex3").innerText, F, S);
+//   req.send(null);
+
+   try {netscape.security.PrivilegeManager.enablePriviledge(priviledge);}
+   catch(e) {}
+   var req = new XMLHttpRequest();
+   req.open('GET', Url, false); 
+   req.send(null);
+   if(req.status == 200) Cb(req.responseText);
+   else alert("uff");
 }
 </script>
-<button onclick="javascript:ex3()">Draw</button>
 #+end_html
 
-/MediaBox [0 0 612 446]
+#+html: <canvas id="c"></canvas>
 
-#+html: <canvas id="c" style="width:612pt;height:446pt;background-color:yellow"/>
+[[http://svn.ghostscript.com/viewvc/trunk/gs/examples/tiger.eps?view=co][tiger.eps]]:
+#+html: <button onclick="javascript:xreq('http://svn.ghostscript.com/viewvc/trunk/gs/examples/tiger.eps?view=co', wps)">Draw</button>
+#+html: <button onclick="javascript:xreq('file:///home/tomas/src/pdf4web/tiger.eps', alert)">Draw</button>
 
-** CanvasRenderingContext2D
+* JavaScript bindings
 
 http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element
 
-Operators:
-
-|   | category               | operator |
-|---+------------------------+----------|
-| / |                        | <        |
-|   | General graphics state | w        |
-|   |                        | J        |
-|   |                        | j        |
-|   |                        | M        |
-|   |                        | d        |
-|   |                        | ri       |
-|   |                        | i        |
-|   |                        | gs       |
-|   | Special graphics state | q        |
-|   |                        | Q        |
-|   |                        | cm       |
-|   | Path construction      | m        |
-|   |                        | l        |
-|   |                        | c        |
-|   |                        | v        |
-|   |                        | y        |
-|   |                        | h        |
-|   |                        | re       |
-|   | Path painting          | S        |
-|   |                        | s        |
-|   |                        | f        |
-|   |                        | F        |
-|   |                        | f*       |
-|   |                        | B        |
-|   |                        | B*       |
-|   |                        | b        |
-|   |                        | b*       |
-|   |                        | n        |
-|   | Clipping paths         | W        |
-|   |                        | W*       |
-|   | Text objects           | BT       |
-|   |                        | ET       |
-|   | Text state             | Tc       |
-|   |                        | Tw       |
-|   |                        | Tz       |
-|   |                        | TL       |
-|   |                        | Tf       |
-|   |                        | Tr       |
-|   |                        | Ts       |
-|   | Text positioning       | Td       |
-|   |                        | TD       |
-|   |                        | Tm       |
-|   |                        | T*       |
-|   | Text showing           | Tj       |
-|   |                        | TJ       |
-|   |                        | '        |
-|   |                        | "        |
-|   | Type 3 fonts           | d0       |
-|   |                        | d1       |
-|   | Color                  | CS       |
-|   |                        | cs       |
-|   |                        | SC       |
-|   |                        | SCN      |
-|   |                        | sc       |
-|   |                        | scn      |
-|   |                        | G        |
-|   |                        | g        |
-|   |                        | RG       |
-|   |                        | rg       |
-|   |                        | K        |
-|   |                        | k        |
-|   | Shading patterns       | sh       |
-|   | Inline images          | BI       |
-|   |                        | ID       |
-|   |                        | EI       |
-|   | XObjects               | Do       |
-|   | Marked content         | MP       |
-|   |                        | DP       |
-|   |                        | BMC      |
-|   |                        | BDC      |
-|   |                        | EMC      |
-|   | Compatibility          | BX       |
-|   |                        | EX       |
-  
-Special graphics state q, Q, cm                 57
-Path construction      m, l, c, v, y, h, re     59
-
 ??? rlineto rmoveto findfont scalefont setfont show rightshow
 stringwidth arcn loop/exit forall cvs array put get length aload
 astore mark ashow widthshow awidthshow kshow currentpoint makefont
@@ -1084,108 +692,343 @@ octal chars in string \234
 
 /Times-Roman findfont typography 15 scalefont setfont
 
-
-Methods:
-
-|   | html5                | ps        | pdf  | method                                                                                                                                                       |
-|---+----------------------+-----------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| / |                      |           |      | <                                                                                                                                                            |
-|   |                      | gsave     | q    | void save();                                                                                                                                                 |
-|   |                      | grestore  | Q    | void restore();                                                                                                                                              |
-|   |                      | scale     |      | void scale(in float x, in float y);                                                                                                                          |
-|   |                      | rotate    |      | void rotate(in float angle);                                                                                                                                 |
-|   |                      | translate |      | void translate(in float x, in float y);                                                                                                                      |
-|   | transform            |           |      | void transform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);                                                            |
-|   | setTransform         |           | cm ? | void setTransform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);                                                         |
-|   | createLinearGradient |           |      | CanvasGradient createLinearGradient(in float x0, in float y0, in float x1, in float y1);                                                                     |
-|   | createRadialGradient |           |      | CanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);                                           |
-|   | createPatternI       |           |      | CanvasPattern createPattern(in HTMLImageElement image, in DOMString repetition);                                                                             |
-|   | createPatternC       |           |      | CanvasPattern createPattern(in HTMLCanvasElement image, in DOMString repetition);                                                                            |
-|   | createPatternV       |           |      | CanvasPattern createPattern(in HTMLVideoElement image, in DOMString repetition);                                                                             |
-|   | clearRect            |           |      | void clearRect(in float x, in float y, in float w, in float h);                                                                                              |
-|   | fillRect             |           |      | void fillRect(in float x, in float y, in float w, in float h);                                                                                               |
-|   | strokeRect           |           |      | void strokeRect(in float x, in float y, in float w, in float h);                                                                                             |
-|   |                      | newpath   | m !  | void beginPath();                                                                                                                                            |
-|   |                      | closepath | h    | void closePath();                                                                                                                                            |
-|   |                      | moveto    |      | void moveTo(in float x, in float y);                                                                                                                         |
-|   |                      | lineto    |      | void lineTo(in float x, in float y);                                                                                                                         |
-|   | quadraticCurveTo     |           |      | void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y);                                                                                   |
-|   |                      |           | c    | void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y);                                                      |
-|   |                      | arcto     |      | void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius);                                                                             |
-|   | rect                 |           |      | void rect(in float x, in float y, in float w, in float h);                                                                                                   |
-|   |                      | arc       |      | void arc(in float x, in float y, in float radius, in float startAngle, in float endAngle, in boolean anticlockwise);                                         |
-|   |                      | fill      | f    | void fill();                                                                                                                                                 |
-|   |                      |           | F !  |                                                                                                                                                              |
-|   |                      | stroke    | S    | void stroke();                                                                                                                                               |
-|   |                      |           | s !  |                                                                                                                                                              |
-|   |                      |           | b !  |                                                                                                                                                              |
-|   |                      |           | b* ! |                                                                                                                                                              |
-|   |                      | clip      | W    | void clip();                                                                                                                                                 |
-|   |                      |           | W* ! |                                                                                                                                                              |
-|   | isPointInPath        |           |      | boolean isPointInPath(in float x, in float y);                                                                                                               |
-|   | fillText             |           |      | void fillText(in DOMString text, in float x, in float y, [Optional] in float maxWidth);                                                                      |
-|   | strokeText           |           |      | void strokeText(in DOMString text, in float x, in float y, [Optional] in float maxWidth);                                                                    |
-|   | measureText          |           |      | TextMetrics measureText(in DOMString text);                                                                                                                  |
-|   | drawImageI1          |           |      | void drawImage(in HTMLImageElement image, in float dx, in float dy, [Optional] in float dw, in float dh);                                                    |
-|   | drawImageI2          |           |      | void drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh);           |
-|   | drawImageC1          |           |      | void drawImage(in HTMLCanvasElement image, in float dx, in float dy, [Optional] in float dw, in float dh);                                                   |
-|   | drawImageC2          |           |      | void drawImage(in HTMLCanvasElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh);          |
-|   | drawImageV1          |           |      | void drawImage(in HTMLVideoElement image, in float dx, in float dy, [Optional] in float dw, in float dh);                                                    |
-|   | drawImageV2          |           |      | void drawImage(in HTMLVideoElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh);           |
-|   | createImageData1     |           |      | ImageData createImageData(in float sw, in float sh);                                                                                                         |
-|   | createImageData2     |           |      | ImageData createImageData(in ImageData imagedata);                                                                                                           |
-|   | getImageData         |           |      | ImageData getImageData(in float sx, in float sy, in float sw, in float sh);                                                                                  |
-|   | putImageData         |           |      | void putImageData(in ImageData imagedata, in float dx, in float dy, [Optional] in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight); |
-
-Attributes:
-
-|   | html5                    | ps              | pdf | attribute                                                                                    | default           |
-|---+--------------------------+-----------------+-----+----------------------------------------------------------------------------------------------+-------------------|
-| / | <                        | <               | <   | <                                                                                            | <                 |
-|   | globalAlpha              |                 |     | float globalAlpha;                                                                           | 1.0               |
-|   | globalCompositeOperation |                 |     | DOMString globalCompositeOperation;                                                          | source-over       |
-|   | strokeStyle              | (~setdash?)     |     | any strokeStyle;                                                                             | black             |
-|   | fillStyle                |                 |     | any fillStyle;                                                                               | black             |
-|   | lineWidth                | ~ setlinewidth  |     | float lineWidth;                                                                             | 1                 |
-|   | lineCap                  | ~ setlinecap    |     | DOMString lineCap; // "butt", "round", "square"                                              | butt              |
-|   | lineJoin                 | ~ setlinejoin   |     | DOMString lineJoin; // "round", "bevel", "miter"                                             | miter             |
-|   | miterLimit               | ~ setmiterlimit |     | float miterLimit;                                                                            | 10                |
-|   | shadowOffsetX            |                 |     | float shadowOffsetX;                                                                         | 0                 |
-|   | shadowOffsetY            |                 |     | float shadowOffsetY;                                                                         | 0                 |
-|   | shadowBlur               |                 |     | float shadowBlur;                                                                            | 0                 |
-|   | shadowColor              |                 |     | DOMString shadowColor;                                                                       | transparent black |
-|   | font                     |                 |     | DOMString font;                                                                              | 10px sans-serif   |
-|   | textAlign                |                 |     | DOMString textAlign; // "start", "end", "left", "right", "center"                            | start             |
-|   | textBaseline             |                 |     | DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" | alphabetic        |
-
-
-#+begin_src idl
-interface CanvasGradient {
-  // opaque object
-  void addColorStop(in float offset, in DOMString color);
-};
-
-interface CanvasPattern {
-  // opaque object
-};
-
-interface TextMetrics {
-  readonly attribute float width;
-};
-
-interface ImageData {
-  readonly attribute unsigned long width;
-  readonly attribute unsigned long height;
-  readonly attribute CanvasPixelArray data;
-};
-
-[IndexGetter, IndexSetter]
-interface CanvasPixelArray {
-  readonly attribute unsigned long length;
-};
-#+end_src
+** Built-in operators
+
+| category       | in                      | operator | out                                                         |
+|----------------+-------------------------+----------+-------------------------------------------------------------|
+| Trivial        |                         | true     | true                                                        |
+|                |                         | false    | false                                                       |
+|                |                         | null     | null                                                        |
+| Math           | x                       | neg      | -x                                                          |
+|                | x y                     | add      | x+y                                                         |
+|                | x y                     | mul      | x*y                                                         |
+|                | x y                     | div      | x/y                                                         |
+|                | x y                     | mod      | x%y                                                         |
+| Stack          |                         | mark     | mark                                                        |
+|                | x y                     | exch     | y x                                                         |
+|                |                         | clear    |                                                             |
+|                | x                       | pop      |                                                             |
+|                | any_n ...any_0 n        | index    | any_n ... any_0 any_n                                       |
+|                | any_(n-1) ... any_0 n j | roll     | any_((j-1) mod n) ... any_0 ... any_(n-1) ... any_(j mod n) |
+|                | any_1 ... any_n n       | copy     | any_1 ... any_n any_1 ... any_n                             |
+| Array          | array                   | length   | n                                                           |
+| Conditionals   | x y                     | eq       | bool                                                        |
+|                | x y                     | lt       | bool                                                        |
+|                | y                       | not      | bool                                                        |
+|                | x y                     | and      | z                                                           |
+|                | x y                     | or       | z                                                           |
+|                | bool then else          | ifelse   |                                                             |
+|                | n proc                  | repeat   |                                                             |
+|                | i j k proc              | for      |                                                             |
+| Debugging      | x                       | .        |                                                             |
+|                |                         | pstack   |                                                             |
+| Dictionaries   | n                       | dict     | dict                                                        |
+|                | dict key                | get      | any                                                         |
+|                | dict key any            | put      |                                                             |
+|                | sym proc                | def      |                                                             |
+| Arrays         | n                       | array    | array                                                       |
+| JavaScript FFI | dict key nargs          | .call    | any                                                         |
+|                |                         | .gc      | gc                                                          |
+|                |                         | .math    | Math                                                        |
+| HTML 5         | r g b                   | .rgb     | text                                                        |
+|                | r g b a                 | .rgba    | text                                                        |
+
+** Core operators
+
+| category     | in          | operator    | out    |
+|--------------+-------------+-------------+--------|
+| Math         |             | abs         |        |
+|              |             | .acos       |        |
+|              |             | .asin       |        |
+|              |             | atan        |        |
+|              |             | .atan2      |        |
+|              |             | ceiling     |        |
+|              |             | cos         |        |
+|              |             | .exp        |        |
+|              |             | floor       |        |
+|              |             | log         |        |
+|              |             | .max        |        |
+|              |             | .min        |        |
+|              |             | .pow        |        |
+|              |             | .random     |        |
+|              |             | rand        |        |
+|              |             | round       |        |
+|              |             | sin         |        |
+|              |             | sqrt        |        |
+|              |             | .tan        |        |
+|              |             | truncate    |        |
+|              |             | .e          |        |
+|              |             | .ln2        |        |
+|              |             | .ln10       |        |
+|              |             | .log2e      |        |
+|              |             | .log10e     |        |
+|              |             | .pi         |        |
+|              |             | .sqrt1_2    |        |
+|              |             | .sqrt2      |        |
+|              |             | sub         |        |
+|              |             | idiv        |        |
+| Stack        | x           | dup         | x x    |
+| Conditionals | x y         | ne          | bool   |
+|              | x y         | ge          | bool   |
+|              | x y         | le          | bool   |
+|              | x y         | gt          | bool   |
+|              | bool proc   | if          |        |
+| HTML 5       | key         | .gget       |        |
+|              | any key     | .gput       |        |
+|              | key nargs   | .gcall0     |        |
+|              | key nargs   | .gcall1     |        |
+|              |             | .gcanvas    | canvas |
+|              | w h         | .gdim       |        |
+|              | x0 y0 x1 y1 | .gbox       |        |
+| PostScript   | gray        | setgray     |        |
+|              | r g b       | setrgbcolor |        |
+|              | ???         | setfont ?   |        |
+|              |             | clippath ?  |        |
+|              | text        | show ?      |        |
+|              | x y         | rlineto     |        |
+
+** Canvas methods
+
+|   | in                                           | canvas                | out            | ps         | pdf         |
+|---+----------------------------------------------+-----------------------+----------------+------------+-------------|
+| / |                                              |                       |                | <          | <           |
+|   |                                              | .save                 |                | gsave      | q           |
+|   |                                              | .restore              |                | grestore   | Q           |
+|   | x y                                          | scale                 |                | scale      | -           |
+|   | angle                                        | rotate                |                | rotate     | -           |
+|   | x y                                          | translate             |                | translate  | -           |
+|   | m11 m12 m21 m22 dx dy                        | .transform            |                | -          | cm          |
+|   | m11 m12 m21 m22 dx dy                        | .setTransform         |                | -          | -           |
+|   | x0 y0 x1 y1                                  | .createLinearGradient | canvasGradient |            |             |
+|   | x0 y0 r0 x1 y1 r1                            | .createRadialGradient | canvasGradient |            |             |
+|   | image repetition                             | .createPattern        | canvasPattern  |            |             |
+|   | x y w h                                      | .clearRect            |                | rectclip   |             |
+|   | x y w h                                      | .fillRect             |                | rectfill   |             |
+|   | x y w h                                      | .strokeRect           |                | rectstroke |             |
+|   |                                              | .beginPath            |                | newpath    | m ?         |
+|   |                                              | .closePath            |                | closepath  | ~ h ? ~ n ? |
+|   | x y                                          | .moveTo               |                | moveto     | m ?         |
+|   | x y                                          | .lineTo               |                | lineto     | l           |
+|   | cpx cpy x y                                  | .quadraticCurveTo     |                |            |             |
+|   | cp1x cp1y cp2x cp2y x y                      | .bezierCurveTo        |                |            | c           |
+|   | x1 y1 x2 y2 radius                           | .arcTo                |                | arcto      |             |
+|   | x y w h                                      | .rect                 |                | -          | ~ re        |
+|   | x y radius startAngle endAngle anticlockwise | .arc                  |                | ~ arc      |             |
+|   |                                              | fill                  |                | fill       | ~ f ?       |
+|   |                                              | stroke                |                | stroke     | S           |
+|   |                                              | clip                  |                | clip       | ~ W ?       |
+|   | x y                                          | .isPointInPath        | boolean        |            |             |
+|   | text x y                                     | .fillText1            |                |            |             |
+|   | text x y maxWidth                            | .fillText2            |                |            |             |
+|   | text x y                                     | .strokeText1          |                |            |             |
+|   | text x y maxWidth                            | .strokeText2          |                |            |             |
+|   | text                                         | .measureText          | textMetrics    |            |             |
+|   | image dx dy                                  | .drawImage1           |                |            |             |
+|   | image dx dy dw dh                            | .drawImage2           |                |            |             |
+|   | image sx sy sw sh dx dy dw dh                | .drawImage3           |                |            |             |
+|   | imagedata                                    | .createImageData1     | imageData      |            |             |
+|   | sw sh                                        | .createImageData1     | imageData      |            |             |
+|   | sx sy sw sh                                  | .getImageData         | imageData      |            |             |
+|   | imagedata dx dy                              | .putImageData1        |                |            |             |
+|   | imagedata dx dy dirtyX dirtyY dirtyW dirtyH  | .putImageData2        |                |            |             |
+
+** Canvas attributes
+
+|   | type | attribute                 | values                                             | ps            | pdf   |
+|---+------+---------------------------+----------------------------------------------------+---------------+-------|
+| / |      | <                         |                                                    | <             | <     |
+|   | num  | .globalAlpha              | (1.0)                                              |               |       |
+|   | str  | .globalCompositeOperation | (source-over)                                      |               |       |
+|   | any  | .strokeStyle              | (black)                                            | ~ setdash ?   | ~ d ? |
+|   | any  | .fillStyle                | (black)                                            |               |       |
+|   | num  | .lineWidth                | (1)                                                | setlinewidth  | w     |
+|   | str  | .lineCap                  | (butt) round square                                | ~ setlinecap  | J     |
+|   | str  | .lineJoin                 | round bevel (miter)                                | ~ setlinejoin | j     |
+|   | num  | .miterLimit               | (10)                                               | setmiterlimit | M     |
+|   | num  | .shadowOffsetX            | (0)                                                |               |       |
+|   | num  | .shadowOffsetY            | (0)                                                |               |       |
+|   | num  | .shadowBlur               | (0)                                                |               |       |
+|   | str  | .shadowColor              | (transparent black)                                |               |       |
+|   | str  | .font                     | (10px sans-serif)                                  |               |       |
+|   | str  | .textAlign                | (start) end left right center                      |               |       |
+|   | str  | .textBaseline             | top hanging middle (alphabetic) ideographic bottom |               |       |
+
+** Other operators
+
+|   | canvas                                      | ps | pdf |
+|---+---------------------------------------------+----+-----|
+| / | <                                           |    |     |
+|   | canvasGradient offset color *.addColorStop* |    |     |
+
+** Other attributes
+
+|   | dict             | type             | attribute | values | ps | pdf |
+|---+------------------+------------------+-----------+--------+----+-----|
+| / |                  |                  | <         |        | <  | <   |
+|   | textMetrics      | num              | width     |        |    |     |
+|   | imageData        | cnt              | width     |        |    |     |
+|   | imageData        | cnt              | heigth    |        |    |     |
+|   | imageData        | canvasPixelArray | data      |        |    |     |
+|   | canvasPixelArray | cnt              | length    |        |    |     |
+
+[IndexGetter, IndexSetter] CanvasPixelArray
+
+** PostScript operators
+
+|   | category | in      | operator   | out |
+|---+----------+---------+------------+-----|
+| / |          | <       | <          | <   |
+|   |          | x y [m] | transform  | x y |
+|   |          | x y [m] | itransform | x y |
+
+** PDF operators
+
+|   | category               | operator |                                                           |
+|---+------------------------+----------+-----------------------------------------------------------|
+| / |                        | <        |                                                           |
+|   | General graphics state | w        | setlinewidth                                              |
+|   |                        | J        | ~ setlinecap                                              |
+|   |                        | j        | ~ setlinejoin                                             |
+|   |                        | M        | setmiterlimit                                             |
+|   |                        | d        | ~ setdash ?                                               |
+|   |                        | ri       | {SetColorRenderingIntent}                                 |
+|   |                        | i        | {1 .min setflat}                                          |
+|   |                        | gs       | {SetExtGState}                                            |
+|   | Special graphics state | q        | gsave                                                     |
+|   |                        | Q        | grestore                                                  |
+|   |                        | cm       | .transform   { //TempMatrix astore concat }               |
+|   | Path construction      | m        | moveto                                                    |
+|   |                        | l        | lineto                                                    |
+|   |                        | c        | .bezierCurveTo (curveto)                                  |
+|   |                        | v        | ! currentpoint cp2 p3 c { currentpoint 6 2 roll curveto } |
+|   |                        | y        | ! cp1 p3 p3 c { 2 copy curveto }                          |
+|   |                        | h        | closepath                                                 |
+|   |                        | re       | ! x y m , x+w y l , x+w y+h l , x y+h l , h               |
+|   | Path painting          | S        | stroke                                                    |
+|   |                        | s        | h S                                                       |
+|   |                        | f        | (fill)                                                    |
+|   |                        | F        | f                                                         |
+|   |                        | f*       | {eofill}                                                  |
+|   |                        | B        | f S { gsave fill grestore stroke }                        |
+|   |                        | B*       | f* S { gsave eofill grestore stroke }                     |
+|   |                        | b        | h b { closepath gsave fill grestore stroke }              |
+|   |                        | b*       | h B* { closepath gsave eofill grestore stroke }           |
+|   |                        | n        | {newpath}                                                 |
+|   | Clipping paths         | W        | clip                                                      |
+|   |                        | W*       | {eoclip}                                                  |
+|   | Text objects           | BT       |                                                           |
+|   |                        | ET       | {grestore}                                                |
+|   | Text state             | Tc       |                                                           |
+|   |                        | Tw       |                                                           |
+|   |                        | Tz       |                                                           |
+|   |                        | TL       |                                                           |
+|   |                        | Tf       |                                                           |
+|   |                        | Tr       |                                                           |
+|   |                        | Ts       |                                                           |
+|   | Text positioning       | Td       |                                                           |
+|   |                        | TD       |                                                           |
+|   |                        | Tm       |                                                           |
+|   |                        | T*       |                                                           |
+|   | Text showing           | Tj       | ~ show                                                    |
+|   |                        | TJ       |                                                           |
+|   |                        | '        |                                                           |
+|   |                        | "        |                                                           |
+|   | Type 3 fonts           | d0       | setcharwidth                                                          |
+|   |                        | d1       | setcachedevice                                                          |
+|   | Color                  | CS       |                                                           |
+|   |                        | cs       |                                                           |
+|   |                        | SC       |                                                           |
+|   |                        | SCN      |                                                           |
+|   |                        | sc       |                                                           |
+|   |                        | scn      |                                                           |
+|   |                        | G        | g                                                         |
+|   |                        | g        | setgray                                                   |
+|   |                        | RG       | rg                                                        |
+|   |                        | rg       | setrgbcolor                                               |
+|   |                        | K        | k                                                         |
+|   |                        | k        | setcmykcolor                                                          |
+|   | Shading patterns       | sh       |                                                           |
+|   | Inline images          | BI       |                                                           |
+|   |                        | ID       |                                                           |
+|   |                        | EI       |                                                           |
+|   | XObjects               | Do       |                                                           |
+|   | Marked content         | MP       |                                                           |
+|   |                        | DP       |                                                           |
+|   |                        | BMC      |                                                           |
+|   |                        | BDC      |                                                           |
+|   |                        | EMC      |                                                           |
+|   | Compatibility          | BX       |                                                           |
+|   |                        | EX       |                                                           |
+
+* References
+
+** PostScript in JavaScript by others
+
+Somebody before: http://www.feiri.de/pcan/ RPN calculator with many
+PostScript operators implemented directly in JavaScript.  Fast drawing
+but not "real" PostScript.
+
+Wish list: http://svgkit.sourceforge.net/
+
+** Interesting PostScript applications
+
+http://starynkevitch.net/Basile/NeWS_descr_oct_1993.html \\
+http://www.art.net/studios/Hackers/Hopkins/Don/hyperlook/index.html \\
+http://books.google.com/books?id=xHSoK66z34YC&pg=PA193 \\
+http://www.art.net/studios/Hackers/Hopkins/Don/lang/NeWS.html \\
+http://en.wikipedia.org/wiki/Display_PostScript
+
+** Mess
 
 http://canvaspaint.org/blog/2006/12/rendering-text/ \\
 http://dev.opera.com/articles/view/html-5-canvas-the-basics/ \\
 http://www.benjoffe.com/code/ \\
 http://arapehlivanian.com/wp-content/uploads/2007/02/canvas.html
+
+http://two.pairlist.net/pipermail/reportlab-users/2002-September/000599.html
+
+http://www.capcode.de/help/put ref \\
+http://www.math.ubc.ca/~cass/courses/ps.html ps operator summary \\
+http://atrey.karlin.mff.cuni.cz/~milanek/PostScript/Reference/PSL2d.html \\
+http://gauss.upf.es/www-storage/PS_Guide-1.0/operators.html \\
+http://web.mit.edu/ghostscript/www/Language.htm \\
+http://pages.cs.wisc.edu/~ghost/doc/gnu/7.05/Ps-style.htm \\
+http://www.tailrecursive.org/postscript/operators.html \\
+
+http://www.math.ubc.ca/~cass/courses/m308-7b/ch5.pdf
+
+http://en.wikibooks.org/wiki/PostScript_FAQ
+
+: http://www.nihilogic.dk/labs/canvas_sheet/HTML5_Canvas_Cheat_Sheet.png
+
+http://dev.opera.com/articles/view/creating-pseudo-3d-games-with-html-5-can-1/
+
+http://dev.opera.com/articles/view/html-5-canvas-the-basics/
+
+js closure over value, not var!
+
+http://www.pvv.ntnu.no/~andersr/fractal/PostScript.html
+http://www.cs.unh.edu/~charpov/Programming/L-systems/
+http://www.cs.unh.edu/~charpov/Programming/PostScript-primes/
+
+http://www.adobe.com/print/features/psvspdf/index.html
+
+   A PDF file is actually a PostScript file which has already been
+   interpreted by a RIP and made into clearly defined objects.
+
+http://c2.com/cgi/wiki?PortableDocumentFormat
+
+   Unfortunately, Adobe have a history of making needlessly
+   incompatible changes to the PDF format. It's not quite as bad as
+   PostScript in terms of the number of broken documents out there,
+   but it's definitely not a stable format.
+
+hate pdf http://www.useit.com/alertbox/20030714.html
+
+* Ideas
+
+do better than http://processingjs.org/ http://processingjs.org/reference
+
+try 3d interface in chrome
+
+reactive programming http://conal.net/fran/tutorial.htm