commit 66a6ea71ddfcfab379efeec941d89957e7242379
parent cb1c91fbac75a952ff4ddbd01adf39df1c81d435
Author: tomas <tomas@logand.com>
Date:   Sat, 23 Jan 2010 14:28:51 +0100
Changes from 2009-06-29
Diffstat:
| M | wps.js |  |  | 197 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- | 
| M | wps.wps |  |  | 267 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------- | 
2 files changed, 292 insertions(+), 172 deletions(-)
diff --git a/wps.js b/wps.js
@@ -144,21 +144,15 @@ function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym?
   function run(X, Z) {
     if(isSymbol(X) && !isQuoted(X)) { // executable name
       var K = symbolName(X);
-//       if("repeat" == K) {
-//         alert("" + inDs(Ds, "def")["setrgbcolor"][1] + "XXX: " + Os + " Z: " + Z);
-//       }
       var D = inDs(Ds, K);
       var V = D && D[K];
-      if(V || V === 0) Es.push([false, V]);
-      else throw "Unknown operator '" + K + "'";
+      if(V !== undefined) Es.push([false, V]);
+      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(isSymbol(X) && !isQuoted(X)) Es.push([false, F]);
-        //else Os.push(F);
-        //alert(R.map(function(E) {return E.nm;}) + "\n" + F.nm);
         run(F, false);
       }
     } else if("function" == typeof X) X(); // operator
@@ -256,7 +250,7 @@ function wps(E, T) {
   Sd["index"] = function() {
     Os.push(Os[Os.length - 2 - Os.pop()]);
   };
-  Sd["roll"] = function() {
+  Sd["roll"] = function() { // TODO in ps
     var J = Os.pop();
     var N = Os.pop();
     var X = [];
@@ -272,11 +266,12 @@ function wps(E, T) {
 	if("object" == typeof N) {
 	  var X = Os.pop();
 	  for(var I in X)
-        N[I]=X[i];
+        N[I] = X[I];
+      Os.push(N);
     } else {
       var X = Os.length - N;
       for(var I = 0; I < N; I++)
-        Os.push(X + I);
+        Os.push(Os[X + I]);
     }
   };
 
@@ -301,7 +296,7 @@ function wps(E, T) {
     var C = Os.pop();
     Es.push([false, C === true ? P : N, Xexec]);
   };
-  Sd["for"] = function Xfor() {
+  Sd["for"] = function Xfor() { // TODO in ps
     var B = Os.pop();
     var L = Os.pop();
     var K = Os.pop();
@@ -314,14 +309,14 @@ function wps(E, T) {
       if(J <= L) Es.push([false, J, B, Xexec]);
     }
   };
-  Sd["repeat"] = function Xrepeat() {
+  Sd["repeat"] = function Xrepeat() { // TODO in ps
     var B = Os.pop();
     var N = Os.pop();
     if(1 < N) Es.push([true, N - 1, B, Xrepeat]);
     if(0 < N) Es.push([false, B, Xexec]);
   };
 
-  Sd["="] = function() {var X = Os.pop(); alert(X.nm || X.length || X);};
+  Sd["="] = function() {var X = Os.pop(); alert(X && X.nm || X);};
   Sd["=="] = function() {alert(Os.pop());}; // TODO
   Sd["stack"] = function() {alert(Os);}; // TODO
   Sd["pstack"] = function() {alert(Os);}; // TODO
@@ -353,12 +348,31 @@ function wps(E, T) {
 	  Os.push(true);
 	} else Os.push(false);
   };
-
   Sd["array"] = function() {Os.push(new Array(Os.pop()));};
 
+  Sd["type"] = function() { // any -- name
+    var A = Os.pop();
+    var X;
+    if(null === A) X = "nulltype";
+    else if(true === A || false === A) X = "booleantype";
+    else if(M === A) X = "marktype";
+    else if("string" == typeof A) X = "stringtype";
+    else if(isSymbol(A)) X = isQuoted(A) ? "nametype" : "operatortype";
+    else if("function" == typeof A) X = "operatortype";
+    else if(isArray(A)) X = "arraytype";
+    else if("object" == typeof A) X = "dicttype";
+    else if(1 * A == A) X = A % 1 == 0 ? "integertype" : "realtype";
+    else throw "Undefined type '" + A + "'";
+    Os.push(X);
+    // filetype
+    // packedarraytype (LanguageLevel 2)
+    // fonttype
+    // gstatetype (LanguageLevel 2)
+    // savetype
+  };
+
   Sd["restore"] = function() {Os.pop();}; // TODO
   Sd["save"] = function() {Os.push([]);}; // TODO
-
   Sd["bind"] = function() {}; // TODO
 
   //////////////////////////////////////////////////////////
@@ -382,11 +396,75 @@ function wps(E, T) {
   Sd[".date"] = function() { // -- date
     Os.push(new Date());
   };
+  Sd[".window"] = function() { // -- window
+    Os.push(window);
+  };
+  Sd[".callback"] = function() { // body -- callback // TODO refactor properly
+    var X = Os.pop();
+    Os.push(function() {
+              //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);
+      var V = D && D[K];
+      if(V !== undefined) Es.push([false, V]);
+      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]);
+        run(F, false);
+      }
+    } 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);
+              while(0 < Es.length)
+                step();
+            });
+  };
 
   /////////////////////////////////////////////////////
 
   // html5 utility operators
 
