wps

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

commit 63f258e83e92979388721f57ff1f9500140f6ea6
parent 900ea78da3b57a7c03a76609c671676c2bd13dd1
Author: tomas <tomas@logand.com>
Date:   Sat, 23 Jan 2010 14:23:42 +0100

Second commit

Diffstat:
Mwps.js | 794+++++++++++++++++++++++++++----------------------------------------------------
Mwps.wps | 411++++++++++++++++++++++++++++++++++++++++++-------------------------------------
2 files changed, 490 insertions(+), 715 deletions(-)

diff --git a/wps.js b/wps.js @@ -1,252 +1,265 @@ function PdfT(V) { - this.V = V; - return this; + this.V = V; + return this; } + function isPdfT(V) { - return V.constructor == PdfT; // TODO better test + return V.constructor == PdfT; // TODO better test } function ps0(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 xchar() {return I < N && L[I++];} - function skip() {while(I < N && member(L[I], " \t\n")) I++;} - - function comment() { - while("%" == peek()) { - while(peek() && "\n" != peek()) - xchar(); - skip(); - } - } - - function text() { - xchar(); - var L = []; - var N = 1; - while(0 < N && peek()) { - var C = xchar(); - switch(C) { - case "(": - N++; - break; - case ")": - N--; - if(N <= 0) C = false; - break; - case "\\": - C = xchar(); - 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 N = L.length; + var I = 0; + + 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 comment() { + while("%" == peek()) { + while(peek() && "\n" != peek()) + xchar(); + skip(); + } + } + + function text() { // TODO hex text in <> + xchar(); + var L = []; + var N = 1; + while(0 < N && peek()) { var C = xchar(); - var N = member(C, "+-0123456789."); - var F = "." == C; - var L = [C]; - while(peek() && !member(peek(), "%/[]{}<>( \t\n")) { - C = xchar(); - L.push(C); - if(N && !member(C, "0123456789")) { - if(!F && "." == C) F = true; - else N = false; - } + switch(C) { + case "(": + N++; + break; + case ")": + N--; + if(N <= 0) C = false; + break; + case "\\": + C = xchar(); + 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; } - L = L.join(""); - if(1 == L.length && member(L, "+-.")) N = false; - return N ? (F ? parseFloat(L) : parseInt(L, 10)) : L; - } - - function code() { - xchar(); - var L = []; - while(peek()) { - var T = token(); - if("}" == T) break; - if(T || T == 0) L.push(T); + if(C !== false) L.push(C); + } + return new PdfT(L.join("")); + } + + function symbol() { + var C = xchar(); + var N = member(C, "+-0123456789."); + var F = "." == C; + var L = [C]; + while(peek() && !member(peek(), "%/[]{}<>( \t\n")) { + C = xchar(); + L.push(C); + if(N && !member(C, "0123456789")) { + if(!F && "." == C) F = true; + else N = false; } - return L; - } - - function token() { - skip(); - switch(peek()) { - case false: return undefined; - case "%": return comment(); - case "[": return xchar(); - case "]": return xchar(); - case "{": return code(); - case "}": return xchar(); - case "(": return text(); - default: return symbol(); - } - } + } + L = L.join(""); + if(1 == L.length && member(L, "+-.")) N = false; + return N ? (F ? parseFloat(L) : parseInt(L, 10)) : L; + } + + function proc() { // TODO supress evaluation??? + xchar(); + var L = []; + while(peek()) { + var T = token(); + if("}" == T) break; + if(T || T == 0) L.push(T); + } + return L; + } + + function token() { + skip(); + switch(peek()) { // TODO read dict in <<>> + case false: return undefined; + case "%": return comment(); + case "[": return xchar(); + case "]": return xchar(); + case "{": return proc(); + case "}": return xchar(); + 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; - } - } + 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 S; + } - return parse(); + return parse(); } function quoted(T) { - return typeof T == "string" && "/" == T.charAt(0); + return typeof T == "string" && "/" == T.charAt(0); } -function wps(E, W, H, T) { - var S = []; - var F = {}; - var C = E.getContext("2d"); - - E.setAttribute("width", W); - E.setAttribute("height", H); - - function min(X, Y) { - return X < Y ? X : Y; - } - function max(X, Y) { - return X < Y ? Y : X; - } - - // basic operators - - F["true"] = function() {S.push(true);}; - F["false"] = function() {S.push(false);}; - F["null"] = function() {S.push(null);}; - - 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); - } +function wps(E, T) { + var S = []; + var F = {}; + var C = E.getContext("2d"); + + F["get"] = function() { // dict key -- any + var K = S.pop(); + var D = S.pop(); + // TODO other datatypes http://www.capcode.de/help/get + S.push(D[K.substring(1)]); + }; + F["put"] = function() { // dict key any -- + var V = S.pop(); + var K = S.pop(); + var D = S.pop(); + // TODO other datatypes http://www.capcode.de/help/put + D[K.substring(1)] = V; + }; + + F["true"] = function() {S.push(true);}; + F["false"] = function() {S.push(false);}; + F["null"] = function() {S.push(null);}; + + F["neg"] = function() {S.push(- S.pop());}; + F["add"] = function() {S.push(S.pop() + S.pop());}; + 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.length = 0;}; + F["pop"] = function() {S.pop();}; + F["roll"] = function() { // n j -- + var J = S.pop(); + var N = S.pop(); + var X = []; + var Y = []; + //alert("roll 1 " + N + " " + J + " " + S); + for(var I = 0; I < N; I++) + if(I < J) X.unshift(S.pop()); + else Y.unshift(S.pop()); + for(I = 0; I < J; I++) S.push(X.shift()); + for(I = 0; I < N - J; I++) S.push(Y.shift()); + //alert("roll 2 " + N + " " + J + " " + S); + }; + + 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);}; + F["."] = function() {alert(S.pop());}; + F["=="] = function() {alert(S[0]);}; + F["pstack"] = function() {alert(S);}; function run(C) { if(!C.length) S.push(C); @@ -271,305 +284,40 @@ function wps(E, W, H, T) { else throw "Wrong operator name " + N + " for " + C; }; - // 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 + // js ffi operators - // html5 utility operators - - F["gput"] = function() { - var K = S.pop(); + F["call"] = function() { // fn nargs -- ... + var A = S.pop(); + var N = S.pop(); + var X = []; + for(var I = 0; I < A; I++) { + // TODO fix PdfT + quoted 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 B = S.pop(); - var R = S.pop(); - var Y = S.pop(); - var X = S.pop(); - C.arc(X, Y, R, B, E, A); - }; - F["fill"] = function() {C.fill();}; - F["stroke"] = function() {C.stroke();}; - F["clip"] = function() {C.clip();}; - F["setgray"] = function() { - var G = S.pop(); - C.fillStyle = "rgb(" + G * 255 + "," + G * 255 + "," + G * 255 + ")"; - }; - - // TODO eps operators - - F["save"] = function() {S.push(true);}; - F["restore"] = function() {S.push(true);}; - F["bind"] = function() {}; - F["dict"] = function() {}; - F["load"] = function() {}; - F["begin"] = function() {}; - F["end"] = function() {}; - F["where"] = function() {}; - F["currentflat"] = function() {}; - F["setflat"] = function() {}; - F["_"] = function() {}; - F["clippath"] = function() {}; - - // 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 -// }; - 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");}; + X.unshift(isPdfT(V) ? V.V : (quoted(V) ? V.substring(1) : V)); + } + alert("call " + N + " " + A); + N.apply(this, X); + }; + + F["gc"] = function() { // -- gc + S.push(C); + }; + + // html5 utility operators + + F["rgb"] = function() { + var B = S.pop(); + var G = S.pop(); + var R = S.pop(); + S.push(new PdfT("rgb(" + 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 + ")")); + }; if(T.length) for(var I = 0; I < T.length; I++) diff --git a/wps.wps b/wps.wps @@ -1,207 +1,241 @@ -%%% wps.wps -- postscript and pdf operators for html 5 canvas %%% (c) 2009 Tomas Hlavaty -%% basic operators - -/sub { % num num -- num - neg add -} def - -%% html5 operators +%% math + +/abs {.math (abs) 1 .call} def +/.acos {.math (acos) 1 .call} def +/.asin {.math (asin) 1 .call} def +/atan {exch .math (atan) 1 .call} def +/.atan2 {.math (atan2) 2 .call} def +/ceiling {.math (ceil) 1 .call} def +/cos {.math (cos) 1 .call} def +/.exp {.math (exp) 1 .call} def +/floor {.math (floor) 1 .call} def +/log {.math (log) 1 .call} def +/.max {.math (max) 2 .call} def +/.min {.math (min) 2 .call} def +/.pow {.math (pow) 2 .call} def +/.random {.math (random) 0 .call} def +/rand {.random} def % TODO follow spec +/round {.math (round) 1 .call} def +/sin {.math (sin) 1 .call} def +/sqrt {.math (sqrt) 1 .call} def +/.tan {.math (tan) 1 .call} def +/truncate {.math (truncate) 1 .call} def % TODO Math.truncate does not exist! + +/.e {.math (E) get} def +/.ln2 {.math (LN2) get} def +/.ln10 {.math (LN10) get} def +/.log2e {.math (LOG2E) get} def +/.log10e {.math (LOG10E) get} def +/.pi {.math (PI) get} def +/.sqrt1_2 {.math (SQRT1_2) get} def +/.sqrt2 {.math (SQRT2) get} def + +/sub {neg add} def +/idiv {div .floor} def + +%% html5 /.gget { % key -- - gc exch + .gc exch get } def /.gput { % any key -- - gc 3 1 roll exch + .gc 3 1 roll exch put } def -/.gcall { % key nargs -- - gc 3 1 roll call +/.gcall0 { % key nargs -- + .gc 3 1 roll .call pop +} def + +/.gcall1 { % key nargs -- result + .gc 3 1 roll .call } def /.gcanvas { % -- canvas - /canvas .gget + (canvas) .gget } def /.gdim { % w h -- - .gcanvas exch /height exch put - .gcanvas exch /width exch put + .gcanvas exch (height) exch put + .gcanvas exch (width) exch put } def -/gbox { % x0 y0 x1 y1 -- +/.gbox { % x0 y0 x1 y1 -- % TODO compute properly .gdim pop pop } def -/.save {/save 0 .gcall} def -/.restore {/restore 0 .gcall} def +/.save {(save) 0 .gcall0} def +/.restore {(restore) 0 .gcall0} def /scale { % x y -- - /scale 2 .gcall + (scale) 2 .gcall0 } def /rotate { % angle -- - /rotate 1 .gcall + (rotate) 1 .gcall0 } def /translate { % x y -- - /translate 2 .gcall + (translate) 2 .gcall0 } def -/transform { % m11 m12 m21 m22 dx dy -- - /transform 6 .gcall +/.transform { % m11 m12 m21 m22 dx dy -- + (transform) 6 .gcall0 } def -/setTransform { % m11 m12 m21 m22 dx dy -- - /setTransform 6 .gcall +/.setTransform { % m11 m12 m21 m22 dx dy -- + (setTransform) 6 .gcall0 } def -/createLinearGradient { % x0 y0 x1 y1 -- CanvasGradient - /createLinearGradient 4 .gcall +/.createLinearGradient { % x0 y0 x1 y1 -- CanvasGradient + (createLinearGradient) 4 .gcall1 } def -/createRadialGradient { % x0 y0 r0 x1 y1 r1 -- CanvasGradient - /createRadialGradient 6 .gcall +/.createRadialGradient { % x0 y0 r0 x1 y1 r1 -- CanvasGradient + (createRadialGradient) 6 .gcall1 } def -/createPattern { % image repetition -- CanvasPattern - /createPattern 2 .gcall +/.createPattern { % image repetition -- CanvasPattern + (createPattern) 2 .gcall1 } def /.clearRect { % x y w h -- - /clearRect 4 .gcall + (clearRect) 4 .gcall0 } def /.fillRect { % x y w h -- - /fillRect 4 .gcall + (fillRect) 4 .gcall0 } def /.strokeRect { % x y w h -- - /strokeRect 4 .gcall + (strokeRect) 4 .gcall0 } def -/.beginPath {/.beginPath 0 .gcall} def -/.closePath {/.closePath 0 .gcall} def +/.beginPath {(beginPath) 0 .gcall0} def +/.closePath {(closePath) 0 .gcall0} def /.moveTo { % x y -- - /moveTo 2 .gcall + (moveTo) 2 .gcall0 } def /.lineTo { % x y -- - /lineTo 2 .gcall + (lineTo) 2 .gcall0 } def -/quadraticCurveTo { % cpx cpy x y -- - /quadraticCurveTo 4 .gcall +/.quadraticCurveTo { % cpx cpy x y -- + (quadraticCurveTo) 4 .gcall0 } def -/bezierCurveTo { % cp1x cp1y cp2x cp2y x y -- - /bezierCurveTo 6 .gcall +/.bezierCurveTo { % cp1x cp1y cp2x cp2y x y -- + (bezierCurveTo) 6 .gcall0 } def /.arcTo { % x1 y1 x2 y2 radius -- - /arcTo 5 .gcall + (arcTo) 5 .gcall0 } def -/rect { % x y w h -- - /rect 4 .gcall +/.rect { % x y w h -- + (rect) 4 .gcall0 } def /arc { % x y radius startAngle endAngle anticlockwise -- - /arc 6 .gcall + (arc) 6 .gcall0 } def /fill { % -- - /fill 0 .gcall + (fill) 0 .gcall0 } def /stroke { % -- - /stroke 0 .gcall + (stroke) 0 .gcall0 } def /clip { % -- - /clip 0 .gcall + (clip) 0 .gcall0 } def -/isPointInPath { % x y -- boolean - /isPointInPath 2 .gcall +/.isPointInPath { % x y -- boolean + (isPointInPath) 2 .gcall1 } def -/fillText { % text x y maxWidth -- - /fillText 4 .gcall +/.fillText { % text x y maxWidth -- + (fillText) 4 .gcall0 } def -/strokeText { % text x y maxWidth -- - /strokeText 4 .gcall +/.strokeText { % text x y maxWidth -- + (strokeText) 4 .gcall0 } def -/measureText { % text -- TextMetrics - /measureText 1 .gcall +/.measureText { % text -- TextMetrics + (measureText) 1 .gcall1 } def -/drawImage1 { % image dx dy dw dh -- - /drawImage1 5 .gcall +/.drawImage1 { % image dx dy dw dh -- + (drawImage1) 5 .gcall0 } def -/drawImage2 { % image sx sy sw sh dx dy dw dh -- - /drawImage2 9 .gcall +/.drawImage2 { % image sx sy sw sh dx dy dw dh -- + (drawImage2) 9 .gcall0 } def -/createImageData1 { % imagedata -- ImageData - /createImageData1 1 .gcall +/.createImageData1 { % imagedata -- ImageData + (createImageData1) 1 .gcall1 } def -/createImageData2 { % sw sh -- ImageData - /createImageData2 2 .gcall +/.createImageData2 { % sw sh -- ImageData + (createImageData2) 2 .gcall1 } def -/getImageData { % sx sy sw sh -- - /getImageData 4 .gcall +/.getImageData { % sx sy sw sh -- + (getImageData) 4 .gcall1 } def -/putImageData { % imagedata dx dy dirtyX dirtyY dirtyWidth dirtyHeight -- - /putImageData 7 .gcall +/.putImageData { % imagedata dx dy dirtyX dirtyY dirtyWidth dirtyHeight -- + (putImageData) 7 .gcall0 } def -/getGlobalAlpha {/globalAlpha .gget} def -/getGlobalCompositeOperation {/globalCompositeOperation .gget} def % TODO str -/getStrokeStyle {/strokeStyle .gget} def % TODO str -/getFillStyle {/fillStyle .gget} def % TODO str -/.getLineWidth {/lineWidth .gget} def -/.getLineCap {/lineCap .gget} def % TODO str -/.getLineJoin {/lineJoin .gget} def % TODO str -/.getMiterLimit {/miterLimit .gget} def -/getShadowOffsetX {/shadowOffsetX .gget} def -/getShadowOffsetY {/shadowOffsetY .gget} def -/getShadowBlur {/shadowBlur .gget} def -/getShadowColor {/shadowColor .gget} def % TODO str -/.getFont {/font .gget} def % TODO str -/getTextAlign {/textAlign .gget} def % TODO str -/getTextBaseline {/textBaseline .gget} def % TODO str +/.getGlobalAlpha {(globalAlpha) .gget} def +/.getGlobalCompositeOperation {(globalCompositeOperation) .gget} def +/.getStrokeStyle {(strokeStyle) .gget} def +/.getFillStyle {(fillStyle) .gget} def +/.getLineWidth {(lineWidth) .gget} def +/.getLineCap {(lineCap) .gget} def +/.getLineJoin {(lineJoin) .gget} def +/.getMiterLimit {(miterLimit) .gget} def +/.getShadowOffsetX {(shadowOffsetX) .gget} def +/.getShadowOffsetY {(shadowOffsetY) .gget} def +/.getShadowBlur {(shadowBlur) .gget} def +/.getShadowColor {(shadowColor) .gget} def +/.getFont {(font) .gget} def +/.getTextAlign {(textAlign) .gget} def +/.getTextBaseline {(textBaseline) .gget} def -/setGlobalAlpha {/globalAlpha .gput} def -/setGlobalCompositeOperation {/globalCompositeOperation .gput} def % TODO str -/setStrokeStyle {/strokeStyle .gput} def % TODO str -/setFillStyle {/fillStyle .gput} def % TODO str -/.setLineWidth {/lineWidth .gput} def -/.setLineCap {/lineCap .gput} def % TODO str -/.setLineJoin {/lineJoin .gput} def % TODO str -/.setMiterLimit {/miterLimit .gput} def -/setShadowOffsetX {/shadowOffsetX .gput} def -/setShadowOffsetY {/shadowOffsetY .gput} def -/setShadowBlur {/shadowBlur .gput} def -/setShadowColor {/shadowColor .gput} def % TODO str -/.setFont {/font .gput} def % TODO str -/setTextAlign {/textAlign .gput} def % TODO str -/setTextBaseline {/textBaseline .gput} def % TODO str +/.setGlobalAlpha {(globalAlpha) .gput} def +/.setGlobalCompositeOperation {(globalCompositeOperation) .gput} def +/.setStrokeStyle {(strokeStyle) .gput} def +/.setFillStyle {(fillStyle) .gput} def +/.setLineWidth {(lineWidth) .gput} def +/.setLineCap {(lineCap) .gput} def +/.setLineJoin {(lineJoin) .gput} def +/.setMiterLimit {(miterLimit) .gput} def +/.setShadowOffsetX {(shadowOffsetX) .gput} def +/.setShadowOffsetY {(shadowOffsetY) .gput} def +/.setShadowBlur {(shadowBlur) .gput} def +/.setShadowColor {(shadowColor) .gput} def +/.setFont {(font) .gput} def +/.setTextAlign {(textAlign) .gput} def +/.setTextBaseline {(textBaseline) .gput} def -%% PostScript operators +%% PostScript + +% TODO track state, e.g. origin x y /gsave {.save} def /grestore {.restore} def @@ -251,112 +285,105 @@ /setgray { % gray -- 255 mul dup dup - rgb setFillStyle + .rgb .setFillStyle } def /setrgbcolor { % r g b -- 3 {255 * 3 1 roll} repeat - rgb setFillStyle + .rgb .setFillStyle } def /setfont { % font -- % TODO C.font = N + "pt " + F.V; } def -% F["save"] = function() {S.push(true);}; -% F["restore"] = function() {S.push(true);}; -% F["bind"] = function() {}; -% F["dict"] = function() {}; -% F["load"] = function() {}; -% F["begin"] = function() {}; -% F["end"] = function() {}; -% F["where"] = function() {}; -% F["currentflat"] = function() {}; -% F["setflat"] = function() {}; -% F["_"] = function() {}; -% F["clippath"] = function() {}; - -%% PDF operators - -/w { - setlinewidth -} def - -/J { - setlinecap -} def - -/j { - setlinejoin -} def - -/M { - setmitterlimit -} def - -/q {gsave} def -/Q {grestore} def - -/cm { - transform +/clippath { % -- + % TODO } def -/m { - newpath % TODO only if not m previously - moveto +/show { % string -- + % TODO + %0 exch 0 exch .fillText + .fillText } def -/l { +/rlineto { % x y -- + % TODO lineto } def -/c { - bezierCurveTo -} def - -/h {closepath} def - -/re { - rect -} def - -/S {stroke} def -/s {h S} def -/f {fill} def -/F {fill} def -/B {f S} def -/B* {f* S} def -/b {h B} def -/b* {h B*} def -/W {clip} def - -/Tf { - setfont -} def - -/Tj { - fillText -} def - -/rg { - % TODO other color spaces - 3 {255 * 3 1 roll} repeat - rgb setFillStyle -} def - -%% other operators - -/pi 3.141592653589 def - -/inch { % num -- - 72 mul -} def - -%/black {0 0 0 setrgbcolor} def -%/red {1 0 0 setrgbcolor} def -%/green {0 1 0 setrgbcolor} def -%/blue {0 0 1 setrgbcolor} def -%/yellow {1 1 0 setrgbcolor} def -%/cyan {0 1 1 setrgbcolor} def -%/magenta {1 0 1 setrgbcolor} def -%/white {1 1 1 setrgbcolor} def +%% PDF + +/w {setlinewidth} def +/J {setlinecap} def % TODO +/j {setlinejoin} def % TODO +/M {setmitterlimit} def +/d {setdash} def % TODO +/ri {} def % TODO +/i {} def % TODO +/gs {} def % TODO +/q {gsave} def +/Q {grestore} def +/cm {.transform} def +/m {newpath moveto} def % TODO only if not m previously +/l {lineto} def +/c {.bezierCurveTo} def +/v {currentpoint cp2 p3 c} def % TODO fix arg order +/y {cp1 p3 p3 c} def % TODO fix arg order +/h {closepath} def % TODO +/re {.rect} def % TODO really, or x y m , x+w y l , x+w y+h l , x y+h l , h +/S {stroke} def +/s {h S} def +/f {fill} def % TODO +/F {f} def +/f* {} def % TODO +/B {f S} def +/B* {f* S} def +/b {h B} def +/b* {h B*} def +/n {} def % TODO +/W {clip} def % TODO +/W* {clip} def % TODO +/BT {} def % TODO +/ET {} def % TODO +/Tc {} def % TODO +/Tw {} def % TODO +/Tz {} def % TODO +/TL {} def % TODO +/Tf {setfont} def % TODO +/Tr {} def % TODO +/Ts {} def % TODO +/Td {} def % TODO +/TD {} def % TODO +/Tm {} def % TODO +/T* {} def % TODO +/Tj {show} def % TODO +/TJ {} def % TODO +%/' {} def % TODO +%/" {} def % TODO +/d0 {} def % TODO +/d1 {} def % TODO +/CS {} def % TODO +/cs {} def % TODO +/SC {} def % TODO +/SCN {} def % TODO +/sc {} def % TODO +/scn {} def % TODO +/G {} def % TODO +/g {} def % TODO +/RG {} def % TODO +/rg {3 {255 * 3 1 roll} repeat .rgb .setFillStyle} def % TODO +/K {} def % TODO +/k {} def % TODO +/sh {} def % TODO +/BI {} def % TODO +/ID {} def % TODO +/EI {} def % TODO +/Do {} def % TODO +/MP {} def % TODO +/DP {} def % TODO +/BMC {} def % TODO +/BDC {} def % TODO +/EMC {} def % TODO +/BX {} def % TODO +/EX {} def % TODO