summaryrefslogtreecommitdiff
path: root/metapost
diff options
context:
space:
mode:
Diffstat (limited to 'metapost')
-rw-r--r--metapost/context/base/metafun.mp75
-rw-r--r--metapost/context/base/mp-back.mp206
-rw-r--r--metapost/context/base/mp-base.mp558
-rw-r--r--metapost/context/base/mp-butt.mp75
-rw-r--r--metapost/context/base/mp-char.mp999
-rw-r--r--metapost/context/base/mp-chem.mp761
-rw-r--r--metapost/context/base/mp-core.mp1418
-rw-r--r--metapost/context/base/mp-figs.mp50
-rw-r--r--metapost/context/base/mp-fobg.mp88
-rw-r--r--metapost/context/base/mp-form.mp403
-rw-r--r--metapost/context/base/mp-func.mp59
-rw-r--r--metapost/context/base/mp-grid.mp145
-rw-r--r--metapost/context/base/mp-grph.mp296
-rw-r--r--metapost/context/base/mp-mlib.mp282
-rw-r--r--metapost/context/base/mp-page.mp474
-rw-r--r--metapost/context/base/mp-shap.mp307
-rw-r--r--metapost/context/base/mp-spec.mp776
-rw-r--r--metapost/context/base/mp-step.mp320
-rw-r--r--metapost/context/base/mp-symb.mp351
-rw-r--r--metapost/context/base/mp-text.mp269
-rw-r--r--metapost/context/base/mp-tool.mp2566
-rw-r--r--metapost/context/base/mp-txts.mp67
-rw-r--r--metapost/context/font/punkfont.mp863
23 files changed, 11408 insertions, 0 deletions
diff --git a/metapost/context/base/metafun.mp b/metapost/context/base/metafun.mp
new file mode 100644
index 000000000..00011c8be
--- /dev/null
+++ b/metapost/context/base/metafun.mp
@@ -0,0 +1,75 @@
+%D \module
+%D [ file=metafun.mp,
+%D version=2000.07.15,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=format generation file,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D When generating many graphics at runtime, it can save run
+%D time to use a format file. We could have named this file
+%D \type {context}, but this is error prone, because it forces
+%D to use the progname \type {mpost} or \type {context}
+%D explicitly, depending on the needs. When using the format,
+%D a mismatch in the memory specification of \type {mpost} or
+%D \type {context} (the \TEX\ one) could lead to lost strings
+%D (and as a result in buggy boundingbox and special
+%D handling). By using the name \type {metatex} we make sure
+%D that we use (unless overloaded) the settings of \type
+%D {mpost}.
+
+%D First we input John Hobby's metapost plain file. However,
+%D because we want to prevent dependency problems and in the
+%D end even may use a patched version, we prefer to use a
+%D copy,
+
+if unknown ahangle :
+ input mp-base.mp ; % input plain.mp ;
+else :
+ let dump = relax ;
+fi ;
+
+input mp-tool.mp ;
+input mp-spec.mp ; % will be skipped in mkiv, some day
+input mp-core.mp ;
+input mp-page.mp ;
+input mp-text.mp ;
+input mp-txts.mp ;
+input mp-shap.mp ;
+input mp-butt.mp ;
+input mp-char.mp ;
+input mp-step.mp ;
+input mp-grph.mp ;
+input mp-figs.mp ;
+
+input mp-mlib.mp ;
+
+if known context_mlib : input mp-chem.mp ; fi ; % only when mkiv
+
+% mp-form.mp ;
+input mp-grid.mp ;
+input mp-func.mp ;
+
+string metafunversion ;
+
+metafunversion = "metafun" & " " &
+ decimal year & "-" &
+ decimal month & "-" &
+ decimal day & " " &
+ if ((time div 60) < 10) : "0" & fi
+ decimal (time div 60) & ":" &
+ if ((time-(time div 60)*60) < 10) : "0" & fi
+ decimal (time-(time div 60)*60) ;
+
+let normalend = end ;
+
+def end =
+ ; message "" ; message metafunversion ; message "" ; normalend ;
+enddef ;
+
+dump ; endinput .
diff --git a/metapost/context/base/mp-back.mp b/metapost/context/base/mp-back.mp
new file mode 100644
index 000000000..f49474cf7
--- /dev/null
+++ b/metapost/context/base/mp-back.mp
@@ -0,0 +1,206 @@
+%D \module
+%D [ file=mp-back.mp,
+%D version=2000.05.31,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_back : endinput ; fi ;
+
+boolean context_back ; context_back := true ;
+
+def some_hash ( expr hash_width ,
+ hash_height ,
+ hash_linewidth ,
+ hash_linecolor ,
+ hash_angle ,
+ hash_gap ) =
+
+ stripe_gap := hash_gap ;
+ stripe_angle := hash_angle ;
+ drawoptions (withpen pencircle scaled hash_linewidth
+ withcolor hash_linecolor) ;
+ path p ; p := unitsquare xscaled hash_width yscaled hash_height ;
+ stripe_path_a () (draw) p ; % next we move it all to quadrant 1
+ currentpicture := currentpicture shifted urcorner currentpicture ;
+
+enddef ;
+
+def some_double_back (expr back_type ,
+ back_width ,
+ back_height ,
+ back_delta ,
+ back_linewidth ,
+ back_linecolor ,
+ back_fillcolor ,
+ back_topcolor ,
+ back_bottomcolor ,
+ back_leftcolor ,
+ back_rightcolor ) =
+
+ numeric ww ; ww := back_width ;
+ numeric hh ; hh := back_height ;
+ numeric dd ; dd := back_delta ;
+
+ color back_nillcolor ; back_nillcolor := back_topcolor ;
+
+ path p ; p := fullsquare xscaled ww yscaled hh ;
+ path q ; q := fullsquare xscaled (ww-2dd) yscaled (hh-2dd) ;
+ path r ; r := llcorner p --
+ lrcorner p shifted (-3dd,0) .. controls lrcorner p ..
+ lrcorner p shifted (0, 3dd) --
+ urcorner p shifted (0,-3dd) .. controls urcorner p ..
+ urcorner p shifted (-3dd,0) --
+ ulcorner p -- cycle ;
+ path s ; s := r xscaled ((ww-2dd)/ww) yscaled ((hh-2dd)/hh) ;
+ path t ; t := llcorner p --
+ lrcorner p --
+ urcorner p shifted (0,-3dd) .. controls urcorner p ..
+ urcorner p shifted (-3dd,0) --
+ ulcorner p shifted ( 3dd,0) .. controls ulcorner p ..
+ ulcorner p shifted (0,-3dd) --
+ llcorner p -- cycle ;
+ path u ; u := t xscaled ((ww-2dd)/ww) yscaled ((hh-2dd)/hh) ;
+ path v ; v := llcorner p shifted ( 3dd,0) --
+ lrcorner p shifted (-3dd,0) .. controls lrcorner p ..
+ lrcorner p shifted (0, 3dd) --
+ urcorner p shifted (0,-3dd) .. controls urcorner p ..
+ urcorner p shifted (-3dd,0) --
+ ulcorner p shifted ( 3dd,0) .. controls ulcorner p ..
+ ulcorner p shifted (0,-3dd) ..
+ llcorner p shifted (0, 3dd) .. controls llcorner p .. cycle ; % {down} .. cycle ;
+ path w ; w := t xscaled ((ww-2dd)/ww) yscaled ((hh-2dd)/hh) ;
+ path a ; a := llcorner p -- ulcorner p --
+ ulcorner q -- llcorner q -- cycle ;
+ path b ; b := llcorner p -- lrcorner p --
+ lrcorner q -- llcorner q -- cycle ;
+ path c ; c := lrcorner p -- urcorner p --
+ urcorner q -- lrcorner q -- cycle ;
+ path d ; d := ulcorner p -- urcorner p --
+ urcorner q -- ulcorner q -- cycle ;
+ path e ; e := llcorner p -- lrcorner p --
+ urcorner p -- urcorner q --
+ lrcorner q -- llcorner q -- cycle ;
+ path f ; f := llcorner p -- ulcorner p --
+ urcorner p -- urcorner q --
+ ulcorner q -- llcorner q -- cycle ;
+
+ linecap := butt ; pickup pencircle scaled back_linewidth ;
+
+ if back_type=1 :
+
+ fill p withcolor back_fillcolor ;
+ fill a withcolor back_leftcolor ;
+ fill b withcolor back_bottomcolor ;
+ fill c withcolor back_rightcolor ;
+ fill d withcolor back_topcolor ;
+ draw a withcolor back_linecolor ;
+ draw d withcolor back_linecolor ;
+ draw b withcolor back_linecolor ;
+ draw c withcolor back_linecolor ;
+
+ elseif back_type=2 :
+
+ fill p withcolor back_fillcolor ;
+ fill e withcolor back_bottomcolor ;
+ fill f withcolor back_topcolor ;
+ draw e withcolor back_linecolor ;
+ draw f withcolor back_linecolor ;
+
+ elseif back_type=3 :
+
+ fill v withcolor back_nillcolor ;
+ fill w withcolor back_fillcolor ;
+ draw v withcolor back_linecolor ;
+ draw w withcolor back_linecolor ;
+
+ elseif back_type=4 :
+
+ fill t withcolor back_nillcolor ;
+ fill u withcolor back_fillcolor ;
+ draw t withcolor back_linecolor ;
+ draw u withcolor back_linecolor ;
+
+ elseif back_type=5 :
+
+ t := t rotatedaround(center t,180) ;
+ u := u rotatedaround(center u,180) ;
+
+ fill t withcolor back_nillcolor ;
+ fill u withcolor back_fillcolor ;
+ draw t withcolor back_linecolor ;
+ draw u withcolor back_linecolor ;
+
+ elseif back_type=6 :
+
+ r := r rotatedaround(center r,180) ;
+ s := s rotatedaround(center s,180) ;
+
+ fill r withcolor back_nillcolor ;
+ fill s withcolor back_fillcolor ;
+ draw r withcolor back_linecolor ;
+ draw s withcolor back_linecolor ;
+
+ elseif back_type=7 :
+
+ fill r withcolor back_nillcolor ;
+ fill s withcolor back_fillcolor ;
+ draw r withcolor back_linecolor ;
+ draw s withcolor back_linecolor ;
+
+fi ;
+
+enddef ;
+
+endinput ;
+
+beginfig (1) ;
+
+some_double_back (1, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, .6white, .7white, .6white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (2, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, .6white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (3, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (4, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (5, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (6, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (7, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (8, 4.5cm, 1.5cm, .25cm, 1mm,
+ .5white, .8white, .7white, white, white, white)
+
+endfig ;
+
+end .
diff --git a/metapost/context/base/mp-base.mp b/metapost/context/base/mp-base.mp
new file mode 100644
index 000000000..d0b3991c8
--- /dev/null
+++ b/metapost/context/base/mp-base.mp
@@ -0,0 +1,558 @@
+% This is (currently) a copy of the plain.mp file. We use a copy
+% because (1) we want to make sure that there are no unresolved
+% dependencies, and (2) we may patch this file eventually.
+
+% This file gives the macros for plain MetaPost
+% It contains all the features of plain METAFONT except those specific to
+% font-making. (See The METAFONTbook by D.E. Knuth).
+% There are also a number of macros for labeling figures, etc.
+string base_name, base_version; base_name="plain"; base_version="0.63";
+
+message "Preloading the plain mem file, version "&base_version;
+
+delimiters (); % this makes parentheses behave like parentheses
+def upto = step 1 until enddef; % syntactic sugar
+def downto = step -1 until enddef;
+def exitunless expr c = exitif not c enddef;
+let relax = \; % ignore the word `relax', as in TeX
+let \\ = \; % double relaxation is like single
+def ]] = ] ] enddef; % right brackets should be loners
+def -- = {curl 1}..{curl 1} enddef;
+def --- = .. tension infinity .. enddef;
+def ... = .. tension atleast 1 .. enddef;
+
+def gobble primary g = enddef;
+primarydef g gobbled gg = enddef;
+def hide(text t) = exitif numeric begingroup t;endgroup; enddef;
+def ??? = hide(interim showstopping:=1; showdependencies) enddef;
+def stop expr s = message s; gobble readstring enddef;
+
+warningcheck:=1;
+tracinglostchars:=1;
+
+def interact = % sets up to make "show" commands stop
+ hide(showstopping:=1; tracingonline:=1) enddef;
+
+def loggingall = % puts tracing info into the log
+ tracingcommands:=3; tracingtitles:=1; tracingequations:=1;
+ tracingcapsules:=1; tracingspecs:=2; tracingchoices:=1; tracinglostchars:=1;
+ tracingstats:=1; tracingoutput:=1; tracingmacros:=1; tracingrestores:=1;
+ enddef;
+
+def tracingall = % turns on every form of tracing
+ tracingonline:=1; showstopping:=1; loggingall enddef;
+
+def tracingnone = % turns off every form of tracing
+ tracingcommands:=0; tracingtitles:=0; tracingequations:=0;
+ tracingcapsules:=0; tracingspecs:=0; tracingchoices:=0; tracinglostchars:=0;
+ tracingstats:=0; tracingoutput:=0; tracingmacros:=0; tracingrestores:=0;
+ enddef;
+
+
+
+%% dash patterns
+
+vardef dashpattern(text t) =
+ save on, off, w;
+ let on=_on_;
+ let off=_off_;
+ w = 0;
+ nullpicture t
+enddef;
+
+tertiarydef p _on_ d =
+ begingroup save pic;
+ picture pic; pic=p;
+ addto pic doublepath (w,w)..(w+d,w);
+ w := w+d;
+ pic shifted (0,d)
+ endgroup
+enddef;
+
+tertiarydef p _off_ d =
+ begingroup w:=w+d;
+ p shifted (0,d)
+ endgroup
+enddef;
+
+
+
+%% basic constants and mathematical macros
+
+% numeric constants
+newinternal eps,epsilon,infinity,_;
+eps := .00049; % this is a pretty small positive number
+epsilon := 1/256/256; % but this is the smallest
+infinity := 4095.99998; % and this is the largest
+_ := -1; % internal constant to make macros unreadable but shorter
+
+newinternal mitered, rounded, beveled, butt, squared;
+mitered:=0; rounded:=1; beveled:=2; % linejoin types
+butt:=0; rounded:=1; squared:=2; % linecap types
+
+
+% pair constants
+pair right,left,up,down,origin;
+origin=(0,0); up=-down=(0,1); right=-left=(1,0);
+
+% path constants
+path quartercircle,halfcircle,fullcircle,unitsquare;
+fullcircle = makepath pencircle;
+halfcircle = subpath (0,4) of fullcircle;
+quartercircle = subpath (0,2) of fullcircle;
+unitsquare=(0,0)--(1,0)--(1,1)--(0,1)--cycle;
+
+% transform constants
+transform identity;
+for z=origin,right,up: z transformed identity = z; endfor
+
+% color constants
+color black, white, red, green, blue, background;
+black = (0,0,0);
+white = (1,1,1);
+red = (1,0,0);
+green = (0,1,0);
+blue = (0,0,1);
+background = white; % The user can reset this
+
+% picture constants
+picture blankpicture,evenly,withdots;
+blankpicture=nullpicture; % `display blankpicture...'
+evenly=dashpattern(on 3 off 3); % `dashed evenly'
+withdots=dashpattern(off 2.5 on 0 off 2.5); % `dashed withdots'
+
+% string constants
+string ditto, EOF;
+ditto = char 34; % ASCII double-quote mark
+EOF = char 0; % end-of-file for readfrom and write..to
+
+% pen constants
+pen pensquare,penrazor,penspeck;
+pensquare = makepen(unitsquare shifted -(.5,.5));
+penrazor = makepen((-.5,0)--(.5,0)--cycle);
+penspeck=pensquare scaled eps;
+
+% nullary operators
+vardef whatever = save ?; ? enddef;
+
+% unary operators
+let abs = length;
+
+vardef round primary u =
+ if numeric u: floor(u+.5)
+ elseif pair u: (round xpart u, round ypart u)
+ else: u fi enddef;
+
+vardef ceiling primary x = -floor(-x) enddef;
+
+vardef byte primary s =
+ if string s: ASCII fi s enddef;
+
+vardef dir primary d = right rotated d enddef;
+
+vardef unitvector primary z = z/abs z enddef;
+
+vardef inverse primary T =
+ transform T_; T_ transformed T = identity; T_ enddef;
+
+vardef counterclockwise primary c =
+ if turningnumber c <= 0: reverse fi c enddef;
+
+vardef tensepath expr r =
+ for k=0 upto length r - 1: point k of r --- endfor
+ if cycle r: cycle else: point infinity of r fi enddef;
+
+vardef center primary p = .5[llcorner p, urcorner p] enddef;
+
+
+
+% binary operators
+
+primarydef x mod y = (x-y*floor(x/y)) enddef;
+primarydef x div y = floor(x/y) enddef;
+primarydef w dotprod z = (xpart w * xpart z + ypart w * ypart z) enddef;
+
+primarydef x**y = if y=2: x*x else: takepower y of x fi enddef;
+def takepower expr y of x =
+ if x>0: mexp(y*mlog x)
+ elseif (x=0) and (y>0): 0
+ else: 1
+ if y=floor y:
+ if y>=0: for n=1 upto y: *x endfor
+ else: for n=_ downto y: /x endfor
+ fi
+ else: hide(errmessage "Undefined power: " & decimal x&"**"&decimal y)
+ fi fi enddef;
+
+vardef direction expr t of p =
+ postcontrol t of p - precontrol t of p enddef;
+
+vardef directionpoint expr z of p =
+ a_:=directiontime z of p;
+ if a_<0: errmessage("The direction doesn't occur"); fi
+ point a_ of p enddef;
+
+secondarydef p intersectionpoint q =
+ begingroup save x_,y_; (x_,y_)=p intersectiontimes q;
+ if x_<0: errmessage("The paths don't intersect"); origin
+ else: .5[point x_ of p, point y_ of q] fi endgroup
+enddef;
+
+tertiarydef p softjoin q =
+ begingroup c_:=fullcircle scaled 2join_radius shifted point 0 of q;
+ a_:=ypart(c_ intersectiontimes p); b_:=ypart(c_ intersectiontimes q);
+ if a_<0:point 0 of p{direction 0 of p} else: subpath(0,a_) of p fi
+ ... if b_<0:{direction infinity of q}point infinity of q
+ else: subpath(b_,infinity) of q fi endgroup enddef;
+newinternal join_radius,a_,b_; path c_;
+
+
+path cuttings; % what got cut off
+
+tertiarydef a cutbefore b = % tries to cut as little as possible
+ begingroup save t;
+ (t, whatever) = a intersectiontimes b;
+ if t<0:
+ cuttings:=point 0 of a;
+ a
+ else: cuttings:= subpath (0,t) of a;
+ subpath (t,length a) of a
+ fi
+ endgroup
+enddef;
+
+tertiarydef a cutafter b =
+ reverse (reverse a cutbefore b)
+ hide(cuttings:=reverse cuttings)
+enddef;
+
+
+
+% special operators
+vardef incr suffix $ = $:=$+1; $ enddef;
+vardef decr suffix $ = $:=$-1; $ enddef;
+
+def reflectedabout(expr w,z) = % reflects about the line w..z
+ transformed
+ begingroup transform T_;
+ w transformed T_ = w; z transformed T_ = z;
+ xxpart T_ = -yypart T_; xypart T_ = yxpart T_; % T_ is a reflection
+ T_ endgroup enddef;
+
+def rotatedaround(expr z, d) = % rotates d degrees around z
+ shifted -z rotated d shifted z enddef;
+let rotatedabout = rotatedaround; % for roundabout people
+
+vardef min(expr u)(text t) = % t is a list of numerics, pairs, or strings
+ save u_; setu_ u; for uu = t: if uu<u_: u_:=uu; fi endfor
+ u_ enddef;
+
+vardef max(expr u)(text t) = % t is a list of numerics, pairs, or strings
+ save u_; setu_ u; for uu = t: if uu>u_: u_:=uu; fi endfor
+ u_ enddef;
+
+def setu_ primary u =
+ if pair u: pair u_ elseif string u: string u_ fi;
+ u_=u enddef;
+
+def flex(text t) = % t is a list of pairs
+ hide(n_:=0; for z=t: z_[incr n_]:=z; endfor
+ dz_:=z_[n_]-z_1)
+ z_1 for k=2 upto n_-1: ...z_[k]{dz_} endfor ...z_[n_] enddef;
+newinternal n_; pair z_[],dz_;
+
+def superellipse(expr r,t,l,b,s)=
+ r{up}...(s[xpart t,xpart r],s[ypart r,ypart t]){t-r}...
+ t{left}...(s[xpart t,xpart l],s[ypart l,ypart t]){l-t}...
+ l{down}...(s[xpart b,xpart l],s[ypart l,ypart b]){b-l}...
+ b{right}...(s[xpart b,xpart r],s[ypart r,ypart b]){r-b}...cycle enddef;
+
+vardef interpath(expr a,p,q) =
+ for t=0 upto length p-1: a[point t of p, point t of q]
+ ..controls a[postcontrol t of p, postcontrol t of q]
+ and a[precontrol t+1 of p, precontrol t+1 of q] .. endfor
+ if cycle p: cycle
+ else: a[point infinity of p, point infinity of q] fi enddef;
+
+vardef solve@#(expr true_x,false_x)= % @#(true_x)=true, @#(false_x)=false
+ tx_:=true_x; fx_:=false_x;
+ forever: x_:=.5[tx_,fx_]; exitif abs(tx_-fx_)<=tolerance;
+ if @#(x_): tx_ else: fx_ fi :=x_; endfor
+ x_ enddef; % now x_ is near where @# changes from true to false
+newinternal tolerance, tx_,fx_,x_; tolerance:=.01;
+
+vardef buildcycle(text ll) =
+ save ta_, tb_, k_, i_, pp_; path pp_[];
+ k_=0;
+ for q=ll: pp_[incr k_]=q; endfor
+ i_=k_;
+ for i=1 upto k_:
+ (ta_[i], length pp_[i_]-tb_[i_]) =
+ pp_[i] intersectiontimes reverse pp_[i_];
+ if ta_[i]<0:
+ errmessage("Paths "& decimal i &" and "& decimal i_ &" don't intersect");
+ fi
+ i_ := i;
+ endfor
+ for i=1 upto k_: subpath (ta_[i],tb_[i]) of pp_[i] .. endfor
+ cycle
+enddef;
+
+
+
+%% units of measure
+
+mm=2.83464; pt=0.99626; dd=1.06601; bp:=1;
+cm=28.34645; pc=11.95517; cc=12.79213; in:=72;
+
+vardef magstep primary m = mexp(46.67432m) enddef;
+
+
+
+%% macros for drawing and filling
+
+def drawoptions(text t) =
+ def _op_ = t enddef
+enddef;
+
+linejoin:=rounded; % parameters that effect drawing
+linecap:=rounded;
+miterlimit:=10;
+
+drawoptions();
+
+pen currentpen;
+picture currentpicture;
+
+def fill expr c = addto currentpicture contour c _op_ enddef;
+def draw expr p =
+ addto currentpicture
+ if picture p:
+ also p
+ else:
+ doublepath p withpen currentpen
+ fi
+ _op_
+enddef;
+def filldraw expr c =
+ addto currentpicture contour c withpen currentpen
+ _op_ enddef;
+def drawdot expr z =
+ addto currentpicture contour makepath currentpen shifted z
+ _op_ enddef;
+
+def unfill expr c = fill c withcolor background enddef;
+def undraw expr p = draw p withcolor background enddef;
+def unfilldraw expr c = filldraw c withcolor background enddef;
+def undrawdot expr z = drawdot z withcolor background enddef;
+def erase text t =
+ def _e_ = withcolor background hide(def _e_=enddef;) enddef;
+ t _e_
+enddef;
+def _e_= enddef;
+
+def cutdraw text t =
+ begingroup interim linecap:=butt; draw t _e_; endgroup enddef;
+
+vardef image(text t) =
+ save currentpicture;
+ picture currentpicture;
+ currentpicture := nullpicture;
+ t;
+ currentpicture
+enddef;
+
+def pickup secondary q =
+ if numeric q: numeric_pickup_ else: pen_pickup_ fi q enddef;
+def numeric_pickup_ primary q =
+ if unknown pen_[q]: errmessage "Unknown pen"; clearpen
+ else: currentpen:=pen_[q];
+ pen_lft:=pen_lft_[q];
+ pen_rt:=pen_rt_[q];
+ pen_top:=pen_top_[q];
+ pen_bot:=pen_bot_[q];
+ currentpen_path:=pen_path_[q] fi; enddef;
+def pen_pickup_ primary q =
+ currentpen:=q;
+ pen_lft:=xpart penoffset down of currentpen;
+ pen_rt:=xpart penoffset up of currentpen;
+ pen_top:=ypart penoffset left of currentpen;
+ pen_bot:=ypart penoffset right of currentpen;
+ path currentpen_path; enddef;
+newinternal pen_lft,pen_rt,pen_top,pen_bot,pen_count_;
+
+vardef savepen = pen_[incr pen_count_]=currentpen;
+ pen_lft_[pen_count_]=pen_lft;
+ pen_rt_[pen_count_]=pen_rt;
+ pen_top_[pen_count_]=pen_top;
+ pen_bot_[pen_count_]=pen_bot;
+ pen_path_[pen_count_]=currentpen_path;
+ pen_count_ enddef;
+
+def clearpen = currentpen:=nullpen;
+ pen_lft:=pen_rt:=pen_top:=pen_bot:=0;
+ path currentpen_path;
+ enddef;
+def clear_pen_memory =
+ pen_count_:=0;
+ numeric pen_lft_[],pen_rt_[],pen_top_[],pen_bot_[];
+ pen currentpen,pen_[];
+ path currentpen_path, pen_path_[];
+ enddef;
+
+vardef lft primary x = x + if pair x: (pen_lft,0) else: pen_lft fi enddef;
+vardef rt primary x = x + if pair x: (pen_rt,0) else: pen_rt fi enddef;
+vardef top primary y = y + if pair y: (0,pen_top) else: pen_top fi enddef;
+vardef bot primary y = y + if pair y: (0,pen_bot) else: pen_bot fi enddef;
+
+vardef penpos@#(expr b,d) =
+ (x@#r-x@#l,y@#r-y@#l)=(b,0) rotated d;
+ x@#=.5(x@#l+x@#r); y@#=.5(y@#l+y@#r) enddef;
+
+def penstroke text t =
+ forsuffixes e = l,r: path_.e:=t; endfor
+ fill path_.l -- reverse path_.r -- cycle enddef;
+path path_.l,path_.r;
+
+
+
+%% High level drawing commands
+
+newinternal ahlength, ahangle;
+ahlength := 4; % default arrowhead length 4bp
+ahangle := 45; % default head angle 45 degrees
+
+vardef arrowhead expr p =
+ save q,e; path q; pair e;
+ e = point length p of p;
+ q = gobble(p shifted -e cutafter makepath(pencircle scaled 2ahlength))
+ cuttings;
+ (q rotated .5ahangle & reverse q rotated -.5ahangle -- cycle) shifted e
+enddef;
+
+path _apth;
+def drawarrow expr p = _apth:=p; _finarr enddef;
+def drawdblarrow expr p = _apth:=p; _findarr enddef;
+
+def _finarr text t =
+ draw _apth t;
+ filldraw arrowhead _apth t
+enddef;
+
+def _findarr text t =
+ draw _apth t;
+ fill arrowhead _apth withpen currentpen t;
+ fill arrowhead reverse _apth withpen currentpen t
+enddef;
+
+
+
+%% macros for labels
+
+newinternal bboxmargin; bboxmargin:=2bp;
+
+vardef bbox primary p =
+ llcorner p-(bboxmargin,bboxmargin) -- lrcorner p+(bboxmargin,-bboxmargin)
+ -- urcorner p+(bboxmargin,bboxmargin) -- ulcorner p+(-bboxmargin,bboxmargin)
+ -- cycle
+enddef;
+
+string defaultfont;
+newinternal defaultscale, labeloffset;
+defaultfont = "cmr10";
+defaultscale := 1;
+labeloffset := 3bp;
+
+vardef thelabel@#(expr s,z) = % Position s near z
+ save p; picture p;
+ if picture s: p=s
+ else: p = s infont defaultfont scaled defaultscale
+ fi;
+ p shifted (z + labeloffset*laboff@# -
+ (labxf@#*lrcorner p + labyf@#*ulcorner p
+ + (1-labxf@#-labyf@#)*llcorner p
+ )
+ )
+enddef;
+
+def label = draw thelabel enddef;
+newinternal dotlabeldiam; dotlabeldiam:=3bp;
+vardef dotlabel@#(expr s,z) text t_ =
+ label@#(s,z) t_;
+ label@#(s,z);
+ interim linecap:=rounded;
+ draw z withpen pencircle scaled dotlabeldiam t_;
+enddef;
+def makelabel = dotlabel enddef;
+
+pair laboff, laboff.lft, laboff.rt, laboff.top, laboff.bot;
+pair laboff.ulft, laboff.llft, laboff.urt, laboff.lrt;
+laboff =(0,0); labxf =.5; labyf =.5;
+laboff.lft=(-1,0); labxf.lft=1; labyf.lft=.5;
+laboff.rt =(1,0); labxf.rt =0; labyf.rt =.5;
+laboff.bot=(0,-1); labxf.bot=.5; labyf.bot=1;
+laboff.top=(0,1); labxf.top=.5; labyf.top=0;
+laboff.ulft=(-.7,.7);labxf.ulft=1; labyf.ulft=0;
+laboff.urt=(.7,.7); labxf.urt=0; labyf.urt=0;
+laboff.llft=-(.7,.7);labxf.llft=1; labyf.llft=1;
+laboff.lrt=(.7,-.7); labxf.lrt=0; labyf.lrt=1;
+
+vardef labels@#(text t) =
+ forsuffixes $=t:
+ label@#(str$,z$); endfor
+ enddef;
+vardef dotlabels@#(text t) =
+ forsuffixes $=t:
+ dotlabel@#(str$,z$); endfor
+ enddef;
+vardef penlabels@#(text t) =
+ forsuffixes $$=l,,r: forsuffixes $=t:
+ makelabel@#(str$.$$,z$.$$); endfor endfor
+ enddef;
+
+
+def range expr x = numtok[x] enddef;
+def numtok suffix x=x enddef;
+tertiarydef m thru n =
+ m for x=m+1 step 1 until n: , numtok[x] endfor enddef;
+
+
+
+%% Overall adminstration
+
+string extra_beginfig, extra_endfig;
+extra_beginfig = extra_endfig = "" ;
+
+def beginfig(expr c) =
+ begingroup
+ charcode:=c;
+ clearxy; clearit; clearpen;
+ pickup defaultpen;
+ drawoptions();
+ scantokens extra_beginfig;
+enddef;
+
+def endfig =
+ ; % added by HH
+ scantokens extra_endfig;
+ shipit ;
+ endgroup
+enddef;
+
+
+%% last-minute items
+
+vardef z@#=(x@#,y@#) enddef;
+
+def clearxy = save x,y enddef;
+def clearit = currentpicture:=nullpicture enddef;
+def shipit = shipout currentpicture enddef;
+
+let bye = end; outer end,bye;
+
+clear_pen_memory; % initialize the `savepen' mechanism
+clearit;
+
+newinternal defaultpen;
+pickup pencircle scaled .5bp; % set default line width
+defaultpen := savepen;
diff --git a/metapost/context/base/mp-butt.mp b/metapost/context/base/mp-butt.mp
new file mode 100644
index 000000000..cf580211e
--- /dev/null
+++ b/metapost/context/base/mp-butt.mp
@@ -0,0 +1,75 @@
+%D \module
+%D [ file=mp-butt.mp,
+%D version=2000.05.31,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=buttons,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_butt : endinput ; fi ;
+
+boolean context_butt ; context_butt := true ;
+
+def some_button (expr button_type ,
+ button_size ,
+ button_linecolor ,
+ button_fillcolor ) =
+
+ numeric button_linewidth ; button_linewidth := button_size/10 ;
+
+ drawoptions (withpen pencircle scaled button_linewidth
+ withcolor button_linecolor) ;
+
+ path p ; p := unitsquare scaled button_size ;
+ numeric d ; d := button_size ;
+ numeric l ; l := button_linewidth ;
+
+ fill p withcolor button_fillcolor ; draw p ;
+
+ if button_type=101 :
+ draw (d-2l,2l)--(2l,.5d)--(d-2l,d-2l)--cycle ;
+ elseif button_type=102 :
+ draw (2l,2l)--(d-2l,.5d)--(2l,d-2l)--cycle ;
+ elseif button_type=103 :
+ for i=2l step 2l until d-2l :
+ draw (2l,i)--(2l ,i) ;
+ draw (4l,i)--(d-2l,i) ;
+ endfor ;
+ elseif button_type=104 :
+ for i=2l step 2l until d-2l :
+ draw (2l ,i)--(d/2-l,i) ;
+ draw (d/2+l,i)--(d-2l ,i) ;
+ endfor ;
+ elseif button_type=105 :
+ fill fullcircle scaled (.2d) shifted (.5d,.7d) ;
+ fill fullcircle xscaled (.6d) yscaled d shifted (.5d,0) ;
+ clip currentpicture to p ;
+ draw p ;
+ elseif button_type=106 :
+ draw (2l,2l)--(d-2l,d-2l) ;
+ draw (d-2l,2l)--(2l,d-2l) ;
+ elseif button_type=107 :
+ p := (3l,d-2l)--(d-3l,d-2l)--(.5d,4l)--cycle ;
+ fill p ; draw p ;
+ draw (.5d,2l) ;
+ elseif button_type=108 :
+ draw (.5d,2l)--(d-2l,d-2l)--(2l,d-2l)--cycle ;
+ elseif button_type=109 :
+ draw (.5d,d-2l)--(d-2l,2l)--(2l,2l)--cycle ;
+ elseif button_type=110 :
+ button_linewidth := button_linewidth/2 ;
+ draw p enlarged (-2l,-l) ;
+ for i=2l step l until d-2l :
+ draw (3l,i)--(d-3l,i) ;
+ endfor ;
+ fi ;
+
+enddef ;
+
+endinput ;
diff --git a/metapost/context/base/mp-char.mp b/metapost/context/base/mp-char.mp
new file mode 100644
index 000000000..786c1f904
--- /dev/null
+++ b/metapost/context/base/mp-char.mp
@@ -0,0 +1,999 @@
+% to be cleaned up, namespace needed ! ! ! ! !
+
+%D \module
+%D [ file=mp-char.mp,
+%D version=1998.10.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=charts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if unknown context_shap : input mp-shap ; fi ;
+if known context_char : endinput ; fi ;
+
+boolean context_char ; context_char := true ;
+
+% kan naar elders
+
+current_position := 0 ;
+
+def save_text_position (expr p) = % beware: clip shift needed
+ current_position := current_position + 1 ;
+ savedata
+ "\MPposition{" & decimal current_position & "}{"
+ & decimal xpart p & "}{"
+ & decimal ypart p & "}%" ;
+enddef ;
+
+%D settings
+
+grid_width := 60pt ; grid_height := 40pt ;
+shape_width := 45pt ; shape_height := 30pt ;
+
+chart_offset := 2pt ;
+
+color chart_background_color ; chart_background_color := white ;
+
+%D test mode
+
+boolean show_mid_points ; show_mid_points := false ;
+boolean show_con_points ; show_con_points := false ;
+boolean show_all_points ; show_all_points := false ;
+
+%D shapes
+
+color shape_line_color, shape_fill_color ;
+
+shape_line_width := 2pt ;
+shape_line_color := .5white ;
+shape_fill_color := .9white ;
+
+shape_node := 0 ;
+shape_action := 24 ;
+shape_procedure := 5 ;
+shape_product := 12 ;
+shape_decision := 14 ;
+shape_archive := 19 ;
+shape_loop := 35 ;
+shape_wait := 6 ;
+shape_subprocedure := 20 ; shape_sub_procedure := 20 ;
+shape_singledocument := 32 ; shape_single_document := 32 ;
+shape_multidocument := 33 ; shape_multi_document := 33 ;
+shape_right := 66 ;
+shape_left := 67 ;
+shape_up := 68 ;
+shape_down := 69 ;
+
+% vardef some_shape_path (expr type) == imported from mp-shap
+
+def show_shapes (expr n) =
+
+ begin_chart(n,8,10) ;
+ show_con_points := true ;
+ for i=0 upto 7 :
+ for j=0 upto 9 :
+ new_shape(i+1,j+1,i*10+j);
+ endfor ;
+ endfor ;
+ end_chart ;
+
+enddef ;
+
+%D connections
+
+def new_chart =
+
+ color connection_line_color ;
+
+ connection_line_width := shape_line_width ;
+ connection_line_color := .8white ;
+ connection_smooth_size := 5pt ;
+ connection_arrow_size := 4pt ;
+ connection_dash_size := 3pt ;
+
+ max_x := 6 ;
+ max_y := 4 ;
+
+ numeric xypoint ; xypoint := 0 ;
+
+ pair xypoints [] ;
+
+ boolean xyfree [][] ;
+ path xypath [][] ;
+ numeric xysx [][] ;
+ numeric xysy [][] ;
+ color xyfill [][] ;
+ color xydraw [][] ;
+ numeric xyline [][] ;
+ boolean xypeep [][] ;
+
+ numeric cpath ; cpath := 0 ;
+ path cpaths [] ;
+ numeric cline [] ;
+ color ccolor [] ;
+ boolean carrow [] ;
+ boolean cdash [] ;
+ boolean ccross [] ;
+
+ boolean smooth ; smooth := true ;
+ boolean peepshape ; peepshape := false ;
+ boolean arrowtip ; arrowtip := true ;
+ boolean dashline ; dashline := false ;
+ boolean forcevalid ; forcevalid := false ;
+ boolean touchshape ; touchshape := false ;
+ boolean showcrossing ; showcrossing := false ;
+
+ picture dash_pattern ;
+
+ boolean reverse_y ; reverse_y := true ;
+
+enddef ;
+
+new_chart ;
+
+def y_pos (expr y) =
+ if reverse_y : max_y + 1 - y else : y fi
+enddef ;
+
+def initialize_grid (expr maxx, maxy) =
+ begingroup ;
+ save i, j ;
+ max_x := maxx ;
+ max_y := maxy ;
+ dsp_x := 0 ;
+ dsp_y := 0 ;
+ for x=1 upto max_x :
+ for y=1 upto max_y :
+ xyfree [x][y] := true ;
+ xyfill [x][y] := shape_fill_color ;
+ xydraw [x][y] := shape_line_color ;
+ xyline [x][y] := shape_line_width ;
+ endfor ;
+ endfor ;
+ endgroup ;
+enddef ;
+
+def scaled_to_grid =
+ xscaled grid_width yscaled grid_height
+enddef ;
+
+def xy_offset (expr x, y) =
+ (x+.5,y+.5)
+enddef ;
+
+def draw_shape (expr x, yy, p, sx, sy) =
+ begingroup ;
+ save y ;
+ y := y_pos(yy) ;
+ xypath [x][y] := (p xscaled sx yscaled sy) shifted xy_offset(x,y) ;
+ xyfree [x][y] := false ;
+ xysx [x][y] := sx ;
+ xysy [x][y] := sy ;
+ xyfill [x][y] := shape_fill_color ;
+ xydraw [x][y] := shape_line_color ;
+ xyline [x][y] := shape_line_width ;
+ xypeep [x][y] := peepshape ;
+ endgroup ;
+enddef ;
+
+vardef i_point (expr x, y, p, t) =
+ begingroup ;
+ save q, ok ;
+ pair q ;
+ boolean ok ;
+ q := xypath[x][y] intersection_point ((p) shifted xy_offset(x,y)) ;
+ ok := true ;
+% if xpart q < -.5 : ok := false ; q := (-.45,ypart q) fi ;
+% if xpart q > .5 : ok := false ; q := ( .45,ypart q) fi ;
+% if ypart q < -.5 : ok := false ; q := (xpart q,-.45) fi ;
+% if ypart q > .5 : ok := false ; q := (xpart q, .45) fi ;
+ if not ok :
+ message (t & " of shape (" & decimal x & "," & decimal y & ") limited") ;
+ fi ;
+ q
+ endgroup
+enddef ;
+
+vardef trimmed (expr x, y, z, t) =
+ if touchshape and t : xyline[x][y]/z else : epsilon fi
+enddef ;
+
+zfactor := 1/3 ;
+
+vardef xy_bottom (expr x, y, z, t) =
+ i_point (x, y, ((0,0)--(0,-2)) shifted (zfactor*z*xysx[x][y],0), "bottom")
+ shifted(0,-trimmed(x,y,grid_height,t))
+enddef ;
+
+vardef xy_top (expr x, y, z, t) =
+ i_point (x, y, ((0,0)--(0,2)) shifted (zfactor*z*xysx[x][y],0), "top")
+ shifted(0,trimmed(x,y,grid_height,t))
+enddef ;
+
+vardef xy_left (expr x, y, z, t) =
+ i_point (x, y, ((0,0)--(-2,0)) shifted (0,zfactor*z*xysy[x][y]), "left")
+ shifted(-trimmed(x,y,grid_width,t),0)
+enddef ;
+
+vardef xy_right (expr x, y, z, t) =
+ i_point (x, y, ((0,0)--(2,0)) shifted (0,zfactor*z*xysy[x][y]), "right")
+ shifted(trimmed(x,y,grid_width,t),0)
+enddef ;
+
+def flush_shapes =
+ for x=1 upto max_x :
+ for y=1 upto max_y :
+ flush_shape (x, y) ;
+ endfor ;
+ endfor ;
+enddef ;
+
+def draw_connection_point (expr x, y, z) =
+ pickup pencircle scaled if (z=0): 2 fi xyline[x][y] ;
+ drawdot xy_bottom(x,y,z,false) scaled_to_grid withcolor (1,0,0) ;
+ drawdot xy_top (x,y,z,false) scaled_to_grid withcolor (0,1,0) ;
+ drawdot xy_left (x,y,z,false) scaled_to_grid withcolor (0,0,1) ;
+ drawdot xy_right (x,y,z,false) scaled_to_grid withcolor (1,1,0) ;
+enddef ;
+
+def flush_shape (expr x, yy) =
+ begingroup ;
+ save y ;
+ y := y_pos(yy) ;
+ if not xyfree[x][y] :
+ pickup pencircle scaled xyline[x][y] ;
+ if xypeep[x][y] :
+ fill (xypath[x][y] peepholed (unitsquare shifted (x,y)))
+ scaled_to_grid withpen pencircle scaled 0
+ withcolor chart_background_color ;
+ else :
+ fill xypath[x][y] scaled_to_grid withcolor xyfill[x][y] ;
+ fi ;
+ draw xypath[x][y] scaled_to_grid withcolor xydraw[x][y] ;
+ if show_con_points or show_all_points :
+ draw_connection_point (x, y, 0) ;
+ fi ;
+ if show_all_points :
+ for i=-1 upto 1 :
+ draw_connection_point (x, y, i) ;
+ endfor ;
+ fi ;
+ fi ;
+ endgroup ;
+enddef ;
+
+vardef points_initialized (expr xfrom, yfrom, xto, yto, n) =
+ if not xyfree[xfrom][yfrom] and not xyfree[xto][yto] :
+ xypoint := n ; true
+ else :
+ xypoint := 0 ; false
+ fi
+enddef ;
+
+def collapse_points = % this is now an mp-tool macro
+ % remove redundant points
+ n := 1 ;
+ for i=2 upto xypoint:
+ if not (xypoints[i]=xypoints[n]) :
+ n := n + 1 ;
+ xypoints[n] := xypoints[i]
+ fi ;
+ endfor ;
+ xypoint := n ;
+ % make straight lines
+ if xypoints[2]=xypoints[xypoint-1] :
+ xypoints[3] := xypoints[xypoint] ;
+ xypoint := 3 ;
+ fi ;
+enddef ;
+
+vardef smooth_connection (expr a,b) =
+ sx := connection_smooth_size/grid_width ;
+ sy := connection_smooth_size/grid_height ;
+ if ypart a = ypart b :
+ a shifted (if xpart a >= xpart b : - fi sx,0)
+% a shifted (sx*xpart unitvector(b-a),0)
+ else :
+ a shifted (0,if ypart a >= ypart b : - fi sy)
+% a shifted (0,sy*ypart unitvector(b-a))
+ fi
+enddef ;
+
+vardef trim_points =
+ begingroup
+ save p, a, b, d, i ; path p ; pair d ;
+ p := for i=1 upto xypoint-1 : xypoints[i]-- endfor xypoints[xypoint] ;
+ if touchshape :
+ a := shape_line_width/grid_width ;
+ b := shape_line_width/grid_height ;
+ else :
+ a := epsilon ;
+ b := epsilon ;
+ fi ;
+ d := direction infinity of p ;
+ xypoints[xypoint] := xypoints[xypoint] shifted
+ if xpart d < 0 : (+a,0) ;
+ elseif xpart d > 0 : (-a,0) ;
+ elseif ypart d < 0 : (0,+b) ;
+ elseif ypart d > 0 : (0,-b) ;
+ else : origin ;
+ fi ;
+ d := direction 0 of p ;
+ xypoints[1] := xypoints[1] shifted
+ if xpart d < 0 : (-a,0) ;
+ elseif xpart d > 0 : (+a,0) ;
+ elseif ypart d < 0 : (0,-b) ;
+ elseif ypart d > 0 : (0,+b) ;
+ else : origin ;
+ fi ;
+ endgroup
+enddef ;
+
+vardef trim_points = enddef ;
+
+vardef connection_path =
+ if reverse_connection : reverse fi (xypoints[1]--
+ for i=2 upto xypoint-1 :
+ if smooth :
+ smooth_connection(xypoints[i],xypoints[i-1]) ..
+ controls xypoints[i] and xypoints[i] ..
+ smooth_connection(xypoints[i],xypoints[i+1]) --
+ else :
+ xypoints[i]--
+ fi
+ endfor
+ xypoints[xypoint])
+enddef ;
+
+% vardef connection_path =
+% sx := connection_smooth_size/grid_width ;
+% sy := connection_smooth_size/grid_height ;
+% if reverse_connection : reverse fi
+% (for i=1 upto xypoint-1 : xypoints[i] -- endfor xypoints[xypoint])
+% if smooth : cornered max(sx,sy) fi
+% enddef ;
+%
+% primarydef p cornered c =
+% if cycle p :
+% ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) --
+% for i=1 upto length(p) :
+% (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) --
+% (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) ..
+% controls point i of p ..
+% endfor cycle)
+% else :
+% ((point 0 of p) --
+% for i=1 upto length(p)-1 :
+% (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) --
+% (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) ..
+% controls point i of p ..
+% endfor
+% (point length(p) of p))
+% fi
+% enddef ;
+
+def draw_connection =
+ if xypoint>0 :
+ collapse_points ;
+ trim_points ;
+ cpath := cpath + 1 ;
+ cpaths[cpath] := connection_path scaled_to_grid ;
+ cline[cpath] := connection_line_width ;
+ ccolor[cpath] := connection_line_color ;
+ carrow[cpath] := arrowtip ;
+ cdash[cpath] := dashline ;
+ ccross[cpath] := showcrossing ;
+ else :
+ message("no connection defined") ;
+ fi ;
+ reverse_connection := false ;
+enddef ;
+
+def flush_connections =
+ pair ip ;
+ boolean crossing ;
+ ahlength := connection_arrow_size ;
+ dash_pattern := dashpattern(on connection_dash_size off connection_dash_size ) ;
+ for i=1 upto cpath :
+ if ccross[i] :
+ crossing := false ;
+ for j=1 upto i :
+ %if not ((point infinity of cpaths[i] = point infinity of cpaths[j]) or
+ % (point 0 of cpaths[i] = point 0 of cpaths[j])) :
+ if not (point infinity of cpaths[i] = point infinity of cpaths[j]) :
+ ip := cpaths[i] intersection_point cpaths[j] ;
+ if intersection_found : crossing := true fi ;
+ fi ;
+ endfor ;
+ if crossing :
+ pickup pencircle scaled 2cline[i] ;
+ %draw cpaths[i] withcolor chart_background_color ;
+ path cp ; cp := cpaths[i] ;
+ cp := cp cutbefore point .05 length cp of cp ;
+ cp := cp cutafter point .95 length cp of cp ;
+ draw cp withcolor chart_background_color ;
+ fi ;
+ fi ;
+ pickup pencircle scaled cline[i] ;
+ if carrow[i] :
+ if cdash[i] :
+ drawarrow cpaths[i] withcolor ccolor[i] dashed dash_pattern ;
+ else :
+ drawarrow cpaths[i] withcolor ccolor[i] ;
+ fi ;
+ else :
+ if cdash[i] :
+ draw cpaths[i] withcolor ccolor[i] dashed dash_pattern ;
+ else :
+ draw cpaths[i] withcolor ccolor[i] ;
+ fi ;
+ fi ;
+ draw_midpoint (i) ;
+ endfor ;
+enddef ;
+
+def draw_midpoint (expr n) =
+ begingroup
+ save p ;
+ pair p ;
+ p := point .5*length(cpaths[n]) of cpaths[n];
+ pickup pencircle scaled 2cline[n] ;
+ save_text_position (p) ;
+ if show_mid_points :
+ drawdot p withcolor .7white ;
+ fi ;
+ endgroup ;
+enddef ;
+
+boolean reverse_connection ; reverse_connection := false ;
+
+vardef up_on_grid (expr n) =
+ (xpart xypoints[n],(ypart xypoints[n]+1) div 1)
+enddef ;
+
+vardef down_on_grid (expr n) =
+ (xpart xypoints[n],(ypart xypoints[n]) div 1)
+enddef ;
+
+vardef left_on_grid (expr n) =
+ ((xpart xypoints[n]) div 1, ypart xypoints[n])
+enddef ;
+
+vardef right_on_grid (expr n) =
+ ((xpart xypoints[n]+1) div 1, ypart xypoints[n])
+enddef ;
+
+vardef x_on_grid (expr n, xfrom, xto, zfrom) =
+ if (xfrom=xto) and not (zfrom=0) :
+ if (zfrom=1) : right_on_grid(2) else : left_on_grid(2) fi
+ elseif xpart xypoints[1] < xpart xypoints[6] :
+ right_on_grid(n)
+ else :
+ left_on_grid(n)
+ fi
+enddef ;
+
+vardef y_on_grid (expr n, yfrom, yto, zfrom) =
+ if (yfrom=yto) and not (zfrom=0) :
+ if (zfrom=1) : up_on_grid(2) else : down_on_grid(2) fi
+ elseif ypart xypoints[1] < ypart xypoints[6] :
+ up_on_grid(n)
+ else :
+ down_on_grid(n)
+ fi
+enddef ;
+
+vardef xy_on_grid (expr n, m) =
+ (xpart xypoints[n], ypart xypoints[m])
+enddef ;
+
+vardef down_to_grid (expr a,b) =
+ (xpart xypoints[a],
+ ypart xypoints[if ypart xypoints[a]<ypart xypoints[b]:a else:b fi])
+enddef ;
+
+vardef up_to_grid (expr a,b) =
+ (xpart xypoints[a],
+ ypart xypoints[if ypart xypoints[a]>ypart xypoints[b]:a else:b fi])
+enddef ;
+
+vardef left_to_grid (expr a,b) =
+ (xpart xypoints[if xpart xypoints[a]<xpart xypoints[b]:a else:b fi],
+ ypart xypoints[a])
+enddef ;
+
+vardef right_to_grid (expr a,b) =
+ (xpart xypoints[if xpart xypoints[a]>xpart xypoints[b]:a else:b fi],
+ ypart xypoints[a])
+enddef ;
+
+% vardef boundingboxfraction(expr p, f) =
+% ((boundingbox p) enlarged (-f*bbwidth(p),-f*bbheight(p)))
+% enddef ;
+
+vardef valid_connection (expr xfrom, yfrom, xto, yto) =
+ begingroup ;
+ save ok, vc, pp ;
+ boolean ok ;
+ % check for slanted lines
+ ok := true ;
+ for i=1 upto xypoint-1 :
+ if not ((xpart xypoints[i]=xpart xypoints[i+1]) or
+ (ypart xypoints[i]=ypart xypoints[i+1])) : ok := false ;
+ fi ;
+ endfor ;
+ if not ok :
+ %message("slanted");
+ false
+ elseif forcevalid :
+ %message("force");
+ true
+ elseif (xfrom=xto) and (yfrom=yto) :
+ %message("self");
+ false
+ else :
+ % check for crossing shapes
+ pair vc ;
+ path pp ;
+
+ pair xyfirst, xylast ;
+ xyfirst := xypoints[1] ;
+ xylast := xypoints[xypoint] ;
+ trim_points ;
+ pp := for i=1 upto xypoint-1 : xypoints[i]-- endfor xypoints[xypoint] ;
+ xypoints[1] := xyfirst ;
+ xypoints[xypoint] := xylast ;
+
+ for i=1 upto max_x :
+ for j=1 upto max_y : % was bug: xfrom,yto
+ if not ( ( (i,j)=(xfrom,yfrom) ) or ( (i,j)=(xto,yto) ) ) :
+ if not xyfree[i][j] :
+ vc := pp intersection_point xypath[i][j] ;
+ if intersection_found : ok := false fi ;
+ fi ;
+ fi ;
+ endfor ;
+ endfor ;
+ %if not ok: message("crossing") ; fi ;
+ ok
+ fi
+ endgroup
+enddef ;
+
+def connect_top_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,6) :
+ xypoints[1] := xy_top(xfrom,yfrom,zfrom,true) ;
+ xypoints[6] := xy_bottom(xto,yto,zto,true) ;
+ xypoints[2] := up_on_grid(1) ;
+ xypoints[5] := down_on_grid(6) ;
+ xypoints[3] := up_to_grid(2,5) ;
+ xypoints[4] := up_to_grid(2,5) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ;
+ xypoints[4] := xy_on_grid(3,5) ;
+ fi ;
+ %%%% begin experiment
+ xypoints[3] := xypoints[3] shifted (dsp_x,0) ;
+ xypoints[4] := xypoints[4] shifted (dsp_x,0) ;
+ if dsp_y>0 :
+ xypoints[2] := xypoints[2] shifted (0,dsp_y) ;
+ xypoints[3] := xypoints[3] shifted (0,dsp_y) ;
+ elseif dsp_y<0 :
+ xypoints[4] := xypoints[4] shifted (0,dsp_y) ;
+ xypoints[5] := xypoints[5] shifted (0,dsp_y) ;
+ fi
+ %%%% end experiment
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_left_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,6) :
+ xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+ xypoints[6] := xy_right(xto,yto,zto,true) ;
+ xypoints[2] := left_on_grid(1) ;
+ xypoints[5] := right_on_grid(6) ;
+ xypoints[3] := left_to_grid(2,5) ;
+ xypoints[4] := left_to_grid(2,5) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ;
+ xypoints[4] := xy_on_grid(5,3) ;
+ fi ;
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_left_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,5) :
+ xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+ xypoints[5] := xy_top(xto,yto,zto,true) ;
+ xypoints[2] := left_on_grid(1) ;
+ xypoints[4] := up_on_grid(5) ;
+ xypoints[3] := left_to_grid(2,5) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := xy_on_grid(2,4) ;
+ fi ;
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_left_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,5) :
+ xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+ xypoints[5] := xy_bottom(xto,yto,zto,true) ;
+ xypoints[2] := left_on_grid(1) ;
+ xypoints[4] := down_on_grid(5) ;
+ xypoints[3] := left_to_grid(2,5) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := xy_on_grid(2,4) ;
+ fi ;
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_right_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,5) :
+ xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ;
+ xypoints[5] := xy_top(xto,yto,zto,true) ;
+ xypoints[2] := right_on_grid(1) ;
+ xypoints[4] := up_on_grid(5) ;
+ xypoints[3] := right_to_grid(2,5) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := xy_on_grid(2,4) ;
+ fi ;
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_right_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,5) :
+ xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ;
+ xypoints[5] := xy_bottom(xto,yto,zto,true) ;
+ xypoints[2] := right_on_grid(1) ;
+ xypoints[4] := down_on_grid(5) ;
+ xypoints[3] := right_to_grid(2,5) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := xy_on_grid(2,4) ;
+ fi ;
+ %%%% begin experiment
+ xypoints[2] := xypoints[2] shifted (dsp_x,0) ;
+ xypoints[3] := xypoints[3] shifted (dsp_x,0) ;
+ if dsp_y>0 :
+ xypoints[3] := xypoints[3] shifted (0,-dsp_y) ;
+ xypoints[4] := xypoints[4] shifted (0,-dsp_y) ;
+ elseif dsp_y<0 :
+ xypoints[3] := xypoints[3] shifted (0,dsp_y) ;
+ xypoints[4] := xypoints[4] shifted (0,dsp_y) ;
+ fi
+ %%%% end experiment
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_left_left (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,6) :
+ xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+ xypoints[6] := xy_left(xto,yto,zto,true) ;
+ xypoints[2] := left_on_grid(1) ;
+ xypoints[5] := left_on_grid(6) ;
+ xypoints[3] := left_to_grid(2,5) ;
+ xypoints[4] := left_to_grid(5,2) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ;
+ xypoints[4] := xy_on_grid(5,3) ;
+ fi ;
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_right_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,6) :
+ xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ;
+ xypoints[6] := xy_right(xto,yto,zto,true) ;
+ xypoints[2] := right_on_grid(1) ;
+ xypoints[5] := right_on_grid(6) ;
+ xypoints[3] := right_to_grid(2,5) ;
+ xypoints[4] := right_to_grid(5,2) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ;
+ xypoints[4] := xy_on_grid(5,3) ;
+ fi ;
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_top_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,6) :
+ xypoints[1] := xy_top(xfrom,yfrom,zfrom,true) ;
+ xypoints[6] := xy_top(xto,yto,zto,true) ;
+ xypoints[2] := up_on_grid(1) ;
+ xypoints[5] := up_on_grid(6) ;
+ xypoints[3] := up_to_grid(2,5) ;
+ xypoints[4] := up_to_grid(5,2) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ;
+ xypoints[4] := xy_on_grid(3,5) ;
+ fi ;
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_bottom_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+ if points_initialized(xfrom,yfrom,xto,yto,6) :
+ xypoints[1] := xy_bottom(xfrom,yfrom,zfrom,true) ;
+ xypoints[6] := xy_bottom(xto,yto,zto,true) ;
+ xypoints[2] := down_on_grid(1) ;
+ xypoints[5] := down_on_grid(6) ;
+ xypoints[3] := down_to_grid(2,5) ;
+ xypoints[4] := down_to_grid(5,2) ;
+ if not valid_connection(xfrom,yfrom,xto,yto) :
+ xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ;
+ xypoints[4] := xy_on_grid(3,5) ;
+ fi ;
+ %%%% begin experiment
+ xypoints[3] := xypoints[3] shifted (dsp_x,0) ;
+ xypoints[4] := xypoints[4] shifted (dsp_x,0) ;
+ if dsp_y<0 :
+ xypoints[2] := xypoints[2] shifted (0,-dsp_y) ;
+ xypoints[3] := xypoints[3] shifted (0,-dsp_y) ;
+ elseif dsp_y>0 :
+ xypoints[4] := xypoints[4] shifted (0,dsp_y) ;
+ xypoints[5] := xypoints[5] shifted (0,dsp_y) ;
+ fi
+ %%%% end experiment
+ draw_connection ;
+ fi ;
+enddef ;
+
+def connect_bottom_top (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ reverse_connection := true ;
+ connect_top_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_right_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ reverse_connection := true ;
+ connect_left_right (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_top_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ reverse_connection := true ;
+ connect_left_top (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_bottom_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ reverse_connection := true ;
+ connect_left_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_top_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ reverse_connection := true ;
+ connect_right_top (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_bottom_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ reverse_connection := true ;
+ connect_right_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def draw_test_shape (expr x, y) =
+ draw_shape(x,y,fullcircle, .7, .7) ;
+enddef ;
+
+def draw_test_shapes =
+ for i=1 upto max_x :
+ for j=1 upto max_y :
+ draw_test_shape(i,j) ;
+ endfor ;
+ endfor ;
+enddef;
+
+def draw_test_area =
+ pickup pencircle scaled .5shape_line_width ;
+ draw (unitsquare xscaled max_x yscaled max_y shifted (1,1))
+ scaled_to_grid withcolor blue ;
+enddef ;
+
+def show_connection (expr n, m) =
+
+ begin_chart(100+n,6,6) ;
+
+ draw_test_area ;
+
+ smooth := true ;
+ arrowtip := true ;
+ dashline := true ;
+
+ draw_test_shape(2,2) ; draw_test_shape(4,5) ;
+ draw_test_shape(3,3) ; draw_test_shape(5,1) ;
+ draw_test_shape(2,5) ; draw_test_shape(1,3) ;
+ draw_test_shape(6,2) ; draw_test_shape(4,6) ;
+
+ if (m=1) :
+ connect_top_bottom (2,2,0) (4,5,0) ;
+ connect_top_bottom (3,3,0) (5,1,0) ;
+ connect_top_bottom (2,5,0) (1,3,0) ;
+ connect_top_bottom (6,2,0) (4,6,0) ;
+ elseif (m=2) :
+ connect_top_top (2,2,0) (4,5,0) ;
+ connect_top_top (3,3,0) (5,1,0) ;
+ connect_top_top (2,5,0) (1,3,0) ;
+ connect_top_top (6,2,0) (4,6,0) ;
+ elseif (m=3) :
+ connect_bottom_bottom (2,2,0) (4,5,0) ;
+ connect_bottom_bottom (3,3,0) (5,1,0) ;
+ connect_bottom_bottom (2,5,0) (1,3,0) ;
+ connect_bottom_bottom (6,2,0) (4,6,0) ;
+ elseif (m=4) :
+ connect_left_right (2,2,0) (4,5,0) ;
+ connect_left_right (3,3,0) (5,1,0) ;
+ connect_left_right (2,5,0) (1,3,0) ;
+ connect_left_right (6,2,0) (4,6,0) ;
+ elseif (m=5) :
+ connect_left_left (2,2,0) (4,5,0) ;
+ connect_left_left (3,3,0) (5,1,0) ;
+ connect_left_left (2,5,0) (1,3,0) ;
+ connect_left_left (6,2,0) (4,6,0) ;
+ elseif (m=6) :
+ connect_right_right (2,2,0) (4,5,0) ;
+ connect_right_right (3,3,0) (5,1,0) ;
+ connect_right_right (2,5,0) (1,3,0) ;
+ connect_right_right (6,2,0) (4,6,0) ;
+ elseif (m=7) :
+ connect_left_top (2,2,0) (4,5,0) ;
+ connect_left_top (3,3,0) (5,1,0) ;
+ connect_left_top (2,5,0) (1,3,0) ;
+ connect_left_top (6,2,0) (4,6,0) ;
+ elseif (m=8) :
+ connect_left_bottom (2,2,0) (4,5,0) ;
+ connect_left_bottom (3,3,0) (5,1,0) ;
+ connect_left_bottom (2,5,0) (1,3,0) ;
+ connect_left_bottom (6,2,0) (4,6,0) ;
+ elseif (m=9) :
+ connect_right_top (2,2,0) (4,5,0) ;
+ connect_right_top (3,3,0) (5,1,0) ;
+ connect_right_top (2,5,0) (1,3,0) ;
+ connect_right_top (6,2,0) (4,6,0) ;
+ else :
+ connect_right_bottom (2,2,0) (4,5,0) ;
+ connect_right_bottom (3,3,0) (5,1,0) ;
+ connect_right_bottom (2,5,0) (1,3,0) ;
+ connect_right_bottom (6,2,0) (4,6,0) ;
+ fi ;
+
+ end_chart ;
+
+enddef ;
+
+def show_connections =
+ for f=1 upto 10 :
+ show_connection(f,f) ;
+ endfor ;
+enddef ;
+
+%D charts
+
+def clip_chart (expr minx, miny, maxx, maxy) =
+ cmin_x := minx ;
+ cmax_x := maxx ;
+ cmin_y := miny ;
+ cmax_y := maxy ;
+enddef ;
+
+def begin_chart (expr n, maxx, maxy) =
+ new_chart ;
+ chart_figure := n ;
+ chart_scale := 1 ;
+ if chart_figure>0: beginfig(chart_figure) ; fi ;
+ startsavingdata ;
+ initialize_grid (maxx, maxy) ;
+ bboxmargin := 0 ;
+ cmin_x := 1 ;
+ cmax_x := maxx ;
+ cmin_y := 1 ;
+ cmax_y := maxy ;
+enddef ;
+
+def end_chart =
+ flush_shapes ;
+ flush_connections ;
+ cmin_x := cmin_x ;
+ cmax_x := cmin_x+cmax_x ;
+ cmin_y := cmin_y-1 ;
+ cmax_y := cmin_y+cmax_y ;
+ if reverse_y :
+ cmin_y := y_pos(cmin_y) ;
+ cmax_y := y_pos(cmax_y) ;
+ fi ;
+ path p ;
+ p := (((cmin_x,cmin_y)--(cmax_x,cmin_y)--
+ (cmax_x,cmax_y)--(cmin_x,cmax_y)--cycle))
+ scaled_to_grid ;
+ %draw p withcolor red ;
+ p := p enlarged chart_offset ;
+ clip currentpicture to p ;
+ setbounds currentpicture to p ;
+ savedata
+ "\MPclippath{" &
+ decimal xpart llcorner p & "}{" &
+ decimal ypart llcorner p & "}{" &
+ decimal xpart urcorner p & "}{" &
+ decimal ypart urcorner p & "}%" ;
+ savedata
+ "\MPareapath{" &
+ decimal (xpart llcorner p + 2chart_offset) & "}{" &
+ decimal (ypart llcorner p + 2chart_offset) & "}{" &
+ decimal (xpart urcorner p - 2chart_offset) & "}{" &
+ decimal (ypart urcorner p - 2chart_offset) & "}%" ;
+ currentpicture := currentpicture scaled chart_scale ;
+ stopsavingdata ;
+ if chart_figure>0: endfig ; fi ;
+enddef ;
+
+def new_shape (expr x, y, n) =
+ if known n :
+ if (x>0) and (x<=max_x) and (y>0) and (y<=max_y) :
+ sx := shape_width/grid_width ;
+ sy := shape_height/grid_height ;
+ draw_shape(x,y,some_shape_path(n), sx, sy) ;
+ else :
+ message ("shape outside grid ignored") ;
+ fi ;
+ else
+ message ("shape not known" ) ;
+ fi ;
+enddef ;
+
+def begin_sub_chart =
+ begingroup ;
+ save shape_line_width , connection_line_width ;
+ save shape_line_color, shape_fill_color, connection_line_color ;
+ color shape_line_color, shape_fill_color, connection_line_color ;
+ save smooth, arrowtip, dashline, peepshape ;
+ boolean smooth, arrowtip, dashline, peepshape ;
+enddef ;
+
+def end_sub_chart =
+ endgroup ;
+enddef ;
+
+%D done
+
+endinput ;
+
+%D testing
+
+show_shapes(100) ;
+
+end
+
+%D more testing
+
+show_connections ;
+
+begin_chart (1,4,5) ;
+ %clip_chart(1,1,1,2) ;
+ new_shape (1,1,31) ;
+ new_shape (1,2,3) ;
+ new_shape (4,4,5) ;
+ connect_top_left (1,1,0) (4,4,0) ;
+ connect_bottom_top (1,2,0) (4,4,0) ;
+ connect_left_right (1,2,0) (1,1,0) ;
+end_chart ;
+
+end
diff --git a/metapost/context/base/mp-chem.mp b/metapost/context/base/mp-chem.mp
new file mode 100644
index 000000000..c70dafd85
--- /dev/null
+++ b/metapost/context/base/mp-chem.mp
@@ -0,0 +1,761 @@
+%D \module
+%D [ file=mp-chem.mp,
+%D version=2009.05.13,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=chemicals,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D This module in incomplete and experimental.
+
+% either consistent setting or not
+
+if known chem_reset : endinput ; fi ;
+
+numeric
+ chem_width, chem_radical_min, chem_radical_max, chem_text_max, chem_circle_radius,
+ chem_rotation, chem_adjacent, chem_stack, chem_substituent, chem_direction, chem_setting_scale,
+ chem_setting_offset, chem_text_offset, chem_picture_offset, chem_center_offset, chem_substituent_offset,
+ chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b ;
+
+boolean
+ chem_setting_axis,
+ chem_setting_fixedwidth, chem_setting_fixedheight,
+ chem_doing_pb, chem_text_trace ;
+
+path
+ chem_setting_bbox ;
+
+pair
+ chem_shift,
+ chem_adjacent_p, chem_substituent_p, chem_direction_p, chem_move_p ;
+
+numeric
+ chem_width[], chem_angle[], chem_start[], chem_initialrot[], chem_initialmov[] ;
+
+pair
+ chem_stack_d[],
+ chem_b_zero[], chem_n_zero[],
+ chem_r_max[], chem_r_min[],
+ chem_r_zero[], chem_mr_zero[], chem_pr_zero[], chem_crz_zero[],
+ chem_rt_zero[], chem_rtt_zero[], chem_rbt_zero[],
+ chem_mid_zero[] ;
+
+path
+ chem_b_path[], chem_bx_path[], chem_eb_path[], chem_sr_path[], chem_br_path[],
+ chem_sb_path[], chem_msb_path[], chem_psb_path[],
+ chem_s_path[], chem_ss_path[], chem_mss_path[], chem_pss_path[],
+ chem_e_path[], chem_sd_path[], chem_bb_path[], chem_oe_path[],
+ chem_bd_path[], chem_bw_path[],
+ chem_ddt_path[], chem_ddb_path[], chem_ldt_path[], chem_ldb_path[], chem_rdt_path[], chem_rdb_path[],
+ chem_dbl_path[], chem_dbr_path[],
+ chem_ad_path[], chem_au_path[],
+ chem_r_path[], chem_rl_path[], chem_rr_path[],
+ chem_rb_path[], chem_prb_path[], chem_mrb_path[],
+ chem_srl_path[], chem_srr_path[],
+ chem_msr_path[], chem_psr_path[],
+ chem_mr_path[], chem_pr_path[],
+ chem_c_path[], chem_cc_path[],
+ chem_midt_path[], chem_midb_path[], chem_midst_path[], chem_midsb_path[] ;
+
+chem_setting_scale := 1 ;
+chem_base_width := 40pt ;
+chem_text_offset := 3pt ;
+chem_center_offset := 6pt ;
+chem_picture_offset := 10pt ;
+chem_substituent_offset := 10pt ;
+chem_radical_min := 1.25 ;
+chem_radical_max := 1.50 ;
+chem_text_min := 0.75 ;
+chem_text_max := 1.75 ;
+chem_circle_radius := 0.80 ;
+chem_circle_radius := 1.10 ;
+chem_rotation := 1 ;
+chem_adjacent := 0 ;
+chem_substituent := 0 ;
+chem_direction := 0 ;
+chem_stack_n := 0 ;
+chem_doing_pb := false ;
+chem_shift := origin ;
+chem_dot_factor := 4 ;
+chem_text_trace := false ;
+chem_bd_n := 4 ;
+chem_bw_n := 4 ;
+chem_bd_angle := 4 ;
+chem_bb_angle := 4 ;
+
+vardef chem_start_structure(expr n, l, r, t, b, scale, axis, fixedwidth, fixedheight, offset) =
+ chem_setting_axis := axis ;
+ chem_setting_l := l * scale ;
+ chem_setting_r := r * scale ;
+ chem_setting_t := t * scale ;
+ chem_setting_b := b * scale ;
+ chem_setting_fixedwidth := fixedwidth ;
+ chem_setting_fixedheight := fixedheight ;
+ chem_setting_offset := offset ;
+ if scale <> chem_setting_scale :
+ chem_setting_scale := scale ;
+ chem_init_all ;
+ fi ;
+ chem_rotation := 1 ;
+ chem_adjacent := 0 ;
+ chem_substituent := 0 ;
+ chem_direction := 0 ;
+ chem_stack_n := 0 ;
+ chem_doing_pb := false ;
+ chem_shift := origin ;
+enddef ;
+
+def chem_stop_structure =
+ currentpicture := currentpicture shifted - chem_shift ;
+ % axis here
+ if chem_setting_fixedwidth :
+ chem_setting_l := - xpart llcorner currentpicture ;
+ chem_setting_r := xpart urcorner currentpicture ;
+ fi ;
+ if chem_setting_fixedheight :
+ chem_setting_t := ypart urcorner currentpicture ;
+ chem_setting_b := - ypart llcorner currentpicture ;
+ fi ;
+ chem_setting_bbox :=
+ (-chem_setting_l,-chem_setting_b) -- ( chem_setting_r,-chem_setting_b) --
+ ( chem_setting_r, chem_setting_t) -- (-chem_setting_l, chem_setting_t) -- cycle ;
+ % maybe put it behind the picture
+ if chem_setting_axis :
+ save stp ; stp := chem_base_width/ 2 * chem_setting_scale ;
+ save siz ; siz := chem_base_width/10 * chem_setting_scale ;
+ draw (-chem_setting_l,0) -- (chem_setting_r,0) withcolor blue ;
+ draw (0,-chem_setting_b) -- (0,chem_setting_t) withcolor blue ;
+ for i = 0 step stp until chem_setting_r : draw (i,-siz) -- (i,siz) withcolor blue ; endfor ;
+ for i = 0 step -stp until -chem_setting_l : draw (i,-siz) -- (i,siz) withcolor blue ; endfor ;
+ for i = 0 step stp until chem_setting_t : draw (-siz,i) -- (siz,i) withcolor blue ; endfor ;
+ for i = 0 step -stp until -chem_setting_b : draw (-siz,i) -- (siz,i) withcolor blue ; endfor ;
+ draw chem_setting_bbox withcolor blue ;
+ fi ;
+ setbounds currentpicture to chem_setting_bbox ;
+enddef ;
+
+def chem_start_component =
+enddef ;
+def chem_stop_component =
+enddef ;
+
+def chem_pb =
+% draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor blue ;
+% draw origin withpen pencircle scaled 2mm withcolor blue ;
+ chem_doing_pb := true ;
+enddef ;
+def chem_pe =
+% draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ;
+% draw origin withpen pencircle scaled 1mm withcolor red ;
+ currentpicture := currentpicture shifted - chem_shift ;
+% draw origin withpen pencircle scaled .5mm withcolor green ;
+ chem_shift := origin ;
+ chem_doing_pb := false ;
+enddef ;
+
+vardef chem_do (expr p) =
+ if chem_doing_pb :
+ chem_doing_pb := false ;
+% save pp ; pair pp ; pp := point 1 of ((origin -- p) enlonged chem_picture_offset) ;
+% currentpicture := currentpicture shifted - pp ;
+% chem_shift := chem_shift - center pp ;
+ currentpicture := currentpicture shifted - p ;
+ chem_shift := chem_shift - p ;
+ origin % nullpicture
+ else :
+ p
+ fi
+enddef ;
+
+vardef chem_b (expr n, f, t, r, c) =
+ chem_draw (n, chem_b_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_sb (expr n, f, t, r, c) =
+ chem_draw (n, chem_sb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_s (expr n, f, t, r, c) =
+ chem_draw (n, chem_s_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_ss (expr n, f, t, r, c) =
+ chem_draw (n, chem_ss_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_mid (expr n, r, c) =
+ chem_draw_fixed (n, chem_midt_path[n], r, c) ;
+ chem_draw_fixed (n, chem_midb_path[n], r, c) ;
+enddef ;
+vardef chem_mids (expr n, r, c) =
+ chem_draw_fixed (n, chem_midst_path[n], r, c) ;
+ chem_draw_fixed (n, chem_midsb_path[n], r, c) ;
+enddef ;
+vardef chem_mss (expr n, f, t, r, c) =
+ chem_draw (n, chem_mss_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_pss (expr n, f, t, r, c) =
+ chem_draw (n, chem_pss_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_msb (expr n, f, t, r, c) =
+ chem_draw (n, chem_msb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_psb (expr n, f, t, r, c) =
+ chem_draw (n, chem_psb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_eb (expr n, f, t, r, c) =
+ chem_draw (n, chem_eb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_db (expr n, f, t, r, c) =
+ if n = 1 :
+ chem_draw (n, chem_msb_path [n], f, t, r, c) ;
+ chem_draw (n, chem_psb_path [n], f, t, r, c) ;
+ else :
+ chem_draw (n, chem_dbl_path [n], f, t, r, c) ;
+ chem_draw (n, chem_dbr_path [n], f, t, r, c) ;
+ fi ;
+enddef ;
+vardef chem_er (expr n, f, t, r, c) =
+ chem_draw (n, chem_rl_path[n], f, t, r, c) ;
+ chem_draw (n, chem_rr_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_dr (expr n, f, t, r, c) =
+ chem_draw (n, chem_srl_path[n], f, t, r, c) ;
+ chem_draw (n, chem_srr_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_ad (expr n, f, t, r, c) =
+ chem_draw_arrow(n, chem_ad_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_au (expr n, f, t, r, c) =
+ chem_draw_arrow(n, chem_au_path[n], f, t, r, c)
+enddef ;
+vardef chem_r (expr n, f, t, r, c) =
+ if n < 0 :
+ chem_draw_vertical (n, chem_r_path[n], f, t, r, c) ;
+ else :
+ chem_draw (n, chem_r_path[n], f, t, r, c) ;
+ fi ;
+enddef ;
+vardef chem_rd (expr n, f, t, r, c) =
+ chem_dashed_normal (n, chem_r_path[n], f, t, r, c)
+enddef ;
+vardef chem_mrd (expr n, f, t, r, c) =
+ chem_dashed_normal (n, chem_mr_path[n], f, t, r, c)
+enddef ;
+vardef chem_prd (expr n, f, t, r, c) =
+ chem_dashed_normal (n, chem_pr_path[n], f, t, r, c)
+enddef ;
+vardef chem_br (expr n, f, t, r, c) =
+ chem_fill (n, chem_br_path[n], f, t, r, c )
+enddef ;
+vardef chem_rb (expr n, f, t, r, c) =
+ chem_fill (n, chem_rb_path[n], f, t, r, c)
+enddef ;
+vardef chem_mrb (expr n, f, t, r, c) =
+ chem_fill (n, chem_mrb_path[n], f, t, r, c)
+enddef ;
+vardef chem_prb (expr n, f, t, r, c) =
+ chem_fill (n, chem_prb_path[n], f, t, r, c)
+enddef ;
+vardef chem_mr (expr n, f, t, r, c) =
+ if n < 0 :
+ chem_draw_vertical(n, chem_mr_path[n], f, t, r, c)
+ else :
+ chem_draw (n, chem_mr_path[n], f, t, r, c)
+ fi
+enddef ;
+vardef chem_pr (expr n, f, t, r, c) =
+ if n < 0 :
+ chem_draw_vertical(n, chem_pr_path[n], f, t, r, c)
+ else :
+ chem_draw (n, chem_pr_path[n], f, t, r, c)
+ fi
+enddef ;
+vardef chem_sr (expr n, f, t, r, c) =
+ chem_draw (n, chem_sr_path[n], f, t, r, c)
+enddef ;
+vardef chem_msr (expr n, f, t, r, c) =
+ chem_draw (n, chem_msr_path[n], f, t, r, c)
+enddef ;
+vardef chem_psr (expr n, f, t, r, c) =
+ chem_draw (n, chem_psr_path[n], f, t, r, c)
+enddef ;
+vardef chem_c (expr n, f, t, r, c) =
+ chem_draw (n, chem_c_path[n], f, t, r, c)
+enddef ;
+vardef chem_cc (expr n, f, t, r, c) =
+ chem_draw (n, chem_cc_path[n], f, f, r, c)
+enddef ;
+vardef chem_cd (expr n, f, t, r, c) =
+ chem_dashed_connected (n, chem_c_path[n], f, t, r, c)
+enddef ;
+vardef chem_ccd (expr n, f, t, r, c) =
+ chem_dashed_normal (n, chem_cc_path[n], f, f, r, c)
+enddef ;
+vardef chem_rn (expr n, i, t) =
+ chem_rt (n,i,t) ;
+enddef ;
+vardef chem_rtn (expr n, i, t) =
+ chem_rtt(n,i,t) ;
+enddef ;
+vardef chem_rbn (expr n, i, t) =
+ chem_rbt(n,i,t) ;
+enddef ;
+vardef chem_tb (expr n, f, t, r, c) = % one
+ chem_draw (n, chem_msb_path[n], f, t, r, c) ;
+ chem_draw (n, chem_sb_path [n], f, t, r, c) ;
+ chem_draw (n, chem_psb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_ep (expr n, f, t, r, c) = % one
+ chem_draw (n, chem_e_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_es (expr n, f, t, r, c) = % one
+ chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_ed (expr n, f, t, r, c) = % one
+ chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ;
+ chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_et (expr n, f, t, r, c) = % one
+ chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ;
+ chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ;
+ chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_sd (expr n, f, t, r, c) = % one
+ chem_draw (n, chem_ddt_path[n], f, t, r, c) ;
+ chem_draw (n, chem_ddb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_rdd (expr n, f, t, r, c) = % one
+ chem_draw (n, chem_ldt_path[n], f, t, r, c) ;
+ chem_draw (n, chem_ldb_path[n], f, t, r, c) ;
+ chem_draw (n, chem_psb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_ldd (expr n, f, t, r, c) = % one
+ chem_draw (n, chem_msb_path[n], f, t, r, c) ;
+ chem_draw (n, chem_rdt_path[n], f, t, r, c) ;
+ chem_draw (n, chem_rdb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_hb (expr n, f, t, r, c) = % one
+ chem_draw_dot (n, point 0 of chem_sb_path[n], f, t, r, c) ;
+ chem_draw_dot (n, center chem_sb_path[n], f, t, r, c) ;
+ chem_draw_dot (n, point 1 of chem_sb_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_bb (expr n, f, t, r, c) = % one
+ if n < 0 :
+ chem_fill (n, chem_bb_path[n], 1, 1, r, c) ;
+ chem_b (n, f, t, r, c) ;
+ else :
+ chem_fill (n, chem_bb_path[n], f, t, r, c) ;
+ fi ;
+enddef ;
+vardef chem_oe (expr n, f, t, r, c) = % one
+ chem_draw (n, chem_oe_path[n], f, t, r, c) ;
+enddef ;
+vardef chem_bd (expr n, f, t, r, c) = % one
+ for i=0 upto 5 :
+ chem_draw (n, subpath (2i,2i+1) of chem_bd_path[n], f, t, r, c) ;
+ endfor ;
+enddef ;
+vardef chem_bw (expr n, f, t, r, c) = % one
+ chem_draw (n, chem_bw_path[n], f, t, r, c) ;
+enddef ;
+
+vardef chem_z_zero@#(text t) =
+ chem_text@#(t, chem_do(origin)) ;
+enddef ;
+vardef chem_cz_zero@#(text t) =
+ chem_text@#(t, chem_do(origin)) ;
+enddef ;
+vardef chem_z@#(expr n, p) (text t) =
+ if p = 0 :
+ chem_text@#(t, chem_do(origin)) ;
+ else :
+ chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ;
+ fi ;
+enddef ;
+vardef chem_cz@#(expr n, p) (text t) =
+ if n = 1 :
+ chem_c_text(t, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ;
+ else :
+ chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ;
+ fi ;
+enddef ;
+vardef chem_midz@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_mid_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_rz@#(expr n, p) (text t) =
+ if n < 0 :
+ % quite special
+ chem_text@#(t, chem_do(chem_r_zero[n] shifted (chem_b_zero[n] rotated chem_ang(n,p)))) ;
+ else :
+ chem_text@#(t, chem_do(chem_r_zero[n] rotated chem_ang(n,p))) ;
+ fi ;
+enddef ;
+vardef chem_crz@#(expr n, p) (text tx) =
+ chem_text(tx, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_mrz@#(expr n, p) (text t) =
+ if n < 0 :
+ % quite special
+ chem_text@#(t, chem_do(chem_mr_zero[n] shifted (chem_b_zero[n] rotated chem_ang(n,p)))) ;
+ else :
+ chem_text@#(t, chem_do(chem_mr_zero[n] rotated chem_ang(n,p))) ;
+ fi ;
+enddef ;
+vardef chem_prz@#(expr n, p) (text t) =
+ if n < 0 :
+ % quite special
+ chem_text@#(t, chem_do(chem_pr_zero[n] shifted (chem_b_zero[n] rotated chem_ang(n,p)))) ;
+ else :
+ chem_text@#(t, chem_do(chem_pr_zero[n] rotated chem_ang(n,p))) ;
+ fi ;
+enddef ;
+vardef chem_rt@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_rtt@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_rbt@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_zt@#(expr n, p) (text t) =
+ if n = 1 :
+ chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
+ else :
+ chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
+ fi ;
+enddef ;
+vardef chem_zn@#(expr n, p) (text t) =
+ if n = 1 :
+ chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
+ else :
+ chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
+ fi ;
+enddef ;
+vardef chem_zbt@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_zbn@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_ztt@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+vardef chem_ztn@#(expr n, p) (text t) =
+ chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
+enddef ;
+
+vardef chem_symbol(expr t) =
+ draw textext(t) ;
+enddef ;
+
+vardef chem_text@#(expr txt, z) = % adapted copy of thelabel@
+ save p ; picture p ;
+ p := textext(txt) ;
+ p := p
+ if (labtype@# >= 10) : shifted (0,ypart center p) fi
+ shifted (z + chem_text_offset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)) ;
+ if chem_text_trace :
+ draw z withpen pencircle scaled 2pt withcolor red ;
+ draw boundingbox p withpen pencircle scaled 1pt withcolor red ;
+ fi ;
+ draw p
+enddef ;
+
+vardef chem_c_text(expr txt, z) = % adapted copy of thelabel@
+ save p ; picture p ; p := textext(txt) ;
+ save b ; path b ; b := (boundingbox p) shifted z ;
+ save a ; pair a ; a := (origin--z) intersection_point b ;
+ if intersection_found :
+ draw p shifted (z enlonged arclength(a -- center b)) ;
+ else :
+ draw p shifted z ;
+ fi
+% draw b withcolor green ;
+% draw a withcolor red ;
+enddef ;
+
+vardef chem_ang (expr n, d) =
+ ((-1 * (d-1) * chem_angle[n]) + (-chem_rotation+1) * 90 + chem_start[n]) % no ;
+enddef ;
+vardef chem_rot (expr n, d) =
+ chem_rotation := d ;
+enddef ;
+vardef chem_adj (expr n, d) =
+ chem_adjacent := d ;
+enddef ;
+vardef chem_sub (expr n, d) =
+ chem_substituent := d ;
+enddef ;
+vardef chem_dir (expr n, d) =
+ if n = 1 :
+ chem_direction_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+1))) ;
+ currentpicture := currentpicture shifted chem_direction_p ;
+ chem_shift := chem_shift + chem_direction_p ;
+ fi ;
+enddef ;
+vardef chem_mov (expr n, d) =
+ if d = 0 :
+ currentpicture := currentpicture shifted - chem_shift ;
+ chem_shift := origin ;
+ else :
+ chem_move_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+chem_initialmov[n]))) ;
+ currentpicture := currentpicture shifted chem_move_p ;
+ chem_shift := chem_shift + chem_move_p ;
+ fi ;
+enddef ;
+vardef chem_off (expr n, d) =
+ if (d = 1) or (d = 2) or (d = 8) : % positive
+ currentpicture := currentpicture shifted (-chem_setting_offset,0) ;
+ chem_shift := chem_shift + (-chem_setting_offset,0)
+ elseif (d = 4) or (d = 5) or (d = 6) : % negative
+ currentpicture := currentpicture shifted ( chem_setting_offset,0) ;
+ chem_shift := chem_shift + ( chem_setting_offset,0)
+ fi ;
+enddef ;
+
+vardef chem_set(expr n, m) =
+ if chem_adjacent > 0 :
+ chem_adjacent_d := xpart chem_b_zero[n] + xpart chem_b_zero[m] ;
+ if chem_adjacent = 1 : chem_adjacent_p := (-chem_adjacent_d, 0) ;
+ elseif chem_adjacent = 2 : chem_adjacent_p := (0, -chem_adjacent_d) ;
+ elseif chem_adjacent = 3 : chem_adjacent_p := ( chem_adjacent_d, 0) ;
+ elseif chem_adjacent = 4 : chem_adjacent_p := (0, chem_adjacent_d) ;
+ else : chem_adjacent_p := origin ;
+ fi ;
+ currentpicture := currentpicture shifted chem_adjacent_p ;
+ chem_shift := chem_shift + chem_adjacent_p ;
+ chem_adjacent := 0 ;
+ fi ;
+ if chem_substituent > 0 :
+ if m = 1 :
+ chem_substituent_d := xpart chem_crz_zero[n] + chem_substituent_offset ;
+ else :
+ chem_substituent_d := xpart chem_crz_zero[n] + xpart chem_b_zero[m] ;
+ fi ;
+ if chem_substituent = 1 : chem_substituent_p := (-chem_substituent_d, 0) ; % - ?
+ elseif chem_substituent = 2 : chem_substituent_p := (0, chem_substituent_d) ;
+ elseif chem_substituent = 3 : chem_substituent_p := ( chem_substituent_d, 0) ;
+ elseif chem_substituent = 4 : chem_substituent_p := (0, -chem_substituent_d) ;
+ else : chem_substituent_p := origin ;
+ fi ;
+ currentpicture := currentpicture shifted chem_substituent_p ;
+ chem_shift := chem_shift + chem_substituent_p ;
+ chem_substituent := 0 ;
+ fi ;
+ chem_rotation := chem_initialrot[m] ;
+enddef ;
+
+vardef chem_draw (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
+ for i:=from_point upto to_point:
+ draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ;
+ endfor ;
+enddef ;
+vardef chem_fill (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
+ for i:=from_point upto to_point:
+ fill (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled 0 withcolor linecolor ;
+ endfor ;
+enddef ;
+
+vardef chem_dashed_normal (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
+ for i:=from_point upto to_point:
+ draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor dashed evenly ;
+ endfor ;
+enddef ;
+vardef chem_dashed_connected (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
+ draw for i:=from_point upto to_point:
+ (path_fragment rotated chem_ang(n,i)) if i < to_point : -- fi
+ endfor withpen pencircle scaled linewidth withcolor linecolor dashed evenly ;
+enddef ;
+vardef chem_draw_dot (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
+ for i:=from_point upto to_point:
+ draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled (chem_dot_factor*linewidth) withcolor linecolor ;
+ endfor ;
+enddef ;
+vardef chem_draw_fixed (expr n, path_fragment, linewidth, linecolor) =
+ draw (path_fragment rotated chem_ang(n,1)) withpen pencircle scaled linewidth withcolor linecolor ;
+enddef ;
+vardef chem_draw_arrow (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
+ for i:=from_point upto to_point:
+ drawarrow (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ;
+ endfor ;
+enddef ;
+vardef chem_draw_vertical (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
+ % quite special
+ for i:=from_point upto to_point:
+ draw (path_fragment shifted (chem_b_zero[n] rotated chem_ang(n,i))) withpen pencircle scaled linewidth withcolor linecolor ;
+ endfor ;
+enddef ;
+
+picture chem_stack_p[] ;
+pair chem_stack_shift[] ;
+
+vardef chem_save =
+ chem_stack_n := chem_stack_n + 1 ;
+ chem_stack_p[chem_stack_n] := currentpicture ;
+ chem_stack_shift[chem_stack_n] := chem_shift ;
+ chem_shift := origin ;
+% chem_adjacent := 0 ;
+% chem_substituent := 0 ;
+% chem_rotation := 1 ;
+ currentpicture := nullpicture ;
+enddef ;
+vardef chem_restore =
+ if chem_stack_n > 0 :
+ currentpicture := currentpicture shifted - chem_shift ;
+ addto chem_stack_p[chem_stack_n] also currentpicture ;
+ currentpicture := chem_stack_p[chem_stack_n] ;
+ chem_stack_p[chem_stack_n] := nullpicture ;
+ chem_shift := chem_stack_shift[chem_stack_n] ;
+ chem_stack_n := chem_stack_n - 1 ;
+ fi ;
+enddef ;
+
+def chem_init_some(expr n, ratio, start, initialrot, initialmov) =
+ chem_width [n] := ratio * chem_base_width * chem_setting_scale ;
+ chem_angle [n] := 360/abs(n) ;
+ chem_start [n] := start ;
+ chem_initialrot[n] := initialrot ;
+ chem_initialmov[n] := initialmov ;
+ chem_b_zero [n] := (chem_width[n],0) rotated (chem_angle[n]/2) ;
+ chem_n_zero [n] := (chem_text_min*chem_width[n],0) rotated (chem_angle[n]/2) ;
+ chem_r_max [n] := chem_radical_max*chem_b_zero[n] ;
+ chem_r_path [n] := chem_b_zero[n] -- chem_r_max[n] ;
+ chem_mr_path [n] := chem_r_path [n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
+ chem_pr_path [n] := chem_r_path [n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
+ chem_r_zero [n] := point 1 of chem_r_path [n] ;
+ chem_mr_zero [n] := point 1 of chem_mr_path[n] ;
+ chem_pr_zero [n] := point 1 of chem_pr_path[n] ;
+ chem_crz_zero [n] := point 1 of (chem_r_path[n] enlonged chem_center_offset) ;
+ chem_au_path [n] := subpath (0.2,0.8) of (chem_r_max[n] -- (chem_r_max[n] rotated chem_angle[n])) ;
+ chem_ad_path [n] := reverse(chem_au_path[n]) ;
+ chem_rt_zero [n] := (((chem_radical_max+chem_radical_min)/2)*chem_width[n],0) rotated (chem_angle[n]/2) ;
+ chem_rtt_zero [n] := chem_rt_zero[n] rotated + 10 ;
+ chem_rbt_zero [n] := chem_rt_zero[n] rotated - 10 ;
+ chem_b_path [n] := reverse(chem_b_zero[n] -- (chem_b_zero[n] rotated -chem_angle[n])) ;
+ chem_bx_path [n] := reverse(chem_b_zero[n] -- (chem_b_zero[n] rotated -chem_angle[n])) ; % ?
+ chem_sb_path [n] := subpath (0.25,0.75) of chem_b_path[n] ;
+ chem_s_path [n] := point 0 of chem_b_path[n] -- point 0 of (chem_b_path[n] rotated (2chem_angle[n])) ;
+ chem_ss_path [n] := subpath (0.25,0.75) of (chem_s_path[n]) ;
+ chem_pss_path [n] := subpath (0.00,0.75) of (chem_s_path[n]) ;
+ chem_mss_path [n] := subpath (0.25,1.00) of (chem_s_path[n]) ;
+ chem_mid_zero [n] := origin shifted (-.25chem_width[n],0) ;
+ chem_midst_path[n] := chem_mid_zero[n] -- (chem_width[n],0) rotated ( chem_angle[n] + chem_angle[n]/2) ;
+ chem_midsb_path[n] := chem_mid_zero[n] -- (chem_width[n],0) rotated (-chem_angle[n] - chem_angle[n]/2) ;
+ chem_midt_path [n] := subpath (0.25,1.00) of chem_midst_path [n] ;
+ chem_midb_path [n] := subpath (0.25,1.00) of chem_midsb_path [n] ;
+ chem_msb_path [n] := subpath (0.00,0.75) of chem_b_path[n] ;
+ chem_psb_path [n] := subpath (0.25,1.00) of chem_b_path[n] ;
+ chem_dbl_path [n] := chem_sb_path[n] shifted - (0.05[origin,center chem_sb_path[n]]) ; % parallel
+ chem_dbr_path [n] := chem_sb_path[n] shifted + (0.05[origin,center chem_sb_path[n]]) ;
+ chem_eb_path [n] := chem_sb_path[n] shifted - (0.25[origin,center chem_sb_path[n]]) ;
+ chem_sr_path [n] := chem_radical_min*chem_b_zero[n] -- chem_r_max[n] ;
+ chem_rl_path [n] := chem_r_path[n] paralleled (chem_base_width/20) ;
+ chem_rr_path [n] := chem_r_path[n] paralleled -(chem_base_width/20) ;
+ chem_srl_path [n] := chem_sr_path[n] paralleled (chem_base_width/20) ;
+ chem_srr_path [n] := chem_sr_path[n] paralleled -(chem_base_width/20) ;
+ chem_br_path [n] := point 1 of chem_sb_path[n] --
+ point 0 of chem_sb_path[n] rotatedaround(point 1 of chem_sb_path[n], -4) --
+ point 0 of chem_sb_path[n] rotatedaround(point 1 of chem_sb_path[n], 4) -- cycle ;
+ chem_rb_path [n] := chem_b_zero[n] -- chem_r_max[n] rotated -2 -- chem_r_max[n] -- chem_r_max[n] rotated 2 -- cycle ;
+ chem_mrb_path [n] := chem_rb_path[n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
+ chem_prb_path [n] := chem_rb_path[n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
+ chem_msr_path [n] := chem_sr_path[n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
+ chem_psr_path [n] := chem_sr_path[n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
+ % not yet ok:
+% chem_c_path [n] := subpath (30/45, -30/45) of (fullcircle scaled (1.25*chem_circle_radius*chem_width[n]));
+% chem_cc_path [n] := subpath (30/45,8-30/45) of (fullcircle rotated 90 scaled (1.25*chem_circle_radius*chem_width[n]));
+ chem_c_path [n] := subpath (30/45, -30/45) of (fullcircle scaled (chem_width[n]));
+ chem_cc_path [n] := subpath (30/45,8-30/45) of (fullcircle rotated 90 scaled (chem_width[n]));
+enddef ;
+
+def chem_init_three = chem_init_some(3,30/52 ,-60,1,2) ; enddef ; % 60
+def chem_init_four = chem_init_some(4,30/42.5, 0,1,0) ; enddef ; % 45
+def chem_init_five = chem_init_some(5,30/35 , 0,1,0) ; enddef ; % 36
+def chem_init_six = chem_init_some(6, 1 , 0,1,0) ; enddef ; % 30
+def chem_init_eight = chem_init_some(8,30/22.5, 0,1,0) ; enddef ; % 22.5
+
+% bb R -R R Z -RZ +RZ
+
+def chem_init_some_front(expr n, ratio, start, initialrot, initialmov) =
+ chem_init_some(n, ratio, start, initialrot, initialmov) ;
+ chem_bb_path [n] := chem_b_path[n] rotated -chem_angle[n] -- chem_b_path[n] -- chem_b_path[n] rotated chem_angle[n] --
+ (reverse(chem_b_path[n] shortened (chem_base_width/20))) paralleled (chem_base_width/20) --
+ cycle ;
+ chem_r_max [n] := chem_radical_max*chem_b_zero[n] ;
+ chem_mr_path [n] := origin -- origin shifted (0,-.25chem_base_width) ;
+ chem_pr_path [n] := origin -- origin shifted (0, .25*chem_base_width) ;
+ chem_r_path [n] := point 1 of chem_mr_path[n] -- point 1 of chem_pr_path[n] ;
+ chem_mr_zero [n] := point 1 of chem_mr_path[n] ;
+ chem_pr_zero [n] := point 1 of chem_pr_path[n] ;
+enddef ;
+
+def chem_init_five_front = chem_init_some_front(-5,30/35,0,2,0) ; enddef ; % 36
+def chem_init_six_front = chem_init_some_front(-6, 1 ,0,2,0) ; enddef ; % 30
+
+vardef chem_init_one =
+ chem_width [1] := .75 * chem_base_width * chem_setting_scale ;
+ chem_angle [1] := 360/8 ;
+ chem_start [1] := 0 ;
+ chem_initialrot[1] := 1 ;
+ chem_initialmov[1] := 1 ;
+ chem_b_zero [1] := (1.75*chem_width[1],0) ;
+ chem_r_min [1] := chem_radical_min*chem_b_zero[1] ;
+ chem_r_max [1] := chem_radical_max*chem_b_zero[1] ;
+ chem_r_path [1] := (.5*chem_width[1],0) -- (1.25*chem_width[1],0) ;
+ chem_r_zero [1] := point 1 of chem_r_path [1] ;
+ chem_b_path [1] := chem_r_path[1] rotated + (chem_angle[1]) ; % used for move here
+ chem_b_zero [1] := chem_r_zero[1] ;
+ chem_crz_zero [1] := chem_r_zero[1] enlonged chem_center_offset ;
+ chem_e_path [1] := (.5*chem_width[1],-.25*chem_width[1]) -- (.5*chem_width[1],.25*chem_width[1]) ;
+ chem_sb_path [1] := chem_r_path [1] ;
+ chem_msb_path [1] := chem_r_path [1] shifted (0,-.1chem_width[1]) ;
+ chem_psb_path [1] := chem_r_path [1] shifted (0, .1chem_width[1]) ;
+ chem_ddt_path [1] := subpath(0,.4) of chem_r_path [1] ;
+ chem_ddb_path [1] := subpath(.6,1) of chem_r_path [1] ;
+ chem_ldt_path [1] := chem_ddt_path [1] shifted (0,-.1chem_width[1]) ; % parallel
+ chem_ldb_path [1] := chem_ddb_path [1] shifted (0,-.1chem_width[1]) ;
+ chem_rdt_path [1] := chem_ddt_path [1] shifted (0, .1chem_width[1]) ;
+ chem_rdb_path [1] := chem_ddb_path [1] shifted (0, .1chem_width[1]) ;
+ save pr ; pair pr[] ;
+ pr0 := point 0 of chem_r_path[1] ;
+ pr1 := point 1 of chem_r_path[1] ;
+ chem_bb_path [1] := pr0 -- (pr1 rotatedaround(pr0,-chem_bb_angle)) -- (pr1 rotatedaround(pr0,chem_bb_angle)) -- cycle ;
+ chem_oe_path [1] := ((-20,0)--(10,0){up}..(20,10)..(30,0)..(40,-10)..(50.0,0)..(60,10)..(70,0)..(80,-10)..{up}(90,0)--(120,0))
+ xsized (.75*chem_width[1]) shifted pr0 ;
+ chem_rt_zero [1] := point .5 of chem_r_path[1] ;
+ chem_rtt_zero [1] := chem_rt_zero[1] rotated + (chem_angle[1]/2) ;
+ chem_rbt_zero [1] := chem_rt_zero[1] rotated - (chem_angle[1]/2) ;
+ % added by Alan Braslau (adapted to use shared variables):
+ save p ; pair p[] ;
+ p0 := pr1 rotatedaround(pr0, -chem_bd_angle) ;
+ p1 := pr1 rotatedaround(pr0, +chem_bd_angle) ;
+ p2 := p0 shifted - pr1 ;
+ p3 := p1 shifted - pr1 ;
+ chem_bd_path [1] :=
+ p0 -- p1 for i=chem_bd_n downto 0 :
+ -- p2 shifted (i/chem_bd_n)[pr1,pr0]
+ -- p3 shifted (i/chem_bd_n)[pr1,pr0]
+ endfor ;
+ chem_bw_path [1] :=
+ for i=0 upto chem_bw_n - 1 :
+ ((i) /chem_bw_n)[pr0,pr1] .. ((i+.25)/chem_bw_n)[pr0,pr1] shifted p2 ..
+ ((i+.50)/chem_bw_n)[pr0,pr1] .. ((i+.75)/chem_bw_n)[pr0,pr1] shifted -p2 ..
+ endfor pr1 ;
+enddef ;
+
+def chem_init_all =
+ chem_init_one ;
+ chem_init_three ;
+ chem_init_four ;
+ chem_init_five ;
+ chem_init_six ;
+ chem_init_eight ;
+ chem_init_five_front ;
+ chem_init_six_front ;
+enddef ;
+
+chem_init_all ;
diff --git a/metapost/context/base/mp-core.mp b/metapost/context/base/mp-core.mp
new file mode 100644
index 000000000..7c5d5a1c1
--- /dev/null
+++ b/metapost/context/base/mp-core.mp
@@ -0,0 +1,1418 @@
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_core : endinput ; fi ;
+
+boolean context_core ; context_core := true ;
+
+pair lxy[], rxy[], cxy[], llxy[], lrxy[], ulxy[], urxy[] ;
+path pxy[] ;
+numeric hxy[], wxy[], dxy[], nxy[] ;
+
+def box_found (expr n,x,y,w,h,d) =
+ not ((x=0) and (y=0) and (w=0) and (h=0) and (d=0))
+enddef ;
+
+def initialize_box_pos (expr pos,n,x,y,w,h,d) =
+ pair lxy, rxy, cxy, llxy, lrxy, ulxy, urxy ;
+ path pxy ; numeric hxy, wxy, dxy, nxy;
+ lxy := (x,y) ;
+ llxy := (x,y-d) ;
+ lrxy := (x+w,y-d) ;
+ urxy := (x+w,y+h) ;
+ ulxy := (x,y+h) ;
+ wxy := w ;
+ hxy := h ;
+ dxy := d ;
+ rxy := lxy shifted (wxy,0) ;
+ pxy := llxy--lrxy--urxy--ulxy--cycle ;
+ cxy := center pxy ;
+ nxy := n ;
+ freeze_box(pos) ;
+enddef ;
+
+def freeze_box (expr pos) =
+ lxy[pos] := lxy ;
+ llxy[pos] := llxy ;
+ lrxy[pos] := lrxy ;
+ urxy[pos] := urxy ;
+ ulxy[pos] := ulxy ;
+ wxy[pos] := wxy ;
+ hxy[pos] := hxy ;
+ dxy[pos] := dxy ;
+ rxy[pos] := rxy ;
+ pxy[pos] := pxy ;
+ cxy[pos] := cxy ;
+ nxy[pos] := nxy ;
+enddef ;
+
+def initialize_box (expr n,x,y,w,h,d) =
+
+ numeric bpos ; bpos := 0 ; initialize_box_pos(bpos,n,x,y,w,h,d) ;
+
+enddef ;
+
+def initialize_area (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td) =
+
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+
+ do_initialize_area (fpos, tpos) ;
+
+enddef ;
+
+def do_initialize_area (expr fpos, tpos) =
+ lxy := lxy[fpos] ;
+ llxy := (xpart llxy[fpos], ypart llxy[tpos]) ;
+ lrxy := lrxy[tpos] ;
+ urxy := (xpart urxy[tpos], ypart urxy[fpos]) ;
+ ulxy := ulxy[fpos] ;
+ wxy := xpart lrxy - xpart llxy ;
+ hxy := hxy[fpos] ;
+ dxy := dxy[tpos] ;
+ rxy := lxy shifted (wxy,0) ;
+ pxy := llxy--lrxy--urxy--ulxy--cycle ;
+ cxy := center pxy ;
+enddef ;
+
+def set_par_line_height (expr ph, pd) =
+ par_strut_height :=
+ if ph>0 : ph elseif StrutHeight>0 : StrutHeight else : 8pt fi ;
+ par_strut_depth :=
+ if pd>0 : pd elseif StrutDepth >0 : StrutDepth else : 3pt fi ;
+ par_line_height :=
+ par_strut_height + par_strut_depth ;
+enddef ;
+
+def initialize_par (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td,
+ mn,mx,my,mw,mh,md,
+ pn,px,py,pw,ph,pd,
+ rw,rl,rr,rh,ra,ri) =
+
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+ numeric mpos ; mpos := 3 ; initialize_box_pos(mpos,mn,mx,my,mw,mh,md) ;
+ numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ;
+
+ numeric par_strut_height, par_strut_depth, par_line_height ;
+
+ set_par_line_height (ph, pd) ;
+
+ do_initialize_area (fpos, tpos) ;
+ do_initialize_par (fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) ;
+
+enddef ;
+
+def initialize_area_par (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td,
+ wn,wx,wy,ww,wh,wd) =
+
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+ numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ;
+
+ numeric par_strut_height, par_strut_depth, par_line_height ;
+
+ set_par_line_height (wh, wd) ;
+
+ numeric ffpos ; ffpos := 4 ; initialize_box_pos(ffpos,wn,wx,fy,0,wh,wd) ;
+ numeric ttpos ; ttpos := 5 ; initialize_box_pos(ttpos,wn,wx+ww,ty,0,wh,wd) ;
+
+ do_initialize_area (ffpos, ttpos) ;
+
+ numeric mpos ; mpos := 6 ; freeze_box(mpos) ;
+
+ do_initialize_par (fpos, tpos, mpos, ffpos, 0,0,0,0,0,0) ;
+
+enddef ;
+
+def do_initialize_par (expr fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) =
+
+ pair lref, rref, pref, lhref, rhref ;
+
+ % clip the page area to the left and right skips
+
+ llxy[mpos] := llxy[mpos] shifted (+rl,0) ;
+ lrxy[mpos] := lrxy[mpos] shifted (-rr,0) ;
+ urxy[mpos] := urxy[mpos] shifted (-rr,0) ;
+ ulxy[mpos] := ulxy[mpos] shifted (+rl,0) ;
+
+ % fixate the leftskip, rightskip and hanging indentation
+
+ lref := (xpart llxy[mpos],ypart ulxy[ppos]) ; lhref := lref shifted (rh,0) ;
+ rref := (xpart lrxy[mpos],ypart urxy[ppos]) ; rhref := rref shifted (rh,0) ;
+
+ pref := lxy[ppos] ;
+
+ if nxy[tpos] > nxy[fpos] :
+ if nxy[fpos] = nxy[mpos] :
+ % first of multiple pages
+ llxy[tpos] := llxy[mpos] ;
+ lrxy[tpos] := lrxy[mpos] ;
+ urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ;
+ ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ;
+ boxgriddirection := down ;
+ elseif nxy[tpos] = nxy[mpos] :
+ % last of multiple pages
+ llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ;
+ lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ;
+ urxy[fpos] := urxy[mpos] ;
+ ulxy[fpos] := ulxy[mpos] ;
+ boxgriddirection := up ;
+ else :
+ % middle of multiple pages
+ llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ;
+ lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ;
+ urxy[fpos] := urxy[mpos] ;
+ ulxy[fpos] := ulxy[mpos] ;
+ llxy[tpos] := llxy[mpos] ;
+ lrxy[tpos] := lrxy[mpos] ;
+ urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ;
+ ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ;
+ boxgriddirection := up ;
+ fi ;
+ else :
+ % just one page
+ boxgriddirection := up ;
+ fi ;
+
+ path txy, bxy, pxy, mxy ;
+
+ txy := originpath ; % top
+ bxy := originpath ; % bottom
+ pxy := originpath ; % composed
+
+ boolean lefthang, righthang, somehang ;
+
+ % we only hang on the first of a multiple page background
+
+ if nxy[mpos] > nxy[fpos] :
+ lefthang := righthang := somehang := false ;
+ else :
+ lefthang := (rh>0) ; righthang := (rh<0) ; somehang := false ;
+ fi ;
+
+ if lefthang :
+ mxy := boundingbox (lref -- lref shifted (rh,ra*par_line_height)) ;
+ elseif righthang :
+ mxy := boundingbox (rref -- rref shifted (rh,ra*par_line_height)) ;
+ else :
+ mxy := originpath ;
+ fi ;
+
+ if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) :
+
+ % We have a one-liner. Watch how er use the bottom pos for
+ % determining the height.
+
+ llxy[fpos] := (xpart llxy[fpos], ypart llxy[tpos]) ;
+ ulxy[fpos] := (xpart ulxy[fpos], ypart ulxy[tpos]) ;
+
+ else :
+
+ % We have a multi-liner. For convenience we now correct the
+ % begin and end points for indentation.
+
+ if lefthang and (round(ypart llxy[tpos]) >= round(ypart lrcorner mxy)) :
+ llxy[tpos] := (xpart lhref, ypart llxy[tpos]) ;
+ ulxy[tpos] := (xpart lhref, ypart ulxy[tpos]) ;
+ else :
+ llxy[tpos] := (xpart lref, ypart llxy[tpos]) ;
+ ulxy[tpos] := (xpart lref, ypart ulxy[tpos]) ;
+ fi ;
+
+ if righthang and (round(ypart lrxy[fpos]) >= round(ypart llcorner mxy)) :
+ lrxy[fpos] := (xpart rhref, ypart lrxy[fpos]) ;
+ urxy[fpos] := (xpart rhref, ypart urxy[fpos]) ;
+ else :
+ lrxy[fpos] := (xpart rref, ypart lrxy[fpos]) ;
+ urxy[fpos] := (xpart rref, ypart urxy[fpos]) ;
+ fi ;
+
+ fi ;
+
+ somehang := (ypart ulxy[fpos]>ypart llcorner mxy) and
+ (ypart llxy[tpos]<ypart llcorner mxy) ;
+
+ if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) :
+
+ % A (short) one-liner goes into the top box.
+
+ txy := llxy[fpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[fpos] -- cycle ;
+
+ elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) and
+ (round(xpart lrxy[tpos]) < round(xpart llxy[fpos])) :
+
+ % We have a sentence that spans two lines but with only end
+ % of line and begin of line segments. We need to take care of
+ % indentation.
+
+ txy := llxy[fpos] -- lrxy[fpos] -- urxy[fpos] -- ulxy[fpos] -- cycle ;
+ bxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[tpos] -- cycle ;
+
+ elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) :
+
+ % We have a sentence that spans two lines but with overlap.
+
+ pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- lrxy[fpos] --
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- ulxy[tpos] -- cycle ;
+
+ elseif lefthang and somehang :
+
+ % We have a sentence that spans more than two lines with
+ % left hanging indentation.
+
+ pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+ (xpart urxy[fpos],ypart urxy[tpos]) --
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+ if round(ypart urxy[tpos]) < round(ypart llcorner mxy) :
+ (xpart lrcorner mxy,ypart llxy[fpos]) --
+ lrcorner mxy --
+ (xpart llxy[tpos],ypart llcorner mxy) --
+ else :
+ (xpart llxy[tpos],ypart llxy[fpos]) --
+ fi
+ cycle ;
+
+ elseif righthang and somehang :
+
+ % We have a sentence that spans more than two lines with
+ % right hanging indentation.
+
+ pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+ if round(ypart urxy[tpos]) < round(ypart llcorner mxy) :
+ (xpart lrcorner mxy,ypart urxy[tpos]) --
+ lrcorner mxy -- llcorner mxy --
+ else :
+ (xpart urxy[fpos],ypart urxy[tpos]) --
+ fi
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+ (xpart llxy[tpos],ypart llxy[fpos]) --
+ cycle ;
+
+ else :
+
+ % We have a sentence that spans more than two lines with
+ % no hanging indentation.
+
+ pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+ (xpart urxy[fpos],ypart urxy[tpos]) --
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+ (xpart llxy[tpos],ypart llxy[fpos]) -- cycle ;
+
+ fi ;
+
+ pxy := simplified pxy ;
+ pxy := unspiked pxy ;
+
+enddef ;
+
+TopSkip := 0 ; % will move
+StrutHeight := 0 ; % will move
+
+pair last_multi_par_shift ; last_multi_par_shift := origin ;
+
+def relocate_multipars (expr xy) =
+ last_multi_par_shift := xy ;
+ for i=1 upto nofmultipars :
+ multipars[i] := multipars[i] shifted last_multi_par_shift ;
+ endfor ;
+enddef ;
+
+boolean compensate_multi_par_topskip ;
+boolean span_multi_column_pars ;
+boolean auto_multi_par_hsize ;
+boolean enable_multi_par_fallback ;
+
+compensate_multi_par_topskip := true ;
+span_multi_column_pars := false ;
+auto_multi_par_hsize := false ; % true ;
+enable_multi_par_fallback := true ;
+
+vardef multi_par_at_top (expr i) =
+ (round (ypart ulcorner multipars[i]) = round (ypart ulcorner
+ (TextAreas[multirefs[i]] shifted last_multi_par_shift)))
+enddef ;
+
+numeric nofmultipars ; nofmultipars := 0 ;
+
+boolean obey_multi_par_hang ; obey_multi_par_hang := true ;
+boolean obey_multi_par_more ; obey_multi_par_more := true ;
+boolean snap_multi_par_tops ; snap_multi_par_tops := true ;
+boolean local_multi_par_area ; local_multi_par_area := false ;
+boolean ignore_multi_par_page ; ignore_multi_par_page := false ;
+boolean force_multi_par_chain ; force_multi_par_chain := true ;
+boolean one_piece_multi_par ; one_piece_multi_par := false ;
+boolean check_multi_par_chain ; check_multi_par_chain := true ; % extra page check
+
+boolean multi_column_first_page_hack; multi_column_first_page_hack := true ; % seems to work ok
+
+def simplify_multi_pars = % boundingbox ipv shape als optie
+ for i := 1 upto nofmultipars :
+ multipars[i] := boundingbox multipars[i] ;
+ endfor ;
+enddef ;
+
+def save_multipar (expr i, l, p) =
+ nofmultipars := nofmultipars + 1 ;
+ multirefs[nofmultipars] := i ;
+ multilocs[nofmultipars] := l ;
+ multipars[nofmultipars] := unspiked (simplified p) ;
+enddef ;
+
+def prepare_multi_pars (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td,
+ wn,wx,wy,ww,wh,wd,
+ pn,px,py,pw,ph,pd,
+ rw,rl,rr,rh,ra,ri) =
+
+ if span_multi_column_pars :
+ begingroup ;
+ save TextAreas ; path TextAreas[] ;
+ save NOfTextAreas ; numeric NOfTextAreas ;
+ for i=1 upto NOfTextColumns :
+ TextAreas[i] := TextColumns[i] ;
+ endfor ;
+ NOfTextAreas := NOfTextColumns ;
+ fi ;
+
+ last_multi_par_shift := origin ;
+
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+ numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ;
+ numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ;
+
+ if local_multi_par_area :
+ RealPageNumber := fn ;
+ NOfTextAreas := 1 ;
+ NOfSavedTextAreas := 0 ;
+ TextAreas[1] := TextAreas[0] ;
+ TextColumns[1] := TextColumns[0] ;
+ nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ;
+ % draw TextColumns[1] withcolor green ;
+ % draw TextAreas[1] withcolor green ;
+ elseif ignore_multi_par_page :
+ RealPageNumber := fn ;
+ nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ;
+ fi ;
+
+ numeric par_strut_height, par_strut_depth, par_line_height ;
+
+ set_par_line_height (ph, pd) ;
+
+ numeric par_hang_indent, par_hang_after, par_indent, par_left_skip ;
+
+ par_hang_indent := rh ;
+ par_hang_after := ra ;
+ par_indent := ri ;
+ par_left_skip := rl ;
+
+ pair par_start_pos ;
+
+
+ par_start_pos := llxy[fpos]
+ if par_indent <0: shifted (-par_indent, 0) fi
+ if par_left_skip<0: shifted (-par_left_skip,0) fi ;
+
+ if wxy[wpos]>0 :
+ left_skip := rl + xpart llxy[wpos] - xpart llxy[ppos] ;
+ right_skip := rw - left_skip - ww ;
+ else :
+ left_skip := rl ;
+ right_skip := rr ;
+ fi ;
+
+ path multipar, multipars[] ;
+ numeric multiref, multirefs[] ;
+ numeric multiloc, multilocs[] ; % 1=begin 2=between 3=end
+
+ numeric multi_par_pages ; multi_par_pages := nxy[tpos]-nxy[fpos]+1 ;
+
+ vardef snapped_multi_pos (expr p) =
+ if snap_multi_par_tops :
+ if abs(ypart p - ypart ulcorner multipar) < par_line_height :
+ (xpart p,ypart ulcorner multipar)
+ else :
+ p
+ fi
+ else :
+ p
+ fi
+ enddef ;
+
+ % def set_multipar (expr i) =
+ % ((TextAreas[i] leftenlarged -left_skip) rightenlarged -right_skip)
+ % enddef ;
+
+ vardef set_multipar (expr i) =
+ ( (TextAreas[i] leftenlarged -left_skip) rightenlarged (-right_skip
+ if auto_multi_par_hsize : + rw - bbwidth(TextAreas[i]) fi) )
+ enddef ;
+
+ vardef top_multi_par(expr p) =
+ (round(estimated_par_lines(bbheight(p)*par_line_height))=round(bbheight(p)))
+ enddef ;
+
+ vardef multi_par_tsc(expr p) =
+ if top_multi_par(p) : TopSkipCorrection else : 0 fi
+ enddef ;
+
+ vardef estimated_par_lines (expr h) =
+ round(h/par_line_height)
+ enddef ;
+
+ vardef estimated_multi_par_height (expr n, t) =
+ if round(par_line_height)=0 :
+ 0
+ else :
+ save ok, h ; boolean ok ;
+ numeric h ; h := 0 ;
+ ok := false ;
+ if (nxy[fpos]=RealPageNumber-1) :
+ for i := 1 upto NOfSavedTextAreas :
+ if (InsideSavedTextArea(i,par_start_pos)) :
+ ok := true ;
+ h := h + estimated_par_lines(ypart ulxy[fpos] -
+ ypart llcorner SavedTextAreas[i]) ;
+ elseif ok :
+ h := h + estimated_par_lines(bbheight(SavedTextAreas[i])) ;
+ fi ;
+ endfor ;
+ fi ;
+ if ok :
+ for i := 1 upto n-1 :
+ h := h + estimated_par_lines(bbheight(TextAreas[i])) ;
+ endfor ;
+ else :
+ % already: ok := false ;
+ for i := 1 upto n-1 :
+ if (InsideTextArea(i,par_start_pos)) :
+ ok := true ;
+ h := h + estimated_par_lines(ypart ulxy[fpos] - ypart llcorner TextAreas[i]) ;
+ elseif ok :
+ h := h + estimated_par_lines(bbheight(TextAreas[i])) ;
+ fi ;
+ endfor ;
+ fi ;
+ h
+ fi
+ enddef ;
+
+ vardef left_top_hang (expr same_area) =
+
+ par_hang_after := ra + estimated_par_lines(py-fy) ;
+
+ if (par_hang_indent>0) and (par_hang_after<0) and obey_multi_par_hang :
+ pair _ul_ ; _ul_ := (xpart ulcorner multipar, ypart snapped_multi_pos(ulxy[fpos]));
+ pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llxy[tpos])) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := min(0,round(par_hang_after +
+ (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ (xpart _ul_ + par_hang_indent, ypart lrxy[fpos]) --
+ (xpart _ul_ + par_hang_indent, ypart _pa_) --
+ (xpart ulcorner multipar, ypart _pa_)
+ else :
+ (xpart ulcorner multipar, ypart lrxy[fpos])
+ fi
+ enddef ;
+
+ vardef right_top_hang (expr same_area) =
+
+ par_hang_after := ra + estimated_par_lines(py-fy) ;
+
+ if (par_hang_indent<0) and (par_hang_after<0) and obey_multi_par_hang :
+ pair _ur_ ; _ur_ := (xpart urcorner multipar, ypart snapped_multi_pos(urxy[fpos])) ;
+ pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart snapped_multi_pos(ulxy[tpos]))) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := min(0,round(par_hang_after +
+ (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ (xpart urcorner multipar, ypart _pa_) --
+ (xpart _ur_ + par_hang_indent, ypart _pa_) --
+ (xpart _ur_ + par_hang_indent, ypart snapped_multi_pos(urxy[fpos]))
+ else :
+ (xpart urcorner multipar, ypart snapped_multi_pos(urxy[fpos]))
+ fi
+ enddef ;
+
+ vardef x_left_top_hang (expr i, t) =
+ par_hang_after := min(0,ra + estimated_multi_par_height(i,t)) ;
+ if (par_hang_indent>0) and (par_hang_after<0) :
+ pair _ul_ ; _ul_ := ulcorner multipar ;
+ pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+ if t :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llxy[tpos]));
+ fi ;
+ if abs(ypart _pa_-ypart llxy[tpos])<par_line_height :
+ _pa_ := (xpart _pa_,ypart llxy[tpos]);
+ fi ;
+ if abs(ypart _pa_-ypart llcorner multipar)<par_line_height :
+ _pa_ := (xpart _pa_,ypart llcorner multipar);
+ fi ;
+ (xpart _ul_, ypart _pa_) --
+ (xpart _ul_ + par_hang_indent, ypart _pa_) --
+ (xpart _ul_ + par_hang_indent, ypart _ul_)
+ else :
+ ulcorner multipar
+ fi
+ enddef ;
+
+ vardef x_right_top_hang (expr i, t) =
+ par_hang_after := min(0,ra + estimated_multi_par_height(i,t)) ;
+ if (par_hang_indent<0) and (par_hang_after<0) :
+ pair _ur_ ; _ur_ := urcorner multipar ;
+ pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+ if t :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart snapped_multi_pos(urxy[tpos]))) ;
+ fi ;
+ (xpart _ur_ + par_hang_indent, ypart _ur_) --
+ (xpart _ur_ + par_hang_indent, ypart _pa_) --
+ (xpart _ur_, ypart _pa_)
+ else :
+ urcorner multipar
+ fi
+ enddef ;
+
+ vardef left_bottom_hang (expr same_area) =
+ pair _ll_, _sa_, _pa_ ;
+ _sa_ := if same_area : llxy[tpos] else : lrcorner multipar fi ;
+ if (par_hang_indent>0) and (par_hang_after>0) and obey_multi_par_hang :
+ _ll_ := (xpart ulcorner multipar, ypart snapped_multi_pos(ulxy[fpos])) ;
+ _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := max(0,round(par_hang_after -
+ (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ _pa_ --
+ (xpart _pa_ + par_hang_indent,ypart _pa_) --
+ (xpart _pa_ + par_hang_indent,ypart _sa_)
+ else :
+ (xpart llcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ vardef right_bottom_hang (expr same_area) =
+ pair _lr_, _sa_, _pa_ ;
+ _sa_ := if same_area : snapped_multi_pos(ulxy[tpos]) else : lrcorner multipar fi ;
+ if (par_hang_indent<0) and (par_hang_after>0) and obey_multi_par_hang :
+ _lr_ := (xpart urcorner multipar, ypart snapped_multi_pos(urxy[fpos])) ;
+ _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart snapped_multi_pos(ulxy[tpos]))) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := max(0,round(par_hang_after -
+ (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ (xpart _pa_ + par_hang_indent,ypart _sa_) --
+ (xpart _pa_ + par_hang_indent,ypart _pa_) --
+ _pa_
+ else :
+ (xpart lrcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ vardef x_left_bottom_hang (expr i, t) =
+ pair _ll_, _sa_, _pa_ ;
+ _sa_ := if t : llxy[tpos] else : llcorner multipar fi ;
+ if (par_hang_indent>0) and (ra>0) :
+ par_hang_after := max(0,ra - estimated_multi_par_height(i,t)) ;
+ _ll_ := ulcorner multipar ;
+ _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+ % we need to compensate for topskip enlarged areas
+ if abs(ypart _pa_ - ypart _sa_) > par_line_height :
+ (xpart _pa_ + par_hang_indent,ypart _sa_) --
+ (xpart _pa_ + par_hang_indent,ypart _pa_) --
+ fi
+ _pa_
+ else :
+ (xpart llcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ vardef x_right_bottom_hang (expr i, t) =
+ pair _lr_, _sa_, _pa_ ;
+ _sa_ := if t : snapped_multi_pos(ulxy[tpos]) else : llcorner multipar fi ;
+ if (par_hang_indent<0) and (ra>0) :
+ par_hang_after := max(0,ra - estimated_multi_par_height(i, t)) ;
+ _lr_ := urcorner multipar ;
+ _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+ % we need to compensate for topskip enlarged areas
+ _pa_
+ if abs(ypart _pa_ - ypart _sa_) > par_line_height :
+ -- (xpart _pa_ + par_hang_indent,ypart _pa_)
+ -- (xpart _pa_ + par_hang_indent,ypart _sa_)
+ fi
+ else :
+ (xpart lrcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ def test_multipar =
+ multipar := boundingbox multipar ;
+ enddef ;
+
+ % first loop
+
+ ii := 0 ; nn := NOfTextAreas+1 ; nofmultipars := 0 ;
+
+ if enable_multi_par_fallback and
+ (nxy[fpos]=RealPageNumber) and
+ (nxy[tpos]=RealPageNumber) and not
+ (InsideSomeTextArea(lxy[fpos]) and
+ InsideSomeTextArea(rxy[tpos])) :
+
+ % fallback
+
+ % multipar :=
+ % llxy[fpos] --
+ % lrxy[tpos] --
+ % urxy[tpos] --
+ % ulxy[fpos] -- cycle ;
+ %
+ % save_multipar (1,1,multipar) ;
+
+ % we need to take the boundingbox because there can be
+ % more lines and we want a proper rectange
+
+ multipar :=
+ ulxy[fpos] --
+ urxy[tpos] --
+ lrxy[fpos] --
+ llxy[tpos] -- cycle ;
+
+ save_multipar (1,1,boundingbox(multipar)) ;
+
+ else :
+
+ % normal
+
+ for i=1 upto NOfTextAreas :
+
+ TopSkipCorrection := 0 ;
+
+ multipar := set_multipar(i) ;
+
+ % watch how we compensate for negative indentation
+
+ if (nxy[fpos]=RealPageNumber) and (InsideTextArea(i,par_start_pos)) :
+
+ % first one in chain
+
+ ii := i ;
+
+ if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,llxy[tpos])) :
+
+ % in same area
+
+ nn := i ;
+
+ if compensate_multi_par_topskip and (round(LineHeight-ph-pd)=0) :
+
+ TopSkipCorrection := TopSkip - StrutHeight ;
+
+ if round(ypart ulxy[fpos] + TopSkipCorrection) =
+ round(ypart ulcorner TextAreas[i]) :
+ ulxy[fpos] := ulxy[fpos] shifted (0,TopSkipCorrection) ;
+ urxy[fpos] := urxy[fpos] shifted (0,TopSkipCorrection) ;
+ else :
+ TopSkipCorrection := 0 ;
+ fi ;
+
+ fi ;
+
+ if ypart llxy[fpos] = ypart llxy[tpos] :
+
+ multipar :=
+ llxy[fpos] --
+ lrxy[tpos] --
+ %urxy[tpos] --
+ snapped_multi_pos(urxy[tpos]) --
+ %ulxy[fpos] --
+ snapped_multi_pos(ulxy[fpos]) --
+ cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ elseif (ypart llxy[fpos] = ypart ulxy[tpos]) and
+ (xpart llxy[tpos] < xpart llxy[fpos]) :
+
+ % two loners
+
+ multipar := if obey_multi_par_hang :
+
+ right_bottom_hang(true) --
+ right_top_hang(true) --
+ snapped_multi_pos(urxy[fpos]) --
+ lrxy[fpos] --
+
+ else :
+
+ llxy[fpos] --
+ (xpart urcorner multipar, ypart llxy[fpos]) --
+ (xpart urcorner multipar, ypart ulxy[fpos]) --
+ snapped_multi_pos(ulxy[fpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ multipar := set_multipar(i) ;
+
+ multipar := if obey_multi_par_hang :
+
+ left_bottom_hang(true) --
+ llxy[tpos] --
+ snapped_multi_pos(ulxy[tpos]) --
+ left_top_hang(true) --
+
+ else :
+
+ (xpart llcorner multipar, ypart llxy[tpos]) --
+ llxy[tpos] --
+ snapped_multi_pos(ulxy[tpos]) --
+ (xpart llcorner multipar, ypart ulxy[tpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ else :
+
+ multipar := if obey_multi_par_hang :
+
+ left_bottom_hang(true) --
+ llxy[tpos] --
+ %ulxy[tpos] --
+ snapped_multi_pos(ulxy[tpos]) --
+ right_bottom_hang(true) --
+ right_top_hang(true) --
+ %urxy[fpos] --
+ snapped_multi_pos(urxy[fpos]) --
+ lrxy[fpos] --
+ left_top_hang(true) --
+
+ else :
+
+ (xpart llcorner multipar, ypart llxy[tpos]) --
+ llxy[tpos] --
+ %ulxy[tpos] --
+ snapped_multi_pos(ulxy[tpos]) --
+ (xpart lrcorner multipar, ypart ulxy[tpos]) --
+ (xpart urcorner multipar, ypart urxy[fpos]) --
+ %urxy[fpos] --
+ snapped_multi_pos(urxy[fpos]) --
+ lrxy[fpos] --
+ (xpart ulcorner multipar, ypart lrxy[fpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ fi ;
+
+ else :
+
+ multipar := if obey_multi_par_hang :
+
+ left_bottom_hang(false) --
+ right_bottom_hang(false) --
+ right_top_hang(false) --
+ %urxy[fpos] --
+ snapped_multi_pos(urxy[fpos]) --
+ lrxy[fpos] --
+ left_top_hang(false) --
+
+ else :
+
+ llcorner multipar --
+ lrcorner multipar --
+ (xpart urcorner multipar, ypart urxy[fpos]) --
+ %urxy[fpos] --
+ snapped_multi_pos(urxy[fpos]) --
+ lrxy[fpos] --
+ (xpart ulcorner multipar, ypart lrxy[fpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ fi ;
+
+ elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,llxy[tpos])) :
+
+ % last one in chain
+
+ nn := i ;
+
+ if obey_multi_par_hang and obey_multi_par_more :
+
+ multipar :=
+ x_left_top_hang(i,true) --
+ x_right_top_hang(i,true) --
+ x_right_bottom_hang(i,true) --
+ snapped_multi_pos(ulxy[tpos]) --
+ llxy[tpos] --
+ x_left_bottom_hang(i,true) --
+ cycle ;
+
+ else :
+
+ multipar :=
+ ulcorner multipar --
+ urcorner multipar --
+ (xpart lrcorner multipar, ypart urxy[tpos]) --
+ snapped_multi_pos(ulxy[tpos]) --
+ llxy[tpos] --
+ (xpart llcorner multipar, ypart llxy[tpos]) --
+ cycle ;
+
+ fi ;
+
+ save_multipar (i,3,multipar) ;
+
+ elseif multi_column_first_page_hack and ((nxy[fpos]=RealPageNumber) and (nxy[tpos]>=RealPageNumber) and (NOfTextColumns>1)) :
+
+ save_multipar (i,2,multipar) ;
+
+ else :
+ % handled later
+ fi ;
+
+ endfor ;
+
+ % second loop
+
+ if force_multi_par_chain or (ii > 1) :
+
+ for i=ii+1 upto nn-1 :
+
+ % rest of chain / todo : hang
+
+% hm, the second+ column in column sets now gets lost in a NOfTextColumns
+
+ if (not check_multi_par_chain) or
+ ((nxy[fpos]<RealPageNumber) and (nxy[tpos]>RealPageNumber))
+ :
+
+ multipar := set_multipar(i) ;
+
+ if obey_multi_par_hang and obey_multi_par_more :
+
+ multipar :=
+ x_left_top_hang(i,false) --
+ x_right_top_hang(i,false) --
+ x_right_bottom_hang(i,false) --
+ x_left_bottom_hang(i,false) --
+ cycle ;
+
+ fi ;
+
+ save_multipar(i,2,multipar) ;
+
+ fi ;
+
+ endfor ;
+
+ fi ;
+
+ % end of normal/fallback
+
+fi ;
+
+ if span_multi_column_pars :
+ endgroup ;
+ fi ;
+
+ % potential safeguard:
+
+ % for i=1 upto nofmultipars :
+ % if length p <= 4 :
+ % multipars[i] := boundingbox(multipars[i]) ;
+ % fi ;
+ % end ;
+
+ % quick hack for gb:
+
+ one_piece_multi_par := (nofmultipars=1) and (pn=tn) ;
+
+enddef ;
+
+color boxgridcolor ; boxgridcolor := .8red ;
+color boxlinecolor ; boxlinecolor := .8blue ;
+color boxfillcolor ; boxfillcolor := .8white ;
+numeric boxgridtype ; boxgridtype := 0 ;
+numeric boxlinetype ; boxlinetype := 1 ;
+numeric boxfilltype ; boxfilltype := 1 ;
+numeric boxdashtype ; boxdashtype := 0 ;
+pair boxgriddirection ; boxgriddirection := up ;
+numeric boxgridwidth ; boxgridwidth := 1pt ;
+numeric boxlinewidth ; boxlinewidth := 1pt ;
+numeric boxlineradius ; boxlineradius := 0pt ;
+numeric boxfilloffset ; boxfilloffset := 0pt ;
+numeric boxgriddistance ; boxgriddistance := .5cm ;
+numeric boxgridshift ; boxgridshift := 0pt ;
+
+def draw_box =
+ draw pxy withcolor boxlinecolor withpen pencircle scaled boxlinewidth ;
+ draw lxy -- rxy withcolor boxlinecolor withpen pencircle scaled boxgridwidth ;
+enddef ;
+
+def draw_par = % 1 2 3 11 12
+ do_draw_par(pxy) ; do_draw_par(txy) ; do_draw_par(bxy) ;
+ for i = pxy, txy, bxy :
+ if boxgridtype = 1 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,true ) withcolor boxgridcolor ;
+ elseif boxgridtype = 2 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,false) withcolor boxgridcolor ;
+ elseif boxgridtype = 3 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,true ) withcolor boxgridcolor ;
+ draw baseline_grid (i,boxgriddirection,true )
+ shifted (0,ExHeight) withcolor boxgridcolor ;
+ elseif boxgridtype = 4 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,true )
+ shifted (0,ExHeight/2) withcolor boxgridcolor ;
+ elseif boxgridtype = 11 :
+ draw graphic_grid(i,boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+ elseif boxgridtype = 12 :
+ draw graphic_grid(i,boxgriddistance,boxgriddistance,0,0) ;
+ fi ;
+ endfor ;
+enddef ;
+
+def do_show_par (expr p, r, c) =
+ if length(p) > 2 : for i=0 upto length(p) :
+ draw fullcircle scaled r shifted point i of p
+ withpen pencircle scaled .5pt withcolor c ;
+ endfor ; fi ;
+ draw p withpen pencircle scaled .5pt withcolor c ;
+enddef ;
+
+def show_par =
+ if length(mxy) > 2 :
+ draw mxy dashed evenly
+ withpen pencircle scaled .5pt withcolor .5white ;
+ fi ;
+ do_show_par(txy, 4pt, .5green) ;
+ do_show_par(bxy, 6pt, .5blue ) ;
+ do_show_par(pxy, 8pt, .5red ) ;
+ draw pref withpen pencircle scaled 2pt ;
+enddef ;
+
+def sort_multi_pars =
+ if nofmultipars>1 :
+ begingroup ; save _p_, _n_ ; path _p_ ; numeric _n_ ;
+ for i := 1 upto nofmultipars :
+ if multilocs[i] = 3 :
+ _p_ := multipars[nofmultipars] ;
+ multipars[nofmultipars] := multipars[i] ;
+ multipars[i] := _p_ ;
+ _n_ := multirefs[nofmultipars] ;
+ multirefs[nofmultipars] := multirefs[i] ;
+ multirefs[i] := _n_ ;
+ _n_ := multilocs[nofmultipars] ;
+ multilocs[nofmultipars] := multilocs[i] ;
+ multilocs[i] := _n_ ;
+ fi ;
+ endfor ;
+ endgroup ;
+ fi ;
+enddef ;
+
+
+def collapse_multi_pars =
+ if nofmultipars>1 :
+ begingroup ; save _nofmultipars_ ; numeric _nofmultipars_ ;
+ _nofmultipars_ := 1 ;
+ sort_multi_pars ; % block not in order: 1, 3, 2....
+ for i:=1 upto nofmultipars-1 :
+ if (round(xpart(llcorner multipars[i]-llcorner multipars[i+1]))=0) and
+ (round(xpart(lrcorner multipars[i]-lrcorner multipars[i+1]))=0) :
+multilocs[_nofmultipars_] := multilocs[i+1] ;
+multirefs[_nofmultipars_] := multirefs[i+1] ;
+ multipars[_nofmultipars_] :=
+ ulcorner multipars[_nofmultipars_] --
+ urcorner multipars[_nofmultipars_] --
+ lrcorner multipars[i+1] --
+ llcorner multipars[i+1] -- cycle ;
+ else :
+ _nofmultipars_ := _nofmultipars_ + 1 ;
+ multipars[_nofmultipars_] := multipars[i+1] ;
+ multilocs[_nofmultipars_] := multilocs[i+1] ;
+ multirefs[_nofmultipars_] := multirefs[i+1] ;
+ fi ;
+ endfor ;
+ nofmultipars := _nofmultipars_ ;
+ endgroup ;
+ fi ;
+enddef ;
+
+% def draw_multi_pars =
+% for i=1 upto nofmultipars :
+% do_draw_par(multipars[i]) ;
+% if boxgridtype= 1 :
+% draw baseline_grid (multipars[i],up,true ) ; % withcolor boxgridcolor ;
+% elseif boxgridtype= 2 :
+% draw baseline_grid (multipars[i],up,false) ; % withcolor boxgridcolor ;
+% elseif boxgridtype= 3 :
+% draw baseline_grid (multipars[i],up,true ) ; % withcolor boxgridcolor ;
+% draw baseline_grid (multipars[i],up,true )
+% shifted (0,ExHeight) ; % withcolor boxgridcolor ;
+% elseif boxgridtype= 4 :
+% draw baseline_grid (multipars[i],up,true )
+% shifted (0,ExHeight/2) ; % withcolor boxgridcolor ;
+% elseif boxgridtype=11 :
+% draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+% elseif boxgridtype=12 :
+% draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ;
+% fi ;
+% endfor ;
+% enddef ;
+
+def draw_multi_pars =
+ for i=1 upto nofmultipars :
+ do_draw_par(multipars[i]) ;
+ if boxgridtype= 1 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; % withcolor boxgridcolor ;
+ elseif boxgridtype= 2 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,false) ; % withcolor boxgridcolor ;
+ elseif boxgridtype= 3 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; % withcolor boxgridcolor ;
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight) ; % withcolor boxgridcolor ;
+ elseif boxgridtype= 4 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight/2) ; % withcolor boxgridcolor ;
+ elseif boxgridtype=11 :
+ draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+ elseif boxgridtype=12 :
+ draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ;
+ fi ;
+ endfor ;
+enddef ;
+
+def show_multi_pars =
+ for i=1 upto nofmultipars :
+ do_show_par(multipars[i], 6pt, .5blue) ;
+ endfor ;
+enddef ;
+
+vardef do_draw_par (expr p) =
+ if (length p>2) and (bbwidth(p)>1) and (bbheight(p)>1) :
+ save pp ; path pp ;
+ if (boxlineradius>0) and (boxlinetype=2) :
+ pp := p cornered boxlineradius ;
+ else :
+ pp := p ;
+ fi ;
+ if boxfilltype>0 :
+ if boxfilloffset>0 :
+ % temporary hack
+ begingroup ; interim linejoin := mitered ;
+ filldraw pp withcolor boxfillcolor withpen pencircle scaled (2*boxfilloffset) ;
+ endgroup ;
+ else :
+ fill pp withcolor boxfillcolor ;
+ fi ;
+ fi ;
+ if boxlinetype>0 :
+ draw pp withcolor boxlinecolor withpen pencircle scaled boxlinewidth ;
+ fi ;
+ fi ;
+enddef ;
+
+vardef baseline_grid (expr pxy, pdir, at_baseline) =
+ if (par_line_height>0) and (bbheight(pxy)>1) and (bbwidth(pxy)>1) and (boxgridwidth>0) :
+ save i, grid, bb ; picture grid ; pair start ; path bb ;
+ def _do_ (expr start) =
+ % 1 = normal, 2 = with background (i.e. no shine-through)
+ if boxdashtype = 2 :
+ draw start -- start shifted (bbwidth(pxy),0)
+ withpen pencircle scaled boxgridwidth
+ withcolor boxfillcolor ;
+ fi ;
+ draw start -- start shifted (bbwidth(pxy),0)
+ if boxdashtype > 0 : dashed evenly fi
+ withpen pencircle scaled boxgridwidth
+ withcolor boxgridcolor ;
+ enddef ;
+ grid := image
+ ( %fails with inlinespace
+ %
+ if pdir=up :
+ for i = if at_baseline : par_strut_depth else : 0 fi
+ step par_line_height
+ until max(bbheight(pxy),par_line_height) :
+ _do_ (llcorner pxy shifted (0,+i)) ;
+ endfor ;
+ else :
+ for i = if at_baseline : par_strut_height else : 0 fi
+ step par_line_height
+ until bbheight(pxy) :
+ _do_ (ulcorner pxy shifted (0,-i)) ;
+ endfor ;
+ fi ;
+ ) ;
+ clip grid to pxy ;
+ bb := boundingbox grid ;
+ grid := grid shifted (0,boxgridshift) ;
+ setbounds grid to bb ;
+ grid
+ else :
+ nullpicture
+ fi
+enddef ;
+
+vardef graphic_grid (expr pxy, dx, dy, x, y) =
+ if (bbheight(pxy)>dy) and (bbwidth(pxy)>dx) and (boxgridwidth>0) :
+ save grid ; picture grid ;
+ grid := image
+ ( for i = xpart llcorner pxy step dx until xpart lrcorner pxy :
+ draw (i,ypart llcorner pxy) -- (i,ypart ulcorner pxy)
+ withpen pencircle scaled boxgridwidth ;
+ endfor ;
+ for i = ypart llcorner pxy step dy until ypart ulcorner pxy :
+ draw (xpart llcorner pxy,i) -- (xpart lrcorner pxy,i)
+ withpen pencircle scaled boxgridwidth ;
+ endfor ) shifted (x,y) ;
+ clip grid to pxy ;
+ grid
+ else :
+ nullpicture
+ fi
+enddef ;
+
+def anchor_box (expr n,x,y,w,h,d) =
+ currentpicture := currentpicture shifted (-x,-y) ;
+enddef ;
+
+let draw_area = draw_box ;
+let anchor_area = anchor_box ;
+let anchor_par = anchor_box ;
+
+
+numeric sync_n[], sync_p[][], sync_w[][], sync_h[][], sync_d[][], sync_t[][] ;
+pair sync_xy[][] ; color sync_c[][] ;
+
+def ResetSyncTasks =
+ path SyncPaths[] ; numeric SyncTasks[], NOfSyncPaths, CurrentSyncClass ;
+ NOfSyncPaths := CurrentSyncClass := 0 ;
+ if unknown SyncLeftOffset : numeric SyncLeftOffset ; SyncLeftOffset := 0 ; fi ;
+ if unknown SyncWidth : numeric SyncWidth ; SyncWidth := 0 ; fi ;
+ if unknown SyncThreshold : numeric SyncThreshold ; SyncThreshold := LineHeight ; fi ;
+ if unknown SyncColor : color SyncColor ; SyncColor := .5white ; fi ;
+ if (SyncLeftOffset = 0) and (SyncWidth = 0) :
+ SyncWidth := if known TextWidth : TextWidth else : -1cm fi ;
+ fi ;
+enddef ;
+
+ResetSyncTasks ;
+
+vardef SyncBox(expr n, i, leftoffset, width, topoffset, bottomoffset) =
+ save o ; pair o ; o := (xpart llcorner PlainTextArea,ypart sync_xy[n][i]) ;
+ o shifted (leftoffset,sync_h[n][i]+topoffset) --
+ o shifted (width+leftoffset,sync_h[n][i]+topoffset) --
+ o shifted (width+leftoffset,bottomoffset) --
+ o shifted (leftoffset,bottomoffset) -- cycle
+enddef ;
+
+def SetSyncColor(expr n, i, c) =
+ sync_c[n][i] := c ;
+enddef ;
+
+def SetSyncThreshold(expr n, i, th) =
+ sync_th[n][i] := th ;
+enddef ;
+
+vardef TheSyncColor(expr n, i) =
+ if known sync_c[n][i] : sync_c[n][i] else : SyncColor fi
+enddef ;
+
+vardef TheSyncThreshold(expr n, i) =
+ if known sync_th[n][i] : sync_th[n][i] else : SyncThreshold fi
+enddef ;
+
+vardef PrepareSyncTasks(expr n, collapse, extendtop, prestartnext) =
+ ResetSyncTasks ;
+ if known sync_n[n] :
+ CurrentSyncClass := n ;
+ save ok, l, d ; boolean ok ; ok := false ; NOfSyncPaths := l := 0 ;
+ for i=1 upto sync_n[n] :
+ if RealPageNumber > sync_p[n][i] :
+ l := i ;
+ elseif RealPageNumber = sync_p[n][i] :
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ if not ok :
+ if i>1 :
+ if sync_t[n][i-1] = sync_t[n][i] :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i-1, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i-1 ;
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ ok := true ;
+ fi ;
+ endfor ;
+ if (NOfSyncPaths = 0) and (l > 0) :
+ NOfSyncPaths := 1 ;
+ SyncPaths[NOfSyncPaths] := SyncBox(n, l, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := l ;
+ fi ;
+ if NOfSyncPaths > 0 :
+ for i = 1 upto NOfSyncPaths-1 :
+ SyncPaths[i] := topboundary SyncPaths[i] -- reverse topboundary SyncPaths[i+1] -- cycle ;
+ endfor ;
+ if unknown SyncThresholdMethod :
+ numeric SyncThresholdMethod ; SyncThresholdMethod := 2 ;
+ fi ;
+ if extendtop :
+ if SyncThresholdMethod = 1 :
+ if NOfSyncPaths>1 :
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[2]]) ;
+ if (SyncTasks[2]>1) and (d > 0pt) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[2]])) and (sync_p[n][SyncTasks[2]] = RealPageNumber) :
+ SyncPaths[2] := SyncPaths[2] topenlarged PaperHeight ;
+ fi ;
+ fi ;
+ else :
+ for i = 1 upto NOfSyncPaths :
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[i]]) ;
+ if (d > 0) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[i]] = RealPageNumber) :
+ SyncPaths[i] := SyncPaths[i] topenlarged PaperHeight ;
+ fi ;
+ endfor ;
+ fi ;
+ fi ;
+ if prestartnext :
+ if NOfSyncPaths>1 :
+ if SyncTasks[NOfSyncPaths] < sync_n[n] : % there is a next one
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[NOfSyncPaths]+1]) ;
+ if (d > 0) and (d <= TheSyncThreshold(n, sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[NOfSyncPaths]+1] = RealPageNumber+1) :
+ SyncPaths[NOfSyncPaths+1] :=
+ (xpart ulcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+ (xpart urcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+ lrcorner SyncPaths[NOfSyncPaths] --
+ llcorner SyncPaths[NOfSyncPaths] -- cycle ;
+ SyncTasks[NOfSyncPaths+1] := SyncTasks[NOfSyncPaths]+1 ;
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ fi ;
+ fi ;
+ fi ;
+ else :
+ if NOfSyncPaths>1 :
+ d := ypart (sync_xy[n][SyncTasks[NOfSyncPaths]] - llcorner PlainTextArea) ;
+ if (d < TheSyncThreshold(n, SyncTasks[NOfSyncPaths])) :
+ NOfSyncPaths := NOfSyncPaths - 1 ;
+ SyncPaths[NOfSyncPaths] := SyncPaths[NOfSyncPaths] bottomenlarged PaperHeight ;
+ fi ;
+ fi ;
+ fi ;
+ if (NOfSyncPaths>1) and collapse :
+ save j ; numeric j ; j := 1 ;
+ for i = 2 upto NOfSyncPaths :
+ if sync_t[n][SyncTasks[i]] = sync_t[n][SyncTasks[j]] :
+ SyncPaths[j] := boundingbox image (draw SyncPaths[i] ; draw SyncPaths[j] ; ) ;
+ SyncTasks[j] := SyncTasks[i] ;
+ else :
+ j := j + 1 ;
+ SyncPaths[j] := SyncPaths[i] ;
+ SyncTasks[j] := SyncTasks[i] ;
+ fi ;
+ endfor ;
+ NOfSyncPaths := j ;
+ fi ;
+ fi ;
+ fi ;
+enddef ;
+
+def SyncTask(expr n) =
+ if known SyncTasks[n] : SyncTasks[n] else : 0 fi
+enddef ;
+
+def FlushSyncTasks =
+ for i = 1 upto NOfSyncPaths :
+ ProcessSyncTask(SyncPaths[i], TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]])) ;
+ endfor ;
+enddef ;
+
+def ProcessSyncTask(expr p, c) =
+ fill p withcolor c ;
+enddef ;
+
+endinput ;
+
+end
+
+% for Jelle Huisman
+%
+% \setupcolors[state=start]
+% \dontcomplain
+% \definecolumnset[example][n=3,distance=5mm]
+% \startMPextensions
+% multi_column_first_page_hack := true ;
+% \stopMPextensions
+% \startuseMPgraphic{mpos:par:trick}
+% for i=1 upto nofmultipars-1 : draw (rightboundary multipars[i]) shifted (2.5mm, 0) ; endfor ;
+% \stopuseMPgraphic
+% \definetextbackground[test][mp=mpos:par:trick,method=mpos:par:columnset]
+% \starttext
+% \definecolumnsetspan[chapter][n=3]
+% \startcolumnset[example]
+% \startcolumnsetspan[chapter]
+% \chapter{Chapter One}
+% \stopcolumnsetspan
+% \starttextbackground[test] \dorecurse {3}{\input knuth } \stoptextbackground
+% \stopcolumnset
+% \startcolumnset[example]
+% \startcolumnsetspan[chapter]
+% \chapter{Chapter One}
+% \stopcolumnsetspan
+% \starttextbackground[test] \dorecurse {10}{\input knuth } \stoptextbackground
+% \stopcolumnset
+% \stoptext
+%
+% fast variant:
+%
+% \startuseMPgraphic{whatever}
+% for i=1 upto NOfTextColumns-1 :
+% draw (rightboundary TextColumns[i]) shifted (2.5mm,0) shifted -\MPxy\textanchor ;
+% endfor ;
+% setbounds currentpicture to OverlayBox ;
+% \stopuseMPgraphic
+% \defineoverlay[whatever][\useMPgraphic{whatever}]
+% \setupbackgrounds[text][background=whatever]
diff --git a/metapost/context/base/mp-figs.mp b/metapost/context/base/mp-figs.mp
new file mode 100644
index 000000000..da5fa0d16
--- /dev/null
+++ b/metapost/context/base/mp-figs.mp
@@ -0,0 +1,50 @@
+%D \module
+%D [ file=mp-tool.mp,
+%D version=2003.01.15,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=figures,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_figs : endinput ; fi ;
+
+boolean context_figs ; context_figs := true ;
+
+% todo: check defined
+
+def registerfigure(expr name,width,height) =
+ begingroup ;
+ save s ; string s ; s := cleanstring(name) ;
+ scantokens( s & "_width := " & decimal(width)) ;
+ scantokens( s & "_height := " & decimal(height)) ;
+ endgroup ;
+enddef ;
+
+vardef figuresize(expr name) =
+ save s ; string s ; s := cleanstring(name) ;
+ save p ; pair p ;
+ scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ;
+ p
+enddef ;
+
+vardef figurewidth(expr name) =
+ xpart figuresize(name)
+enddef ;
+
+vardef figureheight(expr name) =
+ ypart figuresize(name)
+enddef ;
+
+def figuredimensions = figuresize enddef ; % for old times sake
+
+def naturalfigure(expr name) =
+ externalfigure name xyscaled(figuresize(name))
+enddef ;
+
+endinput
diff --git a/metapost/context/base/mp-fobg.mp b/metapost/context/base/mp-fobg.mp
new file mode 100644
index 000000000..712efe751
--- /dev/null
+++ b/metapost/context/base/mp-fobg.mp
@@ -0,0 +1,88 @@
+%D \module
+%D [ file=mp-fobg.mp,
+%D version=2004.03.12,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=Formatting Objects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_fobg : endinput ; fi ;
+
+boolean context_fobg ; context_fobg := true ;
+
+FoNone := 0 ; FoHidden := 1 ; FoDotted := 2 ; FoDashed := 3 ; FoSolid := 4 ;
+FoDouble := 5 ; FoGroove := 6 ; FoRidge := 7 ; FoInset := 8 ; FoOutset := 9 ;
+FoAll := 0 ; FoTop := 1 ; FoBottom := 2 ; FoLeft := 3 ; FoRight := 4 ;
+FoMedium := .5pt ; FoThin := FoMedium/2 ; FoThick := FoMedium*2 ;
+
+color FoBackgroundColor, FoNoColor, FoLineColor[] ; FoNoColor := (-1,-1,-1) ;
+numeric FoLineWidth[], FoLineStyle[] ;
+boolean FoFrame, FoBackground, FoSplit ;
+
+FoFrame := FoBackground := FoSplit := false ;
+FoBackgroundColor := white ;
+FoDashFactor := .5 ;
+FoDotFactor := .375 ;
+
+for i = FoAll upto FoRight :
+ FoLineColor[i] := black ;
+ FoLineWidth[i] := .5pt ;
+ FoLineStyle[i] := FoNone ;
+endfor ;
+
+def DrawFoFrame(expr n, p) =
+ drawoptions(withcolor FoLineColor[n] withpen pencircle scaled FoLineWidth[n]) ;
+ if FoLineStyle[n] = FoNone :
+ % nothing
+ elseif FoLineStyle[n] = FoHidden :
+ % nothing
+ elseif FoLineStyle[n] = FoDotted :
+ draw p dashed (withdots scaled (FoDotFactor*FoLineWidth[n])) ;
+ elseif FoLineStyle[n] = FoDashed :
+ draw p dashed (evenly scaled (FoDashFactor*FoLineWidth[n])) ;
+ elseif FoLineStyle[n] = FoSolid :
+ draw p ;
+ elseif FoLineStyle[n] = FoDouble :
+ draw p enlarged FoLineWidth[n] ; draw p enlarged -FoLineWidth[n] ;
+ elseif FoLineStyle[n] = FoGroove :
+ draw p ;
+ draw p withpen pencircle scaled .5FoLineWidth[n] withcolor (inverted FoLineColor[n] softened .5) ;
+ elseif FoLineStyle[n] = FoRidge :
+ draw p withcolor (inverted FoLineColor[n] softened .5) ;
+ draw p withpen pencircle scaled .5FoLineWidth[n] ;
+ elseif FoLineStyle[n] = FoInset :
+ draw p ; draw p inset 2.5FoLineWidth[n] ;
+ elseif FoLineStyle[n] = FoOutset :
+ draw p ; draw p outset 2.5FoLineWidth[n] ;
+ fi ;
+enddef ;
+
+primarydef p outset d =
+ ((lrcorner p -- urcorner p -- ulcorner p -- llcorner p -- cycle)
+ shifted (d*(-1,1)) cutbefore topboundary p) cutafter leftboundary p
+enddef ;
+
+primarydef p inset d =
+ ((ulcorner p -- llcorner p -- lrcorner p -- urcorner p -- cycle)
+ shifted (d*(1,-1)) cutbefore bottomboundary p) cutafter rightboundary p
+enddef ;
+
+vardef equalpaths(expr p, q) =
+ if length(p) = length(q) :
+ save ok ; boolean ok ; ok := true ;
+ for i = 0 upto length(p)-1 :
+ ok := ok and (round(point i of p) = round(point i of q)) ;
+ endfor ;
+ ok
+ else :
+ false
+ fi
+enddef ;
+
+endinput ;
diff --git a/metapost/context/base/mp-form.mp b/metapost/context/base/mp-form.mp
new file mode 100644
index 000000000..a65ab6d73
--- /dev/null
+++ b/metapost/context/base/mp-form.mp
@@ -0,0 +1,403 @@
+% Hans Hagen / October 2000
+%
+% This file is mostly a copy from the file format.mp, that
+% comes with MetaPost and is written by John Hobby. This file
+% is meant to be compatible, but has a few more features,
+% controlled by the variables:
+%
+% fmt_initialize when false, initialization is skipped
+% fmt_precision the default accuracy (default=3)
+% fmt_separator the pattern separator (default=%)
+% fmt_zerocheck activate extra sci notation zero check
+%
+% instead of a picture, one can format a number in a for TeX
+% acceptable input string
+
+boolean mant_font ; mant_font := true ; % signals graph not to load form
+
+if known fmt_loaded : expandafter endinput fi ;
+ boolean fmt_loaded ; fmt_loaded := true ;
+
+if unknown fmt_precision :
+ numeric fmt_precision ; fmt_precision := 3 ;
+fi ;
+
+if unknown fmt_initialize :
+ boolean fmt_initialize ; fmt_initialize := true ;
+fi ;
+
+if unknown fmt_separator :
+ string fmt_separator ; fmt_separator := "%" ;
+fi ;
+
+if unknown fmt_zerocheck :
+ boolean fmt_zerocheck ; fmt_zerocheck := false ;
+fi ;
+
+boolean fmt_metapost ; fmt_metapost := true ; % == use old method
+
+% As said, all clever code is from John, the more stupid
+% extensions are mine. The following string variables are
+% responsible for the TeX formatting.
+
+% TeX specs when using TeX instead of pseudo TeX.
+
+string sFebraise_ ; sFebraise_ := "{" ;
+string sFeeraise_ ; sFeeraise_ := "}" ;
+string sFebmath_ ; sFebmath_ := "$" ;
+string sFeemath_ ; sFeemath_ := "$" ;
+
+string sFmneg_ ; sFmneg_ := "-" ;
+string sFemarker_ ; sFemarker_ := "{\times}10^" ;
+string sFeneg_ ; sFeneg_ := "-" ;
+string sFe_plus ; sFe_plus := "" ; % "+"
+
+def sFe_base = Fline_up_("1", sFemarker_) enddef ;
+
+% Macros for generating typeset pictures of computed numbers
+%
+% format(f,x) typeset generalized number x using format string f
+% Mformat(f,x) like format, but x is in Mlog form (see marith.mp)
+% init_numbers(s,m,x,sn,e) choose typeset style given sample sign, mantissa,...
+% roundd(x,d) round numeric x to d places right of decimal point
+% Fe_base what precedes the exponent for typeset powers of 10
+% Fe_plus plus sign if any for typesetting positive exponents
+% Ten_to[] powers of ten for indices 0,1,2,3,4
+%
+% New are:
+%
+% formatstr(f,x) TeX string representing x using format f
+% Mformatstr(f,x) like Mformatstr, but x is in Mlog form
+
+% Other than the above-documented user interface, all
+% externally visible names start with F and end with _.
+
+% Allow big numbers in token lists
+
+begingroup interim warningcheck := 0 ;
+
+%%% Load auxiliary macros.
+
+input string
+input marith
+
+%%% Choosing the Layout %%%
+
+picture Fmneg_, Femarker_, Feneg_, Fe_base, Fe_plus ;
+string Fmfont_, Fefont_ ;
+numeric Fmscale_, Fescale_, Feraise_ ;
+
+% Argument
+%
+% s is a leading minus sign
+% m is a 1-digit mantissa
+% x is whatever follows the mantissa
+% sn is a leading minus for the exponent, and
+% e is a 1-digit exponent.
+%
+% Numbers in scientific notation are constructed by placing
+% these pieces side-by-side; decimal numbers use only m
+% and/or s. To get exponents with leading plus signs, assign
+% to Fe_plus after calling init_numbers. To do something
+% special with a unit mantissa followed by x, assign to
+% Fe_base after calling init_numbers.
+
+vardef init_numbers(expr s, m, x, sn, e) =
+ Fmneg_ := s ;
+ for p within m :
+ Fmfont_ := fontpart p ;
+ Fmscale_ := xxpart p ;
+ exitif true ;
+ endfor
+ Femarker_ := x ;
+ Feneg_ := sn ;
+ for p within e :
+ Fefont_ := fontpart p ;
+ Fescale_ := xxpart p ;
+ Feraise_ := ypart llcorner p ;
+ exitif true ;
+ endfor
+ if fmt_metapost :
+ Fe_base := Fline_up_("1" infont Fmfont_ scaled Fmscale_, Femarker_) ;
+ % else :
+ % sFe_base := Fline_up_("1", sFemarker_) ;
+ fi ;
+ Fe_plus := nullpicture ;
+enddef ;
+
+%%% Low-Level Typesetting %%%
+
+vardef Fmant_(expr x) = %%% adapted by HH %%%
+ if fmt_metapost :
+ (decimal abs x infont Fmfont_ scaled Fmscale_)
+ else :
+ (decimal abs x)
+ fi
+enddef ;
+
+vardef Fexp_(expr x) = %%% adapted by HH %%%
+ if fmt_metapost :
+ (decimal x infont Fefont_ scaled Fescale_ shifted (0,Feraise_))
+ else :
+ (decimal x)
+ fi
+enddef ;
+
+vardef Fline_up_(text t_) = %%% adapted by HH %%%
+ if fmt_metapost :
+ save p_, c_ ;
+ picture p_ ; p_ = nullpicture ;
+ pair c_ ; c_ = (0,0) ;
+ for q_ = t_ :
+ addto p_ also q_ if string q_ : infont defaultfont scaled defaultscale fi
+ shifted c_ ;
+ c_ := (xpart lrcorner p_, 0) ;
+ endfor
+ p_
+ else :
+ "" for q_ = t_ : & q_ endfor
+ fi
+enddef ;
+
+vardef Fdec_o_(expr x) = %%% adapted by HH %%%
+ if x<0 :
+ Fline_up_(if fmt_metapost : Fmneg_ else : sFmneg_ fi, Fmant_(x))
+ else :
+ Fmant_(x)
+ fi
+enddef ;
+
+vardef Fsci_o_(expr x, e) = %%% adapted by HH %%%
+ if fmt_metapost :
+ Fline_up_
+ (if x < 0 : Fmneg_,fi
+ if abs x = 1 : Fe_base else : Fmant_(x), Femarker_ fi,
+ if e < 0 : Feneg_ else : Fe_plus fi,
+ Fexp_(abs e))
+ else :
+ Fline_up_
+ (if x < 0 : sFmneg_, fi
+ if abs x = 1 : sFe_base else : Fmant_(x), sFemarker_ fi,
+ sFebraise_,
+ if e < 0 : sFeneg_ else : sFe_plus fi,
+ Fexp_(abs e),
+ sFeeraise_)
+ fi
+enddef ;
+
+% Assume prologues=1 implies troff mode. TeX users who want
+% prologues on should use some other positive value. The mpx
+% file mechanism requires separate input files here.
+%
+% if fmt_initialize : %%% adapted by HH
+% if prologues = 1 : input troffnum else : input texnum fi
+% fi ;
+%
+% wrong assumption, so we need:
+
+if fmt_initialize :
+ input texnum ;
+fi ;
+
+%%% Scaling and Rounding %%%
+
+% Find a pair p where x = xpart p*10**ypart p and either p =
+% (0,0) or xpart p is between 1000 and 9999.99999. This is
+% the `exponent form' of x.
+
+vardef Feform_(expr x) =
+ interim warningcheck := 0 ;
+ if string x :
+ Meform(Mlog_str x)
+ else :
+ save b, e ;
+ b = x ; e = 0 ;
+ if abs b >= 10000 :
+ (b/10, 1)
+ elseif b = 0 :
+ origin
+ else :
+ forever :
+ exitif abs b >= 1000 ;
+ b := b*10 ; e := e-1 ;
+ endfor
+ (b, e)
+ fi
+ fi
+enddef ;
+
+% The marith.mp macros include a similar macro Meform that
+% converts from `Mlog form' to exponent form. In case
+% rounding has made the xpart of an exponent form number too
+% large, fix it.
+
+vardef Feadj_(expr x, y) =
+ if abs x >= 10000 : (x/10, y+1) else : (x,y) fi
+enddef ;
+
+% Round x to d places right of the decimal point. When d<0,
+% round to the nearest multiple of 10 to the -d.
+
+vardef roundd(expr x, d) =
+ if abs d > 4 :
+ if d > 0 : x else : 0 fi
+ elseif d > 0 :
+ save i ; i = floor x ;
+ i + round(Ten_to[d]*(x-i))/Ten_to[d]
+ else :
+ round(x/Ten_to[-d])*Ten_to[-d]
+ fi
+enddef ;
+
+Ten_to0 = 1 ;
+Ten_to1 = 10 ;
+Ten_to2 = 100 ;
+Ten_to3 = 1000 ;
+Ten_to4 = 10000 ;
+
+% Round an exponent form number p to k significant figures.
+
+primarydef p Fprec_ k =
+ Feadj_(roundd(xpart p,k-4), ypart p)
+enddef ;
+
+% Round an exponent form number p to k digits right of the
+% decimal point.
+
+primarydef p Fdigs_ k =
+ Feadj_(roundd(xpart p,k+ypart p), ypart p)
+enddef ;
+
+%%% High-Level Routines %%%
+
+% The following operators convert z from exponent form and
+% produce typeset output: Formsci_ generates scientific
+% notation; Formdec_ generates decimal notation; and
+% Formgen_ generates whatever is likely to be most compact.
+
+vardef Formsci_(expr z) = %%% adapted by HH %%%
+ if fmt_zerocheck and (z = origin) :
+ Fsci_o_(0,0)
+ else :
+ Fsci_o_(xpart z/1000, ypart z + 3)
+ fi
+enddef ;
+
+vardef Formdec_(expr z) =
+ if ypart z > 0 :
+ Formsci_(z)
+ else :
+ Fdec_o_
+ (xpart z if ypart z >= -4 :
+ /Ten_to[-ypart z]
+ else :
+ for i = ypart z upto -5 : /(10) endfor /10000
+ fi)
+ fi
+enddef ;
+
+vardef Formgen_(expr q) =
+ clearxy ; (x,y) = q ;
+ if x = 0 : Formdec_
+ elseif y >= -6 : Formdec_
+ else : Formsci_
+ fi (q)
+enddef ;
+
+def Fset_item_(expr s) = %%% adapted by HH %%%
+ if s <> "" :
+ if fmt_metapost :
+ s infont defaultfont scaled defaultscale,
+ else :
+ s,
+ fi
+ fi
+enddef ;
+
+% For each format letter, the table below tells how to
+% round and typeset a quantity z in exponent form.
+%
+% e scientific, p significant figures
+% p decimal, p digits right of the point
+% g decimal or scientific, p sig. figs.
+% G decimal or scientific, p digits
+
+string fmt_[] ;
+
+fmt_[ASCII "e"] = "Formsci_(z Fprec_ p)" ;
+fmt_[ASCII "f"] = "Formdec_(z Fdigs_ p)" ;
+fmt_[ASCII "g"] = "Formgen_(z Fprec_ p)" ;
+fmt_[ASCII "G"] = "Formgen_(z Fdigs_ p)" ;
+
+% The format and Mformat macros take a format string f and
+% generate typeset output for a numeric quantity x. String f
+% should contain a `%' followed by an optional number and one
+% of the format letters defined above. The number should be
+% an integer giving the precision (default 3).
+
+vardef isfmtseparator primary c = %%% added by HH %%%
+ ((c <> fmt_separator) and (c <> "%"))
+enddef ;
+
+def initialize_form_numbers =
+ initialize_numbers ; % in context: do_initialize_numbers ;
+enddef ;
+
+vardef dofmt_@#(expr f, x) = %%% adapted by HH %%%
+ initialize_form_numbers ;
+ if f = "" :
+ if fmt_metapost : nullpicture else : "" fi
+ else :
+ interim warningcheck := 0 ;
+ save k, l, s, p, z ;
+ pair z ; z = @#(x) ;
+ % the next adaption is okay
+ % k = 1 + cspan(f, fmt_separator <> ) ;
+ % but best is to support both % and fmt_separator
+ k = 1 + cspan(f, isfmtseparator) ;
+ %
+ l-k = cspan(substring(k,infinity) of f, isdigit) ;
+ p = if l > k :
+ scantokens substring(k,l) of f
+ else :
+ fmt_precision
+ fi ;
+ string s ; s = fmt_[ASCII substring (l,l+1) of f] ;
+ if unknown s :
+ if k <= length f :
+ errmessage("No valid format letter found in "&f) ;
+ fi
+ s = if fmt_metapost : "nullpicture" else : "" fi ;
+ fi
+ Fline_up_
+ (Fset_item_(substring (0,k-1) of f)
+ if not fmt_metapost : sFebmath_, fi
+ scantokens s,
+ if not fmt_metapost : sFeemath_, fi
+ Fset_item_(substring (l+1,infinity) of f)
+ if fmt_metapost : nullpicture else : "" fi)
+ fi
+ hide (fmt_metapost := true)
+enddef ;
+
+%%% so far %%%
+
+vardef format (expr f, x) =
+ fmt_metapost := true ; dofmt_.Feform_(f,x)
+enddef ;
+
+vardef Mformat(expr f, x) =
+ fmt_metapost := true ; dofmt_.Meform (f,x)
+enddef ;
+
+vardef formatstr (expr f, x) =
+ fmt_metapost := false ; dofmt_.Feform_(f,x)
+enddef ;
+
+vardef Mformatstr(expr f, x) =
+ fmt_metapost := false ; dofmt_.Meform (f,x)
+enddef ;
+
+% Restore warningcheck to previous value.
+
+endgroup ;
diff --git a/metapost/context/base/mp-func.mp b/metapost/context/base/mp-func.mp
new file mode 100644
index 000000000..d8646ef3b
--- /dev/null
+++ b/metapost/context/base/mp-func.mp
@@ -0,0 +1,59 @@
+%D \module
+%D [ file=mp-func.mp,
+%D version=2001.12.29,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=function hacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_func : endinput ; fi ;
+
+boolean context_func ; context_func := true ;
+
+string pathconnectors[] ;
+
+pathconnectors[0] := "," ;
+pathconnectors[1] := "--" ;
+pathconnectors[2] := ".." ;
+pathconnectors[3] := "..." ;
+
+vardef function (expr f) (expr u, t, b, e, s) = save x ; numeric x ;
+ for xx := b step s until e :
+ hide (x := xx ;) if xx>b : scantokens(pathconnectors[f]) fi
+ (scantokens(u),scantokens(t))
+ endfor
+enddef ;
+
+def punkedfunction = function (1) enddef ;
+def curvedfunction = function (2) enddef ;
+def tightfunction = function (3) enddef ;
+
+vardef constructedpath (expr f) (text t) =
+ save ok ; boolean ok ; ok := false ;
+ for i=t :
+ if ok : scantokens(pathconnectors[f]) else : ok := true ; fi i
+ endfor
+enddef ;
+
+def punkedpath = constructedpath (1) enddef ;
+def curvedpath = constructedpath (2) enddef ;
+def tightpath = constructedpath (3) enddef ;
+
+vardef constructedpairs (expr f) (text p) =
+ save i ; i := -1 ;
+ forever : exitif unknown p[incr(i)] ;
+ if i>0 : scantokens(pathconnectors[f]) fi p[i]
+ endfor
+enddef ;
+
+def punkedpairs = constructedpairs (1) enddef ;
+def curvedpairs = constructedpairs (2) enddef ;
+def tightpairs = constructedpairs (3) enddef ;
diff --git a/metapost/context/base/mp-grid.mp b/metapost/context/base/mp-grid.mp
new file mode 100644
index 000000000..f6e843489
--- /dev/null
+++ b/metapost/context/base/mp-grid.mp
@@ -0,0 +1,145 @@
+%D \module
+%D [ file=mp-grid.mp,
+%D version=2000.07.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=grid support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_grid : endinput ; fi ;
+
+boolean context_grid ; context_grid := true ;
+
+string fmt_separator ; fmt_separator := "@" ;
+numeric fmt_precision ; fmt_precision := 3 ;
+boolean fmt_initialize ; fmt_initialize := false ;
+boolean fmt_zerocheck ; fmt_zerocheck := true ;
+
+if unknown fmt_loaded : input mp-form ; fi ;
+
+boolean fmt_pictures ; fmt_pictures := true ;
+
+def do_format = if fmt_pictures : format else : formatstr fi enddef ;
+def do_mformat = if fmt_pictures : Mformat else : Mformatstr fi enddef ;
+
+numeric grid_eps ; grid_eps = eps ;
+
+def hlingrid (expr Min, Max, Step, Length, Width) text t =
+ image ( for i=Min step Step until Max+grid_eps :
+ draw (origin--(Width,0)) shifted (0,i*(Length/Max)) t ;
+ endfor ; ) ;
+enddef ;
+
+def vlingrid (expr Min, Max, Step, Length, Height) text t =
+ image ( for i=Min step Step until Max+grid_eps :
+ draw (origin--(0,Height)) shifted (i*(Length/Max),0) t ;
+ endfor ; ) ;
+enddef ;
+
+def hloggrid (expr Min, Max, Step, Length, Width) text t =
+ image ( for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw (origin--(Width,0)) shifted (0,Length*log(i)) t ;
+ endfor ; ) ;
+enddef ;
+
+def vloggrid (expr Min, Max, Step, Length, Height) text t =
+ image ( for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw (origin--(0,Height)) shifted (Length*log(i),0) t ;
+ endfor ; ) ;
+enddef ;
+
+vardef hlintext@#(expr Min, Max, Step, Length, Format) text t =
+ image ( do_initialize_numbers ;
+ for i=Min step Step until Max+grid_eps :
+ draw textext@#(do_format(Format,i)) shifted (0,i*(Length/Max)) t ;
+ endfor ; )
+enddef ;
+
+vardef vlintext@#(expr Min, Max, Step, Length, Format) text t =
+ image ( do_initialize_numbers ;
+ for i=Min step Step until Max+grid_eps :
+ draw textext@#(do_format(Format,i)) shifted (i*(Length/Max),0) t ;
+ endfor ; )
+enddef ;
+
+vardef hlogtext@#(expr Min, Max, Step, Length, Format) text t =
+ image ( do_initialize_numbers ;
+ for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw textext@#(do_format(Format,i)) shifted (0,Length*log(i)) t ;
+ endfor ; )
+enddef ;
+
+vardef vlogtext@#(expr Min, Max, Step, Length, Format) text t =
+ image ( do_initialize_numbers ;
+ for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw textext@#(do_format(Format,i)) shifted (Length*log(i),0) t ;
+ endfor ; )
+enddef ;
+
+vardef hlinlabel@#(expr Min, Max, Step, Length) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw thelabel@#(decimal i,(0,i*(Length/Max))) t ;
+ endfor ; )
+enddef ;
+
+vardef vlinlabel@#(expr Min, Max, Step, Length) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw thelabel@#(decimal i,(i*(Length/Max),0)) t ;
+ endfor ; )
+enddef ;
+
+boolean numbers_initialized ; numbers_initialized := false ;
+
+def do_initialize_numbers =
+ if not numbers_initialized :
+ init_numbers ( textext.raw("$-$") ,
+ textext.raw("$1$") ,
+ textext.raw("${\times}10$") ,
+ textext.raw("${}^-$") ,
+ textext.raw("${}^2$") ) ;
+ numbers_initialized := true ;
+ fi ;
+enddef ;
+
+def initialize_numbers =
+ numbers_initialized := false ; do_initialize_numbers ;
+enddef ;
+
+vardef linlog(expr xy) = ( xpart xy, log(ypart xy)) enddef ;
+vardef loglin(expr xy) = (log(xpart xy), ypart xy) enddef ;
+vardef loglog(expr xy) = (log(xpart xy), log(ypart xy)) enddef ;
+vardef linlin(expr xy) = ( (xpart xy), (ypart xy)) enddef ;
+
+vardef loglinpath primary p = processpath (p) (loglin) enddef ;
+vardef linlogpath primary p = processpath (p) (linlog) enddef ;
+vardef loglogpath primary p = processpath (p) (loglog) enddef ;
+vardef linlinpath primary p = processpath (p) (linlin) enddef ;
+
+def processpath (expr p) (text pp) =
+ if path p :
+ for i=0 upto length(p)-1 :
+ (pp(point i of p)) .. controls
+ (pp(postcontrol i of p)) and
+ (pp(precontrol (i+1) of p)) ..
+ endfor
+ if cycle p :
+ cycle
+ else :
+ (pp(point length(p) of p))
+ fi
+ elseif pair p :
+ (pp(p))
+ else :
+ p
+ fi
+enddef ;
diff --git a/metapost/context/base/mp-grph.mp b/metapost/context/base/mp-grph.mp
new file mode 100644
index 000000000..243b45318
--- /dev/null
+++ b/metapost/context/base/mp-grph.mp
@@ -0,0 +1,296 @@
+%D \module
+%D [ file=mp-grph.mp,
+%D version=2000.12.14,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=graphic text support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_grph : endinput ; fi ;
+
+boolean context_grph ; context_grph := true ;
+
+string CRLF ; CRLF := char 10 & char 13 ;
+
+picture _currentpicture_ ;
+
+def beginfig (expr c) =
+ begingroup
+ charcode := c ;
+ resetfig ;
+ scantokens extra_beginfig ;
+enddef ;
+
+def resetfig =
+ clearxy ;
+ clearit ;
+ clearpen ;
+ pickup defaultpen ;
+ interim linecap := linecap ;
+ interim linejoin := linejoin ;
+ interim miterlimit := miterlimit ;
+ save _background_ ; color _background_ ; _background_ := background ;
+ save background ; color background ; background := _background_ ;
+ drawoptions () ;
+enddef ;
+
+def protectgraphicmacros =
+ save showtext ;
+ save beginfig ; let beginfig = begingraphictextfig ;
+ save endfig ; let endfig = endgraphictextfig ;
+ save end ; let end = relax ;
+ interim prologues := prologues ;
+ resetfig ; % resets currentpicture
+enddef ;
+
+numeric currentgraphictext ; currentgraphictext := 0 ;
+string graphictextformat ; graphictextformat := "plain" ;
+string graphictextstring ; graphictextstring := "" ;
+string graphictextfile ; graphictextfile := "dummy.mpo" ;
+
+def data_mpo_file = job_name & "-mpgraph.mpo" enddef ;
+def data_mpy_file = job_name & "-mpgraph.mpy" enddef ;
+
+def savegraphictext (expr str) =
+ if (graphictextstring<>"") :
+ write graphictextstring to data_mpo_file ;
+ graphictextstring := "" ;
+ fi ;
+ write str to data_mpo_file ;
+ let erasegraphictextfile = relax ;
+enddef ;
+
+def erasegraphictextfile =
+ write EOF to data_mpo_file ;
+ let erasegraphictextfile = relax ;
+enddef ;
+
+extra_beginfig := extra_beginfig & " erasegraphictextfile ;" ;
+
+def begingraphictextfig (expr n) =
+ foundpicture := n ; scratchpicture := nullpicture ;
+enddef ;
+
+def endgraphictextfig =
+ if foundpicture = currentgraphictext :
+ expandafter endinput
+ else :
+ scratchpicture := nullpicture ;
+ fi ;
+enddef ;
+
+def loadfigure primary filename =
+ doloadfigure (filename)
+enddef ;
+
+def doloadfigure (expr filename) text figureattributes =
+ begingroup ;
+ save figurenumber, figurepicture, number, fixedplace ;
+ numeric figurenumber ; figurenumber := 0 ;
+ boolean figureshift ; figureshift := true ;
+ picture figurepicture ; figurepicture := currentpicture ;
+ def number primary n = hide(figurenumber := n) enddef ;
+ def fixedplace = hide(figureshift := false) enddef ;
+ protectgraphicmacros ;
+ % defaults
+ interim linecap := rounded ;
+ interim linejoin := rounded ;
+ interim miterlimit := 10 ;
+ %
+ currentpicture := nullpicture ;
+ draw fullcircle figureattributes ; % expand number
+ currentpicture := nullpicture ;
+ def beginfig (expr n) =
+ currentpicture := nullpicture ;
+ if (figurenumber=n) or (figurenumber=0) :
+ let endfig = endinput ;
+ fi ;
+ enddef ;
+ let endfig = relax ;
+ readfile(filename) ;
+ if figureshift :
+ currentpicture := currentpicture shifted -llcorner currentpicture ;
+ fi ;
+ addto figurepicture also currentpicture figureattributes ;
+ currentpicture := figurepicture ;
+ endgroup ;
+enddef ;
+
+def graphictext primary t =
+ dographictext(t)
+enddef ;
+
+def dographictext (expr t) =
+ begingroup ;
+ save figurepicture ; picture figurepicture ;
+ figurepicture := currentpicture ; currentpicture := nullpicture ;
+ if graphictextformat<>"" :
+ graphictextstring :=
+ "% format=" & graphictextformat & CRLF & graphictextstring ;
+ graphictextformat := "" ;
+ fi ;
+ currentgraphictext := currentgraphictext + 1 ;
+ savegraphictext ("\startTEXpage[scale=10000]" & t & "\stopTEXpage") ;
+ dofinishgraphictext
+enddef ;
+
+def redographictext primary t =
+ regraphictext(t)
+enddef ;
+
+def regraphictext (expr t) =
+ begingroup ;
+ save figurepicture ; picture figurepicture ;
+ figurepicture := currentpicture ; currentpicture := nullpicture ;
+ save currentgraphictext ; numeric currentgraphictext ;
+ currentgraphictext := t ;
+ dofinishgraphictext
+enddef ;
+
+%D Believe it or not, but it took me half a day to uncover
+%D the following neccessity:
+%D
+%D \starttypen
+%D save withfillcolor, withdrawcolor ;
+%D \stoptypen
+%D
+%D When we have more than one graphictext, these will be
+%D defined after the first graphic. For some obscure reason,
+%D this means that in the next graphic they will be called, but
+%D afterwards the data and boolean are not set. Don't ask me
+%D why.
+
+def dofinishgraphictext text x_op_x =
+ protectgraphicmacros ; % resets currentpicture
+ interim linecap := butt ; % normally rounded
+ interim linejoin := mitered ; % normally rounded
+ interim miterlimit := 10 ; % todo
+ let normalwithshade = withshade ;
+ save foundpicture, scratchpicture, str ;
+ save fill, draw, withshade, reversefill, outlinefill ;
+ save withfillcolor, withdrawcolor ; % quite important
+ numeric foundpicture ; picture scratchpicture ; string str ;
+ def draw expr p =
+ % the first, naive implementation was:
+ % addto scratchpicture doublepath p withpen currentpen ;
+ % but it is better to turn lines into fills
+ addto scratchpicture contour boundingbox
+ image (addto currentpicture doublepath p withpen currentpen) ;
+ enddef ;
+ def fill expr p =
+ addto scratchpicture contour p withpen currentpen ;
+ enddef ;
+ def f_op_f = enddef ; boolean f_color ; f_color := false ;
+ def d_op_d = enddef ; boolean d_color ; d_color := false ;
+ def s_op_s = enddef ; boolean s_color ; s_color := false ;
+ boolean reverse_fill ; reverse_fill := false ;
+ boolean outline_fill ; outline_fill := false ;
+ def reversefill =
+ hide(reverse_fill := true )
+ enddef ;
+ def outlinefill =
+ hide(outline_fill := true )
+ enddef ;
+ def withshade primary c =
+ hide(def s_op_s = normalwithshade c enddef ; s_color := true )
+ enddef ;
+ def withfillcolor primary c =
+ hide(def f_op_f = withcolor c enddef ; f_color := true )
+ enddef ;
+ def withdrawcolor primary c =
+ hide(def d_op_d = withcolor c enddef ; d_color := true )
+ enddef ;
+ scratchpicture := nullpicture ;
+ addto scratchpicture doublepath origin x_op_x ; % pre-roll
+ for i within scratchpicture : % Below here is a dirty tricky test!
+ if (urcorner dashpart i) = origin : outline_fill := false ; fi ;
+ endfor ;
+ scratchpicture := nullpicture ;
+ readfile(data_mpy_file) ;
+ scratchpicture := (scratchpicture shifted -llcorner scratchpicture) scaled (1/10) ;
+ if not d_color and not f_color : d_color := true ; fi
+ if s_color : d_color := false ; f_color := false ; fi ;
+ currentpicture := figurepicture ;
+ if d_color and not reverse_fill :
+ for i within scratchpicture :
+ if f_color and outline_fill :
+ addto currentpicture doublepath pathpart i _op_ x_op_x f_op_f
+ dashed nullpicture ;
+ fi ;
+ if filled i :
+ addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+ fi ;
+ endfor ;
+ fi ;
+ if f_color :
+ for i within scratchpicture :
+ if filled i :
+ addto currentpicture contour pathpart i _op_ x_op_x f_op_f
+ withpen pencircle scaled 0 ;
+ fi ;
+ endfor ;
+ fi ;
+ if d_color and reverse_fill :
+ for i within scratchpicture :
+ if filled i :
+ addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+ fi ;
+ endfor ;
+ fi ;
+ if s_color :
+ for i within scratchpicture :
+ if filled i :
+ addto currentpicture contour pathpart i _op_ x_op_x s_op_s ;
+ fi ;
+ endfor ;
+ else :
+ for i within scratchpicture :
+ if stroked i :
+ addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+ fi ;
+ endfor ;
+ fi ;
+ endgroup ;
+enddef ;
+
+def resetgraphictextdirective =
+ graphictextstring := "" ;
+enddef ;
+
+def graphictextdirective text t =
+ graphictextstring := graphictextstring & t & CRLF ;
+enddef ;
+
+endinput
+
+% example
+
+input mp-grph ;
+
+ graphictextformat := "context" ;
+% graphictextformat := "plain" ;
+% graphictextformat := "latex" ; graphictextdirective "\documentclass[]{article}" ;
+
+beginfig (1) ;
+ graphictext
+ "\vbox{\hsize10cm \input tufte }"
+ scaled 8
+ withdrawcolor blue
+ withfillcolor red
+ withpen pencircle scaled 2pt ;
+endfig ;
+
+beginfig(1) ;
+ loadfigure "gracht.mp" rotated 20 ;
+ loadfigure "koe.mp" number 1 scaled 2 ;
+endfig ;
+
+end
diff --git a/metapost/context/base/mp-mlib.mp b/metapost/context/base/mp-mlib.mp
new file mode 100644
index 000000000..bf2372ca3
--- /dev/null
+++ b/metapost/context/base/mp-mlib.mp
@@ -0,0 +1,282 @@
+%D \module
+%D [ file=mp-mlib.mp,
+%D version=2008.03.21,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=specials,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown mplib : endinput ; fi ;
+if known context_mlib : endinput ; fi ;
+
+boolean context_mlib ; context_mlib := true ;
+
+numeric _tt_w_[], _tt_h_[], _tt_d_[] ;
+numeric _tt_n_ ; _tt_n_ := 0 ;
+picture _tt_p_ ; _tt_p_ := nullpicture ;
+boolean _trial_run_ ; _trial_run_ := false ;
+
+def resettextexts =
+ _tt_n_ := 0 ;
+ _tt_p_ := nullpicture ;
+enddef ;
+
+extra_endfig := ";addto currentpicture also _tt_p_; " & extra_endfig; % was draw _tt_p_
+extra_beginfig := extra_beginfig & "resettextexts;";
+
+vardef rawtextext(expr str) =
+ if str = "" :
+ nullpicture
+ elseif _trial_run_ :
+ image (
+ _tt_n_ := _tt_n_ + 1 ;
+ _tt_p_ := image (
+ addto currentpicture also _tt_p_ ;
+ addto currentpicture doublepath unitsquare withprescript "tf" withpostscript decimal _tt_n_ & ":" & str ;
+ ) ;
+ addto currentpicture doublepath unitsquare withpen pencircle scaled 0 ;
+ )
+ else :
+ image (
+ _tt_n_ := _tt_n_ + 1 ;
+ addto currentpicture doublepath unitsquare
+ xscaled _tt_w_[_tt_n_]
+ yscaled (_tt_h_[_tt_n_] + _tt_d_[_tt_n_])
+ withprescript "ts"
+ withpostscript decimal _tt_n_ & ":" & str ;
+ ) shifted (0,-_tt_d_[_tt_n_])
+ fi
+enddef ;
+
+% not ok yet
+
+pair laboff.d, laboff.dlft, laboff.drt ; % new positional suffixes
+pair laboff.origin, laboff.raw ; % graph mess
+
+laboff.d := laboff ; labxf.d := labxf ; labyf.d := labyf ;
+laboff.dlft := laboff.lft ; labxf.dlft := labxf.lft ; labyf.dlft := labyf.lft ;
+laboff.drt := laboff.rt ; labxf.drt := labxf.rt ; labyf.drt := labyf.rt ;
+
+labtype := 0 ; labtype.lft := 1 ; labtype.rt := 2 ;
+labtype.bot := 3 ; labtype.top := 4 ; labtype.ulft := 5 ;
+labtype.urt := 6 ; labtype.llft := 7 ; labtype.lrt := 8 ;
+labtype.d := 10 ; labtype.dlft := 11 ; labtype.drt := 12 ;
+labtype.origin := 0 ; labtype.raw := 0 ;
+
+% laboff.origin = (infinity,infinity) ; labxf.origin := 0 ; labyf.origin := 0 ;
+% laboff.raw = (infinity,infinity) ; labxf.raw := 0 ; labyf.raw := 0 ;
+
+% todo: thelabel.origin("xxxx",origin) (overflows)
+
+laboff.origin = (0,0) ; labxf.origin := 0 ; labyf.origin := 0 ;
+laboff.raw = (0,0) ; labxf.raw := 0 ; labyf.raw := 0 ;
+
+pair laboff.l ; laboff.l = laboff.lft ;
+pair laboff.r ; laboff.r = laboff.rt ;
+pair laboff.b ; laboff.b = laboff.bot ;
+pair laboff.t ; laboff.t = laboff.top ;
+pair laboff.l_t ; laboff.l_t = laboff.ulft ;
+pair laboff.r_t ; laboff.r_t = laboff.urt ;
+pair laboff.l_b ; laboff.l_b = laboff.llft ;
+pair laboff.r_b ; laboff.r_b = laboff.lrt ;
+pair laboff.t_l ; laboff.t_l = laboff.ulft ;
+pair laboff.t_r ; laboff.t_r = laboff.urt ;
+pair laboff.b_l ; laboff.b_l = laboff.llft ;
+pair laboff.b_r ; laboff.b_r = laboff.lrt ;
+
+labxf.l ; labxf.l = labxf.lft ;
+labxf.r ; labxf.r = labxf.rt ;
+labxf.b ; labxf.b = labxf.bot ;
+labxf.t ; labxf.t = labxf.top ;
+labxf.l_t ; labxf.l_t = labxf.ulft ;
+labxf.r_t ; labxf.r_t = labxf.urt ;
+labxf.l_b ; labxf.l_b = labxf.llft ;
+labxf.r_b ; labxf.r_b = labxf.lrt ;
+labxf.t_l ; labxf.t_l = labxf.ulft ;
+labxf.t_r ; labxf.t_r = labxf.urt ;
+labxf.b_l ; labxf.b_l = labxf.llft ;
+labxf.b_r ; labxf.b_r = labxf.lrt ;
+
+labyf.l ; labyf.l = labyf.lft ;
+labyf.r ; labyf.r = labyf.rt ;
+labyf.b ; labyf.b = labyf.bot ;
+labyf.t ; labyf.t = labyf.top ;
+labyf.l_t ; labyf.l_t = labyf.ulft ;
+labyf.r_t ; labyf.r_t = labyf.urt ;
+labyf.l_b ; labyf.l_b = labyf.llft ;
+labyf.r_b ; labyf.r_b = labyf.lrt ;
+labyf.t_l ; labyf.t_l = labyf.ulft ;
+labyf.t_r ; labyf.t_r = labyf.urt ;
+labyf.b_l ; labyf.b_l = labyf.llft ;
+labyf.b_r ; labyf.b_r = labyf.lrt ;
+
+labtype.l ; labtype.l = labtype.lft ;
+labtype.r ; labtype.r = labtype.rt ;
+labtype.b ; labtype.b = labtype.bot ;
+labtype.t ; labtype.t = labtype.top ;
+labtype.l_t ; labtype.l_t = labtype.ulft ;
+labtype.r_t ; labtype.r_t = labtype.urt ;
+labtype.l_b ; labtype.l_b = labtype.llft ;
+labtype.r_b ; labtype.r_b = labtype.lrt ;
+labtype.t_l ; labtype.t_l = labtype.ulft ;
+labtype.t_r ; labtype.t_r = labtype.urt ;
+labtype.b_l ; labtype.b_l = labtype.llft ;
+labtype.b_r ; labtype.b_r = labtype.lrt ;
+
+vardef thetextext@#(expr p,z) = % adapted copy of thelabel@
+ if string p :
+ thetextext@#(rawtextext(p),z)
+ else :
+ p
+ if (labtype@# >= 10) : shifted (0,ypart center p) fi
+ shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p))
+ fi
+enddef ;
+
+vardef textext@#(expr txt) =
+ interim labeloffset := textextoffset ;
+ if string txt :
+ thetextext@#(rawtextext(txt),origin)
+ else :
+ thetextext@#(txt,origin)
+ fi
+enddef ;
+
+% \starttext
+% \startMPpage
+% numeric value ; value = 123 ;
+% label.lft(decimal value,origin) ;
+% draw "oeps" infont defaultfont ;
+% \stopMPpage
+% \stoptext
+
+vardef thelabel@#(expr s, z) =
+ save p ; picture p ;
+ if picture s :
+ p = s ;
+ else :
+ p = textext("\definedfont[" & defaultfont & "]" & s) scaled defaultscale ;
+ fi ;
+ p shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p))
+enddef;
+
+let normalinfont = infont ;
+
+primarydef str infont name = % very naughty !
+ if name = "" :
+ textext(str)
+ else :
+ textext("\definedfont[" & name & "]" & str)
+ fi
+enddef ;
+
+def circular_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save ab, r ; pair ab ; numeric r ;
+ r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ;
+ set_circular_vector(ab,r)(p,n) ;
+ fill p withcircularshade(ab,ab,0,r,ca,cb) ;
+ if trace_shades :
+ drawarrow ab -- ab shifted (0,r) withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+def linear_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save a, b, sh ; pair a, b ;
+ set_linear_vector(a,b)(p,n) ;
+ fill p withlinearshade(a,b,ca,cb) ;
+ if trace_shades :
+ drawarrow a -- b withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+def withcircularshade (expr a, b, ra, rb, ca, cb) =
+ withprescript
+ "cs"
+ withpostscript
+ "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb
+enddef ;
+def withlinearshade (expr a, b, ca, cb) =
+ withprescript
+ "ls"
+ withpostscript
+ "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " " &
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset)
+enddef ;
+string _defined_cs_pre_[], _defined_cs_post_[] ; numeric _defined_cs_ ; _defined_cs_:= 0 ;
+vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
+ _defined_cs_ := _defined_cs_ + 1 ;
+ _defined_cs_pre_ [_defined_cs_] := "cs" ;
+ _defined_cs_post_[_defined_cs_] := "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ;
+ _defined_cs_
+enddef ;
+vardef define_linear_shade (expr a, b, ca, cb) =
+ _defined_cs_ := _defined_cs_ + 1 ;
+ _defined_cs_pre_ [_defined_cs_] := "ls" ;
+ _defined_cs_post_[_defined_cs_] := "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " " &
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset) ;
+ _defined_cs_
+enddef ;
+primarydef p withshade sc =
+ p withprescript _defined_cs_pre_[sc] withpostscript _defined_cs_post_[sc]
+enddef ;
+def shadecolor(expr sc) = % obsolete
+ 1 withprescript _defined_cs_pre_[sc] withpostscript _defined_cs_post_[sc]
+enddef ;
+
+def graphictext primary t =
+ if _trial_run_ :
+ let dographictextindeed = nographictext ;
+ else :
+ let dographictextindeed = dographictext ;
+ fi
+ dographictextindeed(t)
+enddef ;
+def dographictext (expr t) =
+ begingroup ;
+ save figurepicture ; picture figurepicture ;
+ figurepicture := currentpicture ; currentpicture := nullpicture ;
+ currentgraphictext := currentgraphictext + 1 ;
+ dofinishgraphictext
+enddef ;
+def nographictext (expr t) text rest =
+ draw unitsquare withprescript "gt" withpostscript t ;
+enddef ;
+def savegraphictext (expr str) =
+enddef ;
+def erasegraphictextfile =
+enddef ;
+
+def externalfigure primary filename =
+ doexternalfigure (filename)
+enddef ;
+def doexternalfigure (expr filename) text transformation =
+ draw unitsquare transformation withprescript "fg" withpostscript filename ;
+enddef ;
+
+def register (expr label, width, height, offset) =
+ draw unitsquare xscaled width yscaled height shifted offset withprescript "ps" withpostscript label ;
+enddef ;
+
+extra_beginfig := extra_beginfig & "currentgraphictext := 0 ; " ;
+extra_endfig := extra_endfig & "finishsavingdata ; " ;
+extra_endfig := extra_endfig & "resettextexts ; " ;
+
+boolean cmykcolors ; cmykcolors := true ;
+boolean spotcolors ; spotcolors := true ;
+
+vardef verbatim(expr str) =
+ ditto & "\detokenize{" & str & "}" & ditto
+enddef ;
diff --git a/metapost/context/base/mp-page.mp b/metapost/context/base/mp-page.mp
new file mode 100644
index 000000000..60bfb1417
--- /dev/null
+++ b/metapost/context/base/mp-page.mp
@@ -0,0 +1,474 @@
+%D \module
+%D [ file=mp-page.mp,
+%D version=1999.03.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=page enhancements,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module is rather preliminary and subjected to
+%D changes.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_page : endinput ; fi ;
+
+boolean context_page ; context_page := true ;
+
+if unknown PageStateAvailable :
+ boolean PageStateAvailable ; PageStateAvailable := false ;
+fi ;
+
+if unknown OnRightPage :
+ boolean OnRightPage ; OnRightPage := true ;
+fi ;
+
+if unknown OnOddPage :
+ boolean OnOddPage ; OnOddPage := true ;
+fi ;
+
+if unknown InPageBody :
+ boolean InPageBody ; InPageBody := false ;
+fi ;
+
+def SaveTextAreas =
+ path SavedTextAreas [] ;
+ path SavedTextColumns[] ;
+ numeric NOfSavedTextAreas ;
+ numeric NOfSavedTextColumns ;
+ for i=1 upto NOfTextAreas :
+ SavedTextAreas[i] := TextAreas[i] ;
+ endfor ;
+ for i=1 upto NOfTextColumns :
+ SavedTextColumns[i] := TextColumns[i] ;
+ endfor ;
+ NOfSavedTextAreas := NOfTextAreas ;
+ NOfSavedTextColumns := NOfTextColumns ;
+enddef ;
+
+def ResetTextAreas =
+ path TextAreas[], TextColumns[] ;
+ numeric NOfTextAreas ; NOfTextAreas := 0 ;
+ numeric NOfTextColumns ; NOfTextColumns := 0 ;
+ numeric nofmultipars ; nofmultipars := 0 ;
+ TextAreas[0] := TextColumns[0] := origin -- cycle ;
+enddef ;
+
+ResetTextAreas ; SaveTextAreas ; ;
+
+def RegisterTextArea (expr x, y, w, h, d) =
+ begingroup ; save p ; path p ;
+ p := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+ if NOfTextAreas>0 :
+ % if needed, concatenate areas
+ if (round(llcorner TextAreas[NOfTextAreas]) = round(ulcorner p)) and
+ (round(lrcorner TextAreas[NOfTextAreas]) = round(urcorner p)) :
+ p := ulcorner TextAreas[NOfTextAreas] --
+ urcorner TextAreas[NOfTextAreas] --
+ lrcorner p --
+ llcorner p --
+ cycle ;
+ else :
+ NOfTextAreas := NOfTextAreas + 1 ;
+ fi ;
+ else :
+ NOfTextAreas := NOfTextAreas + 1 ;
+ fi ;
+ TextAreas[NOfTextAreas] := p ;
+ if NOfTextColumns>0 :
+ if (round(xpart llcorner TextColumns[NOfTextColumns]) = round(xpart ulcorner p)) and
+ (round(xpart lrcorner TextColumns[NOfTextColumns]) = round(xpart urcorner p)) :
+ p := ulcorner TextColumns[NOfTextColumns] --
+ urcorner TextColumns[NOfTextColumns] --
+ lrcorner p --
+ llcorner p --
+ cycle ;
+ else :
+ NOfTextColumns := NOfTextColumns + 1 ;
+ fi ;
+ else :
+ NOfTextColumns := NOfTextColumns + 1 ;
+ fi ;
+ TextColumns[NOfTextColumns] := p ;
+ endgroup ;
+enddef ;
+
+%D We store a local area in slot zero.
+
+def RegisterLocalTextArea (expr x, y, w, h, d) =
+ TextAreas[0] := TextColumns[0] := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+enddef ;
+
+def ResetLocalTextArea =
+ TextAreas[0] := TextColumns[0] := origin -- cycle ;
+enddef ;
+
+ResetLocalTextArea ;
+
+vardef InsideTextArea (expr _i_, _xy_) =
+ ( (round(xpart _xy_) >= round(xpart llcorner TextAreas[_i_])) and
+ (round(xpart _xy_) <= round(xpart lrcorner TextAreas[_i_])) and
+ (round(ypart _xy_) >= round(ypart llcorner TextAreas[_i_])) and
+ (round(ypart _xy_) <= round(ypart urcorner TextAreas[_i_])) )
+enddef ;
+
+vardef InsideSavedTextArea (expr _i_, _xy_) =
+ ( (round(xpart _xy_) >= round(xpart llcorner SavedTextAreas[_i_])) and
+ (round(xpart _xy_) <= round(xpart lrcorner SavedTextAreas[_i_])) and
+ (round(ypart _xy_) >= round(ypart llcorner SavedTextAreas[_i_])) and
+ (round(ypart _xy_) <= round(ypart urcorner SavedTextAreas[_i_])) )
+enddef ;
+
+vardef InsideSomeTextArea(expr _xy_) =
+ save ok ; boolean ok ; ok := false ;
+ for i := 1 upto NOfTextAreas :
+ if InsideTextArea(i,_xy_) : ok := true ; fi ;
+ exitif ok ;
+ endfor ;
+ ok
+enddef ;
+
+vardef InsideSomeSavedTextArea(expr _xy_) =
+ save ok ; boolean ok ; ok := false ;
+ for i := 1 upto NOfSavedTextAreas :
+ if InsideSavedTextArea(i,_xy_) : ok := true ; fi ;
+ exitif ok ;
+ endfor ;
+ ok
+enddef ;
+
+vardef TextAreaX (expr x) =
+ numeric _TextAreaX_ ; _TextAreaX_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) :
+ _TextAreaX_ := xpart llcorner TextAreas[i] ;
+ fi ;
+ endfor ;
+ _TextAreaX_
+enddef ;
+
+vardef TextAreaY (expr y) =
+ numeric _TextAreaY_ ; _TextAreaY_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(y) >= round(ypart llcorner TextAreas[NOfTextAreas])) and
+ (round(y) <= round(ypart ulcorner TextAreas[NOfTextAreas])) :
+ _TextAreaY_ := ypart llcorner TextAreas[NOfTextAreas] ;
+ fi ;
+ endfor ;
+ _TextAreaY_
+enddef ;
+
+vardef TextAreaXY (expr x, y) =
+ pair _TextAreaXY_ ; _TextAreaXY_ := origin ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) and
+ (round(y) >= round(ypart llcorner TextAreas[i])) and
+ (round(y) <= round(ypart ulcorner TextAreas[i])) :
+ _TextAreaXY_ := llconer TextAreas[i] ;
+ fi ;
+ endfor ;
+ _TextAreaXY_
+enddef ;
+
+vardef TextAreaW (expr x) =
+ numeric _TextAreaW_ ; _TextAreaW_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) :
+ _TextAreaW_ := bbwidth(TextAreas[i]) ;
+ fi ;
+ endfor ;
+ _TextAreaW_
+enddef ;
+
+vardef TextAreaH (expr y) =
+ numeric _TextAreaH_ ; _TextAreaH_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(y) >= round(ypart llcorner TextAreas[i])) and
+ (round(y) <= round(ypart ulcorner TextAreas[i])) :
+ _TextAreaH_ := bbheight(TextAreas[i]) ;
+ fi ;
+ endfor ;
+ _TextAreaH_
+enddef ;
+
+vardef TextAreaWH (expr x, y) =
+ pair _TextAreaWH_ ; _TextAreaWH_ := origin ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) and
+ (round(y) >= round(ypart llcorner TextAreas[i])) and
+ (round(y) <= round(ypart ulcorner TextAreas[i])) :
+ _TextAreaWH_ := (bbwidth(TextAreas[i]),bbheight(TextAreas[i])) ;
+ fi ;
+ endfor ;
+ _TextAreaWH_
+enddef ;
+
+PageNumber := 0 ;
+PaperHeight := 845.04684pt ;
+PaperWidth := 597.50787pt ;
+PrintPaperHeight := 845.04684pt ;
+PrintPaperWidth := 597.50787pt ;
+TopSpace := 71.12546pt ;
+BottomSpace := 0.0pt ;
+BackSpace := 71.13275pt ;
+CutSpace := 0.0pt ;
+MakeupHeight := 711.3191pt ;
+MakeupWidth := 426.78743pt ;
+TopHeight := 0.0pt ;
+TopDistance := 0.0pt ;
+HeaderHeight := 56.90294pt ;
+HeaderDistance := 0.0pt ;
+TextHeight := 597.51323pt ;
+FooterDistance := 0.0pt ;
+FooterHeight := 56.90294pt ;
+BottomDistance := 0.0pt ;
+BottomHeight := 0.0pt ;
+LeftEdgeWidth := 0.0pt ;
+LeftEdgeDistance := 0.0pt ;
+LeftMarginWidth := 75.58197pt ;
+LeftMarginDistance := 11.99829pt ;
+TextWidth := 426.78743pt ;
+RightMarginDistance := 11.99829pt ;
+RightMarginWidth := 75.58197pt ;
+RightEdgeDistance := 0.0pt ;
+RightEdgeWidth := 0.0pt ;
+
+PageOffset := 0.0pt ;
+PageDepth := 0.0pt ;
+
+LayoutColumns := 0 ;
+LayoutColumnDistance:= 0.0pt ;
+LayoutColumnWidth := 0.0pt ;
+
+LeftEdge := -4 ; Top := -40 ;
+LeftEdgeSeparator := -3 ; TopSeparator := -30 ;
+LeftMargin := -2 ; Header := -20 ;
+LeftMarginSeparator := -1 ; HeaderSeparator := -10 ;
+Text := 0 ; Text := 0 ;
+RightMarginSeparator := +1 ; FooterSeparator := +10 ;
+RightMargin := +2 ; Footer := +20 ;
+RightEdgeSeparator := +3 ; BottomSeparator := +30 ;
+RightEdge := +4 ; Bottom := +40 ;
+
+Margin := LeftMargin ; % obsolete
+Edge := LeftEdge ; % obsolete
+InnerMargin := RightMargin ; % obsolete
+InnerEdge := RightEdge ; % obsolete
+OuterMargin := LeftMargin ; % obsolete
+OuterEdge := LeftEdge ; % obsolete
+
+InnerMarginWidth := 0pt ;
+OuterMarginWidth := 0pt ;
+InnerMarginDistance := 0pt ;
+OuterMarginDistance := 0pt ;
+
+InnerEdgeWidth := 0pt ;
+OuterEdgeWidth := 0pt ;
+InnerEdgeDistance := 0pt ;
+OuterEdgeDistance := 0pt ;
+
+path Area [][] ; pair Location [][] ; path Field [][] ; path Page ;
+numeric HorPos ; numeric Hstep [] ; numeric Hsize [] ;
+numeric VerPos ; numeric Vstep [] ; numeric Vsize [] ;
+
+for VerPos=Top step 10 until Bottom:
+ for HorPos=LeftEdge step 1 until RightEdge:
+ Area[HorPos][VerPos] := origin--cycle ;
+ Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+ Location[HorPos][VerPos] := origin ;
+ Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+ Field[HorPos][VerPos] := origin--cycle ;
+ Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+ endfor ;
+endfor ;
+
+% def LoadPageState =
+% scantokens "input mp-state.tmp" ;
+% enddef ;
+
+def SwapPageState =
+ if not OnRightPage :
+ BackSpace := PaperWidth-MakeupWidth-BackSpace ;
+ CutSpace := PaperWidth-MakeupWidth-CutSpace ;
+ i := LeftMarginWidth ;
+ LeftMarginWidth := RightMarginWidth ;
+ RightMarginWidth := i ;
+ i := LeftMarginDistance ;
+ LeftMarginDistance := RightMarginDistance ;
+ RightMarginDistance := i ;
+ i := LeftEdgeWidth ;
+ LeftEdgeWidth := RightEdgeWidth ;
+ RightEdgeWidth := i ;
+ i := LeftEdgeDistance ;
+ LeftEdgeDistance := RightEdgeDistance ;
+ RightEdgeDistance := i ;
+
+% these are now available as ..Width and ..Distance
+
+ Margin := LeftMargin ;
+ Edge := LeftEdge ;
+ InnerMargin := RightMargin ;
+ InnerEdge := RightEdge ;
+ OuterMargin := LeftMargin ;
+ OuterEdge := LeftEdge ;
+ else :
+ Margin := RightMargin ;
+ Edge := RightEdge ;
+ InnerMargin := LeftMargin ;
+ InnerEdge := LeftEdge ;
+ OuterMargin := RightMargin ;
+ OuterEdge := RightEdge ;
+ fi ;
+enddef ;
+
+def SetPageAreas =
+
+ numeric Vsize[], Hsize[], Vstep[], Hstep[] ;
+
+ Vsize[Top] = TopHeight ;
+ Vsize[TopSeparator] = TopDistance ;
+ Vsize[Header] = HeaderHeight ;
+ Vsize[HeaderSeparator] = HeaderDistance ;
+ Vsize[Text] = TextHeight ;
+ Vsize[FooterSeparator] = FooterDistance ;
+ Vsize[Footer] = FooterHeight ;
+ Vsize[BottomSeparator] = BottomDistance ;
+ Vsize[Bottom] = BottomHeight ;
+
+ Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ;
+ Vstep[TopSeparator] = PaperHeight-TopSpace ;
+ Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ;
+ Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ;
+ Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ;
+ Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ;
+ Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ;
+ Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ;
+ Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ;
+
+ Hsize[LeftEdge] = LeftEdgeWidth ;
+ Hsize[LeftEdgeSeparator] = LeftEdgeDistance ;
+ Hsize[LeftMargin] = LeftMarginWidth ;
+ Hsize[LeftMarginSeparator] = LeftMarginDistance ;
+ Hsize[Text] = MakeupWidth ;
+ Hsize[RightMarginSeparator] = RightMarginDistance ;
+ Hsize[RightMargin] = RightMarginWidth ;
+ Hsize[RightEdgeSeparator] = RightEdgeDistance ;
+ Hsize[RightEdge] = RightEdgeWidth ;
+
+ Hstep[LeftEdge] = Hstep[LeftEdgeSeparator] -Hsize[LeftEdge] ;
+ Hstep[LeftEdgeSeparator] = Hstep[LeftMargin] -Hsize[LeftEdgeSeparator] ;
+ Hstep[LeftMargin] = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ;
+ Hstep[LeftMarginSeparator] = Hstep[Text] -Hsize[LeftMarginSeparator] ;
+ Hstep[Text] = BackSpace ;
+ Hstep[RightMarginSeparator] = Hstep[Text] +Hsize[Text] ;
+ Hstep[RightMargin] = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ;
+ Hstep[RightEdgeSeparator] = Hstep[RightMargin] +Hsize[RightMargin] ;
+ Hstep[RightEdge] = Hstep[RightEdgeSeparator] +Hsize[RightEdgeSeparator] ;
+
+ for VerPos=Top step 10 until Bottom:
+ for HorPos=LeftEdge step 1 until RightEdge:
+ Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
+ Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+ Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
+ Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+ Field[HorPos][VerPos] := Area[HorPos][VerPos] shifted Location[HorPos][VerPos] ;
+ Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+ endfor ;
+ endfor ;
+
+ Page := unitsquare xscaled PaperWidth yscaled PaperHeight ;
+
+enddef ;
+
+def BoundPageAreas =
+
+ % pickup pencircle scaled 0pt ;
+
+ bboxmargin := 0 ; setbounds currentpicture to Page ;
+
+enddef ;
+
+def StartPage =
+
+ if PageStateAvailable :
+ LoadPageState ;
+ SwapPageState ;
+ fi ;
+
+ SetPageAreas ;
+ BoundPageAreas ;
+
+enddef ;
+
+def StopPage =
+
+ BoundPageAreas ;
+
+enddef ;
+
+def OverlayBox =
+ (unitsquare xyscaled (OverlayWidth,OverlayHeight))
+enddef ;
+
+% handy
+
+def innerenlarged =
+ hide(LoadPageState)
+ if OnRightPage : leftenlarged else : rightenlarged fi
+enddef ;
+
+def outerenlarged =
+ hide(LoadPageState)
+ if OnRightPage : rightenlarged else : leftenlarged fi
+enddef ;
+
+% obsolete
+
+def llEnlarged (expr p,d) = (llcorner p shifted (-d,-d)) enddef ;
+def lrEnlarged (expr p,d) = (lrcorner p shifted (+d,-d)) enddef ;
+def urEnlarged (expr p,d) = (urcorner p shifted (+d,+d)) enddef ;
+def ulEnlarged (expr p,d) = (ulcorner p shifted (-d,+d)) enddef ;
+
+def Enlarged (expr p, d) =
+ (llEnlarged (p,d) --
+ lrEnlarged (p,d) --
+ urEnlarged (p,d) --
+ ulEnlarged (p,d) -- cycle)
+enddef ;
+
+% New:
+
+def position_anchor_bar(expr p_b_self, p_e_self, y_b_self, y_e_self, h_b_self, d_e_self,
+ distance, linewidth, linecolor) =
+ StartPage ;
+ path p ; p :=
+ if p_b_self=p_e_self :
+ (xpart ulcorner Field[Text][Text],y_b_self+h_b_self) --
+ (xpart llcorner Field[Text][Text],y_e_self-d_e_self) ;
+ elseif RealPageNumber=p_b_self :
+ (xpart ulcorner Field[Text][Text],y_b_self+h_b_self) --
+ (llcorner Field[Text][Text]) ;
+ elseif RealPageNumber=p_e_self :
+ (ulcorner Field[Text][Text]) --
+ (xpart llcorner Field[Text][Text],y_e_self-d_e_self) ;
+ else :
+ (ulcorner Field[Text][Text]) --
+ (llcorner Field[Text][Text]) ;
+ fi ;
+ p := p shifted (-llcorner Field[Text][Text]-(distance,0)) ;
+ interim linecap := butt ;
+ draw p
+ withpen pencircle scaled linewidth
+ withcolor linecolor ;
+ StopPage ;
+enddef ;
+
+endinput ;
diff --git a/metapost/context/base/mp-shap.mp b/metapost/context/base/mp-shap.mp
new file mode 100644
index 000000000..0f5fe431d
--- /dev/null
+++ b/metapost/context/base/mp-shap.mp
@@ -0,0 +1,307 @@
+%D \module
+%D [ file=mp-shap.mp,
+%D version=2000.05.31,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=shapes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_shap : endinput ; fi ;
+
+boolean context_shap ; context_shap := true ;
+
+vardef some_shape_path (expr type) =
+
+ begingroup ;
+
+ save border, xradius, yradius,
+ normal, mirror, rotate,
+ lc, rc, tc, bc, ll, lr, ur, ul,
+ llx, lrx, urx, ulx, lly, lry, ury, uly ;
+
+ path border ;
+
+ xradius := .15 ; xxradius := .10 ;
+ yradius := .15 ; yyradius := .10 ;
+
+ pair ll ; ll := llcorner (unitsquare shifted (-.5,-.5)) ;
+ pair lr ; lr := lrcorner (unitsquare shifted (-.5,-.5)) ;
+ pair ur ; ur := urcorner (unitsquare shifted (-.5,-.5)) ;
+ pair ul ; ul := ulcorner (unitsquare shifted (-.5,-.5)) ;
+
+ pair llx ; llx := ll shifted (xradius,0) ;
+ pair lly ; lly := ll shifted (0,yradius) ;
+
+ pair lrx ; lrx := lr shifted (-xradius,0) ;
+ pair lry ; lry := lr shifted (0,yradius) ;
+
+ pair urx ; urx := ur shifted (-xradius,0) ;
+ pair ury ; ury := ur shifted (0,-yradius) ;
+
+ pair ulx ; ulx := ul shifted (xradius,0) ;
+ pair uly ; uly := ul shifted (0,-yradius) ;
+
+ pair llxx ; llxx := ll shifted (xxradius,0) ;
+ pair llyy ; llyy := ll shifted (0,yyradius) ;
+
+ pair lrxx ; lrxx := lr shifted (-xxradius,0) ;
+ pair lryy ; lryy := lr shifted (0,yyradius) ;
+
+ pair urxx ; urxx := ur shifted (-xxradius,0) ;
+ pair uryy ; uryy := ur shifted (0,-yyradius) ;
+
+ pair ulxx ; ulxx := ul shifted (xxradius,0) ;
+ pair ulyy ; ulyy := ul shifted (0,-yyradius) ;
+
+ pair lc ; lc := ll shifted (0,.5) ;
+ pair rc ; rc := lr shifted (0,.5) ;
+ pair tc ; tc := ul shifted (.5,0) ;
+ pair bc ; bc := ll shifted (.5,0) ;
+
+ def mirror (expr p) =
+ p rotatedaround(origin,180)
+ enddef ;
+
+ def normal (expr p ) =
+ p
+ enddef ;
+
+ def rotate (expr p) =
+ p rotated 45
+ enddef ;
+
+ if type= 0 :
+ border := normal (origin--cycle) ;
+
+ elseif type= 5 :
+ border := normal (llx--lrx{right}...rc...{left}urx--ulx{left}...lc...{right}cycle) ;
+ elseif type= 6 :
+ border := normal (ll--lrx{right}...rc...{left}urx--ul--cycle) ;
+ elseif type= 7 :
+ border := mirror (ll--lrx{right}...rc...{left}urx--ul--cycle) ;
+ elseif type= 8 :
+ border := normal (lr--ury{up}...tc...{down}uly--ll--cycle) ;
+ elseif type= 9 :
+ border := mirror (lr--ury{up}...tc...{down}uly--ll--cycle) ;
+ elseif type=10 :
+ border := normal (ll--lr--ur--ul--ll--ur--ul--ll--cycle) ;
+ elseif type=11 :
+ border := normal (ll--lr--ur--ul--ll--lr--ul--ll--cycle) ;
+ elseif type=12 :
+ border := normal (ll--lrx--ur--ulx--cycle) ;
+ elseif type=13 :
+ border := normal (llx--lr--urx--ul--cycle) ;
+ elseif type=14 :
+ border := normal (lly--bc--lry--ury--tc--uly--cycle) ;
+ elseif type=15 :
+ border := normal (llx--lrx--rc--urx--ulx--lc--cycle) ;
+ elseif type=16 :
+ border := normal (ll--lrx--rc--urx--ul--cycle) ;
+ elseif type=17 :
+ border := mirror (ll--lrx--rc--urx--ul--cycle) ;
+ elseif type=18 :
+ border := normal (lr--ury--tc--uly--ll--cycle) ;
+ elseif type=19 :
+ border := mirror (lr--ury--tc--uly--ll--cycle) ;
+ elseif type=20 :
+ border := normal (ll--lr--ur--ul--ll--llxx--ulxx--ul--ll--
+ lr--ur--urxx--lrxx--cycle) ;
+ elseif type=21 :
+ border := normal (ul--ll--lr--ur--ul--ulyy--uryy--ur--ul--
+ ll--lr--lryy--llyy--cycle) ;
+ elseif type=22 :
+ border := normal (ll--lrx--lry--ur--ulx--uly--cycle) ;
+ elseif type=23 :
+ border := normal (llx--lr--ury--urx--ul--lly--cycle) ;
+ elseif type=24 :
+ border := normal (ll--lr--ur--ul--cycle) ;
+ elseif type=25 :
+ border := normal (llx--lrx--lry--ury--urx--ulx--uly--lly--cycle) ;
+ elseif type=26 :
+ border := normal (ll--lrx--lry--ur--ul--cycle) ;
+ elseif type=27 :
+ border := mirror (ll--lr--ury--urx--ul--cycle) ;
+ elseif type=28 :
+ border := normal (ll--lr--ury--urx--ul--cycle) ;
+ elseif type=29 :
+ border := mirror (ll--lrx--lry--ur--ul--cycle) ;
+ elseif type=30 :
+ border := rotate (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc &
+ bc--tc & tc{left}..{down}lc & lc--rc &
+ rc{up}..tc{left}...{down}lc...{right}bc & cycle) ;
+ elseif type=31 :
+ border := normal (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc &
+ bc--tc & tc{left}..{down}lc & lc--rc &
+ rc{up}..tc{left}...{down}lc...{right}bc & cycle) ;
+ elseif type=32 :
+ border := normal (ll{right}...{right}lry--ur--ul--ll--cycle) ;
+ elseif type=33 :
+ border := normal (ll{right}...{right}lry--ur--ul--ll--cycle
+ --ul--ulx--ulx shifted(0,yyradius)
+ --ur shifted(yyradius,yyradius)
+ --lry shifted(yyradius,yyradius)
+ --lry shifted(0,yyradius)
+ --ur--ul--cycle ) ;
+ elseif type=34 :
+ border := normal (uly..tc..ury &
+ ury..tc shifted (0,-2yradius)..uly &
+ uly--lly &
+ lly..bc..lry &
+ lry--ury &
+ ury..tc shifted (0,-2yradius)..uly & cycle ) ;
+ elseif type=35 :
+ border := normal (bc{right}...rc{up}...tc{left}...lc{down}...cycle) ;
+ elseif type=36 :
+ border := normal (ul--tc{right}..rc{down}..{left}bc--ll &
+ ll..(xpart llx, ypart lc)..ul & cycle) ;
+ elseif type=37 :
+ border := mirror (ul--tc{right}..rc{down}..{left}bc--ll &
+ ll..(xpart llx, ypart lc)..ul & cycle) ;
+ elseif type=38 :
+ border := normal (ll--lc{up}..tc{right}..{down}rc--lr &
+ lr..(xpart bc, ypart lly)..ll & cycle) ;
+ elseif type=39 :
+ border := mirror (ll--lc{up}..tc{right}..{down}rc--lr &
+ lr..(xpart bc, ypart lly)..ll & cycle) ;
+ elseif type=40 :
+ border := normal (ll--lr--ur--ul--ll--ur--ul--ll--lr--ul--ll--cycle) ;
+ elseif type=41 :
+ border := normal (ll--lr--ur--ul--ll--lr--rc--lc--ll--bc--tc--ul--ll & cycle) ;
+ elseif type=42 :
+ border := normal (ll--lr--origin shifted (+epsilon,0)--
+ ur--ul--origin shifted (-epsilon,0)--cycle) ;
+ elseif type=43 :
+ border := normal (ll--ul--origin shifted (0,+epsilon)--
+ ur--lr--origin shifted (0,-epsilon)--cycle) ;
+ elseif type=45 :
+ border := normal (bc--rc--tc--lc--cycle) ;
+ elseif type=46 :
+ border := normal (ll--ul--rc--cycle) ;
+ elseif type=47 :
+ border := mirror (ll--ul--rc--cycle) ;
+ elseif type=48 :
+ border := mirror (ul--ur--bc--cycle) ;
+ elseif type=49 :
+ border := normal (ul--ur--bc--cycle) ;
+
+ elseif type=56 :
+ border := normal (ll--lry--ury--ul--cycle) ;
+ elseif type=57 :
+ border := mirror (ll--lry--ury--ul--cycle) ;
+ elseif type=58 :
+ border := normal (ll--ulx--urx--lr--cycle) ;
+ elseif type=59 :
+ border := mirror (ll--ulx--urx--lr--cycle) ;
+
+ elseif type=61 :
+ border := normal (fullcircle scaled (1.5*yradius) xscaled (grid_height/grid_width)) ;
+ elseif type=62 :
+ border := normal (fullcircle scaled (2.0*yradius) xscaled (grid_height/grid_width)) ;
+
+ elseif type=66 :
+ border := normal (rc--origin shifted ( epsilon,0) --cycle &
+ rc--origin --cycle ) ;
+ elseif type=67 :
+ border := normal (lc--origin shifted (-epsilon,0) --cycle &
+ lc--origin --cycle ) ;
+ elseif type=68 :
+ border := normal (tc--origin shifted (0, epsilon) --cycle &
+ tc--origin --cycle ) ;
+ elseif type=69 :
+ border := normal (bc--origin shifted (0,-epsilon) --cycle &
+ bc--origin --cycle ) ;
+
+ elseif type=75 :
+ border := mirror (lly--lry--ury--uly--cycle) ;
+ elseif type=76 :
+ border := mirror (ll--lr--ur--uly--cycle) ;
+ elseif type=77 :
+ border := mirror (ll--lr--ury--ul--cycle) ;
+ elseif type=78 :
+ border := mirror (lly--lr--ur--ul--cycle) ;
+ elseif type=79 :
+ border := mirror (ll--lry--ur--ul--cycle) ;
+
+ else :
+ border := normal (origin--cycle) ;
+ %border := normal (ll--lr--ur--ul--cycle) ;
+ fi ;
+
+ border
+
+ endgroup
+
+enddef;
+
+def some_shape ( expr shape_type ,
+ shape_width ,
+ shape_height ,
+ shape_linewidth ,
+ shape_linecolor ,
+ shape_fillcolor ) =
+
+ path p ; p :=
+ some_shape_path (shape_type)
+ xscaled shape_width
+ yscaled shape_height ;
+
+ pickup pencircle scaled shape_linewidth ;
+
+ fill p withcolor shape_fillcolor ;
+ draw p withcolor shape_linecolor ;
+
+enddef ;
+
+vardef drawshape (expr t, p, lw, lc, fc) =
+ save pp ;
+ if t>1 : % normal shape
+ path pp ;
+ pp := some_shape_path(t) xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ fill pp withcolor fc ;
+ draw pp withpen pencircle scaled lw withcolor lc ;
+ elseif t=1 : % background only
+ path pp ;
+ pp := fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ fill pp withcolor fc ;
+ else : % dimensions only
+ picture pp ; pp := nullpicture ;
+ setbounds pp to fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ draw pp ;
+ fi ;
+enddef ;
+
+vardef drawline (expr t, p, lw, lc) =
+ if (t>0) and (length(p)>1) :
+ saveoptions ;
+ drawoptions(withpen pencircle scaled lw withcolor lc) ;
+ draw p ;
+ if t = 1 :
+ draw arrowheadonpath(p,1) ;
+ elseif t = 2 :
+ draw arrowheadonpath(reverse p,1) ;
+ elseif t = 3 :
+ for $ = p,reverse p : draw arrowheadonpath($,1) ; endfor ;
+ elseif t = 11 :
+ draw arrowheadonpath(p,1/2) ;
+ elseif t = 12 :
+ draw arrowheadonpath(reverse p,1/2) ;
+ elseif t = 13 :
+ for $=p,reverse p : draw arrowheadonpath($,1) ; endfor ;
+ for $=p,reverse p : draw arrowheadonpath($,3/4) ; endfor ;
+ elseif t = 21 :
+ for $=1/5,1/2,4/5 : draw arrowheadonpath(p,$) ; endfor ;
+ elseif t = 22 :
+ for $=1/5,1/2,4/5 : draw arrowheadonpath(reverse p,$) ; endfor ;
+ elseif t = 23 :
+ for $=p,reverse p : draw arrowheadonpath($,1/4) ; endfor ;
+ fi ;
+ fi ;
+enddef ;
+
+endinput ;
diff --git a/metapost/context/base/mp-spec.mp b/metapost/context/base/mp-spec.mp
new file mode 100644
index 000000000..9125b4b8b
--- /dev/null
+++ b/metapost/context/base/mp-spec.mp
@@ -0,0 +1,776 @@
+%D \module
+%D [ file=mp-spec.mp,
+%D version=1999.6.26,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=special extensions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+% Spot colors are not handled by mptopdf !
+
+% let graycolor = numeric ;
+% let greycolor = numeric ;
+% let withanycolor = withcolor ;
+
+% rgbcolor red ; red := (1,0,0) ;
+% rgbcolor green ; green := (0,1,0) ;
+% rgbcolor blue ; blue := (0,0,1) ;
+% cmykcolor cyan ; cyan := (1,0,0,0) ;
+% cmykcolor magenta ; magenta := (0,1,0,0) ;
+% cmykcolor yellow ; yellow := (0,0,1,0) ;
+% graycolor black ; black := 0 ; % (0) ;
+% graycolor white ; white := 1 ; % (1) ;
+
+% primarydef p withcolor c =
+% p withanycolor (c)
+% enddef ;
+
+% fill fullcircle scaled 10cm withcolor cyan ;
+% fill fullcircle scaled 7cm withcolor red ;
+% fill fullcircle scaled 4cm withcolor white ;
+
+% (r,g,b) => cmyk : r=123 g= 1 b=hash
+% => spot : r=123 g= 2 b=hash
+% => transparent rgb : r=123 g= 3 b=hash
+% => transparent cmyk : r=123 g= 4 b=hash
+% => transparent spot : r=123 g= 5 b=hash
+% => rest : r=123 g=n>10 b=whatever
+
+%D This module is rather preliminary and subjected to
+%D changes. Here we closely cooperates with the \METAPOST\
+%D to \PDF\ converter module built in \CONTEXT\ and provides
+%D for instance shading. More information can be found in
+%D type {supp-mpe.tex}.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_spec : endinput ; fi ;
+
+boolean context_spec ; context_spec := true ;
+
+numeric _special_counter_ ; _special_counter_ := 0 ;
+numeric _color_counter_ ; _color_counter_ := 11 ; % < 10 reserved
+numeric _special_signal_ ; _special_signal_ := 123 ;
+
+numeric _special_div_ ; _special_div_ := 1000 ;
+
+%D When set to \type {true}, shading will be supported. Some
+%D day I will also write an additional directive.
+
+boolean _inline_specials_ ; _inline_specials_ := false ;
+
+%D Because we want to output only those specials that are
+%D actually used in a figure, we need a bit complicated
+%D bookkeeping and collection of specials. At the cost of some
+%D obscurity, we now have rather efficient resources.
+
+string _global_specials_ ; _global_specials_ := "" ;
+string _local_specials_ ; _local_specials_ := "" ;
+
+% vardef add_special_signal = % write the version number
+% if (length _global_specials_>0) or (length _local_specials_ >0) :
+% special ("%%MetaPostSpecials: 1.0 " & decimal _special_signal_ ) ;
+% fi ;
+% enddef ;
+%
+% After some reported problems at the \CONTEXT\ mailing list,
+% Taco's came up with:
+
+% TH: \quotation {Ok, got it. There is a bug in mp-spec.mp (inside metafun).
+% Because of a wrapping number, it fails to recognize the fact that there
+% are embedded specials at all.} The corrected definition is:
+
+vardef add_special_signal = % write the version number
+ if (length _global_specials_ <> 0) or (length _local_specials_ <> 0) :
+ special ("%%MetaPostSpecials: 2.0 " & decimal _special_signal_ & " " & decimal _special_div_) ;
+ fi ;
+enddef ;
+
+% \quotation {It now tests for \quote {not equal to zero} instead of
+% \quote {larger than zero}: because of all the included files, the
+% string \type {_local_specials_} becomes longer than the maximum number
+% \quote {length} can return, so it returns -32768 instead, and that is
+% of course less than zero.}
+
+vardef add_extra_specials =
+ scantokens _global_specials_ ;
+ scantokens _local_specials_ ;
+enddef ;
+
+vardef reset_extra_specials =
+ % only local ones
+ _local_specials_ := "" ;
+enddef ;
+
+boolean insidefigure ; insidefigure := false ;
+
+% todo: alleen als special gebruikt flush
+
+extra_beginfig :=
+ " insidefigure := true ; " &
+ " reset_extra_specials ; " &
+ extra_beginfig &
+ " ; " ;
+
+extra_endfig :=
+ " ; " &
+ " add_special_signal ; " &
+ extra_endfig &
+ " add_extra_specials ; " &
+ " reset_extra_specials ; " &
+ " insidefigure := false ; " ;
+
+def set_extra_special (expr s) =
+ if insidefigure :
+ _local_specials_ := _local_specials_ & s ;
+ else :
+ _global_specials_ := _global_specials_ & s ;
+ fi
+enddef ;
+
+def flush_special (expr typ, siz, dat) =
+ _special_counter_ := _special_counter_ + 1 ;
+ if _inline_specials_ :
+ set_extra_special
+ ( "special "
+ & "(" & ditto
+ & dat & " "
+ & decimal _special_counter_ & " "
+ & decimal typ & " "
+ & decimal siz
+ & " special"
+ & ditto & ");" ) ;
+ else :
+ set_extra_special
+ ( "special "
+ & "(" & ditto
+ & "%%MetaPostSpecial: "
+ & decimal siz & " "
+ & dat & " "
+ & decimal _special_counter_ & " "
+ & decimal typ
+ & ditto & ");" ) ;
+ fi ;
+enddef ;
+
+%D The next hack is needed in case you use a version of
+%D \METAPOST\ that does not provide you the means to configure
+%D the buffer size. Patrick Gundlach suggested to use arrays
+%D in this case.
+
+boolean bufferhack ; bufferhack := false ; % true ;
+
+if bufferhack :
+
+ string _global_specials_[] ; numeric _nof_global_specials_ ;
+ string _local_specials_[] ; numeric _nof_local_specials_ ;
+
+ _nof_global_specials_ := _nof_local_specials_ := 0 ;
+
+ vardef add_special_signal = % write the version number
+ if (_nof_global_specials_>0) or (_nof_local_specials_>0) :
+ special ("%%MetaPostSpecials: 1.0 " & decimal _special_signal_ ) ;
+ fi ;
+ enddef ;
+
+ vardef add_extra_specials =
+ for i=1 upto _nof_global_specials_ :
+ scantokens _global_specials_[i] ;
+ endfor;
+ for i=1 upto _nof_local_specials_ :
+ scantokens _local_specials_[i] ;
+ endfor;
+ enddef ;
+
+ vardef reset_extra_specials =
+ string _local_specials_[] ; _nof_local_specials_ := 0 ;
+ enddef ;
+
+ def set_extra_special (expr s) =
+ if insidefigure :
+ _local_specials_[incr(_nof_local_specials_)] := s ;
+ else :
+ _global_specials_[incr(_nof_global_specials_)] := s ;
+ fi
+ enddef ;
+
+fi ;
+
+%D So far for this hack.
+
+%D Shade allocation.
+
+newinternal shadefactor ; shadefactor := 1 ;
+
+pair shadeoffset ; shadeoffset := origin ;
+
+% vardef define_linear_shade (expr a, b, ca, cb) =
+% flush_special(30, 15, "0 1 " & decimal shadefactor & " " &
+% dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " &
+% dddecimal cb & " " & ddecimal (b shifted shadeoffset) ) ;
+% _special_counter_
+% enddef ;
+
+% vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
+% flush_special(31, 17, "0 1 " & decimal shadefactor & " " &
+% dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+% dddecimal cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+% _special_counter_
+% enddef ;
+
+% these tests are not yet robust for new gray/cmyk features;
+%
+% - we need to get rid of cmykcolor() and
+
+vardef _is_cmyk_(expr c) =
+ (redpart c = _special_signal_/_special_div_) and (greenpart c = 1/_special_div_)
+enddef ;
+vardef _is_spot_(expr c) =
+ (redpart c = _special_signal_/_special_div_) and (greenpart c = 2/_special_div_)
+enddef ;
+vardef _is_gray_(expr c) =
+ (redpart c = greenpart c) and (greenpart c = bluepart c)
+enddef ;
+
+numeric mp_shade_version ; mp_shade_version := 2 ; % more colors, needs new backend
+
+vardef define_linear_shade (expr a, b, ca, cb) =
+ save cmyk_a, cmyk_b ; boolean cmyk_a, cmyk_b ;
+ save gray_a, gray_b ; boolean gray_a, gray_b ;
+ cmyk_a := _is_cmyk_(ca) ; gray_a := _is_gray_(ca) ;
+ cmyk_b := _is_cmyk_(cb) ; gray_b := _is_gray_(cb) ;
+ if (mp_shade_version > 1) and cmyk_a and cmyk_b :
+ flush_special(32, 17, "0 1 " & decimal shadefactor & " " &
+ cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " &
+ cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ;
+ elseif (mp_shade_version > 1) and cmyk_a and gray_b :
+ save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart cb) ;
+ flush_special(32, 17, "0 1 " & decimal shadefactor & " " &
+ cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " &
+ cmykcolorpattern[bluepart cg] & " " & ddecimal (b shifted shadeoffset) ) ;
+ elseif (mp_shade_version > 1) and gray_a and cmyk_b :
+ save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart ca) ;
+ flush_special(32, 17, "0 1 " & decimal shadefactor & " " &
+ cmykcolorpattern[bluepart cg] & " " & ddecimal (a shifted shadeoffset) & " " &
+ cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ;
+ elseif (mp_shade_version > 1) and _is_spot_(ca) and _is_spot_(cb) :
+ flush_special(34, 17, "0 1 " & decimal shadefactor & " " &
+ spotcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " &
+ spotcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ;
+ else :
+ flush_special(30, 15, "0 1 " & decimal shadefactor & " " &
+ dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " &
+ dddecimal cb & " " & ddecimal (b shifted shadeoffset) ) ;
+ fi ;
+ _special_counter_
+enddef ;
+
+vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
+ save cmyk_a, cmyk_b ; boolean cmyk_a, cmyk_b ;
+ save gray_a, gray_b ; boolean gray_a, gray_b ;
+ cmyk_a := _is_cmyk_(ca) ; gray_a := _is_gray_(ca) ;
+ cmyk_b := _is_cmyk_(cb) ; gray_b := _is_gray_(cb) ;
+ if (mp_shade_version > 1) and cmyk_a and cmyk_b :
+ flush_special(33, 19, "0 1 " & decimal shadefactor & " " &
+ cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+ elseif (mp_shade_version > 1) and cmyk_a and gray_b :
+ save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart cb) ;
+ flush_special(33, 19, "0 1 " & decimal shadefactor & " " &
+ cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ cmykcolorpattern[bluepart cg] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+ elseif (mp_shade_version > 1) and gray_a and cmyk_b :
+ save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart ca) ;
+ flush_special(33, 19, "0 1 " & decimal shadefactor & " " &
+ cmykcolorpattern[bluepart cg] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+ elseif (mp_shade_version > 1) and _is_spot_(ca) and _is_spot_(cb) :
+ flush_special(35, 19, "0 1 " & decimal shadefactor & " " &
+ spotcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ spotcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+ else :
+ flush_special(31, 17, "0 1 " & decimal shadefactor & " " &
+ dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ dddecimal cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+ fi ;
+ _special_counter_
+enddef ;
+
+%D A few predefined shading macros.
+
+boolean trace_shades ; trace_shades := false ;
+
+% if (n=1) : a := llcorner p ; b := urcorner p ;
+% elseif (n=2) : a := llcorner p ; b := ulcorner p ;
+% elseif (n=3) : a := lrcorner p ; b := ulcorner p ;
+% else : a := llcorner p ; b := lrcorner p ;
+% fi ;
+
+def set_linear_vector (suffix a,b)(expr p,n) =
+ if (n=1) : a := llcorner p ;
+ b := urcorner p ;
+ elseif (n=2) : a := lrcorner p ;
+ b := ulcorner p ;
+ elseif (n=3) : a := urcorner p ;
+ b := llcorner p ;
+ elseif (n=4) : a := ulcorner p ;
+ b := lrcorner p ;
+ elseif (n=5) : a := .5[ulcorner p,llcorner p] ;
+ b := .5[urcorner p,lrcorner p] ;
+ elseif (n=6) : a := .5[llcorner p,lrcorner p] ;
+ b := .5[ulcorner p,urcorner p] ;
+ elseif (n=7) : a := .5[lrcorner p,urcorner p] ;
+ b := .5[llcorner p,ulcorner p] ;
+ elseif (n=8) : a := .5[urcorner p,ulcorner p] ;
+ b := .5[lrcorner p,llcorner p] ;
+ else : a := .5[ulcorner p,llcorner p] ;
+ b := .5[urcorner p,lrcorner p] ;
+ fi ;
+enddef ;
+
+def set_circular_vector (suffix ab, r)(expr p,n) =
+ if (n=1) : ab := llcorner p ;
+ elseif (n=2) : ab := lrcorner p ;
+ elseif (n=3) : ab := urcorner p ;
+ elseif (n=4) : ab := ulcorner p ;
+ else : ab := center p ; r := .5r ;
+ fi ;
+enddef ;
+
+def linear_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save a, b, sh ; pair a, b ;
+ set_linear_vector(a,b)(p,n) ;
+ fill p withshade define_linear_shade (a,b,ca,cb) ;
+ if trace_shades :
+ drawarrow a -- b withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+
+def circular_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save ab, r ; pair ab ; numeric r ;
+ r := (xpart lrcorner p - xpart llcorner p) ++
+ (ypart urcorner p - ypart lrcorner p) ;
+ set_circular_vector(ab,r)(p,n) ;
+ fill p withshade define_circular_shade(ab,ab,0,r,ca,cb) ;
+ if trace_shades :
+ drawarrow ab -- ab shifted (0,r) withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+
+vardef predefined_linear_shade (expr p, n, ca, cb) =
+ save a, b, sh ; pair a, b ;
+ set_linear_vector(a,b)(p,n) ;
+ set_shade_vector(a,b)(p,n) ;
+ define_linear_shade (a,b,ca,cb)
+enddef ;
+
+vardef predefined_circular_shade (expr p, n, ca, cb) =
+ save ab, r ; pair ab ; numeric r ;
+ r := (xpart lrcorner p - xpart llcorner p) ++
+ (ypart urcorner p - ypart lrcorner p) ;
+ set_circular_vector(ab,r)(p,n) ;
+ define_circular_shade(ab,ab,0,r,ca,cb)
+enddef ;
+
+%D Since a \type {fill p withshade s} syntax looks better
+%D than some macro, we implement a new primary.
+
+primarydef p withshade sc = % == p withcolor shadecolor(sh)
+ hide (_color_counter_ := _color_counter_ + 1)
+ p withcolor (_special_signal_/_special_div_,_color_counter_/_special_div_,sc/_special_div_)
+enddef ;
+
+vardef shadecolor(expr sc) =
+ hide (_color_counter_ := _color_counter_ + 1)
+ (_special_signal_/_special_div_,_color_counter_/_special_div_,sc/_special_div_)
+enddef ;
+
+%D Figure inclusion.
+
+%numeric cef ; cef := 0 ;
+
+def externalfigure primary filename =
+ doexternalfigure (filename)
+enddef ;
+
+def doexternalfigure (expr filename) text transformation =
+ begingroup ; save p, t ; picture p ; transform t ;
+ p := nullpicture ; t := identity transformation ;
+ flush_special(10, 9,
+ dddecimal (xxpart t, yxpart t, xypart t) & " " &
+ dddecimal (yypart t, xpart t, ypart t) & " " & filename) ;
+ addto p contour unitsquare scaled 0 ;
+ setbounds p to unitsquare transformed t ;
+ _color_counter_ := _color_counter_ + 1 ;
+ draw p withcolor (_special_signal_/_special_div_,_color_counter_/_special_div_,_special_counter_/_special_div_) ;
+ endgroup ;
+enddef ;
+
+%D Experimental:
+
+%numeric currenthyperlink ; currenthyperlink := 0 ;
+
+def hyperlink primary t = dohyperlink(t) enddef ;
+def hyperpath primary t = dohyperpath(t) enddef ;
+
+def dohyperlink (expr destination) text transformation =
+ begingroup ; save somepath ; path somepath ;
+ somepath := fullsquare transformation ;
+ dohyperpath(destination) somepath ;
+ endgroup ;
+enddef ;
+
+def dohyperpath (expr destination) expr somepath =
+ begingroup ;
+ flush_special(20, 7,
+ ddecimal (xpart llcorner somepath, ypart llcorner somepath) & " " &
+ ddecimal (xpart urcorner somepath, ypart urcorner somepath) & " " & destination) ;
+ _color_counter_ := _color_counter_ + 1 ;
+ fill boundingbox unitsquare scaled 0 withcolor
+ (_special_signal_/_special_div_,_color_counter_/_special_div_,_special_counter_/_special_div_) ;
+ endgroup ;
+enddef ;
+
+% \setupinteraction[state=start]
+% \setupcolors [state=start]
+%
+% Hello There! \blank
+%
+% \startMPcode
+% pickup pencircle scaled 5 ;
+% draw fullcircle scaled 4cm withcolor red ;
+% hyperpath "nextpage" boundingbox currentpicture ;
+% draw origin withcolor blue ;
+% \stopMPcode
+%
+% \blank Does it work or not?
+%
+% \startMPcode
+% pickup pencircle scaled 5 ;
+% draw fullcircle scaled 4cm withcolor red ;
+% hyperpath "nextpage" fullcircle scaled 4cm ;
+% draw origin withcolor blue ;
+% draw fullcircle scaled 4cm shifted (1cm,1cm);
+% \stopMPcode
+%
+% \blank Does it work or not? \page Hello There! \blank
+%
+% \startMPcode
+% pickup pencircle scaled 5 ;
+% draw fullcircle scaled 2cm shifted (-2cm,-1cm) ;
+% draw fullcircle scaled 3cm shifted (2cm,1cm) withcolor red ;
+% draw fullcircle scaled 1cm ;
+% hyperlink "previouspage" scaled 3cm shifted (2cm,1cm) ;
+% draw origin withcolor blue ;
+% \stopMPcode
+%
+% \blank Does it work or not?
+
+_cmyk_counter_ := 0 ;
+
+extra_endfig := " ; resetcmykcolors ; " & extra_endfig ;
+
+def resetcmykcolors =
+ numeric cmykcolorhash[][][][] ;
+enddef ;
+
+resetcmykcolors ; boolean cmykcolors ; cmykcolors := false ; % true
+
+string cmykcolorpattern[] ; % needed for transparancies
+
+vardef cmyk(expr c,m,y,k) =
+ if cmykcolors :
+ save ok ; boolean ok ;
+ if unknown cmykcolorhash[c][m][y][k] :
+ ok := false ; % not yet defined
+ elseif cmykcolorhash[c][m][y][k] = -1 :
+ ok := false ; % locally defined and undefined
+ else :
+ ok := true ; % globally already defined
+ fi ;
+ if not ok :
+% save s ; string s ; s := dddecimal (c,m,y) & " " & decimal k ;
+ save s ; string s ; s := ddddecimal (c,m,y,k) ;
+ _cmyk_counter_ := _cmyk_counter_ + 1 ;
+ cmykcolorpattern[_cmyk_counter_/_special_div_] := s ;
+ cmykcolorhash[c][m][y][k] := _cmyk_counter_ ;
+ flush_special(1, 7, decimal _cmyk_counter_ & " " & s) ;
+ _local_specials_ := _local_specials_ &
+ " cmykcolorhash[" & decimal c & "][" & decimal m &
+ "][" & decimal y & "][" & decimal k & "] := -1 ; " ;
+ fi ;
+ (_special_signal_/_special_div_,1/_special_div_,cmykcolorhash[c][m][y][k]/_special_div_)
+ else :
+ (1-c-k,1-m-k,1-y-k)
+ fi
+enddef ;
+
+% newcolor truecyan, truemagenta, trueyellow ;
+%
+% truecyan = (1,0,0,0) ;
+% truemagenta = (0,1,0,0) ;
+% trueyellow = (0,0,1,0) ;
+
+%D Spot colors
+
+_spotcolor_counter_ := 0 ;
+_spotcolor_number_ := 0 ;
+
+extra_endfig := " ; resetspotcolors ; " & extra_endfig ;
+
+def resetspotcolors =
+ numeric spotcolorhash[][] ;
+enddef ;
+
+resetspotcolors ; boolean spotcolors ; spotcolors := false ; % true
+
+string spotcolorpattern[] ; % needed for transparancies
+
+vardef spotcolor(expr p, s) =
+ multitonecolor(p, 1, "", decimal s)
+enddef ;
+
+vardef multitonecolor(expr n, f, d, p) = % name fractions names factors
+ if spotcolors :
+ save ok, pc_tag ; boolean ok ; string pc_tag ;
+ pc_tag := "_pct_" & n ;
+ if not unstringed(pc_tag) :
+ _spotcolor_number_ := _spotcolor_number_ + 1 ;
+ setunstringed(pc_tag,_spotcolor_number_) ;
+ fi ;
+ pp := getunstringed(pc_tag) ;
+ pc_tag := "_pct_"& decimal f & "_" & if d = "" : n else : d fi & "_" & p ; % check for d empty
+ if not unstringed(pc_tag) :
+ _spotcolor_number_ := _spotcolor_number_ + 1 ;
+ setunstringed(pc_tag,_spotcolor_number_) ;
+ fi ;
+ ps := getunstringed(pc_tag) ;
+ if unknown spotcolorhash[pp][ps] :
+ ok := false ; % not yet defined
+ elseif spotcolorhash[pp][ps] = -1 :
+ ok := false ; % locally defined and undefined
+ else :
+ ok := true ; % globally already defined
+ fi ;
+ if not ok :
+ save ss ; string ss ; ss := n & " " & decimal f & " " & if d = "" : n else : d fi & " " & p ;
+ _spotcolor_counter_ := _spotcolor_counter_ + 1 ;
+ spotcolorpattern[_spotcolor_counter_/_special_div_] := ss ;
+ spotcolorhash[pp][ps] := _spotcolor_counter_ ;
+ flush_special(2, 7, decimal _spotcolor_counter_ & " " & ss) ;
+ _local_specials_ := _local_specials_ &
+ "spotcolorhash["&decimal pp&"]["&decimal ps&"]:=-1;" ;
+ fi ;
+ (_special_signal_/_special_div_,2/_special_div_,spotcolorhash[pp][ps]/_special_div_)
+ else :
+ .5white
+ fi
+enddef ;
+
+%D Transparency
+
+normaltransparent := 1 ; multiplytransparent := 2 ;
+screentransparent := 3 ; overlaytransparent := 4 ;
+softlighttransparent := 5 ; hardlighttransparent := 6 ;
+colordodgetransparent := 7 ; colorburntransparent := 8 ;
+darkentransparent := 9 ; lightentransparent := 10 ;
+differencetransparent := 11 ; exclusiontransparent := 12 ;
+
+% nottransparent := 0 ;
+% compatibletransparent := 99 ;
+
+% fill fullcircle scaled 10cm withcolor transparant(8,.3,red) ;
+
+vardef transparent(expr n, t, c) =
+ save s, ss, nn, cc, is_cmyk, is_spot, ok ;
+ string s, ss ; numeric nn ; color cc ; boolean is_cmyk, is_spot, ok ;
+ % transparancy type
+ if string n :
+ if expandafter known scantokens(n&"transparent") :
+ nn := scantokens(n&"transparent") ;
+ else :
+ nn := 0 ;
+ fi
+ else : % nn := min(n,13)
+ nn := if n<13 : n else : nn := 0 fi ;
+ fi ;
+ % we need to expand the color (can be cmyk(..) or predefined)
+ cc := c ; % expand color
+ % check for cmyk special
+ is_cmyk := (redpart cc = _special_signal_/_special_div_)
+ and (greenpart cc = 1/_special_div_) ;
+ is_spot := (redpart cc = _special_signal_/_special_div_)
+ and (greenpart cc = 2/_special_div_) ;
+ % build special string, fetch cmyk components
+ s := decimal nn & " " & decimal t & " " &
+ if is_cmyk : cmykcolorpattern[bluepart cc]
+ elseif is_spot : spotcolorpattern[bluepart cc]
+ else : dddecimal cc fi ;
+ % check if this one is already used
+ ss := cleanstring("tr_" & s) ;
+ % we now have rather unique names, i.e. a color spec of .234 becomes
+ % tr..._234.... and metapost gives a number overflow (parse error)
+ % for variables like tr_12345678 which may result from many decimal
+ % positions (imo mp bug)
+ ss := asciistring(ss) ;
+ % efficiency hack
+ if expandafter unknown scantokens(ss) :
+ ok := false ; % not yet defined
+ elseif scantokens(ss) < 0 :
+ ok := false ; % locally defined and undefined
+ else :
+ ok := true ; % globally already defined
+ fi ;
+ if not ok :
+ if is_spot :
+ flush_special(5, 8, s) ;
+ elseif is_cmyk :
+ flush_special(4, 8, s) ;
+ else :
+ flush_special(3, 7, s) ;
+ fi ;
+ scantokens(ss) := _special_counter_ ;
+ _local_specials_ := _local_specials_ &
+ "scantokens(" & ditto & ss & ditto & ") := -1 ;" ;
+ fi ;
+ % go ahead
+ if is_spot :
+ (_special_signal_/_special_div_,5/_special_div_,scantokens(ss)/_special_div_)
+ elseif is_cmyk :
+ (_special_signal_/_special_div_,4/_special_div_,scantokens(ss)/_special_div_)
+ else :
+ (_special_signal_/_special_div_,3/_special_div_,scantokens(ss)/_special_div_)
+ fi
+enddef ;
+
+%D This function returns true of false, dependent on transparency.
+
+vardef is_transparent(text t) =
+ begingroup ; save transparent ; save _c_, _b_ ;
+ vardef transparent(expr nn, tt, cc) = _b_ := true ; cc enddef ;
+ boolean _b_ ; _b_ := false ;
+ color _c_ ; _c_ := t ; _b_
+ endgroup
+enddef ;
+
+%D This function returns the not transparent color.
+
+vardef not_transparent(text t) =
+ begingroup ; save transparent ;
+ vardef transparent(expr nn, tt, cc) = cc enddef ;
+ t endgroup
+enddef ;
+
+%D Basic position tracking:
+
+def register (expr label, width, height, offset) =
+ begingroup ;
+ flush_special(50, 7,
+ ddecimal offset & " " &
+ decimal width & " " &
+ decimal height & " " & label) ;
+ endgroup ;
+enddef ;
+
+%D We cannot scale cmyk colors directly since this spoils
+%D the trigger signal (such colors are no real colors).
+
+vardef scaledcmyk(expr c,m,y,k,sf) =
+ cmyk(sf*c,sf*m,sf*y,sf*k)
+enddef ;
+
+vardef scaledcmykasrgb(expr c,m,y,k,sf) =
+ (sf*(1-c-k,1-m-k,1-y-k))
+enddef ;
+
+vardef scaledrgbascmyk(expr c,m,y,k,sf) =
+ scaledcmyk(1-c,1-m,1-y,0,sf)
+enddef ;
+
+vardef scaledrgb(expr r,g,b,sf) =
+ (sf*(r,g,b))
+enddef ;
+
+vardef scaledgray(expr s,sf) =
+ (sf*(s,s,s))
+enddef ;
+
+% spotcolor is already scaled
+
+endinput ;
+
+% just an exercise (due to a question by Chof on the context mailing list); scaling of
+% 'special' colors is not possible and the next solution is incomplete (spot colors,
+% transparency, etc); watch the the tricky chained macro construction
+
+% vardef normalgray(expr s ) = (s,s,s) enddef ;
+% vardef normalrgb (expr r,g,b ) = (r,g,b) enddef ;
+% vardef normalcmyk(expr c,m,y,k) = if cmykcolors : save ok ; boolean ok ; if unknown cmykcolorhash[c][m][y][k] : ok := false ; elseif cmykcolorhash[c][m][y][k] = -1 : ok := false ; else : ok := true ; fi ; if not ok : save s ; string s ; s := dddecimal (c,m,y) & " " & decimal k ; _cmyk_counter_ := _cmyk_counter_ + 1 ; cmykcolorpattern[_cmyk_counter_/_special_div_] := s ; cmykcolorhash[c][m][y][k] := _cmyk_counter_ ; flush_special(1, 7, decimal _cmyk_counter_ & " " & s) ; _local_specials_ := _local_specials_ & " cmykcolorhash[" & decimal c & "][" & decimal m & "][" & decimal y & "][" & decimal k & "] := -1 ; " ; fi ; (_special_signal_/_special_div_,1/_special_div_,cmykcolorhash[c][m][y][k]/_special_div_) else : (1-c-k,1-m-k,1-y-k) fi enddef ;
+
+% vardef gray(expr s) = normalgray(s ) enddef ;
+% vardef rgb (expr r,g,b) = normalrgb (r,g,b ) enddef ;
+% vardef cmyk(expr c,m,y,k) = normalcmyk(c,m,y,k) enddef ;
+
+% numeric _scaled_color_t_ ;
+% color _scaled_color_c_ ;
+
+% def withscaledcolor =
+% hide (
+% _scaled_color_t_ := 0 ; % direct
+% def gray(expr s) =
+% hide (
+% _gray_s_ := s ;
+% _scaled_color_t_ := 1; % gray
+% )
+% 0
+% enddef ;
+% def rgb (expr r,g,b) =
+% hide (
+% _rgb_r_ := r ; _rgb_g_ := g ; _rgb_b_ := b ;
+% _scaled_color_t_ := 2 ; % rgb
+% )
+% 0
+% enddef ;
+% def cmyk (expr c,m,y,k) =
+% hide (
+% _cmyk_c_ := c ; _cmyk_m_ := m ; _cmyk_y_ := y ; _cmyk_k_ := k ;
+% _scaled_color_t_ := 3 ; % cmyk
+% )
+% 0
+% enddef ; )
+% dowithscaledcolor
+% enddef ;
+
+% def dowithscaledcolor expr t =
+% hide (
+% if color t : _scaled_color_c_ := t fi ;
+% vardef gray(expr s) = normalgray(s) enddef ;
+% vardef rgb (expr r,g,b) = normalrgb (r,g,b) enddef ;
+% vardef cmyk(expr c,m,y,k) = normalcmyk(c,m,y,k) enddef ;
+% )
+% enddef ;
+
+% def by expr s =
+% if _scaled_color_t_ = 0 :
+% withcolor s*_scaled_color_c_
+% elseif _scaled_color_t_ = 1 :
+% withcolor gray(s*_gray_s_)
+% elseif _scaled_color_t_ = 2 :
+% withcolor rgb (s*_rgb_r_, s*_rgb_g_, s*_rgb_b_)
+% elseif _scaled_color_t_ = 3 :
+% withcolor cmyk(s*_cmyk_c_, s*_cmyk_m_, s*_cmyk_y_, s*_cmyk_k_)
+% fi
+% enddef ;
+
+% fill fullcircle scaled 10cm withscaledcolor cmyk(0,0,1,0) by .5 ;
+% fill fullcircle scaled 8cm withscaledcolor rgb (0,0,1) by .5 ;
+% fill fullcircle scaled 6cm withscaledcolor gray(1) by .5 ;
+% fill fullcircle scaled 4cm withscaledcolor (0,1,0) by .5 ;
diff --git a/metapost/context/base/mp-step.mp b/metapost/context/base/mp-step.mp
new file mode 100644
index 000000000..d602f7014
--- /dev/null
+++ b/metapost/context/base/mp-step.mp
@@ -0,0 +1,320 @@
+%D \module
+%D [ file=mp-step.mp,
+%D version=2001.05.22,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=steps,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_step : endinput ; fi ;
+
+boolean context_step ; context_step := true ;
+
+%D In the associated \TEX\ module \type {m-steps}, we describe
+%D three methods. The first method uses a different kind of
+%D code than the other two. The method we decided to use,
+%D is based on positional information (paths) provided by
+%D \CONTEXT.
+
+def initialize_step_variables =
+ save line_method, line_h_offset, line_v_offset ;
+ numeric line_method ; line_method := 1 ;
+ numeric line_h_offset ; line_h_offset := 3pt ;
+ numeric line_v_offset ; line_v_offset := 3pt ;
+enddef ;
+
+def begin_step_chart =
+ initialize_step_variables ;
+ save steps, texts, t, b, tb, nofcells ;
+ picture cells[][], texts[][][], lines[][][] ;
+ numeric t, b ; t := 1 ; b := 2 ;
+ numeric nofcells ; nofcells := 0 ;
+enddef ;
+
+def analyze_step_chart =
+ numeric n[], l[][], r[][] ; pair p[] ;
+ n[t] := n[b] := 0 ; numeric tb ;
+ for i=1 upto nofcells : for nn = t, b :
+ if bbwidth(cells[nn][i])>0 : n[nn] := n[nn] + 1 ; fi ;
+ l[t][i] := r[t][i] := l[b][i] := r[b][i] := 0 ;
+ endfor ; endfor ;
+ % count left and right points
+ for i=1 upto nofcells-1 : for j=i upto nofcells-1 : for nn = t, b :
+ if bbwidth(texts[nn][i][j])>0 :
+ l[nn][i] := l[nn][i] + 1 ;
+ r[nn][j+1] := r[nn][j+1] + 1 ;
+ fi ;
+ endfor ; endfor ; endfor ;
+ % calculate left and right points
+ vardef do (expr nn, mm, ii, ss) =
+ if (l[nn][ii] + r[nn][ii]) > 1 : ss else : .5 fi
+ [ ulcorner cells[mm][ii], urcorner cells[mm][ii] ]
+ enddef ;
+ % combined rows
+ tb := if n[t]>0 : t else : b fi ;
+enddef ;
+
+vardef get_step_chart_top_line (expr i, j) =
+ if bbwidth(cells[tb][i])>0 :
+ if bbwidth(texts[t][i][j])>0 :
+ if bbwidth(cells[tb][j+1])>0 :
+ p[1] := top do(t, tb, i, .6) ;
+ p[3] := top do(t, tb, j+1, .4) ;
+ p[2] := .5[p[1],p[3]] ;
+ if line_method = 1 :
+ p[2] := p[2] shifted (0, ypart
+ (llcorner texts[t][i][j] - ulcorner cells[tb][j+1])) ;
+ elseif line_method = 2 :
+ p[2] := center texts[t][i][j] ;
+ else :
+ % nothing
+ fi ;
+ p[1] := p[1] shifted (0,+line_v_offset) ;
+ p[2] := p[2] shifted (0,-line_v_offset) ;
+ p[3] := p[3] shifted (0,+line_v_offset) ;
+ (p[1] {up} ... p[2] ... {down} p[3])
+ else :
+ origin
+ fi
+ else :
+ origin
+ fi
+ else :
+ origin
+ fi
+enddef ;
+
+vardef get_step_chart_bot_line (expr i, j) =
+ if bbwidth(cells[b][i])>0 :
+ if bbwidth(texts[b][i][j])>0 :
+ if bbwidth(cells[b][j+1])>0 :
+ p[1] := (bot do(b, b, i, .6)) shifted (0,-bbheight(cells[b][i])) ;
+ p[3] := (bot do(b, b, j+1, .4)) shifted (0,-bbheight(cells[b][j+1])) ;
+ p[2] := .5[p[1],p[3]] ;
+ if line_method = 1 :
+ p[2] := p[2] shifted (0, -ypart
+ (llcorner cells[b][j+1] - ulcorner texts[b][i][j])) ;
+ elseif line_method = 2 :
+ p[2] := center texts[b][i][j] ;
+ fi ;
+ p[1] := p[1] shifted (0,-line_v_offset) ;
+ p[2] := p[2] shifted (0,+line_v_offset) ;
+ p[3] := p[3] shifted (0,-line_v_offset) ;
+ (p[1] {down} ... p[2] ... {up} p[3])
+ else :
+ origin
+ fi
+ else :
+ origin
+ fi
+ else :
+ origin
+ fi
+enddef ;
+
+def end_step_chart =
+ for i=1 upto nofcells : for nn = t, b :
+ if bbwidth(cells[nn][i]) >0 : draw cells[nn][i] ; fi ;
+ endfor ; endfor ;
+ for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b :
+ if known lines[nn][i][j] :
+ if bbwidth(lines[nn][i][j])>0 : draw lines[nn][i][j] ; fi ;
+ fi ;
+ endfor ; endfor ; endfor ;
+ for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b :
+ if bbwidth(texts[nn][i][j])>0 : draw texts[nn][i][j] ; fi ;
+ endfor ; endfor ; endfor ;
+enddef ;
+
+%D Step tables.
+
+def begin_step_table =
+ initialize_step_variables ;
+ picture cells[], texts[], lines[] ;
+ numeric nofcells ; nofcells := 0 ;
+enddef ;
+
+def end_step_table =
+ for i=1 upto nofcells : if known cells[i] : if bbwidth(cells[i])>0 :
+ draw cells[i] ;
+ fi ; fi ; endfor ;
+ for i=1 upto nofcells : if known lines[i] : if bbwidth(lines[i])>0 :
+ draw lines[i] ;
+ fi ; fi ; endfor ;
+ for i=1 upto nofcells : if known texts[i] : if bbwidth(texts[i])>0 :
+ draw texts[i] ;
+ fi ; fi ; endfor ;
+enddef ;
+
+vardef get_step_table_line (expr i) =
+ pair prev, self, next ;
+ if known texts[i] :
+ self := lft .5[llcorner texts[i], ulcorner texts[i] ] ;
+ prev := rt if known texts[i-1] : .3 else : .5 fi [lrcorner cells[i] , urcorner cells[i] ] ;
+ next := rt if known texts[i+1] : .7 else : .5 fi [lrcorner cells[i+1], urcorner cells[i+1]] ;
+ self := self shifted (-line_h_offset,0) ;
+ prev := prev shifted (+line_h_offset,0) ;
+ next := next shifted (+line_h_offset,0) ;
+ prev {right} ... self ... {left} next
+ else :
+ origin
+ fi
+enddef ;
+
+endinput
+
+%D The older method let \METAPOST\ do the typesetting. The
+%D macros needed for that are included here for educational
+%D purposes.
+%D
+%D \starttypen
+%D def initialize_step_variables =
+%D save line_color, line_width, arrow_alternative,
+%D text_fill_color, text_line_color, text_line_width, text_offset,
+%D cell_fill_color, cell_line_color, cell_line_width, cell_offset,
+%D line_h_offset, line_v_offset ;
+%D color line_color ; line_color := .4white ;
+%D numeric line_width ; line_width := 1.5pt ;
+%D color text_fill_color ; text_fill_color := white ;
+%D color text_line_color ; text_line_color := red ;
+%D numeric text_line_width ; text_line_width := 1pt ;
+%D numeric text_offset ; text_offset := 2pt ;
+%D color cell_fill_color ; cell_fill_color := white ;
+%D color cell_line_color ; cell_line_color := blue ;
+%D numeric cell_line_width ; cell_line_width := 1pt ;
+%D numeric cell_offset ; cell_offset := 2pt ;
+%D numeric line_alternative ; line_alternative := 1 ;
+%D numeric line_h_offset ; line_h_offset := 3pt ;
+%D numeric line_v_offset ; line_v_offset := 3pt ;
+%D enddef ;
+%D
+%D def begin_step_chart =
+%D begingroup ;
+%D initialize_step_variables ;
+%D save steps, texts, t, b ;
+%D picture cells[][] ; numeric nofcells ; nofcells := 0 ;
+%D picture texts[][][] ; numeric noftexts ; noftexts := 0 ;
+%D numeric t, b ; t := 1 ; b := 2 ;
+%D enddef ;
+%D \stoptypen
+%D
+%D We use a couple of macros to store the content. In the
+%D second (third) alternative we will directly fill the
+%D cells.
+%D
+%D \starttypen
+%D def set_step_chart_cells (expr one, two) =
+%D nofcells := nofcells + 1 ; noftexts := 0 ;
+%D cells[t][nofcells] := textext.rt(one) ;
+%D cells[b][nofcells] := textext.rt(two) ;
+%D enddef ;
+%D
+%D def set_step_chart_texts (expr one, two) =
+%D noftexts := noftexts + 1 ;
+%D texts[t][nofcells][noftexts] := textext.rt(one) ;
+%D texts[b][nofcells][noftexts] := textext.rt(two) ;
+%D enddef ;
+%D \stoptypen
+%D
+%D If you compare the building macro with the later
+%D alternative, you will notice that here we explicitly
+%D have to calculate the distances and positions.
+%D
+%D \starttypen
+%D def end_step_chart =
+%D numeric dx ; dx := 0 ; path p ;
+%D numeric n[] ; n[t] := n[b] := 0 ;
+%D numeric stepsvdistance[] ;
+%D vardef bbwidth (expr p) = (xpart (lrcorner p - llcorner p)) enddef ;
+%D vardef bbheight (expr p) = (ypart (urcorner p - lrcorner p)) enddef ;
+%D stepsvdistance[t] := stepsvdistance[b] := 0 ;
+%D for i=1 upto nofcells :
+%D % find largest bbox
+%D p := boundingbox steps
+%D [if bbwidth(cells[t][i])>bbwidth(cells[b][i]): t else: b fi][i] ;
+%D % assign largest bbox
+%D for nn = t, b :
+%D if bbwidth(cells[nn][i])>0 :
+%D setbounds cells[nn][i] to p enlarged cell_offset ;
+%D n[nn] := n[nn] + 1 ;
+%D fi ;
+%D endfor ;
+%D % determine height
+%D if n[t]>0 :
+%D stepsvdistance[t] := bbheight(cells[t][1]) + intertextdistance ;
+%D fi ;
+%D % add to row
+%D for nn = t, b :
+%D cells[nn][i] := cells[nn][i] shifted (dx,stepsvdistance[nn]) ;
+%D if bbwidth(cells[nn][i])>0 :
+%D dowithpath (boundingbox cells[nn][i],
+%D cell_line_width, cell_line_color, cell_background_color) ;
+%D fi ;
+%D endfor ;
+%D % calculate position
+%D dx := dx + interstepdistance + bbwidth(cells[b][i]) ;
+%D endfor ;
+%D boolean stacked ; stacked := false ;
+%D numeric l[][], r[][], l[][], r[][] ;
+%D pair pa, pb, pc ; path p[] ;
+%D for i=1 upto nofcells :
+%D l[t][i] := r[t][i] := l[b][i] := r[b][i] := 0 ;
+%D endfor ;
+%D % count left and right points
+%D for i=1 upto nofcells : for j=1 upto nofcells : for nn = t, b :
+%D if known texts[nn][i][j] : if bbwidth(texts[nn][i][j])>0 :
+%D l[nn][i] := l[nn][i] + 1 ;
+%D r[nn][j+i] := r[nn][j+i] + 1 ;
+%D stacked := (stacked or (j>1)) ;
+%D setbounds texts[nn][i][j] to boundingbox texts[nn][i][j] enlarged cell_offset ;
+%D fi fi ;
+%D endfor ; endfor ; endfor ;
+%D % calculate left and right points
+%D vardef do (expr nn, mm, ii, ss) =
+%D if (l[nn][ii] > 0) and (r[nn][ii] > 0) : ss else : .5 fi
+%D [ ulcorner cells[mm][ii],urcorner cells[mm][ii] ]
+%D enddef ;
+%D % draw arrow from left to right point
+%D def dodo (expr nn, ii, jj, dd) =
+%D drawarrow p[nn]
+%D withpen pencircle scaled arrow_line_width
+%D withcolor arrow_line_color ;
+%D transform tr ; tr := identity
+%D shifted point .5 along p[nn]
+%D shifted -center texts[nn][ii][jj]
+%D if not stacked : shifted (0,dd) fi ;
+%D dowithpath ((boundingbox texts[nn][ii][jj]) transformed tr,
+%D text_line_width, text_line_color, text_fill_color) ;
+%D enddef ;
+%D % draw top and bottom text boxes
+%D for i=1 upto nofcells : for j=1 upto nofcells :
+%D pickup pencircle scaled arrow_line_width ;
+%D if known texts[t][i][j] : if bbwidth(texts[t][i][j]) > 0 :
+%D pa := top do(t, if n[t]>0 : t else : b fi, i, .6) ;
+%D pb := top do(t, if n[t]>0 : t else : b fi, j+i, .4) ;
+%D pc := .5[pa,pb] shifted (0,+step_arrow_depth) ;
+%D p[t] := pa {up} .. if not stacked : pc .. fi {down} pb ;
+%D dodo(t, i, j, +intertextdistance) ;
+%D fi fi ;
+%D if known texts[b][i][j] : if bbwidth(texts[b][i][j]) > 0 :
+%D pa := (bot do(b, b, i, .6)) shifted (0,-bbheight(cells[b][i])) ;
+%D pb := (bot do(b, b, j+i, .4)) shifted (0,-bbheight(cells[b][j+i])) ;
+%D pc := .5[pa,pb] shifted (0,-step_arrow_depth) ;
+%D p[b] := pa {down} .. if not stacked : pc .. fi {up} pb ;
+%D dodo(b, i, j, -intertextdistance) ;
+%D fi fi ;
+%D endfor ; endfor ;
+%D endgroup ;
+%D enddef ;
+%D \stoptypen
+%D
+%D If you compare both methods, you will notice that the
+%D first method is the cleanest, but not the most efficient
+%D (since it needs \TEX\ runs within \METAPOST\ runs within
+%D \TEX\ runs).
diff --git a/metapost/context/base/mp-symb.mp b/metapost/context/base/mp-symb.mp
new file mode 100644
index 000000000..a84c84e82
--- /dev/null
+++ b/metapost/context/base/mp-symb.mp
@@ -0,0 +1,351 @@
+%D \module
+%D [ file=mp-symb.mp,
+%D version=very old,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=navigation symbol macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Instead of these symbols, you can use the \type {contnav}
+%D font by Taco Hoekwater that is derived form this file.
+
+u := 3;
+h := 5u;
+wt := 5u;
+wb := .25wt;
+o := .1u;
+pw := .5u;
+
+drawoptions (withpen pencircle scaled pw);
+
+path lefttriangle, righttriangle, sublefttriangle, subrighttriangle;
+
+pair s ; s = (2wb,0) ;
+
+x1t = x2t = 0;
+x3t = wt;
+y3t = .5h;
+z1t-z2t = (z3t-z2t) rotated 60;
+
+z4t = (z2t--z3t) intersectionpoint ((z1t--z2t) shifted s) ;
+z5t = (z3t--z1t) intersectionpoint ((z1t--z2t) shifted s) ;
+
+righttriangle = z1t--z2t--z3t--cycle;
+lefttriangle = righttriangle rotatedaround((0,.5h), 180) shifted (wt,0);
+
+subrighttriangle = z4t--((z2t--z3t--z1t) shifted s)--z5t ;
+sublefttriangle = subrighttriangle rotatedaround((0,.5h), 180) shifted (wt,0);
+
+path sidebar;
+
+x1b = x4b = 0;
+x2b = x3b = wb;
+y1b = y2b = y1t;
+y3b = y4b = y2t;
+
+sidebar = z1b--z2b--z3b--z4b--cycle;
+
+path midbar, onebar, twobar;
+
+hh = abs(y1t-y2t);
+
+%midbar := unitsquare scaled 2hh/3;
+midbar := unitsquare scaled hh;
+onebar := unitsquare xscaled (hh/3) yscaled hh;
+twobar := onebar;
+
+def prepareglyph =
+ drawoptions (withpen pencircle scaled .5u);
+enddef;
+
+def finishglyph =
+ set_outer_boundingbox currentpicture;
+ bboxmargin := o;
+ setbounds currentpicture to bbox currentpicture;
+% draw boundingbox currentpicture withcolor red withpen pencircle scaled 1;
+enddef;
+
+beginfig (1);
+ prepareglyph;
+ fill lefttriangle;
+ draw lefttriangle; % draw gets the bbox right, filldraw doesn't
+ finishglyph;
+endfig;
+
+beginfig (2);
+ prepareglyph;
+ fill righttriangle;
+ draw righttriangle;
+ finishglyph;
+endfig;
+
+beginfig (3);
+ prepareglyph;
+ fill sidebar;
+ draw sidebar;
+ fill lefttriangle shifted (.5s);
+ draw lefttriangle shifted (.5s);
+ finishglyph;
+endfig;
+
+beginfig (4);
+ prepareglyph;
+ fill righttriangle;
+ draw righttriangle;
+ fill sidebar shifted (wt,0);
+ draw sidebar shifted (wt,0);
+ finishglyph;
+endfig;
+
+beginfig (5);
+ prepareglyph;
+ fill lefttriangle;
+ draw lefttriangle;
+ fill lefttriangle shifted s;
+ draw lefttriangle shifted s;
+ finishglyph;
+endfig;
+
+beginfig (6);
+ prepareglyph;
+ fill righttriangle;
+ draw righttriangle;
+ fill righttriangle shifted s;
+ draw righttriangle shifted s;
+ finishglyph;
+endfig;
+
+beginfig (7);
+ prepareglyph;
+ fill midbar;
+ draw midbar;
+ finishglyph;
+endfig;
+
+beginfig (8);
+ prepareglyph;
+ fill onebar;
+ draw onebar;
+ finishglyph;
+endfig;
+
+beginfig (9);
+ prepareglyph;
+ fill twobar;
+ draw twobar;
+ fill twobar shifted (pw+hh/2,0);
+ draw twobar shifted (pw+hh/2,0);
+ finishglyph;
+endfig;
+
+beginfig(101);
+ prepareglyph;
+ draw lefttriangle;
+ finishglyph;
+endfig;
+
+beginfig(102);
+ prepareglyph;
+ draw righttriangle;
+ finishglyph;
+endfig;
+
+beginfig(103);
+ prepareglyph;
+ draw sidebar;
+ draw lefttriangle shifted (.5s);
+ finishglyph;
+endfig;
+
+beginfig(104);
+ prepareglyph;
+ draw righttriangle;
+ draw sidebar shifted (wt,0);
+ finishglyph;
+endfig;
+
+beginfig(105);
+ prepareglyph;
+ draw lefttriangle;
+ draw lefttriangle shifted s;
+ finishglyph;
+endfig;
+
+beginfig(106);
+ prepareglyph;
+ draw righttriangle;
+ draw righttriangle shifted s;
+ finishglyph;
+endfig;
+
+beginfig(107);
+ prepareglyph;
+ draw midbar;
+ finishglyph;
+endfig;
+
+beginfig(108);
+ prepareglyph;
+ draw onebar;
+ finishglyph;
+endfig;
+
+beginfig(109);
+ prepareglyph;
+ draw twobar;
+ draw twobar shifted (pw+hh/2,0);
+ finishglyph;
+endfig;
+
+beginfig(201);
+ prepareglyph;
+ draw lefttriangle;
+ finishglyph;
+endfig;
+
+beginfig(202);
+ prepareglyph;
+ draw righttriangle;
+ finishglyph;
+endfig;
+
+beginfig(203);
+ prepareglyph;
+ draw sidebar;
+ draw lefttriangle shifted (.5s);
+ finishglyph;
+endfig;
+
+beginfig(204);
+ prepareglyph;
+ draw righttriangle;
+ draw sidebar shifted (wt,0);
+ finishglyph;
+endfig;
+
+beginfig(205);
+ prepareglyph;
+ draw sublefttriangle shifted s;
+ draw lefttriangle shifted s;
+ finishglyph;
+endfig;
+
+beginfig(206);
+ prepareglyph;
+ draw subrighttriangle;
+ draw righttriangle;
+ finishglyph;
+endfig;
+
+beginfig(207);
+ prepareglyph;
+ draw midbar;
+ finishglyph;
+endfig;
+
+beginfig(208);
+ prepareglyph;
+ draw onebar;
+ finishglyph;
+endfig;
+
+beginfig(209);
+ prepareglyph;
+ draw twobar;
+ draw twobar shifted (pw+hh/2,0);
+ finishglyph;
+endfig;
+
+
+beginfig(999);
+
+picture collection [] ;
+
+prepareglyph ;
+draw lefttriangle ;
+finishglyph ;
+collection[201] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw righttriangle ;
+finishglyph ;
+collection[202] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw sidebar ;
+draw lefttriangle shifted (.5s) ;
+finishglyph ;
+collection[203] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw righttriangle ;
+draw sidebar shifted (wt,0) ;
+finishglyph ;
+collection[204] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw sublefttriangle shifted s ;
+draw lefttriangle shifted s ;
+finishglyph ;
+collection[205] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw subrighttriangle ;
+draw righttriangle ;
+finishglyph ;
+collection[206] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw midbar ;
+finishglyph ;
+collection[207] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw onebar ;
+finishglyph ;
+collection[208] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw twobar ;
+draw twobar shifted (pw+hh/2,0) ;
+finishglyph ;
+collection[209] := currentpicture ;
+currentpicture := nullpicture ;
+
+for i=201 upto 209 :
+ collection[i] := collection[i] shifted - center collection[i] ;
+endfor ;
+
+addto currentpicture also collection[205] shifted ( 0, 0)
+ withcolor (.3,.4,.5) ;
+addto currentpicture also collection[202] shifted ( 0,1.5h)
+ withcolor (.5,.6,.7) ;
+addto currentpicture also collection[201] shifted (1.5h, 0)
+ withcolor (.6,.7,.8) ;
+addto currentpicture also collection[206] shifted (1.5h,1.5h)
+ withcolor (.4,.5,.6) ;
+
+collection[210] := currentpicture ;
+currentpicture := nullpicture ;
+
+bboxmargin := .25u;
+
+fill bbox collection[210] withcolor .95(1,1,0);
+addto currentpicture also collection[210] ;
+
+endfig ;
+
+end
diff --git a/metapost/context/base/mp-text.mp b/metapost/context/base/mp-text.mp
new file mode 100644
index 000000000..60e16c09b
--- /dev/null
+++ b/metapost/context/base/mp-text.mp
@@ -0,0 +1,269 @@
+%D \module
+%D [ file=mp-text.mp,
+%D version=2000.07.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=text support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_text : endinput ; fi ;
+
+boolean context_text ; context_text := true ;
+
+if unknown noftexpictures :
+ numeric noftexpictures ; noftexpictures := 0 ;
+fi ;
+
+if unknown texpictures[1] :
+ picture texpictures[] ;
+fi ;
+
+numeric textextoffset ; textextoffset := 0 ;
+
+% vardef textext@#(expr txt) =
+% interim labeloffset := textextoffset ;
+% noftexpictures := noftexpictures + 1 ;
+% if string txt :
+% write "% figure " & decimal charcode & " : " &
+% "texpictures[" & decimal noftexpictures & "] := btex " &
+% txt & " etex ;" to jobname & ".mpt" ;
+% if unknown texpictures[noftexpictures] :
+% thelabel@#("unknown",origin)
+% else :
+% thelabel@#(texpictures[noftexpictures],origin)
+% fi
+% else :
+% thelabel@#(txt,origin)
+% fi
+% enddef ;
+
+boolean hobbiestextext ; hobbiestextext := false ;
+% string textextstring ; textextstring := "" ;
+
+% def resettextextdirective =
+% textextstring := "" ;
+% enddef ;
+
+% def textextdirective text t =
+% textextstring := textextstring & t ;
+% enddef ;
+
+vardef textext@#(expr txt) =
+ save _s_ ; string _s_ ;
+ interim labeloffset := textextoffset ;
+ noftexpictures := noftexpictures + 1 ;
+ if string txt :
+ if hobbiestextext : % the tex.mp method as fallback (see tex.mp)
+ write _s_ & "btex " & txt & " etex" to "mptextmp.mp" ;
+ write EOF to "mptextmp.mp" ;
+ scantokens "input mptextmp"
+ else :
+ write "% figure " & decimal charcode & " : " &
+ "texpictures[" & decimal noftexpictures & "] := btex " &
+ txt & " etex ;" to jobname & ".mpt" ;
+ if unknown texpictures[noftexpictures] :
+ thelabel@#("unknown",origin)
+ else :
+ thelabel@#(texpictures[noftexpictures],origin)
+ fi
+ fi
+ else :
+ thelabel@#(txt,origin)
+ fi
+enddef ;
+
+string laboff_ ; laboff_ := "" ;
+string laboff_c ; laboff_c := "" ;
+string laboff_l ; laboff_l := ".lft" ;
+string laboff_r ; laboff_r := ".rt" ;
+string laboff_b ; laboff_b := ".bot" ;
+string laboff_t ; laboff_t := ".top" ;
+
+string laboff_lt ; laboff_lt := ".ulft" ;
+string laboff_rt ; laboff_rt := ".urt" ; % bugged, conflict with r
+string laboff_lb ; laboff_lb := ".llft" ;
+string laboff_rb ; laboff_rb := ".lrt" ;
+string laboff_tl ; laboff_tl := ".ulft" ;
+string laboff_tr ; laboff_tr := ".urt" ;
+string laboff_bl ; laboff_bl := ".llft" ;
+string laboff_br ; laboff_br := ".lrt" ;
+
+vardef textextstr(expr s, a) =
+ save ss ; string ss ;
+ ss := "laboff_" & a ;
+ ss := scantokens ss ;
+ ss := "textext" & ss & "(" & ditto & s & ditto & ")" ;
+ scantokens ss
+enddef ;
+
+pair laboff.origin ; laboff.origin = (0,0) ; % (infinity,infinity) ;
+pair laboff.raw ; laboff.raw = (0,0) ; % (infinity,infinity) ;
+
+laboff.origin = (0,0) ; labxf.origin := 0 ; labyf.origin := 0 ;
+laboff.raw = (0,0) ; labxf.raw := 0 ; labyf.raw := 0 ;
+
+vardef thelabel@#(expr s, z) =
+ save p ; picture p ;
+ p = s if not picture s : infont defaultfont scaled defaultscale fi ;
+% wrong, see myway textext
+% if laboff@#<>laboff.origin :
+ (p shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p +
+ labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)))
+% else :
+% (p shifted z)
+% fi
+enddef;
+
+def build_parshape (expr p, offset_or_path, dx, dy,
+ baselineskip, strutheight, strutdepth, topskip) =
+
+ if unknown trace_parshape :
+ boolean trace_parshape ; trace_parshape := false ;
+ fi ;
+
+ begingroup ;
+
+ save q, l, r, line, tt, bb,
+ n, hsize, vsize, vvsize, voffset, hoffset, width, indent,
+ ll, lll, rr, rrr, cp, cq, t, b ;
+
+ path q, l, r, line, tt, bb ;
+ numeric n, hsize, vsize, vvsize, voffset, hoffset, width[], indent[] ;
+ pair ll, lll, rr, rrr, cp, cq, t, b ;
+
+ n := 0 ; cp := center p ;
+
+ if path offset_or_path :
+ q := offset_or_path ; cq := center q ;
+ voffset := dy ;
+ hoffset := dx ;
+ else :
+ q := p ; cq := center q ;
+ hoffset := offset_or_path + dx ;
+ voffset := offset_or_path + dy ;
+ fi ;
+
+ hsize := xpart lrcorner q - xpart llcorner q ;
+ vsize := ypart urcorner q - ypart lrcorner q ;
+
+ q := p shifted - cp ;
+
+ startsavingdata ;
+
+ savedata "\global\parvoffset " & decimal voffset&"bp " ;
+ savedata "\global\parhoffset " & decimal hoffset&"bp " ;
+ savedata "\global\parwidth " & decimal hsize&"bp " ;
+ savedata "\global\parheight " & decimal vsize&"bp " ;
+
+ if not path offset_or_path :
+ q := q xscaled ((hsize-2hoffset)/hsize)
+ yscaled ((vsize-2voffset)/vsize) ;
+ fi ;
+
+ hsize := xpart lrcorner q - xpart llcorner q ;
+ vsize := ypart urcorner q - ypart lrcorner q ;
+
+ t := (ulcorner q -- urcorner q) intersection_point q ;
+ b := (llcorner q -- lrcorner q) intersection_point q ;
+
+ if xpart directionpoint t of q < 0 :
+ q := reverse q ;
+ fi ;
+
+ l := q cutbefore t ;
+ l := l if xpart point 0 of q < 0 : & q fi cutafter b ;
+
+ r := q cutbefore b ;
+ r := r if xpart point 0 of q > 0 : & q fi cutafter t ;
+
+% tt := (ulcorner q -- urcorner q) shifted (0,-topskip) ;
+% bb := (llcorner q -- lrcorner q) shifted (0,strutdepth) ;
+%
+% l := l cutbefore (l intersection_point tt) ;
+% l := l cutafter (l intersection_point bb) ;
+% r := r cutbefore (r intersection_point bb) ;
+% r := r cutafter (r intersection_point tt) ;
+
+ if trace_parshape :
+ drawarrow p withpen pencircle scaled 2pt withcolor red ;
+ drawarrow l shifted cp withpen pencircle scaled 1pt withcolor green ;
+ drawarrow r shifted cp withpen pencircle scaled 1pt withcolor blue ;
+ fi ;
+
+ vardef found_point (expr lin, pat, sig) =
+ pair a, b ;
+ a := pat intersection_point (lin shifted (0,strutheight)) ;
+ if intersection_found :
+ a := a shifted (0,-strutheight) ;
+ else :
+ a := pat intersection_point lin ;
+ fi ;
+ b := pat intersection_point (lin shifted (0,-strutdepth)) ;
+ if intersection_found :
+ if sig :
+ if xpart b > xpart a : a := b shifted (0,strutdepth) fi ;
+ else :
+ if xpart b < xpart a : a := b shifted (0,strutdepth) fi ;
+ fi ;
+ fi ;
+ a
+ enddef ;
+
+ if (strutheight+strutdepth<baselineskip) :
+ vvsize := vsize ;
+ else :
+ vvsize := (vsize div baselineskip) * baselineskip ;
+ fi ;
+
+ for i=topskip step baselineskip until vvsize :
+
+ line := (ulcorner q -- urcorner q) shifted (0,-i-eps) ;
+
+ ll := found_point(line,l,true ) ;
+ rr := found_point(line,r,false) ;
+
+ if trace_parshape :
+ fill (ll--rr--rr shifted (0,strutheight)--ll
+ shifted (0,strutheight)--cycle) shifted cp withcolor .5white ;
+ fill (ll--rr--rr shifted (0,-strutdepth)--ll
+ shifted (0,-strutdepth)--cycle) shifted cp withcolor .7white ;
+ draw ll shifted cp withpen pencircle scaled 2pt ;
+ draw rr shifted cp withpen pencircle scaled 2pt ;
+ draw (ll--rr) shifted cp withpen pencircle scaled .5pt ;
+ fi ;
+
+ n := n + 1 ;
+ indent[n] := abs(xpart ll - xpart llcorner q) ;
+ width[n] := abs(xpart rr - xpart ll) ;
+
+ if (i=strutheight) and (width[n]<baselineskip) :
+ n := n - 1 ;
+ savedata "\global\chardef\parfirst=1 " ;
+ fi ;
+
+ endfor ;
+
+ savedata "\global\parlines " & decimal n ;
+ savedata "\global\partoks{ " ;
+ for i=1 upto n:
+ savedata decimal indent[i]&"bp " & decimal width[i]&"bp " ;
+ endfor ;
+ savedata "}" ;
+
+ stopsavingdata ;
+
+ endgroup ;
+
+enddef ;
+
+vardef verbatim(expr str) =
+ ditto & "\detokenize{" & str & "}" & ditto
+enddef ;
diff --git a/metapost/context/base/mp-tool.mp b/metapost/context/base/mp-tool.mp
new file mode 100644
index 000000000..1a748baf9
--- /dev/null
+++ b/metapost/context/base/mp-tool.mp
@@ -0,0 +1,2566 @@
+%D \module
+%D [ file=mp-tool.mp,
+%D version=1998.02.15,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=auxiliary macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% a cleanup is needed, like using image and alike
+% use a few more "newinternal"'s
+
+%D This module is rather preliminary and subjected to
+%D changes.
+
+if known context_tool : endinput ; fi ;
+
+boolean context_tool ; context_tool := true ;
+
+let @## = @# ;
+
+%D New, version number testing:
+%D
+%D \starttyping
+%D fill fullcircle scaled 2cm withcolor if mpversiongt("0.6") : red else : green fi ;
+%D fill fullcircle scaled 1cm withcolor if mpversionlt(0.6) : blue else : white fi ;
+%D \stoptyping
+
+if not known mpversion : string mpversion ; mpversion := "0.641" ; fi ;
+
+% vardef mpversiongt(expr s) =
+% scantokens (mpversion & " > " & if numeric s : decimal s else : s fi)
+% enddef ;
+% vardef mpversionlt(expr s) =
+% scantokens (mpversion & " < " & if numeric s : decimal s else : s fi)
+% enddef ;
+% vardef mpversioneq(expr s) =
+% scantokens (mpversion & " = " & if numeric s : decimal s else : s fi)
+% enddef ;
+
+%D More interesting:
+%D
+%D \starttyping
+%D fill fullcircle scaled 4cm withcolor if mpversiongt("0.6") : red else : green fi ;
+%D fill fullcircle scaled 2cm withcolor if mpversionlt(0.6) : blue else : white fi ;
+%D fill fullcircle scaled 1cm withcolor if mpversioncmp(0.6,">=") : yellow else : black fi ;
+%D \stoptyping
+
+vardef mpversioncmp(expr s, c) =
+ scantokens (mpversion & c & if numeric s : decimal s else : s fi)
+enddef ;
+
+vardef mpversionlt (expr s) = mpversioncmp(s, "<") enddef ;
+vardef mpversioneq (expr s) = mpversioncmp(s, "=") enddef ;
+vardef mpversiongt (expr s) = mpversioncmp(s, ">") enddef ;
+
+%D We always want \EPS\ conforming output, so we say:
+
+prologues := 1 ;
+warningcheck := 0 ;
+mpprocset := 1 ;
+
+%D Namespace handling:
+
+% let exclamationmark = ! ;
+% let questionmark = ? ;
+%
+% def unprotect =
+% let ! = relax ;
+% let ? = relax ;
+% enddef ;
+%
+% def protect =
+% let ! = exclamationmark ;
+% let ? = questionmark ;
+% enddef ;
+%
+% unprotect ;
+%
+% mp!some!module = 10 ; show mp!some!module ; show somemodule ;
+%
+% protect ;
+
+%D A semicolor to be used in specials: ? ? ?
+
+string semicolor ; semicolor := char 59 ;
+
+%D By including this module, \METAPOST\ automatically writes a
+%D high resolution boundingbox to the \POSTSCRIPT\ file. This
+%D hack is due to John Hobby himself.
+
+% When somehow the first one gets no HiRes, then make sure
+% that the format matches the mem sizes in the config file.
+
+% eerste " " er uit
+
+string space ; space = char 32 ;
+
+vardef ddecimal primary p =
+ decimal xpart p & " " & decimal ypart p
+enddef ;
+
+% is now built in
+
+% extra_endfig := extra_endfig
+% & "special "
+% & "("
+% & ditto
+% & "%%HiResBoundingBox: "
+% & ditto
+% & "&ddecimal llcorner currentpicture"
+% & "&space"
+% & "&ddecimal urcorner currentpicture"
+% & ");";
+
+%D Crap (experimental, not used):
+
+def forcemultipass =
+ % extra_endfig := extra_endfig & "special(" & ditto & "%%MetaPostOption: multipass" & ditto & ");" ;
+enddef ;
+
+%D Colors:
+
+nocolormodel := 1 ;
+greycolormodel := 3 ;
+rgbcolormodel := 5 ;
+cmykcolormodel := 7 ;
+
+let grayscale = numeric ;
+
+% def colorlike(expr c) text v = % colorlike(a) b, c, d ;
+% forsuffixes i=v : % save i ;
+% if cmykcolor c :
+% cmykcolor i ;
+% elseif rgbcolor c :
+% rgbcolor i ;
+% else :
+% grayscale i ;
+% fi ;
+% endfor ;
+% enddef ;
+
+vardef colorlike(text c) text v = % colorlike(a) b, c, d ;
+ save _p_ ; picture _p_ ;
+ forsuffixes i=v :
+ _p_ := image(draw origin withcolor c ;) ; % intercept pre and postscripts
+ if (colormodel _p_ = cmykcolormodel) :
+ cmykcolor i ;
+ elseif (colormodel _p_ = rgbcolormodel) :
+ rgbcolor i ;
+ else :
+ grayscale i ;
+ fi ;
+ endfor ;
+enddef ;
+
+% if (unknown colormodel) :
+% def colormodel =
+% rgbcolormodel
+% enddef ;
+% fi ;
+
+%D Also handy (when we flush colors):
+
+vardef dddecimal primary c =
+ decimal redpart c & " " & decimal greenpart c & " " & decimal bluepart c
+enddef ;
+
+vardef ddddecimal primary c =
+ decimal cyanpart c & " " & decimal magentapart c & " " & decimal yellowpart c & " " & decimal blackpart c
+enddef ;
+
+vardef colordecimals primary c =
+ if cmykcolor c :
+ decimal cyanpart c & ":" & decimal magentapart c & ":" & decimal yellowpart c & ":" & decimal blackpart c
+ elseif rgbcolor c :
+ decimal redpart c & ":" & decimal greenpart c & ":" & decimal bluepart c
+ else :
+ decimal c
+ fi
+enddef ;
+
+%D We have standardized data file names:
+
+def job_name =
+ jobname
+enddef ;
+
+def data_mpd_file =
+ job_name & "-mp.mpd"
+enddef ;
+
+%D Because \METAPOST\ has a hard coded limit of 4~datafiles,
+%D we need some trickery when we have multiple files.
+
+if unknown collapse_data :
+ boolean collapse_data ; collapse_data := false ;
+fi ;
+
+boolean savingdata ; savingdata := false ;
+boolean savingdatadone ; savingdatadone := false ;
+
+def savedata expr txt =
+ if collapse_data :
+ write txt to data_mpd_file ;
+ else :
+ write if savingdata : txt else :
+ "\MPdata{" & decimal charcode & "}{" & txt & "}"
+ fi
+ & "%" to data_mpd_file ;
+ fi ;
+enddef ;
+
+def startsavingdata =
+ savingdata := true ;
+ savingdatadone := true ;
+ if collapse_data :
+ write
+ "\MPdata{" & decimal charcode & "}{%"
+ to
+ data_mpd_file ;
+ fi ;
+enddef ;
+
+def stopsavingdata =
+ if collapse_data :
+ write "}%" to data_mpd_file ;
+ fi ;
+ savingdata := false ;
+enddef ;
+
+def finishsavingdata =
+ if savingdatadone :
+ write EOF to data_mpd_file ;
+ savingdatadone := false ;
+ fi ;
+enddef ;
+
+%D Instead of a keystroke eating save and allocation
+%D sequence, you can use the \citeer {new} alternatives to
+%D save and allocate in one command.
+
+def newcolor text v = forsuffixes i=v : save i ; color i ; endfor ; enddef ;
+def newnumeric text v = forsuffixes i=v : save i ; numeric i ; endfor ; enddef ;
+def newboolean text v = forsuffixes i=v : save i ; boolean i ; endfor ; enddef ;
+def newtransform text v = forsuffixes i=v : save i ; transform i ; endfor ; enddef ;
+def newpath text v = forsuffixes i=v : save i ; path i ; endfor ; enddef ;
+def newpicture text v = forsuffixes i=v : save i ; picture i ; endfor ; enddef ;
+def newstring text v = forsuffixes i=v : save i ; string i ; endfor ; enddef ;
+
+%D Sometimes we don't want parts of the graphics add to the
+%D bounding box. One way of doing this is to save the bounding
+%D box, draw the graphics that may not count, and restore the
+%D bounding box.
+%D
+%D \starttypen
+%D push_boundingbox currentpicture;
+%D pop_boundingbox currentpicture;
+%D \stoptypen
+%D
+%D The bounding box can be called with:
+%D
+%D \starttypen
+%D boundingbox currentpicture
+%D inner_boundingbox currentpicture
+%D outer_boundingbox currentpicture
+%D \stoptypen
+%D
+%D Especially the latter one can be of use when we include
+%D the graphic in a document that is clipped to the bounding
+%D box. In such occasions one can use:
+%D
+%D \starttypen
+%D set_outer_boundingbox currentpicture;
+%D \stoptypen
+%D
+%D Its counterpart is:
+%D
+%D \starttypen
+%D set_inner_boundingbox p
+%D \stoptypen
+
+path pushed_boundingbox;
+
+def push_boundingbox text p =
+ pushed_boundingbox := boundingbox p;
+enddef;
+
+def pop_boundingbox text p =
+ setbounds p to pushed_boundingbox;
+enddef;
+
+vardef boundingbox primary p =
+ if (path p) or (picture p) :
+ llcorner p -- lrcorner p -- urcorner p -- ulcorner p
+ else :
+ origin
+ fi -- cycle
+enddef;
+
+vardef inner_boundingbox primary p =
+ top rt llcorner p --
+ top lft lrcorner p --
+ bot lft urcorner p --
+ bot rt ulcorner p -- cycle
+enddef;
+
+vardef outer_boundingbox primary p =
+ bot lft llcorner p --
+ bot rt lrcorner p --
+ top rt urcorner p --
+ top lft ulcorner p -- cycle
+enddef;
+
+def innerboundingbox = inner_boundingbox enddef ;
+def outerboundingbox = outer_boundingbox enddef ;
+
+vardef set_inner_boundingbox text q =
+ setbounds q to inner_boundingbox q;
+enddef;
+
+vardef set_outer_boundingbox text q =
+ setbounds q to outer_boundingbox q;
+enddef;
+
+%D Some missing functions can be implemented rather
+%D straightforward:
+
+numeric Pi ; Pi := 3.1415926 ;
+
+vardef sqr primary x = (x*x) enddef ;
+vardef log primary x = (if x=0: 0 else: mlog(x)/mlog(10) fi) enddef ;
+vardef ln primary x = (if x=0: 0 else: mlog(x)/256 fi) enddef ;
+vardef exp primary x = ((mexp 256)**x) enddef ;
+vardef inv primary x = (if x=0: 0 else: x**-1 fi) enddef ;
+
+vardef pow (expr x,p) = (x**p) enddef ;
+
+vardef asin primary x = (x+(x**3)/6+3(x**5)/40) enddef ;
+vardef acos primary x = (asin(-x)) enddef ;
+vardef atan primary x = (x-(x**3)/3+(x**5)/5-(x**7)/7) enddef ;
+vardef tand primary x = (sind(x)/cosd(x)) enddef ;
+
+%D Here are Taco Hoekwater's alternatives (but
+%D vardef'd and primaried).
+
+pi := 3.1415926 ; radian := 180/pi ; % 2pi*radian = 360 ;
+
+vardef tand primary x = (sind(x)/cosd(x)) enddef ;
+vardef cotd primary x = (cosd(x)/sind(x)) enddef ;
+
+vardef sin primary x = (sind(x*radian)) enddef ;
+vardef cos primary x = (cosd(x*radian)) enddef ;
+vardef tan primary x = (sin(x)/cos(x)) enddef ;
+vardef cot primary x = (cos(x)/sin(x)) enddef ;
+
+vardef asin primary x = angle((1+-+x,x)) enddef ;
+vardef acos primary x = angle((x,1+-+x)) enddef ;
+
+vardef invsin primary x = ((asin(x))/radian) enddef ;
+vardef invcos primary x = ((acos(x))/radian) enddef ;
+
+vardef acosh primary x = ln(x+(x+-+1)) enddef ;
+vardef asinh primary x = ln(x+(x++1)) enddef ;
+
+vardef sinh primary x = save xx ; xx = exp x ; (xx-1/xx)/2 enddef ;
+vardef cosh primary x = save xx ; xx = exp x ; (xx+1/xx)/2 enddef ;
+
+%D We provide two macros for drawing stripes across a shape.
+%D The first method (with the n suffix) uses another method,
+%D slower in calculation, but more efficient when drawn. The
+%D first macro divides the sides into n equal parts. The
+%D first argument specifies the way the lines are drawn, while
+%D the second argument identifier the way the shape is to be
+%D drawn.
+%D
+%D \starttypen
+%D stripe_path_n
+%D (dashed evenly withcolor blue)
+%D (filldraw)
+%D fullcircle xscaled 100 yscaled 40 shifted (50,50) withpen pencircle scaled 4;
+%D \stoptypen
+%D
+%D The a (or angle) alternative supports arbitrary angles and
+%D is therefore more versatile.
+%D
+%D \starttypen
+%D stripe_path_a
+%D (withpen pencircle scaled 2 withcolor red)
+%D (draw)
+%D fullcircle xscaled 100 yscaled 40 withcolor blue;
+%D \stoptypen
+%D
+%D The first alternative obeys:
+
+stripe_n := 10;
+stripe_slot := 3;
+
+%D When no pen dimensions are passed, the slot determines
+%D the spacing.
+%D
+%D The angle alternative is influenced by:
+
+stripe_gap := 5;
+stripe_angle := 45;
+
+def stripe_path_n (text s_spec) (text s_draw) expr s_path =
+ do_stripe_path_n (s_spec) (s_draw) (s_path)
+enddef;
+
+def do_stripe_path_n (text s_spec) (text s_draw) (expr s_path) text s_text =
+ begingroup
+ save curpic, newpic, bb, pp, ww;
+ picture curpic, newpic;
+ path bb, pp;
+ pp := s_path;
+ curpic := currentpicture;
+ currentpicture := nullpicture;
+ s_draw pp s_text;
+ bb := boundingbox currentpicture;
+ newpic := currentpicture;
+ currentpicture := nullpicture;
+ ww := min(ypart urcorner newpic - ypart llcorner newpic,
+ xpart urcorner newpic - xpart llcorner newpic);
+ ww := ww/(stripe_slot*stripe_n);
+ for i=1/stripe_n step 1/stripe_n until 1:
+ draw point (1+i) of bb -- point (3-i) of bb
+ withpen pencircle scaled ww s_spec ;
+ endfor;
+ for i=0 step 1/stripe_n until 1:
+ draw point (3+i) of bb -- point (1-i) of bb
+ withpen pencircle scaled ww s_spec;
+ endfor;
+ clip currentpicture to pp;
+ addto newpic also currentpicture;
+ currentpicture := curpic;
+ addto currentpicture also newpic;
+ endgroup
+enddef;
+
+def stripe_path_a (text s_spec) (text s_draw) expr s_path =
+ do_stripe_path_a (s_spec) (s_draw) (s_path)
+enddef;
+
+def do_stripe_path_a (text s_spec) (text s_draw) (expr s_path) text s_text =
+ begingroup
+ save curpic, newpic, pp; picture curpic, newpic; path pp ;
+ pp := s_path ;
+ curpic := currentpicture;
+ currentpicture := nullpicture;
+ s_draw pp s_text ;
+ def do_stripe_rotation (expr p) =
+ (currentpicture rotatedaround(center p,stripe_angle))
+ enddef ;
+ s_max := max
+ (xpart llcorner do_stripe_rotation(currentpicture),
+ xpart urcorner do_stripe_rotation(currentpicture),
+ ypart llcorner do_stripe_rotation(currentpicture),
+ ypart urcorner do_stripe_rotation(currentpicture));
+ newpic := currentpicture;
+ currentpicture := nullpicture;
+ for i=-s_max-.5stripe_gap step stripe_gap until s_max:
+ draw (-s_max,i)--(s_max,i) s_spec;
+ endfor;
+ currentpicture := do_stripe_rotation(newpic);
+ clip currentpicture to pp ;
+ addto newpic also currentpicture;
+ currentpicture := curpic;
+ addto currentpicture also newpic;
+ endgroup
+enddef;
+
+%D A few normalizing macros:
+%D
+%D \starttypen
+%D xscale_currentpicture ( width )
+%D yscale_currentpicture ( height )
+%D xyscale_currentpicture ( width, height )
+%D scale_currentpicture ( width, height )
+%D \stoptypen
+
+% def xscale_currentpicture(expr the_width) =
+% natural_width := xpart urcorner currentpicture - xpart llcorner currentpicture;
+% currentpicture := currentpicture scaled (the_width/natural_width) ;
+% enddef;
+%
+% def yscale_currentpicture(expr the_height ) =
+% natural_height := ypart urcorner currentpicture - ypart llcorner currentpicture;
+% currentpicture := currentpicture scaled (the_height/natural_height) ;
+% enddef;
+%
+% def xyscale_currentpicture(expr the_width, the_height) =
+% natural_width := xpart urcorner currentpicture - xpart llcorner currentpicture;
+% natural_height := ypart urcorner currentpicture - ypart llcorner currentpicture;
+% currentpicture := currentpicture
+% xscaled (the_width/natural_width)
+% yscaled (the_height/natural_height) ;
+% enddef;
+%
+% def scale_currentpicture(expr the_width, the_height) =
+% xscale_currentpicture(the_width) ;
+% yscale_currentpicture(the_height) ;
+% enddef;
+
+% nog eens uitbreiden zodat path en pic worden afgehandeld.
+
+% natural_width := xpart urcorner currentpicture - xpart llcorner currentpicture;
+% currentpicture := currentpicture scaled (the_width/natural_width) ;
+
+% TODO TODO TODO TODO, not yet ok
+
+primarydef p xsized w =
+ (p if (bbwidth (p)>0) and (w>0) : scaled (w/bbwidth (p)) fi)
+enddef ;
+
+primarydef p ysized h =
+ (p if (bbheight(p)>0) and (h>0) : scaled (h/bbheight(p)) fi)
+enddef ;
+
+primarydef p xysized s =
+ begingroup ;
+ save wh, w, h ; pair wh ; numeric w, h ;
+ wh := paired (s) ; w := bbwidth(p) ; h := bbheight(p) ;
+ (p if (w>0) and (h>0) :
+ if xpart wh > 0 : xscaled (xpart wh/w) fi
+ if ypart wh > 0 : yscaled (ypart wh/h) fi
+ fi)
+ endgroup
+enddef ;
+
+primarydef p sized wh =
+ (p xysized wh)
+enddef ;
+
+def xscale_currentpicture(expr w) =
+ currentpicture := currentpicture xsized w ;
+enddef;
+
+def yscale_currentpicture(expr h) =
+ currentpicture := currentpicture ysized h ;
+enddef;
+
+def xyscale_currentpicture(expr w, h) =
+ currentpicture := currentpicture xysized (w,h) ;
+enddef;
+
+def scale_currentpicture(expr w, h) =
+ currentpicture := currentpicture xsized w ;
+ currentpicture := currentpicture ysized h ;
+enddef;
+
+%D A full circle is centered at the origin, while a unitsquare
+%D is located in the first quadrant. Now guess what kind of
+%D path fullsquare and unitcircle do return.
+
+path fullsquare, unitcircle ;
+
+fullsquare := unitsquare shifted - center unitsquare ;
+unitcircle := fullcircle shifted urcorner fullcircle ;
+
+%D Some more paths:
+
+path urcircle, ulcircle, llcircle, lrcircle ;
+
+urcircle := origin--(+.5,0)&(+.5,0){up} ..(0,+.5)&(0,+.5)--cycle ;
+ulcircle := origin--(0,+.5)&(0,+.5){left} ..(-.5,0)&(-.5,0)--cycle ;
+llcircle := origin--(-.5,0)&(-.5,0){down} ..(0,-.5)&(0,-.5)--cycle ;
+lrcircle := origin--(0,-.5)&(0,-.5){right}..(+.5,0)&(+.5,0)--cycle ;
+
+path tcircle, bcircle, lcircle, rcircle ;
+
+tcircle = origin--(+.5,0)&(+.5,0){up} ..(0,+.5)..{down} (-.5,0)--cycle ;
+bcircle = origin--(-.5,0)&(-.5,0){down} ..(0,-.5)..{up} (+.5,0)--cycle ;
+lcircle = origin--(0,+.5)&(0,+.5){left} ..(-.5,0)..{right}(0,-.5)--cycle ;
+rcircle = origin--(0,-.5)&(0,-.5){right}..(+.5,0)..{left} (0,+.5)--cycle ;
+
+path urtriangle, ultriangle, lltriangle, lrtriangle ;
+
+urtriangle := origin--(+.5,0)--(0,+.5)--cycle ;
+ultriangle := origin--(0,+.5)--(-.5,0)--cycle ;
+lltriangle := origin--(-.5,0)--(0,-.5)--cycle ;
+lrtriangle := origin--(0,-.5)--(+.5,0)--cycle ;
+
+path unitdiamond, fulldiamond ;
+
+unitdiamond := (.5,0)--(1,.5)--(.5,1)--(0,.5)--cycle ;
+fulldiamond := unitdiamond shifted - center unitdiamond ;
+
+%D More robust:
+
+% let normalscaled = scaled ;
+% let normalxscaled = xscaled ;
+% let normalyscaled = yscaled ;
+%
+% def scaled expr s = normalscaled (s) enddef ;
+% def xscaled expr s = normalxscaled (s) enddef ;
+% def yscaled expr s = normalyscaled (s) enddef ;
+
+%D Shorter
+
+primarydef p xyscaled q =
+ begingroup ; save qq ; pair qq ; qq = paired(q) ;
+ ( p
+ if xpart qq<>0 : xscaled (xpart qq) fi
+ if ypart qq<>0 : yscaled (ypart qq) fi )
+ endgroup
+enddef ;
+
+%D Experimenteel, zie folder-3.tex.
+
+def set_grid(expr w, h, nx, ny) =
+ boolean grid[][] ; boolean grid_full ;
+ grid_w := w ;
+ grid_h := h ;
+ grid_nx := nx ;
+ grid_ny := ny ;
+ grid_x := round(w/grid_nx) ; % +.5) ;
+ grid_y := round(h/grid_ny) ; % +.5) ;
+ grid_left := (1+grid_x)*(1+grid_y) ;
+ grid_full := false ;
+ for i=0 upto grid_x:
+ for j=0 upto grid_y:
+ grid[i][j] := false ;
+ endfor ;
+ endfor ;
+enddef ;
+
+vardef new_on_grid(expr _dx_, _dy_) =
+ dx := _dx_ ;
+ dy := _dy_ ;
+ ddx := min(round(dx/grid_nx),grid_x) ; % +.5),grid_x) ;
+ ddy := min(round(dy/grid_ny),grid_y) ; % +.5),grid_y) ;
+ if not grid_full and not grid[ddx][ddy]:
+ grid[ddx][ddy] := true ;
+ grid_left := grid_left-1 ;
+ grid_full := (grid_left=0) ;
+ true
+ else:
+ false
+ fi
+enddef ;
+
+%D usage: \type{innerpath peepholed outerpath}.
+%D
+%D beginfig(1);
+%D def fullsquare = (unitsquare shifted -center unitsquare) enddef ;
+%D fill (fullsquare scaled 200) withcolor red ;
+%D path p ; p := (fullcircle scaled 100) ; bboxmargin := 0 ;
+%D fill p peepholed bbox p ;
+%D endfig;
+
+secondarydef p peepholed q =
+ begingroup ;
+ save start ; pair start ; start := point 0 of p ;
+ if xpart start >= xpart center p :
+ if ypart start >= ypart center p :
+ urcorner q -- ulcorner q -- llcorner q -- lrcorner q --
+ reverse p -- lrcorner q -- cycle
+ else :
+ lrcorner q -- urcorner q -- ulcorner q -- llcorner q --
+ reverse p -- llcorner q -- cycle
+ fi
+ else :
+ if ypart start > ypart center p :
+ ulcorner q -- llcorner q -- lrcorner q -- urcorner q --
+ reverse p -- urcorner q -- cycle
+ else :
+ llcorner q -- lrcorner q -- urcorner q -- ulcorner q --
+ reverse p -- ulcorner q -- cycle
+ fi
+ fi
+ endgroup
+enddef ;
+
+boolean intersection_found ;
+
+secondarydef p intersection_point q =
+ begingroup
+ save x_, y_ ;
+ (x_,y_) = p intersectiontimes q ;
+ if x_<0 :
+ intersection_found := false ;
+ center p % origin
+ else :
+ intersection_found := true ;
+ .5[point x_ of p, point y_ of q]
+ fi
+ endgroup
+enddef ;
+
+%D New, undocumented, experimental:
+
+vardef tensecircle (expr width, height, offset) =
+ ((-width/2,-height/2) ... (0,-height/2-offset) ...
+ (+width/2,-height/2) ... (+width/2+offset,0) ...
+ (+width/2,+height/2) ... (0,+height/2+offset) ...
+ (-width/2,+height/2) ... (-width/2-offset,0) ... cycle)
+enddef ;
+
+%vardef tensecircle (expr width, height, offset) =
+% ((-width/2,-height/2)..(0,-height/2-offset)..(+width/2,-height/2) &
+% (+width/2,-height/2)..(+width/2+offset,0)..(+width/2,+height/2) &
+% (+width/2,+height/2)..(0,+height/2+offset)..(-width/2,+height/2) &
+% (-width/2,+height/2)..(-width/2-offset,0)..(-width/2,-height/2)..cycle)
+%enddef ;
+
+vardef roundedsquare (expr width, height, offset) =
+ ((offset,0)--(width-offset,0){right} ..
+ (width,offset)--(width,height-offset){up} ..
+ (width-offset,height)--(offset,height){left} ..
+ (0,height-offset)--(0,offset){down} .. cycle)
+enddef ;
+
+%D Some colors.
+
+color cyan ; cyan = (0,1,1) ;
+color magenta ; magenta = (1,0,1) ;
+color yellow ; yellow = (1,1,0) ;
+
+def colortype(expr c) =
+ if cmykcolor c : cmykcolor elseif rgbcolor c : rgbcolor else : grayscale fi
+enddef ;
+vardef whitecolor(expr c) =
+ if cmykcolor c : (0,0,0,0) elseif rgbcolor c : (1,1,1) else : 1 fi
+enddef ;
+vardef blackcolor(expr c) =
+ if cmykcolor c : (0,0,0,1) elseif rgbcolor c : (0,0,0) else : 0 fi
+enddef ;
+
+%D Well, this is the dangerous and naive version:
+
+def drawfill text t =
+ fill t ;
+ draw t ;
+enddef;
+
+%D This two step approach saves the path first, since it can
+%D be a function. Attributes must not be randomized.
+
+def drawfill expr c =
+ path _c_ ; _c_ := c ;
+ do_drawfill
+enddef ;
+
+def do_drawfill text t =
+ draw _c_ t ;
+ fill _c_ t ;
+enddef;
+
+def undrawfill expr c =
+ drawfill c withcolor background
+enddef ;
+
+%D Moved from mp-char.mp
+
+vardef paired (expr d) =
+ if pair d : d else : (d,d) fi
+enddef ;
+
+vardef tripled (expr d) =
+ if color d : d else : (d,d,d) fi
+enddef ;
+
+primarydef p enlarged d =
+ (p llmoved d -- p lrmoved d -- p urmoved d -- p ulmoved d -- cycle)
+enddef;
+
+primarydef p llenlarged d =
+ (p llmoved d -- lrcorner p -- urcorner p -- ulcorner p -- cycle)
+enddef ;
+
+primarydef p lrenlarged d =
+ (llcorner p -- p lrmoved d -- urcorner p -- ulcorner p -- cycle)
+enddef ;
+
+primarydef p urenlarged d =
+ (llcorner p -- lrcorner p -- p urmoved d -- ulcorner p -- cycle)
+enddef ;
+
+primarydef p ulenlarged d =
+ (llcorner p -- lrcorner p -- urcorner p -- p ulmoved d -- cycle)
+enddef ;
+
+primarydef p llmoved d =
+ ((llcorner p) shifted (-xpart paired(d),-ypart paired(d)))
+enddef ;
+
+primarydef p lrmoved d =
+ ((lrcorner p) shifted (+xpart paired(d),-ypart paired(d)))
+enddef ;
+
+primarydef p urmoved d =
+ ((urcorner p) shifted (+xpart paired(d),+ypart paired(d)))
+enddef ;
+
+primarydef p ulmoved d =
+ ((ulcorner p) shifted (-xpart paired(d),+ypart paired(d)))
+enddef ;
+
+primarydef p leftenlarged d =
+ ((llcorner p) shifted (-d,0) -- lrcorner p --
+ urcorner p -- (ulcorner p) shifted (-d,0) -- cycle)
+enddef ;
+
+primarydef p rightenlarged d =
+ (llcorner p -- (lrcorner p) shifted (d,0) --
+ (urcorner p) shifted (d,0) -- ulcorner p -- cycle)
+enddef ;
+
+primarydef p topenlarged d =
+ (llcorner p -- lrcorner p --
+ (urcorner p) shifted (0,d) -- (ulcorner p) shifted (0,d) -- cycle)
+enddef ;
+
+primarydef p bottomenlarged d =
+ (llcorner p shifted (0,-d) -- lrcorner p shifted (0,-d) --
+ urcorner p -- ulcorner p -- cycle)
+enddef ;
+
+%D Handy for testing/debugging:
+
+primarydef p crossed d =
+ if pair p :
+ (p shifted (-d, 0) -- p --
+ p shifted ( 0,-d) -- p --
+ p shifted (+d, 0) -- p --
+ p shifted ( 0,+d) -- p -- cycle)
+ else :
+ (center p shifted (-d, 0) -- llcorner p --
+ center p shifted ( 0,-d) -- lrcorner p --
+ center p shifted (+d, 0) -- urcorner p --
+ center p shifted ( 0,+d) -- ulcorner p -- cycle)
+ fi
+enddef ;
+
+%D Also handy (math ladders):
+
+vardef laddered expr p =
+ point 0 of p
+ for i=1 upto length(p) :
+ -- (xpart (point i of p), ypart (point (i-1) of p)) -- (point i of p)
+ endfor
+enddef ;
+
+%D Saves typing:
+
+% vardef bottomboundary primary p = (llcorner p -- lrcorner p) enddef ;
+% vardef rightboundary primary p = (lrcorner p -- urcorner p) enddef ;
+% vardef topboundary primary p = (urcorner p -- ulcorner p) enddef ;
+% vardef leftboundary primary p = (ulcorner p -- llcorner p) enddef ;
+
+vardef bottomboundary primary p =
+ if pair p : p else : (llcorner p -- lrcorner p) fi
+enddef ;
+
+vardef rightboundary primary p =
+ if pair p : p else : (lrcorner p -- urcorner p) fi
+enddef ;
+
+vardef topboundary primary p =
+ if pair p : p else : (urcorner p -- ulcorner p) fi
+enddef ;
+
+vardef leftboundary primary p =
+ if pair p : p else : (ulcorner p -- llcorner p) fi
+enddef ;
+
+%D Nice too:
+
+primarydef p superellipsed s =
+ superellipse
+ (.5[lrcorner p,urcorner p],
+ .5[urcorner p,ulcorner p],
+ .5[ulcorner p,llcorner p],
+ .5[llcorner p,lrcorner p],
+ s)
+enddef ;
+
+primarydef p squeezed s =
+ ((llcorner p .. .5[llcorner p,lrcorner p] shifted ( 0, ypart paired(s)) .. lrcorner p) &
+ (lrcorner p .. .5[lrcorner p,urcorner p] shifted (-xpart paired(s), 0) .. urcorner p) &
+ (urcorner p .. .5[urcorner p,ulcorner p] shifted ( 0,-ypart paired(s)) .. ulcorner p) &
+ (ulcorner p .. .5[ulcorner p,llcorner p] shifted ( xpart paired(s), 0) .. llcorner p) & cycle)
+enddef ;
+
+primarydef p randomshifted s =
+ begingroup ; save ss ; pair ss ; ss := paired(s) ;
+ p shifted (-.5xpart ss + uniformdeviate xpart ss,
+ -.5ypart ss + uniformdeviate ypart ss)
+ endgroup
+enddef ;
+
+%primarydef p randomized s =
+% for i=0 upto length(p)-1 :
+% ((point i of p) randomshifted s) .. controls
+% ((postcontrol i of p) randomshifted s) and
+% ((precontrol (i+1) of p) randomshifted s) ..
+% endfor cycle
+%enddef ;
+
+primarydef p randomized s =
+ (if path p :
+ for i=0 upto length(p)-1 :
+ ((point i of p) randomshifted s) .. controls
+ ((postcontrol i of p) randomshifted s) and
+ ((precontrol (i+1) of p) randomshifted s) ..
+ endfor
+ if cycle p :
+ cycle
+ else :
+ ((point length(p) of p) randomshifted s)
+ fi
+ elseif pair p :
+ p randomshifted s
+ elseif cmykcolor p :
+ if color s :
+ (uniformdeviate cyanpart s * cyanpart p,
+ uniformdeviate magentapart s * magentapart p,
+ uniformdeviate yellowpart s * yellowpart p,
+ uniformdeviate blackpart s * blackpart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
+ elseif rgbcolor p :
+ if color s :
+ (uniformdeviate redpart s * redpart p,
+ uniformdeviate greenpart s * greenpart p,
+ uniformdeviate bluepart s * bluepart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
+ elseif color p :
+ if color s :
+ (uniformdeviate graypart s * graypart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
+ else :
+ p + uniformdeviate s
+ fi)
+enddef ;
+
+%D Not perfect (alternative for interpath)
+
+vardef interpolated(expr s, p, q) =
+ save m ; m := max(length(p),length(q)) ;
+ (if path p :
+ for i=0 upto m-1 :
+ s[point (i /m) along p,
+ point (i /m) along q] .. controls
+ s[postcontrol (i /m) along p,
+ postcontrol (i /m) along q] and
+ s[precontrol ((i+1)/m) along p,
+ precontrol ((i+1)/m) along q] ..
+ endfor
+ if cycle p :
+ cycle
+ else :
+ s[point infinity of p,
+ point infinity of q]
+ fi
+ else :
+ a[p,q]
+ fi)
+enddef ;
+
+%D Interesting too:
+
+% primarydef p parallel s =
+% begingroup ; save q, b ; path q ; numeric b ;
+% b := xpart (lrcorner p - llcorner p) ;
+% q := p if b>0 : scaled ((b+2s)/b) fi ;
+% (q shifted (center p-center q))
+% endgroup
+% enddef ;
+
+%primarydef p parallel s =
+% begingroup ; save q, w,h ; path q ; numeric w, h ;
+% w := bbwidth(p) ; h := bbheight(p) ;
+% q := p if (w>0) and (h>0) :
+% xyscaled ((w+2*xpart paired(s))/w,(h+2*ypart paired(s))/h) fi ;
+% (q shifted (center p-center q))
+% endgroup
+%enddef ;
+
+primarydef p paralleled d =
+ p shifted if d < 0 : - fi ((point abs(d) on (p rotatedaround(point 0 of p,90))) - point 0 of p)
+enddef ;
+
+vardef punked primary p =
+ (point 0 of p for i=1 upto length(p)-1 : -- point i of p endfor
+ if cycle p : -- cycle else : -- point length(p) of p fi)
+enddef ;
+
+vardef curved primary p =
+ (point 0 of p for i=1 upto length(p)-1 : .. point i of p endfor
+ if cycle p : .. cycle else : .. point length(p) of p fi)
+enddef ;
+
+primarydef p blownup s =
+ begingroup
+ save _p_ ; path _p_ ; _p_ := p xysized
+ (bbwidth (p)+2(xpart paired(s)),
+ bbheight(p)+2(ypart paired(s))) ;
+ (_p_ shifted (center p - center _p_))
+ endgroup
+enddef ;
+
+%D Rather fundamental.
+
+% not yet ok
+
+def leftrightpath(expr p, l) = % used in s-pre-19
+ save q, r, t, b ; path q, r ; pair t, b ;
+ t := (ulcorner p -- urcorner p) intersection_point p ;
+ b := (llcorner p -- lrcorner p) intersection_point p ;
+ r := if xpart directionpoint t of p < 0 : reverse p else : p fi ; % r is needed, else problems when reverse is fed
+ q := r cutbefore if l: t else: b fi ;
+ q := q if xpart point 0 of r > 0 : &
+ r fi cutafter if l: b else: t fi ;
+ q
+enddef ;
+
+vardef leftpath expr p = leftrightpath(p,true ) enddef ;
+vardef rightpath expr p = leftrightpath(p,false) enddef ;
+
+%D Drawoptions
+
+def saveoptions =
+ save _op_ ; def _op_ = enddef ;
+enddef ;
+
+%D Tracing.
+
+let normaldraw = draw ;
+let normalfill = fill ;
+
+% bugged in mplib so ...
+
+def normalfill expr c = addto currentpicture contour c _op_ enddef ;
+def normaldraw expr p = addto currentpicture if picture p: also p else: doublepath p withpen currentpen fi _op_ enddef ;
+
+
+def drawlineoptions (text t) = def _lin_opt_ = t enddef ; enddef ;
+def drawpointoptions (text t) = def _pnt_opt_ = t enddef ; enddef ;
+def drawcontroloptions(text t) = def _ctr_opt_ = t enddef ; enddef ;
+def drawlabeloptions (text t) = def _lab_opt_ = t enddef ; enddef ;
+def draworiginoptions (text t) = def _ori_opt_ = t enddef ; enddef ;
+def drawboundoptions (text t) = def _bnd_opt_ = t enddef ; enddef ;
+def drawpathoptions (text t) = def _pth_opt_ = t enddef ; enddef ;
+
+def resetdrawoptions =
+ drawlineoptions (withpen pencircle scaled 1pt withcolor .5white) ;
+ drawpointoptions (withpen pencircle scaled 4pt withcolor black) ;
+ drawcontroloptions(withpen pencircle scaled 2.5pt withcolor black) ;
+ drawlabeloptions () ;
+ draworiginoptions (withpen pencircle scaled 1pt withcolor .5white) ;
+ drawboundoptions (dashed evenly _ori_opt_) ;
+ drawpathoptions (withpen pencircle scaled 5pt withcolor .8white) ;
+enddef ;
+
+resetdrawoptions ;
+
+%D Path.
+
+def drawpath expr p =
+ normaldraw p _pth_opt_
+enddef ;
+
+%D Arrow.
+
+vardef drawarrowpath expr p =
+ save autoarrows ; boolean autoarrows ; autoarrows := true ;
+ drawarrow p _pth_opt_
+enddef ;
+
+%def drawarrowpath expr p =
+% begingroup ;
+% save autoarrows ; boolean autoarrows ; autoarrows := true ;
+% save arrowpath ; path arrowpath ; arrowpath := p ;
+% _drawarrowpath_
+%enddef ;
+%
+%def _drawarrowpath_ text t =
+% drawarrow arrowpath _pth_opt_ t ;
+% endgroup ;
+%enddef ;
+
+def midarrowhead expr p =
+ arrowhead p cutafter
+ (point length(p cutafter point .5 along p)+ahlength on p)
+enddef ;
+
+vardef arrowheadonpath (expr p, s) =
+ save autoarrows ; boolean autoarrows ; autoarrows := true ;
+ set_ahlength(scaled ahfactor) ; % added
+ arrowhead p if s<1 : cutafter (point (s*arclength(p)+.5ahlength) on p) fi
+enddef ;
+
+%D Points.
+
+def drawpoint expr c =
+ if string c :
+ string _c_ ; _c_ := "(" & c & ")" ;
+ dotlabel.urt(_c_, scantokens _c_) ;
+ drawdot scantokens _c_
+ else :
+ dotlabel.urt("(" & decimal xpart c & "," & decimal ypart c & ")", c) ;
+ drawdot c
+ fi _pnt_opt_
+enddef ;
+
+%D PathPoints.
+
+def drawpoints expr c = path _c_ ; _c_ := c ; do_drawpoints enddef ;
+def drawcontrolpoints expr c = path _c_ ; _c_ := c ; do_drawcontrolpoints enddef ;
+def drawcontrollines expr c = path _c_ ; _c_ := c ; do_drawcontrollines enddef ;
+def drawpointlabels expr c = path _c_ ; _c_ := c ; do_drawpointlabels enddef ;
+
+def do_drawpoints text t =
+ for _i_=0 upto length(_c_) :
+ normaldraw point _i_ of _c_ _pnt_opt_ t ;
+ endfor ;
+enddef;
+
+def do_drawcontrolpoints text t =
+ for _i_=0 upto length(_c_) :
+ normaldraw precontrol _i_ of _c_ _ctr_opt_ t ;
+ normaldraw postcontrol _i_ of _c_ _ctr_opt_ t ;
+ endfor ;
+enddef;
+
+def do_drawcontrollines text t =
+ for _i_=0 upto length(_c_) :
+ normaldraw point _i_ of _c_ -- precontrol _i_ of _c_ _lin_opt_ t ;
+ normaldraw point _i_ of _c_ -- postcontrol _i_ of _c_ _lin_opt_ t ;
+ endfor ;
+enddef;
+
+boolean swappointlabels ; swappointlabels := false ;
+
+def do_drawpointlabels text t =
+ for _i_=0 upto length(_c_) :
+ pair _u_ ; _u_ := unitvector(direction _i_ of _c_)
+ rotated if swappointlabels : - fi 90 ;
+ pair _p_ ; _p_ := (point _i_ of _c_) ;
+ _u_ := 12 * defaultscale * _u_ ;
+ normaldraw thelabel ( decimal _i_,
+ _p_ shifted if cycle _c_ and (_i_=0) : - fi _u_ ) _lab_opt_ t ;
+ endfor ;
+enddef;
+
+%D Bounding box.
+
+def drawboundingbox expr p =
+ normaldraw boundingbox p _bnd_opt_
+enddef ;
+
+%D Origin.
+
+numeric originlength ; originlength := .5cm ;
+
+def draworigin text t =
+ normaldraw (origin shifted (0, originlength) --
+ origin shifted (0,-originlength)) _ori_opt_ t ;
+ normaldraw (origin shifted ( originlength,0) --
+ origin shifted (-originlength,0)) _ori_opt_ t ;
+enddef;
+
+%D Axis.
+
+numeric tickstep ; tickstep := 5mm ;
+numeric ticklength ; ticklength := 2mm ;
+
+def drawxticks expr c = path _c_ ; _c_ := c ; do_drawxticks enddef ;
+def drawyticks expr c = path _c_ ; _c_ := c ; do_drawyticks enddef ;
+def drawticks expr c = path _c_ ; _c_ := c ; do_drawticks enddef ;
+
+% Adding eps prevents disappearance due to rounding errors.
+
+def do_drawxticks text t =
+ for i=0 step -tickstep until xpart llcorner _c_ - eps :
+ if (i<=xpart lrcorner _c_) :
+ normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ for i=0 step tickstep until xpart lrcorner _c_ + eps :
+ if (i>=xpart llcorner _c_) :
+ normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ normaldraw (llcorner _c_ -- ulcorner _c_)
+ shifted (-xpart llcorner _c_,0) _ori_opt_ t ;
+enddef ;
+
+def do_drawyticks text t =
+ for i=0 step -tickstep until ypart llcorner _c_ - eps :
+ if (i<=ypart ulcorner _c_) :
+ normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ for i=0 step tickstep until ypart ulcorner _c_ + eps :
+ if (i>=ypart llcorner _c_) :
+ normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ normaldraw (llcorner _c_ -- lrcorner _c_)
+ shifted (0,-ypart llcorner _c_) _ori_opt_ t ;
+enddef ;
+
+def do_drawticks text t =
+ drawxticks _c_ t ;
+ drawyticks _c_ t ;
+enddef ;
+
+%D All of it except axis.
+
+def drawwholepath expr p =
+ draworigin ;
+ drawpath p ;
+ drawcontrollines p ;
+ drawcontrolpoints p ;
+ drawpoints p ;
+ drawboundingbox p ;
+ drawpointlabels p ;
+enddef ;
+
+%D Tracing.
+
+def visualizeddraw expr c =
+ if picture c : normaldraw c else : path _c_ ; _c_ := c ; do_visualizeddraw fi
+enddef ;
+
+def visualizedfill expr c =
+ if picture c : normalfill c else : path _c_ ; _c_ := c ; do_visualizedfill fi
+enddef ;
+
+def do_visualizeddraw text t =
+ draworigin ;
+ drawpath _c_ t ;
+ drawcontrollines _c_ ;
+ drawcontrolpoints _c_ ;
+ drawpoints _c_ ;
+ drawboundingbox _c_ ;
+ drawpointlabels _c_ ;
+enddef ;
+
+def do_visualizedfill text t =
+ if cycle _c_ : normalfill _c_ t fi ;
+ draworigin ;
+ drawcontrollines _c_ ;
+ drawcontrolpoints _c_ ;
+ drawpoints _c_ ;
+ drawboundingbox _c_ ;
+ drawpointlabels _c_ ;
+enddef ;
+
+def visualizepaths =
+ let fill = visualizedfill ;
+ let draw = visualizeddraw ;
+enddef ;
+
+def naturalizepaths =
+ let fill = normalfill ;
+ let draw = normaldraw ;
+enddef ;
+
+extra_endfig := extra_endfig & " naturalizepaths ; " ;
+
+%D Also handy:
+
+extra_beginfig := extra_beginfig & " truecorners := 0 ; " ; % restores
+extra_beginfig := extra_beginfig & " miterlimit := 10 ; " ; % restores
+extra_beginfig := extra_beginfig & " linejoin := rounded ; " ; % restores
+extra_beginfig := extra_beginfig & " linecap := rounded ; " ; % restores
+
+%D Normally, arrowheads don't scale well. So we provide a
+%D hack.
+
+boolean autoarrows ; autoarrows := false ;
+numeric ahfactor ; ahfactor := 2.5 ;
+
+def set_ahlength (text t) =
+% ahlength := (ahfactor*pen_size(_op_ t)) ; % _op_ added
+% problem: _op_ can contain color so a no-go, we could apply the transform
+% but i need to figure out the best way (fakepicture and take components).
+ ahlength := (ahfactor*pen_size(t)) ;
+enddef ;
+
+vardef pen_size (text t) =
+ save p ; picture p ; p := nullpicture ;
+ addto p doublepath (top origin -- bot origin) t ;
+ (ypart urcorner p - ypart lrcorner p)
+enddef ;
+
+%D The next two macros are adapted versions of plain
+%D \METAPOST\ definitions.
+
+def _finarr text t =
+ if autoarrows : set_ahlength (t) fi ;
+ draw _apth t ;
+ filldraw arrowhead _apth t ;
+enddef;
+
+def _findarr text t =
+ if autoarrows : set_ahlength (t) fi ;
+ draw _apth t ;
+ fill arrowhead _apth withpen currentpen t ;
+ fill arrowhead reverse _apth withpen currentpen t ;
+enddef ;
+
+%D Handy too ......
+
+vardef pointarrow (expr pat, loc, len, off) =
+ save l, r, s, t ; path l, r ; numeric s ; pair t ;
+ t := if pair loc : loc else : point loc along pat fi ;
+ s := len/2 - off ; if s<=0 : s := 0 elseif s>len : s := len fi ;
+ r := pat cutbefore t ;
+ r := (r cutafter point (arctime s of r) of r) ;
+ s := len/2 + off ; if s<=0 : s := 0 elseif s>len : s := len fi ;
+ l := reverse (pat cutafter t) ;
+ l := (reverse (l cutafter point (arctime s of l) of l)) ;
+ (l..r)
+enddef ;
+
+def rightarrow (expr pat,tim,len) = pointarrow(pat,tim,len,-len) enddef ;
+def leftarrow (expr pat,tim,len) = pointarrow(pat,tim,len,+len) enddef ;
+def centerarrow (expr pat,tim,len) = pointarrow(pat,tim,len, 0) enddef ;
+
+%D The \type {along} and \type {on} operators can be used
+%D as follows:
+%D
+%D \starttypen
+%D drawdot point .5 along somepath ;
+%D drawdot point 3cm on somepath ;
+%D \stoptypen
+%D
+%D The number denotes a percentage (fraction).
+
+primarydef pct along pat = % also negative
+ (arctime (pct * (arclength pat)) of pat) of pat
+enddef ;
+
+% primarydef len on pat =
+% (arctime len of pat) of pat
+% enddef ;
+
+primarydef len on pat =
+ (arctime if len>0 : len else : (arclength(pat)+len) fi of pat) of pat
+enddef ;
+
+% this cuts of a piece from both ends
+
+% tertiarydef pat cutends len =
+% begingroup ; save tap ; path tap ;
+% tap := pat cutbefore (point len on pat) ;
+% (tap cutafter (point -len on tap))
+% endgroup
+% enddef ;
+
+tertiarydef pat cutends len =
+ begingroup ; save tap ; path tap ;
+ tap := pat cutbefore (point (xpart paired(len)) on pat) ;
+ (tap cutafter (point -(ypart paired(len)) on tap))
+ endgroup
+enddef ;
+
+%D To be documented.
+
+path freesquare ;
+
+freesquare := ((-1,0)--(-1,-1)--(0,-1)--(+1,-1)--
+ (+1,0)--(+1,+1)--(0,+1)--(-1,+1)--cycle) scaled .5 ;
+
+numeric freelabeloffset ; freelabeloffset := 3pt ;
+numeric freedotlabelsize ; freedotlabelsize := 3pt ;
+
+vardef thefreelabel (expr str, loc, ori) =
+ save s, p, q, l ; picture s ; path p, q ; pair l ;
+ interim labeloffset := freelabeloffset ;
+ s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ;
+ setbounds s to boundingbox s enlarged freelabeloffset ;
+ p := fullcircle scaled (2*length(loc-ori)) shifted ori ;
+ q := freesquare xyscaled (urcorner s - llcorner s) ;
+% l := point (xpart (p intersectiontimes (ori--loc))) of q ;
+ l := point xpart (p intersectiontimes
+ (ori--((1+eps)*arclength(ori--loc)*unitvector(loc-ori)))) of q ;
+ setbounds s to boundingbox s enlarged -freelabeloffset ; % new
+ %draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ;
+ (s shifted -l)
+enddef ;
+
+% better?
+
+vardef thefreelabel (expr str, loc, ori) =
+ save s, p, q, l ; picture s ; path p, q ; pair l ;
+ interim labeloffset := freelabeloffset ;
+ s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ;
+ setbounds s to boundingbox s enlarged freelabeloffset ;
+ p := fullcircle scaled (2*length(loc-ori)) shifted ori ;
+ q := freesquare xyscaled (urcorner s - llcorner s) ;
+ l := point xpart (p intersectiontimes (ori--loc shifted (loc-ori))) of q ;
+ setbounds s to boundingbox s enlarged -freelabeloffset ; % new
+ %draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ;
+ (s shifted -l)
+enddef ;
+
+vardef freelabel (expr str, loc, ori) =
+ draw thefreelabel(str,loc,ori) ;
+enddef ;
+
+vardef freedotlabel (expr str, loc, ori) =
+ interim linecap:=rounded ;
+ draw loc withpen pencircle scaled freedotlabelsize ;
+ draw thefreelabel(str,loc,ori) ;
+enddef ;
+
+%D \starttypen
+%D drawarrow anglebetween(line_a,line_b,somelabel) ;
+%D \stoptypen
+
+% angleoffset ; angleoffset := 0pt ;
+numeric anglelength ; anglelength := 20pt ;
+numeric anglemethod ; anglemethod := 1 ;
+
+% vardef anglebetween (expr a, b, str) = % path path string
+% save pointa, pointb, common, middle, offset ;
+% pair pointa, pointb, common, middle, offset ;
+% save curve ; path curve ;
+% save where ; numeric where ;
+% if round point 0 of a = round point 0 of b :
+% common := point 0 of a ;
+% else :
+% common := a intersectionpoint b ;
+% fi ;
+% pointa := point anglelength on a ;
+% pointb := point anglelength on b ;
+% where := turningnumber (common--pointa--pointb--cycle) ;
+% middle := ((common--pointa) rotatedaround (pointa,-where*90))
+% intersectionpoint
+% ((common--pointb) rotatedaround (pointb, where*90)) ;
+% if anglemethod = 0 :
+% curve := pointa{unitvector(middle-pointa)}.. pointb;
+% middle := point .5 along curve ;
+% curve := common ;
+% elseif anglemethod = 1 :
+% curve := pointa{unitvector(middle-pointa)}.. pointb;
+% middle := point .5 along curve ;
+% elseif anglemethod = 2 :
+% middle := common rotatedaround(.5[pointa,pointb],180) ;
+% curve := pointa--middle--pointb ;
+% elseif anglemethod = 3 :
+% curve := pointa--middle--pointb ;
+% elseif anglemethod = 4 :
+% curve := pointa..controls middle..pointb ;
+% middle := point .5 along curve ;
+% fi ;
+% draw thefreelabel(str, middle, common) withcolor black ;
+% curve
+% enddef ;
+
+vardef anglebetween (expr a, b, str) = % path path string
+ save pointa, pointb, common, middle, offset ;
+ pair pointa, pointb, common, middle, offset ;
+ save curve ; path curve ;
+ save where ; numeric where ;
+ if round point 0 of a = round point 0 of b :
+ common := point 0 of a ;
+ else :
+ common := a intersectionpoint b ;
+ fi ;
+ pointa := point anglelength on a ;
+ pointb := point anglelength on b ;
+ where := turningnumber (common--pointa--pointb--cycle) ;
+ middle := (reverse(common--pointa) rotatedaround (pointa,-where*90))
+ intersection_point
+ (reverse(common--pointb) rotatedaround (pointb, where*90)) ;
+ if not intersection_found :
+ middle := point .5 along
+ ((reverse(common--pointa) rotatedaround (pointa,-where*90)) --
+ ( (common--pointb) rotatedaround (pointb, where*90))) ;
+ fi ;
+ if anglemethod = 0 :
+ curve := pointa{unitvector(middle-pointa)}.. pointb;
+ middle := point .5 along curve ;
+ curve := common ;
+ elseif anglemethod = 1 :
+ curve := pointa{unitvector(middle-pointa)}.. pointb;
+ middle := point .5 along curve ;
+ elseif anglemethod = 2 :
+ middle := common rotatedaround(.5[pointa,pointb],180) ;
+ curve := pointa--middle--pointb ;
+ elseif anglemethod = 3 :
+ curve := pointa--middle--pointb ;
+ elseif anglemethod = 4 :
+ curve := pointa..controls middle..pointb ;
+ middle := point .5 along curve ;
+ fi ;
+ draw thefreelabel(str, middle, common) ; % withcolor black ;
+ curve
+enddef ;
+
+% Stack
+
+picture currentpicturestack[] ;
+numeric currentpicturedepth ; currentpicturedepth := 0 ;
+
+def pushcurrentpicture =
+ currentpicturedepth := currentpicturedepth + 1 ;
+ currentpicturestack[currentpicturedepth] := currentpicture ;
+ currentpicture := nullpicture ;
+enddef ;
+
+def popcurrentpicture text t = % optional text
+ if currentpicturedepth > 0 :
+ addto currentpicturestack[currentpicturedepth] also currentpicture t ;
+ currentpicture := currentpicturestack[currentpicturedepth] ;
+ currentpicturedepth := currentpicturedepth - 1 ;
+ fi ;
+enddef ;
+
+%D colorcircle(size, red, green, blue) ;
+
+% vardef colorcircle (expr size, red, green, blue) =
+% save r, g, b, rr, gg, bb, cc, mm, yy ; save radius ;
+% path r, g, b, rr, bb, gg, cc, mm, yy ; numeric radius ;
+%
+% radius := 5cm ; pickup pencircle scaled (radius/25) ;
+%
+% r := g := b := fullcircle scaled radius shifted (0,radius/4) ;
+%
+% r := r rotatedaround (origin, 15) ;
+% g := g rotatedaround (origin,135) ;
+% b := b rotatedaround (origin,255) ;
+%
+% r := r rotatedaround(center r,-90) ;
+% g := g rotatedaround(center g, 90) ;
+%
+% gg := buildcycle(buildcycle(reverse r,b),g) ;
+% cc := buildcycle(buildcycle(b,reverse g),r) ;
+%
+% rr := gg rotatedaround(origin,120) ;
+% bb := gg rotatedaround(origin,240) ;
+%
+% yy := cc rotatedaround(origin,120) ;
+% mm := cc rotatedaround(origin,240) ;
+%
+% pushcurrentpicture ;
+%
+% fill fullcircle scaled radius withcolor white ;
+%
+% fill rr withcolor red ; fill cc withcolor white-red ;
+% fill gg withcolor green ; fill mm withcolor white-green ;
+% fill bb withcolor blue ; fill yy withcolor white-blue ;
+%
+% for i = rr,gg,bb,cc,mm,yy : draw i withcolor .5white ; endfor ;
+%
+% currentpicture := currentpicture xsized size ;
+%
+% popcurrentpicture ;
+% enddef ;
+
+% vardef colorcircle (expr size, red, green, blue) =
+% save r, g, b, rr, gg, bb, cc, mm, yy ; save radius ;
+% path r, g, b, rr, bb, gg, cc, mm, yy ; numeric radius ;
+%
+% radius := 5cm ; pickup pencircle scaled (radius/25) ;
+%
+% transform t ; t := identity rotatedaround(origin,120) ;
+%
+% r := fullcircle scaled radius
+% shifted (0,radius/4) rotatedaround(origin,15) ;
+%
+% g := r transformed t ; b := g transformed t ;
+%
+% r := r rotatedaround(center r,-90) ;
+% g := g rotatedaround(center g, 90) ;
+%
+% gg := buildcycle(buildcycle(reverse r,b),g) ;
+% cc := buildcycle(buildcycle(b,reverse g),r) ;
+%
+% rr := gg transformed t ; bb := rr transformed t ;
+% yy := cc transformed t ; mm := yy transformed t ;
+%
+% pushcurrentpicture ;
+%
+% fill fullcircle scaled radius withcolor white ;
+%
+% fill rr withcolor red ; fill cc withcolor white-red ;
+% fill gg withcolor green ; fill mm withcolor white-green ;
+% fill bb withcolor blue ; fill yy withcolor white-blue ;
+%
+% for i = rr,gg,bb,cc,mm,yy : draw i withcolor .5white ; endfor ;
+%
+% currentpicture := currentpicture xsized size ;
+%
+% popcurrentpicture ;
+% enddef ;
+
+vardef colorcircle (expr size, red, green, blue) =
+ save r, g, b, c, m, y, w ; save radius ;
+ path r, g, b, c, m, y, w ; numeric radius ;
+
+ radius := 5cm ; pickup pencircle scaled (radius/25) ;
+
+ transform t ; t := identity rotatedaround(origin,120) ;
+
+ r := fullcircle rotated 90 scaled radius
+ shifted (0,radius/4) rotatedaround(origin,135) ;
+
+ b := r transformed t ; g := b transformed t ;
+
+ c := buildcycle(subpath(1,7) of g,subpath(1,7) of b) ;
+ y := c transformed t ; m := y transformed t ;
+
+ w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ;
+
+ pushcurrentpicture ;
+
+ fill r withcolor red ;
+ fill g withcolor green ;
+ fill b withcolor blue ;
+ fill c withcolor white-red ;
+ fill m withcolor white-green ;
+ fill y withcolor white-blue ;
+ fill w withcolor white ;
+
+ for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ;
+
+ currentpicture := currentpicture xsized size ;
+
+ popcurrentpicture ;
+enddef ;
+
+% penpoint (i,2) of somepath -> inner / outer point
+
+vardef penpoint expr pnt of p =
+ save n, d ; numeric n, d ;
+ (n,d) = if pair pnt : pnt else : (pnt,1) fi ;
+ (point n of p shifted ((penoffset direction n of p of currentpen) scaled d))
+enddef ;
+
+% nice: currentpicture := inverted currentpicture ;
+
+primarydef p uncolored c =
+ if color p :
+ c - p
+ else :
+ image
+ (for i within p :
+ addto currentpicture
+ if stroked i or filled i :
+ if filled i : contour else : doublepath fi pathpart i
+ dashed dashpart i withpen penpart i
+ else :
+ also i
+ fi
+ withcolor c-(redpart i, greenpart i, bluepart i) ;
+ endfor ; )
+ fi
+enddef ;
+
+vardef inverted primary p =
+ (p uncolored white)
+enddef ;
+
+% primarydef p softened c =
+% if color p :
+% tripled(c) * p
+% else :
+% image
+% (save cc ; color cc ; cc := tripled(c) ;
+% for i within p :
+% addto currentpicture
+% if stroked i or filled i :
+% if filled i : contour else : doublepath fi pathpart i
+% dashed dashpart i withpen penpart i
+% else :
+% also i
+% fi
+% withcolor (redpart cc * redpart i,
+% greenpart cc * greenpart i,
+% bluepart cc * bluepart i) ;
+% endfor ;)
+% fi
+% enddef ;
+
+primarydef p softened c =
+ begingroup
+ save cc ; color cc ; cc := tripled(c) ;
+ if color p :
+ (redpart cc * redpart p,
+ greenpart cc * greenpart p,
+ bluepart cc * bluepart p)
+ else :
+ image
+ (for i within p :
+ addto currentpicture
+ if stroked i or filled i :
+ if filled i : contour else : doublepath fi pathpart i
+ dashed dashpart i withpen penpart i
+ else :
+ also i
+ fi
+ withcolor (redpart cc * redpart i,
+ greenpart cc * greenpart i,
+ bluepart cc * bluepart i) ;
+ endfor ;)
+ fi
+ endgroup
+enddef ;
+
+vardef grayed primary p =
+ if color p :
+ tripled(.30redpart p+.59greenpart p+.11bluepart p)
+ else :
+ image
+ (for i within p :
+ addto currentpicture
+ if stroked i or filled i :
+ if filled i : contour else : doublepath fi pathpart i
+ dashed dashpart i withpen penpart i
+ else :
+ also i
+ fi
+ withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ;
+ endfor ; )
+ fi
+enddef ;
+
+% yes or no: "text" infont "cmr12" at 24pt ;
+
+% let normalinfont = infont ;
+%
+% numeric lastfontsize ; lastfontsize = fontsize defaultfont ;
+%
+% def infont primary name = % no vardef, no expr
+% hide(lastfontsize := fontsize name) % no ;
+% normalinfont name
+% enddef ;
+%
+% def scaledat expr size =
+% scaled (size/lastfontsize)
+% enddef ;
+%
+% let at = scaledat ;
+
+% like decimal
+
+def condition primary b = if b : "true" else : "false" fi enddef ;
+
+% undocumented
+
+primarydef p stretched s =
+ begingroup
+ save pp ; path pp ; pp := p xyscaled s ;
+ (pp shifted ((point 0 of p) - (point 0 of pp)))
+ endgroup
+enddef ;
+
+% primarydef p enlonged len =
+% begingroup
+% save al ; al := arclength(p) ;
+% if al > 0 :
+% if pair p :
+% point 1 of ((origin -- p) stretched ((al+len)/al))
+% else :
+% p stretched ((al+len)/al)
+% fi
+% else :
+% p
+% fi
+% endgroup
+% enddef ;
+
+primarydef p enlonged len =
+ begingroup
+ if pair p :
+ save q ; path q ; q := origin -- p ;
+ save al ; al := arclength(q) ;
+ if al > 0 :
+ point 1 of (q stretched ((al+len)/al))
+ else :
+ p
+ fi
+ else :
+ save al ; al := arclength(p) ;
+ if al > 0 :
+ p stretched ((al+len)/al)
+ else :
+ p
+ fi
+ fi
+ endgroup
+enddef ;
+
+% path p ; p := (0,0) -- (10cm,5cm) ;
+% drawarrow p withcolor red ;
+% drawarrow p shortened 1cm withcolor green ;
+
+primarydef p shortened d =
+ reverse ( ( reverse (p enlonged -d) ) enlonged -d )
+enddef ;
+
+% yes or no, untested -)
+
+def xshifted expr dx = shifted(dx,0) enddef ;
+def yshifted expr dy = shifted(0,dy) enddef ;
+
+% also handy
+
+% right: str = readfrom ("abc" & ".def" ) ;
+% wrong: str = readfrom "abc" & ".def" ;
+
+% Every 62th read fails so we need to try again!
+
+% def readfile (expr name) =
+% if (readfrom (name) <> EOF) :
+% scantokens("input " & name & ";") ;
+% elseif (readfrom (name) <> EOF) :
+% scantokens("input " & name & ";") ;
+% fi ;
+% closefrom (name) ;
+% enddef ;
+%
+% this sometimes fails on the elseif, so :
+%
+
+def readfile (expr name) =
+ begingroup ; save ok ; boolean ok ;
+ if (readfrom (name) <> EOF) :
+ ok := false ;
+ elseif (readfrom (name) <> EOF) :
+ ok := false ;
+ else :
+ ok := true ;
+ fi ;
+ if not ok :
+ scantokens("input " & name & " ") ;
+ fi ;
+ closefrom (name) ;
+ endgroup ;
+enddef ;
+
+% permits redefinition of end in macro
+
+inner end ;
+
+% real fun
+
+let normalwithcolor = withcolor ;
+
+def remapcolors =
+ def withcolor primary c = normalwithcolor remappedcolor(c) enddef ;
+enddef ;
+
+def normalcolors =
+ let withcolor = normalwithcolor ;
+enddef ;
+
+def resetcolormap =
+ color color_map[][][] ;
+ normalcolors ;
+enddef ;
+
+resetcolormap ;
+
+% color_map_resolution := 1000 ;
+%
+% def r_color primary c = round(color_map_resolution*redpart c) enddef ;
+% def g_color primary c = round(color_map_resolution*greenpart c) enddef ;
+% def b_color primary c = round(color_map_resolution*bluepart c) enddef ;
+
+def r_color primary c = redpart c enddef ;
+def g_color primary c = greenpart c enddef ;
+def b_color primary c = bluepart c enddef ;
+
+def remapcolor(expr old, new) =
+ color_map[r_color old][g_color old][b_color old] := new ;
+enddef ;
+
+def remappedcolor(expr c) =
+ if known color_map[r_color c][g_color c][b_color c] :
+ color_map[r_color c][g_color c][b_color c]
+ else :
+ c
+ fi
+enddef ;
+
+% def refill suffix c = do_repath (1) (c) enddef ;
+% def redraw suffix c = do_repath (2) (c) enddef ;
+% def recolor suffix c = do_repath (0) (c) enddef ;
+%
+% color refillbackground ; refillbackground := (1,1,1) ;
+%
+% def do_repath (expr mode) (suffix c) text t = % can it be stroked and filled at the same time ?
+% begingroup ;
+% if mode=0 : save withcolor ; remapcolors ; fi ;
+% save _c_, _cc_, _f_, _b_ ; picture _c_, _cc_ ; color _f_ ; path _b_ ;
+% _c_ := c ; _b_ := boundingbox c ; c := nullpicture ;
+% for i within _c_ :
+% _f_ := (redpart i, greenpart i, bluepart i) ;
+% if bounded i :
+% setbounds c to pathpart i ;
+% elseif clipped i :
+% clip c to pathpart i ;
+% elseif stroked i :
+% addto c doublepath pathpart i
+% dashed dashpart i withpen penpart i
+% withcolor _f_ % (redpart i, greenpart i, bluepart i)
+% if mode=2 : t fi ;
+% elseif filled i :
+% addto c contour pathpart i
+% withcolor _f_
+% if (mode=1) and (_f_<>refillbackground) : t fi ;
+% else :
+% addto c also i ;
+% fi ;
+% endfor ;
+% setbounds c to _b_ ;
+% endgroup ;
+% enddef ;
+
+% Thanks to Jens-Uwe Morawski for pointing out that we need
+% to treat bounded and clipped components as local pictures.
+
+def recolor suffix p = p := repathed (0,p) enddef ;
+def refill suffix p = p := repathed (1,p) enddef ;
+def redraw suffix p = p := repathed (2,p) enddef ;
+def retext suffix p = p := repathed (3,p) enddef ;
+def untext suffix p = p := repathed (4,p) enddef ;
+
+% primarydef p recolored t = repathed(0,p) t enddef ;
+% primarydef p refilled t = repathed(1,p) t enddef ;
+% primarydef p redrawn t = repathed(2,p) t enddef ;
+% primarydef p retexted t = repathed(3,p) t enddef ;
+% primarydef p untexted t = repathed(4,p) t enddef ;
+
+color refillbackground ; refillbackground := (1,1,1) ;
+
+% vardef repathed (expr mode, p) text t =
+% begingroup ;
+% if mode=0 : save withcolor ; remapcolors ; fi ;
+% save _p_, _pp_, _f_, _b_, _t_ ;
+% picture _p_, _pp_ ; color _f_ ; path _b_ ; transform _t_ ;
+% _b_ := boundingbox p ; _p_ := nullpicture ;
+% for i within p :
+% _f_ := (redpart i, greenpart i, bluepart i) ;
+% if bounded i :
+% _pp_ := repathed(mode,i) t ;
+% setbounds _pp_ to pathpart i ;
+% addto _p_ also _pp_ ;
+% elseif clipped i :
+% _pp_ := repathed(mode,i) t ;
+% clip _pp_ to pathpart i ;
+% addto _p_ also _pp_ ;
+% elseif stroked i :
+% addto _p_ doublepath pathpart i
+% dashed dashpart i withpen penpart i
+% withcolor _f_ % (redpart i, greenpart i, bluepart i)
+% if mode=2 : t fi ;
+% elseif filled i :
+% addto _p_ contour pathpart i
+% withcolor _f_
+% if (mode=1) and (_f_<>refillbackground) : t fi ;
+% elseif textual i : % textpart i <> "" :
+% if mode <> 4 :
+% % transform _t_ ;
+% % (xpart _t_, xxpart _t_, xypart _t_) = (xpart i, xxpart i, xypart i) ;
+% % (ypart _t_, yypart _t_, yxpart _t_) = (ypart i, yypart i, yxpart i) ;
+% % addto _p_ also
+% % textpart i infont fontpart i % todo : other font
+% % transformed _t_
+% % withpen penpart i
+% % withcolor _f_
+% % if mode=3 : t fi ;
+% addto _p_ also i if mode=3 : t fi ;
+% fi ;
+% else :
+% addto _p_ also i ;
+% fi ;
+% endfor ;
+% setbounds _p_ to _b_ ;
+% _p_
+% endgroup
+% enddef ;
+
+def restroke suffix p = p := repathed (21,p) enddef ; % keep attributes
+def reprocess suffix p = p := repathed (22,p) enddef ; % no attributes
+
+% also 11 and 12
+
+vardef repathed (expr mode, p) text t =
+ begingroup ;
+ if mode=0 : save withcolor ; remapcolors ; fi ;
+ save _p_, _pp_, _ppp_, _f_, _b_, _t_ ;
+ picture _p_, _pp_, _ppp_ ; color _f_ ; path _b_ ; transform _t_ ;
+ _b_ := boundingbox p ; _p_ := nullpicture ;
+ for i within p :
+ _f_ := (redpart i, greenpart i, bluepart i) ;
+ if bounded i :
+ _pp_ := repathed(mode,i) t ;
+ setbounds _pp_ to pathpart i ;
+ addto _p_ also _pp_ ;
+ elseif clipped i :
+ _pp_ := repathed(mode,i) t ;
+ clip _pp_ to pathpart i ;
+ addto _p_ also _pp_ ;
+ elseif stroked i :
+ if mode=21 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")
+ dashed dashpart i withpen penpart i
+ withcolor _f_ ; ) ;
+ elseif mode=22 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")) ;
+ else :
+ addto _p_ doublepath pathpart i
+ dashed dashpart i withpen penpart i
+ withcolor _f_ % (redpart i, greenpart i, bluepart i)
+ if mode=2 : t fi ;
+ fi ;
+ elseif filled i :
+ if mode=11 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")
+ withcolor _f_ ; ) ;
+ elseif mode=12 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")) ;
+ else :
+ addto _p_ contour pathpart i
+ withcolor _f_
+ if (mode=1) and (_f_<>refillbackground) : t fi ;
+ fi ;
+ elseif textual i : % textpart i <> "" :
+ if mode <> 4 :
+ % transform _t_ ;
+ % (xpart _t_, xxpart _t_, xypart _t_) = (xpart i, xxpart i, xypart i) ;
+ % (ypart _t_, yypart _t_, yxpart _t_) = (ypart i, yypart i, yxpart i) ;
+ % addto _p_ also
+ % textpart i infont fontpart i % todo : other font
+ % transformed _t_
+ % withpen penpart i
+ % withcolor _f_
+ % if mode=3 : t fi ;
+ addto _p_ also i if mode=3 : t fi ;
+ fi ;
+ else :
+ addto _p_ also i ;
+ fi ;
+ endfor ;
+ setbounds _p_ to _b_ ;
+ _p_
+ endgroup
+enddef ;
+
+% After a question of Denis on how to erase a z variable, Jacko
+% suggested to assign whatever to x and y. So a clearz
+% variable can be defined as:
+%
+% vardef clearz@# =
+% x@# := whatever ;
+% y@# := whatever ;
+% enddef ;
+%
+% but Jacko suggested a redefinition of clearxy:
+%
+% def clearxy text s =
+% clearxy_index_:=0;
+% for $:=s:
+% clearxy_index_:=clearxy_index_+1; endfor;
+% if clearxy_index_=0:
+% save x,y;
+% else:
+% forsuffixes $:=s: x$:=whatever; y$:=whatever; endfor;
+% fi
+% enddef;
+%
+% which i decided to simplify to:
+
+def clearxy text s =
+ if false for $ := s : or true endfor :
+ forsuffixes $ := s : x$ := whatever ; y$ := whatever ; endfor ;
+ else :
+ save x, y ;
+ fi
+enddef ;
+
+% so now we can say: clearxy ; as well as clearxy 1, 2, 3 ;
+
+% show x0 ; z0 = (10,10) ;
+% show x0 ; x0 := whatever ; y0 := whatever ;
+% show x0 ; z0 = (20,20) ;
+% show x0 ; clearxy 0 ;
+% show x0 ; z0 = (30,30) ;
+
+primarydef p smoothed d =
+ (p llmoved (-xpart paired(d),0) -- p lrmoved (-xpart paired(d),0) {right} ..
+ p lrmoved (0,-ypart paired(d)) -- p urmoved (0,-ypart paired(d)) {up} ..
+ p urmoved (-xpart paired(d),0) -- p ulmoved (-xpart paired(d),0) {left} ..
+ p ulmoved (0,-ypart paired(d)) -- p llmoved (0,-ypart paired(d)) {down} .. cycle)
+enddef ;
+
+primarydef p cornered c =
+ ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) --
+ for i=1 upto length(p) :
+ (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) --
+ (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) ..
+ controls point i of p ..
+ endfor cycle)
+enddef ;
+
+% cmyk color support
+
+vardef cmyk(expr c,m,y,k) =
+ (1-c-k,1-m-k,1-y-k)
+enddef ;
+
+% handy
+
+vardef bbwidth (expr p) =
+ (if known p :
+ if path p or picture p :
+ xpart (lrcorner p - llcorner p)
+ else : 0 fi else : 0
+ fi )
+enddef ;
+
+vardef bbheight (expr p) =
+ (if known p : if path p or picture p :
+ ypart (urcorner p - lrcorner p)
+ else : 0 fi else : 0
+ fi)
+enddef ;
+
+color nocolor ; numeric noline ; % both unknown signals
+
+def dowithpath (expr p, lw, lc, bc) =
+ if known p :
+ if known bc :
+ fill p withcolor bc ;
+ fi ;
+ if known lw and known lc :
+ draw p withpen pencircle scaled lw withcolor lc ;
+ elseif known lw :
+ draw p withpen pencircle scaled lw ;
+ elseif known lc :
+ draw p withcolor lc ;
+ fi ;
+ fi ;
+enddef ;
+
+% result from metafont discussion list (denisr/boguslawj)
+
+def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ;
+def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ;
+
+% not perfect, but useful since it removes redundant points.
+
+% vardef dostraightened(expr sign, p) =
+% if length(p)>2 : % was 1, but straight lines are ok
+% save pp ; path pp ;
+% pp := point 0 of p ;
+% for i=1 upto length(p)-1 :
+% if round(point i of p) <> round(point length(pp) of pp) :
+% pp := pp -- point i of p ;
+% fi ;
+% endfor ;
+% save n, ok ; numeric n ; boolean ok ;
+% n := length(pp) ; ok := false ;
+% if n>2 :
+% for i=0 upto n : % evt hier ook round
+% if unitvector(round(point i of pp -
+% point if i=0 : n else : i-1 fi of pp)) <>
+% sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp -
+% point i of pp)) :
+% if ok : -- else : ok := true ; fi point i of pp
+% fi
+% endfor
+% if ok and (cycle p) : -- cycle fi
+% else :
+% pp
+% fi
+% else :
+% p
+% fi
+% enddef ;
+
+% vardef simplified expr p =
+% (reverse dostraightened(+1,dostraightened(+1,reverse p)))
+% enddef ;
+
+% vardef unspiked expr p =
+% (reverse dostraightened(-1,dostraightened(-1,reverse p)))
+% enddef ;
+
+% simplified : remove same points as well as redundant points
+% unspiked : remove same points as well as areas with zero distance
+
+vardef dostraightened(expr sign, p) =
+ save _p_, _q_ ; path _p_, _q_ ;
+ _p_ := p ;
+ forever :
+ _q_ := dodostraightened(sign, _p_) ;
+ exitif length(_p_) = length(_q_) ;
+ _p_ := _q_ ;
+ endfor ;
+ _q_
+enddef ;
+
+vardef dodostraightened(expr sign, p) =
+ if length(p)>2 : % was 1, but straight lines are ok
+ save pp ; path pp ;
+ pp := point 0 of p ;
+ for i=1 upto length(p)-1 :
+ if round(point i of p) <> round(point length(pp) of pp) :
+ pp := pp -- point i of p ;
+ fi ;
+ endfor ;
+ save n, ok ; numeric n ; boolean ok ;
+ n := length(pp) ; ok := false ;
+ if n>2 :
+ for i=0 upto n : % evt hier ook round
+ if unitvector(round(point i of pp -
+ point if i=0 : n else : i-1 fi of pp)) <>
+ sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp -
+ point i of pp)) :
+ if ok : -- else : ok := true ; fi point i of pp
+ fi
+ endfor
+ if ok and (cycle p) : -- cycle fi
+ else :
+ pp
+ fi
+ else :
+ p
+ fi
+enddef ;
+
+% vardef simplified expr p =
+% dostraightened(+1,p)
+% enddef ;
+
+% vardef unspiked expr p =
+% dostraightened(-1,p)
+% enddef ;
+
+vardef simplified expr p =
+ (reverse dostraightened(+1,dostraightened(+1,reverse p)))
+enddef ;
+
+vardef unspiked expr p =
+ (reverse dostraightened(-1,dostraightened(-1,reverse p)))
+enddef ;
+
+% path p ;
+% p := (2cm,1cm) -- (2cm,1cm) -- (2cm,1cm) -- (3cm,1cm) --
+% (4cm,1cm) -- (4cm,2cm) -- (4cm,2.5cm) -- (4cm,3cm) --
+% (3cm,3cm) -- (2cm,3cm) -- (1cm,3cm) -- (-1cm,3cm) --
+% .5[(-1cm,3cm),(1cm,1cm)] -- (1cm,1cm) -- cycle ;
+%
+% p := unitcircle scaled 4cm ;
+%
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+% p := p shifted (4cm,0) ; p := straightened p ;
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+% p := p shifted (4cm,0) ; p := straightened p ;
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+
+% new
+
+path originpath ; originpath := origin -- cycle ;
+
+vardef unitvector primary z =
+ if abs z = abs origin : z else : z/abs z fi
+enddef;
+
+% also new
+
+vardef anchored@#(expr p, z) =
+ p shifted (z + (labxf@#*lrcorner p + labyf@#*ulcorner p
+ + (1-labxf@#-labyf@#)*llcorner p))
+enddef ;
+
+% epsed(1.2345)
+
+vardef epsed (expr e) =
+ e if e>0 : + eps elseif e<0 : - eps fi
+enddef ;
+
+% handy
+
+def withgray primary g =
+ withcolor (g,g,g)
+enddef ;
+
+% for metafun
+
+if unknown darkred : color darkred ; darkred := .625(1,0,0) fi ;
+if unknown darkyellow : color darkyellow ; darkyellow := .625(1,1,0) fi ;
+if unknown darkgray : color darkgray ; darkgray := .625(1,1,1) fi ;
+if unknown lightgray : color lightgray ; lightgray := .875(1,1,1) fi ;
+
+% an improved plain mp macro
+
+vardef center primary p =
+ if pair p : p else : .5[llcorner p, urcorner p] fi
+enddef;
+
+% new, yet undocumented
+
+vardef rangepath (expr p, d, a) =
+ (if length p>0 :
+ (d*unitvector(direction 0 of p) rotated a)
+ shifted point 0 of p
+ -- p --
+ (d*unitvector(direction length(p) of p) rotated a)
+ shifted point length(p) of p
+ else :
+ p
+ fi)
+enddef ;
+
+% under construction
+
+vardef straightpath(expr a, b, method) =
+ if (method<1) or (method>6) :
+ (a--b)
+ elseif method = 1 :
+ (a --
+ if xpart a > xpart b :
+ if ypart a > ypart b :
+ (xpart b,ypart a) --
+ elseif ypart a < ypart b :
+ (xpart a,ypart b) --
+ fi
+ elseif xpart a < xpart b :
+ if ypart a > ypart b :
+ (xpart a,ypart b) --
+ elseif ypart a < ypart b :
+ (xpart b,ypart a) --
+ fi
+ fi
+ b)
+ elseif method = 3 :
+ (a --
+ if xpart a > xpart b :
+ (xpart b,ypart a) --
+ elseif xpart a < xpart b :
+ (xpart a,ypart b) --
+ fi
+ b)
+ elseif method = 5 :
+ (a --
+ if ypart a > ypart b :
+ (xpart b,ypart a) --
+ elseif ypart a < ypart b :
+ (xpart a,ypart b) --
+ fi
+ b)
+ else :
+ (reverse straightpath(b,a,method-1))
+ fi
+enddef ;
+
+% handy for myself
+
+def addbackground text t =
+ begingroup ; save p, b ; picture p ; path b ;
+ b := boundingbox currentpicture ;
+ p := currentpicture ; currentpicture := nullpicture ;
+ fill b t ; setbounds currentpicture to b ; addto currentpicture also p ;
+ endgroup ;
+enddef ;
+
+% makes a (line) into an infinite one (handy for calculating
+% intersection points
+
+vardef infinite expr p =
+ (-infinity*unitvector(direction 0 of p)
+ shifted point 0 of p
+ -- p --
+ +infinity*unitvector(direction length(p) of p)
+ shifted point length(p) of p)
+enddef ;
+
+% obscure macros: create var from string and replace - and :
+% (needed for process color id's)
+
+string _clean_ascii_[] ;
+
+def register_dirty_chars(expr str) =
+ for i = 0 upto length(str)-1 :
+ _clean_ascii_[ASCII substring(i,i+1) of str] := "_" ;
+ endfor ;
+enddef ;
+
+register_dirty_chars("+-*/:;., ") ;
+
+vardef cleanstring (expr s) =
+ save ss ; string ss, si ; ss = "" ; save i ;
+ for i=0 upto length(s) :
+ si := substring(i,i+1) of s ;
+ ss := ss & if known _clean_ascii_[ASCII si] : _clean_ascii_[ASCII si] else : si fi ;
+ endfor ;
+ ss
+enddef ;
+
+vardef asciistring (expr s) =
+ save ss ; string ss, si ; ss = "" ; save i ;
+ for i=0 upto length(s) :
+ si := substring(i,i+1) of s ;
+ if (ASCII si >= ASCII "0") and (ASCII si <= ASCII "9") :
+ ss := ss & char(scantokens(si) + ASCII "A") ;
+ else :
+ ss := ss & si ;
+ fi ;
+ endfor ;
+ ss
+enddef ;
+
+vardef setunstringed (expr s, v) =
+ scantokens(cleanstring(s)) := v ;
+enddef ;
+
+vardef setunstringed (expr s, v) =
+ scantokens(cleanstring(s)) := v ;
+enddef ;
+
+vardef getunstringed (expr s) =
+ scantokens(cleanstring(s))
+enddef ;
+
+vardef unstringed (expr s) =
+ expandafter known scantokens(cleanstring(s))
+enddef ;
+
+% new
+
+vardef colorpart(expr i) =
+ (redpart i, greenpart i,bluepart i)
+enddef ;
+
+% for david arnold:
+
+% showgrid(-5,10,1cm,-10,10,1cm);
+
+def showgrid (expr MinX, MaxX, DeltaX, MinY, MaxY, DeltaY)=
+ begingroup
+ save defaultfont, defaultscale, size ;
+ string defaultfont ; defaultfont := "cmtt10"; % i.e. infofont
+ numeric defaultscale ; defaultscale := 8pt / fontsize defaultfont;
+ numeric size ; size := 2pt ;
+ for x=MinX upto MaxX :
+ for y=MinY upto MaxY :
+ draw (x*DeltaX, y*DeltaY)
+ withpen pencircle scaled
+ if (x mod 5 = 0) and (y mod 5 = 0) :
+ 1.5size withcolor .50white
+ else :
+ size withcolor .75white
+ fi ;
+ endfor ;
+ endfor ;
+ for x=MinX upto MaxX:
+ label.bot(decimal x, (x*DeltaX,-size));
+ endfor ;
+ for y=MinY upto MaxY:
+ label.lft(decimal y, (-size,y*DeltaY)) ;
+ endfor ;
+ endgroup
+enddef;
+
+% new, handy for:
+%
+% \startuseMPgraphic{map}{n}
+% \includeMPgraphic{map:germany} ;
+% c_phantom (\MPvar{n}<1) (
+% fill map_germany withcolor \MPcolor{lightgray} ;
+% draw map_germany withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% \includeMPgraphic{map:austria} ;
+% c_phantom (\MPvar{n}<2) (
+% fill map_austria withcolor \MPcolor{lightgray} ;
+% draw map_austria withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% c_phantom (\MPvar{n}<3) (
+% \includeMPgraphic{map:swiss} ;
+% fill map_swiss withcolor \MPcolor{lightgray} ;
+% draw map_swiss withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% c_phantom (\MPvar{n}<4) (
+% \includeMPgraphic{map:luxembourg} ;
+% fill map_luxembourg withcolor \MPcolor{lightgray} ;
+% draw map_luxembourg withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% \stopuseMPgraphic
+%
+% \useMPgraphic{map}{n=3}
+
+vardef phantom (text t) =
+ picture _p_ ; _p_ := image(t) ; addto _p_ also currentpicture ;
+ setbounds currentpicture to boundingbox _p_ ;
+enddef ;
+
+vardef c_phantom (expr b) (text t) =
+ if b :
+ picture _p_ ; _p_ := image(t) ; addto _p_ also currentpicture ;
+ setbounds currentpicture to boundingbox _p_ ;
+ else :
+ t ;
+ fi ;
+enddef ;
+
+% mark paths (for external progs to split)
+
+% def somepath(expr p)
+% p
+% enddef ;
+
+%D Handy:
+
+def break =
+ exitif true fi ;
+enddef ;
+
+%D New too:
+
+primarydef p xstretched w =
+ (p if (bbwidth (p)>0) and (w>0) : xscaled (w/bbwidth (p)) fi)
+enddef ;
+
+primarydef p ystretched h =
+ (p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi)
+enddef ;
+
+primarydef p snapped s =
+ hide ( if path p :
+ forever :
+ exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ;
+ p := p scaled (1/2) ;
+ endfor ;
+ elseif numeric p :
+ forever :
+ exitif p <= s ;
+ p := p scaled (1/2) ;
+ endfor ;
+ fi ; )
+ p
+enddef ;
+
+% done
+
+endinput ;
diff --git a/metapost/context/base/mp-txts.mp b/metapost/context/base/mp-txts.mp
new file mode 100644
index 000000000..f208c7149
--- /dev/null
+++ b/metapost/context/base/mp-txts.mp
@@ -0,0 +1,67 @@
+%D \module
+%D [ file=mp-txts.mp,
+%D version=2006.06.08,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=more text support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown context_tool : input mp-tool ; fi ;
+if known context_txts : endinput ; fi ;
+
+boolean context_txts ; context_txts := true ;
+
+%D The real code:
+
+string txtfile ; txtfile := "" ;
+string txtfont ; txtfont := defaultfont ;
+string txtpref ; txtpref := "00001::::" ;
+numeric txtnext ; txtnext := 0 ;
+numeric txtdepth ; txtdepth := 0 ;
+
+vardef nexttxt =
+ txtnext := txtnext + 1 ;
+ txtnext
+enddef ;
+
+picture savedtxts[] ;
+numeric depthtxts[] ;
+
+vardef zerofilled(expr fd) =
+ if fd<10: "0000" else :
+ if fd<100: "000" else :
+ if fd<1000: "00" else :
+ if fd<10000: "0" else :
+ fi fi fi fi & decimal fd
+enddef;
+
+vardef savetxt(expr n,w,h,d) text t =
+ depthtxts[n] := d ;
+ savedtxts[n] := ((txtpref & zerofilled(n)) infont txtfont) xysized(w,h+d) t
+enddef ;
+
+vardef sometxt(expr n) =
+ if known savedtxts[n] :
+ txtdepth := depthtxts[n] ; savedtxts[n]
+ else :
+ txtdepth := 0 ; nullpicture
+ fi
+enddef ;
+
+def loadtxts =
+ if txtfile <> "" :
+ readfile(txtfile) ;
+ fi ;
+enddef ;
+
+def StartTexts =
+ loadtxts ;
+enddef ;
+
+def StopTexts =
+enddef ;
diff --git a/metapost/context/font/punkfont.mp b/metapost/context/font/punkfont.mp
new file mode 100644
index 000000000..e57499859
--- /dev/null
+++ b/metapost/context/font/punkfont.mp
@@ -0,0 +1,863 @@
+% Remark:
+%
+% This file is a merge of the original punk files by Donald Knuth, who
+% added this comment:
+%
+% Font inspired by Gerard and Marjan Unger's lectures,
+% Feb 1985
+%
+% The regular punk files are part of TeXLive and in metafont format. All
+% errors introduced are ours. We also changed the encoding to unicode. In
+% due time we might add a few more more characters. We still need to
+% improve some of the metrics which involves a bit of trial and error. The
+% font just covers basic latin shapes but in ConTeXt MkIV we add virtual
+% composed shapes. There is a module m-punk.tex that implements this. This
+% derivate is also used in mk.tex (mk.pdf) which is one of our tests for
+% LuaTeX. We published an article on it in the MAPS (NTG magazine).
+%
+% 2008, Taco Hoekwater & Hans Hagen
+
+if unknown punk_font_loaded :
+
+ if unknown scale_factor :
+ scale_factor := 1 ;
+ fi ;
+
+ boolean punk_font_loaded ;
+
+ punk_font_loaded := true ;
+ warningcheck := 0 ;
+ designsize := 10pt#;
+ font_identifier := "Punk Nova" ; % dedicated to Don Knuth and Hermann Zapf
+
+ ht# := 7pt# ; % height of characters
+ u# := 1/4pt# ; % unit width
+ % s# := 1.2pt# ; % extra sidebar
+ % s# := 0.1pt# ; % extra sidebar, needed because we use the bbox currently
+ s# := 0 ; % extra sidebar, ok
+% s# := 1.2pt# ; % extra sidebar
+ px# := .6pt# ; % horizontal thickness of pen
+ py# := .5pt# ; % vertical thickness of pen
+ dot# := 1.3pt# ; % diameter of dots
+ dev# := .3pt# ; % standard deviation of punk points
+
+ % dot# := .8pt# ; % diameter of dots
+ % px# := .3pt# ; % horizontal thickness of pen
+ % py# := .2pt# ; % vertical thickness of pen
+
+ % seed := sqrt2 ;
+ % randomseed := seed ;
+ proofing := 0 ;
+ pt := .1pt ;
+ mag := scale_factor * 10 ;
+ bp_per_pixel := bpppix_ * mag ;
+
+ define_pixels(u,dev) ;
+ define_blacker_pixels(px,py,dot) ;
+ define_whole_pixels(s) ;
+ xoffset := s ;
+
+ pickup pencircle xscaled px yscaled py ;
+ punk_pen := savepen ;
+ pickup pencircle scaled dot ;
+ path dot_pen_path ;
+ dot_pen_path := tensepath makepath currentpen ;
+
+% px# := .8pt# ; % horizontal thickness of pen
+% define_pixels(u,dev) ;
+% define_blacker_pixels(px,py,dot) ;
+% pickup pencircle xscaled 1.25px yscaled 1.25py ;
+% punk_pen := savepen ;
+% pickup pencircle scaled 1.25dot ;
+% path dot_pen_path ;
+% dot_pen_path := tensepath makepath currentpen ;
+
+ defaultcolormodel := 1 ;
+
+ def beginpunkchar(expr c,n,h,v) = % code $c$; width is $n$ units
+ hdev := h * dev ; % modify horizontal amounts of deviation
+ vdev := v * dev ; % modify vertical amounts of deviation
+ beginchar(c,n*u#,ht#,0) ;
+ italcorr 0 ;
+ % italcorr ht#*slant;
+ pickup punk_pen
+ enddef ;
+
+% extra_endchar := extra_endchar & "w := w+2s ; charwd := charwd+2s# ;" ;
+% extra_endchar := extra_endchar & "setbounds currentpicture to (0,-d)--(w*1.2,-d)--(w*1.2,h)--(0,h)--cycle;" ;
+
+% extra_endchar := extra_endchar & "w := w+2s ; " ;
+% extra_endchar := extra_endchar & "w := 1.2w ; " ;
+% extra_endchar := extra_endchar & "charwd := 1.2charwd ; " ;
+% extra_endchar := extra_endchar & "setbounds currentpicture to (0,-d)--(w,-d)--(w,h)--(0,h)--cycle;" ;
+
+% todo:
+
+% extra_endchar := extra_endchar &
+% "currentpicture := currentpicture shifted (0,1pt#) ; setbounds currentpicture to " &
+% "llcorner currentpicture shifted ( 0,-1pt#) -- lrcorner currentpicture shifted ( 1pt#,-1pt#) -- " &
+% "urcorner currentpicture shifted ( 1pt#, 1pt#) -- ulcorner currentpicture shifted ( 0, 1pt#) -- cycle ; " ;
+
+ def ^ =
+ transformed currenttransform
+ enddef ;
+
+ def makebox(text rule) =
+ for y=0, h : % horizontals
+ rule((-s,y)^,(w-s,y)^) ;
+ endfor
+ for x=-s, 0, w-2s, w-s : % verticals
+ rule((x,0)^,(x,h)^) ;
+ endfor
+ enddef ;
+
+ rulepen := pensquare ;
+
+ vardef pp expr z =
+ z + (hdev * normaldeviate, vdev * normaldeviate)
+ enddef;
+
+ def pd expr z = % {\bf drawdot}
+ addto currentpicture contour dot_pen_path shifted z.t_ withpen penspeck
+ enddef;
+
+ def initialize_punk_upper =
+ ht# := 7pt# ; dev# := .3pt# ;
+ enddef ;
+ def initialize_punk_lower =
+ sht# := ht#; sdev := dev;
+ ht# := .6ht# ; dev := .7dev ;
+ enddef ;
+ def revert_punk_lower =
+ ht# := sht#; dev := sdev;
+ enddef ;
+
+fi ;
+
+
+initialize_punk_upper ;
+
+beginpunkchar("A",13,1,2);
+z1=pp(1.5u,0); z2=(.5w,1.1h); z3=pp(w-1.5u,0);
+pd z1; pd z3; draw z1--z2--z3; % left and right diagonals
+z4=pp .3[z1,z2]; z5=pp .3[z3,z2]; pd z4; pd z5; draw z4--z5; % crossbar
+endchar;
+
+beginpunkchar("B",12,1,1);
+z1=pp(2u,0); z2=pp(2u,.6h); z3=pp(2u,h); pd z1; pd z3; draw z1--z3; % stem
+z1.5=pp(w-u,.5y2); z2.5=pp(w-u,.5[y2,y3]); draw z2--z2.5--z3; % upper lobe
+draw flex(z2,z1.5,z1); % lower lobe
+endchar;
+
+beginpunkchar("C",13,1,2);
+z1=pp(w-2u,.8h); z2=pp(.6w,h); z3=pp(u,.5h); z4=(.6w,0); z5=(w-2u,.2h);
+pd z1; pd z5; draw z1..z2..z3..z4..z5; % arc
+endchar;
+
+beginpunkchar("D",14,1,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-u,.6h);
+pd z1; pd z2; draw flex(z1,z3,z2); % lobe
+draw z1--z2; % stem
+endchar;
+
+beginpunkchar("E",12,.5,1);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2.5u,h); z4=pp(w-2u,0);
+pd z3; pd z4; draw z4--z1--z2--z3; % stem and arms
+z5=pp(2u,.6h); z6=pp(w-3u,.6h); pd z5; pd z6; draw z5--z6; % crossbar
+endchar;
+
+beginpunkchar("F",12,.5,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2u,h);
+pd z1; pd z3; draw z1--z2--z3; % stem and arm
+z5=pp(2u,.6h); z6=pp(w-3u,.6h); z4=pp .5[z5,z6]-(0,.1h);
+pd z5; pd z6; draw flex (z5,z4,z6); % crossbar
+endchar;
+
+beginpunkchar("G",13,.5,.5);
+z1=pp(w-2u,.8h); z2=pp(.6w,h); z3=pp(u,.5h); z4=pp(.6w,0); z5=(w-2u,0);
+pd z1; draw z1..z2..z3..z4---z5; % arc
+z6=pp(.5[u,x5],.4h); pd z6; pd z5; draw z6--(pp(x5,y6))--z5; % spur
+endchar;
+
+beginpunkchar("H",14,1,.5);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2u,0); z4=pp(w-2u,h);
+z5=pp(2u,.6h); z6=pp(w-2u,.6h);
+pd z1; pd z2; pd z3; pd z4; draw z1--z2; draw flex(z3,z6,z4); % stems
+pd z5; draw z5--z6; % crossbar
+endchar;
+
+beginpunkchar("I",5,1,2);
+z1=pp(.5w,0); z2=(.5w,1/3h); z3=(.5w,2/3h); z4=(.5w,h);
+pd z1; pd z4; draw flex(z1,z2,z3,z4); % stem
+endchar;
+
+beginpunkchar("J",9,1,2);
+z1=pp(w-2u,h); z2=pp(w-2u,-.1h); z3=pp(u,0);
+pd z1; pd z3; draw z1--z2--z3; % arc
+endchar;
+
+beginpunkchar("K",14,1,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(2u,1/3h); z4=pp(w-1.5u,h);
+pd z1; pd z2; draw z1--z2; % stem
+pd z3; pd z4; draw z3--z4; % upper diagonal
+z6=pp(w-u,0); z5=1/3[z3,z4];
+pd z6; draw flex(z5,.8[z1,2/3[z5,z6] ],z6);% lower diagonal
+endchar;
+
+beginpunkchar("L",11,1,2);
+z1=pp(2u,h); z2=pp(2u,0); z3=pp(w-1.5u,0);
+pd z1; pd z3; draw z1--z2--z3; % stem and arm
+endchar;
+
+beginpunkchar("M",17,.5,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(.5w,0); z4=pp(w-2u,h); z5=pp(w-2u,0);
+pd z1; pd z5; draw z1--z2--z3--z4--z5; % stems and diagonals
+endchar;
+
+beginpunkchar("N",13,.75,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2u,0); z4=pp(w-2u,h);
+pd z1; pd z4; draw z1--z2--z3--z4; % stems and diagonals
+endchar;
+
+beginpunkchar("O",12,.5,2);
+z1=pp(.5w,h); z2=pp(u,.55h); z3=pp(.5w,0); z4=pp(w-u,.55h);
+pd z1; draw z1{left}..z2..z3..z4..z1; % bowl
+endchar;
+
+beginpunkchar("P",13,1,2);
+z1=pp(2u,0); z2=pp(2u,1.1h); z3=pp(2u,.5h); z4=pp(w,.6[y3,y2]);
+pd z1; pd z3; draw z1--z2--z4--z3; % stem and bowl
+endchar;
+
+beginpunkchar("Q",14,.5,2);
+z1=pp(.5w,h); z2=pp(u,.55h); z3=pp(.5w,0); z4=pp(w-u,.55h);
+pd z1; draw z1{curl 2}..z2..z3..z4..z1; % bowl
+z5=pp(.4w,.2h); z6=pp(w-u,-.1h); z7=pp(.5[x5,x6],-.2h);
+pd z5; pd z6; draw z5--z7--z6; % tail
+endchar;
+
+beginpunkchar("R",16,1,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-u,.6[y2,y4]); z4=pp(2u,.5h); z5=pp(w-1.5u,0);
+pd z1; pd z2; pd z5; draw z1--flex(z2,z3,z4)--z5; % stem, bowl, and diagonal
+endchar;
+
+beginpunkchar("S",11,.3,1);
+z1=pp(w-2u,.9h); z2=pp(.5w,h); z3=pp(u,.7h); z4=.6[z6,z2];
+z5=pp(w-u,.35h); z6=pp(.5w,u); z7=pp(u,.2h);
+pd z1; pd z7; draw z1--z2...z3..z4..z5...z6--z7; % stroke
+endchar;
+
+beginpunkchar("T",13,.75,2);
+z1=pp(u,h); z2=pp(w-u,h); z3=pp(.5w,0);
+pd z1; pd z2; pd z3; draw z1--z2; % arms
+draw .5[z1,z2]--z3; % stem
+endchar;
+
+beginpunkchar("U",13,.3,2);
+z1=pp(2u,h); z2=pp(2u,.2h); z3=pp(.5w,0); z4=pp(w-2u,.2h); z5=pp(w-2u,h);
+pd z1; pd z5; draw z1---z2...z3{z4-z2}...z4---z5; % stroke
+endchar;
+
+beginpunkchar("V",13,1,2);
+z1=pp(1.5u,h); z2=pp(.5w,0); z3=pp(w-1.5u,h);
+pd z1; pd z3; draw z1--z2--z3; % diagonals
+endchar;
+
+beginpunkchar("W",18,1,2);
+z1=pp(1.5u,h); z2=pp(.5[x1,x3],0); z3=pp(.5w,.8h); z4=pp(.5[x3,x5],0);
+z5=pp(w-1.5u,h);
+pd z1; pd z5; draw z1--z2--z3--z4--z5; % diagonals
+endchar;
+
+beginpunkchar("X",13,1,1);
+z1=pp(1.5u,h); z2=pp(w-1.5u,0); z3=pp(1.5u,0); z4=pp(w-2.5u,h);
+pd z1; pd z2; draw z1--z2; % main diagonal
+pd z3; pd z4; draw z3--z4; % cross diagonal
+endchar;
+
+beginpunkchar("Y",13,1,2);
+z1=pp(1.5u,h); z2=pp(w-1.5u,h); z3=pp(.5w,.5h); z4=pp(.5w,0);
+pd z1; pd z2; pd z4; draw z1--z3--z4; % stem and left diagonal
+draw z2--z3; % right diagonal
+endchar;
+
+beginpunkchar("Z",11,1,2);
+z1=pp(1.5u,h); z2=pp(w-2.5u,h); z3=pp(1.5u,0); z4=pp(w-1.5u,0);
+pd z1; pd z4; draw z1--z2--z3--z4; % diagonals
+endchar;
+
+beginpunkchar(198,16,1,2); % \AE
+z1=pp(1.5u,0); z2=pp(.6w,h); z3=pp(w-1.5u,h);
+pd z1; pd z3; draw z1--z2--z3; % left diagonal and upper arm
+z4=pp .3[z1,z2]; z5=pp(.6w,0); z6=pp(w-2u,.3h);
+pd z4; pd z6; draw z4--z6; % crossbar
+z7=pp(w-u,0); pd z2; pd z7; draw z2--z5--z7; % stem and lower arm
+endchar;
+
+beginpunkchar(338,18,1,2); % \OE
+z1=pp(.5w,h); z2=pp(u,.4h); z3=pp(.5w,0);
+pd z1; draw z1..z2..{right}z3; % bowl
+z4=pp(w-1.5u,h); z5=pp(w-2u,.4h); z6=pp(w-u,0);
+pd z4; pd z6; draw z4--z1--z3--z6; % arms and stem
+pd z5; draw z5--.4[z3,z1]; % crossbar
+endchar;
+
+beginpunkchar(216,14,1,1); % \O
+z1=pp(.5w,h); z2=pp(u,.5h); z3=pp(.5w,0); z4=pp(w-u,.5h);
+z5=pp(w-2u,1.1h); z6=pp(2u,-.1h);
+pd z1; pd z6; draw z1..z2..z3..z4..z5--z6; % bowl and diagonal
+endchar;
+
+beginpunkchar(915,11,1,2); % $\Gamma$
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-1.5u,h);
+pd z1; pd z3; draw z1--z2--z3; % stem and arm
+endchar;
+
+beginpunkchar(916,15,1,2); % $\Delta$
+z1=pp(u,0); z2=pp(.5w,h); z3=pp(w-u,0);
+pd z1; draw z1--z2..tension 5..z3..tension 5..z1; % triangle
+endchar;
+
+beginpunkchar(920,15,.5,2); % $\Theta$
+z1=pp(.5w,h); z2=pp(u,.6h); z3=pp(.5w,0); z4=pp(w-u,.6h);
+pd z1; draw z1..tension.8..z2..z3..z4..tension.8..z1; % bowl
+z5=pp(x2+2u,.4h); z6=pp(x4-2u,.4h); pd z5; pd z6; draw z5--z6; % bar
+endchar;
+
+beginpunkchar(923,12,1,2); % $\Lambda$
+z1=pp(u,0); z2=pp(.5w,h); z3=pp(w-u,0);
+pd z1; pd z3; draw z1--z2--z3; % diagonals
+endchar;
+
+beginpunkchar(926,12,1,1); % $\Xi$
+z1=pp(u,h); z2=pp(w-u,h); pd z1; pd z2; draw z1--z2; % upper arm
+z3=pp(2u,.55h); z4=pp(w-2u,.55h); pd z3; pd z4; draw z3--z4; % bar
+z5=pp(u,0); z6=pp(w-u,0); pd z5; pd z6; draw z5--z6; % lower arm
+endchar;
+
+beginpunkchar(928,13,1,.5); % $\Pi$
+z1=pp(1.5u,0); z2=pp(1.5u,h); z3=pp(w-1.5u,h); z4=pp(w-1.5u,0);
+pd z1; pd z4; draw z1--z2--z3--z4; % stems and bar
+endchar;
+
+beginpunkchar(931,13,1,1); % $\Sigma$
+z1=pp(w-u,h); z2=pp(u,h); z3=pp(.5w-u,.5h); z4=pp(u,0); z5=pp(w-u,0);
+pd z1; pd z5; draw z1--z2{.5[z4,z5]-z2}..z3--z4--z5; % arms and diagonals
+endchar;
+
+beginpunkchar(933,15,1,.5); % $\Upsilon$
+z1=pp(u,.8h); z2=pp(.3w,h); z3=pp(.5w,.5h); z4=pp(.5w,0);
+pd z1; pd z4; draw z1..z2..tension2..z3---z4; % left arc and stem
+z5=pp(w-u,.8h); z6=pp(.7w,h);
+pd z5; draw z5..z6..tension2..{z4-z3}z3; % right arc
+endchar;
+
+beginpunkchar(934,13,1,2); % $\Phi$
+z1=pp(.5w,h); z2=pp(.5w,0); pd z1; pd z2; draw z1--z2; % stem
+z3=pp(.5w,2/3h); z4=pp(u,.5h); z5=pp(.5w,1/4h); z6=pp(w-u,.5h);
+pd z3; draw z3..z4..z5..z6..z3; % bowl
+endchar;
+
+beginpunkchar(936,14,1,1); % $\Psi$
+z1=pp(.5w,h); z2=pp(.5w,0); pd z1; pd z2; draw z1--z2; % stem
+z3=pp(u,.8h); z4=pp(.5w,.2h); z5=pp(w-u,.8h);
+pd z3; pd z5; draw z3{.4[z1,z2]-z3}..z4{right}..{z5-.4[z1,z2]}z5; % stroke
+endchar;
+
+beginpunkchar(937,13,1,2); % $\Omega$
+z1=pp(u,0); z2=pp(1/3w,0); z3=pp(u,2/3h); z4=pp(.5w,h);
+z5=pp(w-u,2/3h); z6=pp(2/3w,0); z7=pp(w-u,0);
+pd z1; pd z7; draw z1--z2{up}..z3..z4..z5..{down}z6--z7; % bowl and arms
+endchar;
+
+beginpunkchar(".",5,1,2);
+pd pp(.5w,0); % dot
+endchar;
+
+beginpunkchar(",",5,.5,.5);
+z1=pp(.5w,0); z2=pp(w-u,-.1h); z3=pp(.5w,-.3h);
+pd z1; pd z3; draw z1--z2--z3; % stroke
+endchar;
+
+beginpunkchar(":",5,1,.5);
+pd pp(.5w,0); pd pp(.5w,.4h); % dots
+endchar;
+
+beginpunkchar(";",5,.5,.5);
+z1=pp(.5w,0); z2=pp(w-u,-.1h); z3=pp(.5w,-.3h);
+pd z1; pd z3; draw z1--z2--z3; % stroke
+pd pp(.5w,.4h); % dot
+endchar;
+
+beginpunkchar("!",5,.5,.5);
+pd pp(.5w,0); % dot
+z1=pp(.5w,1.05h); z2=pp(.5w,.3h); pd z1; pd z2; draw z1--z2; % stem
+endchar;
+
+beginpunkchar(161,5,.5,.5); % spanish inverted !
+pd pp(.5w,.9h); % dot
+z1=pp(.5w,-.1h); z2=pp(.5w,.6h); pd z1; pd z2; draw z1--z2; % stem
+endchar;
+
+beginpunkchar("?",9,1,.5);
+z1=pp(1.5u,.8h); z2=pp(.5w,h); z3=pp(w-u,.8h); z4=pp(.5w,.3h);
+pd z1; pd z4; draw z1..z2..z3..{down}z4; % arc and stem
+pd pp(.5w,0); % dot
+endchar;
+
+beginpunkchar(191,9,1,.5); % spanish inverted ?
+z1=pp(1.5u,.1h); z2=pp(.5w,-.1h); z3=pp(w-u,.1h); z4=pp(.5w,.6h);
+pd z1; pd z4; draw z1..z2..z3..{up}z4; % arc and stem
+pd pp(.5w,.9h); % dot
+endchar;
+
+beginpunkchar("&",14,.5,.5);
+z1=pp(w-2u,h); z2=pp(u,h); z3=pp(3u,0); z5=pp(w-u,.6h); z6=pp(w-2u,0);
+pd z1; pd z5; draw z1--z2--z3--z5; % arms and stem
+draw z1--.5[z2,z3]; pd z6; draw z6--.6[z3,z5]; % diagonals
+endchar;
+
+beginpunkchar("$",12,.5,.5);
+z1=pp(w-1.5u,.7h); z2=pp(.5w,h); z3=pp(u,.7h); z4=.5[z3,z5];
+z5=pp(w-u,.3h); z6=pp(.5w,0); z7=pp(u,.3h);
+pd z1; pd z7; draw z1..z2..z3..z4..z5..z6..z7; % stroke
+z8=z2+(0,.1h); pd z8; draw z8--z6; % stem
+endchar;
+
+beginpunkchar("%",18,.5,.5);
+z1=pp(3.5u,1.1h); z2=pp(u,.8h); z3=pp(3.5u,.5h); z4=pp(6u,.8h);
+z5=pp(w-3.5u,.5h); z6=pp(w-6u,.2h); z7=pp(w-3.5u,-.1h); z8=pp(w-u,.2h);
+pd z1; draw z1..z2..z3..z4..z1; % upper bowl
+pd z5; draw z5..z6..z7..z8..z5; % lower bowl
+z9=pp(w-3u,1.1h); z0=pp(3u,-.1h); pd z0; draw z9--z0; % diagonal
+draw z1{z5-z1}..z9; % link
+endchar;
+
+beginpunkchar("@",18,1,.5);
+z1=pp(2u,0); z2=pp(1/3w,.7h); z3=pp(w-6u,0);
+z4=pp(w,.3h); z5=pp(1/3w,h); z6=pp(u,.5h); z7=.7[z2,z3];
+pd z1; pd z7; draw z1--z2--z3{right}..z4..z5..z6..z7; % diagonals and stroke
+endchar;
+
+beginpunkchar("-",7,.5,.5);
+z1=pp(u,.4h); z2=pp(w-u,.5h); pd z1; pd z2; draw z1--z2; % bar
+endchar;
+
+beginpunkchar(8211,9,.5,.5); % --
+z1=pp(0,.5h); z2=pp(w,.4h); pd z1; pd z2; draw z1--z2; % bar
+endchar;
+
+beginpunkchar(8212,18,.5,.5); % ---
+z1=pp(0,.5h); z2=pp(w,.4h); pd z1; pd z2; draw z1--z2; % bar
+endchar;
+
+beginpunkchar("+",9,.5,1);
+z1=pp(0,.5h); z2=pp(w,.5h); pd z1; pd z2; draw z1--z2; % bar
+z3=pp(.5w,.1h); z4=pp(.5w,.9h); pd z3; pd z4; draw z3--z4; % stem
+endchar;
+
+beginpunkchar("*",13,.5,1);
+z0=pp(.5w,1.1h); z1=pp(u,.9h); z2=pp(2u,.3h); z3=pp(w-u,.3h); z4=pp(w-u,.9h);
+pd z0; draw z0--z2..1/3[.5[z2,z4],z0]..z4--z1--z3--z0; % star
+endchar;
+
+beginpunkchar(39,5,.5,1.5); % ' apostrofe HH/TH (to be checked)
+z1=pp(w/2,h); z2=pp(w/2+u,.85h); z3=pp(w/2,2/3h);
+pd z1; pd z3; draw z1..z2..z3; % stroke
+endchar;
+
+beginpunkchar(34,9,1,1.5); % " HH/TH (to be checked)
+z1=pp(1.5u,h); z2=pp(1.5u,.6h); z3=pp(w-1.5u,h); z4=pp(w-1.5u,.6h);
+pd z1; pd z2; pd z3; pd z4; draw z1--z2; draw z3--z4;
+endchar;
+
+beginpunkchar(8216,5,.3,.5); % `
+z1=pp(w-1.5u,h); z2=pp(u,.85h); z3=pp(w-u,2/3h);
+pd z1; pd z3; draw z1--z2--z3; % stroke
+endchar;
+
+beginpunkchar(8217,5,.3,.5); % '
+z1=pp(1.5u,h); z2=pp(w-u,.85h); z3=pp(u,2/3h);
+pd z1; pd z3; draw z1--z2--z3; % stroke
+endchar;
+
+beginpunkchar(8220,9,.3,.5); % `` quotedblleft
+z1=pp(.5w+.5u,h); z2=pp(w-u,.6h); z3=pp(u,.95h);
+pd z1; pd z3; draw z1--z2--z3; % stroke
+endchar;
+
+beginpunkchar(8221,9,.3,.5); % '' quotedblright
+z1=pp(.5w-.5u,h); z2=pp(u,.6h); z3=pp(w-u,.95h);
+pd z1; pd z3; draw z1--z2--z3; % stroke
+endchar;
+
+beginpunkchar("(",7,.5,.5);
+z1=pp(w-u,h); z2=pp(u,.5h); z3=pp(w-u,0);
+pd z1; pd z3; draw z1..z2..z3; % stroke
+endchar;
+
+beginpunkchar(")",7,.5,.5);
+z1=pp(u,h); z2=pp(w-u,.5h); z3=pp(u,0); pd z1; pd z3; draw z1..z2..z3; % stroke
+endchar;
+
+beginpunkchar("[",8,.5,.5);
+z1=pp(w-u,h); z2=pp(.5w,h); z3=pp(.5w,0); z4=pp(w-u,0);
+pd z1; pd z4; draw z1--z2--z3--z4; % bars and stem
+endchar;
+
+beginpunkchar("]",8,.5,.5);
+z1=pp(u,h); z2=pp(.5w,h); z3=pp(.5w,0); z4=pp(u,0);
+pd z1; pd z4; draw z1--z2--z3--z4; % bars and stem
+endchar;
+
+beginpunkchar("<",9,.5,.5);
+z1=pp(w-u,.9h); z2=pp(u,.5h); z3=pp(w-u,.1h);
+pd z1; pd z3; draw z1--z2--z3; % diagonals
+endchar;
+
+beginpunkchar(">",9,.5,.5);
+z1=pp(u,.9h); z2=pp(w-u,.5h); z3=pp(u,.1h);
+pd z1; pd z3; draw z1--z2--z3; % diagonals
+endchar;
+
+beginpunkchar("{",10,.5,.5); % HH/TH
+z1=pp(w-2u,h); z3=pp(2u,.5h); z5=pp(w-2u,0);
+z2=pp(w-4u,.6h); z4=(w-4u,.4h);
+pd z1; pd z3; pd z5; draw z1{left}..z2--z3 & z3--z4..{right}z5;
+endchar;
+
+beginpunkchar("}",10,.5,.5); % HH/TH
+z1=pp(2u,h); z3=pp(w-2u,.5h); z5=pp(2u,0);
+z2=pp(4u,.6h); z4=(4u,.4h);
+pd z1; pd z3; pd z5; draw z1{right}..z2--z3 & z3--z4..{left}z5;
+endchar;
+
+beginpunkchar("=",9,.5,.5);
+z5=pp(u,2/3h); z6=pp(w-u,2/3h); pd z5; pd z6; draw z5--z6; % upper bar
+z7=pp(u,1/3h); z8=pp(w-u,1/3h); pd z7; pd z8; draw z7--z8; % lower bar
+endchar;
+
+beginpunkchar("#",15,.5,.5);
+z1=pp(.5w,h); z2=pp(3u,0); z3=pp(w-3u,h); z4=pp(.5w,0);
+pd z2; pd z3; draw z3--z1--z2; draw z3--z4--z2; % diagonals (linked)
+z5=pp(u,2/3h); z6=pp(w-u,2/3h); pd z5; pd z6; draw z5--z6; % upper bar
+z7=pp(u,1/3h); z8=pp(w-u,1/3h); pd z7; pd z8; draw z7--z8; % lower bar
+endchar;
+
+beginpunkchar("/",9,1,1);
+z1=pp(1.5u,-.05h); z2=pp(w-1.5u,1.05h); pd z1; pd z2; draw z1--z2; % diagonal
+endchar;
+
+beginpunkchar("\",9,1,1); % HH/TH
+z1=pp(1.5u,1.05h); z2=pp(w-1.5u,-.05h); pd z1; pd z2; draw z1--z2; % reverse diagonal
+endchar;
+
+
+beginpunkchar("0",9,.5,1);
+z1=pp(.5w,h); z2=pp(u,.55h); z3=pp(.5w,0); z4=pp(w-u,.55h);
+pd z1; draw z1{curl 2}..z2..z3..z4..z1; % bowl
+endchar;
+
+beginpunkchar("1",9,.3,1);
+z1=pp(2u,.7h); z2=pp(.6w,h); z3=pp(.6w,0);
+pd z1; pd z3; draw z1--z2--z3; % serif and stem
+endchar;
+
+beginpunkchar("2",9,1,1);
+z1=pp(2u,.7h); z2=pp(.5w,h); z3=pp(w-u,.6h); z4=pp(u,0); z5=pp(w-2u,0);
+pd z1; pd z5; draw z1..z2..z3..z4--z5; % stroke
+endchar;
+
+beginpunkchar("3",9,.5,.5);
+z1=pp(2u,.7h); z2=pp(.5w,h); z3=pp(w-u,.5[y2,y4]);
+z4=pp(.5w-u,.55h); z5=pp(w-u,.5[y4,y6]); z6=pp(.5w,0); z7=pp(1.5u,.2h);
+pd z1; pd z7; draw z1..z2..z3..z4&z4..z5..z6..z7; % arcs
+endchar;
+
+beginpunkchar("4",9,1,1);
+z1=pp(w-u,.3h); z2=pp(u,.3h); z3=pp(2/3w,h); z4=pp(2/3w,0);
+pd z1; pd z4; draw z1--z2--z3--z4; % stem and diagonals
+endchar;
+
+beginpunkchar("5",9,.5,.5);
+z1=pp(w-2u,h); z2=pp(2u,h); z3=pp(u,.7h); z4=pp(w-u,.5[y3,y5]);
+z5=pp(.5w,0); z6=pp(u,.2h);
+pd z1; pd z6; draw z1--z2--z3..z4..z5..z6; % stroke
+endchar;
+
+beginpunkchar("6",9,1,1);
+z1=pp(2/3w,h); z2=pp(u,.3h); z3=pp(.5w,0); z4=pp(w-u,.3h); z5=pp(.6w,.6h);
+z6=pp z2; pd z1; pd z6; draw z1..z2..z3..z4..z5--z6; % stroke
+endchar;
+
+beginpunkchar("7",9,.5,1);
+z1=pp(2u,h); z2=pp(w-.5u,h); z3=pp(.4w,0);
+pd z1; pd z3; draw z1--z2&z2..z3{down}; % stroke
+endchar;
+
+beginpunkchar("8",9,.5,.5);
+z1=pp(.5w,h); z2=pp(u,.5[y1,y3]); z3=pp(.5w,.6h); z4=pp(w-u,.5[y3,y5]);
+z5=pp(.5w,0); z6=pp(u,.5[y5,y3]); z7=pp(w-u,.5[y1,y3]);
+pd z1; draw z1{curl 8}..z2..z3..z4..z5..z6..z3..z7..z1; % stroke
+endchar;
+
+beginpunkchar("9",9,1,1);
+z1=pp(1/3w,0); z2=pp(w-u,.7h); z3=pp(.5w,h); z4=pp(u,.7h); z5=pp(.5w,.4h);
+pd z1; pd z5; draw z1..z2..z3..z4..z5; % stroke
+endchar;
+
+beginpunkchar(96,9,1,1); % \`{} grave
+z1=pp(2.5u,h); z2=pp(.6w,.8h); pd z1; pd z2; draw z1--z2; % diagonal
+endchar;
+
+beginpunkchar(180,9,1,1); % \'{} acute
+z1=pp(w-2.5u,h); z2=pp(.4w,.8h); pd z1; pd z2; draw z1--z2; % diagonal
+endchar;
+
+beginpunkchar(710,13,1,1); % \^{} circumflex
+z1=pp(2.5u,.8h); z2=pp(.5w,h); z3=(w-2.5u,.8h);
+pd z1; pd z3; draw z1--z2--z3; % diagonals
+endchar;
+
+beginpunkchar(711,13,1,1); % \v{} caron
+z1=pp(2.5u,.9h); z2=pp(.5w,.7h); z3=pp(w-2.5u,.9h);
+pd z1; pd z3; draw z1--z2--z3; % diagonals
+endchar;
+
+beginpunkchar(728,11,1,1); % \u{} breve
+z1=pp(2u,h); z2=pp(.5w,.75h); z3=pp(w-2u,h);
+pd z1; pd z3; draw flex(z1,z2,z3); % stroke
+endchar;
+
+beginpunkchar(175,12,1,1); % \={} macron
+z1=pp(u,.8h); z2=pp(w-u,.8h); pd z1; pd z2; draw z1--z2; % bar
+endchar;
+
+beginpunkchar(729,5,1,1); % \.{}
+pd pp(.5w,.9h); % dot
+endchar;
+
+beginpunkchar(168,13,1,1); % \"{} diaeresis
+pd pp(1/5w,.9h); pd pp(4/5w,.9h); % dots
+endchar;
+
+beginpunkchar(732,13,1,1); % \~{} tilde
+z1=pp(u,.75h); z2=pp(w-u,.9h); pd z1; pd z2; draw z1{up}..{up}z2; % stroke
+endchar;
+
+beginpunkchar(733,13,1,1); % \H{} hungarumlaut
+z1=pp(4u,h); z2=pp(2.5u,.7h); z3=pp(w-2u,h); z4=pp(w-3.5u,.7h);
+pd z1; pd z3; draw z1--z2--z4--z3; % diagonals (linked)
+endchar;
+
+beginpunkchar(730,13,0,0); % Scandinavian loop, for \AA\ and \aa (ring)
+z0=(.5w,.66h); % point $z^2$ of lowercase A
+z1=(.5w,.9h); draw z0{z0-(1.5u,0)}..z1..{(w-1.5u,0)-z0}z0; % loop
+endchar;
+
+beginpunkchar(184,13,.5,.5); % Cedilla, for \c c
+z1=(.6w,0); z2=pp(.6w,-.1h); z3=pp(2.5u,-.1h);
+pd z3; draw z1--z2--z3; % stroke
+endchar;
+
+initialize_punk_lower ;
+
+beginpunkchar(305,5,1,2); % dotless I
+z1=pp(.5w,0); z2=(.5w,1/3h); z3=(.5w,2/3h); z4=(.5w,h);
+pd z1; pd z4; draw flex(z1,z2,z3,z4); % stem
+endchar;
+
+beginpunkchar(567,9,1,2); % dotless J
+z1=pp(w-2u,h); z2=pp(w-2u,-.1h); z3=pp(u,0);
+pd z1; pd z3; draw z1--z2--z3; % arc
+endchar;
+
+beginpunkchar(223,18,.3,1); % German SS
+z1=pp(.5w-u,.9h); z2=pp(1/3w,h); z3=pp(u,.7h); z4=.6[z6,z2];
+z5=pp(.5w,.35h); z6=pp(1/3w,u); z7=pp(u,.2h);
+pd z1; pd z7; draw z1--z2...z3..z4..z5...z6--z7; % left stroke
+for i=1 upto 7: z[i+10]=pp(z[i] shifted (.5w-u,0)); endfor
+pd z11; pd z17; draw z11--z12...z13..z14..z15...z16--z17; % right stroke
+endchar;
+
+beginpunkchar("a",13,1,2);
+z1=pp(1.5u,0); z2=(.5w,1.1h); z3=pp(w-1.5u,0);
+pd z1; pd z3; draw z1--z2--z3; % left and right diagonals
+z4=pp .3[z1,z2]; z5=pp .3[z3,z2]; pd z4; pd z5; draw z4--z5; % crossbar
+endchar;
+
+beginpunkchar("b",12,1,1);
+z1=pp(2u,0); z2=pp(2u,.6h); z3=pp(2u,h); pd z1; pd z3; draw z1--z3; % stem
+z1.5=pp(w-u,.5y2); z2.5=pp(w-u,.5[y2,y3]); draw z2--z2.5--z3; % upper lobe
+draw flex(z2,z1.5,z1); % lower lobe
+endchar;
+
+beginpunkchar("c",13,1,2);
+z1=pp(w-2u,.8h); z2=pp(.6w,h); z3=pp(u,.5h); z4=(.6w,0); z5=(w-2u,.2h);
+pd z1; pd z5; draw z1..z2..z3..z4..z5; % arc
+endchar;
+
+beginpunkchar("d",14,1,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-u,.6h);
+pd z1; pd z2; draw flex(z1,z3,z2); % lobe
+draw z1--z2; % stem
+endchar;
+
+beginpunkchar("e",12,.5,1);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2.5u,h); z4=pp(w-2u,0);
+pd z3; pd z4; draw z4--z1--z2--z3; % stem and arms
+z5=pp(2u,.6h); z6=pp(w-3u,.6h); pd z5; pd z6; draw z5--z6; % crossbar
+endchar;
+
+beginpunkchar("f",12,.5,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2u,h);
+pd z1; pd z3; draw z1--z2--z3; % stem and arm
+z5=pp(2u,.6h); z6=pp(w-3u,.6h); z4=pp .5[z5,z6]-(0,.1h);
+pd z5; pd z6; draw flex (z5,z4,z6); % crossbar
+endchar;
+
+beginpunkchar("g",13,.5,.5);
+z1=pp(w-2u,.8h); z2=pp(.6w,h); z3=pp(u,.5h); z4=pp(.6w,0); z5=(w-2u,0);
+pd z1; draw z1..z2..z3..z4---z5; % arc
+z6=pp(.5[u,x5],.4h); pd z6; pd z5; draw z6--(pp(x5,y6))--z5; % spur
+endchar;
+
+beginpunkchar("h",14,1,.5);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2u,0); z4=pp(w-2u,h);
+z5=pp(2u,.6h); z6=pp(w-2u,.6h);
+pd z1; pd z2; pd z3; pd z4; draw z1--z2; draw flex(z3,z6,z4); % stems
+pd z5; draw z5--z6; % crossbar
+endchar;
+
+beginpunkchar("i",5,1,2);
+z1=pp(.5w,0); z2=(.5w,1/3h); z3=(.5w,2/3h); z4=(.5w,h);
+pd z1; pd z4; draw flex(z1,z2,z3,z4); % stem
+endchar;
+
+beginpunkchar("j",9,1,2);
+z1=pp(w-2u,h); z2=pp(w-2u,-.1h); z3=pp(u,0);
+pd z1; pd z3; draw z1--z2--z3; % arc
+endchar;
+
+beginpunkchar("k",14,1,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(2u,1/3h); z4=pp(w-1.5u,h);
+pd z1; pd z2; draw z1--z2; % stem
+pd z3; pd z4; draw z3--z4; % upper diagonal
+z6=pp(w-u,0); z5=1/3[z3,z4];
+pd z6; draw flex(z5,.8[z1,2/3[z5,z6] ],z6);% lower diagonal
+endchar;
+
+beginpunkchar("l",11,1,2);
+z1=pp(2u,h); z2=pp(2u,0); z3=pp(w-1.5u,0);
+pd z1; pd z3; draw z1--z2--z3; % stem and arm
+endchar;
+
+beginpunkchar("m",17,.5,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(.5w,0); z4=pp(w-2u,h); z5=pp(w-2u,0);
+pd z1; pd z5; draw z1--z2--z3--z4--z5; % stems and diagonals
+endchar;
+
+beginpunkchar("n",13,.75,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-2u,0); z4=pp(w-2u,h);
+pd z1; pd z4; draw z1--z2--z3--z4; % stems and diagonals
+endchar;
+
+beginpunkchar("o",12,.5,2);
+z1=pp(.5w,h); z2=pp(u,.55h); z3=pp(.5w,0); z4=pp(w-u,.55h);
+pd z1; draw z1{left}..z2..z3..z4..z1; % bowl
+endchar;
+
+beginpunkchar("p",13,1,2);
+z1=pp(2u,0); z2=pp(2u,1.1h); z3=pp(2u,.5h); z4=pp(w,.6[y3,y2]);
+pd z1; pd z3; draw z1--z2--z4--z3; % stem and bowl
+endchar;
+
+beginpunkchar("q",14,.5,2);
+z1=pp(.5w,h); z2=pp(u,.55h); z3=pp(.5w,0); z4=pp(w-u,.55h);
+pd z1; draw z1{curl 2}..z2..z3..z4..z1; % bowl
+z5=pp(.4w,.2h); z6=pp(w-u,-.1h); z7=pp(.5[x5,x6],-.2h);
+pd z5; pd z6; draw z5--z7--z6; % tail
+endchar;
+
+beginpunkchar("r",16,1,2);
+z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-u,.6[y2,y4]); z4=pp(2u,.5h); z5=pp(w-1.5u,0);
+pd z1; pd z2; pd z5; draw z1--flex(z2,z3,z4)--z5; % stem, bowl, and diagonal
+endchar;
+
+beginpunkchar("s",11,.3,1);
+z1=pp(w-2u,.9h); z2=pp(.5w,h); z3=pp(u,.7h); z4=.6[z6,z2];
+z5=pp(w-u,.35h); z6=pp(.5w,u); z7=pp(u,.2h);
+pd z1; pd z7; draw z1--z2...z3..z4..z5...z6--z7; % stroke
+endchar;
+
+beginpunkchar("t",13,.75,2);
+z1=pp(u,h); z2=pp(w-u,h); z3=pp(.5w,0);
+pd z1; pd z2; pd z3; draw z1--z2; % arms
+draw .5[z1,z2]--z3; % stem
+endchar;
+
+beginpunkchar("u",13,.3,2);
+z1=pp(2u,h); z2=pp(2u,.2h); z3=pp(.5w,0); z4=pp(w-2u,.2h); z5=pp(w-2u,h);
+pd z1; pd z5; draw z1---z2...z3{z4-z2}...z4---z5; % stroke
+endchar;
+
+beginpunkchar("v",13,1,2);
+z1=pp(1.5u,h); z2=pp(.5w,0); z3=pp(w-1.5u,h);
+pd z1; pd z3; draw z1--z2--z3; % diagonals
+endchar;
+
+beginpunkchar("w",18,1,2);
+z1=pp(1.5u,h); z2=pp(.5[x1,x3],0); z3=pp(.5w,.8h); z4=pp(.5[x3,x5],0);
+z5=pp(w-1.5u,h);
+pd z1; pd z5; draw z1--z2--z3--z4--z5; % diagonals
+endchar;
+
+beginpunkchar("x",13,1,1);
+z1=pp(1.5u,h); z2=pp(w-1.5u,0); z3=pp(1.5u,0); z4=pp(w-2.5u,h);
+pd z1; pd z2; draw z1--z2; % main diagonal
+pd z3; pd z4; draw z3--z4; % cross diagonal
+endchar;
+
+beginpunkchar("y",13,1,2);
+z1=pp(1.5u,h); z2=pp(w-1.5u,h); z3=pp(.5w,.5h); z4=pp(.5w,0);
+pd z1; pd z2; pd z4; draw z1--z3--z4; % stem and left diagonal
+draw z2--z3; % right diagonal
+endchar;
+
+beginpunkchar("z",11,1,2);
+z1=pp(1.5u,h); z2=pp(w-2.5u,h); z3=pp(1.5u,0); z4=pp(w-1.5u,0);
+pd z1; pd z4; draw z1--z2--z3--z4; % diagonals
+endchar;
+
+beginpunkchar(230,16,1,2); % \ae
+z1=pp(1.5u,0); z2=pp(.6w,h); z3=pp(w-1.5u,h);
+pd z1; pd z3; draw z1--z2--z3; % left diagonal and upper arm
+z4=pp .3[z1,z2]; z5=pp(.6w,0); z6=pp(w-2u,.3h);
+pd z4; pd z6; draw z4--z6; % crossbar
+z7=pp(w-u,0); pd z2; pd z7; draw z2--z5--z7; % stem and lower arm
+endchar;
+
+beginpunkchar(339,18,1,2); % \oe
+z1=pp(.5w,h); z2=pp(u,.4h); z3=pp(.5w,0);
+pd z1; draw z1..z2..{right}z3; % bowl
+z4=pp(w-1.5u,h); z5=pp(w-2u,.4h); z6=pp(w-u,0);
+pd z4; pd z6; draw z4--z1--z3--z6; % arms and stem
+pd z5; draw z5--.4[z3,z1]; % crossbar
+endchar;
+
+beginpunkchar(248,14,1,1); % \o
+z1=pp(.5w,h); z2=pp(u,.5h); z3=pp(.5w,0); z4=pp(w-u,.5h);
+z5=pp(w-2u,1.1h); z6=pp(2u,-.1h);
+pd z1; pd z6; draw z1..z2..z3..z4..z5--z6; % bowl and diagonal
+endchar;
+
+revert_punk_lower;
+
+beginpunkchar("_",12,.5,.5); % _
+z1=pp(0,-.2h); z2=pp(w,-.2h); pd z1; pd z2; draw z1--z2; % bar
+endchar;
+
+beginpunkchar("^",12,1,.5); %
+z1=pp(.5w,h); z2=pp(1.5u,.6h); z3=pp(w-1.5u,.6h);
+pd z2; pd z3; draw z2--z1--z3;
+endchar;