% DELAY.MF (RMCG19950405)

%    DELAY.MF delays the actual drawing till the endchar;
%    Copyright (C) 2003 Ram\'on Casares
%
%    This program is free software; you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation; either version 2 of the License, or
%    (at your option) any later version.
%
%    This program is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this program; if not, write to the
%       Free Software Foundation, Inc.,
%       59 Temple Place, Suite 330,
%       Boston, MA  02111-1307  USA

def clear_del =
 save _dn, _del; _dn := 0; string _del[];
enddef;

def make_del =
 for k := 1 upto _dn: scantokens _del[k]; endfor
enddef;

extra_beginchar := extra_beginchar & "clear_del;";
extra_endchar := "make_del;" & extra_endchar;

def MTlabel(suffix i)(expr v,h,add,wd,ht,dp) =
 x.i.l = x.i if h="c": - wd/2 elseif h="r": - wd fi;
 y.i.t = y.i if v="c": + ht/2 elseif v="b": + ht fi;
 x.i.r = x.i.l + wd; y.i.b = y.i.t - ht - dp;
 if not (add=""): _del[incr _dn] := "_delete(" & str i & ");"; fi
 _del[incr _dn] := "_pos(" & str i & ");";
enddef;

def _delete(suffix i) = erase fill (x.i.l,y.i.t) --
 (x.i.l,y.i.b) -- (x.i.r,y.i.b) -- (x.i.r,y.i.t) -- cycle;
enddef;

def _pos(suffix i) =
 message"\MTloglabel"; show x\i/pt; show y\i/pt; message"";
enddef;

pickup pencircle scaled 0.4pt; thin_pen:=savepen;
pickup pencircle scaled 0.8pt; med_pen:=savepen;
pickup pencircle scaled 1.2pt; thick_pen:=savepen;

def thinpen = pickup thin_pen;
 _del[incr _dn] := "pickup thin_pen;";
enddef;

def medpen = pickup med_pen;
 _del[incr _dn] := "pickup med_pen;";
enddef;

def thickpen = pickup thick_pen;
 _del[incr _dn] := "pickup thick_pen;";
enddef;

def rectangle(suffix s)(expr width,height) =
 x.s.l = x.s - width/2;   x.s.r = x.s + width/2;
 y.s.t = y.s + height/2;  y.s.b = y.s - height/2;
 _del[incr _dn] := "_rectangle(" & str s & ");";
enddef;

def _rectangle(suffix s) =
 draw (x.s.l,y.s.b) -- (x.s.r,y.s.b) --
  (x.s.r,y.s.t) -- (x.s.l,y.s.t) -- cycle;
enddef;

def square(suffix s)(expr side) =
 x.s.l = x.s - side/2;  x.s.r = x.s + side/2;
 y.s.t = y.s + side/2;  y.s.b = y.s - side/2;
 _del[incr _dn] := "_square(" & str s & ");";
enddef;

def _square(suffix s) =
 draw (x.s.l,y.s.b) -- (x.s.r,y.s.b) --
  (x.s.r,y.s.t) -- (x.s.l,y.s.t) -- cycle;
enddef;

def ellipse(suffix s)(expr width,height) =
 x.s.l = x.s - width/2;   x.s.r = x.s + width/2;
 y.s.t = y.s + height/2;  y.s.b = y.s - height/2;
 _del[incr _dn] := "_ellipse(" & str s & ");";
enddef;

def _ellipse(suffix s) =
 draw (fullcircle xscaled (x.s.r - x.s.l) yscaled (y.s.t - y.s.b)
  shifted z.s);
enddef;

def circle(suffix s)(expr diameter) =
 x.s.l = x.s - diameter/2;  x.s.r = x.s + diameter/2;
 y.s.t = y.s + diameter/2;  y.s.b = y.s - diameter/2;
 _del[incr _dn] := "_circle(" & str s & ");";
enddef;

def _circle(suffix s) =
 draw (fullcircle scaled (x.s.r - x.s.l) shifted z.s);