+  Sd[".minv"] = function() { // m -- m^-1
+    var M = Os.pop();
+    var a = M[0]; var b = M[1];
+    var d = M[2]; var e = M[3];
+    var g = M[4]; var h = M[5];
+    Os.push([e, b, d, a, d*h-e*g, b*g-a*h]);
+  };
+  Sd[".mmul"] = function() { // m1 m2 -- (m1 x m2)
+    var B = Os.pop();
+    var A = Os.pop();
+    var a = A[0]; var b = A[1];
+    var d = A[2]; var e = A[3];
+    var g = A[4]; var h = A[5];
+    var r = B[0]; var s = B[1];
+    var u = B[2]; var v = B[3];
+    var x = B[4]; var y = B[5];
+    Os.push([a*r+b*u, a*s+b*v, d*r+e*u, d*s+e*v, g*r+h*u+x, g*s+h*v+y]);
+  };
+  Sd[".xy"] = function() { // x y m -- x' y'
+    var M = Os.pop();
+    var Y = Os.pop();
+    var X = Os.pop();
+    Os.push(M[0] * X + M[2] * Y + M[4]);
+    Os.push(M[1] * X + M[3] * Y + M[5]);
+  };
+
   // TODO js ffi to manipulate strings so the following can be in ps
   Sd[".rgb"] = function() {
     var B = Os.pop();
@@ -402,93 +480,6 @@ function wps(E, T) {
     Os.push("rgba(" + R + "," + G + "," + B + "," + A + ")");
   };
 
-  Sd[".xy"] = function() { // x y m -- x' y'
-    var M = Os.pop();
-    var Y = Os.pop();
-    var X = Os.pop();
-    Os.push(M[0] * X + M[2] * Y + M[4]);
-    Os.push(M[1] * X + M[3] * Y + M[5]);
-  };
-  Sd["translate"] = function() {
-	var A = Os.pop();
-	var B = Os.pop();
-	if(typeof A == "object") Os.push([1, 0, 0, 1, Os.pop(), B]);
-    else {
-	  var M = [1, 0, 0, 1, B, A];
-	  CTMupdate(M);
-	  E.getContext("2d").translate(B, A);
-	}
-  };
-  Sd["rotate"] = function() {
-	var A = Os.pop();
-	if(typeof A == "object") {
-	  var B = opStack.pop();
-      Os.push([Math.cos(d2r(B)), Math.sin(d2r(B)),
-               -1 * Math.sin(d2r(B)), Math.cos(d2r(B)),
-               0, 0]);
-	} else {
-	  var M = [Math.cos(d2r(A)), Math.sin(d2r(A)),
-               -1 * Math.sin(d2r(A)), Math.cos(d2r(A)),
-               0, 0];
-      CTMupdate(M);
-	  //E.getContext("2d").rotate(d2r(A));
-	  E.getContext("2d").rotate(A);
-	}
-  };
-  Sd["scale"] = function() {
-	var A = Os.pop();
-	var B = Os.pop();
-	if(typeof A == "object") Os.push([Os.pop(), 0, 0, B, 0, 0]);
-    else {
-	  var M = [B, 0, 0, A, 0, 0,1];
-	  CTMupdate(M);
-	  ctx.scale(B, A);
-	}
-  };
-  Sd["transform"] = function() {
-	var A = Os.pop();
-    Os.push(A);
-	if(typeof A != "object")
-      Sd[".tm"]();
-    Sd[".xy"]();
-  };
-  Sd["itransform"] = function() {
-	var A = Os.pop();
-	if(typeof A == "object") Os.push(inverse(A));
-    else {
-      Os.push(A);
-      Sd[".tm"]();
-	  var M = Os.pop();
-      Os.push(inverse(M));
-    }
-    Sd[".xy"]();
-  };
-  Sd["rlineto"] = function() {
-	var Y = Os.pop();
-	var X = Os.pop();
-// 	pathY += yUnderMatrix(offX,offY,CTMdelta);
-// 	pathX += xUnderMatrix(offX,offY,CTMdelta);
-// 	var iCTMdelta = CTMdelta.inverse();
-// 	currentX = xUnderMatrix(pathX,pathY,iCTMdelta);
-// 	currentY = yUnderMatrix(pathX,pathY,iCTMdelta);
-// 	pathX=currentX;
-// 	pathY=currentY;
-// 	CTMdelta = CTMident;
-
- 	//ctx.lineTo(X, Y);
-  };
-  function d2r(A) {
-    return Math.PI / 180 * A;
-  }
-  function CTMupdate(M) {
-// 	currentX = xUnderMatrix(currentX,currentY,mat);
-// 	currentY = yUnderMatrix(currentX,currentY,mat);
-// 		CTMdelta = CTMdelta.timesMatrix(mat);
-// 		CTM = CTM.timesMatrix(mat);
-  }
-
-
-
   if(T.length)
     for(var I = 0; I < T.length; I++)
       ps0(T[I], Os, Ds, Es);
diff --git a/wps.wps b/wps.wps
@@ -1,10 +1,8 @@
 %%% (c) 2009 Tomas Hlavaty
 
 currentdict/systemdict currentdict put
-
 systemdict/{/mark cvx put
 systemdict/[/mark cvx put
-
 systemdict/]
 /counttomark cvx
 /array cvx
@@ -12,15 +10,73 @@ systemdict/]
 /exch cvx
 /pop cvx
 5 array astore cvx put
-
 systemdict/}/] cvx/cvx cvx 2 array astore cvx put
