wps

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

commit 6f9bd88894ebf146a8a1af7728545026aa3a5153
parent ff872314c1b478b69cd65583bc4d25099225231d
Author: tomas <tomas@logand.com>
Date:   Sat, 23 Jan 2010 14:48:13 +0100

Changes from 2009-06-20

Diffstat:
Aindex.org | 1191+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1191 insertions(+), 0 deletions(-)

diff --git a/index.org b/index.org @@ -0,0 +1,1191 @@ +* Postscript interpreter + +- S :: stack +- F :: function dictionary + +** Trivial example + +#+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["."](); +} +</script> +<button onclick="javascript:ex1()">Eval</button> +"<tt>1 2 . 2 + .</tt>" from stack +#+end_html + +** Example with simple reader + +#+begin_html +<script> +function PdfT(V) { + this.V = V; + return this; +} +function isPdfT(V) { + return V.constructor == PdfT; // TODO better test +} + +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(); +} + +function quoted(T) { + return typeof T == "string" && "/" == T.charAt(0); +} + + + +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;}); +} + +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); +} +</script> +<button onclick="javascript:ex2()">Eval</button> +"<tt id="ex2">12 34 + dup . 56 + .</tt>" from string +#+end_html + +#+begin_src text +{ /category (COOKING) } + +: sum +1 2 + ; + +1 (sdfsdf) /Tf + +12 34 (cooking is fun) /Tf + +{ /key (value) } +#+end_src + +* PDF drawing + + +#+html: <div id="wps"> +#+include "wps.wps" src ps +#+html: </div> + +#+html: <div id="bowtie"> +#+include "bowtie.wps" src ps +#+html: </div> + + + + + +#+begin_html +<pre id="ex3x"> +1 2.3 + -5.6 + . +</pre> +<pre id="ex3"> + +%%% ps operators + +/setlinewidth {/lineWidth gput} def + +/setlinecap {/lineCap gput} def + +/setlinejoin {/lineJoin gput} def + +/setmiterlimit {/miterLimit gput} def + +/setgray {255 mul dup dup rgb /fillStyle gput} def + +%%% examples + +1 0 0 -1 0 446 cm % 0,0 in bottom left corner + +% E1 + +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 + +% E2 + +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 + +% E3 + +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 + +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 + +% Ex4 + +q +%BT +%/F1 24 Tf +%1 0 0 1 260 600 Tm +%/CS1 cs +%63 127 127 sc +%(Hello World)Tj +%ET +%100 0 127 sc +%/CS2 CS +%0 0 1 SC +%315 572 m +%299 528 l +%339 554 l +%291 554 l +%331 528 l +%b +q +0 255 255 rg +4 0 0 4 315 550 cm +0 5.5 m +-4 -5.5 l + 6 1 l +-6 1 l + 4 -5.5 l +f +Q +%/CS1 cs +%63 127 127 sc +1 0 0 1 315 490 cm +0 0 m + -7 23 -40 19 -15 -17 c + -7.5 -27.8 -11 -22 0 -35 c + 11 -22 7.5 -27.8 15 -17 c + 40 19 7 23 0 0 c +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 +%50 120 30 125 c2 +%60 120 65 100 c2 +%125 100 125 62.5 c2 +%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 + 0 72 l + -72 0 l + h f +} def + +1 0 0 1 -452 124 cm +box +0 setgray fill +1 0 0 1 27.0 36.0 cm +box +.4 setgray fill +1 0 0 1 28.8 39.6 cm +box +.8 setgray fill + +% 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> + +<script> +function min(X, Y) { + return X < Y ? X : Y; +} + +function max(X, Y) { + return X < Y ? Y : X; +} + +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 +// }; + 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); +} +</script> +<button onclick="javascript:ex3()">Draw</button> +#+end_html + +/MediaBox [0 0 612 446] + +#+html: <canvas id="c" style="width:612pt;height:446pt;background-color:yellow"/> + +** CanvasRenderingContext2D + +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 +charpath setdash image putinterval dict begin settransfer +readhexstring flattenpath curveto pathbbox pathforall search transform +itransform definefont setrgbcolor setcharwidth + + setmatrix + +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 + +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