wps

PostScript for the Web
git clone https://logand.com/git/wps.git/
Log | Files | Refs | LICENSE

commit c893f037558ad06a1686635fcc7e526d3e454893
parent 7d089e5f79273c3644c826f5f6b9682490a08146
Author: tomas <tomas@logand.com>
Date:   Sat, 23 Jan 2010 15:09:36 +0100

index.org from 2009-07-14

Diffstat:
Mindex.org | 154+++++++++++++++++++++++++++++++++----------------------------------------------
1 file changed, 64 insertions(+), 90 deletions(-)

diff --git a/index.org b/index.org @@ -4,9 +4,9 @@ #+options: num:nil toc:t #+macro: ps [[http://www.capcode.de/help/$1][$1]] -#+BEGIN_HTML: +#+begin_html <p class="h0">WPS: PostScript for the Web</p> -#+END_HTML +#+end_html Welcome to WPS, a PostScript and PDF interpreter for HTML 5 canvas. @@ -29,18 +29,21 @@ canvas {width:12em;height:12em;border:1px dashed black} #+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;} +wps = new Wps; +wps.parse($$("wps")); </script> #+end_html * WPS sandbox -#+html: <canvas id="xsandbox"></canvas> #+begin_html +<canvas id="xsandbox"></canvas> <p>Sandbox:</p> <p> <textarea id="sandbox" style="width:100%" rows="18"> @@ -64,7 +67,7 @@ end </textarea> </p> <script> -function sandbox() {wps($("xsandbox"), [$$("wps"), $("sandbox").value]);} +function sandbox() {(new Wps).parse($$("wps"), "(xsandbox) .setGc", $("sandbox").value);} </script> <button onclick="javascript:sandbox();">Run</button> code from sandbox. #+end_html @@ -160,7 +163,7 @@ function ex1() { PostScript has simple but non-trivial syntax so a reader which reads text and creates internal PostScript objects is necessary. The reader -and evaluator is called =ps0= (an empty PostScript interpreter) in the +and evaluator is called =Ps0= (an empty PostScript interpreter) in the JavaScript code bellow. #+html: <div id="example2"> @@ -173,7 +176,7 @@ function example2(T) { 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 + (new Ps0(Os, Ds, Es)).parse(T); // read and interpret code T } #+end_src #+html: </div> @@ -213,11 +216,20 @@ PostScript code is from the [[http://www.math.ubc.ca/~cass/graphics/manual/pdf/c } def 5 factorial2 = + +% based on the PostScript example from +% http://partners.adobe.com/public/developer/en/ps/sdk/sample/BlueBook.zip + +/factorial3 { + dup 1 gt {dup 1 sub factorial3 mul} if +} def + +5 factorial3 = #+end_src #+html: </div> #+begin_html <script> -function ex3() {wps(null, [$$("wps"), $$("example3")]);} +function ex3() {(new Wps).parse($$("wps"), $$("example3"));} </script> <button onclick="javascript:ex3();">Run</button> the example. #+end_html @@ -308,7 +320,8 @@ All the above types are represented directly in JavaScript except: | proc | quoted array | The interpreter needs to understand when to evaluate an argument. The -distinction between a "literal" and "executable" is the key. +distinction between a "literal" and "executable" is the key. For the +"proc" type, its origin from the Execution Stack is also important. ** Quoting and execution @@ -376,11 +389,7 @@ See the [[https://developer.mozilla.org/en/drawing_graphics_with_canvas#section_ #+html: <div id="bowtie"> #+include "bowtie.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xbowtie"), [$$("wps"), $$("bowtie")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xbowtie) .setGc", $$("bowtie"), "restore");</script> ** Analog clock example @@ -393,18 +402,13 @@ 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> -#+end_html +#+html: <script>(new Wps).parse($$("wps"), "(xclock2) .setGc", $$("clock2"));</script> Running the clock keeps the CPU noticeably busy. Chrome is best with -very little overhead, followed by Opera, and Firefox significantly -worse than the previous two browsers. WPS seems to be fast enough for -one-off drawings, but its usability when running the interpreter in a -tight loop, depends on the efficiency of the host JavaScript -interpreter. +very little overhead. Firefox and Opera perform significantly worse. +WPS seems to be fast enough for one-off drawings, but its usability +depends on the efficiency of the host JavaScript interpreter when +running the interpreter in a tight loop. ** Fill example @@ -414,11 +418,7 @@ See the [[https://developer.mozilla.org/samples/canvas-tutorial/4_1_canvas_fills #+html: <div id="fill"> #+include "fill.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xfill"), [$$("wps"), $$("fill")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xfill) .setGc", $$("fill"), "restore");</script> ** Tiger example @@ -436,6 +436,7 @@ The [[http://svn.ghostscript.com/viewvc/trunk/gs/examples/tiger.eps?view=co][ori #+begin_html <div id="tiger1" style="display:none"> +(xtiger) .setGc 0 0 567 739 .gbox 1 0 0 -1 0 739 .transform /time1 .date (getTime) 0 .call def @@ -447,7 +448,7 @@ The [[http://svn.ghostscript.com/viewvc/trunk/gs/examples/tiger.eps?view=co][ori </div> <script> -function tiger() {wps($("xtiger"), [$$("wps"), $$("tiger1"), $$("tiger"), $$("tiger2")]);} +function tiger() {(new Wps).parse($$("wps"), $$("tiger1"), $$("tiger"), $$("tiger2"));} </script> <button onclick="javascript:tiger();">Draw</button> the tiger (be patient). #+end_html @@ -457,26 +458,27 @@ Is this an interesting JavaScript and canvas benchmark? #+plot: title:"tiger.eps drawing times" ind:1 deps:(2 3 4) type:2d with:histograms set:"yrange [0:]" set:"xlabel 'browser'" set:"ylabel 'time [s]'" set:"style histogram gap 3" file:"tiger.png" set:"term png size 600, 300" | browser | WPS time [s] | WPS time (no bind) [s] | PostCanvas time [s] | |------------------+--------------+------------------------+---------------------| -| Chrome | 2.5 | 3.8 | 1.6 | -| Opera | 15.9 | 13.4 | | -| Firefox 3.0 | 15.4 | 19.5 | 7.4 | -| Firefox 3.5 | 11.6 | | | - -[[http://www.feiri.de/pcan/][PostCanvas]] runs this [[http://www.feiri.de/pcan/example1.html][example]] about 1.5 times (Chrome) to 2 times -(Firefox) faster. I am actually surprised that WPS runs only up to 2 -times slower even though it interprets almost everything with minimal -number of operators coded directly in JavaScript (compared to -PostCanvas which implements all operators directly in JavaScript). +| Chrome | 2.7 | 4.1 | 1.6 | +| Opera | 17.9 | 12.3 | 0 | +| Firefox 3.0 | 21.0 | 19.0 | 7.4 | +| Firefox 3.5 | 13.0 | 9.5 | 0 | + +[[http://www.feiri.de/pcan/][PostCanvas]] runs this [[http://www.feiri.de/pcan/example1.html][example]] about 1.5 times (Chrome) to 3 times +(Firefox) faster. I am actually surprised that WPS runs only about +1.5 times slower in Chrome even though it interprets almost everything +with minimal number of operators coded directly in JavaScript +(compared to PostCanvas which implements all operators directly in +JavaScript). Another surprise to me is that I expected more significant speed up -after implementing the {{{ps(bind)}}} operator. Why does Opera get -slower in this case? +after implementing the {{{ps(bind)}}} operator. Why does Opera and +Firefox get slower in this case? -It should be fairly easy to speed up WPS by adding more operators +It should be fairly easy to speed up WPS by coding more operators implemented directly in JavaScript. This could be done dynamically by redefining/rebinding existing operators to their optimized JavaScript -version. The speed of PostCanvas could probably be taken as the best -case that could be achieved by optimizing WPS though. +versions. The speed of PostCanvas could probably be taken as the best +case that could be achieved by optimizing WPS. file:tiger.png @@ -488,15 +490,15 @@ really needed to get proper image as intended. It is also interesting to observe that PDF operators and their names probably came up from shortening/compressing "user-space" PostScript -operators in final PostScript files. The tiger.eps file was created -in 1990 and contains some "shortcuts" that match PDF operators -standardised later. +operators in PostScript files. The tiger.eps file was created in 1990 +and contains some "shortcuts" that match PDF operators standardised +later. * Drawing with PDF -PDF is rather complex format. WPS implements only drawing operators -that can be present in PDF content streams. The number of these -operators is fixed and limited. Even though the full PostScript +PDF is rather complex format. WPS aims to implement only drawing +operators that can be present in PDF content streams. The number of +these operators is fixed and limited. Even though the full PostScript language is not required, it can be convenient to implement them in PostScript. @@ -522,11 +524,7 @@ See also the [[https://developer.mozilla.org/samples/canvas-tutorial/2_6_canvas_ #+html: <div id="heart"> #+include "heart.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xheart"), [$$("wps"), $$("heart")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xheart) .setGc", $$("heart"), "restore");</script> ** Rectangle example @@ -534,11 +532,7 @@ wps($("xheart"), [$$("wps"), $$("heart")]); #+html: <div id="rect"> #+include "rect.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xrect"), [$$("wps"), $$("rect")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xrect) .setGc", $$("rect"), "restore");</script> ** Triangles example @@ -548,11 +542,7 @@ See also the [[https://developer.mozilla.org/samples/canvas-tutorial/2_3_canvas_ #+html: <div id="triangles"> #+include "triangles.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xtriangles"), [$$("wps"), $$("triangles")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xtriangles) .setGc", $$("triangles"), "restore");</script> ** Smile example @@ -562,11 +552,7 @@ See also the [[http://developer.mozilla.org/samples/canvas-tutorial/2_2_canvas_m #+html: <div id="smile"> #+include "smile.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xsmile"), [$$("wps"), $$("smile")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xsmile) .setGc", $$("smile"), "restore");</script> ** Star example @@ -576,11 +562,7 @@ See also the [[http://www.adobe.com/technology/pdfs/presentations/KingPDFTutoria #+html: <div id="star"> #+include "star.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xstar"), [$$("wps"), $$("star")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xstar) .setGc", $$("star"), "restore");</script> ** Squares example @@ -590,11 +572,7 @@ See also the [[https://developer.mozilla.org/samples/canvas-tutorial/5_1_canvas_ #+html: <div id="squares"> #+include "squares.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xsquares"), [$$("wps"), $$("squares")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xsquares) .setGc", $$("squares"), "restore");</script> ** Two squares example @@ -604,11 +582,7 @@ See also the [[https://developer.mozilla.org/en/drawing_graphics_with_canvas][or #+html: <div id="squares2"> #+include "squares2.wps" src ps #+html: </div> -#+begin_html -<script> -wps($("xsquares2"), [$$("wps"), $$("squares2")]); -</script> -#+end_html +#+html: <script>wps.parse("save (xsquares2) .setGc", $$("squares2"), "restore");</script> * Operators and JavaScript bindings @@ -617,11 +591,11 @@ implemented in PostScript itself. Many JavaScript data types map quite easily to PostScript data types so native bindings can be implemented mostly in PostScript via -PostScript dictionaries. [[http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element][HTML 5 canvas API]] bindings are quite -straightforward. Probably the trickiest bit is implementing callbacks -to handle [[http://en.wikipedia.org/wiki/Document_Object_Model][DOM]] events using PostScript code. +PostScript dictionaries (JavaScript objects). [[http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element][HTML 5 canvas API]] +bindings are quite straightforward. Probably the trickiest bit is +implementing callbacks to handle [[http://en.wikipedia.org/wiki/Document_Object_Model][DOM]] events using PostScript code. -** Built-in operators +** Native operators | category | in | operator | out | |----------------+-------------------------+------------------+-------------------------------------------------------------| @@ -929,4 +903,4 @@ implemented directly in JavaScript. It is faster than WPS but not a [[http://svgkit.sourceforge.net/][SVGKit]] has a PostScript interpreter on the wish list. -Postscript is a registered trademark of [[http://www.adobe.com][Adobe Systems Incorporated]]. +PostScript is a registered trademark of [[http://www.adobe.com][Adobe Systems Incorporated]].