+systemdict/def{currentdict 2 index 2 index put pop pop}put
+
+%% stack & dict
+
+/dup{0 index}def
+/cleartomark{array pop}def
 
-%[1 2 3] =
+/known{exch begin where{currentdict eq}{false}if end}def
+/store{1 index where{3 1 roll put}{def}ifelse}def
+/load{dup where pop exch get}def
 
-systemdict/def{currentdict 2 index 2 index put pop pop} put
+/maxlength 1000 def % TODO
+
+%% conditionals
+
+/true/.true load def
+/false/.false load def
+/null/.null load def
+
+/not{false true ifelse}def
+/.logand{{{true}{false}ifelse}{pop false}ifelse}def
+/and/.logand load def % TODO numeric and
+/.logor{{pop true}{{true}{false}ifelse}ifelse}def
+/or/.logor load def % TODO numeric or
+
+/ne{eq not}def
+/ge{lt not}def
+/le{1 index 1 index eq 3 1 roll lt or}def
+/gt{le not}def
+/if{{}ifelse}def
+
+/.repeat{1 1 4 2 roll for}def
+%//     var B = Os.pop();
+%//     var N = Os.pop();
+%//     if(1 < N) Es.push([true, N - 1, B, Xrepeat]);
+%//     if(0 < N) Es.push([false, B, Xexec]);
+% /repeat{ % n b
+%   exch 2 copy dup % b n, b n n
+%   1 gt{-1 add exch/repeat cvx exec}{pop pop}ifelse
+%   0 gt{exec}{pop}ifelse
+% } def
+% /repeat{ % n b
+%   exch % b n
+%   2 copy % b n b n
+%   0 gt pstack{exec}{pop}ifelse % b n
+%   pop pop
+% %  dup 1 gt{-1 add exch repeat}{pop pop}ifelse
+% } def
+% /repeat { % n b
+%   2 dict begin
+%     /b exch def
+%     /n exch def
+%     0 n lt b if
+%     1 n lt {n 1 sub b repeat} if
+%   end
+% } def
+%/repeat{/pop cvx exch/exec cvx 3 array astore cvx 1 1 4 2 roll for}def
+%/loop{0 exch 0 exch 1 exch for}def % TODO
+%/exit{}def % TODO
 
 %% math
 
+/neg{0 exch sub}def
+/add{neg sub}def
+/idiv{div floor}def
+
 /abs{.math(abs)1 .call}def
 /.acos{.math(acos)1 .call}def
 /.asin{.math(asin)1 .call}def
