wps

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

commit 676ee856da06028ea3d77722dcc88594178844ea
parent 6898dc118663b89e6b74306502fe4c7d0817a9c2
Author: tomas <tomas@logand.com>
Date:   Sat, 23 Jan 2010 15:13:01 +0100

changes from 2009-07-14

Diffstat:
Mwps.js | 182++++++++++++++++++++++++++++++++-----------------------------------------------
Mwps.wps | 68++++++++++++++++++++++++++++++++++++++++++++------------------------
2 files changed, 117 insertions(+), 133 deletions(-)

diff --git a/wps.js b/wps.js @@ -37,16 +37,24 @@ function inDs(Ds, K) { return false; } -function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? - var N = L.length; - var I = 0; - - // TODO white space ffeed + null??? - function member(C, L) {return 0 <= L.indexOf(C);} - function peek() {return I < N && L[I];} - function xchar() {return I < N && L[I++];} - function skip() {while(I < N && member(L[I], " \t\n")) I++;} +function member(C, L) { + return 0 <= L.indexOf(C); +} +function PsParser() { + var Self = this; + function init(L) { + Self.L = L; + Self.N = L.length; + Self.I = 0; + Self.D = 0; + } + function peek() {return Self.I < Self.N && Self.L[Self.I];} + function xchar() {return Self.I < Self.N && Self.L[Self.I++];} + function skip() { // TODO white space ffeed + null??? + while(Self.I < Self.N && member(Self.L[Self.I], " \t\n")) + Self.I++; + } function comment() { while("%" == peek()) { while(peek() && "\n" != peek()) @@ -54,7 +62,6 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? skip(); } } - function text() { // TODO hex text in <> // TODO ASCII base-85 <~ and ~> @@ -90,7 +97,6 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? } return L.join(""); } - function symbol() { // TODO 1e10 1E-5 real numbers // TODO radix numbers 8#1777 16#FFFE 2#1000 @@ -111,9 +117,6 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? if(1 == L.length && member(L, "+-.")) N = false; return N ? (F ? parseFloat(L) : parseInt(L, 10)) : new Symbol(L); } - - var D = 0; - function token() { skip(); switch(peek()) { // TODO read dict in <> <~~> <<>> immediate literal // @@ -121,8 +124,8 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? case "%": return comment(); case "[": return new Symbol(xchar()); case "]": return new Symbol(xchar()); - case "{": D++; return new Symbol(xchar()); - case "}": D--; return new Symbol(xchar()); + case "{": Self.D++; return new Symbol(xchar()); + case "}": Self.D--; return new Symbol(xchar()); case "/": xchar(); var X = symbol(); return quote(X); case "(": return text(); case "<": @@ -138,38 +141,34 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? default: return symbol(); } } + PsParser.prototype.init = init; + PsParser.prototype.peek = peek; + PsParser.prototype.token = token; + return this; +} - //function Xexec() {Es.push([false, Os.pop()]);}; - +function Ps0(Os, Ds, Es) { function run(X, Z) { if(isSymbol(X) && !isQuoted(X)) { // executable name var K = symbolName(X); var D = inDs(Ds, K); - if(!D) { + if(!D) throw "bind error '" + K + "'"; - } Es.push([false, D[K]]); - //if(V !== undefined) Es.push([false, V, Xexec]); - //else throw "Unknown operator '" + K + "' " + V; } else if(Z && isArray(X) && isQuoted(X)) { // proc from Es if(0 < X.length) { var F = X[0]; var R = quote(X.slice(1)); - //if(0 < R.length) Es.push([false, R, Xexec]); if(0 < R.length) Es.push([false, R]); - //run(F, true); run(F, false); - //Es.push([false, F]); } } else if("function" == typeof X) X(); // operator else Os.push(X); } - function exec() { var X = Os.pop(); run(X, false); } - function step() { var C = Es.pop(); var L = C.shift(); // TODO use for 'exit' @@ -178,13 +177,14 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? Os.push(C[I]); run(X, true); } - - function parse() { - while(peek()) { - var T = token(); + var PsP = new PsParser; + function parse(L) { + PsP.init(L); + while(PsP.peek()) { + var T = PsP.token(); if(T || T === 0) { Os.push(T); - if(D <= 0 || isSymbol(T) && + if(PsP.D <= 0 || isSymbol(T) && (member(symbolName(T), "[]{}") || "<<" == symbolName(T) || ">>" == symbolName(T))) { exec(); @@ -195,15 +195,19 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym? } return Os; } - - return parse(); + Ps0.prototype.run = run; + Ps0.prototype.exec = exec; + Ps0.prototype.step = step; + Ps0.prototype.parse = parse; + return this; } -function wps(E, T) { +function Wps() { var Os = []; var Sd = {}; var Ds = [Sd]; var Es = []; + var Ps = new Ps0(Os, Ds, Es); // trivial Sd[".true"] = function() {Os.push(true);}; @@ -293,8 +297,6 @@ function wps(E, T) { Sd["eq"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X == Y);}; Sd["lt"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X < Y);}; - //function Xexec() {Es.push([false, Os.pop()]);}; - //Sd["exec"] = Xexec; Sd["exec"] = function() {Es.push([false, Os.pop()]);}; Sd["ifelse"] = function() { @@ -332,7 +334,7 @@ function wps(E, T) { Sd["get"] = function() { // dict key -- any var K = Os.pop(); var D = Os.pop(); - // TODO other datatypes http://www.capcode.de/help/get + // TODO other datatypes if(isSymbol(K)) Os.push(D[symbolName(K)]); else Os.push(D[K]); }; @@ -340,7 +342,7 @@ function wps(E, T) { var V = Os.pop(); var K = Os.pop(); var D = Os.pop(); - // TODO other datatypes http://www.capcode.de/help/put + // TODO other datatypes if(isSymbol(K)) D[symbolName(K)] = V; else D[K] = V; }; @@ -378,8 +380,24 @@ function wps(E, T) { // savetype }; - Sd["restore"] = function() {Os.pop();}; // TODO - Sd["save"] = function() {Os.push([]);}; // TODO + Sd["save"] = function() { + var X = Ds.slice(); + for(var I = 0; I < X.length; I++) { + var A = X[I]; + var B = {}; + for(var J in A) + B[J] = A[J]; + X[I] = B; + } + Os.push(X); + }; + Sd["restore"] = function() { + var X = Os.pop(); + while(0 < Ds.length) + Ds.pop(); + while(0 < X.length) + Ds.unshift(X.pop()); + }; var Sb = true; Sd[".strictBind"] = function() {Sb = true === Os.pop();}; // bool -- @@ -409,30 +427,6 @@ function wps(E, T) { return X; } -// function bind(X) { -// if(isSymbol(X) && !isQuoted(X)) { -// var K = symbolName(X); -// var D = inDs(Ds, K); -// return !D ? X : bind(D[K]); // TODO .strictBind ??? -// // if(!D) { -// // throw "bind error '" + K + "'"; -// // } -// // return bind(D[K]); -// } else if(isArray(X) && isQuoted(X)) { -// var N = X.length; -// var A = []; -// for(var I = 0; I < N; I++) { -// var Xi = X[I]; -// var Xb = bind(Xi); -// if(isArray(Xi)) -// A = A.concat(isQuoted(Xi) ? quote([Xb]) : [Xb]); -// else -// A = A.concat(Xb); -// } -// return quote(A); -// } -// return X; -// } ////////////////////////////////////////////////////////// // js ffi operators @@ -448,54 +442,18 @@ function wps(E, T) { Sd[".math"] = function() { // -- Math Os.push(Math); }; - Sd[".gc"] = function() { // -- gc - Os.push(E.getContext("2d")); - }; Sd[".date"] = function() { // -- date Os.push(new Date()); }; Sd[".window"] = function() { // -- window Os.push(window); }; - Sd[".callback"] = function() { // body -- callback // TODO refactor properly + Sd[".callback"] = function() { // body -- callback var X = Os.pop(); - Os.push(function() { // TODO fix this mess - //alert(".callback"); - //Es.push([false, X]); // TODO process event in ps0 ??? - function run(X, Z) { - if(isSymbol(X) && !isQuoted(X)) { // executable name - var K = symbolName(X); - var D = inDs(Ds, K); - if(!D) { - throw "bind error '" + K + "'"; - } - Es.push([false, D[K]]); - //if(V !== undefined) Es.push([false, V, Xexec]); - //else throw "Unknown operator '" + K + "' " + V; - } else if(Z && isArray(X) && isQuoted(X)) { // proc from Es - if(0 < X.length) { - var F = X[0]; - var R = quote(X.slice(1)); - //if(0 < R.length) Es.push([false, R, Xexec]); - if(0 < R.length) Es.push([false, R]); - //run(F, true); - run(F, false); - //Es.push([false, F]); - } - } else if("function" == typeof X) X(); // operator - else Os.push(X); - } - function step() { - var C = Es.pop(); - var L = C.shift(); // TODO use for 'exit' - var X = C.pop(); - for(var I = 0; I < C.length; I++) - Os.push(C[I]); - run(X, true); - } - run(X, true); + Os.push(function() { + Ps.run(X, true); while(0 < Es.length) - step(); + Ps.step(); }); }; @@ -544,8 +502,14 @@ function wps(E, T) { Os.push("rgba(" + R + "," + G + "," + B + "," + A + ")"); }; - if(T.length) - for(var I = 0; I < T.length; I++) - ps0(T[I], Os, Ds, Es); - else ps0(T, Os, Ds, Es); + function parse() { + var T = arguments; + if(T.length) + for(var I = 0; I < T.length; I++) + Ps.parse(T[I]); + else Ps.parse(T); + return Os; + } + Wps.prototype.parse = parse; + return this; } diff --git a/wps.wps b/wps.wps @@ -134,6 +134,8 @@ systemdict/def{currentdict 2 index 2 index put pop pop}put %% html5 +/.setGc{.getElementById(2d)exch(getContext)1 .call/.$gc .xdef}.bdef +/.gc{/.$gc load}.bdef /.gget{.gc exch get}.bdef /.gput{.gc 3 1 roll exch put}.bdef /.gcall0{.gc 3 1 roll .call pop}.bdef @@ -221,41 +223,40 @@ systemdict/def{currentdict 2 index 2 index put pop pop}put /.deg2rad{.pi 180 div mul}.bdef /.rad2deg{180 .pi div mul}.bdef -/.cx 0 def -/.cy 0 def -/.px 0 def -/.py 0 def -/.setPoint{/.cy .xdef/.cx .xdef}.bdef -/.setPath{/.py .xdef/.px .xdef}.bdef -/currentpoint{/.cx load /.cy load}.bdef -/.getPath{/.px load /.py load}.bdef +/.$cx 0 def +/.$cy 0 def +/.$px 0 def +/.$py 0 def +/.setPoint{/.$cy .xdef/.$cx .xdef}.bdef +/.setPath{/.$py .xdef/.$px .xdef}.bdef +/currentpoint{/.$cx load /.$cy load}.bdef +/.getPath{/.$px load /.$py load}.bdef /identmatrix{pop [1 0 0 1 0 0]}.bdef % TODO fill /matrix{6 array identmatrix}.bdef -/setmatrix{/.tm .xdef}.bdef +/setmatrix{/.$tm .xdef}.bdef /defaultmatrix{pop matrix}.bdef % TODO fill /initmatrix{matrix defaultmatrix setmatrix}.bdef -/currentmatrix{pop /.tm load}.bdef % TODO fill +/currentmatrix{pop /.$tm load}.bdef % TODO fill initmatrix %/matrix load = %matrix = -/.getTmd{/.tmd load}.bdef -/.setTmd{/.tmd .xdef}.bdef +/.getTmd{/.$tmd load}.bdef +/.setTmd{/.$tmd .xdef}.bdef /.resetTmd{matrix .setTmd}.bdef .resetTmd /.update{ % m -- - %dup .cx exch .cy exch % m .cx .cy m - currentpoint 2 index % m .cx .cy m + currentpoint 2 index % m .$cx .$cy m .xy .setPoint % m - dup .getTmd exch .mmul .setTmd % (.tmd x m) - dup currentmatrix exch .mmul setmatrix % = .tm x m + dup .getTmd exch .mmul .setTmd % (.$tmd x m) + dup currentmatrix exch .mmul setmatrix % = .$tm x m }.bdef -/transform{dup type(arraytype)ne{.getTmd}if .xy}.bdef % TODO why .tmd not .tm? -/itransform{dup type(arraytype)ne{.getTmd}if .minv .xy}.bdef % TODO why .tmd not .tm? +/transform{dup type(arraytype)ne{.getTmd}if .xy}.bdef % TODO why .$tmd not .$tm? +/itransform{dup type(arraytype)ne{.getTmd}if .minv .xy}.bdef % TODO why .$tmd not .$tm? /.scaleM{0 0 3 2 roll 0 0 6 array astore}.bdef % x y -- [x 0 0 y 0 0] /.scale3{pop .scaleM}.bdef @@ -272,7 +273,6 @@ initmatrix /.rotate1{.deg2rad dup .rotateM .update .rotate}.bdef /rotate{dup type(arraytype)eq{.rotate2}{.rotate1}ifelse}.bdef - %matrix concat – Replace CTM by matrix ´ CTM %matrix1 matrix2 matrix3 concatmatrix matrix3 Fill matrix3 with matrix1 ´ matrix2 @@ -308,19 +308,17 @@ initmatrix /setgray{255 mul dup dup .rgb dup .setStrokeStyle .setFillStyle}.bdef /setrgbcolor{3{255 mul round 3 1 roll}repeat .rgb dup .setStrokeStyle .setFillStyle}.bdef -/setfont{}.bdef % TODO C.font = N + "pt " + F.V; +/setcmykcolor{setrgbcolor pop}.bdef % TODO +/sethsbcolor{setrgbcolor}.bdef % TODO /clippath{0 0 .gcanvas(width)get .gcanvas(height)get .rect}.bdef % TODO /show{currentpoint 3 2 roll 3 copy .fillText .strokeText}.bdef % TODO -%/rlineto{.getTmd .xy .py add exch .px add exch .getTmd .minv .xy lineto}.bdef -/rlineto{.getTmd .xy /.py load add exch /.px load add exch .getTmd .minv .xy lineto}.bdef +/rlineto{.getTmd .xy /.$py load add exch /.$px load add exch .getTmd .minv .xy lineto}.bdef /curveto{2 copy .setPoint 2 copy .setPath .resetTmd .bezierCurveTo}.bdef /currentflat{42}.bdef % TODO /setflat{pop}.bdef % TODO -/showpage{}.bdef % TODO - /arc{.deg2rad exch .deg2rad exch true .arc}.bdef % TODO currentpoint /arcn{.deg2rad exch .deg2rad exch false .arc}.bdef % TODO currentpoint @@ -330,7 +328,29 @@ initmatrix /stroke{.stroke newpath currentpoint .moveTo}.bdef +/showpage{}.bdef % TODO /grestoreall{}.bdef % TODO +/readonly{}.bdef % TODO +/currentfile{(url?)}.bdef % TODO +/eexec{pop}.bdef % TODO +/findfont{}.bdef % TODO +/scalefont{pop}.bdef % TODO +/setfont{pop}.bdef % TODO C.font = N + "pt " + F.V; +/stopped{}.bdef % TODO +/loop{}.bdef % TODO !!! +/string{}.bdef % TODO +/cvi{}.bdef % TODO +/pathbbox{}.bdef % TODO +/urx{}.bdef % TODO +/ury{}.bdef % TODO +/llx{}.bdef % TODO +/lly{}.bdef % TODO +/pagewidth{}.bdef % TODO +/pageheight{}.bdef % TODO +/inwidth{}.bdef % TODO +/inheight{}.bdef % TODO +/usertime{}.bdef % TODO +/srand{}.bdef % TODO %% PDF