enddef;

def oval(suffix s)(expr width,height,superness) =
 x.s.l = x.s - width/2;   x.s.r = x.s + width/2;
 y.s.t = y.s + height/2;  y.s.b = y.s - height/2;
 x.s.ness = superness;
 _del[incr _dn] := "_oval(" & str s & ");";
enddef;

def _oval(suffix s) =
 draw superellipse((x.s.r,y.s),(x.s,y.s.t),(x.s.l,y.s),(x.s,y.s.b),
                   x.s.ness);
enddef;

def triangle(suffix s)(expr width,height) =
 x.s.l = x.s - width/2;   x.s.r = x.s + width/2;
 y.s.t = y.s + height/2;  y.s.b = y.s - height/2;
 _del[incr _dn] := "_triangle(" & str s & ");";
enddef;

def _triangle(suffix s) =
 draw (x.s.l,y.s.b) -- (x.s.r,y.s.b) -- (x.s,y.s.t) -- cycle;
enddef;

def lozenge(suffix s)(expr width,height) =
 x.s.l = x.s - width/2;   x.s.r = x.s + width/2;
 y.s.t = y.s + height/2;  y.s.b = y.s - height/2;
 _del[incr _dn] := "_lozenge(" & str s & ");";
enddef;

def _lozenge(suffix s) =
 draw (x.s.l,y.s) -- (x.s,y.s.b) --
  (x.s.r,y.s) -- (x.s,y.s.t) -- cycle;
enddef;

dot_diameter := 2.4pt;

def dot(suffix s) =
 x.s.dd = dot_diameter;
 _del[incr _dn] := "_dot(" & str s & ");";
enddef;

def _dot(suffix s) =
 fill fullcircle scaled x.s.dd shifted z.s;
enddef;

def line(suffix s) =
 _del[incr _dn] := "_line(" & str s & ");";
enddef;

def _line(suffix s) =
 draw z.s.o -- z.s.d;
enddef;

dash_length := 4pt;

def dottedline(suffix s) =
 x.s.dl = dash_length;  x.s.dd = dot_diameter;
 _del[incr _dn] := "_dottedline(" & str s & ");";
enddef;

def _dottedline(suffix s) =
 begingroup save p, n;
 path p; p = z.s.o -- z.s.d;
 n := floor(length(z.s.d-z.s.o)/abs(x.s.dl));
 for i := 0 upto n:
  fill fullcircle scaled x.s.dd shifted (point i/n of p);
 endfor endgroup
enddef;

def dashedline(suffix s) =
 x.s.dl = dash_length;
 _del[incr _dn] := "_dashedline(" & str s & ");";
enddef;

def _dashedline(suffix s) =
 begingroup save p, n;
 path p; p = z.s.o -- z.s.d;
 n := floor(length(z.s.d-z.s.o)/abs(x.s.dl));
 if not (odd n): n := n + 1; fi
 for i := 0 upto (n-1): if not (odd i):
  draw subpath(i/n,(i+1)/n) of p;
 fi endfor endgroup
enddef;

arrow_head_length := 6pt;
arrow_head_width := 2.4pt;

def arrowhead(suffix s) =
 x.s.ahl = arrow_head_length;  x.s.ahw = arrow_head_width;
 _del[incr _dn] := "_arrowhead(" & str s & ");";
enddef;

def _arrowhead(suffix s) =
 z.s.dh = (x.s.ahl/length(z.s.d-z.s.o))[z.s.d,z.s.o];
 z.s.dr = z.s.dh + x.s.ahw / 2 * dir(angle(z.s.d-z.s.o)+90);
 z.s.dl = z.s.dh + x.s.ahw / 2 * dir(angle(z.s.d-z.s.o)-90);
 fill z.s.d -- z.s.dr -- z.s.dl -- cycle;
enddef;

def arrow(suffix s) =
 arrowhead(s);
 _del[incr _dn] := "_arrow(" & str s & ");";
enddef;