@@ -51,27 +107,20 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 /.sqrt1_2{.math(SQRT1_2)get}def
 /.sqrt2{.math(SQRT2)get}def
 
-/sub{neg add}def
-/idiv{div .floor}def
-
-%% stack
-
-/dup{0 index}def
-
-%% conditionals
+%% html
 
-/true .true def
-/false .false def
-/null .null def
+/.setTimeout{.window(setTimeout)2 .call}def % cb ms -- id
+/.clearTimeout{.window(clearTimeout)1 .call pop}def % id --
+/.setInterval{.window(setInterval)2 .call}def % cb ms -- id
+/.clearInterval{.window(clearInterval)1 .call pop}def % id --
+/.document{.window(document)get}def % -- document
+/.getElementById{.document(getElementById)1 .call}def % id -- w
 
-/ne{eq not}def
-/ge{lt not}def
-/le{1 index 1 index eq 3 1 roll lt or}def
-/gt{le not}def
-/if{{}ifelse}def
-
-/loop{0 exch 0 exch 1 exch for}def
-/repeat{1 1 4 2 roll for}def
+%/.attachEvent{3 2 roll(attachEvent)2 .call pop}def % e k fn --
+%/.setAttribute{3 2 roll(setAttribute)2 .call pop}def % e k v --
+/.hook{put}def % e k cb --
+%if( td.attachEvent ) td.attachEvent('onclick', 'alert("blabla")');
+% else td.setAttribute('onclick', 'alert("blabla")');
 
 %% html5
 
@@ -156,6 +205,7 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 %% PostScript
 
 /.deg2rad{.pi 180 div mul}def
+/.rad2deg{180 .pi div mul}def
 
 /identmatrix{pop [1 0 0 1 0 0]}def % TODO fill
 /matrix{6 array identmatrix}def
@@ -164,56 +214,56 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 /.cy 0 def
 /.px 0 def
 /.py 0 def
-/.tm0 matrix def
 /.tm matrix def
 /.tmd matrix def
 
 /.setPoint{/.cy exch def/.cx exch def}def
 /.setPath{/.py exch def/.px exch def}def
 
+/.update{ % m --
+  dup .cx exch .cy exch % m .cx .cy m
+  .xy .setPoint % m
+  dup .tmd exch .mmul/.tmd exch def % (.tmd x m)
+  .tm exch .mmul setmatrix % = .tm x m
+} def
+
+/transform{dup type(arraytype)ne{.tm}if .xy}def
+/itransform{dup type(arraytype)ne{.tm}if .minv .xy}def
+
+/.scaleM{0 0 3 2 roll 0 0 6 array astore}def % x y -- [x 0 0 y 0 0]
+/.scale3{pop .scaleM}def
+/.scale2{2 copy .scaleM .update .scale}def
+/scale{dup type(arraytype)eq{.scale3}{.scale2}ifelse}def
+
+/.translateM{1 0 0 1 6 4 roll 6 array astore}def % x y -- [1 0 0 1 x y]
+/.translate3{pop .translateM}def
+/.translate2{2 copy .translateM .update .translate}def
+/translate{dup type(arraytype)eq{.translate3}{.translate2}ifelse}def
+
+/.rotateM{dup cos exch sin dup neg 2 index 0 0 6 array astore}def % a -- [c s -s c 0 0]
+/.rotate2{pop .deg2rad .rotateM}def
+/.rotate1{.deg2rad dup .rotateM .update .rotate}def
+/rotate{dup type(arraytype)eq{.rotate2}{.rotate1}ifelse}def
+
 /currentpoint{.cx .cy}def
 
 /setmatrix{/.tm exch def}def
 
-/..p{2 dict begin/y exch def/x exch def}def
-/..P{end}def
-/..tm{6 dict begin/ty exch def/tx exch def/d exch def/c exch def/b exch def/a exch def}def
-/..TM{end}def
-/.x{a x mul c y mul tx add add}def
-/.y{b x mul d y mul ty add add}def
-/.mmul{}def % TODO
-/.tmu{/.cx .x def/.cy .y def/.tmd .tmd}def % TODO
 %– initmatrix – 	Set CTM to device default
 %matrix defaultmatrix matrix 	Fill matrix with device default matrix
 %matrix currentmatrix matrix 	Fill matrix with CTM
 
-/translate{2 copy ..p 1 0 0 1 6 4 roll ..tm .tmu ..TM ..P .translate}def % TODO
-%tx ty matrix translate matrix 	Define translation by (tx , ty)
-
-%sx sy scale – 	Scale user space by sx and sy
-%sx sy matrix scale matrix 	Define scaling by sx and sy
-
-%angle rotate – 	Rotate user space by angle degrees
-%angle matrix rotate matrix 	Define rotation by angle degrees
-
 %matrix concat – 	Replace CTM by matrix ´ CTM
 %matrix1 matrix2 matrix3 concatmatrix matrix3 	Fill matrix3 with matrix1 ´ matrix2
 
-/transform{..p .tm ..tm .x .y ..TM ..P}def % TODO
-%x y matrix transform x¢ y¢ 	Transform (x, y) by matrix
-
 %dx dy dtransform dx¢ dy¢ 	Transform distance (dx, dy) by CTM
 %dx dy matrix dtransform dx¢ dy¢ 	Transform distance (dx, dy) by matrix
 
-%x¢ y¢ itransform x y 	Perform inverse transform of (x¢, y¢) by CTM
-%x¢ y¢ matrix itransform x y 	Perform inverse transform of (x¢, y¢) by matrix
-
 %dx¢ dy¢ idtransform dx dy 	Perform inverse transform of distance (dx¢, dy¢) by CTM
 %dx¢ dy¢ matrix idtransform dx dy 	Perform inverse transform of distance (dx¢, dy¢) by matrix
 
 %matrix1 matrix2 invertmatrix matrix2 	Fill matrix2 with inverse of matrix1
 
-
 /gsave{.save}def
 /grestore{.restore}def
 /rectclip{.clipRect}def
@@ -221,8 +271,8 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 /rectstroke{.strokeRect}def
 /newpath{.beginPath}def
 /closepath{.closePath}def
-/moveto{2 copy .setPoint 2 copy .setPath .moveTo/.tm0 matrix def}def
-/lineto{2 copy .setPoint 2 copy .setPath .lineTo/.tm0 matrix def}def
+/moveto{2 copy .setPoint 2 copy .setPath/.tmd matrix def .moveTo}def
+/lineto{2 copy .setPoint 2 copy .setPath/.tmd matrix def .lineTo}def
 /arcto{.arcTo}def
 
 /setlinewidth{.setLineWidth}def
@@ -236,30 +286,28 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 /currentmiterlimit{.getMiterLimit}def
 
 /setgray{255 mul dup dup .rgb dup .setStrokeStyle .setFillStyle}def
-/setrgbcolor{3{255 mul 3 1 roll} repeat .rgb dup .setStrokeStyle .setFillStyle}def
+/setrgbcolor{3{255 mul round 3 1 roll}repeat .rgb dup .setStrokeStyle .setFillStyle}def
 /setfont{} def % TODO C.font = N + "pt " + F.V;
 /clippath{0 0 .gcanvas(width)get .gcanvas(height)get .rect}def % TODO
 /show{currentpoint 3 2 roll .fillText .strokeText}def % TODO
-/rlineto{lineto}def % TODO
 
-/currentflat{42}def
-/setflat{pop}def
+/rlineto{.tmd .xy .py add exch .px add exch .tmd .minv .xy lineto}def
 
-/transform{}def % TODO
-/itransform{}def % TODO
+/currentflat{42}def % TODO
+/setflat{pop}def % TODO
 
-/currentpoint{0 0}def % TODO
+/showpage{}def % TODO
 
-/showpage{}def
+%/arc{.deg2rad exch .deg2rad exch true (arc)6 .gcall0}def % TODO currentpoint
+%/arcn{.deg2rad exch .deg2rad exch false(arc)6 .gcall0}def % TODO currentpoint
+/arc{.deg2rad exch .deg2rad exch true .arc}def % TODO currentpoint
+/arcn{.deg2rad exch .deg2rad exch false .arc}def % TODO currentpoint
 
-/arc{.deg2rad exch .deg2rad exch true(arc)6 .gcall0}def % TODO currentpoint
-/arcn{.deg2rad exch .deg2rad exch false(arc)6 .gcall0}def % TODO currentpoint
+/fill{.fill newpath currentpoint .moveTo}def % TODO
 
-/fill{.fill newpath currentpoint moveto}def % TODO
+/setdash{pop pop}def % TODO
 
-/setdash{pop pop}def
-
-/stroke{.stroke newpath currentpoint moveto}def
+/stroke{.stroke newpath currentpoint .moveTo}def
 
 /curveto{2 copy .setPoint .bezierCurveTo}def
 
@@ -306,7 +354,7 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 /Tf{setfont}def % TODO
 /Tr{}def % TODO
 /Ts{}def % TODO