def _arrow(suffix s) =
 draw z.s.o .. z.s.dh;
enddef;

def cillinder(suffix s)(expr width,height) =
 x.s.l = x.s - 1/2width;   x.s.r = x.s + 1/2width;
 y.s.b = y.s - 1/2height;  y.s.t = y.s + 1/2height;
 y.s.ar = 1/6height;
 _del[incr _dn] := "_cillinder(" & str s & ");";
enddef;

def _cillinder(suffix s) =
 draw (x.s.l,y.s.t-y.s.ar) -- (x.s.l,y.s.b+y.s.ar);
 draw (x.s.r,y.s.t-y.s.ar) -- (x.s.r,y.s.b+y.s.ar);
 draw (x.s.l,y.s.b+y.s.ar){down} .. (x.s,y.s.b){right}
      .. (x.s.r,y.s.b+y.s.ar){up};
 draw (x.s.l,y.s.t-y.s.ar){down} .. (x.s,y.s.t-2y.s.ar){right}
      .. (x.s.r,y.s.t-y.s.ar){up} .. (x.s,y.s.t){left} .. cycle;
enddef;

join_radius := 5pt;

def box(suffix s)(expr width,height) =
 x.s.l = x.s - width/2;   x.s.r = x.s + width/2;
 y.s.t = y.s + height/2;  y.s.b = y.s - height/2;
 x.s.jr = join_radius;
 _del[incr _dn] := "_box(" & str s & ");";
enddef;

def _box(suffix s) =
 if min((x.s.r-x.s.l),(y.s.t-y.s.b)) > 2x.s.jr:
  draw (((x.s,y.s.b) .. (x.s.r,y.s.b)) softjoin
      ((x.s.r,y.s.b) .. (x.s.r,y.s.t)) softjoin
      ((x.s.r,y.s.t) .. (x.s.l,y.s.t)) softjoin
      ((x.s.l,y.s.t) .. (x.s.l,y.s.b)) softjoin
      ((x.s.l,y.s.b) .. (x.s,y.s.b)));
 else:
  draw (fullcircle xscaled (x.s.r-x.s.l) yscaled (y.s.t-y.s.b)
   shifted z.s);
 fi
enddef;

def soft(suffix s) =
 _del[incr _dn] := "_soft(" & str s & ");";
enddef;

def _soft(suffix s) =
 draw (z.s.o -- z.s.m) softjoin (z.s.m -- z.s.d);
enddef;

def softt(suffix s) =
 _del[incr _dn] := "_softt(" & str s & ");";
enddef;

def _softt(suffix s) =
 draw ((z.s.o .. z.s.m1) softjoin
      (z.s.m1 .. z.s.m2) softjoin (z.s.m2 .. z.s.d));
enddef;

def fork(suffix s) =
 z.s.head.o = z.s.m; z.s.head.d = z.s.d;
 arrowhead(s.head);
 dot(s.o);
 z.s.body.o = z.s.o; z.s.body.m = z.s.m;
 z.s.body.d = z.s.head.dh;
 soft(s.body);
enddef;

def darrow(suffix s) =
 z.s.med = 1/2[z.s.o,z.s.d];
 z.s.one.o = z.s.med; z.s.one.d = z.s.d;
 arrow(s.one);
 z.s.two.o = z.s.med; z.s.two.d = z.s.o;
 arrow(s.two);
enddef;

def arroww(suffix s) =
 z.s.head.o = z.s.m; z.s.head.d = z.s.d;
 arrowhead(s.head);
 z.s.body.o = z.s.o; z.s.body.m = z.s.m;
 z.s.body.d = z.s.head.dh;
 soft(s.body);
enddef;

def arrowww(suffix s) =
 z.s.head.o = z.s.m2; z.s.head.d = z.s.d;
 arrowhead(s.head);
 z.s.body.o = z.s.o; z.s.body.m1 = z.s.m1;
 z.s.body.m2 = z.s.m2; z.s.body.d = z.s.head.dh;
 softt(s.body);
enddef;