-/Td{}def % TODO
+/Td{translate 0 0 moveto}def
 /TD{}def % TODO
 /Tm{}def % TODO
 /T*{}def % TODO
@@ -318,14 +366,14 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 /d1{}def % TODO
 /CS{}def % TODO
 /cs{}def % TODO
-/SC{}def % TODO
+/SC/setcolor load def
 /SCN{}def % TODO
-/sc{}def % TODO
+/sc/setcolor load def
 /scn{}def % TODO
 /G{}def % TODO
 /g{}def % TODO
 /RG{}def % TODO
-/rg{3{255 mul 3 1 roll} repeat .rgb dup .setStrokeStyle .setFillStyle}def % TODO
+/rg{setrgbcolor}def % TODO
 /K{}def % TODO
 /k{}def % TODO
 /sh{}def % TODO
@@ -341,6 +389,87 @@ systemdict/def{currentdict 2 index 2 index put pop pop} put
 /BX{}def % TODO
 /EX{}def % TODO
 
+/PS{cvx exec}def
+
+% /Operators 50 dict begin
+%   /cs { //ResolveColorSpace exec //SetColorSpaceSafe exec
+%       } bind def
+%   /scn { //SetColor exec } bind def
+%   /CS //cs def
+%   /SCN { //SetColor exec } bind def
+
+%   /re {
+%     4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
+%     closepath
+%   } def
+%   /sh { % Reserved for ps3write.
+%         ResolveShading 
+%         dup /Background known {
+%           gsave
+%           dup /ColorSpace get setcolorspace
+%           dup /Background get aload pop setcolor
+%           pathbbox               % x0 y0 x1 y1
+%           2 index sub exch 3 index sub exch
+%           rectfill
+%           grestore
+%         } if
+%         shfill 
+%       } bind def
+
+%   /Do { //DoXObject exec } bind def
+
+%   /BI { currentglobal false setglobal << } bind def
+%   /ID { >>
+%         dup /DataSource currentfile 
+%         % HACK BEG
+%         % This hack provides a compatibility to HP LaserJet 1320,
+%         % which sometimes closes the underlying stream when EOD 
+%         % is reached in the ASCII85Decode filter.
+%         % This portion is not required by the Postscript language definition.
+%         2 index /F //knownget exec {
+%           /A85 eq {
+%             0 (~>) /SubFileDecode filter 
+%           } if
+%         } if
+%         % HACK END
+%         put
+%         //CompleteInlineImage exec
+%         exch setglobal
+%         //DoImage exec
+%       } bind def
+%   /EI {} bind def
+
+%   /BT { gsave //GraphicState /InitialTextMatrix get currentmatrix pop } bind def
+%   /Tc { //GraphicState exch /CharacterSpacing exch put } bind def
+%   /TL { //GraphicState exch /TextLeading exch put } bind def
+%   /Tr { //GraphicState exch /TextRenderingMode exch put } bind def
+%   /Ts {  % Ghostscript never generates it.
+%         mark (Unimplemented SetTextRise) //error exec
+%       } bind def
+%   /Tw { //GraphicState exch /WordSpacing exch put } bind def
+%   /Tz { % Ghostscript never generates it.
+%             mark (Unimplemented SetHorizontalTextScaling) //error exec
+%       } bind def
+%   /TD { dup neg //TL exec //Td exec } bind def
+%   /Tm { //GraphicState /InitialTextMatrix get setmatrix
+%         //TempMatrix astore concat
+%         0 0 moveto } bind def
+%   /T* { 0 //GraphicState /TextLeading get neg //Td exec } bind def
+%   /Tj { //ShowTextBeg exec  //ShowText exec  //ShowTextEnd exec } bind def
+%   /'  { //T* exec  //ShowText exec  //ShowTextEnd exec } bind def
+%   /"  { 3 2 roll //Tw exec exch //Tc exec //' exec} bind def
+%   /TJ //ShowTextWithGlyphPositioning def
+%   /Tf //SetFont def
+
+%   /BDC { BeginMarkedContentSequenceWithPropertyList } bind def
+%   /BMC { BeginMarkedContentSequence } bind def
+%   /EMC { EndMarkedContentSequence } bind def
+%   /BX { BeginCompatibilitySection } bind def
+%   /EX { EndCompatibilitySection } bind def
+%   /DP { DefineMarkedContentPointWithPropertyList } bind def
+%   /MP { DefineMarkedContentPoint } bind def
+% currentdict end def
+
 %% finish
 
 /userdict 1000 dict def