summaryrefslogtreecommitdiff
path: root/graphics/mfpic
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/mfpic
Initial commit
Diffstat (limited to 'graphics/mfpic')
-rw-r--r--graphics/mfpic/README143
-rw-r--r--graphics/mfpic/doc/README143
-rw-r--r--graphics/mfpic/doc/changes.txt839
-rw-r--r--graphics/mfpic/doc/coil.mps139
-rw-r--r--graphics/mfpic/doc/examples/data.dat37
-rw-r--r--graphics/mfpic/doc/examples/forfun.tex160
-rw-r--r--graphics/mfpic/doc/examples/lapictures.tex206
-rw-r--r--graphics/mfpic/doc/examples/pictures.tex204
-rw-r--r--graphics/mfpic/doc/install.txt106
-rw-r--r--graphics/mfpic/doc/lcheadings.ist11
-rw-r--r--graphics/mfpic/doc/mfpcard.pdfbin0 -> 145519 bytes
-rw-r--r--graphics/mfpic/doc/mfpcard.tex659
-rw-r--r--graphics/mfpic/doc/mfpdoc.sty294
-rw-r--r--graphics/mfpic/doc/mfpguide.pdfbin0 -> 344598 bytes
-rw-r--r--graphics/mfpic/doc/mfpguide.tex1640
-rw-r--r--graphics/mfpic/doc/mfpic-doc.pdfbin0 -> 558198 bytes
-rw-r--r--graphics/mfpic/doc/mfpic-doc.tex7575
-rw-r--r--graphics/mfpic/install.txt106
-rw-r--r--graphics/mfpic/metafont/grafbase.mf4055
-rw-r--r--graphics/mfpic/metapost/dvipsnam.mp118
-rw-r--r--graphics/mfpic/metapost/grafbase.mp4051
-rw-r--r--graphics/mfpic/source/grafbase.dtx9710
-rw-r--r--graphics/mfpic/source/mfpic.dtx6735
-rw-r--r--graphics/mfpic/source/mfpic.ins59
-rw-r--r--graphics/mfpic/tex/mfpic.sty67
-rw-r--r--graphics/mfpic/tex/mfpic.tex1786
-rw-r--r--graphics/mfpic/tex/mfpicdef.tex39
27 files changed, 38882 insertions, 0 deletions
diff --git a/graphics/mfpic/README b/graphics/mfpic/README
new file mode 100644
index 0000000000..fcc76efe00
--- /dev/null
+++ b/graphics/mfpic/README
@@ -0,0 +1,143 @@
+% File: README
+% A part of mfpic 1.10 2012/11/13
+%
+
+MFpic defines a command group \mfpic...\endmfpic (optionally in LaTeX
+an environment, mfpic) and drawing commands to be used inside this group.
+When TeX (or LaTeX) is run on a file containing those commands, a
+MetaPost (or Metafont) source file is created. When that file is correctly
+processed by MetaPost (or Metafont), and LaTeX or TeX is run again, the
+result is a figure in the TeX document at the location of each
+environment.
+
+See install.txt for installation instructions. See mfpguide.pdf for a
+short tutorial. See below for a summary of features added since the
+previous major release (1.0). See the manual mfpic-doc.pdf for more
+detailed instructions and descriptions of features.
+
+This is mfpic version 1.10
+
+LICENSE
+-------
+All files of the core mfpic distribution (listed below) may be
+distributed and/or modified under the conditions of the LaTeX Project
+Public License, either version 1.3c of this license or (at your option)
+any later version. The latest version of this license is
+
+ http://www.latex-project.org/lppl.txt
+
+and version 1.3c or later is part of all distributions of LaTeX version
+2008/12/01 or later.
+
+DISCLAIMER
+----------
+While every effort has been made to make mfpic useful, it comes with no
+warranty, expressed or implied.
+
+MANIFEST
+--------
+Here is a list, plus explanation of purpose, of all files in the mfpic
+distribution. Read it *before* trying to process any of the example
+files. These files constitute the mfpic distribution to which the LPPL
+applies.
+
+The six files marked with "+" below are the only ones essential to using
+all the facilities of mfpic. The three files marked with "*" below are
+sufficient to generate those essential files.
+
+All the *.tex files in the doc directory (except the plain TeX file
+mfpcard.tex) require the LaTeX style file mfpdoc.sty. The mfpic manual
+is mfpic-doc.pdf. A tutorial is available in mfpguide.pdf.
+
+The directory names given below are subdirectories of graphics/mfpic/ in
+your nearest CTAN mirror (go to http://mirror.ctan.org/)
+
+Source files (in source/):
+------------
+*mfpic.dtx Contains mfpic.sty and mfpic.tex
+*grafbase.dtx Contains grafbase.mf, grafbase.mp and dvipsnam.mp
+*mfpic.ins The unpacking script: run tex or latex on it. It reads
+ in mfpic.dtx and grafbase.dtx and produces the six
+ required run-time files (marked "+" below)
+
+TeX/LaTeX code (in tex/):
+--------------
++mfpic.tex Basic TeX/LaTeX code
++mfpic.sty LaTeX2e wrapper for mfpic.tex
++mfpicdef.tex Input file used by metapost for TeX labels
+
+MetaPost/Metafont code (in metapost/ and metafont/):
+----------------------
++grafbase.mp MetaPost macros supporting mfpic
++dvipsnam.mp Color definitions for MetaPost, needed by grafbase.mp
++grafbase.mf Metafont macos supporting mfpic
+
+Documentation (in doc/):
+-------------
+ changes.txt Summary of 20+ years of changes
+ install.txt Basic information on installation
+ README This file.
+ mfpguide.pdf Tutorial (usletter paper size)
+ mfpic-doc.pdf Manual (usletter paper size)
+ mfpcard.pdf Reference card (two sides of usletter, landscape).
+ mfpdoc.sty LaTeX style used by the next two
+ mfpguide.tex LaTeX source for mfpguide.pdf, requires mfpdoc.sty and
+ the mfpic package.
+ mfpic-doc.tex LaTeX source for mfpic-doc.pdf, requires mfpdoc.sty.
+ coil.mps Figure included in mfpic-doc.tex
+ mfpcard.tex reference card source, should fit on two sides of
+ either USletter or A4, rotated. Plain TeX.
+ lcheaders.ist makeindex style file for mfpic-doc.tex
+
+Examples (in doc/examples/):
+--------
+ pictures.tex Example pictures. Produces pics.mp. Plain TeX
+ lapictures.tex Same examples. Produces same pics.mp. LaTeX
+ data.dat Sample data file used by above two
+ forfun.tex Examples of \mfsrc. Produces fun.mp. Plain TeX
+
+
+This distribution, any new updates, and some past versions, should also be
+available at my web site:
+
+http://comp.uark.edu/~luecking/tex/mfpic.html
+
+
+NEW FEATURES since Version 1.0
+-------------------------------
+
+ -- bugfix in \vectorfield. (1.01)
+
+ -- Work-around for some not-so-nice behavior of verbatimtex in some
+ versions of MetaPost. (1.02)
+
+ -- Bugfix in grafbase handling of color. (1.03)
+
+ -- Bugfix in \mfresolution and \mfmode. (1.04)
+
+ -- Changes to avoid namespace clashes in some internal macros. (1.05)
+
+ -- Differential equation plotters \DEgraph and \DEtrajectory added. (1.06)
+
+ -- Remove mfppatch.tex (which has never been used). (1.06)
+
+ -- Added file mfpicdef.tex for metapost labels. (1.07)
+
+ -- Added \quarterellipse, \halfellipse and \fullellipse. (1.07)
+
+ -- Added \gbrace for large braces in pictures. (1.07)
+
+ -- Added \hypergeodesic for certain (technical) circular arcs. (1.07)
+
+ -- Added \browniangraph and \randomwalk (1.07)
+
+ -- Added \gradient, \radialgradient and \areagradient (1.08)
+
+ -- Added \interpolatepath. Added \reversepath (= \reverse) (1.10)
+
+\sig
+Dan Luecking (luecking at uark dot edu)
+Department of Mathematical Sciences
+University of Arkansas
+Fayetteville, Arkansas 72701-1201
+U.S.A.
diff --git a/graphics/mfpic/doc/README b/graphics/mfpic/doc/README
new file mode 100644
index 0000000000..fcc76efe00
--- /dev/null
+++ b/graphics/mfpic/doc/README
@@ -0,0 +1,143 @@
+% File: README
+% A part of mfpic 1.10 2012/11/13
+%
+
+MFpic defines a command group \mfpic...\endmfpic (optionally in LaTeX
+an environment, mfpic) and drawing commands to be used inside this group.
+When TeX (or LaTeX) is run on a file containing those commands, a
+MetaPost (or Metafont) source file is created. When that file is correctly
+processed by MetaPost (or Metafont), and LaTeX or TeX is run again, the
+result is a figure in the TeX document at the location of each
+environment.
+
+See install.txt for installation instructions. See mfpguide.pdf for a
+short tutorial. See below for a summary of features added since the
+previous major release (1.0). See the manual mfpic-doc.pdf for more
+detailed instructions and descriptions of features.
+
+This is mfpic version 1.10
+
+LICENSE
+-------
+All files of the core mfpic distribution (listed below) may be
+distributed and/or modified under the conditions of the LaTeX Project
+Public License, either version 1.3c of this license or (at your option)
+any later version. The latest version of this license is
+
+ http://www.latex-project.org/lppl.txt
+
+and version 1.3c or later is part of all distributions of LaTeX version
+2008/12/01 or later.
+
+DISCLAIMER
+----------
+While every effort has been made to make mfpic useful, it comes with no
+warranty, expressed or implied.
+
+MANIFEST
+--------
+Here is a list, plus explanation of purpose, of all files in the mfpic
+distribution. Read it *before* trying to process any of the example
+files. These files constitute the mfpic distribution to which the LPPL
+applies.
+
+The six files marked with "+" below are the only ones essential to using
+all the facilities of mfpic. The three files marked with "*" below are
+sufficient to generate those essential files.
+
+All the *.tex files in the doc directory (except the plain TeX file
+mfpcard.tex) require the LaTeX style file mfpdoc.sty. The mfpic manual
+is mfpic-doc.pdf. A tutorial is available in mfpguide.pdf.
+
+The directory names given below are subdirectories of graphics/mfpic/ in
+your nearest CTAN mirror (go to http://mirror.ctan.org/)
+
+Source files (in source/):
+------------
+*mfpic.dtx Contains mfpic.sty and mfpic.tex
+*grafbase.dtx Contains grafbase.mf, grafbase.mp and dvipsnam.mp
+*mfpic.ins The unpacking script: run tex or latex on it. It reads
+ in mfpic.dtx and grafbase.dtx and produces the six
+ required run-time files (marked "+" below)
+
+TeX/LaTeX code (in tex/):
+--------------
++mfpic.tex Basic TeX/LaTeX code
++mfpic.sty LaTeX2e wrapper for mfpic.tex
++mfpicdef.tex Input file used by metapost for TeX labels
+
+MetaPost/Metafont code (in metapost/ and metafont/):
+----------------------
++grafbase.mp MetaPost macros supporting mfpic
++dvipsnam.mp Color definitions for MetaPost, needed by grafbase.mp
++grafbase.mf Metafont macos supporting mfpic
+
+Documentation (in doc/):
+-------------
+ changes.txt Summary of 20+ years of changes
+ install.txt Basic information on installation
+ README This file.
+ mfpguide.pdf Tutorial (usletter paper size)
+ mfpic-doc.pdf Manual (usletter paper size)
+ mfpcard.pdf Reference card (two sides of usletter, landscape).
+ mfpdoc.sty LaTeX style used by the next two
+ mfpguide.tex LaTeX source for mfpguide.pdf, requires mfpdoc.sty and
+ the mfpic package.
+ mfpic-doc.tex LaTeX source for mfpic-doc.pdf, requires mfpdoc.sty.
+ coil.mps Figure included in mfpic-doc.tex
+ mfpcard.tex reference card source, should fit on two sides of
+ either USletter or A4, rotated. Plain TeX.
+ lcheaders.ist makeindex style file for mfpic-doc.tex
+
+Examples (in doc/examples/):
+--------
+ pictures.tex Example pictures. Produces pics.mp. Plain TeX
+ lapictures.tex Same examples. Produces same pics.mp. LaTeX
+ data.dat Sample data file used by above two
+ forfun.tex Examples of \mfsrc. Produces fun.mp. Plain TeX
+
+
+This distribution, any new updates, and some past versions, should also be
+available at my web site:
+
+http://comp.uark.edu/~luecking/tex/mfpic.html
+
+
+NEW FEATURES since Version 1.0
+-------------------------------
+
+ -- bugfix in \vectorfield. (1.01)
+
+ -- Work-around for some not-so-nice behavior of verbatimtex in some
+ versions of MetaPost. (1.02)
+
+ -- Bugfix in grafbase handling of color. (1.03)
+
+ -- Bugfix in \mfresolution and \mfmode. (1.04)
+
+ -- Changes to avoid namespace clashes in some internal macros. (1.05)
+
+ -- Differential equation plotters \DEgraph and \DEtrajectory added. (1.06)
+
+ -- Remove mfppatch.tex (which has never been used). (1.06)
+
+ -- Added file mfpicdef.tex for metapost labels. (1.07)
+
+ -- Added \quarterellipse, \halfellipse and \fullellipse. (1.07)
+
+ -- Added \gbrace for large braces in pictures. (1.07)
+
+ -- Added \hypergeodesic for certain (technical) circular arcs. (1.07)
+
+ -- Added \browniangraph and \randomwalk (1.07)
+
+ -- Added \gradient, \radialgradient and \areagradient (1.08)
+
+ -- Added \interpolatepath. Added \reversepath (= \reverse) (1.10)
+
+\sig
+Dan Luecking (luecking at uark dot edu)
+Department of Mathematical Sciences
+University of Arkansas
+Fayetteville, Arkansas 72701-1201
+U.S.A.
diff --git a/graphics/mfpic/doc/changes.txt b/graphics/mfpic/doc/changes.txt
new file mode 100644
index 0000000000..dc99de4dfa
--- /dev/null
+++ b/graphics/mfpic/doc/changes.txt
@@ -0,0 +1,839 @@
+% File: changes.txt
+% A part of mfpic 1.10 2012/12/03
+%
+
+ Summaries of changes.
+
+0.1:
+First version released to network, 30 June 1992.
+
+0.2:
+Second version released to network, 7 Sept. 1992. (Still had 0.1.13.1
+version number in code---oops!) Many new features added, bugs
+worked out, code cleaned up.
+
+
+0.2.5 of Wed 10 Nov. 1993:
+Bug fix release Primarily work by Geoffrey Tobin.
+
+0.2.5.1 of Wed 13 July 1994:
+Bug fix release Corrected "unxconv" bug which remained in version
+0.2.5's graphbase.mf.
+
+0.2.9 Alpha of Thu 11 August 1994:
+A test release prior to any official version 0.3, is ready for intrepid
+users. Introduces coordinate transforms, and other novelties.
+
+0.2.9.1 Alpha} of Thu 8 September 1994:
+Fixes a bug in \sclosed and a bug in \white, corrects some omissions and
+typos in the documentation, and adds the \shadewd, \hatchwd, \lhatch and
+\rhatch macros.
+
+0.2.9.3 Alpha of Thu 21 March 1995:
+Renamed \fill to \gfill, in order to avoid conflict with the LaTeX \fill
+macro.
+
+0.2.9.4 Alpha of Thu 13 April 1995:
+Renaming of \label to \tlabel, and \caption to \tcaption, in order to
+avoid conflict with the LaTeX macros with those names.
+
+\white was renamed to \gclear, because \white is a likely name for a
+color macro.
+
+Also, a new macro for defining Metafont functions was introduced,
+because user-defined functions provide more power, and function plotting
+macros were added that accept Metafont function names instead of
+Metafont expressions.
+
+0.2.9.5 Alfa of Wed 19 July 1995:
+Renames \mfcmd to \mfsrc for clarity.
+
+Renames \wedge to \sector to avoid conflict with the character name
+defined in plain TeX and LaTeX.
+
+Introduces \mftitle, \tmtitle and \plr.
+
+Abolishes \plrpoint, \plrlines, \plrcurve and \plrcyclic as
+redundant specializations. The meaning of \turtle is changed to a
+Cartesian form, for flexibility.
+
+Rendering macros redesigned, and \setrender introduced. Coordinate
+transforms in grafbase.mf made slightly more robust. Begin an attempt
+to make grafbase.mf compatible with John Hobby's MetaPost drawing
+program.
+
+0.2.9.6 Alfa of Mon 24 July 1995:
+Contributes \thatch which provides hatching by lines at any angle.
+
+Modifications to \pen, \shadewd and \hatchwd, along with changes to
+grafbase.mf to make drawing, shading and hatching more independent.
+
+Renamed \rotate to \rotatepath.
+
+Also renamed the affine transform macros, so that they no longer use the
+`s' of the present tense, which could be mistaken for a plural.
+
+0.2.9.8 alfa, Mon 11 September 1995:
+Retain line separations of user's document's mfpic environment when
+writing Metafont file. This prevents long Metafont commands from
+exceeding Metafont's input buffer.
+
+0.2.10.5 alfa, Sat 9 March 1996:
+Introduced \polyline as an alternative name for \lines.
+
+In order to avoid repetition of side-effects, changed \tcaption to use
+\unhbox\@textbox, instead of repeating its text argument.
+
+0.2.10.6 alfa, (two hours later) on Sat 9 March 1996:
+\polygon figure has been introduced;
+
+\\ specifies explicit line breaks in tlabels and tcaptions;
+
+\savepic and \copypic allow saving, use and copying of an entire
+mfpic picture, including its tcaptions and tlabels.
+
+Also modified \tcaption code to prevent repeated use of the text
+argument, as that can cause side effects, as reported by Dennis
+Petrovic.
+
+0.2.10.7 alfa, Sat 28 March 1996:
+First release via Geoffrey Tobin's School's local anon ftp site:
+ ftp.ee.latrobe.edu.au : pub/gt/mfpic
+
+0.2.10.8 alfa, Tue 26 May 1996:
+Second, and bug fix, release via Geoffrey Tobin's anonymous ftp area.
+
+0.3.0 alpha, 1998:
+Numbers jump a lot from here because I (Dan Luecking) have been lax in
+keeping track of changes. First version with support for Metapost. Now
+any(?) .mf file created by a recent mfpic can be run through Metapost
+to produce a PostScript picture.
+
+Added functions sin, cos, and their inverses invsin,
+etc., that compute in radian measure. Also tan and cot.
+
+0.3.8 alpha, 1999:
+Color has been added. Default colors for lines/curves (drawcolor),
+fills (fillcolor), hatch patterns (hatchcolor), and arrowheads
+(headcolor). Optional arguments for color added to \gfill, \draw,
+\arrow, and all the hatching macros. A new macro \polkadot creates
+polkadot fill patterns.
+
+Changed some of the commands for setting dimensions so that they
+actually worked, and so they are local to mfpic environments.
+
+Added support for LaTeX2e's \usepackage command and options. Added
+graphics inclusion code. Added code to detect which TeX format was in
+use.
+
+0.3.9 alpha, 2000:
+Minor change to definition of \circle to avoid error messages in LaTeX.
+
+Changed the graphic placement code so that it tests for the existence of
+the graphic first.
+
+0.3.10 alpha, 2000:
+Added changes contributed by Jaromir Kuben: An option centercaptions
+and command \centercaptions to center the lines in a \tcaption. Also
+\nocentercaptions. Improvements to the code that positions text labels
+(so that) c and b now take into account the depth of the text. A new
+parameter B to align the baseline of the text with the point.
+
+Added option dvipsnames to allow color names as in the dvips header
+color.pro. Later removed and made default. Added color functions
+cmyk, RGB, gray and rgb.
+
+Added functions tanh, its inverse atanh, and additional trig
+functions secd, sec, cscd, csc, atan, invtan. Made log a
+synonym for ln. Added complex variables functions Arg, cis, zexp
+and Log.
+
+0.3.11 alpha, 2000:
+Added \plot similar to \dotted but these shapes can be placed:
+ Triangle, Square, Circle, Plus, Cross, Star, SolidTriangle,
+ SolidSquare, or SolidCircle
+
+0.3.12 alpha, 2000:
+Added macro \datafile to read a file of number pairs and create the
+polygonal path connecting them.
+
+Added options clip, truebbox, and debug.
+Command forms: \clipmfpic, \noclipmfpic, \usetruebbox,
+\notruebbox, \mfpicdebugtrue, and \mfpicdebugfalse.
+
+Changed names of various commands to a more imperative form:
+\usemetapost, \usemetafont,
+Changed name of option centercaptions to centeredcaptions.
+
+0.3.13 alpha, 2000:
+\datafile now ignores leading blank lines and comments,
+and won't gag on commented out EOLs.
+
+Went back to technique of expanding argument of \tcaption twice:
+caveat emptor.
+
+New command \plotdata reads a data file and draws one (polygonal) path
+for each non-blank sequence of lines in the data file. Exits when a pair
+of blank lines is encountered (or EOF). Cycles through six different
+drawing styles for successive curves. User may elect different colors
+(with \coloredlines), different symbols (\pointedlines), or
+different dashing patterns (\dashedlines).
+
+New command \using affects what \datafile and \plotdata write to
+the .mf output.
+
+\gendashed{<pattern>}... is a generalized dashing command; <pattern>
+is the name of a dashing pattern.
+\dashpat{<name>}{<dim1>,<dim2>,...,<dim2n>} creates a dashing pattern
+with the specified name.
+
+All dots now pixel aligned in shading. Looks infinitely better.
+
+Added Diamond and SolidDiamond to the symbols available.
+
+A command \fcncurve that draws a function (i.e., curve doesn't double
+back) if the x-values are unique and listed in order.
+
+0.3.14 alpha, 2000:
+Added optiom mplabels to make \tlabel write btex ... etex groups
+to the .mp file. Commands \usemplabels and \nomplabels.
+Added third part to the optional argument of \tlabel to
+rotate the text. Ignored without mplabels
+
+New macro \mfpdatacomment so that \datafile and \plotdata can now
+have their comment character reset. Commands \makepercentother and
+\makepercentcomment created to allow the user to use `%' in \using
+arguments.
+
+Gave \plotdata the ability to cycle through 8 colors or 9 symbols
+(instead of only 6).
+
+Draw a frame for figures not yet created. Add command \frame for users.
+
+Added \fdef, which seemed to be documented (see Update 0.2.9.4 above),
+but somehow not defined.
+
+Changed \savepic: Now use \newpic{\foo} to allocate a box,
+\savepic{\foo} to store the next picture, and \usepic{\foo} to copy
+it.
+
+0.3.15 alpha, 2000:
+Added \mfpverbtex to write verbatimtex block to .mp file.
+
+Changed \newpic to \newsavepic to more closely parallel LaTeX's
+\newsavebox command.
+
+Allow plotting of a number in a data file against its sequence position
+with \using{...}{...\sequence...}.
+
+Added \pointdef: \pointdef{A}(1,3) makes \A expand to (1,3), with
+\Ax and \Ay expanding to 1 and 3, respectively.
+
+
+0.4.0 beta, Aug 2000:
+Released to CTAN.
+
+
+0.4.01 beta, Nov/Dec 2000:
+Generate a time-stamp for the output file.
+
+Added \penwd as a synonym for \pen.
+
+Added macros \xaxis[<hlen>] and \yaxis[<hlen>] with the obvious
+meanings.
+
+0.4.04 beta, Mar 2001:
+Added \smoothdata[<tension>] to cause \datafile and \plotdata to
+draw smooth curves with optional tension setting. And \unsmoothdata to
+restore the default.
+
+0.4.10 beta, May 2001:
+Renamed \framed to \mfpframed, similarly: \mfpframegap and
+\mfpframethickness.
+
+\tlabeloffset{<hadj>}{<vadj>} and \tlabelsep{<dimen>} added to apply
+offsets to label placement.
+
+Added macros for drawing axes along the borders of the picture, and
+tickmarks along those axes. Syntax eventually settled on in 0.4.16:
+
+ \axis{<axis>}, draws an axis (\axis{x} almost equivalent to \xaxis).
+ Allowed values for <axis>: x, y, l, b, r, and t.
+ \axismargin{<axis>}{<num>}, sets the axis margin (lbrt only)
+ \setaxismargins{<num>}{<num>}{<num>}{<num>}, sets all 4 margins.
+ \setallaxismargins{<num>}, sets all 4 margins.
+
+ \xmarks, \ymarks, \lmarks, \bmarks, \rmarks, \tmarks, place the marks.
+ \setaxismarks{<axis>}{<pos>}, sets position of tic marks. Allowed
+ <pos> are inside, outside, ontop, onbottom, and centered. 2
+ abbreviations: \setxmarks and \setymarks.
+ \setbordermarks{<pos>}{<pos>}{<pos>}{<pos>}
+ \setallbordermarks{<pos>}
+
+For arrowheads on the side axis, a dimesion \sideheadlen was added.
+
+Added \gridlines to draw a regular grid of lines.
+
+Added \tlabeljustify to change the default justification of text
+labels.
+
+Added the command \tlabels (note the plural). It has one mandatory
+argument which contains a concatenation of arguments for one or more
+\tlabel commands.
+
+0.4.11--15 beta, July 2001:
+Added support for multiline labels under mplabels.
+
+Added ability to create a curve surrounding some text:
+\tlabelrect creates a rectangle, with optionally rounded corners,
+\tlabeloval creates an ellipse with aspect ratio the same as the block
+ of text (optionally multiplied by a given factor),
+\tlabelellipse creates an ellipse with an optional aspect ratio
+ (default = 1),
+\tlablecircle is \tlabelellipse[1].
+
+Added \axislabels. This takes a letter indicating the axis, an
+optional justification parameter (as in \tlabel) and a comma separated
+list of TeX text and numbers.
+
+Added \tlabelcolor to control color of Metapost placed text.
+Added \backgroundcolor to set the color variable background, the
+color used by \gclear.
+
+Added \doaxes. It takes a set of letters chosen from {xylbrt}, and
+draws the specified axes.
+
+Added optional parameter to \plotdata and \datafile; can be used
+instead of \(un)smoothdata.
+
+Added \mfpframe...\endmfpframe to frame the contents.
+
+0.4.16 beta, July 28--30 2001:
+Added "star form" of each \tlabel<path> that defines the curve without
+placing the label.
+
+0.4.17 beta, July 28--Aug 10, 2001:
+Commands: \function, \parafcn, \plrfcn, \btwnfcn and
+\plrregion now take an option of the form [s<tension>].
+
+Changed the \mfpic command so both optional parameters may be omitted
+(scale 1 is then assumed).
+
+0.4.18 beta, Aug 10--20, 2001:
+Added point size option to \grid.
+
+Added a macro \plottext similar to \plotsymbol except instead of a
+symbol, it takes a bit of TeX text.
+
+Added \plrgrid and \plrpatch.
+
+Added \piechart and \piewdge.
+
+0.4.19 beta, Aug 20--26, 2001:
+Added \mfpicnumber to set the number of the next character or figure.
+
+0.4.20 beta, Aug 26--Sep 1, 2001:
+Added \barchart.
+
+0.4.21 beta, Sept 1--10, 2001:
+Added SolidStar to symbols available. Changed Star to produces an
+open five-pointed star instead of the asterisk previously drawn. Added
+Asterisk to duplicate the old Star.
+
+Added \shiftpath{p}, \scalepath{p,sf}, \xscalepath{x,sf},
+\yscalepath{y,sf} and \slantpath{y,sl}. "p" is a pair "sf" is a
+scale factor, "x" is an x-coordinate, "y" is a y-coordinate and "sl"
+is a slant factor.
+
+0.4.22 beta, Sept 11--22, 2001:
+Added \reflectpath{p1,p2}, \xyswappath and \yslantpath{x,sl}; also
+\xslantpath (a synonym for \slantpath).
+
+0.5.0 beta, Sept 24--Oct25, 2001:
+Change comment written at the top of the output file. Now includes the
+name of the output file, as well as the \jobname of the TeX source
+that produced it.
+
+Made \mfpic and \endmfpic write the source line number to the
+output for debugging use.
+
+Added \everytlabel for setting commands issued at the outermost level
+at the start of each label.
+
+\mfpic now writes "verbatimtex \begingroup etex" to
+output and \endmfpic ends the group (under mplabels).
+
+Released to CTAN, Oct, 2001.
+
+0.5.01 beta
+Corrects a small bug by adding some braces around the point arguments of
+\tlabel in a couple of places.
+
+0.5.04 alpha, ???--April 11, 2002:
+Added options draft, final, and nowrite (commands \mfpicdraft,
+\mfpicfinal, and \mfpicnowrite) which should avoid including the
+pictures (draft) or include the pictures (final), overriding automatic
+decisions. Option nowrite avoids writing anything to the .mf file.
+
+Rewrote \tlabel and friends so that the point arguments could
+be enclosed in braces.
+
+All those macros that take a list as last argument can now substitute
+"\datafile{name}" in place of the list.
+
+Collected the common code in \xmarks, \ymarks, etc., so that now they
+are implemented with \marks x, etc. (Later renamed to \axismarks.)
+
+Added aliases \lattice and \gridpoints for \grid.
+
+0.5.05 alpha, April 16, 2002:
+Corrected bug in \mfpverbtex which caused # symbols to be doubled in
+the output.
+
+0.5.06 alpha, April 16--May 7, 2002:
+Made changes to avoid MF/MP overflow in \tlabelellipse/oval.
+
+0.5g (= 0.5.07) alpha, May 7--June 25, 2002:
+Added \usingpairdefault to reset the \using specification to the
+default. Also \usingnumericdefault for commands that take numeric
+data.
+
+Changed version numbering scheme so LaTeX file utilities like the
+snapshot package are better served.
+
+0.5h alpha, Aug 1--6, 2002:
+Added \gclip rendering macro that clips the current picture to a path.
+
+0.6 beta, Sep 12, 2002:
+Uploaded to CTAN.
+
+0.6a alpha, Sep 12--Nov 5, 2002.
+Added \let\par\relax (later \@empty) in \mfpic to nullify blank lines
+in user code. (Reported by Jaromir Kuben.) Put in commands to restore
+\par to its normal meaning in labels and captions.
+
+0.6b beta, Nov 6--, 2002.
+Correct sign on sinh function with negative argument
+
+0.6c beta, Nov 6--, 2002.
+Bounding box had the horizontal and vertical data reversed if all
+of the following three options were selected: metapost, mplabels and
+clip.
+0.63(=0.6c) alpha
+New numbering scheme: increment hundreds (perhaps also thousands) digit
+for alpha, add letters only for patches to released beta version.
+
+Added check that versions match to mfpic and grafbase.
+
+Added a \partialpath{a,b} (later \partpath) command to produce the
+subpath of the following path f that goes from a*length(f) to
+b*length(f).
+
+Also added \subpath{a,b} to give the equivalent of the MF code
+ subpath (a, b) of <following path>
+
+Added tension option to closure commands where it makes sense.
+
+Moved \fdef to a global location.
+
+Rewrote \tlabelrect, etc., so that they take a second optional
+parameter: the label justification.
+
+Redid all(?) optional argument handling so that an empty optional
+argument is the same as no optional argument.
+
+Changed \store to be usable as a prefix command.
+
+Removed bug reintroduced into filling commands (shade , polkadot and
+tess) so they did not respect aspect_ratio (affected only MF).
+
+Introduced color to Metafont: color functions (rgb, cmyk, etc.) return a
+numeric. Drawing commands subtract white paths (and simply draw others).
+A process something like \shade is used to produce gray polkadots and
+fills.
+
+Transcribed documentation to latex.
+
+Packaged mfpic in mfpic.dtx, mfpic.ins and grafbase.dtx.
+
+0.64 alpha
+Added optional argument to \circle (similar to the ones for \arc). So
+the circle through three points can be easily drawn, filled, etc.
+
+0.65 alpha
+Rewrote \noship and added \stopshipping and \resumeshipping so that
+shipping can be turned off for several figures.
+
+Added \transformpath , similar to \applyT except that it is a
+modification macro for figures. It's argument is a transformer.
+
+Added \cutoffafter {<obj>} and \cutoffbefore {<obj>} as prefix
+macros that cut the following path after its intersection with the named
+<obj>.
+
+Added \trimpath{<dim1>,<dim2>} , a prefix macro that removes the part
+of the following path within <dim1> of its start and within <dim2>
+of its end.
+
+0.66 alpha
+Added \pointcolor , the color in which points are drawn by \point and
+in which symbols are drawn by \plotsymbol.
+
+The optional parameter of \tlabelrect may now be the literal word
+"roundends". This will make the radius of the quarter circles equal to
+half the narrower dimension of the rectangle, giving the "rectangle"
+semicircular ends.
+
+0.67 alpha
+Allow the use of \usetruebbox in an mfpic environment.
+
+Added \reconfigureplot which takes the word `dashes', `colors', or
+`symbols' for an argument, followed by a list to be used by \plotdata.
+Added \defaultplot which takes the same arguments and restores the
+builtin defaults.
+
+Added \regpolygon{n}{P}{<eqn1>}{<eqn2>}.
+
+Moved the loading of the figure to \endmfpic.
+
+Added \mpobj as a synonym for \mfobj.
+
+Added \settension to set the grafbase variable default_tension.
+and \setfcntension to set the grafbase variable fcn_tension (this
+second one later removed).
+
+Started mfpguide.tex, a beginner's tutorial.
+
+0.68 alpha
+Added complex function sgn Z : returns (0,0) if Z = (0,0),
+otherwise unitvector Z.
+
+Added \makesector, a prefix that can make a sector out of
+a following arc.
+
+Added check to \opengraphsfile that no previous file is still open.
+
+Added option clearsymbols option and commands \clearsymbols and
+\noclearsymbols. Open symbols used with \plotsymbol can have their
+interiors cleared
+
+Added option: overlaylabels and commands \overlaylabels and
+\nooverlaylabels. Saves mplabels in a separate picture added on at
+endmfpic.
+
+Added \pairarray{<name>}{<list-of-pairs>} and
+\numericarray{<name>}{<list-of-numbers>} that define an array of pairs
+and an array of numbers.
+
+Added \mfbezier[<tens>]{<list>} to produce standard MF bezier path.
+Also \closedmfbezier.
+
+Add the equivalent of (a sequence of) LaTeX \qbezier: \qbeziers and
+\closedqbeziers.
+
+Added \ifmfpmpost so users can use it to write code that adapts to the
+figure processor.
+
+Renamed \mfp@addto to \mfpaddto and added \mfpmultiply for power
+users.
+
+0.69 alpha and 0.69a
+Make \gridlines honor the settings of \axismargin.
+
+Added \hgridlines to draw only the horizontal and \vgridlines to
+draw only the vertical.
+
+Added \gridarcs and \gridrays to draw only the arcs or rays of a
+polar grid.
+
+Added \setmfboolean and \setmfnumeric for the indicated instances of
+\setmfvariable.
+
+Added \InputIfFileExists{mfpic.cfg} in the LaTeX section just before
+\ProcessOptions. Added code to detect and input mfppatch.tex if it
+exists.
+
+Renamed manual to mfpman.tex. Provide a linked mfpman.pdf with
+TOC, and two indices.
+
+0.69c alpha
+Lowered MF memory usage of \gendashed (and therefore also for \dashed,
+\dotted and \plot). Problem reported by J. Kuben.
+
+0.69d
+\barchart can now take pair data. Interpreting (a,b) as an interval
+and creates bars that begin at a and end at b (Gantt diagrams).
+
+Added \gantt (= \barchart)
+
+0.69f
+Made [cc] the default for \tlabelrect, etc. Added command
+\tlpathjustify to change the default.
+
+Added code to input user additions, defaults, etc., in mfpic.usr, if
+it exists.
+
+0.69g
+Bug fix to \tlabelrect.
+
+0.7 beta, 14 Nov 2003
+Packed up and put on web page and CTAN.
+
+0.7a beta, 16 Apr 2004
+Change one semicolon (;) in a string written by \opengraphsfile to a
+colon (:) to work around a bug in the perl scripts mptopdf and/or
+texexec.
+
+0.71 alpha--0.8 beta, 17 May 2005
+Added
+ \arc[r], \arc[q], \circle[r], circle[q].
+ \arrow* (star form).
+ \mfpimage...\endmfimage.
+ \globalsetvariable.
+ \levelcurve.
+ \convexcurve, \convexcyclic.
+ \doubledraw, \parallelpath.
+ \tlpointsep, \tlpathsep.
+ \computedspline, \closedcomputedspline.
+ \fcnspline, \periodicfcnspline, \btwnplrfcn
+
+Changed the "\begingroup" and "\endgroup" written to output
+to "\bgroup" and "\egroup".
+
+Added \assignmfvalue, \mfpreadlog and option mfpreadlog for
+requesting and receiving values calculated by MF.
+
+Added \setmfarray and redefined \numericarray and \pairarray to
+call it. Added \colorarray.
+
+Added \mfpdraftfont, the font to use in draft when text replaces a
+figure.
+
+Added loop structures
+ \mfpfor{<header>} ... \endmfpfor
+ \mfpwhile{<condition>} ... \endmfpwhile
+ \mfploop ... \mfpuntil{<condition>} ... \endmfploop
+
+Added a \norender command.
+
+Added new.txt to contain what used to be the part of changes.txt
+that covers the changes since the last version.
+
+Renamed file refcard.tex to mfpcard.tex.
+
+Rewrote mfppatch.tex (formerly empty when there is no patch) to test
+the version info and emit a message if there is a mismatch.
+
+Sent to CTAN 13 May 2005.
+
+0.8a 17 May 2005
+Added forgotton \belowfcn plus the documentation of \btwnplrfcn.
+
+0.8b 27 Sep 2005
+Bug fixed concerning unprintable characters in filenames.
+NOT uploaded.
+
+0.89 08 May 2006
+Added: \arrowhead, \arrowtail and \arrowmid for arrows.
+
+Added: \zigzag, \sinewave and \corkscrew renderings.
+
+Added \border, a closed rectangle around the border, adjusted inward by
+the axis margin amounts.
+
+Added \randomizepath and \randomlines.
+
+Added \startbacktext ... \stopbacktext for background text.
+
+Added \arccomplement to produce the complementary arc.
+
+Gave \arc a *-form which produces the complementary arc.
+
+Added \vectorfield and \plrvectorfield.
+
+\tlabel command handles a list of points in either TeX or MP label mode.
+
+Added redefinition of \mpxshipout to correct mpost vers 0.901.
+
+Added \axisline for maximum flexibility in rendering axes.
+
+Added \globalassignmfvalue since \global\assignmfvalue didn't work.
+
+New dimension \griddotsize for size of grid dots.
+
+\circle and \arc now produce grafbase command "fallbackpath" when
+the optional letter is not a valid choice.
+
+Added \@safe@activestrue to the beginning of \mfpic and
+\@safe@activesfalse to each tlabel placed by TeX and to tcaption.
+
+Added \everymfpic and \everyendmfpic.
+
+Added \closedcurve as an alias for \cyclic, \closedconvexcurve
+for \convexcyclic and \closedpolyline for \polygon.
+
+Allow loops outside mfpic environments.
+
+Added \mfppiechart and \mfpbarchart as versions of \piechart and
+\barchart that are available outside the mfpic environment. The old
+names can still be used inside the environment.
+
+Correct centeredcaptions (broken in LaTeX).
+
+Added \pageref commands to the "List of commands by type" in
+mfpman.tex.
+
+Corrected behavior of mfpic environments with regard to \everypar.
+
+
+0.90 01 Jun 2006
+Uploaded to CTAN
+
+0.94 09 Sep 2009
+Added support for cmyk and grayscale color models that have been
+available in MetaPost since version 1.000.
+
+0.95
+Added support for filename setting: MetaPost 1.0's filenametemplate
+or 1.2's outputtemplate. Command \setfilenametemplate.
+
+0.96
+Added \mfresolution and \mfmode to set the resolution and/or mf mode
+(only for mfpic's metafont option).
+
+Added pseudohyperbolic circles, \pshcircle and pshcircle().
+
+0.97
+Changed all commands \setmf... that refer to variables in the .mf/.mp
+file (e.g., \setmfvariable \setmfarray, but not \setmfpicgraphic) to
+\set.... Added Easter egg.
+
+Store all 6 arguments of \@mfpic in macros \xfactor, \yfactor, \xmin,
+\xmax, \ymin and \ymax. Use these macros in \mfp@setconv instead of
+passing arguments. Same with \axislabels. Document them.
+
+0.98
+Added \cbeziers, \closedcbeziers and grafbase implementation cbezier and
+mkcbezier. Fixed bug in documentation of \qbeziers (no optional
+argument), and in implementation (less than ideal behavior when list is
+empty).
+
+Changed name of \assignmfvalue to \assignvalue, \globalassignmfvalue to
+\globalassignvalue. But recognize old names.
+
+Command name \setboolean is used by other packages: revert to old
+\..setmf.. commands (and for good measure revert \..assign.. to
+\..assignmf..).
+
+0.99
+Change forceclr so that if the argument is an unknown color of a
+particular model, it returns black _in that model_.
+
+Correct cmyk -> rgb conversion part of makergb to include the blackpart.
+Correct cmykgray(g) (now cmyk(0,0,0,1-g)).
+
+Add \mfpprelabel and \mfppostlabel, then remove them. When \mfpprelabel
+takes an argumemt, it doesn't work with \\ as the line breaker; it needs
+\cr.
+
+Add \brownianmotion (mfpic) and brownianpath (grafbase).
+
+Make \mfpverbtex cumulative before \opengraphsfile.
+
+1.00
+Rearranged the handling of color and color conversion. Added makegray.
+Corrected bug in rgbgray. Added rgbtogray, cmyktogray, rgbtocmyk and
+cmyktorgb. Added colorchoice.
+
+Improved the message from assignmfvalue (incorrectly invoked figure
+number if used outside a picture).
+
+Simplify non-grafbase code in dvipsname.
+
+Rewrite \mfp@useMP to check for both supp-pdf.tex and supp-pdf.mkii
+under pdfTeX (sufficiently recent pdftex.def will do this under
+pdfLaTeX). Also have it check for both epsf.tex and epsf.sty under
+non-pdf, non-LaTeX (though both files should be identical).
+
+Rename mfpman.tex/pdf to mfpic-doc.tex/pdf.
+Prepared release mfpic100.zip, placed on personal web site.
+Prepared mfpic.tds.zip for release.
+
+
+1.01
+Correct bug in vectorfield (upperbounds of xpos+raxis and ypos+taxis
+should have been xpos-raxis and ypos-taxis). To prevent recurrence,
+added definitions
+ xlow = xneg+laxis
+ xhigh = xpos-raxis
+ ylow = yneg+baxis
+ yhigh = ypos-taxis
+Replaced frequent occurence of these combinations with the
+abbreviations.
+
+Correct minor error in mfpic.dtx affecting only the documentation.
+
+1.02
+Add work-around for verbatimtex (added a commented blank line after
+user-supplied verbatimtex material).
+
+1.03
+Correct iscolor in grafbase, adding parentheses.
+
+Change detection of amstex to \ifx\amstexloaded@\relax (don't know why I
+rejected this before). This takes care of formats built on top of
+amstex.
+
+Replaced corrupted PDF files mfpguide.pdf and mfpcard.pdf.
+
+1.04
+Although \mfresolution and \mfmode were defined in mfpic.tex (and
+documented) grafbase did nothing with them. Corrected.
+
+(no change in version; documentation changes only 2010/04/07)
+Correct a wrong checksum and some typos in the dtx. Reformat the source
+files grafbase.dtx and mfpic.dtx.
+
+1.05
+Name changes in grafbase ("GB" prefixed to romannumeral, etc.) \endgroup
+moved in mfpic.
+
+1.06
+Added differential equation plotters \DEgraph and \DEtrajectory and MF
+support macros *RKIV (4-step Runge-Kutta numerical method).
+
+Removed mfppatch.tex from the distribution. Add lcheadings.ist for the
+index.
+
+1.07
+Added mfpicdef.tex for metapost labels and removed token register
+\mfp@commonverbatimtex.
+
+Added \quarterellipse, \halfellipse and \fullellipse.
+
+Use \MFPeverylabel in the metapost file instead of \everylabel in case
+someone uses a LaTeX package that includes such a macro.
+
+Added \gbrace.
+
+Changed the detection of AmS-TeX. Check that both \amstexloaded@=\relax
+and \NoBlackBoxes is defined. The former alone is too easy to occur by
+accident.
+
+Added hyperbolic geodesics. Also a half-plane version of pshdist(,).
+
+Added \browniangraph and \randomwalk.
+
+Added the Kelvin transform, kelvin(z). Also the complex function
+zsqrt(z) and complex number operations zmul and zdiv.
+
+1.08
+Added gradients: \gradient, \areagradient and \radialgradient.
+
+1.09
+Testing...
+
+1.10
+Added commands to interpolate between two paths.
+Added \reversepath=\reverse.
+
diff --git a/graphics/mfpic/doc/coil.mps b/graphics/mfpic/doc/coil.mps
new file mode 100644
index 0000000000..2fcf234530
--- /dev/null
+++ b/graphics/mfpic/doc/coil.mps
@@ -0,0 +1,139 @@
+%!PS
+%%BoundingBox: 0 0 33 7
+%%HiResBoundingBox: 0 0 32.87663 6.37607
+%%Creator: MetaPost 0.901
+%%CreationDate: 2006.05.23:1308
+%%Pages: 1
+%%BeginProlog
+%%EndProlog
+%%Page: 1 1
+ 1 0 0 setrgbcolor
+newpath 0.49814 2.98878 moveto
+0.49814 3.12091 0.44563 3.24759 0.35222 3.341 curveto
+0.2588 3.43442 0.13213 3.48692 0 3.48692 curveto
+-0.13213 3.48692 -0.2588 3.43442 -0.35222 3.341 curveto
+-0.44563 3.24759 -0.49814 3.12091 -0.49814 2.98878 curveto
+-0.49814 2.85666 -0.44563 2.72998 -0.35222 2.63657 curveto
+-0.2588 2.54315 -0.13213 2.49065 0 2.49065 curveto
+0.13213 2.49065 0.2588 2.54315 0.35222 2.63657 curveto
+0.44563 2.72998 0.49814 2.85666 0.49814 2.98878 curveto closepath fill
+newpath 3.48701 3.00691 moveto
+3.48701 3.13904 3.43451 3.26572 3.3411 3.35913 curveto
+3.24768 3.45255 3.121 3.50505 2.98888 3.50505 curveto
+2.85675 3.50505 2.73007 3.45255 2.63666 3.35913 curveto
+2.54324 3.26572 2.49074 3.13904 2.49074 3.00691 curveto
+2.49074 2.87479 2.54324 2.74811 2.63666 2.6547 curveto
+2.73007 2.56128 2.85675 2.50877 2.98888 2.50877 curveto
+3.121 2.50877 3.24768 2.56128 3.3411 2.6547 curveto
+3.43451 2.74811 3.48701 2.87479 3.48701 3.00691 curveto closepath fill
+newpath 6.47589 3.025 moveto
+6.47589 3.15712 6.42339 3.2838 6.32997 3.37721 curveto
+6.23656 3.47063 6.10988 3.52313 5.97775 3.52313 curveto
+5.84563 3.52313 5.71895 3.47063 5.62553 3.37721 curveto
+5.53212 3.2838 5.47961 3.15712 5.47961 3.025 curveto
+5.47961 2.89287 5.53212 2.76619 5.62553 2.67278 curveto
+5.71895 2.57936 5.84563 2.52686 5.97775 2.52686 curveto
+6.10988 2.52686 6.23656 2.57936 6.32997 2.67278 curveto
+6.42339 2.76619 6.47589 2.89287 6.47589 3.025 curveto closepath fill
+newpath 9.46477 3.04312 moveto
+9.46477 3.17525 9.41226 3.30193 9.31885 3.39534 curveto
+9.22543 3.48875 9.09875 3.54126 8.96663 3.54126 curveto
+8.8345 3.54126 8.70782 3.48875 8.61441 3.39534 curveto
+8.521 3.30193 8.46849 3.17525 8.46849 3.04312 curveto
+8.46849 2.911 8.521 2.78432 8.61441 2.6909 curveto
+8.70782 2.59749 8.8345 2.54498 8.96663 2.54498 curveto
+9.09875 2.54498 9.22543 2.59749 9.31885 2.6909 curveto
+9.41226 2.78432 9.46477 2.911 9.46477 3.04312 curveto closepath fill
+newpath 12.45364 3.06125 moveto
+12.45364 3.19337 12.40114 3.32005 12.30772 3.41347 curveto
+12.21431 3.50688 12.08763 3.55939 11.9555 3.55939 curveto
+11.82338 3.55939 11.6967 3.50688 11.60329 3.41347 curveto
+11.50987 3.32005 11.45737 3.19337 11.45737 3.06125 curveto
+11.45737 2.92912 11.50987 2.80244 11.60329 2.70903 curveto
+11.6967 2.61562 11.82338 2.56311 11.9555 2.56311 curveto
+12.08763 2.56311 12.21431 2.61562 12.30772 2.70903 curveto
+12.40114 2.80244 12.45364 2.92912 12.45364 3.06125 curveto closepath fill
+newpath 15.44252 3.07936 moveto
+15.44252 3.21149 15.39001 3.33817 15.2966 3.43158 curveto
+15.20319 3.525 15.0765 3.5775 14.94438 3.5775 curveto
+14.81226 3.5775 14.68558 3.525 14.59216 3.43158 curveto
+14.49875 3.33817 14.44624 3.21149 14.44624 3.07936 curveto
+14.44624 2.94724 14.49875 2.82056 14.59216 2.72714 curveto
+14.68558 2.63373 14.81226 2.58122 14.94438 2.58122 curveto
+15.0765 2.58122 15.20319 2.63373 15.2966 2.72714 curveto
+15.39001 2.82056 15.44252 2.94724 15.44252 3.07936 curveto closepath fill
+newpath 18.4309 3.09746 moveto
+18.4309 3.22958 18.37839 3.35626 18.28497 3.44968 curveto
+18.19156 3.54309 18.06488 3.5956 17.93275 3.5956 curveto
+17.80063 3.5956 17.67395 3.54309 17.58054 3.44968 curveto
+17.48712 3.35626 17.43462 3.22958 17.43462 3.09746 curveto
+17.43462 2.96533 17.48712 2.83865 17.58054 2.74524 curveto
+17.67395 2.65182 17.80063 2.59932 17.93275 2.59932 curveto
+18.06488 2.59932 18.19156 2.65182 18.28497 2.74524 curveto
+18.37839 2.83865 18.4309 2.96533 18.4309 3.09746 curveto closepath fill
+newpath 21.41977 3.11557 moveto
+21.41977 3.2477 21.36726 3.37437 21.27385 3.46779 curveto
+21.18044 3.5612 21.05376 3.61371 20.92163 3.61371 curveto
+20.7895 3.61371 20.66283 3.5612 20.56941 3.46779 curveto
+20.476 3.37437 20.4235 3.2477 20.4235 3.11557 curveto
+20.4235 2.98344 20.476 2.85677 20.56941 2.76335 curveto
+20.66283 2.66994 20.7895 2.61743 20.92163 2.61743 curveto
+21.05376 2.61743 21.18044 2.66994 21.27385 2.76335 curveto
+21.36726 2.85677 21.41977 2.98344 21.41977 3.11557 curveto closepath fill
+newpath 24.40865 3.1337 moveto
+24.40865 3.26582 24.35614 3.3925 24.26273 3.48592 curveto
+24.16931 3.57933 24.04263 3.63184 23.9105 3.63184 curveto
+23.77838 3.63184 23.6517 3.57933 23.55829 3.48592 curveto
+23.46487 3.3925 23.41237 3.26582 23.41237 3.1337 curveto
+23.41237 3.00157 23.46487 2.8749 23.55829 2.78148 curveto
+23.6517 2.68806 23.77838 2.63556 23.9105 2.63556 curveto
+24.04263 2.63556 24.16931 2.68806 24.26273 2.78148 curveto
+24.35614 2.8749 24.40865 3.00157 24.40865 3.1337 curveto closepath fill
+newpath 27.39752 3.15182 moveto
+27.39752 3.28395 27.34502 3.41063 27.2516 3.50404 curveto
+27.15819 3.59746 27.03151 3.64996 26.89938 3.64996 curveto
+26.76726 3.64996 26.64058 3.59746 26.54716 3.50404 curveto
+26.45375 3.41063 26.40125 3.28395 26.40125 3.15182 curveto
+26.40125 3.0197 26.45375 2.89302 26.54716 2.7996 curveto
+26.64058 2.70619 26.76726 2.65369 26.89938 2.65369 curveto
+27.03151 2.65369 27.15819 2.70619 27.2516 2.7996 curveto
+27.34502 2.89302 27.39752 3.0197 27.39752 3.15182 curveto closepath fill
+newpath 30.3864 3.1699 moveto
+30.3864 3.30203 30.3339 3.42871 30.24048 3.52213 curveto
+30.14706 3.61554 30.02039 3.66805 29.88826 3.66805 curveto
+29.75613 3.66805 29.62946 3.61554 29.53604 3.52213 curveto
+29.44263 3.42871 29.39012 3.30203 29.39012 3.1699 curveto
+29.39012 3.03778 29.44263 2.9111 29.53604 2.81769 curveto
+29.62946 2.72427 29.75613 2.67177 29.88826 2.67177 curveto
+30.02039 2.67177 30.14706 2.72427 30.24048 2.81769 curveto
+30.3339 2.9111 30.3864 3.03778 30.3864 3.1699 curveto closepath fill
+newpath 33.37477 3.18803 moveto
+33.37477 3.32016 33.32227 3.44684 33.22885 3.54025 curveto
+33.13544 3.63367 33.00876 3.68617 32.87663 3.68617 curveto
+32.7445 3.68617 32.61783 3.63367 32.52441 3.54025 curveto
+32.431 3.44684 32.3785 3.32016 32.3785 3.18803 curveto
+32.3785 3.05591 32.431 2.92923 32.52441 2.83582 curveto
+32.61783 2.7424 32.7445 2.6899 32.87663 2.6899 curveto
+33.00876 2.6899 33.13544 2.7424 33.22885 2.83582 curveto
+33.32227 2.92923 33.37477 3.05591 33.37477 3.18803 curveto closepath fill
+ 0 setgray 0 0.49814 dtransform truncate idtransform setlinewidth pop
+ [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit
+newpath 0 2.98878 moveto
+2.98888 3.00691 lineto
+3.0082 -0.18108 lineto
+6.81596 -0.158 7.27444 6.22098 5.21121 6.20848 curveto
+3.14795 6.19598 3.68372 -0.17706 7.49153 -0.15393 curveto
+11.29922 -0.1308 11.75749 6.24817 9.69423 6.23564 curveto
+7.63097 6.22311 8.16666 -0.14981 11.97432 -0.12674 curveto
+15.7821 -0.10367 16.24059 6.27533 14.17735 6.26283 curveto
+12.11414 6.25034 12.64987 -0.12263 16.45766 -0.09956 curveto
+20.26543 -0.07649 20.7239 6.30249 18.66068 6.29 curveto
+16.59741 6.2775 17.13318 -0.09555 20.941 -0.07242 curveto
+24.74869 -0.04929 25.20695 6.32968 23.14369 6.31715 curveto
+21.08043 6.30463 21.61612 -0.0683 25.42378 -0.04523 curveto
+29.23155 -0.02216 29.69003 6.35683 27.6268 6.34433 curveto
+25.56357 6.33183 26.09929 -0.04115 29.90707 -0.01808 curveto
+29.88776 3.1699 lineto
+32.87663 3.18803 lineto stroke
+showpage
+%%EOF
diff --git a/graphics/mfpic/doc/examples/data.dat b/graphics/mfpic/doc/examples/data.dat
new file mode 100644
index 0000000000..12222ede48
--- /dev/null
+++ b/graphics/mfpic/doc/examples/data.dat
@@ -0,0 +1,37 @@
+# File: data.dat
+# A part of mfpic 1.10 2012/12/03
+#
+# A file of data to plot a function curve
+# ("#", not "%", must be comment character when this is read.)
+
+
+#
+-10% 11.68# This is a comment
+ -9% 9.62
+ -8.5% 8.445
+ -8% 8.28
+ -7.5% 5.865 unused: random list, of, words,,,
+ -7% 5.5
+# This is not a blank line
+ -5.5% 3.445
+ -5% 1
+ -4.5% 1.965
+ -4% 2.14
+ -3.5% 2.985
+ -2.5% -1.215
+ -2% 1.52
+ -0.5% 1.545
+ 0% 0.42
+ 0.5% -0.435
+ 1% 0.96
+ 2.5% -1.235
+ 3% 0.94
+ 3.5% 0.165
+ 4% 0.28
+ 5% 1.1
+ 5.5% 3.145
+ 6% 1.94
+ 6.5% 5.505
+ 7% 3.44
+ 9.5% 8.925
+ 10% 9.84
diff --git a/graphics/mfpic/doc/examples/forfun.tex b/graphics/mfpic/doc/examples/forfun.tex
new file mode 100644
index 0000000000..76fcdbb8b7
--- /dev/null
+++ b/graphics/mfpic/doc/examples/forfun.tex
@@ -0,0 +1,160 @@
+% File: forfun.tex
+% A part of mfpic 1.10 2012/12/03
+%
+\nopagenumbers
+\input mfpic.tex
+\usemetapost
+\usetruebbox
+\opengraphsfile{fun}
+
+\mfpicunit=2bp
+
+\noindent
+\mfpic{-1.25}{118.5}{-11.25}{40}
+%
+% "meta"-ness:
+%
+\mfsrc{h:=25; % height of "m" These are graph units
+ s:=10; % width of stems
+}
+%
+% Calculate key points:
+%
+% "m"
+%
+\mfsrc{%
+ z1=(0,0);
+ y1=y2=y5=y6=y9=y10;
+ x2-x1=x6-x5=x10-x9=s;
+ x6-x1=x10-x5=h;
+ z15-z1=z3-z2=z4-z5=z7-z6=z8-z9=z11-z10=(0,h/2);
+ y12=y1+h; x12=.5[x6,x9];
+ y14=y12; x14=.5[x2,x5];
+ z13= arcppp(z7,z14,z15) intersectionpoint arcppp(z11,z12,z4);}
+%
+% "f"
+%
+\mfsrc{%
+ z21=z10; % start "f" at "m"'s end
+ z22=z21+(s,0);
+ z23=z22+(0,h-s);
+ z24=z23+(3s/4,0);
+ z25=z24+(0,s);
+ z26=z23+(0,s);
+ z27=z26+(0,s/4);
+ z28=z27+(s/4,0)+ (s/4)*dir(30);
+ z29=z28+s*dir(30);
+ x30=x21; y30=y27;}%
+%
+% "p"
+%
+\mfsrc{%
+ x31=x24;
+ y31=y21;
+ z32=z31-(0,s);
+ z33=z32+(s,0);
+ z35=(x33,h/2);
+ z39=z31+(h,h)/2; %center of round part
+ z34=(z33--z35) intersectionpoint (fullcircle scaled h shifted z39);
+ z36=z39+(h/2,0);
+ z37=z31+(0,h/2);}%
+%
+% "i"
+%
+\mfsrc{%
+ z41=(x36,y31);
+ z42=z41+(s,0);
+ z43=z42+(0,h);
+ z44=z41+(0,h);
+ x45=0.5[x41,x42]; y45=y43 + s/2 +3/50;}% Center of dot
+%
+% "c"
+%
+\mfsrc{%
+ z51=z42;
+ z52=z51+(h,h)/2; %center
+ z53=z52+(h/2)*dir(15);
+ z54=z52-(h/2,0);
+ z55=z52+(h/2)*dir(-15);
+ z56=z52+(s/4)*dir(-15);
+ z57=z52-(s/4,0);
+ z58=z52+(s/4)*dir(15);}%
+%
+\penwd{2.5*\the\mfpicunit}
+\mfsrc{%
+%
+% Calculate bounding box
+%
+% Need to account for half the thickness of pen;
+% penwd is in absolute units so we need to convert.
+% This is a displacement, so use invvconv (not invzconv):
+ begingroup
+ save border,ll,ur;
+ pair border,ll,ur; border:= invvconv((penwd,penwd))/2;
+ ll=(0,y32)-border;
+ ur=(x55,y27+5s/4)+border;}
+%
+\gfill[yellow]\rect{ll,ur} % background
+\mfsrc{endgroup;}
+%
+\fillcolor{blue}
+\drawcolor{green}
+%
+% "m"
+\mftitle{m}
+\draw\gfill\lclosed
+ \connect
+ \lines{z15,z1,z2,z3}
+ \arc[s]{z3,z4,-180}
+ \lines{z4,z5,z6,z7}
+ \arc[s]{z7,z8,-180}
+ \lines{z8,z9,z10,z11}
+ \arc[t]{z11,z12,z13}
+ \arc[t]{z13,z14,z15}
+ \endconnect
+%
+% "f"
+\mftitle{f}
+\draw\gfill\lclosed
+ \connect
+ \lines{z21,z22,z23,z24,z25,z26,z27}
+ \arc[s]{z27,z28,-150}
+ \lines{z28,z29}
+ \arc[s]{z29,z30,150}
+ \endconnect
+%
+% "p"
+\mftitle{p}
+\draw\gfill\lclosed
+ \connect
+ \lines{z31,z32,z33,z34}
+ \arc[t]{z34,z36,z37}
+ \endconnect
+\draw\gfill[yellow]\circle{z39,(h/2-s)}
+%
+% "i"
+\mftitle{i}
+\draw\gfill\polygon{z41,z42,z43,z44}
+\draw\gfill\circle{z45,s/2}
+%
+% "c"
+\mftitle{c}
+\draw\gfill\lclosed
+ \connect
+ \arc[t]{z53,z54,z55}
+ \arc[t]{z56,z57,z58}
+ \endconnect
+% uncoment to exhibit the points
+%\pointsize2bp
+%\pointfillfalse
+%\penwd{.2pt}
+%\point{z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14}
+%\point{z21,z22,z23,z24,z25,z26,z27,z28,z29,z30}
+%\point{z31,z32,z33,z34,z35,z36,z37}
+%\point{z41,z42,z43,z44,z45}
+%\point{z51,z52,z53,z54,z55,z56,z57,z58}
+% done
+\endmfpic
+
+\closegraphsfile % {fun}
+\bye
diff --git a/graphics/mfpic/doc/examples/lapictures.tex b/graphics/mfpic/doc/examples/lapictures.tex
new file mode 100644
index 0000000000..4400d8734d
--- /dev/null
+++ b/graphics/mfpic/doc/examples/lapictures.tex
@@ -0,0 +1,206 @@
+% File: lapictures.tex
+% A part of mfpic 1.10 2012/12/03
+%
+% Magnify to same scale as pictures.tex :
+% (Use of \mag is against the law of LaTeX, but Bugs Bunny set a precedent.)
+\mag=1200
+\documentclass{article}
+
+%%!!!!!!!!!!!!!!!!!!!!!!!!!!!
+% adjust these to your liking:
+\setlength{\paperheight}{11truein}
+\setlength{\paperwidth}{8.5truein}
+
+% Default plainTeX margins
+\setlength{\textwidth}{\paperwidth}
+\addtolength{\textwidth}{-2truein}
+\setlength{\textheight}{\paperheight}
+\addtolength{\textheight}{-2.1truein}
+\setlength{\headheight}{0in}
+\setlength{\headsep}{0in}
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{\oddsidemargin}
+\setlength{\footskip}{\baselineskip}
+
+% Use the metafont option if you prefer.
+\usepackage[metapost,raggedcaptions]{mfpic}
+
+\ifx\pdfoutput\UndEfInEd
+\else
+ \setlength{\pdfpageheight}{\paperheight}
+ \setlength{\pdfpagewidth}{\paperwidth}
+\fi
+
+\opengraphsfile{pics}
+
+\setlength{\mfpframesep}{0pt}
+\headshape{1}{1}{true}
+\newcommand{\vs}{\bigskip\filbreak}
+%\renewcommand\raggedright{\rightskip 0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax}
+\begin{document}
+\mftitle{Commutative Diagram example.}
+
+% A-----D
+% |\ /|
+% | C-F |
+% |/ \|
+% B.....E
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[12]{0}{10}{0}{10}
+\tlabeljustify{cc}
+\tcaption[2.0,1.0]{{\it Figure 1:} Commutative diagram example.}
+\tlabels{(1,9){A}
+ (1,1){B}
+ (3,5){C}
+ (9,9){D}
+ (9,1){E}
+ (7,5){F}}
+\setrender{\arrow\draw\trimpath{6pt}}
+\lines{(1,9), (1,1)} % A -> B.
+\lines{(1,9), (3,5)} % A -> C.
+\lines{(3,5), (1,1)} % C -> B.
+\lines{(1,9), (9,9)} % A -> D.
+\lines{(9,9), (9,1)} % D -> E.
+\lines{(9,9), (7,5)} % D -> F.
+\lines{(7,5), (9,1)} % F -> E.
+\lines{(3,5), (7,5)} % C -> F.
+% B- - ->E :
+%\dotted\arrow[r90][b-12pt]\arrow[b15pt]\reverse\arrow\lines{(1.5,1), (8.5,1)}
+\arrow\arrow[b10pt]\reverse\arrow\dotted\trimpath{6pt}\lines{(1,1), (9,1)}
+\end{mfpic}
+\end{mfpframe}
+
+\vs
+
+\mftitle{Function Plot with Cartesian Axes.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[20]{-3}{3}{-3}{3}
+\axes
+\function{-2,2,0.1}{((x**3)-x)/3}
+\tcaption{{\it Figure 2:} Function Plot with Cartesian Axes.}
+\end{mfpic}
+\end{mfpframe}
+
+\vs
+
+\mftitle{Parametric Function Plot, and Filled Circle.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[30]{-1.5}{1.5}{-1}{1}
+\parafcn{0,6,0.1}{cosd(150t)*dir(90t)}
+\gfill\circle{(0,0),0.25}
+\tcaption{{\it Figure 3:} Parametric Function Plot, and Filled Circle.}
+\end{mfpic}
+\end{mfpframe}
+
+\vs
+
+\mftitle{Bar Graph.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[20]{-0.5}{4}{-0.5}{4}
+\axes
+\shade\draw\rect{(0,0),(1,0.5)}
+\darkershade
+\shade\draw\rect{(1,0),(2,1)}
+\hatch\draw\rect{(2,0),(3,2)}
+\tcaption{{\it Figure 4:} Bar Graph.}
+\end{mfpic}
+\end{mfpframe}
+
+\vs
+
+\mftitle{Pie Chart.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[30]{-1.3}{1.7}{-1}{1.1}
+\gfill\sector{(0.3,0.2), 1, 0, 60}
+\shade\sector{(0,0), 1, 60, 105}
+\turtle{(0,0), \plr{(1, 105)}}
+\sector{(0,0), 1, 60, 360}
+\tcaption{{\it Figure 5:} Pie Chart.}
+\end{mfpic}
+\end{mfpframe}
+
+\noindent Unindented text here.
+
+\vs
+
+\mftitle{Circle with Arrow.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[20]{-2}{2}{-1}{1}
+\arrow\circle{(0,0),1}
+\tcaption{{\it Figure 6:} Circle with Arrow.}
+\end{mfpic}
+\end{mfpframe}
+
+\vs
+
+\mftitle{Use of hatch, draw, lclosed, connect, curve, point, lines,
+ dotted, reverse.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[20]{-3}{3}{-3}{3}
+\hatch\draw\lclosed\connect
+\curve{(1,0), (1,0.5), (1,1), (0,1.5)}
+\point{(0,0)}
+\endconnect
+\lines{(-1,1), (-1,-1), (1,-1.5)}
+\point{(0,0)}
+\dotted\reverse\lines{(-2,2), (-2,-2), (2,-3)}
+\tcaption{{\it Figure 7:} Use of hatch, draw, lclosed, connect,
+ curve, point, lines, dotted, reverse.}
+\end{mfpic}
+\end{mfpframe}
+
+\vs
+
+\mftitle{Simpler variant of the previous figure.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[40]{-1}{1}{-1}{1} % Was `[20]'.
+\tcaption{{\it Figure 8:} Simpler variant of the previous figure.}
+\hatch\draw\lclosed\connect
+\curve{(1,0), (0.5,0.25), (0.5,0.5), (0,0.75)}
+\point{(0,0)}
+\endconnect
+\reverse\lines{(-0.5,0.5), (-0.5,-0.5), (0.5,-0.75)}
+\tcaption{{\it Figure 8:} Simpler variant of the previous figure.}
+\end{mfpic}
+\end{mfpframe}
+
+\vs
+
+\mftitle{Graph of data from file.}
+
+\noindent
+\begin{mfpframe}
+\begin{mfpic}[6]{-10}{10}{-2}{12}
+ \makepercentother
+ \using{#1% #2 #3}{(#1,#2)}
+ \makepercentcomment
+ \mfpdatacomment\#
+ \fcncurve\datafile{data.dat}
+ \axes
+\tcaption{{\it Figure 9:} Example of a graph drawn from data in a file}
+\end{mfpic}
+\end{mfpframe}
+
+\closegraphsfile
+
+\end{document}
+
+%%%
+%%% EOF lapictures.tex
+%%%
diff --git a/graphics/mfpic/doc/examples/pictures.tex b/graphics/mfpic/doc/examples/pictures.tex
new file mode 100644
index 0000000000..44146130a5
--- /dev/null
+++ b/graphics/mfpic/doc/examples/pictures.tex
@@ -0,0 +1,204 @@
+% File: pictures.tex
+% A part of mfpic 1.10 2012/12/03
+%
+\magnification=\magstep1
+
+\newdimen\paperheight
+\newdimen\paperwidth
+%%!!!!!!!!!!!!!!!!!!!!!!!!!!!
+% adjust these to your liking:
+\paperheight 11truein
+\paperwidth 8.5truein
+
+% Default plainTeX margins
+\hsize \paperwidth
+\advance\hsize -2 truein
+\hoffset 0 truein
+%
+\vsize\paperheight
+\advance\vsize -2.1 truein
+\voffset 0 truein
+
+\input mfpic
+%% Comment this if you prefer metafont:
+\usemetapost
+\useraggedcaptions
+\ifx\pdfoutput\UndEfInEd
+\else
+ \pdfpageheight=\paperheight
+ \pdfpagewidth=\paperwidth
+\fi
+
+\opengraphsfile{pics}
+
+\mfpframesep0pt
+\headshape{1}{1}{true}
+
+\def\vs{\bigskip\filbreak}
+
+\mftitle{Commutative Diagram example.}
+
+% A-----D
+% |\ /|
+% | C-F |
+% |/ \|
+% B.....E
+
+\noindent
+\mfpframe
+\mfpic[12]{0}{10}{0}{10}
+\tlabeljustify{cc}
+\tcaption[2.0,1.0]{{\it Figure 1:} Commutative diagram example.}
+\tlabels{(1,9){A}
+ (1,1){B}
+ (3,5){C}
+ (9,9){D}
+ (9,1){E}
+ (7,5){F}}
+\setrender{\arrow\draw\trimpath{6pt}}
+\lines{(1,9), (1,1)} % A -> B.
+\lines{(1,9), (3,5)} % A -> C.
+\lines{(3,5), (1,1)} % C -> B.
+\lines{(1,9), (9,9)} % A -> D.
+\lines{(9,9), (9,1)} % D -> E.
+\lines{(9,9), (7,5)} % D -> F.
+\lines{(7,5), (9,1)} % F -> E.
+\lines{(3,5), (7,5)} % C -> F.
+% B- - ->E :
+\arrow\arrow[b10pt]\reverse\arrow\dotted\trimpath{6pt}\lines{(1,1), (9,1)}
+\endmfpic
+\endmfpframe
+
+\vs
+
+\mftitle{Function Plot with Cartesian Axes.}
+
+\noindent
+\mfpframe
+\mfpic[20]{-3}{3}{-3}{3}
+\axes
+\function{-2,2,0.1}{((x**3)-x)/3}
+\tcaption{{\it Figure 2:} Function Plot with Cartesian Axes.}
+\endmfpic
+\endmfpframe
+
+\vs
+
+\mftitle{Parametric Function Plot, and Filled Circle.}
+
+\noindent
+\mfpframe
+\mfpic[30]{-1.5}{1.5}{-1}{1}
+\parafcn{0,6,0.1}{cosd(150t)*dir(90t)}
+\gfill\circle{(0,0),0.25}
+\tcaption{{\it Figure 3:} Parametric Function Plot, and
+Filled Circle.}
+\endmfpic
+\endmfpframe
+
+\vs
+
+\mftitle{Bar Graph.}
+
+\noindent
+\mfpframe
+\mfpic[20]{-0.5}{4}{-0.5}{4}
+\axes
+\shade\draw\rect{(0,0),(1,0.5)}
+\darkershade
+\shade\draw\rect{(1,0),(2,1)}
+\hatch\draw\rect{(2,0),(3,2)}
+\tcaption{{\it Figure 4:} Bar Graph.}
+\endmfpic
+\endmfpframe
+
+\vs
+
+\mftitle{Pie Chart.}
+
+\noindent
+\mfpframe
+\mfpic[30]{-1.3}{1.7}{-1}{1.1}
+\gfill\sector{(0.3,0.2), 1, 0,60}
+\shade\sector{(0,0), 1, 60, 105}
+\turtle{(0,0), \plr{(1, 105)}}
+\sector{(0,0), 1, 60, 360}
+\tcaption{{\it Figure 5:} Pie Chart.}
+\endmfpic
+\endmfpframe
+
+\noindent Unindented text here.
+
+\vs
+
+\mftitle{Circle with Arrow.}
+
+\noindent
+\mfpframe
+\mfpic[20]{-2}{2}{-1}{1}
+\arrow\circle{(0,0),1}
+\tcaption{{\it Figure 6:} Circle with Arrow.}
+\endmfpic
+\endmfpframe
+
+\vs
+
+\mftitle{Use of hatch, draw, lclosed, connect, curve, point, lines,
+ dotted, reverse.}
+
+\noindent
+\mfpframe
+\mfpic[20]{-3}{3}{-3}{3}
+\hatch\draw\lclosed\connect
+\curve{(1,0), (1,0.5), (1,1), (0,1.5)}
+\point{(0,0)}
+\endconnect
+\lines{(-1,1), (-1,-1), (1,-1.5)}
+\point{(0,0)}
+\dotted\reverse\lines{(-2,2), (-2,-2), (2,-3)}
+\tcaption{{\it Figure 7:} Use of hatch, draw, lclosed, connect,
+ curve, point, lines, dotted, reverse.}
+\endmfpic
+\endmfpframe
+
+\vs
+
+\mftitle{Simpler variant of the previous figure.}
+
+\noindent
+\mfpframe
+\mfpic[40]{-1}{1}{-1}{1} % Was `[20]'.
+\tcaption{{\it Figure 8:} Simpler variant of the previous figure.}
+\hatch\draw\lclosed\connect
+\curve{(1,0), (0.5,0.25), (0.5,0.5), (0,0.75)}
+\point{(0,0)}
+\endconnect
+\reverse\lines{(-0.5,0.5), (-0.5,-0.5), (0.5,-0.75)}
+\tcaption{{\it Figure 8:} Simpler variant of the previous figure.}
+\endmfpic
+\endmfpframe
+
+\vs
+
+\mftitle{Graph of data from file.}
+
+\noindent
+\mfpframe
+\mfpic[6]{-10}{10}{-2}{12}
+ \makepercentother
+ \using{#1% #2 #3}{(#1,#2)}
+ \makepercentcomment
+ \mfpdatacomment\#
+ \fcncurve\datafile{data.dat}
+ \axes
+\tcaption{{\it Figure 9:} Example of a graph drawn from data in a file}
+\endmfpic
+\endmfpframe
+
+\closegraphsfile
+
+\end
+
+%%%
+%%% EOF pictures.tex
+%%%
diff --git a/graphics/mfpic/doc/install.txt b/graphics/mfpic/doc/install.txt
new file mode 100644
index 0000000000..8c8df9a5c4
--- /dev/null
+++ b/graphics/mfpic/doc/install.txt
@@ -0,0 +1,106 @@
+% File: install.txt
+% A part of mfpic 1.10 2012/12/03
+%
+
+This is version 1.10 of mfpic. See README for a list of files and a
+brief description of each.
+
+Generating and installing the files
+-----------------------------------
+
+This sections is unnecessary if you get
+ http://mirror.ctan.org/install/graphics/mfpic.tds.zip
+when it becomes available. Just unzip it in a texmf directory.
+Alternatively, you can get the entire graphics/mfpic/ directory from
+http://mirror.ctan.org/ and move those files as described below
+
+-- If you have acquired only mfpic.ins, mfpic.dtx and grafbase.dtx, put
+ the three in the same temporary directory and change to that
+ directory. Run latex (or tex) on mfpic.ins, which should produce
+ these six files:
+ mfpic.tex grafbase.mf
+ mfpic.sty grafbase.mp
+ mfpicdef.tex dvipsnam.mp
+
+-- If you have an older version of mfpic, remove any old files with the
+ same names as the above from your TeX directories, or ensure that the
+ following procedure overwrites them (back them up first, if you wish).
+
+-- Copy mfpic.tex and mfpicdef.tex where TeX and LaTeX will find them,
+ and mfpic.sty where LaTeX will find it. On any TDS compliant system
+ (such as TeXLive, MacTeX and MiKTeX) they can all be put in
+ $TEXMF/tex/generic/mfpic/ (where $TEXMF indicates a directory serving
+ as a root of a texmf tree).
+
+-- Copy grafbase.mp and dvipsnam.mp where MetaPost will find them, for
+ example $TEXMF/metapost/mfpic/ .
+
+-- Copy grafbase.mf where Metafont will find it. For example,
+ $TEXMF/metafont/mfpic/ .
+
+-- Copy mfpguide.pdf, mfpic-doc.pdf. mfpcard.pdf where documentation is
+ kept. For example, $TEXMF/doc/generic/mfpic/ . Optionally, copy the
+ *.tex versions of these, plus mfpdoc.sty, lcheadings.ist and
+ coil.mps, as well as examples/*.* either to the documentation area or
+ to the same place as mfpic.tex. Also optional: copy the two .dtx
+ files and mfpic.ins to the source area
+ ($TEXMF/source/generic/mfpic/).
+
+-- If required by your TeX system (most do): update the tex filename
+ database.
+
+There is one optional step that may be useful if you plan to make use of
+mfpic's support for Metafont (you may skip this if you only wish to use
+its MetaPost support): find the file modes.mf on your system. Typically
+this will be in $TEXMF/metafont/misc/ . Find, near the end of that file,
+a line similar to
+
+ localfont := ljfour;
+
+Replace, if necessary, the string "ljfour" by one of the modes defined
+in that file. At minimum, select one whose resolution (DPI) matches both
+your printer and the configuration of your dvi viewer. If you make such
+a change, regenerate the mf.base file (fmtutil on MacTeX or TeXLive;
+MiKTeX Options in MiKTeX). On some systems this may be named plain.base.
+
+Read mfpguide.pdf before trying anything further. If you are already
+familiar with mfpic (version 0.2.10.9 or later) you can probably get
+going right away.
+
+If you want to read the documented source code for mfpic, run pdflatex
+on mfpic.dtx and grafbase.dtx three times each. Then run makeindex for
+each:
+ makeindex -s gind.ist -o mfpic.ind mfpic.idx
+ makeindex -s gind.ist -o grafbase.ind grafbase.idx
+and then pdflatex again.
+
+------------------------------------------------------------------------
+
+If you desire to remake mfpic-doc.pdf, make sure mfpic-doc.tex and
+mfpdoc.sty are in the current directory or where LaTeX can find them.
+Make sure that coil.mps is also where LaTeX can find it. Edit, if you
+like, the paper size option in the \documentclass command in
+mfpic-doc.tex. (The document uses Times for the main font family,
+LuxiMono for a typewriter font, and CMSS for a sans serif font. Packages
+mathptmx amd luximono are required.) Then run
+ pdflatex mfpic-doc
+three times. Make sure lcheadings.ist is where makeindex can find it
+and run
+ makeindex -s lcheadings.ist -o mfpic-doc.ind mfpic-doc.idx
+Then
+ pdflatex mfpic-doc
+at least 2 more times.
+
+You could do something similar for mfpguide.tex:
+ pdflatex mfpguide
+ mpost guide.mp
+ pdflatex mfpguide
+ pdflatex mfpguide
+This relies on the mfpic package itself.
+
+\sig
+Dan Luecking (luecking at uark dot edu)
+Department of Mathematical Sciences
+University of Arkansas
+Fayetteville, Arkansas 72701-1201
+U.S.A
diff --git a/graphics/mfpic/doc/lcheadings.ist b/graphics/mfpic/doc/lcheadings.ist
new file mode 100644
index 0000000000..145317b8b1
--- /dev/null
+++ b/graphics/mfpic/doc/lcheadings.ist
@@ -0,0 +1,11 @@
+% File: lcheadings.ist
+% A part of mfpic 1.10 2012/12/03
+%
+%% Generic headings. The macros \headingprefix and \headingsuffix must
+%% be defined in the document or in a package that it uses.
+%%
+heading_prefix "\n\\headingprefix{"
+heading_suffix "}\\headingsuffix\n"
+headings_flag -1
+%% headings_flag = +/-1 turns on headings. Positive for uppercase,
+%% negative for lowercase.
diff --git a/graphics/mfpic/doc/mfpcard.pdf b/graphics/mfpic/doc/mfpcard.pdf
new file mode 100644
index 0000000000..3422bfacc1
--- /dev/null
+++ b/graphics/mfpic/doc/mfpcard.pdf
Binary files differ
diff --git a/graphics/mfpic/doc/mfpcard.tex b/graphics/mfpic/doc/mfpcard.tex
new file mode 100644
index 0000000000..6d79fc79df
--- /dev/null
+++ b/graphics/mfpic/doc/mfpcard.tex
@@ -0,0 +1,659 @@
+% File: mfpcard.tex
+% A part of mfpic 1.10 2012/12/03
+%
+% (Ask your driver to print so that longer dimension is horizontal.)
+\newdimen\paperlongside
+ \paperlongside 11 truein
+\newdimen\papershortside
+ \papershortside 8.5 truein
+
+\ifx\pdfoutput\undefined
+\else\ifx\pdfoutput\relax
+\else\ifnum\pdfoutput>0
+ \pdfpagewidth\paperlongside
+ \pdfpageheight\papershortside
+\fi\fi\fi
+
+\font\manual=cmcsc8
+\def\MF{{\manual meta}\-{\manual font}}
+\def\MP{{\manual meta}\-{\manual post}}
+\def\TeX{{\rm T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\null}}
+\def\plainTeX{{\rm plain\kern -.15em\TeX}}
+\def\LaTeX{{\rm L\raise.42ex\hbox{\kern-.36em \manual a}\kern-.15em\TeX}}
+%\def\LaTeXe{\LaTeX$2_{\textstyle\varepsilon}$}
+\def\gobble#1{}
+\def\bsl{{\tt\char\escapechar}}
+
+\def\cs#1{{\tt\char`\\#1}}
+\def\marg#1{{\tt\char`\{#1\char`\}}}
+\def\oarg#1{{\tt[#1]}}
+\def\parg#1{{\tt(#1)}}
+
+% logical markup to typeset filenames, program names, MF code,
+% grafbase identifiers, environment names, email addresses, and
+% emphasis.
+\def\file#1{{\tt #1}}
+\def\prog#1{{\sf #1}} % didn't want everything in \tt
+\def\mfc#1{{\tt #1}}
+\def\opt#1{{\tt #1}} % LaTeX2e option names
+\def\gbc#1{{\tt #1}}
+\def\env#1{{\tt #1}}
+\def\mail#1{{\tt #1}}
+\def\emph#1{{\it #1\/}}
+
+% Forced, Clean, Linebreak.
+
+\def\brk{\nobreak\hfil\break}
+
+\newcount\columnsperpage
+
+% Entries are too wide for 3 columns. Print 2 columns landscape
+\columnsperpage=2
+
+% The rest of this header is nicked from gnuplot (which took it from
+% Emacs) but was drastically adapted for mfpic.
+%
+% This file is intended to be processed by plainTeX.
+%
+% You will need to inform your dvi driver to print it in landscape
+% and, optionally, double sided.
+% Author of GNU Emacs Refcard:
+% Stephen Gildea
+% UUCP: mit-erl!gildea
+% Internet: gildea@erl.mit.edu
+%
+% Person who ripped off the formatter for gnuplot:
+% Alex Woo
+% NASA Ames Research Center
+% Internet: woo@ames.arc.nasa.gov
+%
+% Modified on 9 Dec 1992 by:
+% Daniel S. Lewart
+% University of Illinois
+% Internet: d-lewart@uiuc.edu
+%
+% Modified on 29 Sep 1999, 11 Jul 2002, 29 Sep 2003 (for mfpic) by:
+% Daniel H. Luecking
+% University of Arkansas
+% luecking@uark.edu
+
+\newdimen\intercolumnskip
+\newbox\columna
+\newbox\columnb
+
+\hsize4.75truein
+\vsize 7.25truein
+
+% Equal left right, right and middle margins, about .5in on USletter
+\intercolumnskip=\paperlongside
+\advance\intercolumnskip -2\hsize
+\intercolumnskip .33333\intercolumnskip
+\hoffset\intercolumnskip
+\advance\hoffset -1truein
+
+% Equal top and bottom margins, about .4in on A4 paper
+\voffset\papershortside
+\advance\voffset-\vsize
+\voffset .5\voffset
+\advance\voffset -1truein
+
+\topskip8truept
+
+\font\manual=cmcsc10 at 8pt
+\font\titlefont=cmbx10 scaled \magstep1
+\font\headingfont=cmbx10
+\font\smallfont=cmr6
+\font\smallsy=cmsy6
+\font\eighti=cmmi8
+\font\sixi=cmmi6
+\font\eightex=cmex10 at 8pt
+\font\eightrm=cmr8
+\font\eightbf=cmbx8
+\let\subheadingfont\eightbf
+\font\sixbf=cmbx6
+\font\eightit=cmti8
+\font\eighttt=cmtt8
+\font\eightsy=cmsy8
+\font\sixsy=cmsy6
+\font\eightsf=cmss10 at 8pt
+\font\eightsl=cmsl8
+\font\tensf=cmss10
+\textfont0=\eightrm \scriptfont0=\smallfont
+\textfont1=\eighti \scriptfont1=\sixi
+\textfont2=\eightsy \scriptfont2=\sixsy
+\textfont3=\eightex \scriptfont3=\eightex \scriptscriptfont3=\eightex
+\textfont\bffam\eightbf \scriptfont\bffam\sixbf
+\def\rm{\fam0\eightrm}
+\def\bf{\fam\bffam\eightbf}
+\def\it{\eightit}
+\def\tt{\eighttt}
+\def\sf{\eightsf}
+\def\sl{\eightsl}
+\smallskipamount 2pt plus 1pt minus 0pt
+\medskipamount 5pt plus 2pt minus 2pt
+\bigskipamount 10pt plus 3pt minus 3pt
+\normalbaselineskip=10pt
+\normalbaselines
+\rm
+\setbox\strutbox=\hbox{\vrule height6.8pt depth3.2pt width0pt}
+
+\def\abc{a}
+\output={%
+ \if b\abc \multicolumnformat \global\def\abc{a}
+ \else\if a\abc
+ \global\setbox\columna\columnbox \global\def\abc{b}
+ \global\setbox\columnb\hbox to -\intercolumnskip{}
+ \fi\fi}
+\def\multicolumnformat{\shipout\vbox{%
+ \hbox{\box\columna\hskip\intercolumnskip
+ \box\columnb\hskip\intercolumnskip\columnbox}}\advancepageno}
+\def\columnbox{\leftline{\pagebody}}
+
+\def\bye{\par\vfill\supereject
+ \if a\abc \else\null\vfill\eject\fi
+ \if a\abc \else\null\vfill\eject\fi
+ \end}
+
+% Typewriter type braces (redefinitions of escaped braces) :
+\def\{{{\tt \char`\{}}
+\def\}{{\tt\char`\}}}
+
+
+\parindent 0pt
+
+\def\title#1{{\titlefont\centerline{#1}}\vskip 1ex plus .5ex}
+
+\def\section#1{\par
+ \penalty-100
+ \vskip 2.25ex plus 2ex minus 2ex {\headingfont #1}%
+ \par \nobreak
+ \vskip 1.25ex plus 1ex minus 1.5ex}
+
+\def\subsection#1{\par
+ \ifdim\lastskip<1.5ex
+ \vskip -\lastskip
+ \vskip 1.5ex plus 1ex minus 1ex
+ \fi
+ {\subheadingfont #1}%
+ \par \nobreak
+ \vskip .75ex plus .5ex minus .5ex}
+
+\newdimen\describeindent
+\describeindent=0em
+
+\def\meta#1{$\langle\hbox{\it #1\/}\rangle$}
+\def\alt{\unskip$\;|\;$\hfilbreak}
+\def\hfilbreak{\hfil\allowbreak\hfilneg}
+
+\newdimen\secondkeyindent
+
+\def\describe#1#2{\leavevmode\vtop
+ {\hsize=\firstkeyfrac\hsize\rightskip=1em plus 1 fill\relax
+ \secondkeyindent\describeindent \advance\secondkeyindent 1em
+ \hangindent\secondkeyindent \hangafter1
+ \hskip\describeindent\relax\strut#1\nobreak\hskip0pt\strut}%
+ \vtop
+ {\hsize=\secondkeyfrac\hsize\rightskip=0pt plus 1 fill\relax
+ \leavevmode\strut#2\unskip\strut}\par}
+\def\code#1{{\sf #1}}
+
+\title{MFPIC Quick Reference}
+
+\centerline{(Copyright 2000--2012 by Daniel Luecking)}
+\medskip
+This information was prepared for version 1.10 of \prog{mfpic}.
+
+\section{Preamble commands}
+
+\def\firstkeyfrac{.4}
+\def\secondkeyfrac{.6}
+
+\describe{Load \prog{mfpic} package (\LaTeX)}
+ {\cs{usepackage}\oarg{\meta{options}}\marg{mfpic}}
+\describe{Options}{\opt{metafont} \alt \opt{metapost}, \opt{mplabels},
+ \opt{overlaylabels}, \opt{centeredcaptions},
+ \opt{raggedcaptions}, \opt{clip}, \opt{truebbox}, \opt{draft},
+ \opt{final}, \opt{nowrite}, \opt{mfpreadlog}}
+\describe{Load \prog{mfpic}; activate options (\plainTeX)}
+ {\cs{input} \file{mfpic}. \cs{usemetafont} \alt
+ \cs{usemetapost}, \cs{usemplabels}, \cs{overlaylabels}
+ \cs{usecenteredcaptions}, \cs{useraggedcaptions},
+ \cs{clipmfpic}, \cs{usetruebbox}, \cs{mfpicdraft},
+ \cs{mfpicfinal}, \cs{mfpicnowrite}, \cs{mfpreadlog}}
+\describe{Turn off some options}
+ {\cs{nomplabels}, \cs{nooverlaylabels},
+ \cs{nocenteredcaptions}, \cs{noraggedcaptions}, \cs{noclipmfpic},
+ \cs{notruebbox}}
+\describe{Set up/close the output file}
+ {\cs{opengraphsfile}\marg{\meta{base name}}$\ldots$\cs{closegraphsfile}}
+
+\section{The {\tensf mfpic} environment}
+
+\def\firstkeyfrac{.30}
+\def\secondkeyfrac{.70}
+
+\describe{Start an \prog{mfpic} figure}
+ {\cs{mfpic}\oarg{\meta{xscale}}\oarg{\meta{yscale}}%
+ \marg{\meta{$x_{\min}$}}\allowbreak\marg{\meta{$x_{max}$}}\allowbreak
+ \marg{\meta{$y_{min}$}}\allowbreak\marg{\meta{$y_{max}$}}\brk
+ \null\quad\meta{mfpic commands}\brk
+ \cs{endmfpic}}
+\describe{\quad\LaTeX{} (optional)}
+ {\cs{begin}\marg{mfpic}${}\equiv{}$\cs{mfpic},
+ \cs{end}\marg{mfpic}${}\equiv{}$\cs{endmfpic}}
+
+
+\section{Dimensions (lengths)}
+
+\def\firstkeyfrac{.58}
+\def\secondkeyfrac{.42}
+
+\describe{\sl Purpose; where used:} {\sl Name and default value:}
+\vskip1pt
+\describe{Unit of length; \cs{mfpic}} {\cs{mfpicunit}, \tt 1pt}
+\describe{Size of a symbol; \cs{point}, \cs{plot}, and \cs{plotsymbol}}
+ {\cs{pointsize}, \tt 2pt}
+\describe{Darkness of shading; \cs{shade}} {\cs{shadespace}, \tt 1pt }
+\describe{Space between dots; \cs{polkadot}}
+ {\cs{polkadotspace}, \tt 10pt}
+\describe{Space between hatch lines; hatching macros}
+ {\cs{hatchspace}, \tt 3pt}
+\describe{Size of arrowhead; \cs{arrow}} {\cs{headlen}, \tt 3pt}
+\describe{Size of x-, y-axis arrowhead; xy-axes macros}
+ {\cs{axisheadlen}, \tt 5pt}
+\describe{Size of border axis arrowhead; side axis macros}
+ {\cs{sideheadlen}, \tt 0pt}
+\describe{Size of marks on axes; axis marks} {\cs{hashlen}, \tt 4pt}
+\describe{Size of dashes; \cs{dashed}} {\cs{dashlen}, \tt 4pt}
+\describe{Space between dashes; \cs{dashed}} {\cs{dashspace}, \tt 4pt}
+\describe{Size of dots; \cs{dotted}} {\cs{dotsize}, \tt 0.5pt}
+\describe{Space between dots; \cs{dotted}} {\cs{dotspace}, 3pt}
+\describe{Space between symbols; \cs{plot}} {\cs{symbolspace}, \tt 5pt}
+
+\medskip
+The following commands are used to change the size of some dimension
+parameters:
+
+\smallskip
+\describe{{\sl Purpose} ({\sl default\/}):} {\sl Command:}
+\vskip1pt
+\describe{Set diameter of drawing pen ({\tt 0.5pt})}
+ {\cs{penwd}\marg{\meta{dimen}}}
+\describe{Set diameter of shading dots ({\tt 0.5pt})}
+ {\cs{shadewd}\marg{\meta{dimen}}}
+\describe{Set diameter of polkadot ({\tt 5pt})}
+ {\cs{polkadotwd}\marg{\meta{dimen}}}
+\describe{Set diameter of hatching pen ({\tt 0.5pt})}
+ {\cs{hatchwd}\marg{\meta{dimen}}}
+\describe{Multiply \cs{shadespace} by 1.2} {\cs{lightershade}}
+\describe{Divide \cs{shadespace} by 1.2} {\cs{darkershade}}
+
+%\vfil\eject
+\section{Colors}
+
+\def\firstkeyfrac{.45}
+\def\secondkeyfrac{.55}
+
+\smallskip
+\describe{Set color for curves} {\cs{drawcolor}\marg{\meta{color}}}
+\describe{Set color for fills} {\cs{fillcolor}\marg{\meta{color}}}
+\describe{Set color for points, symbols} {\cs{pointcolor}\marg{\meta{color}}}
+\describe{Set color for hatching} {\cs{hatchcolor}\marg{\meta{color}}}
+\describe{Set color for arrowheads} {\cs{headcolor}\marg{\meta{color}}}
+\describe{Set color for tlabels} {\cs{tlabelcolor}\marg{\meta{color}}}
+\describe{Set color used by \cs{gclear}} {\cs{backgroundcolor}\marg{\meta{color}}}
+\describe{\quad \LaTeX{} syntax}
+ {\cs{drawcolor}\oarg{\meta{model}}\marg{\meta{clrspec}}, etc.}
+\describe{Define a color name} {\cs{mfpdefinecolor}\marg{\meta{name}}\marg{\meta{model}}\marg{\meta{clrspec}}}
+
+
+\section{Common geometric figures}
+
+Drawing commands that operate on a variable length list in braces may
+be followed by \cs{datafile}\marg{\meta{filename}} instead of the list.
+
+\subsection{Points}
+
+\def\firstkeyfrac{.42}
+\def\secondkeyfrac{.58}
+
+\describe{Place a symbol at given point(s)}
+ {\cs{plotsymbol}\oarg{\meta{size}}\marg{\meta{name}}%
+ \marg{($x_0,y_0$),($x_1,y_1$),$\ldots$}}
+\describe{\quad Available symbol names} {{\tt Triangle}, {\tt Square}, {\tt Circle}, {\tt
+ Diamond}, {\tt Star}, {\tt SolidTriangle}, {\tt SolidSquare}, {\tt SolidCircle},
+ {\tt SolidDiamond}, \tt{SolidStar}, {\tt Plus}, {\tt Cross},
+ {\tt Asterisk}}
+\describe{Points (filled or unfilled circles)}
+ {\cs{point}\oarg{\meta{size}}\marg{($x_0,y_0$),($x_1,y_1$),$\ldots$}}
+\describe{Force filled/open circles in \cs{point}:}
+ {\cs{pointfilltrue}/\cs{pointfillfalse}}
+
+\subsection{Lines}
+
+\def\firstkeyfrac{.45}
+\def\secondkeyfrac{.55}
+
+\describe{Connect points with lines}
+ {\cs{polyline}\marg{($x_0,y_0$),($x_1,y_1$),$\ldots$},
+ or (\cs{lines})}
+\describe{Closed polygon}
+ {\cs{polygon}\marg{($x_0,y_0$),($x_1,y_1$),$\ldots$}}
+\describe{Concatenate vectors}
+ {\cs{turtle}\marg{\meta{initialpoint},\meta{$v_1$},\meta{$v_2$},$\ldots$}}
+\describe{Rectangle (upright) with given corners}
+ {\cs{rect}\marg{($x_0,y_0$),($x_1,y_1$)}}
+
+\subsection{Circles, arcs and ellipses}
+
+\def\firstkeyfrac{.55}
+\def\secondkeyfrac{.45}
+
+\describe{Circles} {}
+\describe{\qquad polar form (default):}
+ {\cs{circle}\oarg{p}\marg{\meta{center},\meta{radius}}}
+\describe{\qquad three-point form:}
+ {\cs{circle}\oarg{t}\marg{($x_0,y_0$),($x_1,y_1$),($x_2,y_2$)}}
+\describe{\qquad center-point form:}
+ {\cs{circle}\oarg{c}\marg{\meta{center},\meta{point}}}
+\describe{\qquad point-sweep form:}
+ {\cs{circle}\oarg{s}\marg{($x_0,y_0$),($x_1,y_1$),\meta{angle}}}
+\describe{Arcs} {}
+\describe{\qquad polar form:}
+ {\cs{arc}\oarg{p}\marg{\meta{center},\meta{$\theta_1$},\meta{$\theta_2$},%
+ \meta{radius}}}
+\describe{\qquad three-point form:}
+ {\cs{arc}\oarg{t}\marg{($x_0,y_0$),($x_1,y_1$),($x_2,y_2$)}}
+\describe{\qquad center-point-angle form:}
+ {\cs{arc}\oarg{c}\marg{\meta{center},\meta{point},\meta{angle}}}
+\describe{\qquad point-sweep form (default):}
+ {\cs{arc}\oarg{s}\marg{($x_0,y_0$),($x_1,y_1$),\meta{angle}}}
+\describe{Ellipse, center $(x_0,y_0)$, radii \meta{$r_x$}, \meta{$r_y$}, angle
+\meta{$\theta$}}
+ {\cs{ellipse}\oarg{\meta{$\theta$}}%
+ \tt\{($x_0,y_0$),\meta{$r_x$},\meta{$r_y$}\}}
+
+\section{General curves}
+
+\def\firstkeyfrac{.45}
+\def\secondkeyfrac{.55}
+
+A \meta{spec} can be {\tt p} (for polyline) or {\tt s} (for smooth)
+followed by a number for the tension.
+
+\smallskip
+\describe{Smooth curve through points}
+ {\cs{curve}\oarg{\meta{tension}}\marg{($x_0,y_0$),($x_1,y_1$),$\ldots$}}
+\describe{Graph of $y=f(x)$}
+ {\cs{function}\oarg{\meta{spec}}\marg{$x_{\min}$,$x_{\max}$,%
+ $\Delta x$}\marg{$f(\hbox{\tt x})$}}
+\describe{Graph of parametric curve $(x(t),y(t))$}
+ {\cs{parafcn}\oarg{\meta{spec}}\marg{$t_{\min}$,$t_{\max}$,$\Delta t$}%
+ \marg{($x(\hbox{\tt t})$, $y(\hbox{\tt t})$)}}
+\describe{Graph of $r = f(\theta)$}
+ {\cs{plrfcn}\oarg{\meta{spec}}%
+ \marg{$\theta_{\min}$,$\theta_{\max}$,$\Delta\theta$}\marg{$f(\hbox{\tt t})$}}
+\describe{Interpolate with a smooth {\it function}}
+ {\cs{fcncurve}\oarg{\meta{tension}}\marg{($x_0,y_0$),($x_1,y_1$),$\ldots$}}
+\describe{Curve from data in a file}
+ {\cs{datafile}\oarg{\meta{spec}}\marg{\meta{file}}}
+\describe{\quad Set how \cs{datafile} processes a line}
+ {\cs{using}\marg{\meta{read\_pattern}}\marg{\meta{write\_pattern}}\brk
+ Default is \cs{using}\marg{\#1 \#2 \#3}\marg{(\#1,\#2)}}
+
+
+\section{Regions}
+
+\def\firstkeyfrac{.45}
+\def\secondkeyfrac{.55}
+
+Curves are not necessarily `closed' even if the start and end are the
+same. The following are closed (can be filled), as are \cs{rect},
+\cs{polygon}, \cs{circle}, and \cs{ellipse}.
+
+\smallskip
+\describe{Closed curve through given points}
+ {\cs{cyclic}\oarg{\meta{tension}}\marg{$(x_1,y_1),(x_2,y_2),\ldots$}}
+\describe{Circular sector (pie slice)}
+ {\cs{sector}\marg{\meta{center},\meta{radius},\meta{$\theta_1$},%
+ \meta{$\theta_2$}}}
+\describe{Region between two functions}
+ {\cs{btwnfcn}\oarg{\meta{spec}}\marg{$x_{\min}$,%
+ $x_{\max}$,$\Delta x$}\marg{$f(\hbox{\tt x})$}\marg{$g(\hbox{\tt x})$}}
+\describe{Region in polar coordinates}
+ {\cs{plrregion}\oarg{\meta{spec}}\marg{$\theta_{\min}$,$\theta_{\max}$,%
+ $\Delta \theta$}\marg{$f(\hbox{\tt t})$}}
+\describe{Curves surrounding text}
+ {\cs{tlabelrect}\oarg{\meta{radius}}\parg{\meta{x},\meta{y}}\marg{\meta{text}}\brk
+ \cs{tlabeloval}\oarg{\meta{mult}}\parg{\meta{x},\meta{y}}\marg{\meta{text}}\brk
+ \cs{tlabelellipse}\oarg{\meta{ratio}}\parg{\meta{x},\meta{y}}\marg{\meta{text}}\brk
+ \meta{radius}: round corners. \meta{mult}: stretch horizontally.
+ \meta{ratio}: width/height of ellipse}
+
+
+\section{Prefix macros}
+
+\subsection{Drawing curves}
+
+\def\firstkeyfrac{.4}
+\def\secondkeyfrac{.6}
+
+\describe{Dashed path}{\cs{dashed}\oarg{\meta{length},\meta{gap}}$\ldots$}
+\describe{Dotted path}{\cs{dotted}\oarg{\meta{size},\meta{gap}}$\ldots$}
+\describe{Trace a path with symbols}
+ {\cs{plot}\oarg{\meta{size},\meta{gap}}\marg{\meta{symbol}}$\ldots$}
+\describe{Generalized dashes}{\cs{gendashed}\marg{\meta{patname}}$\ldots$}
+\describe{\quad Define a named dash pattern}
+ {\cs{dashpattern}\marg{\meta{patname}}\marg{\meta{len$_1$},\meta{len$_2$},$\ldots$,%
+ \meta{len$_{2n}$}}}
+\describe{Place a symbol at all nodes}
+ {\cs{plotnodes}\oarg{\meta{size}}\marg{\meta{symbol}}$\ldots$}
+\describe{Solid curve}{\cs{draw}\oarg{\meta{color}}$\ldots$}
+
+
+\subsection{Closing a curve}
+
+\def\firstkeyfrac{.45}
+\def\secondkeyfrac{.55}
+
+These turn any path into a `closed' path (result can then be filled).
+
+\smallskip
+\describe{Close with a straight line,}{\cs{lclosed}$\ldots$}
+\describe{Close with a smooth join, like \cs{cycle},}{\cs{sclosed}$\ldots$}
+\describe{Close letting \MF{} choose}{\cs{bclosed}$\ldots$}
+
+\subsection{Filling closed curves}
+
+\def\firstkeyfrac{.4}
+\def\secondkeyfrac{.6}
+
+These filling prefixes turn off automatic drawing of the curve.
+
+\smallskip
+\describe{Solid fill} {\cs{gfill}\oarg{\meta{color}}$\ldots$}
+\describe{Unfill} {\cs{gclear}$\ldots$}
+\describe{Hatched fills}
+ {\cs{thatch}\oarg{\meta{space},\meta{angle}}\oarg{\meta{color}}$\ldots$}
+\describe{\qquad \meta{angle}${}=45\,$deg}
+ {\cs{rhatch}\oarg{\meta{space}}\oarg{\meta{color}}$\ldots$}
+\describe{\qquad \meta{angle}${}=-45\,$deg}
+ {\cs{lhatch}\oarg{\meta{space}}\oarg{\meta{color}}$\ldots$}
+\describe{\qquad crosshatching}
+ {\cs{xhatch}\oarg{\meta{space}}\oarg{\meta{color}}$\ldots$}
+\describe{} {\cs{hatch} $=$ \cs{xhatch}}
+\describe{Shading}
+ {\cs{shade}\oarg{\meta{space}}$\ldots$}
+\describe{Gradients$^{\dag}$}
+ {\cs{gradient}\marg{\meta{clr},\meta{width},\meta{angle}}$\ldots$}
+\describe{}
+ {\cs{areagradient}\marg{\meta{clr},\meta{h-wd},\meta{v-wd}}$\ldots$}
+\describe{}
+ {\cs{radialgradient}\marg{\meta{clr},\meta{wd},\meta{center}}$\ldots$}
+\describe{Polkadot fill}{\cs{polkadot}\oarg{\meta{space}}$\ldots$}
+\describe{Fill with copies of a tile} {\cs{tess}\marg{\meta{tile}}$\ldots$}
+\describe{\quad Define a tile*}
+ {\cs{tile}\marg{\meta{name},\meta{unit},\meta{width},\meta{height},\meta{clip}}
+ \meta{drawing commands} \cs{endtile}}
+
+\smallskip
+$^{\dag}$ \meta{clr} is a function that returns a color for parameter(s)
+in $(0,1)$.\brk
+* Creates a mini-mfpic, clipped if \meta{clip}${}={}${\tt true}.
+
+\subsection{Storing and reusing a path}
+
+\describe{Store a path} {\cs{store}\marg{\meta{name}}$\ldots$}
+\nobreak
+\describe{\quad reusing a stored path} {\cs{mfobj}\marg{\meta{name}}}
+
+\subsection{Subpaths}
+
+\describe{Subpath by fractions of length}
+ {\cs{partpath}\marg{\meta{frac1},\meta{frac2}}$\ldots$}
+\describe{Subpath by node numbers} {\cs{subpath}\marg{\meta{m},\meta{n}}$\ldots$}
+\describe{Cutting by another path}
+ {\cs{cutoffafter}\marg{\meta{obj}}$\ldots$,
+ \cs{cutoffbefore}\marg{\meta{obj}}$\ldots$.\brk
+ \meta{obj} is a name created with \cs{store}}
+\describe{Trim the ends of a path}
+ {\cs{trimpath}\marg{\meta{dim1},\meta{dim2}}$\ldots$}
+
+
+\subsection{Modifying a curve}
+
+\def\firstkeyfrac{.4}
+\def\secondkeyfrac{.6}
+
+\describe{Add arrowhead to the end}
+ {\cs{arrow}\oarg{l\meta{length}}\oarg{r\meta{angle}}%
+ \oarg{b\meta{backset}}\oarg{c\meta{color}}$\ldots$}
+\describe{\quad Define arrowhead shape}
+ {\cs{headshape}\marg{\meta{ratio}}\marg{\meta{tension}}\marg{\meta{filled}}}
+\describe{Reverse a curve} {\cs{reverse}$\ldots$}
+\describe{Double arrow} {\cs{arrow}\cs{reverse}\cs{arrow}$\ldots$}
+\describe{Rotate around a point} {\cs{rotatepath}\marg{($x_0$,$y_0$),\meta{angle}}$\ldots$}
+\describe{Reflect about a line} {\cs{reflectpath}\marg{($x_0$,$y_0$),($x_1$,$y_1$)}$\ldots$}
+\describe{Shift} {\cs{shiftpath}\marg{($dx$,$dy$)}$\ldots$}
+\describe{Scale around a point} {\cs{scalepath}\marg{($x_0$,$y_0$),\meta{scale}}$\ldots$}
+\describe{xscale about line $x=x_0$} {\cs{xscalepath}\marg{$x_0$,\meta{scale}}$\ldots$}
+\describe{yscale about line $y=y_0$} {\cs{yscalepath}\marg{$y_0$,\meta{scale}}$\ldots$}
+\describe{slant, pivoting on line $y=y_0$} {\cs{slantpath}\marg{$y_0$,\meta{slant}}$\ldots$}
+\describe{yslant, pivoting on line $x=x_0$} {\cs{yslantpath}\marg{$x_0$,\meta{slant}}$\ldots$}
+\describe{Swap x and y} {\cs{xyswappath}$\ldots$}
+
+
+\section{Axes}
+
+\def\firstkeyfrac{.30}
+\def\secondkeyfrac{.70}
+
+\describe{Draw x- and/or y-axes} {\cs{axes}\oarg{\meta{headlen}},
+ \cs{xaxis}\oarg{\meta{headlen}}, \cs{yaxis}\oarg{\meta{headlen}}}
+\describe{Draw various axes}
+ {\cs{axis}\oarg{\meta{headlen}}\marg{\meta{axis}}, \ \meta{axis} is one of
+ {\tt x}, {\tt y}, {\tt l}, {\tt b}, {\tt r}, or {\tt t}.}
+\describe{Draw many axes} {\cs{doaxes}\oarg{\meta{headlen}}\marg{\meta{list}}, \
+ \meta{list} of letters, no commas.}
+\describe{Shift border axis inward}
+ {\cs{axismargin}\marg{\meta{axis}}\marg{\meta{amt}}, \ \meta{amt} is
+ in graph units.}
+\describe{Add hashmarks to axes}{%
+ \cs{axismarks}\marg{\meta{axis}}\oarg{\meta{len}}\marg{$c_1$,$c_2$,$\ldots$}, \
+ $c_j$ are positions.\brk Abbrev. by
+ \cs{xmarks} for \cs{axismarks}\marg{x}, etc.}
+\describe{Change position of hash marks}
+ {\cs{setaxismarks}\marg{\meta{axis}}\marg{\meta{pos}} \ \meta{pos} is one of
+ {\tt inside}, {\tt outside}, {\tt centered}, {\tt ontop},
+ {\tt onbottom}, {\tt onleft}, or {\tt onright}.}
+
+\section{Miscellaneous}
+
+\def\firstkeyfrac{.30}
+\def\secondkeyfrac{.70}
+
+\describe{Text labels}
+ {\cs{tlabel}\oarg{\meta{pos}\meta{$\theta$}}%
+ \parg{\meta{x},\meta{y}}\marg{\meta{\TeX{} text}}\brk
+ \cs{tlabels}\marg{\meta{args$_1$}\meta{args$_2$}$\ldots$}\brk
+ \cs{axislabels}\marg{\meta{axis}}\oarg{\meta{pos}\meta{$\theta$}}%
+ \marg{\marg{\meta{txt$_1$}}\meta{$n_1$},%
+ \marg{\meta{txt$_2$}}\meta{$n_2$},$\ldots$}\brk
+ \meta{pos} is a two-letter sequence, \meta{$\theta$} the
+ angle* of rotation in degrees;
+ \meta{args$_j$} is an entire set of arguments as in \cs{tlabel};
+ \meta{axis} is a letter, \meta{txt$_j$} is label, \meta{$n_j$}
+ is coordinate on axis}
+\describe{Clipping to a path} {\cs{gclip}$\ldots$}
+\describe{Polar conversion}
+ {\cs{plr}\marg{($r_0$,$\theta_0$),($r_1$,$\theta_1$),$\ldots$}}
+\describe{Connect paths} {\cs{connect} \meta{path1} \meta{path2} $\ldots$
+ \cs{endconnect}}
+\describe{Draw many curves from one datafile}
+ {\cs{plotdata}\oarg{\meta{spec}}\marg{\meta{file}}, \ \meta{spec} is {\tt
+ p} or {\tt s\meta{num}} where \meta{num} is the (optional) tension
+ in the smooth curve}
+\describe{Set how \cs{plotdata} draws curves$^{\dag}$}{\cs{dashedlines}
+ \ (different dash patterns)\brk
+ \cs{coloredlines} \ (different colors, \MP{} only)\brk
+ \cs{pointedlines} \ (different symbols, like \cs{plot})\brk
+ \cs{datapointsonly} \ (different symbols, like \cs{plotnodes})}
+
+\smallskip
+* The angle is optional, and ignored unless option \opt{mplabels} is
+in effect.\brk
+$^{\dag}$ \cs{plotdata} also respects the \cs{using} setting (see
+\cs{datafile} in section {\bf General curves}).
+
+\bye
+
+% Other commands:
+\cs{setrender}[\<\TeX{} commands\>]
+
+\cs{coords}$\ldots$\cs{endcoords}
+\cs{applyT}[\<transformer\>]
+\cs{rotate}[$\theta$]
+\cs{rotatearound}[$p$][$\theta$]
+\cs{turn}[?$p$][$\theta$]
+\cs{mirror}[$p_1$][$p_2$]
+\cs{reflectabout}[$p_1$][$p_2$]
+\cs{shift}[$p$]
+\cs{scale}[$s$]
+\cs{xscale}[$s$]
+\cs{yscale}[$s$]
+\cs{zscale}[$p$]
+\cs{xslant}[$s$]
+\cs{yslant}[$s$]
+\cs{zslant}[$s$]
+\cs{boost}[$\chi$]
+\cs{xyswap}
+
+\cs{fdef}[\<fcn\>]%
+ (\<param1\>,\<param2\>,$\ldots$)%
+ [\<mf-expr\>]
+
+\cs{tcaption}[?\<maxwd\>,\<linewd\>][\<caption text\>]
+
+\cs{savepic}\bsl\<picname\>
+\cs{newsavepic}
+\cs{usepic}
+
+\cs{dashlineset}, \cs{dotlineset}
+
+\cs{mfsrc}[\<metafont code\>]
+\cs{noship}
+
+\cs{store}[\<path variable\>][\<path\>]
+\cs{mfobj}[\<path expression\>]
+\cs{patharr}[\<pv\>]$\ldots$\cs{endpatharr}
+
+\cs{mftitle}[\<title\>]
+\cs{tmtitle}[\<title\>]
+
+\cs{newfdim}[\<fdim\>]
+
+\cs{setmfpicgraphic}
+\cs{getmfpicoffset}
+\cs{setfilename}
+
+\bye
diff --git a/graphics/mfpic/doc/mfpdoc.sty b/graphics/mfpic/doc/mfpdoc.sty
new file mode 100644
index 0000000000..405a80fe07
--- /dev/null
+++ b/graphics/mfpic/doc/mfpdoc.sty
@@ -0,0 +1,294 @@
+% File: mfpdoc.sty
+% A part of mfpic 1.10 2012/12/03
+%
+\ProvidesPackage{mfpdoc}[2012/12/03 v1.10 macros for mfpic documentation]
+\newcommand\mfpversion{1.10}
+\newcommand\mfpicversion{110}
+\newcommand\mfpfiledate {2012/12/03}
+\newif\if@chapters
+\@chaptersfalse
+\DeclareOption{chapters}{\@chapterstrue}
+
+\newif\if@stupidlogos
+\@stupidlogostrue
+\DeclareOption{nologos}{\@stupidlogosfalse}
+\ProcessOptions
+
+\IfFileExists{ifpdf.sty}{\RequirePackage{ifpdf}}
+ {\csname newif\expandafter\endcsname\csname ifpdf\endcsname \pdffalse
+ \ifx\pdfoutput\undefined
+ \else\ifx\pdfoutput\relax
+ \else\ifnum0=\pdfoutput
+ \else
+ \pdftrue
+ \fi\fi\fi}
+
+
+%% Text size:
+
+\textwidth 5.5in
+\textheight 8.0in
+\oddsidemargin 0.5in
+\evensidemargin\oddsidemargin
+\topmargin 0.5in
+ \advance\topmargin-\headheight
+ \advance\topmargin-\headsep
+
+\ifpdf
+% These two are now defaults in TeX Live:
+% \pdfminorversion 5
+% \pdfobjcompresslevel 2
+ \pdfpageheight\paperheight
+ \pdfpagewidth\paperwidth
+ \def\mfpHyOpts{%
+ pdftex,colorlinks,pdfpagemode=UseNone,%
+ pdfstartview={XYZ null null null},%
+ plainpages=false,hypertexnames=true}
+ \def\mfpHyDisable{%
+ \let\opt\@firstofone\let\prog\@firstofone}
+\else % dvi output could be for dvipdfm or dvips
+ \ifx\mfpdvipdfm\UndEfInEd
+ \special{papersize=\the\paperwidth,\the\paperheight}
+ \else
+ \special{pdf: pagesize width \the\paperwidth\space height \the\paperheight}
+ \fi
+\fi
+\renewcommand\section{\@startsection{section}{1}{\z@}%
+ {-2.4ex \@plus -.5ex \@minus -.1ex}%
+ {1.0ex \@plus.1ex}%
+ {\normalfont\large\bfseries}}
+\renewcommand\subsection{\@startsection{subsection}{2}{\z@}%
+ {-1.8ex\@plus -.4ex \@minus -.1ex}%
+ {.75ex \@plus .1ex}%
+ {\normalfont\bfseries}}
+\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%
+ {-1.5ex\@plus -.3ex \@minus -.1ex}%
+ {.5ex \@plus .1ex}%
+ {\normalfont\scshape\raggedright}}
+\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
+ {-1ex\@plus -.2ex \@minus -.1ex}%
+ {.4ex \@plus .1ex}%
+ {\normalfont\itshape\raggedright}}
+%
+% To allow \chapter command in article class, load this package with
+% [chapters] option
+\if@chapters
+ \let\chapter\section
+ \let\section\subsection
+ \let\subsection\subsubsection
+ \let\subsubsection\paragraph
+\fi
+
+\def\mfpicversiontext{\prog{Mfpic} version: \mfpversion.}
+
+\def\@maketitle{%
+ \newpage\vspace*{-2\baselineskip}
+ \ifx\mfpicversiontext\relax
+ \else
+ {\let\p@footnote\relax\let\@thempfn\relax
+ \footnotetext{\mfpicversiontext}}%
+ \fi
+ {\centering%
+ {\Large \@title \par}%
+ \vskip 1em%
+ {\large \lineskip .5em%
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par}%
+ \vskip .7em%
+ {\normalsize \@date}%
+ \par
+ }%
+ \vskip 1em\relax}
+
+\def\@listi{\leftmargin\leftmargini
+ \parsep \z@ \@plus\p@ \@minus\z@
+ \topsep 1ex \@plus.2ex \@minus 1ex
+ \itemsep\parsep}
+\let\@listI\@listi \@listi
+\renewcommand\labelitemi{\normalfont\bfseries \textendash}
+\renewcommand\labelitemii{\textasteriskcentered}
+\renewcommand\labelitemiii{\textperiodcentered}
+\leftmargini 1.5\parindent
+
+% Index stuff
+\def\mfpindexheading{}
+\def\mfpindexpagemarks{}
+
+% If lcheadings.ist or ucheadings.ist is used we need these:
+\def\headingprefix#1{\textbf{#1}}
+\def\headingsuffix{\par\nobreak\smallskip}
+
+\renewenvironment{theindex}
+ {%
+ \@restonecoltrue
+ \columnseprule \z@
+ \columnsep 35\p@
+ \twocolumn[\mfpindexheading%
+ \vspace{1ex}]%
+ \mfpindexpagemarks
+ \parindent\z@
+ \parskip\z@ \@plus .3\p@\relax
+ \let\item\@idxitem
+ }
+ {\clearpage}
+
+
+%% Because \pageref doesn't link to the actual page:
+\newcommand\pagelabel{\ifpdf \phantomsection \fi\label}
+
+%% Displays %%%%%%%%%%%
+%% command descriptions (cd):
+\newenvironment{cd}
+ {\par\addvspace{1.75ex plus .3ex minus .1ex}
+ \parindent0pt
+ \vbox\bgroup\hsize\textwidth
+ \def\ {\leavevmode\null\quad}% small space at beginning of line
+ }
+ {\unskip\strut\egroup\@ignoretrue
+ \aftergroup\@afterindenttrue\aftergroup\@afterheading
+ \nobreak\vskip.75ex plus .3ex minus .1ex}
+
+%% examples (ex):
+\newenvironment{ex}
+ {\par\addvspace{1ex plus.2ex minus.1ex}%
+ \parindent0pt
+ \vbox\bgroup\hsize\textwidth
+ \leftskip\leftmargini
+ \def\ {\leavevmode\null\quad}}
+ {\unskip \strut \egroup \vskip 1ex plus.2ex minus.1ex
+ \@ignoretrue\@endpetrue}
+
+%% verbatim:
+\RequirePackage{verbatim}
+\def\verbatim@processline{\hspace{\leftmargini}\the\verbatim@line\par}
+\addto@hook\every@verbatim{\predisplaypenalty\@M}
+
+%% displayed text:
+\newenvironment{display}{\list{}{}\item[]}{\endlist}
+%% end displays %%%%%%%
+
+%% Logos %%%%%%%%%%%%%%
+\if@stupidlogos
+ \def\TeX{T\kern-.1667em\lower.4ex\hbox{E}\kern-.125emX}
+ \def\pdfTeX{pdf\kern.04em\TeX}
+ \def\pdfLaTeX{pdf\kern.06em\LaTeX}
+ \def\ConTeXt{Con\kern-.16em \TeX \kern-0.06em t}
+ \def\eTeX{e\kern-.10em \TeX}
+ \def\LMcal{\fontencoding{OMS}\fontfamily{lmsy}\selectfont}
+ \def\CMcal{\fontencoding{OMS}\fontfamily{cmsy}\selectfont}
+%
+% Use CM mathcal for AMS logo
+% \def\AmSTeX{{\CMcal A\kern-.1667em\lower.5ex\hbox{M}\kern-.125em S}-\TeX}
+%
+% Use whatever is default for \mathcal:
+% \def\AmSTeX{%
+% $\mathcal{A}\kern-.1667em
+% \lower.5ex
+% \hbox{$\mathcal{M}$}\kern-.125em
+% \mathcal{S}$-\TeX}
+%
+% Use LM mathcal for AMS logo
+ \def\AmSTeX{{\LMcal A\kern-.1667em\lower.5ex\hbox{M}\kern-.125em S}-\TeX}
+ \def\PiCTeX{P\kern-.06em\lower.4ex\hbox{I}\kern-.075emC\kern-.06em\TeX}
+\else
+ \def\TeX {\textsc{TeX}}
+ \def\LaTeX {\textsc{LaTeX}}
+ \def\pdfTeX {\textsc{pdfTeX}}
+ \def\pdfLaTeX{\textsc{pdfLaTeX}}
+ \def\ConTeXt {\textsc{ConTeXt}}
+ \def\eTeX {\textsc{eTeX}}
+ \def\AmSTeX {\textsc{$AMS$-TeX}}
+ \def\PiCTeX {\textsc{PiCTeX}}
+\fi
+%% end Logos %%%%%%%%%%
+
+\hyphenation{meta-font meta-post Post-Script Ghost-script}
+
+%% Special words %%%%%%%%%%
+\def\MF{\prog{metafont}}
+\def\CMF{\prog{Metafont}}
+\def\MP{\prog{metapost}}
+\def\CMP{\prog{Metapost}}
+\def\PS{\prog{PostScript}}
+\def\GS{\prog{Ghostscript}}
+\def\EPS{\prog{EPS}\null}
+\def\mfp{\prog{mfpic}}
+\def\Mfp{\prog{Mfpic}}
+\def\grafbase{\prog{grafbase}}
+\def\Grafbase{\prog{Grafbase}}
+
+%% font commands
+\def\mytt#1{\relax
+ \ifmmode
+ \mathtt{#1}%
+ \else
+ {\upshape\ttfamily#1}%
+ \fi
+}
+\def\mfc{% % Metafont/Post code
+ \begingroup
+ \ttfamily\catcode`\_=12 \grabit
+}
+\def\grabit#1{#1\endgroup}
+% like \mfc, but no line breaks
+\def\codebox{%
+ \hbox\bgroup
+ \ttfamily\catcode`\_=12 \boxgrabit
+}
+\def\boxgrabit#1{#1\egroup}
+\def\_{\mytt{\char`\_}}
+\def\prog#1{{\mdseries\scshape#1}} % programs, packages
+\let\file\mytt % filenames
+\def\opt#1{{\upshape\sffamily#1}} % package options
+\let\gbc \mfc % grafbase code
+\let\env \file % LaTeX environment names
+\let\email\file % email addresses
+\let\mail \file % (ditto)
+\let\dim \file % TeX and Metafont dimensions
+\let\kw \opt % MF key word like numeric
+
+%% TeX code %%%%%%%%%%%%%%%
+{
+\escapechar`\\
+\xdef\otherbsbs{\string\\}
+\escapechar-1
+\xdef\otherbackslash{\string\\}
+}
+\DeclareRobustCommand\cs[1]{%
+ \texorpdfstring{\leavevmode\mytt{\otherbackslash#1}}{\textbackslash#1}}
+\def\bbsl{\mytt{\otherbsbs}}% prints "\\"
+\DeclareRobustCommand\meta[1]{%
+ \ensuremath{\langle\mbox{\rmfamily\itshape#1\/}\rangle}}
+\providecommand\marg[1]{\mytt{\char`\{#1\char`\}}}
+\providecommand\oarg[1]{\mytt{[#1]}}
+\providecommand\parg[1]{\mytt{(#1)}}
+
+%% page style %%%%%%%%%%%%%%%
+\def\ps@mfpdoc{%
+ \let\@oddfoot\@empty\let\@evenfoot\@empty
+ \def\@oddhead{\small{\scshape\rightmark}\hfil\thepage}%
+ \let\@evenhead\@oddhead
+ \let\@mkboth\markboth
+ \def\sectionmark##1{\thispagestyle{plain}}
+ \def\subsectionmark##1{%
+ \markright {\thesubsection\enspace##1}}%
+ \def\subsubsectionmark##1{}}
+
+\if@chapters
+\renewcommand\tableofcontents{\pagenumbering{roman}%
+ \chapter*{\contentsname
+ \@mkboth{\scshape\contentsname}{\scshape\contentsname}}%
+ \@starttoc{toc}\clearpage\pagenumbering{arabic}}
+\fi
+
+%% figures:
+\@fptop=-\@fpsep
+\@addtoreset{figure}{section}
+
+%% misc:
+\def\tallstrut{\vbox to 10pt{}}
+\def\deepstrut{\vtop to 5pt{}}
+
+\frenchspacing
+\endinput
diff --git a/graphics/mfpic/doc/mfpguide.pdf b/graphics/mfpic/doc/mfpguide.pdf
new file mode 100644
index 0000000000..65f2568ddc
--- /dev/null
+++ b/graphics/mfpic/doc/mfpguide.pdf
Binary files differ
diff --git a/graphics/mfpic/doc/mfpguide.tex b/graphics/mfpic/doc/mfpguide.tex
new file mode 100644
index 0000000000..01cba68471
--- /dev/null
+++ b/graphics/mfpic/doc/mfpguide.tex
@@ -0,0 +1,1640 @@
+% File: mfpguide.tex
+% A part of mfpic 1.10 2012/12/03
+%
+% Tutorial on mfpic
+\documentclass[letterpaper]{article}
+
+\usepackage[chapters]{mfpdoc}
+
+\renewcommand{\thefigure}{\thesection.\arabic{figure}}
+
+\newenvironment{mfpfig}[1]
+{\figure[htb] \centering \refstepcounter{figure} \label{#1}}
+{\par\medskip Figure \thefigure. \endfigure}
+
+\ifpdf
+ \usepackage[pdftex,final]{graphics}
+\else
+ \usepackage[dvips,final]{graphics}
+\fi
+
+\usepackage[metapost]{mfpic}
+\opengraphsfile{guide}
+
+\dotsize1pt
+
+\ifpdf
+\expandafter\usepackage\expandafter
+ [\mfpHyOpts,plainpages=false,naturalnames=true]{hyperref}
+\expandafter\pdfstringdefDisableCommands\expandafter
+ {\mfpHyDisable}
+
+\fi
+
+\def\theHfigure{\thefigure}
+
+\begin{document}
+
+\title{\Mfp: A Short Introduction}
+\author{Daniel H. Luecking\thanks{luecking at uark dot edu}}
+\date{\mfpfiledate}
+
+\maketitle
+\tableofcontents
+
+\chapter{Introduction}\label{sec:intro}
+
+As this document aims only to instruct the reader in the building of
+figures with \mfp{}, we will not be too concerned with the intricacies
+of running programs in various operating systems and \TeX{}
+distributions. What will be described here is the simplest case: a
+command-line system in which commands are typed at a keyboard. To
+simplify things further, we will assume that \mfp{} is used with the
+\opt{metapost} option, in a \LaTeX{} document, with \pdfLaTeX{} as the
+compiler. An appendix will discuss some of the differences when these
+assumptions are not satisfied.
+
+We will start right out with the ``Hello, world'' of \mfp{}. Construct a
+\LaTeX{} document by typing the following in a text editor and saving it
+as \file{first.tex}.
+\begin{verbatim}
+% first.tex
+\documentclass{article}
+ \usepackage[metapost]{mfpic}
+ \opengraphsfile{myfigs}
+\begin{document}
+ My first figure:
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \ellipse{(0,0),1,.5}
+ \end{mfpic}
+ \closegraphsfile
+\end{document}
+\end{verbatim}
+Run the command
+\begin{ex}
+ \texttt{pdflatex first}
+\end{ex}
+which should create several files, the two most important being
+\file{first.pdf} and \file{myfigs.mp}. You can go ahead and open
+\file{first.pdf}. You should see a 2 inch by 2 inch square with
+something similar to `\texttt{\#1}' in the lower left corner. This shows
+where the picture will be when it has been created.
+
+Now run the command
+\begin{ex}
+ \texttt{mpost myfigs}
+\end{ex}
+which should create the file \file{myfigs.1}. This is an EPS file
+(Encapsulated PostScript) and can be opened in GhostScript or GSview or
+similar Postscript viewing program to see an ellipse.
+
+If you are viewing \file{first.pdf} in Acrobat Reader or Adobe Reader,
+you will need to close it. Now repeat the \pdfLaTeX{} step:
+\begin{ex}
+ \texttt{pdflatex first}
+\end{ex}
+and then view the file \file{first.pdf}. You should see something very
+close to figure~\ref{fig1}.
+\begin{mfpfig}{fig1}
+ My first figure:
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \ellipse{(0,0),1,.5}
+ \end{mfpic}
+\end{mfpfig}
+
+What can go wrong? According to Murphy's Law: anything. If \mfp{} is not
+properly installed, one could obtain messages of files not found. If
+that happens, determine (from your \TeX{} system's documentation) where
+\TeX{} input files should go and make sure that \file{mfpic.sty},
+\file{mfpic.tex} and \file{mfpicdef.tex} reside there. Similarly, find
+out where \MP{} inputs should go and make sure that \file{grafbase.mp}
+and \file{dvipsnam.mp} reside there. Then run whatever command your
+\TeX{} system might require to ``update the filename database''. You may
+safely ignore the message from \mfp{} itself that \file{myfigs.1} is not
+found (on the first run of \pdfLaTeX). This file should be created only
+after running \texttt{mpost}.
+
+If you get an error message from \LaTeX{}, carefully check your typing.
+Also check whether an older version of \mfp{} might have been used
+instead of the current version. If you get an error message from \MP{}
+do the same, especially checking the typing within the \env{mfpic}
+environment. If you get a message from \MP{} that ``Grafbase'' believes
+your \mfp{} installation may be broken, check the log files
+(\file{first.log} and \file{myfigs.log}) to find out the locations of
+these input files:
+\begin{ex}
+ \file{mfpic.tex} and \file{grafbase.mp}
+\end{ex}
+and make sure that both these files are from the most recently installed
+\mfp{} package. If you are only evaluating \mfp{} without committing to
+installing it, just make sure all the files mentioned in the previous
+paragraphs are in the current directory.
+
+If \pdfLaTeX{} complains it can't write on the file \file{first.pdf},
+unload \file{first.pdf} from your pdf viewer and try again.
+
+If the figures look a little choppy in Acrobat Reader, turn on ``smooth
+line art'' in the edit preferences dialogue.
+
+I will assume that eventually all went well and you are now able to
+obtain the ellipse of figure~\ref{fig1}. Each time you change an
+\env{mfpic} environment or the options to the package, you potentially
+change the file \file{myfigs.mp} produced and you should repeat the
+sequence:
+\begin{verbatim}
+pdflatex first
+mpost myfigs
+pdflatex first
+\end{verbatim}
+to be sure of seeing the changes.
+
+One thing you might notice about figure~\ref{fig1} is that the ellipse
+is positioned quite a bit above the base line of the text. This is
+because \mfp{} reserves the amount of space specified in the arguments
+of the \env{mfpic} environment. These arguments were
+\verb$[72]{-1}{1}{-1}{1}$, which means that each unit in the picture is
+72 times the value of \cs{mfpicunit}, that is, about one inch. The first
+pair of mandatory arguments, \verb${-1}{1}$, indicate the
+$x$-coordinates run from $-1$ to $1$. Since these differ by 2, they
+indicate a width of two inches. The second pair similarly represents a
+height of two inches. But the ellipse is centered at $(0,0)$, which is
+one inch above the bottom (bottom is at $y = -1$), and its vertical
+radius is .5. So the lowest point on the ellipse should be 0.5 inches
+above the bottom of the space reserved. \Mfp{} provides a way to fit the
+space reserved to the actual extent of `ink' in the picture. That is by
+the option \opt{truebbox}:
+\begin{verbatim}
+\usepackage[metapost,truebbox]{mfpic}
+\end{verbatim}
+This would then produce something like figure~\ref{fig2}.
+From now on, this option will be in effect in our examples.
+\usetruebbox
+\begin{mfpfig}{fig2}
+ My first figure:
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \ellipse{(0,0),1,.5}
+ \end{mfpic}
+\end{mfpfig}
+
+Even though the arguments to the \env{mfpic} environment are ignored in
+determining the size of the figure (under \opt{truebbox}), they are
+still needed in order to establish the coordinate system that the
+ordered pairs refer to (for example \texttt{(0,0)} in the \cs{ellipse}
+arguments).
+
+\chapter{Positioning text}\label{sec:text}
+
+By now you are probably thinking: ``This so-called `Hello, world'
+of \mfp{} doesn't say `Hello, world' anywhere!'' We correct that
+with the following example:
+\begin{verbatim}
+\begin{mfpic}[72]{-1}{1}{-1}{1}
+ \ellipse{(0,0),1,.5}
+ \tlabel[cc](0,0){Hello, world.}
+\end{mfpic}
+\end{verbatim}
+This should give you figure~\ref{fig3}.
+\begin{mfpfig}{fig3}
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \ellipse{(0,0),1,.5}
+ \tlabel[cc](0,0){Hello, world.}
+ \end{mfpic}
+\end{mfpfig}
+
+The \cs{tlabel} command places the given text at the given position
+($(0,0)$) adjusted according to the optional argument \texttt{[cc]},
+which says to center the text (both vertically and horizontally) at that
+location. The \texttt{[cc]} is optional. Without it, the text would have
+the leftmost point of its baseline (the imaginary line that most letters
+sit on) placed at $(0,0)$.
+
+You are no doubt thinking: ``The ellipse doesn't really match the
+text. What you need is some macro that measures the text and produces an
+oval with similar dimensions.'' For that we have the \cs{tlabeloval}
+command. The \cs{tlabeljustify} command in the example below is to
+communicate to both the text placement and the curve generation
+procedures that they are to be centered at the point $(0,0)$. (We'll see
+an easier way to do this later.)
+\begin{verbatim}
+\begin{mfpic}[72]{-1}{1}{-1}{1}
+ \tlabeljustify{cc}
+ \tlabeloval(0,0){Hello, world.}
+\end{mfpic}
+\end{verbatim}
+This produces figure~\ref{fig4}.
+\begin{mfpfig}{fig4}
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \tlabeljustify{cc}
+ \tlabeloval(0,0){Hello, world.}
+ \end{mfpic}
+\end{mfpfig}
+
+This would be better still if a little space is left around the text so
+the ellipse doesn't touch it. The \cs{tlpathsep} command can do that:
+\begin{verbatim}
+\begin{mfpic}[72]{-1}{1}{-1}{1}
+ \tlabeljustify{cc}
+ \tlpathsep{3pt}
+ \tlabeloval(0,0){Hello, world.}
+\end{mfpic}
+\end{verbatim}
+producing figure~\ref{fig5}.
+\begin{mfpfig}{fig5}
+\begin{mfpic}[72]{-1}{1}{-1}{1}
+ \tlabeljustify{cc}
+ \tlpathsep{3pt}
+ \tlabeloval(0,0){Hello, world.}
+\end{mfpic}
+\end{mfpfig}
+
+It would be nice to make the text pop out a bit with some color%
+ \footnote{Colors are included in this document only to give
+ examples of their use in \prog{mfpic}. I do not necessarily
+ recommend any of them.}%
+. You can do that by adding \verb$\gfill[yellow]$ in front of either
+\verb$\ellipse$ or \verb$\tlabeloval$:
+\begin{verbatim}
+\begin{mfpic}[72]{-1}{1}{-1}{1}
+ \tlpathsep{3pt}
+ \tlabeljustify{cc}
+ \gfill[yellow]\tlabeloval(0,0){Hello, world.}
+\end{mfpic}
+\end{verbatim}
+This will produce figure~\ref{fig6}.
+\begin{mfpfig}{fig6}
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \tlpathsep{3pt}
+ \tlabeljustify{cc}
+ \gfill[yellow]\tlabeloval(0,0){Hello, world.}
+ \end{mfpic}
+\end{mfpfig}
+
+Notice that now the boundary of the oval has not been drawn. This is the
+standard behavior of \mfp{}. A figure command alone will draw the
+figure. If you want some other rendering than that, you must explicitly
+provide all of it. To get the boundary back, simply add \verb$\draw$
+before the \verb$\gfill$. You can draw the curve in a color other than
+black with an optional argument. We can also make the line thicker with
+the command \verb$\penwd$:
+\begin{verbatim}
+\begin{mfpic}[72]{-1}{1}{-1}{1}
+ \penwd{1.5pt}
+ \tlpathsep{3pt}
+ \tlabeljustify{cc}
+ \draw[blue]\gfill[yellow]\tlabeloval(0,0){Hello, world.}
+\end{mfpic}
+\end{verbatim}
+This will produce figure~\ref{fig7}.
+\begin{mfpfig}{fig7}
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \penwd{1.5pt}
+ \tlpathsep{3pt}
+ \tlabeljustify{cc}
+ \draw[blue]\gfill[yellow]\tlabeloval(0,0){Hello, world.}
+ \end{mfpic}
+\end{mfpfig}
+
+This last version doesn't look too bad, but it seems that the oval ought
+to be a little fatter (slightly higher than it is now). By default,
+\verb$\tlabeloval$ will make the ratio of width to height the same as
+that of the text, or rather of the text plus the additional space
+specified by \verb$\tlpathsep$. This can be changed with an optional
+argument, a number that multiplies the width-to-height ratio. Decreasing
+this ratio will decrease the width (slightly) and increase the height.
+Here we have also omitted the \cs{tlabeljustify} command and shown that
+\cs{tlabeloval} takes a second optional argument that can be used to
+`justify' both the curve and the text. To use this, one must explicitly
+include the first optional argument; if the default is intended, an
+empty pair of brackets may be used.
+\begin{verbatim}
+\begin{mfpic}[72]{-1}{1}{-1}{1}
+ \penwd{1.5pt}
+ \tlpathsep{3pt}
+ \draw[blue]\gfill[yellow]\tlabeloval[.8][cc](0,0){Hello, world.}
+\end{mfpic}
+\end{verbatim}
+This will produce figure~\ref{fig8}.
+\begin{mfpfig}{fig8}
+ \begin{mfpic}[72]{-1}{1}{-1}{1}
+ \penwd{1.5pt}
+ \tlpathsep{3pt}
+ \draw[blue]\gfill[yellow]\tlabeloval[.8][cc](0,0){Hello, world.}
+ \end{mfpic}
+\end{mfpfig}
+
+The \cs{tlabeloval} command places the label last, after the action of
+all the preceding macros; therefore the text ends up on top of
+everything else. The \cs{tlabeloval} command also has a \mbox{`*-form'} that
+does everything \emph{except} place the text. Finally, ovals are not the
+only thing that can be used to surround text. See the manual
+(\file{mfpic-doc.pdf}) and below for others.
+
+Here is a more common use of \verb$tlabel$ commands: labeling a graph
+and axes. In the following example we have given \cs{tlabel} the option
+\texttt{[bl]} to place the bottom left corner of the text at the given
+coordinates. However, we have used \verb$\tlpointsep{3pt}$, which has
+the effect of shifting text away from its nominal location, to prevent the
+text from colliding with the curve.%
+ \footnote{One can also use \cs{tlabelsep}, which is equivalent to
+ \cs{tlpathsep} plus \cs{tlpointsep}.}
+The value set by \cs{tlpointsep} has an effect only if the point is on
+the edge of the text, so there would be no shifting with the
+\texttt{[cc]} placement used earlier.
+\begin{verbatim}
+\begin{mfpic}[72]{0}{2.5}{0}{1}
+ \tlpointsep{3pt}
+ \polyline{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \tlabel[bl](.5,1){Max output}
+ \dashed\polyline{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \tlabel[bl](1.5,.7){Max input}
+\end{mfpic}
+\end{verbatim}
+This will produce figure~\ref{fig9}.
+\begin{mfpfig}{fig9}
+ \begin{mfpic}[72]{0}{2.5}{0}{1}
+ \tlpointsep{3pt}
+ \polyline{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \tlabel[bl](.5,1){Max output}
+ \dashed\polyline{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \tlabel[bl](1.5,.7){Max input}
+ \end{mfpic}
+\end{mfpfig}
+
+Notice that \verb$\polyline$ alone produces a solid line while
+\verb$\dashed\polyline$ makes a dashed line. Let us close this section
+by dressing up this figure with axes, some fat dots marking the
+keypoints, and hash marks on the axes:
+\begin{verbatim}
+\begin{mfpic}[72]{0}{2.5}{0}{1}
+ \tlpointsep{3pt}
+ \polyline{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \point[3pt]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \tlabel[bl](.5,1){Max output}
+ \dashed\polyline{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \tlabel[bl](1.5,.7){Max input}
+ \axes
+ \xmarks{0,0.5,1,1.5,2}
+ \axislabels x{{$50$} .5, {$100$} 1, {$150$} 1.5, {$200$} 2}
+\end{mfpic}
+\end{verbatim}
+This will produce figure~\ref{fig10}.
+\begin{mfpfig}{fig10}
+ \begin{mfpic}[72]{0}{2.5}{0}{1}
+ \tlpointsep{3pt}
+ \polyline{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \point[3pt]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \tlabel[bl](.5,1){Max output}
+ \dashed\polyline{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \tlabel[bl](1.5,.7){Max input}
+ \axes
+ \xmarks{0,0.5,1,1.5,2}
+ \axislabels x{{$50$} .5, {$100$} 1, {$150$} 1.5, {$200$} 2}
+ \end{mfpic}
+\end{mfpfig}
+
+The optional argument of \verb$\point$ specifies the diameter of the
+points to draw. The command \verb$\pointfillfalse$ forces the points to
+be drawn as open circles. The axes configure themselves to the size
+specified in the argument of the \env{mfpic} environment. The
+\verb$axislabels$ command takes as arguments a letter, to specify the
+axis, and a comma separated list of labels, each of which is specified
+by some text to place (in braces) and the x-coordinate to place it at.
+
+\chapter{Drawing figures}
+
+\Mfp{} has several predefined figures and commands to obtain essentially
+any curve (provided one can obtain enough points on it with sufficient
+precision). We've already seen \verb$\polyline$ and \verb$\ellipse$. The
+former needs a list of points to connect with line segments and the
+latter needs the center and radii of the ellipse. The \verb$\ellipse$
+also takes an optional argument: the number of degrees to rotate the
+ellipse. Here we list some of the more common such figures. Remember
+that all of them will produce some sort of line drawing if used alone.
+They can be preceded by \verb$\dashed$ to make the lines dashed or
+\verb$\dotted$ to make them dotted. If the figure is a closed curve,
+\verb$\gfill$ will fill it in.
+\begin{verbatim}
+\begin{mfpic}[72]{0}{4}{0}{1}
+ \rect{(0,0),(1,.75)}
+ \circle{(1.5,.5),.45}
+ \arc[s]{(3,0),(2,1),45}
+ \ellipse[20]{(3.5, 0.5), 0.6, 0.4}
+\end{mfpic}
+\end{verbatim}
+This produces figure~\ref{fig11}. The \verb$\arc$ command has several
+forms. The optional argument picks the form to use. This one specifies
+the endpoints of the circular arc and the angle of the arc (the angle
+between the radii from the center of the circle to those two points).
+Other possibilities are a three-point form (option \texttt{[t]}), a
+polar form (option \texttt{[p]}), and a center-point-sweep form (option
+\texttt{[c]}, specify a center, starting point, and angle). See the
+manual for details. The default (what would be assumed if no optional
+argument is given) is \oarg{s} and is called the ``point-sweep'' form.
+\begin{mfpfig}{fig11}
+ \begin{mfpic}[72]{0}{4}{0}{1}
+ \rect{(0,0),(1,.75)}
+ \circle{(1.5,.5),.45}
+ \arc[s]{(3,0),(2,1),45}
+ \ellipse[20]{(3.5, 0.5), 0.6, 0.4}
+ \end{mfpic}
+\end{mfpfig}
+
+The \cs{polyline} command draws straight lines connecting points. We can
+also draw smooth curves. Lets take the same points from our
+\cs{polyline} example (figure~\ref{fig9}), but change \cs{polyline} to
+\cs{curve}, omit the text, and add the points from figure~\ref{fig10}:
+\begin{verbatim}
+\begin{mfpic}[72]{0}{2.5}{0}{1}
+ \curve{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \point[3pt]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \dashed\curve{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+\end{mfpic}
+\end{verbatim}
+This should produce figure~\ref{fig12}.
+\begin{mfpfig}{fig12}
+ \begin{mfpic}[72]{0}{2.5}{0}{1}
+ \curve{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \point[3pt]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \dashed\curve{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \end{mfpic}
+\end{mfpfig}
+
+This is somewhat unsatisfying. One could improve the result by selecting
+more points, or by increasing the `tension' in the curve.
+
+Roughly speaking, tension determines how straight the segments between
+the points are, and how sharp the turns at each point. High tension
+makes the curve look a little more like a polyline. The default tension
+is 1, a tension of about 5 makes the result look somewhat like a
+polyline with very slightly rounded corners, very high tensions make the
+curve indistinguishable from a polyline. Tension must (almost) always be
+greater than $0.75$.
+
+Another effect of increased tension is to reduce the little wobbles we
+can see in the first curve. Let's try a tension of 1.5, which can be
+specified as an optional argument to \cs{curve}:
+\begin{verbatim}
+\begin{mfpic}[72]{0}{2.5}{0}{1}
+ \curve[1.5]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \point[3pt]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \dashed\curve[1.5]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+\end{mfpic}
+\end{verbatim}
+This give figure~\ref{fig13}.
+\begin{mfpfig}{fig13}
+ \begin{mfpic}[72]{0}{2.5}{0}{1}
+ \curve[1.5]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \point[3pt]{(0,.2),(.5,1),(1,.7),(1.5,0),(2,.3)}
+ \dashed\curve[1.5]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,.6),(1,.3),(1.5,.7),(2,.1)}
+ \end{mfpic}
+\end{mfpfig}
+
+When we use \cs{curve}, there is no way \MP{} can tell if we are just
+connecting points or if we are trying to graph a function.
+It \emph{cannot} enforce the requirement, which every function must
+satisfy, that the curve should travel left-to-right. The command
+\cs{fcncurve} does enforce this (assuming the points to be connected are
+listed in left-to-right order). This command also permits an optional
+tension argument. The dotted line in figure~\ref{fig14} is produced with
+\cs{curve}, the solid one with \cs{fcncurve}. One might conceivably want
+to decrease the tension a bit here.
+\begin{verbatim}
+\begin{mfpic}[72]{0}{2.5}{0}{1}
+ \dotted\curve{(0,.2),(.5,0),(.85,.5),(1,1),(1.5,0),(2,.3)}
+ \fcncurve{(0,.2),(.5,0),(.85,.5),(1,1),(1.5,0),(2,.3)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,0),(.85,.5),(1,1),(1.5,0),(2,.3)}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig14}
+ \begin{mfpic}[72]{0}{2.5}{0}{1}
+ \dotted\curve{(0,.2),(.5,0),(.85,.5),(1,1),(1.5,0),(2,.3)}
+ \fcncurve{(0,.2),(.5,0),(.85,.5),(1,1),(1.5,0),(2,.3)}
+ \pointfillfalse
+ \point[3pt]{(0,.2),(.5,0),(.85,.5),(1,1),(1.5,0),(2,.3)}
+ \end{mfpic}
+\end{mfpfig}
+
+Other figures available include\leftmargini=2\leftmargini
+\begin{description}
+\item[\cs{cyclic}] Used just like \cs{curve} but closes the path
+ (connects the last point smoothly to the starting point).
+\item[\cs{polygon}] Used just like \cs{polyline} except it connects the
+ last point to the first with a straight line.
+\item[\cs{sector}] Makes a wedge with two straight lines and an arc. The
+ arguments are almost the same as \cs{arc}\oarg{p}, but the order is
+ different: center, radius and two angles.
+\end{description}
+
+Here are some other curves that, like \cs{tlabeloval}, are proportioned
+to fit given text. All have a \texttt{*}-form that draws the path
+without placing the text.
+\begin{description}
+\item[\cs{tlabelrect}] This produces a rectangle. It has the same usage
+ as \cs{tlabeloval}, except the first optional argument specifies
+ the radius of quarter-circles used to make rounded corners.
+\item[\cs{tlabelellipse}] This is similar to \cs{tlabeloval}
+ except that instead of modifying the width-to-height ratio, the
+ first optional argument \emph{is} the width-to-height ratio. If that
+ argument is 1 (the default) you get a circle.
+\item[\cs{tlabelcircle}] This produces a circle, of course.
+\end{description}
+
+
+\chapter{Functions}
+
+\CMP{} is able to calculate a number of functions natively, and still
+more have been defined in \mfp{}. Also available are the usual
+arithmetic operations. Any valid \MP{} expression, containing
+one unknown \gbc{x} and producing a numerical result can be graphed.
+
+Here is an example of the graphs of $y = x^2$ and $y = \pm\sqrt{x}$.
+Note that exponentials are denoted by \texttt{**} and it is important to
+note that it has the same precedence as multiplication (denoted by a
+single \texttt{*}). That is, in a formula like \mfc{3*3**2}, the
+operations are performed in order, left to right, producing $(3\cdot
+3)^2 = 81$ and not $3\cdot 3^2 = 27$. Parentheses are needed if the
+latter is intended: \mfc{3*(3**2)}.
+\begin{verbatim}
+\setlength{\mfpicunit}{1cm}
+\begin{mfpic}{-2.5}{2.5}{-1.5}{4}
+ \function{-2,2,.1}{x**2}
+ \function{0,2,.1}{sqrt x}
+ \function{0,2,.1}{-sqrt x}
+ \axes
+ \xmarks{-2,-1,1,2}
+ \ymarks{-1,1,2,3}
+ \tlpointsep{3pt}
+ \axislabels x{{$-2$}-2,{$-1$}-1,{$1$}1,{$2$}2}
+ \axislabels y{{$-1$}-1,{$1$}1,{$2$}2,{$3$}3}
+\end{mfpic}
+\end{verbatim}
+This produces figure~\ref{fig15}.
+\begin{mfpfig}{fig15}
+ \setlength{\mfpicunit}{1cm}
+ \begin{mfpic}{-2.5}{2.5}{-1.5}{4}
+ \function{-2,2,.1}{x**2}
+ \function{0,2,.1}{sqrt x}
+ \function{0,2,.1}{-sqrt x}
+ \axes
+ \xmarks{-2,-1,1,2}
+ \ymarks{-1,1,2,3}
+ \tlpointsep{3pt}
+ \axislabels x{{$-2$}-2,{$-1$}-1,{$1$}1,{$2$}2}
+ \axislabels y{{$-1$}-1,{$1$}1,{$2$}2,{$3$}3}
+ \end{mfpic}
+\end{mfpfig}
+
+The command \cs{function} has two arguments. The first contains the
+starting and ending x-values of the desired graph, followed by a
+\emph{step size}. Generally the smaller the steps the better the
+accuracy, but \MP{} has a limit on the number of steps (usually about
+2000). There is also an optional argument which can be \oarg{s}, the
+default, which means the graph is to be smooth, or \oarg{p}, which means
+the graph is constructed by connecting the calculated points with
+straight lines. Here is the same example with larger step size to
+emphasize the difference (see figure~\ref{fig16})
+\begin{verbatim}
+\setlength{\mfpicunit}{1cm}
+\begin{mfpic}{-2.5}{2.5}{-1.5}{4}
+ \function[p]{-2,2,.5}{x**2}
+ \function[p]{0,2,.5}{sqrt x}
+ \function[p]{0,2,.5}{-sqrt x}
+ \axes
+ \xmarks{-2,-1,1,2}
+ \ymarks{-1,1,2,3}
+ \tlpointsep{3pt}
+ \axislabels x{{$-2$}-2,{$-1$}-1,{$1$}1,{$2$}2}
+ \axislabels y{{$-1$}-1,{$1$}1,{$2$}2,{$3$}3}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig16}
+ \setlength{\mfpicunit}{1cm}
+ \begin{mfpic}{-2.5}{2.5}{-1.5}{4}
+ \function[p]{-2,2,.5}{x**2}
+ \function[p]{0,2,.5}{sqrt x}
+ \function[p]{0,2,.5}{-sqrt x}
+ \axes
+ \xmarks{-2,-1,1,2}
+ \ymarks{-1,1,2,3}
+ \tlpointsep{3pt}
+ \axislabels x{{$-2$}-2,{$-1$}-1,{$1$}1,{$2$}2}
+ \axislabels y{{$-1$}-1,{$1$}1,{$2$}2,{$3$}3}
+ \end{mfpic}
+\end{mfpfig}
+
+In addition, one can increase the tension in the curve drawn by putting
+a tension value after the \gbc{s} in \oarg{s}. For a tension of 2.4:
+\cs{function}\oarg{s2.4}\marg{\dots}.
+
+The functions available include \gbc{sqrt} and all the trig functions:
+\gbc{sin x} assumes \gbc{x} is an angle in radians, \mfc{sind x} assumes
+it is in degrees, with a similar naming convention for the remaining
+trig functions. The inverses are \gbc{asin x}, \gbc{acos x}, and
+\gbc{atan x}, which produce angles in degrees, and \gbc{invsin x}, etc.,
+which produce angles in radians. There is also \gbc{ln~x} or \gbc{log~x}
+for the natural logarithm, \gbc{exp~x} for $e^x$, \gbc{logten}~\gbc{x}
+for the base 10 logarithm, \gbc{logtwo}~\gbc{x} for base 2, and
+\gbc{logbase} for other bases:
+\gbc{logbase(16)}~\gbc{x} (for example) for base 16. The general syntax of
+these functions is the following: if the argument is \gbc{x} alone or a
+pure number alone or the particular case of a number followed by \gbc{x}
+(no \gbc{*} in between!) then parentheses are not needed. Example:
+\gbc{sin~2x}. For almost anything else, parentheses are required:
+\gbc{sin(3*x)} or \gbc{sin(x**2)}.
+
+Some other functions available are the hyperbolic functions, \gbc{sinh x},
+\gbc{cosh x}, etc. (all 6 of them), and the inverses of three of them:
+\gbc{asinh x}, \gbc{acosh x}, and \gbc{atanh x}.
+
+These functions (or any \MP{} numeric expression) can also be used in
+any of the coordinates of points in drawing commands like \cs{polyline}
+(but not usually in text placement commands like \cs{tlabeloval}). For
+example (from now on the value of \cs{mfpicunit} is set to
+\texttt{1cm}):\setlength{\mfpicunit}{1cm}
+\begin{verbatim}
+\begin{mfpic}{-.5}{2.5}{-1.5}{1.5}
+ \polyline{(2,-sqrt 2),(1,-1),(.5,- sqrt .5),(0,0),
+ (.5,sqrt .5),(1,1),(2,sqrt 2)}
+ \axes
+ \xmarks{1,2}
+ \ymarks{-1,1}
+ \tlpointsep{3pt}
+ \axislabels x{{$1$}1,{$2$}2}
+ \axislabels y{{$-1$}-1,{$1$}1}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig17}
+ \begin{mfpic}{-.5}{2.5}{-1.5}{1.5}
+ \polyline{(2,-sqrt 2),(1,-1),(.5,- sqrt .5),(0,0),
+ (.5,sqrt .5),(1,1),(2,sqrt 2)}
+ \axes
+ \xmarks{1,2}
+ \ymarks{-1,1}
+ \tlpointsep{3pt}
+ \axislabels x{{$1$}1,{$2$}2}
+ \axislabels y{{$-1$}-1,{$1$}1}
+ \end{mfpic}
+\end{mfpfig}
+
+There are other types of functions: parametric functions, and polar
+coordinate versions. \Mfp{} provides \cs{parafcn} and \cs{plrfcn} to
+graph these. The \cs{parafcn} requires a starting value, and ending
+value and a step size just as in \cs{function}, but in the second
+argument there must be either a pair of expressions in the variable
+\gbc{t}, separated by a comma and enclosed in parentheses, or a single
+\emph{pair-valued} expression. \CMP{} and \mfp{} provide only a few
+pair-valued functions; one is used below.
+
+The second argument of \cs{plrfcn} must contain a single numeric
+expression in the variable \gbc{t}, and indicates a function of $\theta$
+to be graphed in polar coordinates: $r = f(\theta)$. In the following
+example (figure~\ref{fig22}), we draw a portion of the graph of $x =
+y^2$ by representing it as the graph of the parametric equations $x =
+t^2$, $y = t$, and a portion of a circle of radius $1.5$ by representing
+it as the graph of the pair-valued function \mfc{dir(t)}. The expression
+\mfc{dir(t)} gives the point whose distance from $(0,0)$ is $1$ in the
+direction given by the angle \mfc{t}.
+\begin{verbatim}
+\begin{mfpic}{-2}{4}{-2}{2}
+ \parafcn{-2,2,.1}{(t**2,t)}
+ \dotted\parafcn{45,315,5}{1.5*dir(t)}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig22}
+ \begin{mfpic}{-2}{4}{-2}{2}
+ \parafcn{-2,2,.1}{(t**2,t)}
+ \dotted\parafcn{45,315,5}{1.5*dir(t)}
+ \end{mfpic}
+\end{mfpfig}
+
+
+Here is an example of a graph of the polar coordinate function
+$r=2\sin 3\theta$ (figure~\ref{fig23}). We use the degree version
+\mfc{sind} in order to work with integers.
+\begin{verbatim}
+\begin{mfpic}{-2}{2}{-2}{2}
+ \plrfcn{0,180,5}{2*sind 3t}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig23}
+ \begin{mfpic}{-2}{2}{-2}{2}
+ \plrfcn{0,180,5}{2*sind 3t}
+ \end{mfpic}
+\end{mfpfig}
+
+
+\chapter{Transforming figures}
+
+\CMP{} is capable of any affine transformation (things like shifting,
+rotating, scaling, reflecting and slanting) of any path. The figures
+we've been dealing with so far (\cs{ellipse}, \cs{curve}, \cs{function},
+etc.) all produce, in the \MP{} code, the definition of some path (as
+well as a drawing of that path). \Mfp{} provides for different methods
+of `drawing' the path with \emph{prefix macros}. We've seen \cs{dashed},
+\cs{dotted}, \cs{gfill} so far, in addition to the default \cs{draw}.
+\Mfp{} also provides for modifying the shape and position of the path
+with other prefixes. Here's a simple example.
+\begin{verbatim}
+\begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \rotatepath{(1,.5), 45}\rect{(0,0),(2,1)}
+ \point{(1,.5)}
+\end{mfpic}
+\end{verbatim}
+The command \cs{rotatepath} obviously rotates the path that follows, but
+it needs to know what the center of rotation will be, and how much to
+rotate. These are given in its mandatory argument, separated by a comma.
+The example above (pictured in figure~\ref{fig18}) rotates 45 degrees
+around the center of the rectangle.
+\begin{mfpfig}{fig18}
+ \begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \rotatepath{(1,.5), 45}\rect{(0,0),(2,1)}
+ \point{(1,.5)}
+ \end{mfpic}
+\end{mfpfig}
+
+Notice that we have no drawing prefix. A combination of
+transformation-plus-figure is treated as a figure in its own right and
+behaves the same. If we want the figure dashed, we could write
+\begin{verbatim}
+\dashed\rotatepath{(1,.5),45}\rect{(0,0),(2,1)}
+\end{verbatim}
+It may not be obvious, but we can also write a drawing macro between
+the rotation and the figure, producing figure~\ref{fig19}
+\begin{verbatim}
+\begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \rotatepath{(1,.5), 45}\draw\rect{(0,0),(2,1)}
+ \point{(1,.5)}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig19}
+ \begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \rotatepath{(1,.5), 45}\draw\rect{(0,0),(2,1)}
+ \point{(1,.5)}
+ \end{mfpic}
+\end{mfpfig}
+
+This illustrates another property of \mfp{} macros: the combination of a
+rendering prefix and a figure is also treated the same as a figure in
+its own right: the same figure as the one that follows. In fact, the
+only difference between \cs{rect} and \cs{draw}\cs{rect} in this
+example is that the second one has a minor(!) side effect: the
+rectangle is drawn.
+
+Finally, try to guess what happens if we add another prefix at the
+front:
+\begin{verbatim}
+\begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \dotted\rotatepath{(1,.5), 45}
+ \draw\rect{(0,0),(2,1)}
+\end{mfpic}
+\end{verbatim}
+and if we add another rotation in front of that.
+\begin{verbatim}
+\begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \rotatepath{(0,0),45}
+ \dotted\rotatepath{(1,.5), 45}
+ \draw\rect{(0,0),(2,1)}
+\end{mfpic}
+\end{verbatim}
+
+
+Available transformations include
+\begin{display}\raggedright
+ \cs{scalepath}, \cs{shiftpath}, \cs{xscalepath}, \cs{yscalepath},
+ \cs{slantpath}, and \cs{reflectpath}.
+\end{display}
+See the manual for a description of what arguments are required for
+each. Here's a final example, producing figure~\ref{fig20}
+\begin{verbatim}
+\begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \shiftpath{(-1,1)}\draw[red]\slantpath{.5,1}\dotted
+ \rotatepath{(0,0), 90}\dashed\rect{(0,0),(2,1)}
+ \point{(0,0),(2,1)}
+ \tlpointsep{2pt}
+ \tlabel[tr](0,0){$(0,0)$}
+ \tlabel[bl](2,1){$(2,1)$}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig20}
+ \begin{mfpic}{-.5}{2.5}{-.5}{2.5}
+ \shiftpath{(-1,1)}\draw[red]\slantpath{.5,1}\dotted
+ \rotatepath{(0,0), 90}\dashed\rect{(0,0),(2,1)}
+ \point{(0,0),(2,1)}
+ \tlpointsep{2pt}
+ \tlabel[tr](0,0){$(0,0)$}
+ \tlabel[bl](2,1){$(2,1)$}
+ \end{mfpic}
+\end{mfpfig}
+
+\chapter{Rendering figures}
+
+\emph{Rendering} is the act of making a description of a figure visible.
+Examples are: drawing a solid curve, drawing a dashed curve, or filling
+its interior, For \mfp{} figure macros the default, in the absence of
+explicit commands, is to use \cs{draw}. That is,
+\begin{verbatim}
+\rect{(0,0),(1,2)}
+\end{verbatim}
+has the same result as
+\begin{verbatim}
+\draw\rect{(0,0),(1,2)}
+\end{verbatim}
+The default rendering can be changed. Just say
+\cs{setrender}\marg{\cs{dashed}}, and all figures afterward will be dashed
+(see figure~\ref{fig21}).
+\begin{verbatim}
+\begin{mfpic}{0}{2}{0}{1}
+\setrender{\dashed}
+ \rect{(0,0),(1,1)}
+ \circle{(1.5,.5),.5}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig21}
+ \begin{mfpic}{0}{2}{0}{1}
+ \setrender{\dashed}
+ \rect{(0,0),(1,1)}
+ \circle{(1.5,.5),.5}
+ \end{mfpic}
+\end{mfpfig}
+The \cs{setrender} command can be inside an \env{mfpic} environment to
+affect only later commands in that figure, or outside to affect all
+later \mfp{} figures.
+
+We give a few examples now of the renderings possible. These divide
+more-or-less into those that trace a path and those that fill in a path.
+In order to fill in a path, it must be a closed path, of course, but
+\MP{} distinguishes between closed paths and those that merely happen to
+end where they began. There is a good reason for this: \MP{} cannot,
+without human aid, know if two points are the same, or merely
+accidentally so close that the accuracy of the program sees them as the
+same. It requires human aid in the form of an explicit request to
+create a closed path. Of the \mfp{} macros we've seen so far,
+\cs{ellipse}, \cs{circle}, \cs{rect}, \cs{polygon}, and \cs{cyclic}
+produce closed paths, but \cs{polyline}, \cs{curve}, \cs{function},
+\cs{parafcn}, and \cs{plrfcn} do not. Also producing closed paths are
+\cs{tlabeloval} and its relatives.
+
+The following example illustrates filling with a hatching pattern
+(parallel lines) and an \emph{unfilling}. Clearing the interior of a
+path may not seem like rendering, but it is treated in exactly the same way
+(think of it as a negative rendering). We first hatch a rectangle, then
+clear out a smaller rectangle with rounded corners to place our text
+inside. The results are in figure~\ref{fig24}.
+\begin{verbatim}
+\begin{mfpic}{0}{2}{0}{2}
+ \draw[red]\lhatch[2pt][blue]\rect{(0,0),(2,2)}
+ \gclear\tlabelrect[6pt][cc](1,1){Hatching!}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig24}
+ \begin{mfpic}{0}{2}{0}{2}
+ \draw[red]\lhatch[2pt][blue]\rect{(0,0),(2,2)}
+ \gclear\tlabelrect[6pt][cc](1,1){Hatching!}
+ \end{mfpic}
+\end{mfpfig}
+This example illustrates that \cs{lhatch} fills with left slanting
+lines. And that it takes two optional arguments. The first is the
+distance between lines, and the second is the color to make the lines.
+There are also \cs{rhatch} which slants the lines the other way,
+\cs{xhatch} which uses both slants, and \cs{thatch} which can draw
+the lines at any angle.
+
+Here is another example of rendering (figure~\ref{fig26}). The new
+macro is \cs{polkadot}. We've repeated this example twice to
+show the effect of changing the order of the prefixes. Each prefix
+applies its rendering to the result of everything to the right of it. In
+the second example the hatching goes over the dots (and a bit of the
+dashes as well). If the \cs{gfill} were first, it would cover almost
+everything else.
+\begin{verbatim}
+\begin{mfpic}{0}{6}{0}{2}
+ \penwd{2pt}
+ \hatchwd{2pt}
+ \drawcolor{blue}
+ \hatchcolor{red}
+ \fillcolor{green}
+ \dashed\polkadot\rhatch[5pt]\gfill[yellow]\rect{(0,0),(2.8,1.8)}
+ \rhatch[5pt]\dashed\polkadot\gfill[yellow]\rect{(3,0),(5.8,1.8)}
+\end{mfpic}
+\end{verbatim}
+We've added a couple of other new features to this example. To emphasize
+effects, we've increased the thickness of the drawing pen (\cs{penwd})
+and the hatch lines (\cs{hatchwd}). We've also used the \cs{drawcolor}
+macro and its relatives to set the colors to be used. The \cs{polkadot}
+macro uses the color set by \cs{fillcolor}; so does \cs{gfill} if no
+optional color is given.
+\begin{mfpfig}{fig26}
+ \begin{mfpic}{0}{6}{0}{2}
+ \penwd{2pt}
+ \hatchwd{2pt}
+ \drawcolor{blue}
+ \hatchcolor{red}
+ \fillcolor{green}
+ \dashed\polkadot\rhatch[5pt]\gfill[yellow]\rect{(0,0),(2.8,1.8)}
+ \rhatch[5pt]\dashed\polkadot\gfill[yellow]\rect{(3,0),(5.8,1.8)}
+ \end{mfpic}
+\end{mfpfig}
+
+If one wants to plot several curves in a single graph, they often need
+to be rendered differently. The three methods we've seen so far,
+\cs{draw}, \cs{dashed}, and \cs{dotted}, may not be enough. The
+\cs{dashed} and \cs{dotted} commands permit an optional argument to
+adjust the length of the dashes and spaces, and size of the dots. One
+can also change the curve thickness with \cs{penwd}. But
+that may not be `different' enough. \Mfp{} provides a few solutions.
+When color is available, they may be drawn in different colors. When
+not, there are two possibilities: \cs{gendashed} and \cs{plot}.
+
+The first, \cs{gendashed}, is a generalized dashing macro. It takes one
+mandatory argument, the name of a dashing pattern. Named dashing
+patterns may be created with the \cs{dashpattern} command, as shown by
+the following example (see figure~\ref{fig27}):
+\begin{verbatim}
+\begin{mfpic}{-3.5}{3.5}{-1.2}{1.2}
+ \dashpattern{dotdash}{0pt,4pt,3pt,4pt}
+ \gendashed{dotdash}\function{-pi,pi,.2}{sin 2x}
+ \function{-pi,pi,.2}{cos 2x}
+ \axes
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig27}
+ \begin{mfpic}{-3.5}{3.5}{-1.2}{1.2}
+ \dashpattern{dotdash}{0pt,4pt,3pt,4pt}
+ \gendashed{dotdash}\function{-pi,pi,.2}{sin 2x}
+ \function{-pi,pi,.2}{cos 2x}
+ \axes
+ \end{mfpic}
+\end{mfpfig}
+
+The \cs{dashpattern} command takes a name and an even number of lengths.
+The first, third, etc., lengths represent the lengths of dashes
+(\texttt{0pt} means a dot), and the second, fourth, etc., represent
+spaces. The given pattern is dot-space-dash-space. This pattern, when
+used in a \cs{gendashed} command, is repeated for the length of the
+curve.
+
+This last example illustrates that the predefined \MP{} variable
+\gbc{pi} (equal to 3.14159) can be used pretty much anywhere a number
+can be used (except, often, in text label commands).
+
+Another way to get more distinctive curves is to `dot' them with
+something other than tiny dots. The \cs{plot} command does that. It
+takes one mandatory argument, the name of a symbol to use instead of a
+dot. Here are the same two curves \cs{plot}-ed (figure~\ref{fig28}):
+\begin{verbatim}
+\begin{mfpic}{-3.5}{3.5}{-1.2}{1.2}
+ \setlength{\pointsize}{2.5pt}
+ \plot{Triangle}\function{-pi,pi,.2}{sin 2x}
+ \plot[2pt,6pt]{SolidCircle}\function{-pi,pi,.2}{cos 2x}
+ \axes
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig28}
+ \begin{mfpic}{-3.5}{3.5}{-1.2}{1.2}
+ \setlength{\pointsize}{2.5pt}
+ \plot{Triangle}\function{-pi,pi,.2}{sin 2x}
+ \plot[2pt,6pt]{SolidCircle}\function{-pi,pi,.2}{cos 2x}
+ \axes
+ \end{mfpic}
+\end{mfpfig}
+
+The \cs{plot} command takes an optional argument to specify the size of
+the symbols and the spacing between them. The size of the symbols can
+also be adjusted by changing the length command \cs{pointsize} (that also
+adjusts the size of the dots placed with the \cs{point} command).
+
+In this last example, \cs{plotnodes} is similar to \cs{plot}, except it
+placed the symbols at the `nodes' defined by the path command. In the
+case of \cs{function}, these are the points $(x_k, f(x_k))$ with $x_k$
+stepping through all the $x$-values determined by the first argument of
+\cs{function} (figure~\ref{fig29}).
+\begin{verbatim}
+\begin{mfpic}{-3.5}{3.5}{-1.2}{1.2}
+ \plotnodes[2.5pt]{Square}\function{-pi,pi,pi/16}{sin 2x}
+ \axes
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig29}
+ \begin{mfpic}{-3.5}{3.5}{-1.2}{1.2}
+ \plotnodes[2.5pt]{Square}\function{-pi,pi,pi/16}{sin 2x}
+ \axes
+ \end{mfpic}
+\end{mfpfig}
+
+See the manual for the list of predefined symbols available to the
+\cs{plot} and \cs{plotnodes} command.
+
+\chapter{More on text}
+
+The text positioning commands used so far in this guide are entirely
+handled by \TeX{} or \LaTeX. This is why we have occasionally had to say
+that certain things could be done ``except in text placement commands''.
+It is possible for text positioning to be done within \MP, making many
+things possible that couldn't be done otherwise. For example, text can
+be rotated about the point of placement. You are probably thinking that
+\LaTeX{} can rotate text, but it is not all that easy to arrange for the
+point on the graph where we place the text to be the center of rotation.
+Below are two examples, in which we attempt to place the text separated
+from $(0,0)$ by \texttt{5pt} and rotated 45 degrees around $(0,0)$. In
+the first we try to use \LaTeX's \cs{rotatebox} command, and in the
+second we turn on \MP{} handling of labels and use a rotation option to
+the \cs{tlabel} command.
+\begin{verbatim}
+\begin{mfpic}{0}{1}{0}{1}
+ \point{(0,0)}
+ \polyline{(0,0),(1,1)}
+\tlabel[Bl](0,0){\rotatebox{45}{\hspace{5pt}Test text}}
+\end{mfpic}
+\end{verbatim}
+\begin{verbatim}
+\usemplabels
+\begin{mfpic}{0}{1}{0}{1}
+ \point{(0,0)}
+ \polyline{(0,0),(1,1)}
+ \tlpointsep{5pt}
+ \tlabel[Bl45](0,0){Test text}
+\end{mfpic}
+\end{verbatim}
+\begin{figure}[!hb]
+ \centering
+ \begin{minipage}{4cm}
+ \centering
+ \begin{mfpic}{0}{1}{0}{1}
+ \point{(0,0)}
+ \polyline{(0,0),(1,1)}
+ \tlabel[Bl](0,0){\rotatebox{45}{\hspace{5pt}Test text}}
+ \end{mfpic}\renewcommand\thefigure{\thesection.\arabic{figure}a}
+ \refstepcounter{figure}\label{fig30a}
+ \par\medskip (a)
+ \end{minipage}\addtocounter{figure}{-1}\qquad
+ \begin{minipage}{4cm}\usemplabels
+ \centering
+ \begin{mfpic}{0}{1}{0}{1}
+ \point{(0,0)}
+ \polyline{(0,0),(1,1)}
+ \tlpointsep{5pt}
+ \tlabel[Bl45](0,0){Test text}
+ \end{mfpic}\renewcommand\thefigure{\thesection.\arabic{figure}b}
+ \refstepcounter{figure}\label{fig30b}
+ \par\medskip (b)
+ \end{minipage}
+
+ \medskip Figure \thesection.\arabic{figure}.
+\end{figure}
+
+The first produces figure~\ref{fig30a} and the second produces
+figure~\ref{fig30b}. Our goal was to get the baseline of the text lined
+up with the reference line drawn.
+
+In the first example, \LaTeX's \cs{rotatebox} command produces the
+following result, where we put a frame around both the unrotated text
+and the rotated result to emphasize what \LaTeX{} sees as the
+boundaries:
+$$
+ \hbox{\setlength\fboxsep{0pt}%
+ \fbox{\rotatebox{45}{\fbox{\hspace{5pt}Test text}}}}
+$$
+This is then placed by the \cs{tlabel} command with the lower left
+corner of the \emph{outer} box at $(0,0)$. But \LaTeX's axis of rotation
+was at the lower left corner of the inner box. In the second case, \MP{}
+placed the label. The command \cs{tlpointsep}\marg{5pt} and the parameter
+\oarg{Bl45} explicitly request that the label be placed with its left
+baseline 5 points from $(0,0)$ and rotated 45 degrees \emph{about the
+point $(0,0)$}.
+
+The \cs{usemplabels} command used above asks \MP{} to arrange for the
+setting of labels. Adding the option \opt{mplabels} to the
+\cs{usepackage} command that loads \mfp{} has the same effect for the
+whole document. There can be problems with using \MP{} to set labels.
+One is that \MP{} has to call a \file{tex} program to do the actual
+typesetting, and then one must either make arrangements that ensure
+\MP{} will call \LaTeX, or never use any macros in the labels that are
+not defined in plain\TeX. If one does arrange for \LaTeX{} to be used,
+one needs to arrange that a \LaTeX{} preamble is prepended to the output
+\file{.mp} file. The \cs{mfpverbtex} command can be used for this.
+
+The command \cs{nomplabels} can be used to return to having labels set
+at the document level. For the rest of this guide, we have
+\opt{mplabels} in effect.
+
+There are a few more commands that place text on the picture. All of
+them pass the final responsability for text placement to \MP{} if
+\opt{mplabels} is in effect. See the manual for more details.
+
+
+\chapter{Arrows}
+
+The command \cs{arrow} adds an arrowhead onto the \emph{end} of any path
+that follows. For this to have predictable effects, you need to know
+which part of a curve is the end, and which the start. Not surprisingly,
+for the commands that connect a list of points in order the first point
+in the list is the start point and the last point is the end. Except the
+closed paths (\cs{cyclic}, \cs{polygon}, etc.); for them, the start and
+the end points are the same, but the order of the points gives a
+direction to the arrowhead. The default \cs{circle} has an anticlockwise
+direction, but if the circle is defined by three points (for example)
+the direction of the circle is determined by the order in which the
+points are written.
+
+Anyway, here are a few examples, illustrating the use of \cs{arrow}, and
+some of its optional arguments.
+\begin{verbatim}
+\begin{mfpic}{0}{4}{0}{4}
+ \arrow[r-5]\circle{(1,1),.5}
+ \arrow[b4pt]\arrow\polyline{(3,2),(3,0)}
+ \arrow[cred]\reverse\arrow\polyline{(0,3),(2,3)}
+ \arrow[l 5pt]\rect{(4,2),(2,4)}
+\end{mfpic}
+\end{verbatim}
+See figure~\ref{fig31} for the results of this example. There are four
+possible optional arguments, the first character inside the brackets
+tells what option the rest of the argument applies to. The first example
+above starts with `\texttt{r}', which stands for `rotate' and asks for
+the arrowhead to be rotated $-5$ degrees (positive rotation means
+anticlockwise, negative means clockwise). This is frequently useful for
+arrows on curved paths, as the default direction (tangent to the path)
+often just looks wrong). The second example starts with `\texttt{b}',
+which stands for `backset' and it moves the head back \texttt{4pt} from
+where it would otherwise be placed. In the example, this is used to put
+a double arrowhead on the line. In the third example we put an arrow at
+both ends by reversing the sense of the curve in between the two
+\cs{arrow} prefixes. We also used the letter `\texttt{c}' in the
+optional argument of one arrowhead. This stands for `color' and the
+requested color is `\texttt{red}'. Finally, the \texttt{l} option
+(that's a lowercase `ell', not the number `one') changes the length of
+the arrowhead to 5 points (from the \verb$3pt$ default).%
+ \footnote{I have put a space between the \texttt{l} and the
+ \texttt{5pt} so it won't be mistaken for `$15$pt. Normally one
+ should avoid spaces in \mfp{} optional arguments, but this is one
+ case where it will cause no harm.}
+\begin{mfpfig}{fig31}
+ \begin{mfpic}{0}{4}{0}{4}
+ \arrow[r-5]\circle{(1,1),.5}
+ \arrow[b4pt]\arrow\polyline{(3,2),(3,0)}
+ \arrow[cred]\reverse\arrow\polyline{(0,3),(2,3)}
+ \arrow[l 5pt]\rect{(4,2),(2,4)}
+ \end{mfpic}
+\end{mfpfig}
+
+The options can be combined in one command:
+\cs{arrow}\oarg{cblue}\oarg{b4pt}\oarg{r25}\oarg{l6pt} would produce a
+\texttt{6pt} long blue arrowhead rotated 25 degrees anticlockwise, set
+back \texttt{4pt}. The setting back is done in the direction determined
+\emph{after} rotation. The order of the options is not significant.
+
+The shape of the arrowhead can be changed with the \cs{headshape}
+command. The following example draws the arrowhead first normally, and
+then after an instance of this command. We draw it a third time, exactly
+like the second time, except we use the *-form. We have increased the
+length of head and the thickness of the pen to emphasize the effects.
+\begin{verbatim}
+\begin{mfpic}{0}{4}{0}{4}
+ \setlength{\headlen}{20pt}
+ \penwd{3pt}
+ \arrow\polyline{(0,3),(4,3)}
+ \headshape{.5}{2}{true}
+ \arrow\polyline{(0,2),(4,2)}
+ \arrow*\polyline{(0,1),(4,1)}
+\end{mfpic}
+\end{verbatim}
+The results are pictured in figure~\ref{fig32}. The first argument to
+\cs{headshape} sets the ratio of width to height for the head. We have
+cut it in half here. The second argument sets the tension in the curves
+that form the sides of the head. This reduces the curvature in the
+sides. The third argument can be only \texttt{true} or \texttt{false}
+and determines whether the head is a solid shape, or only the two
+`barbs'. The defaults correspond to \verb$\headshape{1}{1}{false}$. The
+filled form does not draw the outline so what we see is the pointy
+arrowhead on top of a thick line. The *-form tries to erase part of the
+line so that one sees an actual pointy arrow.
+\begin{mfpfig}{fig32}
+ \begin{mfpic}{0}{4}{0}{4}
+ \setlength{\headlen}{20pt}
+ \penwd{3pt}
+ \arrow\polyline{(0,3),(4,3)}
+ \headshape{.5}{2}{true}
+ \arrow\polyline{(0,2),(4,2)}
+ \arrow*\polyline{(0,1),(4,1)}
+ \end{mfpic}
+\end{mfpfig}
+
+
+\chapter{Color}
+
+We saw the use of color in earlier sections, and now it's time to be
+systematic about it. The several rendering commands have a color option;
+examples are \cs{draw}, \cs{gfill}, \cs{arrow}, and the hatching
+commands. However, even those commands that don't provide such an option
+can have the color of their rendering changed. \Mfp{} provides the
+following commands to change certain colors. Those commands with a
+color option can be used without that option and then they will the use
+the appropriate color described here. Each of these color-changing
+commands takes a mandatory argument containing the color to change to,
+and an optional argument to be described later.
+
+\begin{description}
+\item[\cs{backgroundcolor}] This sets the color to be used by \cs{gclear}.
+ It is the same color used by \cs{point} for the inside of the
+ points when \cs{pointfillfalse} has been used. In \MP{}, the
+ only way to clear the inside of a region is to cover it up. The
+ default color for this purpose is \mfc{white}. Use this command
+ to change that default.
+\item[\cs{drawcolor}] This sets the default color used by those rendering
+ commands that draw a path. This includes \cs{draw}, but also
+ includes \cs{dashed}, \cs{dotted}, \cs{plot} and \cs{plotnodes}.
+ It is also used by other commands that produce lines or curves:
+ figure macros used without any rendering prefix, as well as
+ \cs{axes} and related commands.
+\item[\cs{fillcolor}] This sets the default color used by \cs{gfill}. It
+ is also used by \cs{polkadot} (which has no color option).
+\item[\cs{hatchcolor}] This sets the default color used by any hatching
+ command.
+\item[\cs{headcolor}] This sets the default color for arrowheads added
+ by the \cs{arrow} command. It is also the color of
+ arrowheads on any coordinate axis.
+\item[\cs{pointcolor}] This sets the color used by \cs{point}, \cs{grid},
+ and \cs{plotsymbol} (the last one will be described later).
+\item[\cs{tlabelcolor}] This sets the color used for all text labels if
+ the \opt{mplabels} option is turned on.
+\end{description}
+
+The color can be a common name for a color, provided that name is one of
+the following: \texttt{white}, \texttt{black}, \texttt{red},
+\texttt{green}, \texttt{blue}, \texttt{cyan}, \texttt{magenta}, or
+\texttt{yellow}. We have already seen this usage. It can also be a color
+name defined in the file \file{dvipsnam.mp} that accompanies \mfp. It can
+also be an explicit color formula, where color formulas are described in
+the \mfp{} manual.
+
+The optional argument is one of the \emph{color models}. See the manual
+for details, but the syntax is just like that of the \prog{color}
+package's \cs{color} command. For example,
+\begin{verbatim}
+\pointcolor[rgb]{0,1,0}
+\end{verbatim}
+would use the color model \opt{rgb} with parameters 0, 1, and 0 (this is
+green). After each of these commands a certain color name is assigned a
+value. For example, a use of the \cs{pointcolor} command assigns a value
+to the color named \gbc{pointcolor}. Also \cs{drawcolor} sets
+\gbc{drawcolor} and this pattern is followed for all the color setting
+commands above except \cs{backgroundcolor}, which assigns its value to
+the color named \gbc{background}.
+
+Color names for \mfp{} use can be defined using the \cs{mfpdefinecolor}
+command. Here's an example (figure~\ref{fig33}). Note the use of the
+color name \gbc{pointcolor} to make arrowheads and points have the same
+color.
+\begin{verbatim}
+\begin{mfpic}{0}{3.5}{0}{3.5}
+ \tlabelcolor{red}
+ \pointcolor{rgb(0,1,0)}% green
+ \drawcolor[rgb]{0,0,1} % blue
+ \fillcolor{Goldenrod} % from dvipsnam.mp
+ \headcolor{pointcolor} % will be green after above
+ \mfpdefinecolor{DarkerRed}{rgb}{.67,0,0}
+ \hatchcolor{DarkerRed}
+ \penwd{1pt}
+ \gfill\circle{(1,1),.5}
+ \point[3pt]{(1,.5),(1,1.5),(.5,1),(1.5,1)}
+ \hatch\rect{(2.5,2.5),(3.5,3.5)}
+ \arrow[l 5pt]\polyline{(1,1),(3,3)}
+ \tlabel[cc](1,3){Examples\\of\\colors}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig33}
+ \begin{mfpic}{0}{3.5}{0}{3.5}
+ \tlabelcolor{red}
+ \pointcolor{rgb(0,1,0)}% green
+ \drawcolor[rgb]{0,0,1} % blue
+ \fillcolor{Goldenrod} % from dvipsnam.mp
+ \headcolor{pointcolor} % will be green after above
+ \mfpdefinecolor{DarkerRed}{rgb}{.67,0,0}
+ \hatchcolor{DarkerRed}
+ \penwd{1pt}
+ \gfill\circle{(1,1),.5}
+ \point[3pt]{(1,.5),(1,1.5),(.5,1),(1.5,1)}
+ \hatch\rect{(2.5,2.5),(3.5,3.5)}
+ \arrow[l 5pt]\polyline{(1,1),(3,3)}
+ \tlabel[cc](1,3){Examples\\of\\colors}
+ \end{mfpic}
+\end{mfpfig}
+
+\chapter{Closing paths}
+
+There are many different ways to modify a figure. We have already seen
+\cs{arrow}, which appends an arrowhead, \cs{reverse} which reverses the
+sense, and several that apply an affine transformation
+(\cs{rotatepath}, \cs{shiftpath}, etc.). Now we will see the simple
+operation of closing a path.
+
+All methods of closing a path have to connect the end to the start, but
+simply drawing a connection is not enough. \MP{} has to be told to close
+the path, and what kind of connection is desired. We have several macros
+that can do the job, the simplest being \cs{lclosed}, which closes with
+a straight line. Putting \cs{lclosed} in front of \cs{polyline}, for
+example, produces the same result as \cs{polygon}. Another macro is
+\cs{sclosed} which produces a smooth closure. Putting it in front of
+\cs{curve} gives (almost) the same result as \cs{cyclic}. There is one
+other useful macro, \cs{bclosed}, which also informs \MP{} to make a
+smooth closure. The difference between \cs{sclosed} and \cs{bclosed} is
+that the first modifies slightly the original path (in order to achieve
+the effect that \cs{sclosed}${}+{}$\cs{curve}${}\approx{}$\cs{cyclic}),
+the second just asks \MP{} to do its best to connect the ends smoothly.
+Here's an example comparing the two smooth methods (figure~\ref{fig34}).
+\begin{verbatim}
+\begin{mfpic}{0}{4}{0}{4}
+ % an open curve:
+ \curve{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ % \sclosed a shifted copy:
+ \draw\gfill[green]\sclosed\shiftpath{(2,0)}
+ \curve{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ % \bclosed another copy:
+ \draw\gfill[yellow]\bclosed\shiftpath{(2,-2)}
+ \curve{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ % \cyclic with same points, shifted:
+ \draw\gfill[red]\shiftpath{(0,-2)}
+ \cyclic{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ \tlabeljustify{bc}
+ \nomplabels
+ \tlabels{
+ (1,2.4){\cs{curve}}
+ (3,2.4){\cs{sclosed}}
+ (1,0.4){\cs{cyclic}}
+ (3,0.4){\cs{bclosed}}
+ }
+ % Some points to help illustrate
+ \point{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ \point{(2.49,3),(2.5,3.7),(3,4),(3.5,3.7),(3.51,3)}
+ \point{(0.49,1),(.5,1.7),(1,2),(1.5,1.7),(1.51,1)}
+ \point{(2.49,1),(2.5,1.7),(3,2),(3.5,1.7),(3.51,1)}
+\end{mfpic}
+\end{verbatim}
+\begin{mfpfig}{fig34}
+ \begin{mfpic}{0}{4}{0}{4}
+ \curve{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ \draw\gfill[green]\sclosed\shiftpath{(2,0)}
+ \curve{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ \draw\gfill[yellow]\bclosed\shiftpath{(2,-2)}
+ \curve{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ \draw\gfill[red]\shiftpath{(0,-2)}
+ \cyclic{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ \tlabeljustify{bc}
+ \nomplabels
+ \tlabels{
+ (1,2.4){\cs{curve}}
+ (3,2.4){\cs{sclosed}}
+ (1,0.4){\cs{cyclic}}
+ (3,0.4){\cs{bclosed}}
+ }
+ \point{(0.49,3),(.5,3.7),(1,4),(1.5,3.7),(1.51,3)}
+ \point{(2.49,3),(2.5,3.7),(3,4),(3.5,3.7),(3.51,3)}
+ \point{(0.49,1),(.5,1.7),(1,2),(1.5,1.7),(1.51,1)}
+ \point{(2.49,1),(2.5,1.7),(3,2),(3.5,1.7),(3.51,1)}
+ \end{mfpic}
+\end{mfpfig}
+
+A word about the labels: we turned off \opt{mplabels} with the command
+\verb$\nomplabels$, because we used a command (\verb$\cs$) defined for
+this document and not known to basic \TeX{} or \LaTeX. The labels
+therefore are positioned by \LaTeX{} while it assembles this document,
+instead of by \MP{} which would call a separate instance of \TeX{} or
+\LaTeX{} where \cs{cs} was unknown. We could have kept \opt{mplabels},
+provided we had used \verb$\mfpverbtex$ to write the appropriate
+\LaTeX{} preamble to the \file{.mp} output. It would need to be some
+subset of the preamble of this document.
+
+
+\chapter*{Appendices}
+\addcontentsline{toc}{section}{Appendices}
+
+In addition to \pdfLaTeX, \Mfp{} works with plain \pdfTeX, \LaTeX, and
+plain \TeX{}. Instead of \MP{} as the figure processor, \MF{} can also
+be used. Let's start with the difference between using \mfp{} in a
+plain~\TeX{} document and using it in a \LaTeX{} document.
+
+\renewcommand\thesubsection{\Alph{subsection}}
+
+\section{\Mfp{} in plain \TeX}
+
+Here is a sample plain \pdfTeX{} document with results the same as our
+first ``Hello, world'' example. Let's call this file \file{plfirst}
+\begin{verbatim}
+\input mfpic
+ \usemetapost
+\opengraphsfile{myfigs}
+ My first figure:
+ \mfpic[72]{-1}{1}{-1}{1}
+ \ellipse{(0,0),1,.5}
+ \endmfpic
+\closegraphsfile
+\end
+\end{verbatim}
+The main difference is the lack of \LaTeX{} commands. The crucial
+difference is in the first two lines. There we simply
+\verb$\input mfpic$ and we turn on \MP{} support with the
+\verb$\usemetapost$ command instead of an option to \verb$\usepackage$.
+
+Since \verb$\usepackage$ and its options don't exist in plain \TeX{},
+all those features that we select with options in \LaTeX{} must be
+selected by some command in plain. For example, the \opt{mplabels}
+option is replaced with the command \verb$\usemplabels$ (which can also
+be used in \LaTeX).
+
+Also, plain \TeX{} doesn't have environments, so instead of
+\verb$\begin{mfpic}$ we just use \verb$\mfpic$ and instead of
+\verb$\end{mfpic}$ we use \verb$\endmfpic$.
+
+The external processing is essentially the same:
+\begin{verbatim}
+pdftex plfirst
+mpost myfigs
+pdftex plfirst
+\end{verbatim}
+should produce \texttt{plfirst.pdf} with the same picture of an ellipse.
+
+
+\section{\Mfp{} without PDF}
+
+If we wish to use nonPDF versions of \LaTeX{} or plain \TeX, the only
+difference is in the processing steps. To process \file{first.tex} with
+\LaTeX, run the command
+\begin{verbatim}
+latex first
+\end{verbatim}
+followed by
+\begin{verbatim}
+mpost myfigs
+\end{verbatim}
+followed by latex again.
+\begin{verbatim}
+latex first
+\end{verbatim}
+Then run the dvi processor of your choice. It should be one that can
+successfully handle eps figures (or at least the simple eps produced by
+\MP). Certainly \prog{dvips} can do it:
+\begin{verbatim}
+dvips first
+\end{verbatim}
+will produce \file{first.ps}. The file{.ps} file can be viewed with
+\prog{gsview} or printed, or converted to PDF with some distillation
+program like \prog{ps2pdf}. Also \prog{dvipdfm} (if properly
+configured) can be used convert the \file{.dvi} file to PDF.
+
+\section{\Mfp{} without \MP}
+
+\Mfp{} can produce figures using \MF{} instead of \MP. What it does is
+work with \MF{} to produce a made-to-order font, where each picture is a
+large character in that font.
+
+Since \pdfTeX{} and \pdfLaTeX{} do not work well with the fonts produced
+by \MF, and many PDF viewers don't display them well anyway, I do not
+recommend using \mfp{} to produce PDF without turning on \MP{} support.
+However, all dvi viewers and \prog{dvips} \emph{do} work well with such
+fonts, so it can make sense to use \mfp{} with \MF{} \emph{if} you don't
+need the features that \MP{} enables: color and rotation of labels. One
+advantage of doing this is the smaller number of files produced. If
+there are 100 \mfp{} figures in a document, \MP{} produces 100 files
+(apart from a couple of temporary files and the \file{.log} file), but
+the \MF{} procedure produces only four files no matter how many figures
+are present.
+
+To use \mfp{} without \MP{}, omit the \opt{metapost} option or the
+\verb$\usemetapost$ command. If you want a visible reminder of the fact
+that \MF{} is being used, you can use the \opt{metafont} option or the
+\verb$\usemetafont$ command. Of course, you may not use \opt{mplabels}
+without \MP. You may use the color commands and options, but the only
+colors actually produced will be black and white (and occasionally a
+pattern of pixels that simulate gray). The processing steps are
+different. After
+\begin{ex}
+\texttt{latex first} \quad(or \texttt{tex plfirst})
+\end{ex}
+run \MF:
+\begin{ex}
+ \texttt{mf myfigs}
+\end{ex}
+This should produce three files: \texttt{myfigs.log},
+\texttt{myfigs.tfm}, and \texttt{myfigs.600gf}. The last one (which
+might have a different number on your system) is called a \emph{generic
+font} (GF) file and contains the bitmap descriptions. If the file
+produced is \texttt{myfigs.2602gf}, and the \file{.tfm} is not produced,
+that indicates a configuration problem with your system that we'll get
+to later. If this did work, one needs to convert the GF file to a
+PK font file, the standard format for bitmap fonts in the \TeX{} world.
+This may be done with
+\begin{ex}
+ \texttt{gftopk myfigs.600gf}
+\end{ex}
+Some systems may require you to name the output file on the command
+line:
+\begin{ex}
+ \texttt{gftopk myfigs.600gf myfigs.600pk}
+\end{ex}
+And some systems may require the extension to be simply \file{.pk}:
+\begin{ex}
+ \texttt{gftopk myfigs.600gf myfigs.pk}
+\end{ex}
+Finally, some systems may have a \prog{makepk} or \prog{mktexpk} command
+that can be used in place of the combination of \MF{} and \prog{gftopk}.
+You'll have to check what your system has and what its usage might be,
+and what it might do with the PK file produced.
+
+After the above, one again runs `\texttt{latex first}' (or `\texttt{tex
+plfirst}'), and then the \file{.dvi} can be viewed or processed with dvips.
+The two files \file{myfigs.log} and \file{myfigs.600gf} can be deleted;
+only \file{myfigs.tfm} and \file{myfigs.600pk} are needed. If the viewed
+image shows the pictures at a far different size than you expect, this can
+also indicate a configuration problem.
+
+Some systems permit on-the-fly creation of PK files by various
+\file{.dvi} processing programs. It is not wise to allow this to happen
+when working with \mfp. The problem is that this automatic creation
+process is \emph{not} repeated when a figure is edited unless the old PK
+files are deleted, and it may take some hunting to even locate them. One
+should \emph{always} follow the \MF{} step with the \prog{gftopk} step.
+You might even want to write a batch script or makefile to ensure that
+this happens.
+
+Another problem (more an annoyance) that can occur comes from the
+behavior of most dvi viewers: most will reload a \file{.dvi} file if
+they detect that it has changed (or if asked to), but none that I know
+of will reload any fonts even if they have changed. So if one is going
+through a edit-compile-view cycle involving \mfp{} figures, one usually
+has to close the viewer and open it again before one can see changes
+that were made in the figures after starting the viewer. It is also
+possible that PK fonts are cached and shared by other programs, so you
+may need to close other programs to ensure the cache is cleared and the
+new figures loaded.
+
+\section{\MF{} configuration problems}
+
+To diagnose these problems it important to know something about
+\emph{printer modes}. \CMF{} produces bitmap images of characters. This
+means a description of a block of pixels, telling which ones are black
+and which are white. If the description says that 60 pixels in a row are
+black, that produces a thin black line. How long that line is depends on
+the size of a printer's pixels. For the LaserJet IV, there are 600
+pixels to the inch, so 60 pixels makes 1/10 of an inch. The LaserJet~II,
+however, has 300 pixels to the inch, so 60 pixels is 1/5 of an inch
+long. What \MF{} needs in order to produce an image that is the correct
+size is (at a minimum) the \emph{resolution} of the intended printer.
+This is typically reported in DPI (dots per inch) and \MF{} keeps the
+value in the variable \mfc{pixels_per_inch}.
+
+As part of the configuration of your DVI viewer or of \prog{dvips} you
+may have needed to select a printer from a list, or edit a line in some
+configuration file (e.g., \file{config.ps}). What was going on then was
+the assigning of a default \MF{} printer mode. There is a file on most
+\TeX{} systems named \file{modes.mf} which assigns symbolic names to a
+set of parameters that enable \MF{} to tune its output to a particular
+printer. For example, the LaserJet~IV is given the name
+`\texttt{ljfour}' and that name is associated with the value 600 for
+\mfc{pixels_per_inch}. In order to tell \MF{} to make output for the
+LaserJet~IV, one can put that information on the command line:
+\begin{ex}
+ \texttt{mf \cs{mode}:=ljfour; input myfigs}
+\end{ex}
+Your operating system or \TeX{} distribution may require you to quote
+the backslash in the above command.
+
+There is a system for making the selection of the correct mode
+semi-automatic, not requiring a command line specification. Near the end
+of \file{modes.mf} is a line similar to
+\begin{ex}
+ \mfc{localfont:=ljfour;}
+\end{ex}
+This is intended to equate the symbolic name \mfc{localfont} with the
+user's default printer. If the LaserJet~IV is your default printer, the
+line above would be the correct one. If it is not, then that line should
+be changed. This can be done with an ordinary text editor, or your
+\TeX{} system may have a configuration utility to take care of it.
+
+If you say ``\texttt{mf myfigs}'' on an \mfp{} file \file{myfigs.mf}, \mfp's
+internal code will detect that no mode was defined on the command line.
+It will then check if \mfc{localfont} is defined and if so, use that for
+the printer mode. If that fails, it will try to select \mfc{ljfour}.
+If even that is unknown, \mfp{} will define its own generic 600 DPI mode.
+
+\Mfp{} doesn't need to know all the parameters associated to a printer
+mode, only the value of \mfc{pixels_per_inch}. If you get a GF file that
+indicates an incorrect DPI value for your printer, you should arrange
+for the line in \file{modes.mf} that sets \mfc{localfont} to be
+corrected. At the very least it should equate \mfc{localfont} to a name
+defined in \file{modes.mf} and associated to a printer with the same DPI
+as yours. After changing \file{modes.mf}, you need to run whatever
+programs your \TeX{} system requires to remake the \MF{} format.
+
+\end{document}
diff --git a/graphics/mfpic/doc/mfpic-doc.pdf b/graphics/mfpic/doc/mfpic-doc.pdf
new file mode 100644
index 0000000000..58105a908d
--- /dev/null
+++ b/graphics/mfpic/doc/mfpic-doc.pdf
Binary files differ
diff --git a/graphics/mfpic/doc/mfpic-doc.tex b/graphics/mfpic/doc/mfpic-doc.tex
new file mode 100644
index 0000000000..603a98e59d
--- /dev/null
+++ b/graphics/mfpic/doc/mfpic-doc.tex
@@ -0,0 +1,7575 @@
+% File: mfpic-doc.tex
+% A part of mfpic 1.10 2012/12/03
+%
+% Documentation of mfpic macros
+\documentclass[letterpaper]{article}
+
+% Fonts:
+% Body text: TimesRoman,
+% Titles: CM Sans serif,
+% Typewriter: LuxiMono.
+\usepackage[T1]{fontenc}
+\usepackage{mathptmx}
+\usepackage[scaled]{luximono}
+\renewcommand\sfdefault{cmss}
+% Fake chapters (really sections):
+\usepackage[chapters]{mfpdoc}
+\pagestyle{mfpdoc}
+
+\newcommand\sgn{\mathop{\mathrm{sgn}}\nolimits}
+
+\usepackage{makeidx}
+\makeindex
+
+\usepackage{graphics}
+
+\ifpdf
+\expandafter\usepackage\expandafter
+ [\mfpHyOpts,pdfpagelabels=true,hyperindex]{hyperref}
+\expandafter\pdfstringdefDisableCommands\expandafter
+ {\mfpHyDisable}
+\fi
+
+\stepcounter{secnumdepth}
+
+\title{\Mfp{}: Pictures in \TeX{}\\ with Metafont and
+MetaPost\thanks{Copywrite 2002--2012, Daniel H. Luecking}}
+
+
+\author{%
+Daniel H. Luecking%
+ \thanks{\email {luecking@uark.edu}: Communications regarding \mfp{}
+ should be sent to this author. Any first-person references in this
+ manual refer to Dr.~Luecking.}
+\and Thomas E. Leathrum
+\and Geoffrey Tobin}
+
+\date{\mfpfiledate}
+
+\begin{document}
+
+\pagenumbering{roman}
+\maketitle
+\tableofcontents
+
+\clearpage
+\pagenumbering{arabic}
+
+\chapter{Introduction}\label{introduction}
+\thispagestyle{plain}
+
+
+\section{Why?}\label{why}
+
+Tom got the idea for \mfp{}%
+ \footnote{`\Mfp{}' is pronounced by spelling the first two letters:
+ `em-eff-pick'.}
+mostly out of a feeling of frustration. Different output mechanisms for
+printing or viewing \TeX{} DVI files each have their own ways to include
+pictures. More often than not, there are provisions for including
+graphic objects into a \prog{DVI} file using \TeX{} \cs{special}'s.
+However, this technique seemed far from \TeX{}'s ideal of device
+independence because different \TeX{} output drivers recognize different
+\cs{special's}, and handle them in different ways.
+
+\LaTeX{}'s \env{picture} environment has a hopelessly limited supply of
+available objects to draw---if you want to draw a graph of a polynomial
+curve, you're out of luck.
+
+There was, of course, \PiCTeX{}, which was wonderfully flexible and
+general, but its most obvious feature was its speed---or rather lack of
+it. Processing a single picture in \PiCTeX{} (in those days) could often
+take several seconds.
+
+It occurred to Tom that it might be possible to take advantage of the
+fact that \MF{} is \emph{designed} for drawing things. The result of
+pursuing this idea was \mfp{}, a set of macros for \TeX{} and
+\MF{} which incorporate \MF{}-drawn pictures into a \TeX{} file.
+
+With the creation of \MP{} by John Hobby, and the almost universal
+availability of free \PS{} interpreters like \GS, some \mfp{} users
+wanted to run their \mfp{} output through \MP{}, to produce \PS{}
+pictures. Moreover, users wanted to be able to use \pdfTeX{}, which did
+not get along well with PK fonts, but was quite happy with \MP{}
+pictures. So \MP{} support was added to \mfp{}. This got us a little bit
+away from device independence, but many users were not much concerned
+with that: they just wanted a convenient way to have text and pictures
+described in the same document file.
+
+With the extra capabilities of \PS{} (e.g., color) and the corresponding
+abilities of \MP{}, there was a demand for some \mfp{} interface to
+access them. Consequently, switches (options) have been added to access
+some of them. When these are used, output files may no longer be
+compatible with \MF{}.
+
+
+\section{Who?}\label{author}
+
+The original \mfp{} (and still the core of the current version) was written
+primarily by Tom Leathrum during the late (northern hemisphere) spring
+and summer of 1992, while at Dartmouth College. Different versions were
+being written and tested for nearly two years after that, during which
+time Tom finished his Ph.D. and took a job at Berry College, in Rome,
+GA. Between fall of 1992 and fall of 1993, much of the development was
+carried out by others. Those who helped most in this process are
+credited in the Acknowledgements.
+
+Somewhere in the mid 1990's the development passed to Geoffrey Tobin who
+kept things going for several years.
+
+The addition of \MP{} support was carried out by Dan Luecking around
+1997--99. He is also responsible for all other additions and changes
+since then, with help from Geoffrey and a few others mentioned in the
+Acknowledgements.
+
+
+\section{What?}\label{manifest}
+
+See the \file{README} file for a list of files in the distribution and a
+brief explanation of each. Only three are actually needed for full access
+to \mfp{}'s capabilities: \file{mfpic.dtx}, \file{mfpic.ins} and
+\file{grafbase.dtx}. Running \LaTeX{} on
+\file{mfpic.ins} creates the only required files:
+\begin{display}
+ \file{mfpic.tex} and \file{mfpic.sty}, the latter required only for
+ \LaTeX{}.\\
+ \file{grafbase.mf}, required only if \MF{} will be processing
+ figures.\\
+ \file{grafbase.mp}, \file{dvipsnam.mp} and \file{mfpicdef.tex}, needed
+ only if \MP{} will be the processor.
+\end{display}
+The README file also gives some guidence on the proper location for the
+installation of these files.
+
+
+\section{How?}\label{process}
+
+Some guidance on writing files that contain \mfp{} figures can be found
+in the accompanying file \file{mfpguide.pdf}. If you use \mfp{} to
+produce \MP{} figures the process is straightforward: run \TeX{} (or
+\LaTeX), then \MP{}, then \TeX{} again. If there are no errors, then
+\prog{dvips} or other DVI-to-PS converter can be run to produce
+viewable\slash printable output. You can also run \prog{dvipdfm(x)} to obtain PDF
+output, or even use \pdfTeX{} instead of \TeX{} (or \pdfLaTeX{} instead
+of \LaTeX{}) to get PDF output directly.
+
+Here is an example of the process: for the sample file
+\file{pictures.tex}, first run \TeX{} on it (or run \LaTeX{} on
+\file{lapictures.tex}). You may see a message from \mfp{} that there is
+no file \file{pics.1}, but \TeX{} will continue processing the file
+anyway. When \TeX{} is finished, you will now have a file called
+\file{pics.mp}. This is the \MP{} file containing the descriptions of
+the pictures for \file{pictures.tex}. You need to run \MP{} on
+\file{pics.mp} (Read your \MP{} manual to see how to do
+this.%
+ \footnote{The document \textit{Some experiences on running Metafont
+ and MetaPost}, by Peter Wilson, can be useful for beginners. Fetch
+ \file{CTAN/info/metafp.pdf}. `\file{CTAN}' means the Comprehensive
+ \TeX{} Archive Network. You can find the mirror nearest you by
+ pointing your browser at \url{http://www.ctan.org/}\,.}) %
+Typically, you just type
+\begin{verbatim}
+mpost pics.mp
+\end{verbatim}
+
+This usually produces files named%
+ \footnote{Recent \MP{} allows one to change the default names of the
+ output files. Current \mfp{} provides an interface to that
+ capability: see \cs{setfilenametemplate} on page
+ \pageref{setfilenametemplate}.}
+\file{pics.1}, \file{pics.2}, etc., the number of files depending on the
+version of \file{pictures.tex}. You then reprocess \file{pictures.tex}
+with \TeX{} to produce a DVI file. This file can then be processed with
+\prog{dvips} (for example) to produce \PS{} output which can be printed
+or viewed. One can also process the DVI with \prog{dvipdfm(x)} to
+produce a PDF file.
+
+If \pdfTeX{} is used instead of \TeX{} on the second run, you should be
+able to view the resulting PDF file immediately, without any further
+processing.
+
+If instead you use \mfp{} to produce \MF{} figures, things are a little
+less straightforward. The process is \TeX{}, then \MF{}, then
+\prog{gftopk}, then \TeX{} again. After this, \TeX{}'s DVI output ought
+to be viewable and printable by most DVI viewers or printer drivers. For
+a few \TeX{} systems there may be some prior setup needed. One needs to
+convince \TeX{} and its output drivers to find \MF{}'s output files. You
+should do whatever is necessary (perhaps nothing!) to insure that \TeX{}
+looks in the current directory for \file{.tfm} files, and that your DVI
+drivers look in the current directory for \file{.pk} files. There may
+also be some setup needed to ensure that the \file{.pk} files are
+created at a resolution that matches that of your printer and of your
+DVI viewer. See the discussion in \file{mfpguide.pdf}.
+
+If you want to test this process on the supplied sample files, edit
+\file{pictures.tex} removing the \cs{usemetapost} command (or edit
+\file{lapictures.tex}, removing the \opt{metapost} option). After that,
+run \TeX{} on \file{pictures.tex} (or run \LaTeX{} on
+\file{lapictures.tex}). You may see a message from \mfp{} that there is
+no file \file{pics.tfm}, but \TeX{} will continue processing the file.
+When \TeX{} is finished, you will now have a file called \file{pics.mf}.
+This is the \MF{} file containing the descriptions of the pictures for
+\file{pictures.tex}. You need to run \MF{} on \file{pics.mf}, with
+\texttt{mode:=localfont} set up.
+(Read your \MF{} manual to see how to do this.%
+ \footnote{If you are new to running \MF{}, the document
+ \textit{Metafont for Beginners}, by Geoffrey~Tobin, is a good
+ start. Fetch \file{CTAN/info/metafont-for-beginners.tex}.}) %
+Typically, you just type
+\begin{verbatim}
+mf pics.mf
+\end{verbatim}
+or, to use a particular printer mode such as \texttt{ljfour}, possibly
+something like
+\begin{verbatim}
+mf '\mode:=ljfour; input pics.mf'
+\end{verbatim}
+This produces a \file{pics.tfm} file and a GF file with a name something
+like \file{pics.600gf}. The actual number may be different and the
+extension may get truncated on some file systems. Then you run
+\prog{gftopk} on the GF file to produce a PK font file. (Read your
+\prog{gftopk} manual on how to do this.) Typically, you just run
+\begin{verbatim}
+gftopk pics.600gf
+\end{verbatim}
+(or possibly ``\verb$gftopk pics.600gf pics.600pk$'' or
+``\verb$gftopk pics.600gf pics.pk$'').
+
+Now that you have the font (the \file{.pk} file) and font metric file (the
+\file{.tfm}) generated by \MF{}, reprocess the file \file{pictures.tex}
+with \TeX{}. The resulting DVI file should now be complete, and you should
+be able to print and view it at your computer (assuming your viewer and
+print driver have been set up to be able to find the PK font generated
+from \file{pics.mf}).
+
+It is not advisable to rely on automatic font generation to create the
+\file{.tfm} and \file{.pk} files. (Different systems do this in
+different ways, so here I will try to give a generic explanation.) The
+reason: later editing of a figure will require new files to be built,
+and most automatic systems will \emph{not} remake the files once they
+have been created. This is not so much a problem with the \file{.tfm},
+because \mfp{} never tries to load the font if the \file{.tfm} is absent
+and therefore no automatic \file{.tfm}-making should ever be triggered.
+However, if you forget to run \prog{gftopk}, then try to view your
+resulting file, you may have to search your system and delete some
+automatically generated \file{.pk} file (they can turn up in far-away
+places) before you can see any later changes. It might be wise to write
+a shell script (batch file) that runs both \MF{} and \prog{gftopk}. It
+should also do some error checking and delete the \file{.tfm} if the
+\file{.pk} file is not produced. That way, if anything goes wrong, the
+\file{.dvi} will not contain the font (\mfp{} will draw a rectangle and
+the figure number in place of the figure).
+
+These processing steps---processing with \TeX{}, processing with
+\MF{}\slash\prog{gftopk} or \MP{}, and reprocessing with \TeX{}---may not always be
+necessary. In particular, if you change the \TeX{} document without
+making any changes at all to the pictures, then there will be no need to
+repeat the \MF{} or \MP{} steps.
+
+There are also somewhat subtle circumstance under which you can skip the
+second \TeX{} step after editing a figure if the file has already gone
+through the above process. Delineating the exact cirumstances is rather
+involved, so it is recommended that you always repeat the \TeX{} step if
+you have made changes that affect any figure.
+
+What makes \mfp{} work? When you run \TeX{} on the file
+\file{pictures.tex}, the \mfp{} macros issue \TeX{} \cs{write} commands,
+writing \MF{} (or \MP{}) commands to a file \file{pics.mf} (or
+\file{pics.mp}). The user should never have to read or change the file
+\file{pics.mf} directly---the \mfp{} macros take care of it.
+
+The enterprising user can determine by examining the \mfp{} source and
+the resulting \file{.mf} or \file{.mp} file, that \mfp{} drawing macros
+translate almost directly into similar \MF{}\slash\MP{} commands,
+defined in one of the files \file{grafbase.mf} or \file{grafbase.mp}.
+The labels and captions, however, are placed on the graph by \TeX{}
+using box placement techniques similar to those used in \LaTeX{}'s
+\env{picture} environment (except when option \opt{mplabels} is in
+effect, in which case the labels are written to the \file{.mp} file and
+handled by \MP{}).
+
+\smallskip
+\emph{Note}: In this manual, when describing \mfp{} operations, we will
+often refer to `\MF{}' when we really mean ``\MF{} or \MP{}''. This
+will especially be the case whenever we need to refer to commands in the
+two languages which are substantially the same, but occasionally we will
+even talk about ``running \MF{}'' when we mean running one or the other
+program \texttt{mf} or \texttt{mpost} to process the figures. If we need
+to discriminate between the two processors, (for example when they have
+different behavior) we will make the difference explicit.
+
+A similar shorthand is used when referring to `\TeX{}'. It should not be
+taken to mean ``plain \TeX{}'', but rather whatever version of \TeX{} is used
+to process the source file: plain \TeX{}, \LaTeX{}, \pdfTeX{}, or
+\pdfLaTeX{}. Also \AmSTeX{}, \prog{eplain} and some other variants. When
+last tried, \mfp{} didn't work with \ConTeXt{}.
+
+\clearpage
+\chapter{Options.}\label{options}
+
+There are several options to the \mfp{} package. These options can be
+turned on with certain provided commands, but under \LaTeX{} they can
+also be used in the standard \LaTeX{} \cs{usepackage} optional argument.
+Some options can be switched off and on throughout the document. Here we
+merely list them and provide a general description of their purpose.
+More details may be found later in the discussion of the features
+affected. The headings below give the option name, the alternative macro
+and, if available, the command for turning off the option. Any option
+in the \cs{usepackage} command not among those given below will be
+passed on to the \prog{graphics} package, provided the \opt{metapost}
+option has been used.
+
+If the file \file{mfpic.cfg} exists, it will be input just before all
+options are processed. You can create such a file containing an
+\cs{ExecuteOptions} command to execute any options you would like to
+have as default. Actual options to \cs{usepackage} will override these
+defaults, of course. And so will any of the commands below.
+
+Finally, if a file named \file{mfpic.usr} can be found, it will be input
+at the end of the loading of \mfp{}. The user can create such a file
+containing any of the commands of this section that he would like to
+have as default, plus any other \TeX{} code.
+
+
+\section{\opt{metapost}, \opt{metafont}, \cs{usemetapost}, \cs{usemetafont}.}%
+\label{metapost}\index{metapost@\opt{metapost}}\index{usemetapost@\cs{usemetapost}}%
+\index{metafont@\opt{metafont}}\index{usemetafont@\cs{usemetafont}}
+
+The option \opt{metapost} or the command \cs{usemetapost} selects \MP{}
+as the figure processor and makes specific features available. It
+changes the extension used on the output file to `\file{.mp}' to signal
+that it can no longer be processed with \MF{}. There is also a
+\opt{metafont} option (command \cs{usemetafont}), but it is redundant,
+as \MF{} is the default (for backward compatibility of files written
+before \MP{} existed). Either command must come before the
+\cs{opengraphsfile} command (see section~\ref{files}). They should not
+be used together in the same document. (Actually they can, but one needs
+to close one output file and open another. Moreover, it hasn't ever been
+seriously tested, and it wasn't taken into consideration in writing most
+of the macros.) If the command form \cs{usemetapost} is used in a
+\LaTeXe{} document, it must come in the preamble. Because of the timing
+of actions by the \prog{babel} package and by older versions of
+\file{supp-pdf.tex} (input by \file{pdftex.def} in the \prog{graphics}
+package), when \pdfLaTeX{} is used, \mfp{} should be loaded and
+\cs{usemetapost} (if used) declared before \prog{babel} is loaded.
+
+
+\section{\opt{mplabels}, \cs{usemplabels},
+\cs{nomplabels}.}\label{mplabels}
+\index{mplabels@\opt{mplabels}}%
+\index{usemplabels@\cs{usemplabels}}%
+\index{nomplabels@\cs{nomplabels}}
+
+Causes all label creation commands to write their contents to the output
+file. It effects only labels on the figure, not a caption added by the
+\cs{tcaption} command (see section~\ref{text}). In this case labels are
+handled by \MP{} and can be rotated. It requires \MP{}, and will be be
+ignored without it (\MF{} cannot handle labels). Using this option
+without the \opt{metapost} option may also produce an error message
+either from \TeX{} or \MF{}. The command forms can be placed anywhere.
+If used outside an mfpic environment, they affect all subsequent
+\cs{tlabel} commands; inside an mfpic environment they affect all
+\cs{tlabel} commands in that figure.
+
+When this is in effect, the labels become part of the figure and, in the
+default handling, they may be clipped off or covered up by later drawing
+elements. But see the next section on the \opt{overlaylabels} option.
+Labels added to a picture contribute to the bounding box even if
+\opt{truebbox} is not in effect.
+
+The user is responsible for adding the appropriate \mfc{verbatimtex}
+header to the output file if necessary. For this purpose, there is the
+\cs{mfpverbtex} command, see section~\ref{labels}. If the label text
+contains only valid plain \TeX{} macros, there is generally no need for
+a \mfc{verbatimtex} preamble at all. If you add a \mfc{verbatimtex}
+preamble of \LaTeX{} code take care to make sure \MP{} calls \LaTeX{}
+(for example, the \texttt{mpost} command may take an option for this
+purpose, or an environmental variable named \texttt{TEX} may be set
+equal to \texttt{latex} in the command shell of your operating system.).
+
+
+\section{\opt{overlaylabels}, \cs{overlaylabels}, \cs{nooverlaylabels}.}
+\label{overlaylabels}
+\index{overlaylabels@\opt{overlaylabels}}%
+\index{overlaylabels@\cs{overlaylabels}}%
+\index{nooverlaylabels@\cs{nooverlaylabels}}
+
+In the past, under \opt{mplabels} all text labels created by \cs{tlabel}
+and its relatives were added to the picture by \MP{} \emph{as they
+occurred}. This made them subject to later drawing commands: they could
+be covered up, erased, or clipped. With this option (or after the
+command \cs{overlaylabels}) text labels are saved in a separate place
+from the rest of a picture. When a picture is completed, the labels that
+were saved are added on top of it. This is the way labels always behave
+under the \opt{metafont} option, because then \TeX{} must add the labels
+and there is no possibility for special effects involving clipping or
+erasing (at the \MF{} level).
+
+With the \opt{metapost} option, but without \opt{mplabels} it has been
+decided to keep the same behavior (and the same code) as under the
+\opt{metafont} option. However, when \opt{mplabels} is used, there is
+the possibility for special effects with text, and it has always been
+the behavior before version 0.7 to simply place the labels as they
+occurred. It turns out that placing the labels at the end is cleaner and
+simpler to code, so I experimented with it and rejected it as a default,
+but now offer it as an option. With this option, \mfp{} labels have
+almost the same behavior with or without \opt{mplabels}.
+
+The commands may be used anywhere. Outside a figure they affect all
+subsequent figures, inside a figure they affect all subsequent text in
+that figure. The commands and option are ignored under the metafont
+option.
+
+
+\section{\opt{truebbox}, \cs{usetruebbox}, \cs{notruebbox}.}%
+\label{truebbox}%
+\index{truebbox@\opt{truebbox}}%
+\index{usetruebbox@\cs{usetruebbox}}%
+\index{notruebbox@\cs{notruebbox}}
+
+Normally \MP{} outputs an EPS file with the actual bounding box of the
+figure. By default, \mfp{} \emph{overrides} this and sets the bounding
+box to the dimensions specified by the \cs{mfpic} command that produced
+it. (This used to be needed for \TeX{} is to handle \cs{tlabel} commands
+correctly. Now, it is just for backward compatability, and for
+compatability with \MF{}'s behavior.) It is reasonable to let \MP{} have
+its way, and that is what this option does. If one of the command forms
+is used in an \env{mfpic} environment, it affects only that environment,
+otherwise it affects all subsequent figures. This option currently has
+no effect with \MF{}, but should cause no errors.
+
+This option is almost mandatory if you wish to use \prog{dvipdfm(x)} to
+convert \TeX{}'s DVI output to PDF. Both \prog{dvipdfm} and
+\prog{dvipdfmx} have a tendency to clip \MP{} figures to the stated
+bounding box. Thus, anything running outside those bounds is lost.
+
+
+\section{\opt{clip}, \cs{clipmfpic}, \cs{noclipmfpic}.}\label{clip}
+\index{clip@\opt{clip}}%
+\index{clipmfpic@\cs{clipmfpic}}%
+\index{noclipmfpic@\cs{noclipmfpic}}
+
+The \opt{clip} option causes all parts of the figure outside the
+rectangle specified by the \cs{mfpic} command to be removed. The
+commands can come anywhere. If issued inside an \env{mfpic} environment
+they affect the current figure only. Otherwise all subsequent figures
+are affected. Note: this is a rather rudimentary option. It has an often
+unexpected interaction with truebbox. When both are in effect, \MP{}
+will produce a bounding box that is the intersection of two rectangles:
+the true one \emph{without clipping}, and the clipping rectangle (i.e.,
+the one specified in the \cs{mfpic} command). It is possible for the
+actual figure to be much smaller than this bounding box (even empty!).
+This is a property of the \MP{} \gbc{clip} command and we know of no way
+to avoid it.
+
+
+\section{\opt{centeredcaptions}, \cs{usecenteredcaptions},
+\cs{nocenteredcaptions}.}\label{centeredcaptions}
+\index{centeredcaptions@\opt{centeredcaptions}}%
+\index{usecenteredcaptions@\cs{usecenteredcaptions}}%
+\index{nocenteredcaptions@\cs{nocenteredcaptions}}
+
+The \opt{centeredcaptions} option causes multiline captions created by
+\cs{tcaption} to have all lines centered. This has no effect on the
+normal \LaTeX{} \cs{caption} command.%
+ \footnote{This writer [DHL] feels that \cs{tcaption} is too limited
+ and users ought to apply the caption by other means, such as
+ \LaTeX{}'s \cs{caption} command, outside the \env{mfpic}
+ environment.}%
+
+The commands can be issued anywhere. If inside an \env{mfpic}
+environment they should come before the \cs{tcaption} command and affect
+only it, otherwise they affect all subsequent figures. They should not
+be used in the argument of a \cs{tcaption} command.
+
+
+\section{\opt{raggedcaptions}, \cs{useraggedcaptions},
+\cs{noraggedcaptions}.}\label{raggedcaptions}
+\index{raggedcaptions@\opt{raggedcaptions}}%
+\index{useraggedcaptions@\cs{useraggedcaptions}}%
+\index{noraggedcaptions@\cs{noraggedcaptions}}
+
+The \opt{raggedcaptions} option causes multiline captions created by
+\cs{tcaption} to have all lines ragged\-right. If \opt{centeredcaptions}
+is on, both sides will be ragged. This option can be turned off with the
+command \cs{noraggedcaptions}. This is the default: to have all lines
+except the last justified. The last line is either centered or flush
+left according to whether \opt{centeredcaptions} is on or off.
+
+The commands can be issued anywhere. If inside an \env{mfpic}
+environment they should come before the \cs{tcaption} command and affect
+only it, otherwise they affect all subsequent figures. They should not
+be used in the argument of a \cs{tcaption} command.
+
+
+\section{\opt{debug}, \cs{mfpicdebugtrue},
+\cs{mfpicdebugfalse}.}\label{debug}
+\index{debug@\opt{debug}}%
+\index{mfpicdebugtrue@\cs{mfpicdebugtrue}}%
+\index{mfpicdebugfalse@\cs{mfpicdebugfalse}}
+
+The \opt{debug} option causes \mfp{} to write a rather large amount of
+information to the \file{.log} file and sometimes to the terminal. Debug
+information generated by \file{mfpic.tex} \emph{while loading} is
+probably of interest only to developers, but can be turned on by giving
+a definition to the command \cs{mfpicdebug} prior to loading. Any
+definition will work because \prog{mfpic} only checks whether it is
+defined.
+
+
+\section{\opt{clearsymbols}, \cs{clearsymbols}, \cs{noclearsymbols}.}
+\index{clearsymbols@\opt{clearsymbols}}%
+\index{clearsymbols@\cs{clearsymbols}}%
+\index{noclearsymbols@\cs{noclearsymbols}}
+
+\Mfp{} has two commands, \cs{point} and \cs{plotsymbol} that place a
+small symbol at each of a list of points. The first can place either a
+small filled disk or an open disk, the choice being dictated by the
+setting of the boolean \cs{pointfilltrue} or \cs{pointfillfalse}. The
+behavior of \cs{point} in the case of \cs{pointfillfalse} is to erase the
+interior of the disk in addition to drawing its circumference.
+
+The second command \cs{plotsymbol} can place a variety of shapes, some
+open, some not. Its behavior before version 0.7 was to always draw the
+shape without erasing the interior. Two other commands that placed these
+symbols, \cs{plotnodes} and \cs{plot}, had the same behavior. With this
+option, two of these, \cs{plotsymbol} and \cs{plotnodes}, will erase the
+interior of the open symbols before drawing them. Thus
+\cs{plotsymbol}\marg{SolidCircle} still works just like
+\cs{pointfilltrue}\cs{point}, and now with this option
+\cs{plotsymbol}\marg{Circle} behaves the same as
+\cs{pointfillfalse}\cs{point}. The \cs{plot} command is unaffected by
+this option.
+
+
+\section{\opt{draft}, \opt{final}, \opt{nowrite}, \cs{mfpicdraft},
+ \cs{mfpicfinal}, \cs{mfpicnowrite}.}\label{draft}
+\index{draft@\opt{draft}}%
+\index{final@\opt{final}}%
+\index{nowrite@\opt{nowrite}}%
+\index{mfpicdraft@\cs{mfpicdraft}}%
+\index{mfpicfinal@\cs{mfpicfinal}}%
+\index{mfpicnowrite@\cs{mfpicnowrite}}
+
+Under the \opt{metapost} option, the various macros that include the
+\EPS{} files emit rather large amounts of confusing error messages when
+the files don't exist (especially in \LaTeX{}). For this reason, before
+each picture is placed, \mfp{} checks for the existence of the graphic
+before trying to include it. However, on some systems checking for the
+existence of a nonexistent file can be very slow because the entire
+\TeX{} search path will need to be checked. Therefore, \mfp{} doesn't
+even attempt any inclusion on the first run. The first run is detected
+by the non-existence of \file{\meta{file}.1}, where \meta{file} is the
+name given in the \cs{opengraphsfile} command (but see also
+section~\ref{files}). These options can be used to override this
+automatic detection. All the command versions \emph{should} come before
+the \cs{opengraphsfile} command. The \cs{mfpicnowrite} command
+\emph{must} come before it.
+
+These options might be used if, for example, the first figure has an
+error and is not created by \MP{}, but you would like \mfp{} to go
+ahead and include the remaining figures. Then use \opt{final}. It can
+also be used to override a \LaTeX{} global \opt{draft} option. Or if
+\file{\meta{file}.1} exists, but other figures still have errors and you
+would like several runs to be treated as first runs until \MP{} has
+stopped issuing error messages, then use \opt{draft}. These commands
+also work under the \opt{metafont} option, but time and error messages
+are less of an issue then. If all the figures have been created and
+debugged, some time might be saved (with either \opt{metafont} or
+\opt{metapost}) by not writing the output file again, then \opt{nowrite}
+can be used.
+
+
+\section{\opt{mfpreadlog}, \cs{mfpreadlog}.}\label{readlog}
+\index{mfpreadlog@\opt{mfpreadlog}}%
+\index{mfpreadlog@\cs{mfpreadlog}}
+
+From version 0.8, there exists a scheme to allow \MF{} or \MP{} to pass
+information back to the \file{.tex} file. This is done by writing code
+to the figure file requesting \MF{} to place that information in the
+\file{.log} file it produces. This option instructs \mfp{} to read
+through that log file line-by-line looking for such information. Since
+such log files can be potentially quite lengthy, this is made an option.
+If the command form \cs{mfpreadlog} is used, it must come before the
+\cs{opengraphsfile} command, since that is when the file will be
+examined. At the present time, the only \mfp{} facility that requires
+this two-way communication is \cs{assignmfvalue} (see
+subsection~\ref{misc}). If this is used, the filename given to
+\cs{opengraphsfile} should not be the same as the \TeX{} source file in
+which this occurs, as then the wrong \file{.log} may be read.
+
+
+\section{Scoping Rules.}\label{scoping}
+
+Some of these options merely change \TeX{} behavior, others write
+information to the output file for \MF{} or \MP{}. Changes in \TeX{}
+behavior obey the normal \TeX{} grouping rules, the information written
+to the output file obeys \MF{} grouping rules. Since each \env{mfpic}
+environment is both a \TeX{} group and (corresponds to) a \MF{} group,
+the following always holds: use of one of the command forms inside of an
+\env{mfpic} environment makes the change local to that environment.
+
+An effort has been made (as of version 0.7) to make this universal. That
+is, any of the commands listed above for turning options on and off will
+be global when issued outside an \env{mfpic} environment. The debug
+commands are exceptions; they obey all \TeX{} scoping rules.
+
+We have also tried to make all other \mfp{} commands for changing the
+various parameters follow this rule: local inside \env{mfpic}
+environment, global outside. If this is ever untrue, and I don't
+document that fact, please let me know.
+
+The following are special:
+\begin{display}
+ \cs{usemetapost}\index{usemetapost@\cs{usemetapost}},
+ \cs{usemetafont}\index{usemetafont@\cs{usemetafont}},
+ \cs{mfpicdraft}\index{mfpicdraft@\cs{mfpicdraft}},
+ \cs{mfpicfinal}\index{mfpicfinal@\cs{mfpicfinal}},
+ \cs{mfpicnowrite}\index{mfpicnowrite@\cs{mfpicnowrite}},\\
+ and \cs{mfpreadlog}\index{mfpreadlog@\cs{mfpreadlog}}.
+\end{display}
+\noindent Their effects are always global, partly because they should
+occur prior to the initialization command \cs{opengraphsfile} (described
+in section~\ref{files}). Note that \cs{usemetapost} may cause a file of
+graphic inclusion macros to be input. If this command is issued inside a
+group, some definitions in that file may be lost, breaking the graphic
+inclusion code.
+
+
+\clearpage
+\chapter{\CMF{} and \CMP{} Data Types.}\label{types}
+
+Since the arguments of most \mfp{} drawing commands are sent to \MF{} to
+be interpreted, it's useful to know something about \MF{} concepts. In
+this chapter we will discuss some of the data types \MF{} supports.
+Even the casual user should know how coordinates and colors are treated
+and so should at least skim the next two sections. The last
+section can be read when the user wants to manipulate more complex
+objects.
+
+\CMF{} permits several different data types, and we will mainly be
+concerned with six of these: \kw{numeric}, \kw{pair}, \kw{color} (\MP{}
+only), \kw{path}, \kw{picture} and \kw{boolean}.%
+ \footnote{For the curious, there are a total of eight types (nine or
+ ten for \MP{}). The other three are \kw{string}, \kw{transform} and
+ \kw{pen}. \MF{} also permits expressions that produce nothing, which
+ is sometimes called the vacuous type, but doesn't allow (or need)
+ variables of this type.}
+In \MP{} version 1.000, a tenth data type was added, \kw{cmykcolor}, and
+the \kw{color} data type can be referred to as `\kw{rgbcolor}' if one
+wants to emphasize the distinction.
+
+A \emph{variable} is a symbolic name, which can be a single letter such
+as \mfc{A}, or a descriptive name like \mfc{origin}. Any sequence of
+letters and underscores is permitted as a variable name. Numeric indexes
+are also allowed, provided all variables that differ only in the index
+have the same type. Thus \mfc{A1}, \mfc{A2}, etc., might be variables
+which are all of type \kw{pair}. Quite a lot more is permited for variable
+names, but the rules are rather complex and easy to violate. \Mfp{} has
+commands for creating both simple variables and indexed variables
+(called \emph{arrays}) but the casual user can get quite a lot of use
+out of \mfp{} without ever creating or using a \MF{} variable.
+
+\CMF{} also has something akin to functions. For example, \mfc{sin(1.57)}
+might represent a function named \mfc{sin} receiving the parameter
+$1.57$ as input and returning the appropriate value. Functions
+can take any number of parameters and return any of the data types that
+\MF{} supports.%
+ \footnote{Including the vacuous type.}
+
+
+\section{Numerics and pairs.}\label{pairs}
+
+\CMF{} has \kw{numeric} quantities. These include lengths, such as the
+radius of a circle, as well as dimension units such as \mfc{in} (inches)
+and \mfc{pt} (points). In fact it understands all the same units that
+\TeX{} does. These \kw{numeric} quantities can be constants (explicit
+numbers) or variables (symbolic names). In fact, \mfc{in} and \mfc{pt}
+are symbolic names for \kw{numeric} quantities.
+
+\CMF{} also has \kw{pair} objects, which may be constants or variables.
+Constants of type \kw{pair} have the form \mfc{($x$,$y$)} where $x$ and
+$y$ are numbers, for example \mfc{(0,0)}. Pairs are two-dimensional
+quantities used for representing either points or vectors in a
+rectangular (Cartesian) coordinate system.
+
+In this manual we often represent each pair by a brief name, such as
+\meta{p} or \meta{v}, the meanings of which are usually obvious in the
+context of the macro. These are intended to be replaced in actual use by
+either a pair constant or variable. The succinctness of this notation
+helps us to think geometrically rather than only of coordinates.
+
+
+\section{Colors.}\label{MPcolors}
+
+\CMP{} has the same concepts as \MF, but also has \kw{color} objects,
+which may also be constants or variables. In recent MP{}, colors come in
+two flavors: \kw{rgbcolor} and \kw{cmykcolor}. Constants of type
+\kw{rgbcolor} have the form \mfc{($r$,$g$,$b$)} where $r$, $g$, and $b$
+are numbers between $0$ and $1$ determining the relative proportions of
+red, green and blue in the color (the `rgb' model). Constants of type
+\kw{cmykcolor} have the form \mfc{($c$,$m$,$y$,$k$)} where $c$, $m$, $y$
+and $k$ are numbers between $0$ and $1$ determining the relative
+proportions of cyan, magenta, yellow and black in the color (the `cmyk'
+model).
+
+A color variable is a name, like \mfc{red}, \mfc{blue} (both predefined
+rgb colors in \MP) or \gbc{magenta} (predefined by \mfp{} to be an rgb
+color if \MP{} has version ${}<1.000$, a cmyk color if the version is at
+least 1.000).
+
+
+\section{Paths, pictures and booleans.}\label{paths}
+
+Most of the things that \mfp{} is designed to draw are paths. Examples
+of paths are circles, rectangles, other polygons, graphs of
+functions and splines. Because we tend to want to draw these (or fill
+them, or render them in other ways) we call the \mfp{} commands that
+produce them \emph{figure macros}. Although they are much more complex
+than numerics, pairs, or colors, they can still be stored in symbolic
+names.
+
+Normally in \mfp{} we want to create a picture, usually by rendering one
+or more paths. It is possible in \MF{} to store a picture in a symbolic
+name without actually drawing it. However, because of their complexity,
+objects of type \kw{picture} require somewhat more care than paths or
+other data types. Do not expect to use stored pictures in the same way
+as stored paths. In fact, one should use \kw{picture} variables only in
+those command that are explicitly designed for them. In \mfp{} to date
+these are only \cs{tile...}\cs{endtile} and \cs{mfpimage} to store
+pictures, and \cs{putmfpimage} to draw copies of one. There is also
+\cs{tess}, but it is used only to fill a region with copies of a picture
+created by \cs{tile}.
+
+The \kw{boolean} data type is one of the values \mfc{true} or
+\mfc{false}. Variables of type \kw{boolean} are symbolic names that can
+take either of these two values. Usually these are used to influence the
+behavior of some command by setting a relevant \kw{boolean} variable to
+one or the other value.
+
+
+\clearpage
+\chapter{The Macros.}\label{macros}
+
+Many of the commands of \mfp{} have optional arguments. These are
+denoted just as in \LaTeX{}, with square brackets. Thus, the command for
+drawing a circle can be given
+\begin{verbatim}
+\circle{(0,0),1}
+\end{verbatim}
+having only the mandatory argument, or
+\begin{verbatim}
+\circle[p]{(0,0),1}
+\end{verbatim}
+Whenever an optional argument is omitted, the behavior is equivalent to
+some choice of the optional argument. In this example, the two forms
+have exactly the same behavior, drawing a circle centered at $(0,0)$
+with radius $1$. In this case we will say ``\oarg{p} is the
+\emph{default}''. Another example is \cs{point}\marg{(1,0)} versus
+\cs{point}\oarg{3pt}\marg{(1,0)}. They both place a dot at the point
+$(1,0)$. The second one explicitly requests that it have diameter
+\dim{3pt}; the first will examine the length command \cs{pointsize},
+which the user can change, but it is initialized to \dim{2pt}. In this
+case we will say ``the default is the value of \cs{pointsize},
+\emph{initially} \dim{2pt}''.
+
+If an \mfp{} command that takes an optional argument finds only empty
+brackets (completely empty, no spaces), then it will use the default
+value. This is useful for commands that have two optional arguments and
+one wants the default value in the first one and some nondefault value
+in the second. An optional argument should normally not contain any
+spaces. Even when the argument contains more than one piece of data,
+spaces should not separate the parts. In some cases this will cause no
+harm, but it would be better to avoid doing it altogether, because there
+are cases where it will cause wrong results or error messages.
+
+
+\section{Files and Environments.}\label{files}
+
+\begin{cd}\pagelabel{opengraphsfile}
+\cs{opengraphsfile}\marg{\meta{file}}\\
+ \ $\ldots$\\
+\cs{closegraphsfile}%
+\index{opengraphsfile@\cs{opengraphsfile}}%
+\index{closegraphsfile@\cs{closegraphsfile}}
+\end{cd}
+
+These macros open and close the \MF{} or \MP{} file which will contain
+the pictures to be included in this document. The name of the file will
+be \file{\meta{file}.mf} (or \file{\meta{file}.mp}). Do \emph{not}
+specify the extension, which is added automatically.
+
+\emph{Note}: This command may cause \file{\meta{file}.mf} or
+\file{\meta{file}.mp} to be overwritten if it already exists, so be sure
+to consider that when selecting the name. Repeating the running of
+\TeX{} will overwrite the file created on previous runs, but that should
+be harmless. For if no changes are made to \env{mfpic} environments, the
+identical file will be recreated, and if changes have been made, then
+you want the file to be replaced with the new version.
+
+It is possible (but \emph{has not} been seriously tested) to close one
+file and open another, and even to change between \opt{metapost} and
+\opt{metafont} in between. If anything goes wrong with this, contact the
+maintainer and it might be fixed in some later version.
+
+There may be limitations on what can be used as a filename. As of \mfp{}
+version 1.00, we have tried to permit \cs{jobname} as part of
+\meta{file}. Thus we permit \TeX{} macros, but they should expand to
+non-special characters. Permitting macros makes it essentially
+impossible for the filename to contain the backslash and brace
+characters. Also spaces are problematic. However other special \TeX{}
+characters (for example: tilde, underscore and percent) can be used,
+though that is not recommended.
+
+\begin{cd}\pagelabel{mfpic}
+\cs{mfpic}\oarg{\meta{xfactor}}\oarg{\meta{yfactor}}%
+ \marg{\meta{xmin}}\marg{\meta{xmax}}\marg{\meta{ymin}}\marg{\meta{ymax}}\\
+ \ $\ldots$\\
+\cs{endmfpic}%
+\index{mfpic@\cs{mfpic}}%
+\index{endmfpic@\cs{endmfpic}}
+\end{cd}
+
+These macros open and close the \env{mfpic} environment%
+ \footnote{We use the term `environment' loosely. However, in
+ \LaTeX{} one may use an actual \env{mfpic} environment. See
+ page~\pageref{envusage}.}
+in which the drawing macros make sense. While many \mfp{} commands can
+be used inside or outside this environment, those that actually produce
+visible output are required to be inside. The \cs{mfpic} macro also sets
+up the local coordinate system for the picture. The \meta{xfactor} and
+\meta{yfactor} parameters establish the length of a coordinate system
+unit, as a multiple of the \TeX{} dimension \cs{mfpicunit}. If neither
+is specified, both are taken to be 1 and each coordinate system unit is
+1 \cs{mfpicunit}. If only one is specified, then they are assumed to be
+equal. Note that some drawing commands require equal scales to work as
+expected: if you try to draw a circle with different scales you will get
+an ellipse.
+
+The \meta{xmin} and \meta{xmax} parameters establish the lower
+and upper bounds for the $x$-axis coordinates; similarly, \meta{ymin}
+and \meta{ymax} establish the bounds for the $y$-axis. These bounds are
+expressed in local units---in other words, the actual width of the
+picture will be $(\meta{xmax}-\meta{xmin})\cdot\meta{xfactor}$ times
+\cs{mfpicunit}, its height $(\meta{ymax}-\meta{ymin})\cdot\meta{yfactor}$
+times \cs{mfpicunit}, and its depth zero.
+
+Most of \mfp{}'s drawing macros accept parameters which are
+\emph{coordinate pairs}. A coordinate pair is a pair of numbers $(x,y)$
+enclosed in parentheses, with $\meta{xmin} \le x \le \meta{xmax}$ and
+$\meta{ymin} \le y \le \meta{ymax}$.%
+ \footnote{These inequalities can be violated, usually causing
+ something to be drawn outside the designated borders of the figure.}
+We will call these \emph{graph coordinates} and refer to the numbers $x$
+and $y$ as being \emph{in graph units}. Things like the thickness of
+lines and the lengths of arrowheads are required to be expressed in
+actual lengths such as \dim{1pt} or \dim{3mm}. These will be referred to as
+\emph{absolute} units.
+
+One can scale all pictures uniformly by changing \cs{mfpicunit}, and
+scale an individual picture by changing \meta{xfactor} and \meta{yfactor}.
+After loading \mfp{}, \cs{mfpicunit} has the value \dim{1pt}. One
+\texttt{pt} is a \emph{printer's point}, which equals 1/72.27 inches or
+0.35146 millimeters.
+
+\emph{Note}: Changing \cs{mfpicunit} or the optional parameters will
+scale the coordinate system, but not the values of parameters that are
+defined in absolute units. If you wish, you can set these to multiples
+of \cs{mfpicunit}, but it is difficult (and almost certainly unwise) to
+get the thickness of lines (for example) to scale along with the scale
+parameters.
+
+In addition to establishing the coordinate system, these scales and
+bounds are used to establish the metric for the \MF{} character or
+bounding box for the \MP{} figure described within the environment. If
+any of these parameters are changed, the \file{.tfm} file (\MF{}) or the
+bounding box (\MP{}) will be affected, so you will have to be sure to
+reprocess the \TeX{} file after processing the \file{.mf} or \file{.mp}
+file, even if no other changes are made in the figure.
+
+The value of these 6 parameters to \cs{mfpic} are available within the
+environment as macros: \cs{xfactor}, \cs{yfactor}, \cs{xmin}, \cs{xmax},
+\cs{ymin} and \cs{ymax}.
+
+\begin{cd}\pagelabel{mfpicnumber}
+\cs{mfpicnumber}\marg{\meta{num}}%
+\index{mfpicnumber@\cs{mfpicnumber}}
+\end{cd}
+
+Normally, \cs{mfpic} assigns the number 1 to the first \env{mfpic}
+environment, after which the number is increased by one for each new
+\env{mfpic} environment. This number is used internally to include the
+picture. It is also transmitted to the output file where it is used as
+the argument to a \gbc{beginmfpic} command. In \MF{} this number becomes
+the position of the character in the font file, while in \MP{} it is
+part of the name of the graphic file that is output. The above command
+tells \mfp{} to ignore this sequence and number the next \env{mfpic}
+figure with \meta{num} (and the one after that $\meta{num}+1$, etc.). It
+is up to the user to make sure no number is repeated, as no checking is
+done. Numbers greater than 255 may cause errors, as \TeX{} assumes that
+characters are represented by numbers no larger than that. If the first
+figure is to be numbered something other than $1$, then, under the
+\opt{metapost} option, this command should come before
+\cs{opengraphsfile}, as that command checks for the existence of the
+first numbered figure to determine if there are figures to be included.
+
+\begin{cd}\pagelabel{everymfpic}
+\cs{everymfpic}\marg{\meta{commands}}\\
+\cs{everyendmfpic}\marg{\meta{commands}}%
+\index{everymfpic@\cs{everymfpic}}%
+\index{everyendmfpic@\cs{everyendmfpic}}%
+\end{cd}
+
+These commands store the \meta{commands}. The first arranges for these
+commands to be issued at the start of every \env{mfpic} environment and
+the second arranges for its commands to be issued at the end of every
+such environment. These could be any commands that make sense inside
+that environment. The purpose of these commands is to save typing if
+there is identical setup being performed in every picture.
+
+\begin{cd}\pagelabel{envusage}
+\cs{begin}\marg{mfpic}\texttt{...}\cs{end}\marg{mfpic}%
+\index{begin@\cs{begin}\marg{mfpic}}
+\end{cd}
+
+In \LaTeX{} you may prefer to use \cs{begin}\marg{mfpic} and
+\cs{end}\marg{mfpic} (instead of \cs{mfpic} and \cs{endmfpic}). This is
+by no means required. The sample file \file{lapictures.tex} provided
+with \mfp{} illustrates this use of an \env{mfpic} environment in
+\LaTeX{}.
+
+\medskip
+One should be careful using \TeX{} groups inside \env{mfpic}
+environments. These can be useful to limit the scope of declarations or
+of changes to some variables. However, they do not limit the scope of
+changes to the figure file that is being written, so there is a danger
+that \TeX{} and \MF{} will have different values. There are also some
+\mfp{} commands that need to be at the outermost level. Thus, grouping
+should generally be avoided except for those groups provided by \mfp{}
+commands.
+
+\medskip
+For the remainder of the macros, the numerical parameters are expressed
+in graph units, the units of the local coordinate system specified by
+\cs{mfpic}, unless otherwise indicated.
+
+
+\section{Common objects.}\label{figures}
+
+The \mfp{} macros that draw things can be roughly divided into two
+classes.
+\begin{enumerate}
+ \item Those that simply cause something to be drawn. Examples of these
+ are the \cs{point} command, which places a dot at a list of
+ coordinates, and \cs{gridlines}, which draw coordinate lines with
+ specified separation.
+ \item Those that both \emph{define} and draw a \emph{path}. The macros
+ \cs{circle}, \cs{rect}, and \cs{polyline} are examples of these.
+\end{enumerate}
+
+Macros of type 2 are referred to hereafter as \emph{figure macros}, for
+lack of a better term. With them one can use \emph{prefix
+macros}\index{prefix macro} to modify various aspects of the path and
+how it is drawn. For example,
+\begin{verbatim}
+\polyline{(1,2),(3,4)}
+\end{verbatim}
+draws a line from $(1,2)$ to $(3,4)$, but
+\begin{verbatim}
+\dotted\polyline{(1,2),(3,4)}
+\end{verbatim}
+produces a dotted version, and
+\begin{verbatim}
+\arrow\polyline{(1,2),(3,4)}
+\end{verbatim}
+draws it with an arrowhead at the tip. This is not possible with
+\cs{gridlines}, for example. As \mfp{} and the accompanying \MF{}
+package \grafbase{} are currently written, prefix macros can only be
+applied to single paths, and \cs{gridlines} produces a whole set of
+lines. In this manual, as each macro is introduced, if it is a figure
+macro, this will be explicitly stated.
+
+Some commands depend on the value of separately defined parameters. all
+these parameters are initialized when \mfp{} is loaded. In the following
+descriptions we give the initial value of all the relevant parameters.
+\Mfp{} provides commands to change any of these parameters. When \MP{}
+output is selected, figures can be drawn in any color and several of the
+above mentioned parameters are colors. For example, \gbc{drawcolor} is
+the name of the default color used to draw curves, \gbc{headcolor} is
+used when drawing arrowheads, etc. To save repetition: all special
+colors for figures are initialized to \mfc{black} except
+\mfc{background}, which is \mfc{white}.
+
+
+\subsection{Points, lines, and rectangles}\label{points}
+
+\begin{cd}\pagelabel{point}
+\cs{point}\oarg{\meta{size}}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}%
+\index{point@\cs{point}}
+\end{cd}
+
+Draws small disks centered at the points specified in the list of
+ordered pairs. The optional argument \meta{size} is an absolute
+dimension that determines the diameter of the disks. The default is the
+\TeX{} dimension \cs{pointsize}, initially \dim{2pt}. The disks have a
+filled interior if the command \cs{pointfilltrue} has been issued (the
+initial behavior). After the command \cs{pointfillfalse}, \cs{point}
+commands will produce outlined circles with the interiors erased. The
+color of the circles is the value of the predefined variable
+\gbc{pointcolor}, and the color inside of the open circles is the value
+of the variable \mfc{background}.%
+ \footnote{\MP{} cannot actually erase. The illusion of erasing is
+ created by painting over with \mfc{background}.}
+
+\begin{cd}\pagelabel{plotsymbol}
+\cs{plotsymbol}\oarg{\meta{size}}\marg{\meta{symbol}}%
+\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}%
+\index{plotsymbol@\cs{plotsymbol}}
+\end{cd}
+
+Draws small symbols centered at the points \meta{$p_0$}, \meta{$p_1$},
+and so on. The symbols must be given by name, and the available symbols
+are:
+\begin{display}
+ \gbc{Asterisk}\index{Asterisk@\gbc{Asterisk}},
+ \gbc{Circle}\index{Circle@\gbc{Circle}},
+ \gbc{Diamond}\index{Diamond@\gbc{Diamond}},
+ \gbc{Square}\index{Square@\gbc{Square}},
+ \gbc{Triangle}\index{Triangle@\gbc{Triangle}},
+ \gbc{Star}\index{Star@\gbc{Star}},
+ \gbc{SolidCircle}\index{SolidCircle@\gbc{SolidCircle}},\\
+ \gbc{SolidDiamond}\index{SolidDiamond@\gbc{SolidDiamond}},
+ \gbc{SolidSquare}\index{SolidSquare@\gbc{SolidSquare}},
+ \gbc{SolidTriangle}\index{SolidTriangle@\gbc{SolidTriangle}},
+ \gbc{SolidStar}\index{SolidStar@\gbc{SolidStar}},
+ \gbc{Cross}\index{Cross@\gbc{Cross}}, and
+ \gbc{Plus}\index{Plus@\gbc{Plus}}.
+\end{display}
+The names should be self-explanatory, the `\gbc{Solid}' ones are filled
+in, the others are outlines. Under \opt{metapost}, symbols are drawn in
+\gbc{pointcolor}. The \meta{size} defaults to \cs{pointsize} as in
+\cs{point} above. \gbc{Asterisk} consists of six line segments while
+\gbc{Star} is the standard five-pointed star formed from ten straight
+line segments. \gbc{Cross} is a $\times$ shape. The name
+`\cs{plotsymbol}' comes from the fact that the \cs{plot} command (see
+subsection~\ref{drawing}), which was written first, utilizes these same
+symbols. The command \cs{symbol} was already taken (standard \LaTeX{}).
+
+While one would rarely want to use them for this purpose, the following
+symbols are also available:
+\begin{display}
+ \gbc{Arrowhead}\index{Arrowhead@\gbc{Arrowhead}},
+ \gbc{Crossbar}\index{Crossbar@\gbc{Crossbar}},
+ \gbc{Leftbar}\index{Leftbar@\gbc{Leftbar}},
+ \gbc{Rightbar}\index{Rightbar@\gbc{Rightbar}},
+ \gbc{Lefthook}\index{Lefthook@\gbc{Lefthook}},
+ \gbc{Righthook}\index{Righthook@\gbc{Righthook}},
+ \gbc{Leftharpoon}\index{Leftharpoon@\gbc{Leftharpoon}},\\
+ \gbc{Rightharpoon}\index{Rightharpoon@\gbc{Rightharpoon}}.
+\end{display}
+These are mainly intended for making arrows. See subsection~\ref{arrows}
+for a further description.
+
+The difference between \cs{pointfillfalse}\cs{point} and
+\cs{plotsymbol}\marg{Circle} is that the inside of the circle will not
+be erased in the second version, so whatever else has already been drawn
+in that area will remain visible. This is the default (for backward
+compatibility), but that can be changed with the commands below.
+
+\begin{cd}\pagelabel{clearsymbols}
+\cs{clearsymbols}\\
+\cs{noclearsymbols}%
+\index{clearsymbols@\cs{clearsymbols}}%
+\index{noclearsymbols@\cs{noclearsymbols}}
+\end{cd}
+
+After the first of these two commands, subsequent \cs{plotsymbol}
+commands will draw the open symbols with their interiors erased. After
+the second, the default behavior (described above) will be restored.
+These commands have no effect on \cs{point}. \cs{plotnodes} (see
+subsection~\ref{drawing}) also responds to the settings made by these
+commands. The \cs{plot} command (also in subsection~\ref{drawing}) does
+not.
+
+You can design your own `symbols'. See the discussion of arrowheads in
+subsection~\ref{arrows}, and of storing paths in
+subsection~\ref{transformation}.
+
+\begin{cd}\pagelabel{pointdef}
+\cs{pointdef}\marg{\meta{name}}\texttt{(\meta{xcoord},\meta{ycoord})}%
+\index{pointdef@\cs{pointdef}}
+\end{cd}
+
+Defines a symbolic name for an ordered pair and the coordinates it
+contains. \meta{name} is any legal \TeX{} command name \emph{without}
+the backslash; \meta{xcoord} and \meta{ycoord} are any numbers. For
+example, after the command \cs{pointdef}\marg{A}\texttt{(1,3)}, \cs{A}
+expands to \texttt{(1,3)}, while \cs{Ax} and \cs{Ay} expand to
+\texttt{1} and \texttt{3}, respectively. If \opt{mplabels} is in effect
+one can use \cs{A} to specify where to place a text label, but if \TeX{}
+is placing labels one must use \texttt{(\cs{Ax},\cs{Ay})}. In most
+other cases, one can use \cs{A} where a pair or point is required.
+
+\begin{cd}\pagelabel{polyline}
+\cs{polyline}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}\\
+\cs{lines}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}%
+\index{polyline@\cs{polyline}}%
+\index{lines@\cs{lines}}
+\end{cd}
+
+The figure macro \cs{polyline} produces connected line segments from
+\meta{$p_0$} to \meta{$p_1$}, and from there to \meta{$p_2$}, etc. The
+result is an open polygonal path through the specified points, in the
+specified order. The macro \cs{lines} is an alias for \cs{polyline}.
+
+\begin{cd}\pagelabel{polygon}
+\cs{polygon}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}\\
+\cs{closedpolyline}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}%
+\index{polygon@\cs{polygon}}%
+\index{closedpolyline@\cs{closedpolyline}}
+\end{cd}
+
+The figure macro \cs{polygon} produces a closed polygon with vertices
+at the specified points in the specified order. It works exactly like
+\cs{polyline} except the last point in the list is also joined to the
+first. The macro \cs{closedpolyline} is an alias for \cs{polygon}.
+
+\begin{cd}\pagelabel{rect}
+\cs{rect}\marg{\meta{$p_0$},\meta{$p_1$}}%
+\index{rect@\cs{rect}}
+\end{cd}
+
+This figure macro produces the closed rectangle with horizontal and
+vertical sides, having the points \meta{$p_0$} and \meta{$p_1$} as
+diagonally opposite corners. The same rectangle can be specified in four
+different ways: either pair of opposite corners in either order.
+
+It is occasionally helpful to know that connected paths like those
+produced by \cs{polyline} or \cs{rect} have a \emph{start} and a
+\emph{finish} as well as \emph{sense} (or direction). The path produced
+by \cs{polyline} starts at the first listed point and ends at last,
+having the direction determined by the order of the points. For
+\cs{rect} the sense may be clockwise or anticlockwise depending on the
+corners used: it starts by moving horizontally from the first listed
+point. Several \mfp{} macros (such as those that add arrowheads) treat
+the beginning and the end of a path differently, or adjust their
+behavior according to the sense of the curve.
+
+\begin{cd}\pagelabel{regpolygon}
+\cs{regpolygon}\marg{\meta{num}}\marg{\meta{name}}%
+ \marg{\meta{eqn$_1$}}\marg{\meta{eqn$_2$}}%
+\index{regpolygon@\cs{regpolygon}}
+\end{cd}
+
+This figure macro produces a closed regular polygon with \meta{num}
+sides. The second argument, \meta{name} is a symbolic name. It can be
+used to refer to the vertices later. The last two arguments should be
+equations that position two of the vertices or one vertex and the
+center. The center is referred to by \meta{name}\gbc{0} and the vertices
+by \meta{name}\gbc{1} \meta{name}\gbc{2}, etc., going anticlockwise
+around the polygon. The \meta{name} itself (without a number suffixed)
+will be a \MF{} variable assigned the value of \meta{num}. For example,
+\begin{verbatim}
+\regpolygon{5}{Kay}{Kay0=(0,1)}{Kay1=(2,0)}
+\end{verbatim}
+will produce a regular pentagon with its center at $(0,1)$ and its first
+vertex at $(2,0)$. One could later draw a star inside it with
+\begin{verbatim}
+\polygon{Kay1,Kay3,Kay5,Kay2,Kay4}
+\end{verbatim}
+Moreover, \gbc{Kay} will equal $5$. The name given becomes a \MF{}
+variable and care should be taken to make the name distinctive so as not
+to redefine some internal variable.
+
+
+\subsection{A word about list arguments}\label{list}
+
+We have seen already four \mfp{} macros that take a mandatory argument
+consisting of an arbitrary number of coordinate pairs, separated by
+commas. There are many more, and some that take a comma-separated list
+of items of other types. If the lists are long, especially if they are
+generated by a program, it might be more convenient if one could simply
+refer to an external file for the data. This is possible, and one does
+it the following way: instead of \cs{polyline}\marg{\meta{list}}, one
+can write\index{datafile@\cs{datafile}}
+\begin{ex}
+ \cs{polyline}\cs{datafile}\marg{\meta{filename}}
+\end{ex}
+where \meta{filename} is the full name of the file containing the data.
+The required format of this file and the details of this usage can be
+found in subsection~\ref{external}. This method is available for any
+command that takes a comma-separated list of data (of arbitrary length)
+as its last argument, \emph{with the exception of those commands that
+add text to the picture}. Examples of the latter are \cs{plottext} and
+\cs{axislabels} (subsection~\ref{text}).
+
+
+\subsection{Axes, axis marks, and grids}\label{axesthings}
+
+\begin{cd}\pagelabel{axes}
+\cs{axes}\oarg{\meta{hlen}}\\
+\cs{xaxis}\oarg{\meta{hlen}}\\
+\cs{yaxis}\oarg{\meta{hlen}}%
+\index{axes@\cs{axes}}%
+\index{xaxis@\cs{xaxis}}%
+\index{yaxis@\cs{yaxis}}
+\end{cd}
+
+These are retained for backward compatibility, but there are more
+flexible alternatives below. They draw $x$- and $y$-axes for the
+coordinate system. The command \cs{axes} is equivalent to \cs{xaxis}
+followed by \cs{yaxis} which produce the obvious. The $x$- and $y$-axes
+extend the full width and height of the \env{mfpic} environment. The
+optional \meta{hlen} sets the length of the arrowhead on each axis. The
+default is the value of the \TeX{} dimension \cs{axisheadlen}, initially
+\dim{5pt}. The shape of the arrowhead is determined as in the \cs{arrow}
+macro (section~\ref{modifier}). The color of the head is the value of
+\gbc{headcolor}, the shaft is \gbc{drawcolor}.
+
+Unlike other commands that produce lines or curves, these do not respond
+to prefix macros. They always draw a solid line (with an arrowhead
+unless \cs{axisheadlen} is \dim{0pt}). They \emph{do} respond to changes
+in the pen thickness (see \cs{penwd} in section~\ref{parameters}) but
+that is pretty much the only possibility for variation.
+
+\begin{cd}\pagelabel{axis}
+\cs{axis}\oarg{\meta{hlen}}\marg{\meta{one-axis}}\\
+\cs{doaxes}\oarg{\meta{hlen}}\marg{\meta{axis-list}}%
+\index{axis@\cs{axis}}%
+\index{doaxes@\cs{doaxes}}%
+\end{cd}
+
+These produce any of 6 different axes. The parameter \meta{one-axis} can
+be \texttt{x} or \texttt{y}, to produce (almost) the equivalent of
+\cs{xaxis} and \cs{yaxis}; or it can be \texttt{l}, \texttt{b},
+\texttt{r}, or \texttt{t} to produce an axis on the border of the
+picture (left, bottom, right or top, respectively). \cs{doaxes} takes a
+list of any or all of the six letters (with either spaces or nothing in
+between) and produces the appropriate axes. Example:
+\cs{doaxes}\marg{lbrt}. The optional argument sets the length of the
+arrowhead. In the case of axes on the edges, the default is the value of
+\cs{sideheadlen}, which \mfp{} initializes to \dim{0pt}. For the $x$-
+and $y$-axis the default is \cs{axisheadlen} as in \cs{xaxis} and
+\cs{yaxis} above.
+
+The commands \cs{axis}\marg{x}, \cs{axis}\marg{y}, and
+\cs{doaxes}\marg{xy} differ from the old \cs{xaxis}, \cs{yaxis} and
+\cs{axes} in that these new versions respond to prefix macros. The
+\cs{arrow} prefix previously mentioned is an exception: these macros add
+an arrowhead automatically. For example, the sequence
+\cs{dotted}\cs{axis}\marg{x} draws a dotted $x$-axis, but
+\cs{dotted}\cs{xaxis} produces a \MF{} error. A prefix macro applied to
+\cs{doaxes} generates no error, but only the first axis in the list will
+be affected.
+
+\begin{cd}\pagelabel{axisline}
+\cs{axisline}\marg{\meta{one-axis}}\\
+\cs{border}%
+\index{axisline@\cs{axisline}}%
+\index{border@\cs{border}}%
+\end{cd}
+
+These are figure macros that draw the line or lines that an \cs{axis}
+command would draw. An \cs{axis} command is almost the equivalent of
+\begin{display}
+ \cs{arrow}\oarg{l\meta{hlen}}\cs{axisline}\marg{\meta{one-axis}}.
+\end{display}
+The \cs{axisline} command is provided as a figure macro for maximum
+flexibility. For example, one can use the star-form of the \cs{arrow}
+command if desired or decorate it with ones own choice of arrowhead (see
+subsection~\ref{arrows}).
+
+Also a figure macro, \cs{border} produces the rectangle which, if drawn,
+is visibly the same as the four border \cs{axisline}\,s (without heads).
+It is a closed path and could easily be drawn with a \cs{rect} command,
+but the \cs{border} command automatically adjusts for the margins set by
+the commands below.
+
+The side axes are drawn by default with a pen stroke along the very edge
+of the picture (as determined by the parameters to \cs{mfpic}). This can
+be changed with the command \cs{axismargin} described below.
+
+Axes on the edges are drawn so that they don't cross each other.
+\cs{doaxes}\marg{lbrt}, for example, produces a perfect rectangle. If the
+$x$- and $y$-axis are drawn with \cs{axis} or \cs{doaxes}, then they
+will not cross the side axes. For this to work properly, all the
+following margin settings have to be done before the axes are drawn.
+
+\begin{cd}\pagelabel{axismargin}
+\cs{axismargin}\marg{\meta{one-axis}}\marg{\meta{num}}\\
+\cs{setaxismargins}%
+ \marg{\meta{num}}\marg{\meta{num}}\marg{\meta{num}}\marg{\meta{num}}\\
+\cs{setallaxismargins}\marg{\meta{num}}%
+\index{axismargin@\cs{axismargin}}%
+\index{setaxismargins@\cs{setaxismargins}}%
+\index{setallaxismargins@\cs{setallaxismargins}}%
+\end{cd}
+
+The parameter \meta{one-axis} is one of the letters \texttt{l},
+\texttt{b}, \texttt{r}, or \texttt{ t}, and \cs{axismargin} causes the
+given axis to be shifted \emph{inward} by the \meta{num} specified (in
+\emph{graph} units). The second command \cs{setaxismargins} takes
+4 arguments, using them to set the margins starting with the left and
+proceeding anticlockwise. The last command sets all the axis margins to
+the same value.
+
+A change to an axis margin affects not only the axis at that edge but
+also the three axes perpendicular to it. For example, if the margins are
+$M_{\mathrm{lft}}$, $M_{\mathrm{bot}}$, $M_{\mathrm{rt}}$ and
+$M_{\mathrm{top}}$, then \cs{axis}\marg{b} draws a line starting
+$M_{\mathrm{lft}}$ graph units from the left edge and ending
+$M_{\mathrm{rt}}$ units from the right edge. Of course, the entire line
+is $M_{\mathrm{bot}}$ units above the bottom edge. The margins are also
+respected by the $x$- and $y$-axis, but only when drawn with \cs{axis}.
+The old \cs{xaxis}, \cs{yaxis} and \cs{axes} ignore them.
+
+Special effects can be achieved by lying to one axis about the other
+margins. That is, axes can be draw in separate commands with changes to
+the declared margins in between. Be aware that various other commands
+are affected by the margin values. Examples are the already mentioned
+\cs{border}, as well as \cs{grid} and \cs{gridlines}
+(page~\pageref{grid} in this subsection).
+
+\begin{cd}\pagelabel{axismarks}
+\cs{xmarks}\oarg{\meta{len}}\marg{\meta{numberlist}}\\
+\cs{ymarks}\oarg{\meta{len}}\marg{\meta{numberlist}}\\
+\cs{lmarks}\oarg{\meta{len}}\marg{\meta{numberlist}}\\
+\cs{bmarks}\oarg{\meta{len}}\marg{\meta{numberlist}}\\
+\cs{rmarks}\oarg{\meta{len}}\marg{\meta{numberlist}}\\
+\cs{tmarks}\oarg{\meta{len}}\marg{\meta{numberlist}}\\
+\cs{axismarks}\marg{\meta{axis}}\oarg{\meta{len}}\marg{\meta{numberlist}}%
+\index{xmarks@\cs{xmarks}}%
+\index{tmarks@\cs{tmarks}}%
+\index{bmarks@\cs{bmarks}}%
+\index{ymarks@\cs{ymarks}}%
+\index{lmarks@\cs{lmarks}}%
+\index{rmarks@\cs{rmarks}}%
+\index{axismarks@\cs{axismarks}}
+\end{cd}
+
+These macros place hash marks on the appropriate axes at the places
+indicated by the values in the list. The optional \meta{len} gives the
+length of the hash marks. If \meta{len} is not specified, the \TeX{}
+dimension \cs{hashlen}, initially \dim{4pt}, is used. The marks on the
+$x$- and $y$-axes are centered on the respective axis; the marks on the
+border axes are drawn to the inside. Both these behaviors can be
+changed (see below). The commands may be repeated as often as desired.
+(The timing of drawing commands can make a difference as outlined in
+appendix~\ref{mpconsiderations}.) The command \cs{axismarks}\marg{x} is
+equivalent to \cs{xmarks} and so on for each of the six axes. (I would
+have used the shorter name \cs{marks}, but that name was already taken
+by \eTeX{}.)
+
+The \meta{numberlist} is normally a comma-separated list of numbers. In
+place of this, one can give a starting number, an increment and an
+ending number as in the following example:
+\begin{verbatim}
+\xmarks{-2 step 1 until 2}
+\end{verbatim}
+is the equivalent of
+\begin{verbatim}
+\xmarks{-2,-1,0,1,2}
+\end{verbatim}
+
+One must use exactly the words \mfc{step} and \mfc{until}. Spaces are
+not needed unless a variable name is used in place of one of the
+numbers (see subsection~\ref{variables}). The number of spaces is not
+significant.%
+ \footnote{Experienced \MF{} programmers may recognize that anything
+ can be used that is permitted in \MF{}'s \meta{forloop} syntax. Thus
+ the given example can also be reworded \cs{xmarks}\marg{-2 upto 2},
+ or even \cs{xmarks}\marg{2 downto -2}. See subsection~\ref{loops}
+ for more on for-loops in \mfp{}.} %
+Users of this syntax should be aware that if any of the numbers is not
+an integer then, because of natural round-off effects, the last value
+might be overshot and a mark not printed there. For example, to ensure
+that a mark is printed at the point $1.0$ on the $x$-axis, the second
+line below is better than the first.
+\begin{verbatim}
+\xmarks{0 step .2 until 1.0}
+\xmarks{0 step .2 until 1.1}
+\end{verbatim}
+
+\begin{cd}\pagelabel{setaxismarks}
+\cs{setaxismarks}\marg{\meta{axis}}\marg{\meta{pos}}\\
+\cs{setbordermarks}\marg{\meta{lpos}}\marg{\meta{bpos}}\marg{\meta{rpos}}\marg{\meta{tpos}}\\
+\cs{setallbordermarks}\marg{\meta{pos}}\\
+\cs{setxmarks}\marg{\meta{pos}}\\
+\cs{setymarks}\marg{\meta{pos}}%
+\index{setaxismarks@\cs{setaxismarks}}%
+\index{setbordermarks@\cs{setbordermarks}}%
+\index{setallbordermarks@\cs{setallbordermarks}}%
+\index{setxmarks@\cs{setxmarks}}%
+\index{setymarks@\cs{setymarks}}%
+\end{cd}
+
+These set the placement of the hash marks relative to the axis. The
+parameter \meta{axis} is one of the letters \texttt{x}, \texttt{y}, \texttt{l},
+\texttt{b}, \texttt{r}, or \texttt{t}, and \meta{pos} must be one of the literal
+words \gbc{inside}, \gbc{outside}, \gbc{centered}, \gbc{onleft},
+\gbc{onright}, \gbc{ontop} or \gbc{onbottom}. The second command takes
+four arguments and sets the position of the marks on each border. The
+third command sets the position on all four border axis to the same
+value. The last two commands are abbreviations for
+\cs{setaxismarks}\marg{x}\marg{\meta{pos}} and
+\cs{setaxismarks}\marg{y}\marg{\meta{pos}}, respectively.
+
+Not all combinations make sense (for example, \gbc{ontop} for the right
+side axis). In these cases, no error message is produced. These words
+are actually \MF{} numeric variables and the variables \gbc{ontop} and
+\gbc{onleft}, for example, have the same value. Thus, using \gbc{ontop}
+for the right axis will have the same effect as \gbc{onleft}. Similarly,
+\gbc{onright} and \gbc{onbottom} are the same. The parameters
+\gbc{inside} and \gbc{outside} usually make no sense for the $x$- and
+$y$-axes, but if they are used then \gbc{inside} means \gbc{ontop} for
+the $x$-axis and \gbc{onright} for the $y$-axis.
+
+\begin{cd}\pagelabel{grid}
+\cs{grid}\oarg{\meta{size}}\marg{\meta{xsep},\meta{ysep}}\\
+\cs{gridpoints}\oarg{\meta{size}}\marg{\meta{xsep},\meta{ysep}}\\
+\cs{lattice}\oarg{\meta{size}}\marg{\meta{xsep},\meta{ysep}}\\
+\cs{hgridlines}\marg{\meta{ysep}}\\
+\cs{vgridlines}\marg{\meta{xsep}}\\
+\cs{gridlines}\marg{\meta{xsep},\meta{ysep}}%
+\index{grid@\cs{grid}}%
+\index{gridpoints@\cs{gridpoints}}%
+\index{lattice@\cs{lattice}}%
+\index{vgridlines@\cs{vgridlines}}%
+\index{hgridlines@\cs{hgridlines}}%
+\index{gridlines@\cs{gridlines}}%
+\end{cd}
+
+\cs{grid} draws a dot at every point for which the first coordinate is
+an integer multiple of the \meta{xsep} and the second coordinate is an
+integer multiple of \meta{ysep}. The diameter of the dot is determined
+by \meta{size}. The default is the value of \cs{griddotsize},
+initially \dim{0.5pt}. Under the \opt{metapost} option, the color of the
+dot is \gbc{pointcolor}. The commands \cs{gridpoints and \cs{lattice}}
+are synonyms for \cs{grid}.
+
+\cs{hgridlines} draws the horizontal and \cs{vgridlines} the vertical
+lines through these same points. \cs{gridlines} draws both sets of
+lines. The thickness of the lines is set by \cs{penwd}. Authors are
+recommended to either reduce the pen width or change \gbc{drawcolor} to
+a lighter color for grid lines. Or omit them entirely: well-designed
+graphs usually don't need them and almost never should both horizontals
+and verticals be used.
+
+The above commands draw their dots and lines within the margins set by the
+axis margin commands on page~\pageref{axismargin}.
+
+\begin{cd}\pagelabel{plrgrid}
+\cs{plrgrid}\marg{\meta{rsep},\meta{anglesep}}\\
+\cs{gridarcs}\marg{\meta{rsep}}\\
+\cs{gridrays}\marg{\meta{anglesep}}\\
+\cs{plrpatch}\marg{\meta{rmin},\meta{rmax},\meta{rsep},%
+ \meta{tmin},\meta{tmax},\meta{tsep}}\\
+\cs{plrgridpoints}\oarg{\meta{size}}\marg{\meta{rsep},\meta{anglesep}}%
+\index{plrgrid@\cs{plrgrid}}%
+\index{plrpatch@\cs{plrpatch}}%
+\index{gridarcs@\cs{gridarcs}}%
+\index{gridrays@\cs{gridrays}}%
+\index{plrgridpoints@\cs{plrgridpoints}}%
+\end{cd}
+
+\cs{plrgrid} fills the graph with circular arcs and radial lines.
+\cs{gridarcs} draws only the arcs, \cs{gridrays} only the radial lines.
+\cs{plrgridpoints} places a dot (diameter \meta{size}) at all the places
+the rays and arcs would intersect. It takes an optional argument for the
+size of the dots, the default being \cs{griddotsize}, the same as the
+\cs{grid} command.
+
+The arcs lie on circles centered at $(0,0)$ and the rays would all meet
+at $(0,0)$ if extended. The corresponding \MF{} commands actually draw
+just enough to cover the graph area and then clip them to the graph
+boundaries. If you don't want them clipped, use \cs{plrpatch}. Unlike
+the rectangular coordinate grid commands, these do not respect the axis
+margins (rectangular margins don't really belong with polar coordinates).
+
+\cs{plrpatch} draws arcs with radii starting at \meta{rmin}, stepping by
+\meta{rsep} and ending with \meta{rmax}. Each arc goes from angle
+\meta{tmin} to \meta{tmax}. It also draws radial lines with angles
+starting at \meta{tmin}, stepping by \meta{tsep} and ending with
+\meta{tmax}. Each line goes from radius \meta{rmin} to \meta{rmax}. If
+$\meta{rmax}-\meta{rmin}$ doesn't happen to be a multiple of
+\meta{rsep}, the arc with radius \meta{rmax} is drawn anyway. The same
+is true of the line at angle \meta{tmax}, so that the entire boundary is
+always drawn.
+
+If \meta{tsep} is larger than \meta{tmax}${}-{}$\meta{tmin}, then only
+the boundary rays will be drawn. If \meta{rsep} is larger than
+\meta{rmax}${}-{}$\meta{rmin}, then only the boundary arcs will be
+drawn.
+
+The color used for rays and arcs is \gbc{drawcolor}, and for dots
+\gbc{pointcolor}. The advice about color and use of \cs{gridlines} holds
+for \cs{plrgrid} and its relatives as well.
+
+\begin{cd}\pagelabel{vectorfield}
+\cs{vectorfield}\oarg{\meta{hlen}}\marg{\meta{xsp},\meta{ysp}}%
+\marg{\meta{formula}}\marg{\meta{restriction}}\\
+\cs{plrvectorfield}\oarg{\meta{hlen}}\marg{\meta{rsp},\meta{tsp}}%
+\marg{\meta{formula}}\marg{\meta{restriction}}%
+\index{vectorfield@\cs{vectorfield}}%
+\index{plrvectorfield@\cs{plrvectorfield}}
+\end{cd}
+
+These commande draw a field of vectors (arrows). The optional argument
+is the length of the arrowhead, the default being the dimension
+\cs{headlen}, initially \dim{3pt}.
+
+For \cs{vectorfield}, an arrow is drawn starting from each point $(x,y)$
+where $x$ is an integer multiple of \meta{xsp} and $y$ is an integer
+multiple of \meta{ysp}. The vector field is given by \meta{formula},
+which should be a pair-valued expression in the literal variables
+\mfc{x} and \mfc{y}. Typically that would be a pair of numeric
+expressions enclosed in parentheses and separated by a comma. The last
+argument is a boolean expression in the literal variables \mfc{x} and
+\mfc{y}, used to restrict the domain. That is, if the expression is
+false for some $(x,y)$, no arrow is drawn at that point. If you do not
+wish to restrict the domain, type \texttt{true} for the restriction.
+
+For \cs{plrvectorfield}, an arrow is drawn starting from each point with
+polar coordinates $(r,\theta)$ if $r$ is an integer multiple of
+\meta{rsp} and $\theta$ is an integer multiple of \meta{tsp}. In this
+case, the \meta{formula} must be a pair-valued expression in the literal
+variables \mfc{r} and \mfc{t}. This should be (or produce) a pair of $x$
+and $y$ coorinates, not a polar coordinate pair. If you have formulas
+$R(r,\theta)$ for the length of each vector and $T(r,\theta)$ for the
+angle, then the following will convert to $(x,y)$ pairs:
+\begin{verbatim}
+{polar (R(r,t),T(r,t))}
+\end{verbatim}
+The last argument is as in \cs{vectorfield}, except it should depend on
+the literal variables \mfc{r} and \mfc{t}.
+
+In either case, the arrow is not drawn if the starting point would lie
+outside the borders set with \cs{axismargins} and its relatives.
+
+The following draws a rotational field, omitting the inside of the
+circle of radius $1$, where the arrows would be excessively long, and
+especially avoiding $(0,0)$ where the vector field is undefined.
+\begin{verbatim}
+\vectorfield[2.5pt]{.25,.25}{.5*(-y,x)/(x**2+y**2)}{x**2+y**2 >= 1}
+\end{verbatim}
+The following is the same field, represented by arrows whose locations
+are regularly spaced in polar coordinates.
+\begin{verbatim}
+\plrvectorfield[2.5pt]{.25,20}{polar(.5/r,t+90)}{r >= 1}
+\end{verbatim}
+
+
+\subsection{Circles, arcs and ellipses}\label{circles}
+
+\begin{cd}\pagelabel{circle}
+\cs{circle}\oarg{\meta{format}}\marg{\meta{specification}}%
+\index{circle@\cs{circle}}%
+\end{cd}
+
+This figure macro produces a circle. Starting with \mfp{} version 0.7,
+there are more than one way to specify a circle. In version 0.8 and
+later there are six ways, and one selects which one by giving
+\cs{circle} an optional argument that signals what data will be
+specified in the mandatory argument.
+
+\begin{cd}
+\cs{circle}\oarg{p}\marg{\meta{$c$},\meta{$r$}}\\
+\cs{circle}\oarg{c}\marg{\meta{$c$},\meta{$p$}}\\
+\cs{circle}\oarg{t}\marg{\meta{$p_1$},\meta{$p_2$},\meta{$p_3$}}\\
+\cs{circle}\oarg{s}\marg{\meta{$p_1$},\meta{$p_2$},\meta{$\theta$}}\\
+\cs{circle}\oarg{r}\marg{\meta{$p_1$},\meta{$p_2$},\meta{$r$}}\\
+\cs{circle}\oarg{q}\marg{\meta{$p_1$},\meta{$p_2$},\meta{$r$}}%
+\index{circle@\cs{circle}}%
+\end{cd}
+
+The optional arguments produce circles according to the following
+descriptions.
+%
+\begin{description}
+\item[\oarg{p}] The \textit{Polar form} is the default. The data in the
+mandatory argument should then be the center \meta{c} and radius
+\meta{r} of the circle. A negative radius is a mathematical error, but
+it is accepted. It produces the same circle, with the same sense, but
+the starting point (normally \meta{$r$} units to the right of the
+center) is \meta{$r$} units \emph{left} of the center.
+
+\item[\oarg{c}] The \textit{center-point form}. In this case the data
+should be the center and one point on the circumference. The circle
+starts at the point and has an anticlockwise sense.
+
+\item[\oarg{t}] The \textit{three-point form}. The data are three points
+that do not lie in a straight line. The circle starts at the first point
+and has the sense determined by the order of the points.
+
+\item[\oarg{s}] The \textit{point-sweep form}. The data are two points on the
+circle, followed by the angle of arc between them. This circle starts at
+the first point and has a sense determined by the angle: anticlockwise
+for positive angles, clockwise for negative.
+
+\item[\oarg{r}] The \textit{point-radius form}. The data are two points on the
+circle, followed by the radius. There are two circles with this data.
+The one that makes the angle from the first to the second point positive
+and less than $180$ degrees is produced. The sense of the circle is
+normally anticlockwise starting at the first point. Using a negative
+radius is a mathematical error, but this command just produces the other
+circle with the opposite sense.
+
+\item[\oarg{q}] The \textit{alternative point-radius form}. The data are
+the same as for the \oarg{r} case, except the other circle is produced.
+That is, a circle starting at the first point, proceeding anticlockwise
+through an angle greater than $180$ degrees to the second point, then
+along the shorter arc to the first point. Again, a negative radius
+produces the other circle with clockwise sense.
+\end{description}
+%
+These optional arguments are also used in the \cs{arc} command (see
+below). The \cs{circle} command draws the whole circle of which the
+corresponding \cs{arc} command draws only a part.
+
+\begin{cd}\pagelabel{arc}
+\cs{arc}\oarg{\meta{format}}\marg{\meta{specification}}\\
+\cs{arc*}\oarg{\meta{format}}\marg{\meta{specification}}%
+\index{arc@\cs{arc}}%
+\end{cd}
+
+This figure macro produces a circular arc specified as determined by the
+\meta{format} optional parameter. As with \cs{circle}, the optional
+\meta{format} parameter determines the format of the other parameter, as
+indicated below. The user is responsible for ensuring that the parameter
+values make geometric sense. The starting point of each arc is at the
+first specified angle or point and the ending point is at the last one.
+
+The star-form produces the complementary arc. That is, instead of the
+arc described below, it produces the rest of the circle from the ending
+point to the starting point of the arc described.
+
+\begin{cd}
+\cs{arc}\oarg{s}\marg{\meta{$p_0$},\meta{$p_1$},\meta{$\theta$}}\\
+\cs{arc}\oarg{p}\marg{\meta{$c$},\meta{$\theta_1$},\meta{$\theta_2$},\meta{$r$}}\\
+\cs{arc}\oarg{a}\marg{\meta{$c$},\meta{$r$},\meta{$\theta_1$},\meta{$\theta_2$}}\\
+\cs{arc}\oarg{c}\marg{\meta{$c$},\meta{$p_1$},\meta{$\theta$}}\\
+\cs{arc}\oarg{t}\marg{\meta{$p_0$},\meta{$p_1$},\meta{$p_2$}}\\
+\cs{arc}\oarg{r}\marg{\meta{$p_0$},\meta{$p_1$},\meta{$r$}}\\
+\cs{arc}\oarg{q}\marg{\meta{$p_0$},\meta{$p_1$},\meta{$r$}}%
+\index{arc@\cs{arc}}%
+\end{cd}
+
+The optional arguments produce arcs according to the following
+descriptions.
+\begin{description}
+\item[\oarg{s}] The \textit{point-sweep form} is the default format. It
+draws the circular arc starting from the point \meta{$p_0$}, ending at
+the point \meta{$p_1$}, and covering an arc angle of \meta{$\theta$}
+degrees, measured anticlockwise around the center of the circle. If,
+for example, the points \meta{$p_0$} and \meta{$p_1$} lie on a
+horizontal line with \meta{$p_0$} to the \emph{left}, and \meta{$\theta$}
+is between $0$~and $360$ (degrees), then the arc will sweep \emph{below} the
+horizontal line (in order for the arc to be anticlockwise). A
+negative value of \meta{$\theta$} gives a clockwise arc from \meta{$p_0$}
+to \meta{$p_1$}.
+
+\item[\oarg{p}] The \textit{polar form} draws the arc of a circle with
+center \meta{$c$} starting at the angle \meta{$\theta_1$} and ending at
+the angle \meta{$\theta_2$}, with radius \meta{$r$}. Both angles are
+measured anticlockwise from the positive $x$ axis. If the first angle is
+less than the second, the arc has an anticlockwise sense, otherwise
+clockwise. A negative radius is a mathematical error, but the result is
+the arc on the opposite side of the circle, as if both angles were
+increased by $180$ degrees
+
+\item[\oarg{a}] The alternative polar form differs from the polar form
+above only in the order of the arguments. This seems (to me) a more
+reasonable order, and matches the order \cs{sector} requires (see below).
+The \texttt{[p]} option is retained for backward compatibility.
+
+\item[\oarg{c}] The \textit{center-point-angle form} draws the circular
+arc with center \meta{$c$}, starting at the point \meta{$p_1$}, and
+sweeping an angle of \meta{$\theta$} around the center from that point.
+This is the fundamental method for drawing arcs. All other methods are
+converted to this or the point-sweep method. Even the point sweep form
+is converted to this one for angles greater than 90 degrees.
+
+\item[\oarg{t}] The \textit{three-point form} draws the circular arc
+which passes through all three points given, in the order given.
+Internally, this is converted to two applications of the point-sweep
+form.
+
+\item[\oarg{r}] The \textit{point-radius form} draws an arc on the
+circle that \cs{circle}\oarg{r} would produce. The arc starts at the
+point \meta{$p_0$} and ends at \meta{$p_1$}. Of the two possible arcs on
+that circle, it produces the shorter one: the one with an angle $\theta$
+less than $180$ degrees measured anticlockwise around the center of the
+circle. A negative radius is a mathematical error, but the result is the
+short arc on the other circle with a clockwise sense.
+
+\item[\oarg{q}] The \textit{alternative point-radius form} is the same
+as \oarg{r} except it produces the longer arc: the one with angle
+$\theta$ larger than $180$ degrees measured anticlockwise around the
+center of the circle. A negative radius is a mathematical error, but the
+result is the longer arc on the other circle with a clockwise sense.
+\end{description}
+
+For both options \oarg{r} and \oarg{q} the angle is computed and then
+the point-sweep method is used. If the absolute value of the radius is
+less than half the distance between the points, then no such arc exists.
+In this case, the angle is just set equal to $\pm180$ degrees (as if the
+radius were changed to half the distance).
+
+\begin{cd}\pagelabel{sector}
+\cs{sector}\marg{\meta{$c$},\meta{$r$},\meta{$\theta_1$},\meta{$\theta_2$}}%
+\index{sector@\cs{sector}}%
+\end{cd}
+
+This figure macro produces the sector of the circle with center at the
+point \meta{$c$} and radius \meta{$r$}, from the angle \meta{$\theta_1$}
+to the angle \meta{$\theta_2$}. Both angles are measured in degrees
+anticlockwise from the direction parallel to the $x$ axis. The sector
+forms a closed path. \emph{Note}: \cs{sector} and \cs{arc}\oarg{p} have
+the same parameters, but \emph{in a different order}.%
+ \footnote{This apparently was unintended, but we now have to live
+ with it so as not to break existing \file{.tex} files.}
+
+
+\begin{cd}\pagelabel{ellipse}
+\cs{ellipse}\oarg{\meta{$\theta$}}\marg{\meta{$c$},\meta{$r_x$},\meta{$r_y$}}%
+\index{ellipse@\cs{ellipse}}%
+\end{cd}
+
+This figure macro produces an ellipse with the $x$ radius \meta{$r_x$}
+and $y$ radius \meta{$r_y$}, centered at the point \meta{$c$}. The
+optional parameter \meta{$\theta$} provides a way of rotating the
+ellipse by \meta{$\theta$} degrees anticlockwise around its center.
+Ellipses may also be created by differentially scaling a circle and
+perhaps rotating the result. See subsection~\ref{transformation}.
+
+\begin{cd}\pagelabel{fullellipse}
+\cs{fullellipse}\marg{\meta{$C$},\meta{$M_1$},\meta{$M_2$}}\\%
+\cs{halfellipse}\marg{\meta{$M_1$},\meta{$M_2$},\meta{$M_3$}}\\%
+\cs{quarterellipse}\marg{\meta{$M_1$},\meta{$A$},\meta{$M_2$}}%
+\index{fullellipse@\cs{fullellipse}}%
+\index{halfellipse@\cs{halfellipse}}%
+\index{quarterellipse@\cs{quarterellipse}}%
+\end{cd}
+
+For any parallelogram there is a unique ellipse incribed in it which is
+tangent to the sides at their midpoints. The above allows one to obtain
+that ellipse and parts of it. The input to \cs{fullellipse} is the
+center \meta{$C$} of that parallelogram and the midpoints \meta{$M_1$}
+and \meta{$M_2$} of two adjacent sides. For $\cs{halfellipse}$, one
+supplies the midpoints \meta{$M_1$}, \meta{$M_2$}, and \meta{$M_3$} of
+three successive sides. Lastly, \cs{quarterellipse} requires the
+midpoints of two adjacents sides and the corner \meta{$A$} between them.
+Internally, a quarter-circle is transformed to produce the
+quarter-ellipse and the other two are built up out of two or four such
+quarter-ellipses.
+
+The reasoning behind my choice of parameters is based on the anticipated
+use of these commands. For example, I wanted \cs{quarterellipse} to be
+used to round a corner represented by the three points $M_1$,
+$A$ and $M_2$. In order for the quarter-ellipse to have
+the same direction at $M_1$ and $M_2$ as the polygon $M_1AM_2$, the
+associated parallelogram has to have midpoints at $M_1$ and $M_2$.
+
+\begin{cd}\pagelabel{plr}
+\cs{plr}\marg{(\meta{$r_0$},\meta{$\theta_0$}),%
+ (\meta{$r_1$},\meta{$\theta_1$}), $\ldots$}%
+\index{plr@\cs{plr}}%
+\end{cd}
+
+When dealing with arcs and circles, it is useful to work in polar
+coordinates. The macro \cs{plr} causes \MF{} to replace the specified
+list of polar coordinate pairs by the equivalent list of rectangular
+(cartesian) coordinate pairs. Through \cs{plr}, commands designed for
+rectangular coordinates can be applied to data represented in polar
+coordinates. It must be cautioned that this wholesale conversion of a
+list applies only to commands that take a list consisting of an
+arbitrary number of points, such as \cs{polyline}.
+
+The effect of \cs{plr} is to apply a \MF{} command, \gbc{polar}, to each
+point in the list, producing a new list. This \MF{} command can also be
+used separately in any situation where a single \MF{} point is required. For
+example, to connect the point $(2,3)$ to the point with polar
+coordinates $(1, 135)$ write
+\begin{verbatim}
+\polyline{(2,3),polar(1,135)}
+\end{verbatim}
+
+This last circle-producing macro I wrote for my own use. It produces a
+circle associated with the hyperbolic geometry of a disk or a
+half-plane.
+
+\begin{cd}\pagelabel{pshcircle}
+\cs{pshcircle}\marg{\meta{center},\meta{radius}}\\
+\cs{pshcircle}*\marg{\meta{center},\meta{radius}}%
+\index{pshcircle@\cs{pshcircle}}%
+\end{cd}
+
+This produces the circle whose hyperbolic center is at \meta{center} and
+whose pseudohyperbolic radius is \meta{radius}. This all takes place
+inside the circle with center $(0,0)$ and radius $1$ (the \emph{unit
+circle}). The \meta{center} is required to be inside the unit circle and
+the \meta{radius} is required to be less than $1$.
+
+The star-form is for the \emph{upper half-plane}, which is the set of
+points with positive $y$-coordinate In this case, the \meta{center} must
+be in the upper half-plane and the \meta{radius} must still be less than
+$1$. If you are not versed in hyperbolic geometry, be warned that the
+actual diameter of the resulting circle is on the order of $2y/(1-R)$,
+where $R$ is the \meta{radius} and $y$ is the $y$-coordinate of
+\meta{center}. This can be quite large even for modest values of $R$ and
+$y$.
+
+Finally, an arc-producing macro. This is also related to the hyperbolic
+geometry of a disk or a half-plane. The hyperbolic geometry includes a
+notion of distance that allow one to determine `shortest' path between
+two points. This shortest path is called a `geodesic' and it turns out
+(in the case of the upper half-plane or a disk) to be an arc of a
+circle: the unique circle that passes through both points and meets the
+boundary (of the half-plane or disk) at right angles.
+
+\begin{cd}\pagelabel{hypergeodesic}
+\cs{hypergeodesic}\marg{$z_1$,$z_2$}\\
+\cs{hypergeodesic}*\marg{$z_1$,$z_2$}%
+\index{hypergeodesic@\cs{hypergeodesic}}%
+\end{cd}
+
+This produces the hyperbolic geodesic from $z_1=(x_1,y_1)$ to
+$z_2=(x_2,y_2)$. For guaranteed results both points should be in the
+unit disk (i.e., $|z_1| < 1$ and $|z_2| < 1$) or, for the star form,
+both in the upper half-plane (i.e., $y_1 > 0$ and $y_2 > 0$). However,
+if these are not satisfied an arc of the circle described above will be
+drawn whenever not prevented by a numeric overflow. The star form
+produces the geodesic for points in the upper half-plane. The normal
+form produces the geodesic for points in the unit disk (inside of the
+circle of radius $1$ and center $(0,0)$). One can use transforms of
+these to get geodesics suitable for other disks and other half-planes.
+
+
+\subsection{Curves}\label{curves}
+
+\begin{cd}\pagelabel{curve}
+\cs{curve}\oarg{\meta{tension}}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}\\
+\cs{cyclic}\oarg{\meta{tension}}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}\\
+\cs{closedcurve}\oarg{\meta{tension}}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}%
+\index{curve@\cs{curve}}%
+\index{cyclic@\cs{cyclic}}
+\index{closedcurve@\cs{closedcurve}}%
+\end{cd}
+
+These figure macros produce a smooth path through the specified points,
+in the specified order. It is `smooth' in two ways: it never changes
+direction abruptly (no `corners' or `cusps' on the curve), and it tries
+to make turns that are not too sharp. This latter property is acheived
+by specifying (to \MF{}) that the tangent to the curve at each listed
+point is to be parallel to the line from that point's predecessor to its
+successor. The \cs{cyclic} variant arranges for the last point to be
+connected (smoothly) to the first, and produces a closed \MF{} B\'ezier
+curve. The command \cs{closedcurve} is an alias for \cs{cyclic}.
+
+The optional \meta{tension} influences \emph{how} smooth the curve is.
+The special value \mfc{infinity} (in fact, usually anything greater than
+about $10$), makes the curve not visibly different from a polyline. The
+higher the value of tension, the sharper the corners on the curve and
+the flatter the portions in between. \CMF{} requires the tension to be
+larger than $0.75$. The default value of the tension is $1$ when \mfp{} is
+loaded, but that can be changed with the following command.
+
+\begin{cd}\pagelabel{settension}
+\cs{settension}\marg{\meta{num}}%
+\index{settension@\cs{settension}}
+\end{cd}
+
+This sets the default tension for all commands that take an optional
+tension parameter.
+
+\medskip
+Sometimes one would like a convex set of points to produce a convex
+curve. This will not always be the case with \cs{curve} or \cs{cyclic}.
+You can verify this with the following example, where the list of points
+traces a rectangle:
+\begin{verbatim}
+\cyclic{(0,0),(0,1),(1,1),(2,1),(2,0),(0,0)}
+\end{verbatim}
+To produce a convex curve, use one of the following:
+
+\begin{cd}\pagelabel{convexcurve}
+\cs{convexcurve}\oarg{\meta{tension}}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}\\
+\cs{convexcyclic}\oarg{\meta{tension}}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}\\
+\cs{closedconvexcurve}\oarg{\meta{tension}}\marg{\meta{$p_0$},\meta{$p_1$},$\ldots$}%
+\index{convexcurve@\cs{convexcurve}}%
+\index{convexcyclic@\cs{convexcyclic}}%
+\index{closedconvexcurve@\cs{closedconvexcurve}}%
+\end{cd}
+
+These figure macros can be used even if the list of points is not
+convex, and the result will be convex where possible. The third one is
+an alias for for the second one.
+
+\medskip
+Occasionally it is necessary to specify a sequence of points with
+\emph{increasing} $x$-coordinates and draw a curve through them. One
+would then like the resulting curve both to be smooth \textit{and} to
+represent a function (that is, the curve always has increasing $x$
+coordinate, never turning leftward). This cannot be guaranteed with the
+\cs{curve} command unless the tension is \texttt{infinity}.
+
+\begin{cd}\pagelabel{fcncurve}
+\cs{fcncurve}\oarg{\meta{tension}}\marg{($x_0$,$y_0$),($x_1$,$y_1$),$\ldots$}%
+\index{fcncurve@\cs{fcncurve}}%
+\end{cd}
+
+This figure macro produces a curve through the points specified. If the
+points are listed with increasing (or decreasing) $x$ coordinates, the
+curve will also have increasing (resp., decreasing) $x$ coordinates. The
+\meta{tension} is a number greater than $1/3$ which controls how tightly
+the curve is drawn. Generally, the larger it is, the closer the curve is
+to the polyline through the points. The default tension is that set with
+\cs{settension}, initially $1$. For those who know something about
+\MF{}, this `tension' is not the same as the \MF{} notion of tension
+(the tension in the \cs{curve} command), but it functions in a similar
+fashion. In this case it can actually be any positive number, but only
+values greater than $1/3$ guarantee the property of never doubling back.
+
+\begin{cd}\pagelabel{turtle}
+\cs{turtle}\marg{\meta{$p_0$},\meta{$v_1$},\meta{$v_2$},$\ldots$}%
+\index{turtle@\cs{turtle}}%
+\end{cd}
+
+This figure macro produces a a sequence of line segments starting from
+the point \meta{$p_0$}, and extending along the (2-dimen\-sional vector)
+displacement \meta{$v_1$}. The next segment is from the previous
+segment's endpoint, along displacement \meta{$v_2$}. This continues for
+all listed displacements, a process similar to `turtle graphics'.
+
+
+\subsection{Bar charts and pie charts}\label{charts}
+
+\begin{cd}\pagelabel{barchart}
+\cs{barchart}\oarg{\meta{start},\meta{sep},\meta{r}}%
+ \marg{\meta{h-or-v}}\marg{\meta{list}}\\
+\cs{bargraph}\dots\\
+\cs{gantt}\dots\\
+\cs{histogram}\dots\\
+\cs{mfpbarchart}\dots\\
+\cs{mfpbargraph}\dots\\
+\cs{mfpgantt}\dots\\
+\cs{mfphistogram}\dots
+\index{barchart@\cs{barchart}}%
+\index{bargraph@\cs{bargraph}}%
+\index{histogram@\cs{histogram}}%
+\index{gantt@\cs{gantt}}%
+\end{cd}
+
+The macro \cs{barchart} computes a bar chart or a Gantt chart. It does
+not draw the bars, but only defines their rectangular paths which the
+user may then draw or fill or both using the \cs{chartbar} macros (see
+below). Since bar charts have many names, \cs{bargraph} and
+\cs{histogram} are provided as synonyms. The macro \cs{gantt} is also a
+synonym; whether a Gantt chart or bar chart is created depends on the
+data.
+
+Since \cs{barchart} never draws anything, there is no particular reason
+it needs to be inside an \env{mfpic} environment. Starting with version
+0.9 of \mfp{} this is no longer required, but the command name
+\cs{mfpbarchart} must be used outside (in case some other package also
+defines \cs{barchart}). One can use any of the four synonyms listed that
+start with `\cs{mfp}'. The commands to draw the bars are still required to
+be inside an \env{mfpic} environment.
+
+\meta{h-or-v} should be \texttt{v} if you want the ends of the bars to
+be measured vertically from the $x$-axis, or \texttt{h} if they should
+be measured horizontally from the $y$-axis. \meta{list} should be a
+comma-separated list of numbers and ordered pairs giving the
+end(s) of each bar. A number $c$ is interpreted as the pair $(0,c)$; a
+pair $(a,b)$ is interpreted as an interval giving the ends of the bar
+(for Gantt diagrams). The rest of this description refers to the
+\texttt{h} case; the \texttt{v} case is analogous.
+
+By default the bars are 1 graph unit high (thickness), from $y = n-1$ to
+$y = n$. Their width and location are determined by the data. The
+optional parameter consists of three numeric parameters separated by
+commas. \meta{start} is the $y$-coordinate of the bottom edge of the
+first bar, \meta{sep} is the distance between the bottom edges of
+successive bars, and \meta{r} is the fraction of \meta{sep} occupied by
+each bar. The default behavior corresponds to \texttt{[0,1,1]}. In
+general, bar number $n$ will be from $y = \meta{start} +
+(n-1)*\meta{sep}$ to $y = \meta{start} + (n-1 + \meta{r})*\meta{sep}$
+
+Notice the bars are numbered in order from bottom to top. You can
+reverse them by making \meta{sep} negative, and making \meta{start} the
+top edge of the first bar.
+
+The fraction \meta{r} should be between $-1$ and $1$. A negative value
+reverses the direction from the ``leading edge'' of the bar to the
+`trailing edge'. For example, if one bar chart is created with
+\begin{ex}
+ \cs{barchart}\oarg{1,1,-.4}\marg{h}\marg{$\ldots$}
+\end{ex}
+and another with
+\begin{ex}
+ \cs{barchart}\oarg{1,1,.4}\marg{h}\marg{$\ldots$}
+\end{ex}
+both having the same number of bars, then the first will have its first
+bar from $y = 1$ to $y = 1 -.4 = .6$, while the second will have its
+first bar on top of that one, from $1$ to $1 + .4$. Similarly the next
+bars will be above and below $y=2$, etc. This makes it easy to draw bars
+next to one another for comparison.
+
+\begin{cd}\pagelabel{chartbar}
+\cs{chartbar}\marg{\meta{num}}\\
+\cs{graphbar}\marg{\meta{num}}\\
+\cs{histobar}\marg{\meta{num}}\\
+\cs{ganttbar}\marg{\meta{num}}%
+\index{chartbar@\cs{chartbar}}%
+\index{graphbar@\cs{graphbar}}%
+\index{histobar@\cs{histobar}}%
+\index{ganttbar@\cs{ganttbar}}%
+\end{cd}
+
+The figure macro \cs{chartbar} (synonyms \cs{graphbar}, \cs{ganttbar},
+and \cs{histobar}) takes a number from $1$ to the number of elements in
+the list of data of the most recent \cs{barchart} command and produces
+the corresponding rectangular path computed by that command. This
+behaves just like any other figure macro, and the prefix macros from
+section~\ref{rendering} may be used to give adjacent bars contrasting
+colors, fills, etc.
+
+
+\begin{cd}\pagelabel{piechart}
+\cs{piechart}\oarg{\meta{dir}\meta{angle}}\marg{\meta{$c$},\meta{$r$}}%
+ \marg{\meta{list}}\\
+\cs{mfppiechart}\dots
+\index{piechart@\cs{piechart}}%
+\end{cd}
+
+The macro \cs{piechart} also does not draw anything, but computes the
+\cs{piewedge} regions described below. The first part of the optional
+parameter, \meta{dir}, is a single letter to indicate a direction:
+`\texttt{c}' for \emph{clockwise} or `\texttt{a}' for \emph{anticlockwise}.
+The \meta{angle} is the angle in degrees of the starting edge of the
+first wedge. The defaults correspond to \oarg{c90}, which means the
+first wedge starts at 12~o'clock and proceeds clockwise.
+
+The first required argument contains the center \meta{$c$} and radius
+\meta{$r$} of the chart. The second required argument is the list of
+data: positive numbers separated by commas.
+
+Since this command never actually draws anything, only defining the
+wedges, it makes sense to heave it available outside the drawing
+environment. Starting with version 0.9 of \mfp{} that is the case, but
+the command name is \cs{mfppiechart} (to avoid a name clash with some
+other package's \cs{piechart} command). The command to draw wedges
+(\cs{piewedge}, see below) is still required to be inside an \env{mfpic}
+environment.
+
+\begin{cd}\pagelabel{piewedge}
+\cs{piewedge}\oarg{\meta{spec}\meta{trans}}\marg{\meta{num}}%
+\index{piewedge@\cs{piewedge}}%
+\end{cd}
+
+This figure macro takes a number from $1$ to the number of elements in
+the list of data of the most recent \cs{piechart} command and produces
+the corresponding wedge-shaped path computed by that command. By
+default, the path is positioned as computed by that \cs{piechart}
+command, but The optional argument to \cs{piewedge} can override this.
+The parameter \meta{spec} is a single letter, which can be \texttt{x},
+\texttt{s} or \texttt{m}. The \texttt{x} stands for \emph{exploded} and
+it means the wedge is moved directly out from the center of the pie a
+distance \meta{trans}. \meta{trans} should then be a pure number and is
+interpreted as a distance in graph units. The \texttt{s} stands for
+\emph{shifted} and in this case \meta{trans} should be a pair of the
+form \texttt{(\meta{dx},\meta{dy})} indicating the wedge should be
+shifted \meta{dx} horizontally and \meta{dy} vertically (in graph
+units). The \texttt{m} stands for \emph{move to}, and \meta{trans} is
+then the absolute coordinates \texttt{(\meta{x},\meta{y})} in the graph
+where the point of the wedge should be placed.
+
+
+\subsection{Braces}
+
+This figure is intended to group some graphical objects and label them.
+
+\begin{cd}\pagelabel{gbrace}
+\cs{gbrace}\marg{\meta{$z_1$},\meta{C},\meta{$z_2$}}%
+\index{grbace@\cs{gbrace}}%
+\end{cd}
+
+This figure macro creates the shape of a brace (i.e., a `$\}$') with its
+ends at \meta{$z_1$} and \meta{$z_2$} and its `center' cusp at
+\meta{C}. The three points must be expressed as ordered pairs or as
+\MF{} pair expressions, and must be separated by commas. The `width' of
+the brace (the distance from \meta{C} to the line through the other
+two points) is computed automatically and should not be $0$. The cusp of
+the brace will not necessarily be in the center of the brace. Users
+position it with their choice of \meta{C}. The cusp should not be
+positioned too close to one of the endpoints as this can distort the
+brace.
+
+
+\section{Colors in \mfp{}.}\label{colors}
+
+\subsection{\CMP{} color functions}\label{mpcolors}
+
+Because of changes to color handling with \MP{} 1.000, we will have to
+give two descriptions of some operations. For brevity, we will refer to
+\MP{} versions before the addition of the \kw{cmykcolor} data type as
+`early' \MP{} and the versions afterward as `recent' \MP{}. Early \MP{}
+actually ended with version 0.642. When development resumed, beta test
+versions began with 0.900. Any version 0.900 or later qualifies as
+`recent'.
+
+In early \MP{}, the only \kw{color} data type is a triple of numbers
+like \mfc{(1,.5,.5)}, with the components between 0 and 1, representing
+red, green and blue levels, respectively. White is given by
+\mfc{(1,1,1)} and black by \mfc{(0,0,0)}. Recent \MP{} has the
+\kw{color} data type (refered to as either \kw{color} or \kw{rgbcolor})
+as well as the \kw{cmykcolor} type. A \kw{cmykcolor} is a quadruple of
+numbers like \mfc{(1,.2,0,.3)}, with components between 0 and 1
+representing levels of cyan, magenta, yellow and black. White is
+represented by \mfc{(0,0,0,0)}. While black can be obtained in several
+ways,\mfc{(0,0,0,1)} is the simplest.
+
+\CMP{} also has \kw{color} variables (and \kw{cmykcolor} variables) and
+several have been predefined. The colors \mfc{red}, \mfc{green},
+\mfc{blue}, \mfc{white} and \mfc{black} are built in to \MP{} and are of
+type \kw{rgbcolor}. Colors \gbc{cyan}, \gbc{magenta} and \gbc{yellow}
+are defined by \mfp{}'s \MP{} support macros to be \kw{cmykcolor}. In
+addition, \mfp{} defines \gbc{grayscaleblack}, \gbc{grayscalewhite},
+\gbc{cmykblack}, \gbc{cmykwhite}, \gbc{rgbblack} and \gbc{rgbwhite}.
+These give black and white in the indicated data type (grayscale being a
+numeric: $0$ for black, $1$ for white).
+
+All the names in the \LaTeX{} \prog{color} package's \file{dvipsnam.def}
+have also been predefined by \mfp{} as color variable names. Since \MP{}
+allows color expressions, colors may be added together (as long as they
+are the same type) and multiplied by numerics. Multiplication by a
+number between $0$ and $1$ darkens a \kw{rgbcolor}, but lightens a
+\kw{cmykcolor}.
+
+Moreover, several \MP{} color functions have been defined in
+\file{grafbase.mp}. These have the same names as the color models.
+Strictly speaking, it is never necessary to use these in recent \MP{}.
+However, since \MF{} and early \MP{} don't have a data type consisting
+of quadruples, and \MF{} doesn't have one for triples, these functions
+allow the same \mfp{} code to be used for all three figure processors.
+These functions are defined to convert to a usable data type, (which may
+be ignored in \MF{}).
+
+\begin{cd}
+\mfc{cmyk($c$,$m$,$y$,$k$)}%
+\index{cmyk@\mfc{cmyk($c$,$m$,$y$,$k$)}}
+\end{cd}
+
+In early \MP{}, this converts a cmyk color specification to \MP{}'s
+native rgb. For example, the command \mfc{cmyk(1,0,0,0)} yields
+\mfc{(0,1,1)}, which is the rgb equivalent of cyan. In recent \MP{} this
+produces the \kw{cmykcolor} with the given components. That is,
+\gbc{cmyk(1,0,0,0)} simply produces $(1,0,0,0)$, the cmyk coding for
+cyan.
+
+\begin{cd}
+\mfc{gray($g$)}%
+\index{gray@\mfc{gray($g$)}}
+\end{cd}
+
+In early \MP{}, this converts a numeric $g$ (designating a level of
+gray) to the corresponding multiple of white: \mfc{($g$,$g$,$g$)}. In
+recent \MP{}, commands to draw paths or pictures in a particular color
+will accept a \kw{numeric} parameter instead of \kw{color} or
+\kw{cmykcolor}, so in recent \MP{} this command simply returns the given
+numeric $g$.
+
+\begin{cd}
+\mfc{named(\meta{name})},
+\mfc{rgb($r$,$g$,$b$)}%
+\index{named@\mfc{named(\meta{name})}}%
+\index{rgb@\mfc{rgb($r$,$g$,$b$)}}
+\end{cd}
+
+These are essentially no-ops. However; \mfc{rgb()} will truncate the
+arguments to the 0--1 range, and set an unknown argument to 0. An
+unknown \meta{name} is converted to \mfc{black} (in the appropriate
+color model if \meta{name} is an unknown color variable, otherwise rgb
+black).
+
+\begin{cd}
+\mfc{RGB($R$,$G$,$B$)}%
+\index{RGB@\mfc{RGB($R$,$G$,$B$)}}
+\end{cd}
+
+Converts an RGB color specification to rgb. It divides each component by
+255, and performs the same truncations as \gbc{rgb()}. The RGB model
+consists of a triple of numbers between 0 and 255. Originally, the model
+required they be integers. However, since they are converted to
+fractions anyway, it doesn't matter in this command.
+
+\medskip
+As an example of the use of these functions, in early \MP{} one could
+conceivable write:
+%
+\begin{verbatim}
+\draw[0.5*RGB(255,0,0)+0.5*cmyk(1,0,0,0)]\circle{(0,0),1}
+\end{verbatim}
+%
+to have a circle drawn in a color halfway between red and cyan (which
+turns out to be the same as \gbc{gray(0.5)}). In recent \MP{}, however,
+this would be an error, as one cannot add two different data types
+(\kw{rgbcolor} and \kw{cmykcolor}). So \mfp{} supplies conversion functions.
+
+\begin{cd}
+\mfc{makecmyk \meta{clr}}\\
+\mfc{makergb \meta{clr}}\\
+\mfc{makegray \meta{clr}}%
+\index{makecmyk@\mfc{makecmyk}}%
+\index{makergb@\mfc{makergb}}%
+\index{makegray@\mfc{makegray}}
+\end{cd}
+
+In recent \MP{}, the \meta{clr} can be a known color name, a constant
+of type \kw{numeric}, \kw{rgbcolor}, or \kw{cmykcolor}, or the result of
+a color function. Then \mfc{makecmyk} returns the \kw{cmykcolor}
+equivalent, and \mfc{makergb} returns the \kw{rgbcolor} equivalent (a
+\kw{numeric} \meta{clr} is interpreted as a grayscale color). Unknown
+colors produce a black in the appropriate model. Then one can use
+%
+\begin{verbatim}
+\draw{.5*RGB(255,0,0) + .5*makergb cmyk(1,0,0,0)}\circle{(0,0),1}
+\end{verbatim}
+%
+If one has forgotton whether \mfc{RGB} returns an \kw{rgbcolor}, one
+could write \verb$makergb RGB(255,0,0)$ to be sure to get an
+\kw{rgbcolor}.
+
+The first two commands are never necessary in early \MP{}, but they are
+still defined: they simply return the given color if it is a known
+argument of type \kw{color}, or apply the function \gbc{gray()} is it is
+\kw{numeric}, and return black for an unknown name.
+
+The last one \gbc{makegray} converts any color to a numeric, and then
+returns either that number (recent \MP) or that multiple of \mfc{white}
+(early \MP). In \MF{}, all three pass the (presumably numeric) argument
+\meta{clr} unchanged.
+
+All three functions return some version of black if \meta{clr} is not a
+color of some type, or has an unknown value.
+
+
+\subsection{Establishing \mfp{} default colors}\label{defaultcolors}
+
+\begin{cd}\pagelabel{drawcolor}
+\cs{drawcolor}\oarg{\meta{model}}\marg{\meta{colorspec}}\\
+\cs{fillcolor}\oarg{\meta{model}}\marg{\meta{colorspec}}\\
+\cs{hatchcolor}\oarg{\meta{model}}\marg{\meta{colorspec}}\\
+\cs{pointcolor}\oarg{\meta{model}}\marg{\meta{colorspec}}\\
+\cs{headcolor}\oarg{\meta{model}}\marg{\meta{colorspec}}\\
+\cs{tlabelcolor}\oarg{\meta{model}}\marg{\meta{colorspec}}\\
+\cs{backgroundcolor}\oarg{\meta{model}}\marg{\meta{colorspec}}%
+\index{drawcolor@\cs{drawcolor}}%
+\index{fillcolor@\cs{fillcolor}}%
+\index{hatchcolor@\cs{hatchcolor}}%
+\index{pointcolor@\cs{pointcolor}}%
+\index{headcolor@\cs{headcolor}}%
+\index{tlabelcolor@\cs{tlabelcolor}}%
+\index{backgroundcolor@\cs{backgroundcolor}}%
+\end{cd}
+
+
+These macros set the default color for various drawing elements. Any
+curve (with one exception, those drawn by \cs{plotdata}), whether solid,
+dashed, dotted, or plotted in symbols, will be in the color set by
+\cs{drawcolor}. Set the color used by \cs{gfill} with \cs{fillcolor}.
+For all the hatching commands use \cs{hatchcolor}. For the \cs{point},
+and \cs{plotsymbol} commands, as well as \cs{gridpoints} and
+\cs{plrgridpoints}, use \cs{pointcolor}, and for arrowheads,
+\cs{headcolor}. One can set the color used by \cs{gclear} with
+\cs{backgroundcolor} (the same color will also be used in the interior
+of unfilled points that are drawn with \cs{point}) and, when
+\opt{mplabels} is in effect, the color of labels can be set with
+\cs{tlabelcolor}.
+
+The optional \meta{model} may be one of \texttt{rgb}, \texttt{RGB},
+\texttt{cmyk}, \texttt{gray}, and \texttt{named}. The \meta{colorspec}
+depends on the model, as outlined below. Each of these commands sets a
+corresponding \MP{} color variable with the same name (except
+\cs{backgroundcolor} sets the color named \mfc{background}). Thus, after
+\texttt{drawcolor} has been set, one can issue the command
+\cs{fillcolor}\marg{drawcolor} to fill with the same color.
+
+As previously discussed, all these colors are initially set to
+\mfc{black} except \mfc{background} is set to \mfc{white}.
+
+If the optional \meta{model} argument is omitted, the color
+specification may be any expression recognized as a color by \MP{}. It
+is highly recommended (for portability) that one use either a predefined
+name or one of the color functions of the previous section.
+
+When the optional \meta{model} is specified in the color setting
+commands, it determines the format of the color specification as in
+figure~\ref{fig:colorspecs}.
+
+\begin{figure}[hbt]
+\halign{\quad\texttt{#}\hfil\quad&#\hfil\cr
+\omit\quad{\slshape Model:}\hfil& {\slshape Specification:}\cr
+rgb & Three numbers in the range 0 to 1 separated by commas.\cr
+RGB & Three numbers in the range 0 to 255 separated by commas.\cr
+cmyk & Four numbers in the range 0 to 1 separated by commas.\cr
+gray & One number in the range 0 to 1, with 0 indicating
+ black, 1 white.\cr
+named & A \MP{} color variable name either predefined by
+ \mfp{} or by the user.\cr}
+\caption{Color specifications}
+\label{fig:colorspecs}
+\end{figure}
+
+\pagebreak[3]
+\Mfp{} translates the command:
+\begin{verbatim}
+\fillcolor[cmyk]{1,.3,0,.2}
+\end{verbatim}
+into the equivalent of:
+\begin{verbatim}
+\fillcolor{cmyk(1,.3,0,.2)}.
+\end{verbatim}
+Note that when the optional model is specified, the color specification
+must \emph{not} be enclosed in parentheses. Note also that each model
+name is the name of a color function described in the previous
+subsection. That is how the models are implemented internally. One sees
+from this that the optional argument is never necessary. It's there only
+to make the \LaTeX{} user comfortable.
+
+
+\subsection{Defining a color name}\label{colorname}
+
+\begin{cd}\pagelabel{mfpdefinecolor}
+\cs{mfpdefinecolor}\marg{\meta{name}}\marg{\meta{model}}\marg{\meta{colorspec}}%
+\index{mfpdefinecolor@\cs{mfpdefinecolor}}
+\end{cd}
+
+This defines a color variable \meta{name} for later use, either in the
+commands \cs{drawcolor}, etc., or in the optional parameters to
+\cs{draw}, etc. The name can be used alone or in the \texttt{named} model.
+The mandatory \meta{model} and \meta{colorspec} are as above.
+
+\medskip
+A final caution, the colors of an \mfp{} figure are stored in the
+\file{.mp} output file, and are not related to colors used or defined by
+any \LaTeX{} package (such as \prog{color} or \prog{xcolor}). In
+particular a color defined only by \LaTeX{}'s \cs{definecolor} command
+will remain unknown to \mfp{}. Conversely, \LaTeX{} commands will not
+recognize any color defined only by \cs{mfpdefinecolor}.
+
+
+\subsection{\CMF{} colors}\label{MFcolor}
+
+\CMF{} was never meant to understand colors, but it certainly can be
+taught the difference between black and white and, to a limited extent,
+various grays. Starting with version 0.7, \mfp{} will not generate
+an error when a color-changing command is used under the \opt{metafont}
+option. Instead, when possible, the variables that represent colors in
+\MP{} will be converted to a numeric value between 0 and 1 in \MF{}. When
+possible (for example, when a region is filled) the numeric will be
+interpreted as a gray level and shading (see subsection~\ref{filling})
+will be used to approximate the gray. In other cases (drawing or dashing
+of curves, placing of points or symbols, filling with a pattern of hatch
+lines) the number will be interpreted as black or white: a value less
+than 1 will cause the figure to be rendered in black, while a value
+equal to 1 (white) will cause pixels corresponding to the figure to be
+erased.
+
+This depends on adhering to certain restrictions. \CMF{}'s syntax
+does not recognize a triple of numbers as any sort of data structure,
+but it does allow \emph{commands} to have any number of parameters in
+parentheses. So colors must be specified using the color commands such
+as \gbc{rgb(1,1,0)} or color names such as \gbc{yellow}, and never as a
+bare triple. Also, as currently written, the color names defined in
+\file{dvipsnam.mp} are not defined in \MF{}. With these provisions the
+same \mfp{} code can often produce either gray scale \MF{} pictures or
+\MP{} color pictures depending only on the \opt{metapost} option.
+
+The commands \cs{shade} and \cs{gfill}\oarg{gray(.75)} (see
+subsection~\ref{filling} for their meaning) will produce a similar shade
+of gray, but there is a difference. The first simply adds small dots on
+top of whatever is already drawn. The second, however, tries to simulate
+the \MP{} effect, which is to cover up whatever is previously drawn.
+Therefore, it first erases all affected pixels before adding the dots to
+simulate gray. In particular, \cs{gfill}\oarg{white} should have the
+same effect as \cs{gclear}.
+
+
+\section{Modifying the figures.}\label{modifier}
+
+Some \mfp{} macros operate by \emph{modifying} a figure macro: if you
+want to turn an open arc into a closed figure by adding a straight line,
+you can write:
+\begin{ex}
+ \cs{lclosed}\cs{arc}\marg{(0,0),(1,0),45}.
+\end{ex}
+These are always prefixed to some figure drawing command, and apply only
+to the next following figure macro provided that only other prefix
+commands intervene. This is a rather long section, but even more
+modification prefixes are documented in subsection~\ref{transformation}.
+
+The combination of a modifying macro, followed by a figure macro, can
+usually be thought of as a new figure macro, to which further prefixes
+might be prepended.
+
+More precisely: all prefix macros have an \emph{input} path, an
+\emph{output} path, and a \emph{side effect}. The input is the path that
+is output by the \emph{following} prefix or figure macro. The output is
+either the same as the input or a modification of it. The side effect
+might be a drawing or filling of the path or the addition of an
+arrowhead.
+
+We list here a classifications of prefix and figure macros that is
+useful for understanding the \mfp{} system.
+
+\begin{description}
+
+\item[Figure macros.] These\index{figure macro} take no input path; they
+ must come last in a sequence. They output the path they were
+ designed to produce. Examples are \cs{circle}, \cs{rect} and
+ \cs{polygon}. If they have no prefixes, or are preceded only by
+ appending macros (see next), they invoke a default rendering of the
+ path (usually a drawing as a solid stroke) as the side effect.
+
+\item[Appending macros] These\index{prefix macro} pass their input
+ unchanged as their output. Their side effect is the appending of
+ some object such as an arrow head or tail. Currently only the
+ various prefix macros whose names begin with \texttt{arrow} are
+ appending macros (see subsection~\ref{arrows}). But \cs{reverse},
+ which technically modifies a path and has no side effect, is coded
+ as an appending macro so that it will work correctly with arrows.
+ Think of it as `appending' a new direction.
+
+\item[Rendering macros] These\index{prefix macro} pass their
+ input unchanged as their output. They have the side effect of adding
+ or subtracting ink from a picture in the shape of the input path.
+ Examples are \cs{draw}, \cs{dotted}, \cs{gfill} and \cs{gclip}.
+
+\item[Modifying macros] These\index{prefix macro} output the result of
+ applying their intended modification to the input path. Examples are
+ macros that close the path if it was open, macros that apply a
+ transformation such as a rotation, and macros that return only a
+ part of a path. If they have no prefixes, or are preceded only by
+ appending macros (see above), they also invoke a default rendering
+ of the output path (usually a drawing as a solid stroke of the
+ modified path) as the side effect.
+
+\end{description}
+
+
+\subsection{Closure of paths}\label{closure}
+
+It should be pointed out that the closure macros will leave already
+closed paths unchanged, so it is always safe to add one when uncertain.
+Moreover, if the path is not closed but the endpoints are identical,
+\cs{lclosed} and \cs{bclosed} will close it without adding any path segment.
+
+
+\begin{cd}\pagelabel{lclosed}
+\cs{lclosed}$\ldots$\\
+\cs{bclosed}\oarg{\meta{tens}}$\ldots$\\
+\cs{sclosed}\oarg{\meta{tens}}$\ldots$%
+\index{lclosed@\cs{lclosed}}
+\index{bclosed@\cs{bclosed}}%
+\index{sclosed@\cs{sclosed}}
+\end{cd}
+
+These modifying macros all turn an open path into a closed one. If the
+path is already closed, they do nothing.
+
+\cs{lclosed} makes an open path into a closed path by adding a line
+segment between the endpoints of the path. In the special case where
+the path ends exactly where it begins, all \cs{lclosed} does is change
+the type of the path from open to closed.
+
+The \cs{bclosed} macro is similar to \cs{lclosed}, except that it closes
+an open path smoothly by drawing a B\'ezier curve. A B\'ezier is \MF{}'s
+natural way of connecting points into a curve, and \cs{bclosed} is the
+simplest and most efficient closure next to \cs{lclosed}. Moreover it
+usually gives a reasonably aesthetic result. Sometimes, however, one
+might wish a tighter connection. If that is the case, use the optional
+argument with a value of the tension \meta{tens} greater than $1$, the
+default. The command \cs{settension} (see subsection~\ref{curves}) can
+be used to change the default.
+
+\cs{sclosed} closes the curve by mimicking the definition of the
+\cs{curve} command. That command tries to force the curve to pass
+through the $n$th point in a direction parallel to the line from point
+$(n-1)$ to point $(n+1)$. In order to close a curve in this way, the
+direction at the two endpoints often has to be changed, and this changes
+the shape of the first and last segments of the curve. Use \cs{bclosed}
+if you don't wish this to happen. However, \cs{sclosed}\cs{curve}
+produces a result almost identical to \cs{cyclic} given the same points
+and tension values. The optional tension argument is as in the
+\cs{bclosed} command.
+
+There are two other closure commands but, because they are associated
+with particular types of paths (splines), we delay their discussion
+until those are discussed (subsection~\ref{splines}).
+
+\begin{cd}\pagelabel{makesector}
+\cs{makesector}\cs{arc}[\meta{fmt}]\marg{\meta{spec}}%
+\index{makesector@\cs{makesector}}
+\end{cd}
+
+The modifying macro \cs{makesector} can be applied to any path, but its
+name makes sense (and its action is predictable) only if that path is an
+arc. It appends line segments from the center of the arc's circle to the
+ends of the arc, producing a closed path. It is useful if one doesn't
+know where the center of the arc is (a required parameter of
+\cs{sector}). It works by selecting the first point, a middle point, and
+the last point of the following path, then calculates the center of the
+circle through those three points.
+
+
+\subsection{Reversal, connection and other path modifications}%
+\label{reversal}
+
+\begin{cd}\pagelabel{reverse}
+\cs{reverse}$\ldots$\\
+\cs{reversepath}\ldots%
+\index{reverse@\cs{reverse}}
+\index{reversepath@\cs{reversepath}}
+\end{cd}
+
+This modifies the following path by reversing its sense. This will
+affect the direction of arrows: bi-directional arrows can be coded with
+\cs{arrow}\cs{reverse}\cs{arrow}$\ldots$, where the leftmost \cs{arrow}
+prefix applies to the \emph{reversed} path. The order of endpoints for
+a \env{connect} environment will also be affected. The command
+\cs{reversepath} is exactly the same. It has been added (in vresion 1.10) to
+more closely match the names of other modification macros (see
+subsection~\ref{transformation}).
+
+\begin{cd}\pagelabel{connect}
+\cs{connect} $\ldots$ \cs{endconnect}%
+\index{connect@\cs{connect}}%
+\index{endconnect@\cs{endconnect}}
+\end{cd}
+
+The macro \cs{connect} produces a connected path by joining all the
+paths following it up to the matching \cs{endconnect} command. Line
+segments are added from the end of one path to the start of the next.
+The whole group acts as one figure macro, permitting any prefix macros
+to come before.
+
+In \LaTeX{}, instead of this pair of macros, an environment named
+\env{connect} may be used. For example
+\begin{verbatim}
+\lclosed
+\begin{connect}
+ \curve{(2,1),(1,2),(0,1)}
+ \polyline{(0,0),(2,0)}
+\end{connect}
+\end{verbatim}
+produces a closed figure consisting of one smooth curve and three line
+segments: the segment produced by \cs{polyline}, the segment added by
+the \env{connect} environment, and the segment added by \cs{lclosed}.
+
+
+\begin{cd}\pagelabel{partpath}
+\cs{partpath}\marg{\meta{frac1},\meta{frac2}}\dots\\
+\cs{subpath}\marg{\meta{num1},\meta{num2}}\dots\\
+\cs{trimpath}\marg{\meta{dim$_1$},\meta{dim$_2$}}\dots\\
+\cs{trimpath}\marg{\meta{dim}}\dots%
+\index{partpath@\cs{partpath}}%
+\index{subpath@\cs{subpath}}%
+\index{trimpath@\cs{trimpath}}%
+\end{cd}
+
+These macros modify the following path by producing only a part of it. In
+\cs{partpath} the parameters \meta{frac1} and \meta{frac2} should be
+numbers between 0 and 1. The path produced travels the same course as
+the path that follows, but starts at the point that is the fraction
+\meta{frac1} of the original length along it, and ends at the point
+\meta{frac2} of its original length. If \meta{frac1} is greater than
+\meta{frac2}, the sense of the path is reversed. In \cs{subpath}, the
+two numbers should be between 0 and the number of B\'ezier segments in
+the path. This is mainly for experienced \MF{}ers and provides an \mfp{}
+interface to \MF{}'s `\mfc{subpath}' operation.
+
+The \cs{trimpath} macro takes two dimensions separated by commas and
+trims those lengths off the initial and terminal ends of the following path.
+Alternatively, it takes one dimension and and trims that length off of
+both ends. If any of \meta{dim$_1$}, \meta{dim$_2$} or \meta{dim} is
+missing, it is taken to be \dim{0pt}. This works by finding the points of
+intersection between the path and circles around the endpoints with the given
+dimensions as radii. If the path is shorter than either dimension, it
+will not intersect either circle and nothing will be trimmed. Similar
+problems can occur, at one end or the other, if the path is shorter than
+the sum of the dimensions.
+
+\begin{cd}\pagelabel{parallelpath}
+\cs{parallelpath}\marg{\meta{dist}}$\ldots$
+\index{parallelpath@\cs{parallelpath}}
+\end{cd}
+
+This modifying macro takes the following path and returns a path that
+follows beside it, keeping a fixed distance \meta{dist} to the left. If
+\meta{dist} is negative, it keeps to the right. Left or right is from
+the point of view of a traveller following the given path from start to
+finish. The distance is a pure number in \emph{graph} coordinates. Note:
+this should be compared to the first optional argument of
+\cs{doubledraw} (see subsection~\ref{drawing}), which requires an
+absolute dimension like \dim{2pt}, even though it is implemented using
+the internal code of \cs{parallelpath}.
+
+The calculation of the parallel path is approximate and rather
+inefficient. It is likely to produce inexplicable small loops where it
+tries to follow the inside of tight turns (radius less than
+\meta{dist}). Actual corners, (which might be thought of as turns of
+radius $0$) are usually detected and dealt with in a reasonable manner.
+However, if the path is made up of segments of length \meta{dist} or
+less, this is unlikely to work correctly at all.
+
+\begin{cd}\pagelabel{arccomplement}
+\cs{arccomplement}\dots%
+\index{arccomplement@\cs{arccomplement}}
+\end{cd}
+
+This macro, to work properly, must be followed by an arc of a circle. It
+produces the complementary arc. That is, it produces the circular arc,
+which would, if appended to the following arc, complete the circle. The
+complementary arc will have the same direction, clockwise or
+anticlockwise, as the original. The arc that follows doesn't have to be
+produced by \cs{arc}, as in the following example:
+\begin{ex}
+ \cs{draw}\oarg{blue}\cs{arccomplement}\\
+\ \cs{draw}\oarg{red}\cs{partpath}\marg{0,.333}\\
+\ \cs{circle}\marg{(0,0),1}
+\end{ex}
+This will draw 1/3 of this circle in red and the rest of it in blue.
+
+\CMF{} cannot check if a path is really a circular arc. The \MF{} code,
+like that of \cs{makesector} (see subsection~\ref{closure}), selects
+three key points on the arc, then it produces the rest of the circle
+much the same way as the internal code of \cs{arc}\oarg{t} (the three
+point option for \cs{arc}). Thus, it will produce \emph{some} arc from
+the end of any following path to its beginning (or a straight line if
+the three chosen points happen to lie in a straight line). However, the
+result needn't bear any significant relation to the original path.
+
+\begin{cd}\pagelabel{interpolatepath}
+\cs{interpolatepath}\marg{\meta{frac},\meta{path1}}\dots
+\index{interpolatepath@\cs{interpolatepath}}
+\end{cd}
+
+This modifying macro takes the following path (call it \meta{path0}) and
+computes a new path that is \meta{frac} of the way ``between'' it and
+the argument \meta{path1}. The argument \meta{path1} would usually be
+the name of a \MF{} path variable used to store a figure (see \cs{store}
+from subsection~\ref{transformation}). However it can actually be any
+legal \MF{} path expression. The argument \meta{frac} is a number. If
+\meta{frac} is $0$, nothing is done and the following path \meta{path0}
+is produced; if \meta{frac} is $1$, then the argument \meta{path1} is
+produced. For values of \meta{frac} between $0$ and $1$ the resulting
+path is somewhere between the two. Numbers larger than $1$ or less than
+$0$ produce an extrapolated path. An ordered pair can be supplied
+instead of the argumant \meta{path1}: it will be interpreted as a
+trivial path. If \meta{path0} (the following figure) is closed and if
+\meta{path1} is an ordered pair or a closed path, then the resulting
+path will also be closed. Otherwise it will not be.
+
+What this command actually interpolates are the key points of the paths
+and the directions of travel at those key points. Therefore, if the two
+paths are visually very similar but have very different node structure,
+then the interpolated path can be quite unexpectedly different from both
+of them. For example
+\begin{verbatim}
+ \store{ABC}\circle{(0,0),1}
+ \interpolatepath{.5,ABC}\reverse\circle{(0,0),1}
+\end{verbatim}
+produces a straight line from $(1,0)$ to $(-1,0)$ (and back again).
+
+
+
+\subsection{Arrows}\label{arrows}
+
+\begin{cd}\pagelabel{arrow}
+\cs{arrow}\oarg{l\meta{headlen}}\oarg{r\meta{rotate}}%
+ \oarg{b\meta{backset}}\oarg{c\meta{color}}$\ldots$\\
+\cs{arrow*}\oarg{l\meta{headlen}}\oarg{r\meta{rotate}}%
+ \oarg{b\meta{backset}}\oarg{c\meta{color}}$\ldots$%
+\index{arrow@\cs{arrow}}
+\end{cd}
+
+This macro adds an arrowhead at the endpoint of the open path (or at the
+last key point of the closed path) that follows. The optional parameter
+\meta{headlen} determines the length of the arrowhead. The default is
+the value of the \TeX{} dimension \cs{headlen}, initially \dim{3pt}. The
+optional parameter \meta{rotate} allows the arrowhead to be rotated
+anticlockwise around its point an angle of \meta{rotate} degrees. The
+default is 0. The optional parameter \meta{backset} allows the arrowhead
+to be ``set back'' from its original point, thus allowing (for example)
+double arrowheads. This parameter is in the form of a \TeX{}
+dimension---its default value is \dim{0pt}. If an arrowhead is both
+rotated and set back, it is set back in the direction after the
+rotation. The optional \meta{color} defaults to \gbc{headcolor},
+initially black. The optional parameters may appear in any order, the
+indicated key character determining the meaning of a parameter. The key
+letter \texttt{l} for `length' can be replaced by \texttt{s} for `size'.
+
+There is also a star-form: If \cs{arrow} is called as \cs{arrow*}, then
+any part of the tip of the following curve that lies outside the
+arrowhead shape is clipped off. Imagine a rectangle with one side
+connecting the ends of the barbs and the opposite side passing through
+the tip. Everything in that rectangle outside the arrowhead is erased,
+so be careful using this (also see comments about \MP{}'s method of
+`erasing' in the description of \cs{gclear} in
+\cs{}subsection~\ref{filling}). One use of this is adding an arrowhead
+to a figure rendered with \cs{doubledraw} (see the next section) or with
+a rather large pen diameter (see section~\ref{parameters}).
+
+For the star-form to work, the head has to be added after the path is
+drawn. What this means in practice is that the \cs{arrow*} command must
+come before any drawing command in the list of prefixes. This is because
+prefix macros add their elements to the result of everything that
+follows. If you \cs{store} a curve in a path variable (see
+subsection~\ref{transformation}), and draw the path and the arrowhead in
+separate commands, then the arrow command must come \emph{after} the
+drawing command.
+
+\begin{cd}\pagelabel{arrowhead}
+\cs{arrowhead}\marg{\meta{symbol}}\oarg{l\meta{length}}\oarg{r\meta{rotate}}%
+ \oarg{b\meta{backset}}\oarg{c\meta{color}}$\ldots$\\
+\cs{arrowmid}\marg{\meta{symbol}}\oarg{l\meta{length}}\oarg{r\meta{rotate}}%
+ \oarg{f\meta{fraction}}\oarg{c\meta{color}}$\ldots$\\
+\cs{arrowtail}\marg{\meta{symbol}}\oarg{l\meta{length}}\oarg{r\meta{rotate}}%
+ \oarg{f\meta{forward}}\oarg{c\meta{color}}$\ldots$%
+\index{arrowhead@\cs{arrowhead}}%
+\index{arrowmid@\cs{arrowmid}}%
+\index{arrowtail@\cs{arrowtail}}
+\end{cd}
+
+These macros add some sort of symbol at different locations along a
+path. The first adds an arrowhead, but the head can be any appropriately
+designed symbol. It has been arranged that any of the symbols usable in
+\cs{plotsymbol} (see subsection~\ref{points}) can be used: you can have
+\gbc{Diamond}- or \gbc{Asterisk}-tipped arrows. The special symbol
+\gbc{Arrowhead} produces the same shape as the head in the \cs{arrow}
+command. In total eight special \meta{symbols} have been made available,
+intended for use with \cs{arrowhead}, \cs{arrowmid} and \cs{arrowtail}.
+Here is a list and description of all these symbols.
+\begin{description}
+ \item[\gbc{Arrowhead}] The\index{Arrowhead@\gbc{Arrowhead}} shape that
+ would be drawn at the end of a path by \cs{arrow}.
+ \item[\gbc{Leftharpoon}] The\index{Leftharpoon@\gbc{Leftharpoon}} left
+ half of \gbc{Arrowhead}.
+ \item[\gbc{Rightharpoon}] The\index{Rightharpoon@\gbc{Rightharpoon}}
+ right half of \gbc{Arrowhead}.
+ \item[\gbc{Crossbar}] A\index{Crossbar@\gbc{Crossbar}} short
+ line crossing the path perpendicularly unless rotated.
+ \item[\gbc{Leftbar}] Essentially\index{Leftbar@\gbc{Leftbar}} the left
+ half of \gbc{Crossbar}.
+ \item[\gbc{Rightbar}] The\index{Rightbar@\gbc{Rightbar}} right half.
+ \item[\gbc{Lefthook}] An\index{Lefthook@\gbc{Lefthook}} open
+ semicircle with its open face in the direction of the path, added to
+ the left side of the path.
+ \item[\gbc{Righthook}] Like\index{Righthook@\gbc{Righthook}}
+ \gbc{Lefthook} but on the right side.
+\end{description}
+Here `left' and `right' are from the point of view of an observer facing
+in the direction of the path.
+
+If the symbol is a closed path (see subsection~\ref{closure} for the
+difference between a closed path and one that merely looks closed), the
+head will be filled, otherwise its outline will be drawn. Thus
+\cs{arrowhead}\marg{Diamond} draws an outline, and
+\cs{arrowhead}\marg{SolidDiamond} draws a filled shape because
+\gbc{Diamond} has been left open, while \gbc{SolidDiamond} has been
+defined to be closed.
+
+It is possible, to get an outline drawn with the inside erased: just
+place the solid version with color \mfc{background} (usually the same as
+\mfc{white}) and then the outline version. This can produce a pleasing
+result. But recall that the prefix macro nearest the figure macro is
+executed first. For example:
+%
+\begin{verbatim}
+\arrowmid{Circle}\arrowmid{SolidCircle}[cwhite]\polyline{(0,0),(1,1)}
+\end{verbatim}
+
+The symbol is always rotated so that it points in the direction of the
+path (for this purpose, all symbols are initially assumed to point
+straight upward) before the \oarg{r\meta{rotate}} parameter is applied.
+
+There is a star-form \cs{arrowhead*} that behaves like \cs{arrow*} (when
+possible). The optional arguments are exactly as in \cs{arrow}, with the
+same defaults for all of them.
+
+The second command, \cs{arrowmid}, places the symbol somewhere between
+the start and the end of the path. In this case the optional parameter
+\oarg{f\meta{fraction}} gives the location of the symbol as a fraction
+of the length of the path. The default is \oarg{f0.5}, which places it
+approximately in the middle. The other optional arguments have the same
+meaning as for \cs{arrowhead}. As with \cs{arrowhead}, the symbol is
+rotated to `point' in the direction of the path before the
+\oarg{r\meta{rotate}} is applied.
+
+The third command \cs{arrowtail} places the symbol at the start of the
+path. Otherwise it behaves as the other two commands, except the option
+\oarg{f\meta{forward}} is an amount to shift the symbol forward from
+that first point.
+
+One might be tempted to use \cs{arrowmid} with the \meta{fraction} equal
+to $1$ or $0$ to get arrowheads or tails. This will work sometimes.
+However, some shapes have a `tip', that is, a particular point
+designated as the tip of the arrowhead. The \cs{arrowhead} and
+\cs{arrowtail} commands pay attention to this, while \cs{arrowmid} does
+not. Also, \cs{arrowmid} has no star-form.
+
+You can design your own \meta{symbol} for these commands: use \cs{store}
+to store a path in a path variable (see
+subsection~\ref{transformation}). These commands assume that the length
+is $1$, that the symbol `points' up and that the `tip' (the `pointy
+end') is at $(0,0)$ (unless the pair variable \meta{symbol}\gbc{.tip} is
+defined, in which case that is taken to be the tip). So draw your symbol
+pointing up with its tip at $(0,0)$ and its length equal to $1$ (graph
+unit). For example the following produces a solid head with a common
+shape:
+\begin{verbatim}
+\store{myAH}\polygon{(-.5,-1)(0,0),(0.5,-1),(0,-.7)}
+\arrowhead{myAH}\arc{(-10,0),(10,0),90}
+\end{verbatim}
+If you replace the \cs{polygon} above with \cs{polyline}:
+\begin{verbatim}
+\store{myAH}\polyline{(-.5,-1)(0,0),(0.5,-1),(0,-.7),(-.5,-1)}
+\end{verbatim}
+the path will not be closed and so the arrowhead will not be filled in.
+
+To make the star-form work with such self-defined symbols, one must also
+define a closed path \gbc{myAH.clear} that gives the region to be
+erased. In the above example:
+\begin{verbatim}
+\store{myAH.clear}\polygon{(-.5,-1),(-.5,0),(.5,0),(.5,-1),(0,-.7)}
+\end{verbatim}
+
+
+\section{Rendering figures.}\label{rendering}
+
+When \mfp{} is loaded, the initial way in which figures are drawn is
+with a solid outline. That is, \cs{polyline}\marg{(1,0),(1,1),(0,0)} will
+draw two solid lines connecting the points. It is possible to establish
+a different default (see \cs{setrender} in subsection~\ref{default}),
+however that default is used only when no explicit rendering prefix is
+present. That is, when the macros in this section are used, any
+previously established default is overridden.
+
+\begin{cd}\pagelabel{norender}
+\cs{norender}$\ldots$%
+\index{norender@\cs{norender}}%
+\end{cd}
+
+This causes the following path not to be rendered at all. This can be
+used to override \mfp{}'s automatic rendering rules. See
+section~\ref{transformation}, page~\pageref{norenderexample} for an
+example where one might need to do this.
+
+
+\subsection{Drawing}\label{drawing}
+
+\begin{cd}\pagelabel{draw}
+\cs{draw}\oarg{\meta{color}}$\ldots$%
+\index{draw@\cs{draw}}
+\end{cd}
+
+Draws the subsequent path using a solid outline. For an example: to both
+draw a curve and hatch its interior, \cs{draw}\cs{hatch} must be used.
+The default for \meta{color} is \gbc{drawcolor}.
+
+To save repetition, the color used for the following commands is also
+\gbc{drawcolor}:\\
+\cs{dashed}, \cs{dotted}, \cs{doubledraw}, \cs{plot}, \cs{plotnodes},
+and \cs{gendashed},
+
+\begin{cd}\pagelabel{doubledraw}
+\cs{doubledraw}\oarg{\meta{sep}}\oarg{\meta{color}}$\ldots$
+\index{doubledraw@\cs{doubledraw}}
+\end{cd}
+
+This rendering macro draws the path with a double line. The default
+separation (distance between centers of the two penstrokes) is twice the
+pen diameter. This normally leaves one line thickness of white space
+between. You can change this with the \oarg{\meta{sep}} argument. In
+order to make the space between the lines transparent, this command is
+implemented by calculating two curves that are parallel to the given
+curve and drawing those. For technical reasons, that calculation is
+rather lengthy so this is somewhat inefficient and users of slow
+machines might want to avoid it. See also comments at \cs{parallelpath}
+in subsection~\ref{reversal}.
+
+\begin{cd}\pagelabel{dashed}
+\cs{dashed}\oarg{\meta{length},\meta{space}}$\ldots$%
+\index{dashed@\cs{dashed}}
+\end{cd}
+
+This rendering macro draws dashed segments along the path specified.
+The default length of the dashes is the value of the \TeX{} dimension
+\cs{dashlen}, initially \dim{4pt}. The default space between the dashes
+is the value of the \TeX{} dimension \cs{dashspace}, initially
+\dim{4pt}. The dashes and the spaces between may be increased or
+decreased by as much as $1/n$ of their value, where $n$ is the number of
+spaces appearing in the curve, in order to have the proper dashes at the
+ends. The dashes at the ends are half of \cs{dashlen} long.
+
+\begin{cd}\pagelabel{dotted}
+\cs{dotted}\oarg{\meta{size},\meta{space}}$\ldots$%
+\index{dotted@\cs{dotted}}
+\end{cd}
+
+This rendering macro draws dots along the specified path. The default
+size of the dots is the value of the \TeX{} dimension \cs{dotsize},
+initially \dim{0.5pt}. The default space between the dots is the value
+of the \TeX{} dimension \cs{dotspace}, initially \dim{3pt}. The size of
+the spaces may be adjusted as in \cs{dashed}.
+
+\begin{cd}\pagelabel{plot}
+\cs{plot}\oarg{\meta{size},\meta{space}}\marg{\meta{symbol}}$\ldots$%
+\index{plot@\cs{plot}}
+\end{cd}
+
+Similar to \cs{dotted}, this rendering macro draws copies of
+\meta{symbol} along the path. Possible symbols are those listed under
+\cs{plotsymbol} in subsection~\ref{points}. The default \meta{size} is
+\cs{pointsize} (initially \dim{2pt}) and the default \meta{space} is
+\cs{symbolspace} (initially \dim{5pt}).
+
+\begin{cd}\pagelabel{plotnodes}
+\cs{plotnodes}\oarg{\meta{size}}\marg{\meta{symbol}}$\ldots$%
+\index{plotnodes@\cs{plotnodes}}
+\end{cd}
+
+This rendering macro places a symbol at each \emph{node} of the path
+that follows. Possible symbols are those listed under \cs{plotsymbol} in
+subsection~\ref{points}. A node is one of the points through which \MF{}
+draws its curve. If one of the macros \cs{polyline}\marg{$\ldots$} or
+\cs{curve}\marg{$\ldots$} follows, each of the points listed is a node.
+In the \cs{datafile} command (subsection~\ref{external}), each of the
+data points in the file is a node. In the function macros
+(subsection~\ref{plotting}) the points corresponding to \meta{min},
+\meta{max} and each step in between are nodes. The optional \meta{size}
+defaults to \cs{pointsize}. If the command \cs{clearsymbols} has been
+issued then the interiors of the open symbols are erased. The effect of
+something like the following is rather nice:
+\begin{verbatim}
+\clearsymbols
+\plotnodes{Circle}\draw\polyline{...}
+\end{verbatim}
+This will first draw the polyline with solid lines, and then the points
+listed will be plotted as open circles with the portion of the lines
+inside the circles erased. One sees a series of open circles connected
+one to the next by line segments
+
+
+\begin{cd}\pagelabel{dashpattern}
+\cs{dashpattern}\marg{\meta{name}}%
+ \marg{\meta{len1},\meta{len2},$\ldots$,\meta{len2k}}%
+\index{dashpattern@\cs{dashpattern}}
+\end{cd}
+
+For more general dash patterns than \cs{dashed} and \cs{dotted} provide,
+\mfp{} offers a generalized dashing command. Before using it, one must
+first establish a named dashing pattern with the above command. The
+\meta{name} can be any sequence of letters and underscores. Try to make
+it distinctive to avoid undoing some internal variable. \meta{len1}
+through \meta{len2k} are an even number of lengths. The odd ones
+determine the lengths of dashes, the even ones the lengths of spaces. A
+dash of length \texttt{0pt} means a dot. An alternating dot-dash pattern
+can be specified with
+\begin{verbatim}
+\dashpattern{dotdash}{0pt,4pt,3pt,4pt}
+\end{verbatim}
+\emph{Note}: Since pens have some thickness, dashes look a little
+longer, and spaces a little shorter, than the numbers suggest. If one
+wants dashes and spaces with the same length, one needs to take the size
+desired and increase the spaces by the thickness of the drawing pen
+(normally) \dim{0.5pt}) and decrease the dashes by the same amount.%
+ \footnote{Experienced \MP{} users could also set the \mfc{linecap}
+ variable to \mfc{butt}.}
+
+If \cs{dashpattern} is used with an odd number of entries, a space of
+length \dim{0pt} is appended. This makes the last dash in one copy of
+the pattern abut the first dash in the next copy.
+
+\begin{cd}\pagelabel{gendashed}
+\cs{gendashed}\marg{\meta{name}}$\ldots$%
+\index{gendashed@\cs{gendashed}}
+\end{cd}
+
+Once a dashing pattern name has been defined, it can be used in this
+figure macro to draw the curve that follows it. Using a name not
+previously defined will cause the curve to be drawn with a solid line,
+and generate a \MF{} warning, but \TeX{} will not complain. If all the
+dimensions in a dash pattern are 0, \cs{gendashed} responds by drawing a
+solid curve. The same is true if the pattern has only one entry.
+
+\begin{cd}\pagelabel{zigzag}
+\cs{zigzag}\marg{\meta{start},\meta{end},\meta{wl},\meta{amp}}\dots\\
+\cs{sinewave}\oarg{\meta{tens}}%
+ \marg{\meta{start},\meta{end},\meta{wl},\meta{amp}}\dots%
+\index{zigzag@\cs{zigzag}}%
+\index{sinewave@\cs{sinewave}}
+\end{cd}
+
+These figure macros both draw a solid line that crosses from one
+side of the path to the other. The \cs{zigzag} makes a jagged result
+while the \cs{sinewave} makes a smooth one. The optional argument of
+\cs{sinewave} is a `tension' and controls how smooth the result is. The
+default tension is $1$. Higher values make a less smooth path, and
+values of 10 or so produce a result almost indistinguishable from
+\cs{zigzag}. Tension is required to be greater than $3/4$.
+
+The mandatory arguments consists of four dimensions separated by a comma.
+The rendering produced by these macros actually follow the path a little
+way at the start and end of the path. This is controlled by the
+dimensions \meta{start} and \meta{end}.
+
+The third dimension, \meta{wl}, is the distance from one `peak' to the
+next (the `wavelength'). The second, \meta{amp}, is the maximum distance
+to either side of the true path (the `amplitude'). Reasonable values of
+\meta{wl} and \meta{amp} are \dim{8pt} and \dim{2pt}, respectively.
+These proportions (4 to 1) causes the zigzag and the sinewave to cross
+the path at an angle of about 45 degrees, a rather pleasant result.
+Those sizes are close to optimal: too much smaller and the rendering
+just looks like a fuzzy line, too much larger, and bends in the path
+will distort the zigzagging.
+
+The zigzags zig to the left first if \meta{amp} is positive, to the
+right if it is negative. For closed curves, the beginning and end are
+constructed to meet smoothly. It is always arranged that there are an
+equal number of left zigs and right zags, so the \meta{wl} is only
+approximate.
+
+
+\begin{cd}\pagelabel{corkscrew}
+\cs{corkscrew}\oarg{\meta{tens}}%
+ \marg{\meta{start},\meta{end},\meta{wl},\meta{amp}}\dots\\%
+\cs{coil}\oarg{\meta{tens}}%
+ \marg{\meta{start},\meta{end},\meta{wl},\meta{amp}}\dots%
+\index{corkscrew@\cs{corkscrew}}%
+\index{coil@\cs{coil}}
+\end{cd}
+
+This rendering macro draws a coil or corkscrew that coils around a
+given path, something like this: \includegraphics{coil.mps} (the red
+dots show the actual path). The \meta{tens} is a tension option that
+controls how `loopy' the result will be (the higher the number the more
+jagged). The mandatory argument contains four explicit dimensions. The
+first two, \meta{start} and \meta{end} are as in \cs{zigzag}. The
+\meta{wl} is the distance from one loop to the next, and \meta{amp} is
+the distance from the true path to the tops (or bottoms) of the
+loops. If \meta{amp} is positive, the tip of the loop is to the left
+of the path, if negative it is to the right. The example at the start of
+this paragraph was drawn using the following code:
+\begin{verbatim}
+\mfpic{0}{33}{0}{6.4}
+\dotsize=1pt
+\drawcolor{red}
+ \dotted\polyline{(0,3.2),(33,3.2)}
+\drawcolor{black}
+ \coil[1.5]{3pt,3pt,4.8pt,3.2pt}\polyline{(0,3.2),(33,3.2)}
+\endmfpic
+\end{verbatim}
+
+
+\subsection{Shading, filling, erasing, clipping, hatching}\label{filling}
+
+For the purposes of this section, a distinction must be made in the
+figure macros between `open' and `closed' paths. A path that merely
+returns to its starting point is \emph{not} automatically closed; such a
+path might be open and may need to be explicitly closed, for example by
+\cs{lclosed}. The (already) closed paths are those that have
+`\texttt{closed}' or `\texttt{cyclic}' in their name plus:
+\begin{display}
+ \cs{belowfcn}, \cs{border}, \cs{btwnfcn}, \cs{btwnplrfcn},
+ \cs{chartbar} (and its aliases),\\
+ \cs{circle}, \cs{ellipse}, \cs{fullellipse}, \cs{levelcurve},
+ \cs{makesector},\cs{piewedge},\\ \cs{plrregion},
+ \cs{polygon}, \cs{pshcircle}. \cs{rect}, \cs{regpolygon},
+ \cs{sector}, \cs{tlabelcircle},\\
+ \cs{tlabelellipse}, \cs{tlabeloval}, and \cs{tlabelrect}.
+\end{display}
+
+The macros of this section can all be used to fill (or unfill) the
+interior of closed paths, even if the paths cross themselves. Filling an
+open curve is technically an error, but the \MF{} code responds by
+drawing the path and not doing any filling. Note that these macros
+override the default rendering, so if you want some sort of fill pattern
+\emph{and} an outline drawn, you need an explicit prefix for both.
+
+\begin{cd}\pagelabel{gfill}
+\cs{gfill}\oarg{\meta{color}}$\ldots$%
+\index{gfill@\cs{gfill}}
+\end{cd}
+
+This rendering macro fills in the subsequent closed path. Under \MP{} it
+fills with \meta{color}, which defaults to
+\index{fillcolor@\gbc{fillcolor}}\gbc{fillcolor}. Under \MF{} it
+approximates the color with a shade of gray, clears the interior, and
+then fills with a pattern of black and white pixels simulating gray.
+
+\begin{cd}\pagelabel{gclear}
+\cs{gclear}$\ldots$%
+\index{gclear@\cs{gclear}}
+\end{cd}
+
+This rendering macro erases everything \emph{inside} the subsequent
+closed path (except text labels under some circumstances, see
+section~\ref{mplabels} and \ref{overlaylabels}). Under \MP{} it actually
+fills with the predefined color named \mfc{background}. Since
+\mfc{background} is normally \mfc{white}, and so are most actual
+backgrounds, this is usually indistinguishable from clearing. However,
+if an \env{mfpic} environment utilzes \emph{background text} (see
+subsection~\ref{text}), part of the background text may appear to be
+`erased'. Unfortunately, there is little that can be done about this.
+
+\begin{cd}\pagelabel{gclip}
+\cs{gclip}$\ldots$%
+\index{gclip@\cs{gclip}}
+\end{cd}
+
+This rendering macro erases everything \emph{outside} the subsequent
+closed path from the picture (except text labels under some
+circumstances, see section~\ref{mplabels} and \ref{overlaylabels}). Note
+that this is a true erasing, even in \MP{}.
+
+\begin{cd}\pagelabel{shade}
+\cs{shade}\oarg{\meta{shadesp}}$\ldots$%
+\index{shade@\cs{shade}}
+\end{cd}
+
+This rendering macro shades the interior of the subsequent closed path
+with dots. The diameter of the dots is the \MF{} variable \mfc{shadewd},
+set by the macro \cs{shadewd}\marg{\meta{size}}. Normally this is
+\dim{0.5bp}. The optional argument specifies the spacing between (the
+centers of) the dots, which defaults to the \TeX{} dimension
+\cs{shadespace}, initially \dim{1pt}. If \mfc{shadewd} is larger than
+\cs{shadespace}, the closed path is filled with black, as if with
+\cs{gfill}. Under \MP{} this macro actually fills the path's interior
+with a shade of gray. The shade to use is computed based on
+\cs{shadespace} and \mfc{shadewd}. The default values of these
+parameters correspond to a gray level of about 78\% of white.%
+ \footnote{If \cs{shadewd} is $w$ and \cs{shadespace} is $s$, then
+ the level of gray is $1 - (.88w/s)^2$, where $0$ denotes black and
+ $1$ white.} %
+The \MF{} version attempts to optimize the dots to the pixel grid
+corresponding to the printers resolution (to avoid generating dither
+lines). Because this involves rounding, it will happen that values of
+\cs{shadespace} that are relatively close and at the same time close to
+\mfc{shadewd} produce exactly the same shade. Most of the time, however,
+values of \cs{shadespace} that differ by at least 20\% will produce
+different patterns. The actual behavior for particular values of the
+parameters and particular printer resolutions cannot be predicted, and
+we even make no guarantee it will not change from one version of \mfp{}
+to another.
+
+\begin{cd}\pagelabel{polkadot}
+\cs{polkadot}\oarg{\meta{space}}$\ldots$%
+\index{polkadot@\cs{polkadot}}
+\end{cd}
+
+This rendering macro fills the interior of a closed path with large
+dots. This is almost what \cs{shade} does, but there are several
+differences. \cs{shade} is intended solely to simulate a gray fill in
+\MF{} where the only color is black. So it is optimized for small dots
+aligned to the pixel grid (in \MF{}). In \MP{} \cs{shade} only fills with
+gray and is intended merely for compatibility. The macro \cs{polkadot}
+is intended for large dots in any color, and so it optimizes spacing (a
+nice hexagonal array) and makes no attempt to align at the pixel level.
+The \meta{space} defaults to the \TeX{} dimension \cs{polkadotspace},
+initially \dim{10pt}. The diameter of the dots is the value of the \MF{}
+variable \mfc{polkadotwd}, which can be set with
+\cs{polkadotwd}\marg{\meta{size}}, and is initially \dim{5bp}. The dots
+are colored with \index{fillcolor@\gbc{fillcolor}}\gbc{fillcolor}. In
+\MF{}, nonblack values of \gbc{fillcolor} will produce shaded dots.
+
+\begin{cd}\pagelabel{thatch}
+\cs{thatch}\oarg{\meta{hatchsp},\meta{angle}}\oarg{\meta{color}}$\ldots$%
+\index{thatch@\cs{thatch}}
+\end{cd}
+
+This rendering macro fills a closed path with equally spaced parallel
+lines at the specified angle. The thickness of the lines is set by the
+macro \cs{hatchwd}. In the optional argument, \meta{hatchsp} specifies
+the space between lines, which defaults to the \TeX{} dimension
+\cs{hatchspace}, initially \dim{3pt}. The \meta{angle} defaults to 0.
+The \meta{color} defaults to \gbc{hatchcolor}. If \cs{hatchspace} is
+less than the line thickness, the closed path is filled with
+\meta{color}, as if with \cs{gfill}. If the first optional argument
+appears, both parts must be present, separated by a comma. For the color
+argument to be present, the other optional argument must also be
+present. However, if one wishes only to override the default color one
+can use an empty first optional argument (completely empty, no spaces or
+comma).
+
+An angle of $0$ yields horizontal lines, nonzero angles indicate
+rotations from horizontal where, as usual, positive angles indicate
+anticlockwise rotation.
+
+\begin{cd}\pagelabel{hatch}
+\cs{lhatch}\oarg{\meta{hatchsp}}\oarg{\meta{color}}$\ldots$\\
+\cs{rhatch}\oarg{\meta{hatchsp}}\oarg{\meta{color}}$\ldots$\\
+\cs{hatch}\oarg{\meta{hatchsp}}\oarg{\meta{color}}$\ldots$\\
+\cs{xhatch}\oarg{\meta{hatchsp}}\oarg{\meta{color}}$\ldots$%
+\index{lhatch@\cs{lhatch}}%
+\index{rhatch@\cs{rhatch}}%
+\index{hatch@\cs{hatch}}%
+\index{xhatch@\cs{xhatch}}%
+\end{cd}
+
+These rendering macros are just \cs{thatch} with predefined values of
+the angle. \cs{lhatch} fills the region with left slanted lines (from
+upper left to lower right). It is exactly the same as
+\begin{display}
+ \cs{thatch}\oarg{\meta{hatchsp},-45}\oarg{\meta{color}}$\ldots$
+\end{display}
+
+\cs{rhatch} draws right slanted lines (lower left to upper right). It is
+exactly the same as
+\begin{display}
+ \cs{thatch}\oarg{\meta{hatchsp},45}\oarg{\meta{color}}$\ldots$
+\end{display}
+
+\cs{hatch} (\cs{xhatch} is a synonym) draws lines in a cross-hatched
+pattern. It is exactly the same as \cs{rhatch} followed by \cs{lhatch}
+using the same \meta{hatchsp} and \meta{color}.
+
+Hatching should normally be used very sparingly, or never if
+alternatives are available (color, shading). However, hatching on top of
+another filling macro is a common way to fill in \emph{two} regions in
+such a way that the overlap area is clearly evident. Hatching is at
+least less garish than polkadots.
+
+\begin{cd}\pagelabel{gradient}
+\cs{gradient}\marg{\meta{clrfcn},\meta{width},\meta{angle}}$\ldots$%
+\index{gradient@\cs{gradient}}%
+\end{cd}
+
+Neither \MP{} nor \MF{} can do true gradients, but this rendering macro
+obtains a good approximation by filling adjacent narrow strips in a
+range of colors. The argument \meta{width} is the width of those strips,
+and it should be specified in absolute units, \meta{angle} is the angle
+of these strips (horizontal being $0$ degrees). The first argument
+takes a little explanation.
+
+The \meta{clrfcn} should be the name of a function, say \mfc{gr},
+such that \mfc{gr(t)} returns a color\footnote{It can also return a
+number between $0$ and $1$, which will result in shades of gray.} for
+any value of $t$ from $0$ to $1$ (inclusive). Such a function can be
+defined with \cs{fdef} (see subsection~\ref{defining}). The first strip
+will have the color returned for \mfc{t}${}=0$ and the last will have
+the color returned for \mfc{t}${}=1$. One kind of gradient fill is
+obtained by a simple interpolation between two colors in the same model:
+\begin{verbatim}
+\fdef{gr}{t}{(1-t)*red + t*blue}
+\gradient{gr,3pt,45}\circle{(0,0),1}
+\end{verbatim}
+This example will start the gradient with red and end it with blue. For
+an angle of $0$ the starting color is at the bottom and the ending color
+at the top, for other angles simply rotate that description. The above
+circle will be red at the lower right and blue at the upper left.
+
+This type of gradient is called an \emph{axial} gradient. The following
+is another kind, based on a color function of \emph{two} variables over
+an area.
+
+\begin{cd}\pagelabel{areagradient}
+\cs{areagradient}\marg{\meta{clrfcn},\meta{h-dim},\meta{v-dim}}$\ldots$%
+\index{areagradient@\cs{areagradient}}%
+\end{cd}
+
+Instead of filling with strips of different colors, \cs{areagradient}
+fills with ``pixels'' of different colors. These are rectangles that
+have size \meta{h-dim} by \meta{v-dim}, which values must be specified
+in absolute units. These rectangles are filled with the color determined
+by \meta{clrfcn}. This must be a function of \emph{two} parameters that
+returns a color for values of these parameters from $0$ to $1$
+(inclusive). For example,
+\begin{verbatim}
+\fdef{agr}{t,u}%
+ {(1-t)(1-u)*white + (1-t)*u*red + t*(1-u)*green + t*u*blue}
+\gradient{agr,3pt,4pt}\rect{(0,0),(1,2)}
+\end{verbatim}
+The color returned for $(0,0)$ is at the lower left and the color
+returned for $(1,1)$ is at the upper right. In the above example, the
+rectangle will be white at the lower left, red at the upper left, green
+at the lower right and blue at the upper right.
+
+Our last gradient is something like the first, but in polar coordinates.
+The colors vary with the distance from a center point.
+
+\begin{cd}\pagelabel{radialgradient}
+\cs{radialgradient}\marg{\meta{clrfcn},\meta{width},\meta{center}}$\ldots$%
+\index{radialgradient@\cs{radialgradient}}%
+\end{cd}
+
+This gradient fills with concentric circular strips whose center is
+\meta{center} and whose thickness is \meta{width}. The \meta{clrfcn} is
+as in \cs{gradient}. The circle of radius \meta{width} and center
+\meta{center} is filled with the color returned for parameter value $0$.
+The largest concentric circular strip is filled with the color returned
+for parameter value $1$.
+
+These commands all initially compute a bounding figure for the curve. In
+the first case it is a rotated rectangle, in the second case an upright
+rectangle, and in the third case a circle centered at the given point.
+The interiors of the rectangles are considered to have coordinates
+$(t,u)$ that vary from $(0,0)$ at the lower left to $(1,1)$ at the upper
+right. The inside of the circle is considered to have the polar
+coordinate $r$ ranging from $0$ at the center to $1$ at the boundary.
+The relevant coordinate(s) are fed to the specified \meta{clrfcn} and
+the returned color is used to fill the relevant portion of the rectangle
+or circle. The whole picture is then clipped to the boundaries of the
+given closed curve and the result added to the picture.
+
+The process is somewhat wasteful of memory in \MP{}, as each strip or
+pixel's path is kept in memory and written to the output file. This can
+be quite large for \cs{areagradient} if the pixel dimensions are too
+small. For example, covering a one inch square with pixels 1 point on
+each side takes over 5000 paths and the resulting EPS is over 100,000
+bytes in size. I would recommend dimensions on the order of 2 to 3
+points. Larger dimensions are not as visually appealing, and smaller
+dimensions waste memory with little improvement in appearence.
+
+This command works in \MF{} using a \meta{clrfcn} that returns numeric
+values in the range $0$ to $1$. The result is much like
+\cs{gfill}\oarg{\meta{clr}} (see the beginning of this section) except
+the dots simulating a gray fill will vary in size corresponding to the
+\meta{clrfcn}. The result will be disappointing unless there is
+considerable contrast between the lightest and darkest grays of the
+gradient. Therefore, it is recommended that the color function cover the
+entire range from $0$ to $1$ (black to white). There are no particular
+memory problems with gradients in \MF{}, at least no more so than gray
+fills.
+
+
+\subsection{Changing the default rendering}\label{default}
+
+\emph{Rendering} is the process of converting a geometric description
+into a drawing. In \MF{}, this means producing a bitmap (\MF{} stores
+these in \mfc{picture} variables), either by stroking (drawing) a path
+using a particular pen), or by filling a closed path. In \MP{} it means
+producing a \PS{} description of penstrokes and fills (with possible
+clipping).
+
+\begin{cd}\pagelabel{setrender}
+\cs{setrender}\marg{\meta{\TeX{} commands}}%
+\index{setrender@\cs{setrender}}
+\end{cd}
+
+Initially, \mfp{} uses the \cs{draw} command (stroking) as the default
+operation when a figure is to be rendered. However, this can be changed
+to any combination of \mfp{} rendering commands or indeed any \TeX{}
+commands, by using the \cs{setrender} command. This redefinition is
+local when it occurs inside an \env{mfpic} environment, so there it can
+be enclosed in braces to restrict its range. Outside an \env{mfpic}
+environment it is a global redefinition.
+
+For example, suppose one uses \cs{setrender}\marg{\cs{dashed}\cs{shade}}
+in a \env{mfpic} environment. If the command \cs{circle}\marg{(0,0),1}
+occurs later in that environment, it will produce a shaded circle with a
+dashed outline. If an explicit rendering prefix is given in a drawing
+command, it will override this default.
+
+
+\subsection{Examples}\label{examples}
+
+It may be instructive, for the purpose of understanding the syntax of
+\emph{shape-modifier and rendering prefixes}, to consider two examples:
+\begin{ex}
+ \cs{draw}\cs{gfill}\oarg{red}\cs{lclosed}\cs{polyline}\marg{$\ldots$}
+\end{ex}
+which fills inside a polygon and draws its outline; and
+\begin{ex}
+ \cs{gfill}[red]\cs{lclosed}\cs{draw}\cs{polyline}\marg{$\ldots$}
+\end{ex}
+which draws all of the outline \emph{except} the line segment supplied
+by \cs{lclosed}, then fills the interior. Thus, in the first case the
+path is first defined (by \cs{polyline}), then closed, then the resulting closed
+path is filled, and finally drawn. In the second case the order is:
+defined, drawn, closed, filled. In particular, what is drawn in the
+second case is the path not yet closed. It should also be pointed out
+that in the last case, the fill is placed last and will cover half
+the thickness of the previously drawn outline.
+
+
+\section{Functions and Plotting.}\label{functions}
+
+In the following macros, expressions like $f(\mathtt{x})$ or $g(\mathtt{t})$
+stand for any legal \MF{} expression, in which the only unknown
+variables are those indicated (\texttt{x} in the first case, and \texttt{t} in
+the second).
+
+
+\subsection{Defining functions}\label{defining}
+
+\begin{cd}\pagelabel{fdef}
+\cs{fdef}\marg{\meta{fcn}}\marg{\meta{param1},\meta{param2},$\ldots$}%
+ \marg{\meta{mf-expr}}%
+\index{fdef@\cs{fdef}}
+\end{cd}
+
+Defines a \MF{} function \meta{fcn} of the parameters \meta{param1},
+\meta{param2}, $\ldots$, by the \MF{} expression \meta{mf-expr} in which
+the only free parameters are those named. The return type of the
+function is the same as the type of the expression. What is allowed for
+the function name \meta{fcn} is more restrictive than \MF{}'s rule for
+variable names. Roughly speaking, it should consist of letters and
+underscore characters only. (In particular, for those who know what
+this means, the name should have no suffixes.) Try to make the name
+distinctive to avoid redefining internal \MF{} commands.
+
+The expression \meta{mf-expr} is passed directly into the corresponding
+\MF{} macro and interpreted there, so \MF{}'s rules for algebraic
+expressions apply. If \cs{fdef} occurs inside an \env{mfpic}
+environment, it is local to that environment, otherwise it is available
+to all subsequent \env{mfpic} environments.
+
+As an example, after \cs{fdef}\marg{myfcn}\marg{s,t}\marg{s*t-t}, any
+place below where a \MF{} expression is required, you can use
+\mfc{myfcn(2,3)} to mean \mfc{2*3-3} and \mfc{myfcn(x,x)} to mean
+\mfc{x*x-x}.
+
+Operations available include \mfc{+}, \mfc{-}, \mfc{*}, \mfc{/}, and
+\mfc{**} (\mfc{x**y}$=x^y$), with `\mfc{(}' and `\mfc{)}' for grouping.
+Functions already available include the standard \MF{} functions
+\mfc{round}, \mfc{floor}, \mfc{ceiling}, \mfc{abs}, \mfc{sqrt},
+\mfc{sind}, \mfc{cosd}, \mfc{mlog}, and \mfc{mexp}. Note that in \MF{}
+the operations \mfc{*} and \mfc{**} have the same level of precedence,
+so \mfc{x*y**z} means $(xy)^z$. Use parentheses liberally!
+
+(\textit{Notes:} The \MF{} trigonometric functions \mfc{sind} and
+\mfc{cosd} take arguments in degrees; \mfc{mlog(x)}$=256\ln x$, and
+\mfc{mexp} is its inverse.) You can also define the function \meta{fcn}
+by cases, using the \MF{} conditional expression
+\begin{ex}
+ \mfc{if~\meta{boolean}:~\meta{expr}~elseif
+ \meta{boolean}:~$\ldots$~else:~\meta{expr}~fi}.
+\end{ex}
+Relations available for the \meta{boolean} part of the expression
+include \mfc{=}, \mfc{<}, \mfc{>}, \mfc{<=}, \mfc{<>} and \mfc{>=}.
+
+Complicated functions can be defined by a compound expression, which is
+a series of \MF{} statements, followed by an expression, all enclosed
+between \mfc{begingroup} and \mfc{endgroup}. The \cs{fdef} command
+automatically supplies these grouping commands around the definition so
+if the entire \meta{mf-expr} is one such compound expression the user
+need not type them. \CMF{} functions can call \MF{} functions, even
+recursively.
+
+Many common functions have been predefined in \file{grafbase}, which is
+a package of \MF{} macros that implement \prog{mfpic}'s drawing. These
+include the rest of the trig functions \mfc{tand}, \mfc{cotd}, \mfc{secd},
+\mfc{cscd}, which take angles in degrees, plus variants \mfc{sin},
+\mfc{cos}, \mfc{tan}, \mfc{cot}, \mfc{sec}, and \mfc{csc}, which take
+angles in radians. Some inverse trig functions are also available, the
+following produce angles in degrees: \mfc{asin}, \mfc{acos}, and
+\mfc{atan}, and the following in radians: \mfc{invsin}, \mfc{invcos},
+\mfc{invtan}. The exponential and hyperbolic functions: \mfc{exp},
+\mfc{sinh}, \mfc{cosh}, \mfc{tanh}, \mfc{coth}, \mfc{sech}, and
+\mfc{csch}; and some of their inverses: \mfc{ln} (or \mfc{log}),
+\mfc{asinh}, \mfc{acosh}, and \mfc{atanh} are also defined.
+
+There are also two conversion functions: \gbc{radians(t)} produces the
+number of radians in \mfc{t} degrees and \gbc{degrees(t)} produces the
+number of degrees in \mfc{t} radians. In these expressions the special
+variable \gbc{pi} produces $\pi$, accurate to roughly 5 decimals.
+(\CMF{} and \MP{} provide accuracy only to $\pm2^{-17} = \pm
+.76\times10^{-5}$.)
+
+The integer functions \gbc{gcd(m,n)} and \gbc{lcm(m,n)} produce the
+greatest common divisor and least common multiple of two integers
+\gbc{m} and \gbc{n}.
+
+
+\subsection{Plotting functions}\label{plotting}
+
+The plotting macros take two or more arguments. They have an optional
+first argument, \meta{spec}, which determines whether a function is
+drawn smooth (as a \MF{} B\'ezier curve), or polygonal (as line
+segments)---if \meta{spec} is \texttt{p}, the function will be
+polygonal. Otherwise the \meta{spec} should be \texttt{s}, followed by
+an optional positive number no smaller than 0.75. In this case the
+function will be smooth with a tension equal to the number. See the
+\cs{curve} command (subsection~\ref{curves}) for an explanation of
+tension. The default \meta{spec} depends on the purpose of the macro.
+
+One compulsory argument contains three values \meta{min}, \meta{max} and
+\meta{step} separated by commas. The independent variable of a function
+starts at the value \meta{min} and steps by \meta{step} until reaching
+\meta{max}. If (\meta{max}${}-{}$\meta{min})/\meta{step} is not a whole
+number, the nearest whole number of equal steps are used. One may have
+to experiment with the size of \meta{step}, since \MF{} merely connects
+the points corresponding to these steps with what \emph{it} considers to
+be a smooth curve. Smaller \meta{step} gives better accuracy, but too
+small may cause the curve to exceed \MF{}'s capacity or slow down its
+processing. Increasing the tension may help keep the curve in line, but
+at the expense of reduced smoothness.
+
+There are one or more subsequent arguments, each of which is a \MF{}
+function or expression as described above. All the macros are figure
+macros, defining a path to which prefixes may be applied.
+
+\begin{cd}\pagelabel{function}
+\cs{function}\oarg{\meta{spec}}\marg{\meta{$x_{\mathrm{min}}$},%
+ \meta{$x_{\mathrm{max}}$},\meta{$\Delta x$}}%
+ \marg{$f(\mathtt{x})$}%
+\index{function@\cs{function}}
+\end{cd}
+
+This figure macro produces an approximation to the graph of $y = f(x)$,
+where $f$ is a \MF{} numeric function or expression of one numeric
+argument, which must be denoted by a literal \texttt{x}. The default
+\meta{spec} is \texttt{s}. For example
+\begin{verbatim}
+\function{0,pi,pi/10}{sin x}
+\end{verbatim}
+draws the graph of $\sin x$ between 0 and $\pi$.
+
+\begin{cd}\pagelabel{parafcn}
+\cs{parafcn}\oarg{\meta{spec}}\marg{\meta{$t_{\mathrm{min}}$},%
+ \meta{$t_{\mathrm{max}}$},\meta{$\Delta t$}}%
+ \marg{($x(\mathtt{t}), y(\mathtt{t})$)}\\
+\cs{parafcn}\oarg{\meta{spec}}\marg{\meta{$t_{\mathrm{min}}$},%
+ \meta{$t_{\mathrm{max}}$},\meta{$\Delta t$}}%
+ \marg{\meta{pair-fcn}}%
+\index{parafcn@\cs{parafcn}}
+\end{cd}
+
+This figure macro produces the parametric path determined by the last
+argument. This can be a pair of expressions $x(\mathtt{t})$ and
+$y(\mathtt{t})$ enclosed in parentheses and separated by a comma, with
+the literal variable \texttt{t}. Alternatively, the last argument can be
+a \MF{} function or expression in \texttt{t} that returns a pair.%
+ \footnote{There are very few of these. \CMF{} provides
+ \codebox{dir t}, which is essentially
+ \codebox{(cosd t, sind t)}. \Mfp{} adds \codebox{cis t} which
+ is \codebox{(cos t, sin t)}.}
+The default \meta{spec} is \texttt{s}. For example
+\begin{verbatim}
+\parafcn{0,1,.1}{(2t, t+t*t)}
+\end{verbatim}
+plots a smooth parabola from $(0,0)$ to $(2,2)$.
+
+\begin{cd}\pagelabel{plrfcn}
+\cs{plrfcn}\oarg{\meta{spec}}\marg{\meta{$\theta_{\mathrm{min}}$},%
+ \meta{$\theta_{\mathrm{max}}$},\meta{$\Delta\theta$}}%
+ \marg{$f(\mathtt{t})$}%
+\index{plrfcn@\cs{plrfcn}}
+\end{cd}
+
+This figure macro produces the graph of the polar coordinate equation
+$r=f(\theta)$, where $f$ is a \MF{} numeric function or expression of
+one numeric argument, and $\theta$ varies from
+\meta{$\theta_{\mathrm{min}}$} to \meta{$\theta_{\mathrm{max}}$} in
+steps of \meta{$\Delta\theta$}. Each $\theta$ value is interpreted as an
+angle measured in \emph{degrees}. In the expression $f(\mathtt{t})$, the
+unknown \texttt{t} stands for $\theta$. The default \meta{spec} is
+\texttt{s}. For example
+\begin{verbatim}
+\plrfcn{0,90,5}{sind (2t)}
+\end{verbatim}
+draws one loop of a 4-petal rosette. Note that this function demands the
+variable \mfc{t} be in degrees. The range and step size must be in
+degrees and the function must operate on the numeric variable \gbc{t} in
+degrees. If one needs to measure angles in radians, use the conversion
+functions \gbc{degrees()} and \gbc{radians()}, as follows:
+\begin{verbatim}
+\plrfcn{0,degrees(pi/2),degrees(pi/36)}{sin (radians(2t))}
+\end{verbatim}
+
+
+\begin{cd}\pagelabel{btwnfcn}
+\cs{btwnfcn}\oarg{\meta{spec}}\marg{\meta{$x_{\mathrm{min}}$},%
+ \meta{$x_{\mathrm{max}}$},\meta{$\Delta x$}}%
+ \marg{$f(\mathtt{x})$}\marg{$g(\mathtt{x})$}\\
+\cs{btwnplrfcn}\oarg{\meta{spec}}\marg{\meta{$\theta_{\mathrm{min}}$},%
+ \meta{$\theta_{\mathrm{max}}$},\meta{$\Delta \theta$}}%
+ \marg{$f(\mathtt{t})$}\marg{$g(\mathtt{t})$}%
+\index{btwnfcn@\cs{btwnfcn}}%
+\index{btwnplrfcn@\cs{btwnplrfcn}}
+\end{cd}
+
+These are figure macros. The first one produces a closed path
+surrounding the region between the graphs of the two functions. The
+second one does the same for two polar functions. That is (in both
+cases), the path follows the first function (in order or increasing $x$
+or $\theta$), thence along the straight line to the \emph{end} of the
+second one, thence backwards along the second function (decreasing $x$
+or $\theta$) and finally along the straight line to the start. The last
+two mandatory arguments, the functions, are specified exactly as in
+\cs{function} and \cs{plrfcn}, being numeric functions of one numeric
+argument \texttt{x} or \texttt{t}. Unlike the previous function macros,
+the default \meta{spec} is \texttt{p}---these macros are intended to be
+used for shading between drawn functions, a task for which smoothness is
+usually unnecessary. For example, the first line below
+\begin{verbatim}
+\shade\btwnfcn{0,1,.1}{0}{x - x**2}
+\btwnplrfcn[s]{-30,30,5}{1}{2*cosd 2t}
+\end{verbatim}
+shades the area between the $x$-axis and the given parabola. The second
+draws the boundary of the region between the circle $r = 1$ and one loop
+of the rosette $r = 2\cos 2\theta$.
+
+Note: the effect of \cs{btwnfcn} could also be accomplished with
+\begin{ex}
+ \cs{lclosed}\cs{connect}\\
+ \cs{function}\marg{\meta{$x_{\mathrm{min}}$},%
+ \meta{$x_{\mathrm{max}}$},\meta{$\Delta x$}}\marg{$f(\mathtt{x})$}\\
+ \cs{reverse}\cs{function}\marg{\meta{$x_{\mathrm{min}}$},%
+ \meta{$x_{\mathrm{max}}$},\meta{$\Delta x$}}\marg{$g(\mathtt{x})$}\\
+ \cs{endconnect}
+\end{ex}
+\cs{lclosed} was described in subsection~\ref{closure} and the
+\cs{connect}\dots\cs{endconnect} pair was described in
+subsection~\ref{reversal}.
+
+\begin{cd}\pagelabel{belowfcn}
+\cs{belowfcn}\oarg{\meta{spec}}%
+ \marg{\meta{$x_{\mathrm{min}}$},\meta{$x_{\mathrm{max}}$},%
+ \meta{$\Delta x$}}\marg{$f(\mathtt{x})$}\\
+\cs{plrregion}\oarg{\meta{spec}}%
+ \marg{\meta{$\theta_{\mathrm{min}}$},\meta{$\theta_{\mathrm{max}}$},%
+ \meta{$\Delta\theta$}}\marg{$f(\mathtt{t})$}%
+\index{belowfcn@\cs{belowfcn}}%
+\index{plrregion@\cs{plrregion}}
+\end{cd}
+
+These figure macros produce identical results to \cs{btwnfcn} and
+\cs{btwnplrfcn} when the first function is just $0$. They are, however,
+much more efficient. The first of these, \cs{belowfcn}, produces the
+path surrounding the region bounded by the $x$-axis, the graph of
+$y=f(x)$ and the two vertical lines $x=x_{\mathrm{min}}$ and $x =
+x_{\mathrm{max}}$. (The region is not actually \emph{below} $y = f(x)$
+unless $f(x) \ge 0$ throughout the interval.) The second produces the
+path surrounding the region bounded by the polar function $r =
+f(\theta)$ and the two rays $\theta=\theta_{\mathrm{min}}$ and
+$\theta=\theta_{\mathrm{max}}$.
+
+The arguments of these command are the same as the nonclosed versions,
+\cs{function} and \cs{plrfcn}, except the default for the optional
+agument is \texttt{[p]}. Again, this is because it is mainly for
+shading. However, drawing the boundary is often needed:
+\begin{verbatim}
+\shade\plrregion{0,90,5}{sind (2t)}
+\plrregion[s]{0,90,5}{sind (2t)}
+\end{verbatim}
+shades one loop of the 4-petal rosette, and then draws it.
+
+The next sets of macros are similar to the previous function plotting
+macros, but don't fit the \meta{max}, \meta{min} \meta{step} model for
+the first argument. For the first (\cs{levelcurve}) this is a limitation
+of the task being performed. For the others (\cs{DEgraph},
+\cs{DEtrajectory}) it is a design choice.
+
+\begin{cd}\pagelabel{levelcurve}
+\cs{levelcurve}\oarg{\meta{spec}}\marg{\meta{seed},\meta{step}}
+ \marg{\meta{inequality}}%
+\index{levelcurve@\cs{levelcurve}}
+\end{cd}
+
+This figure macro produces a level curve of some function $F(x,y)$.
+There are three requirements on the parameters for this to work
+correctly. First, in order to obtain the curve satisfying $F(x,y) = C$,
+the \marg{\meta{inequality}} must be either \verb${F(x,y) > C}$ or
+\verb${F(x,y) < C}$.%
+ \footnote{A non-strict inequality such as \mfc{>=} can be
+ used, but the result will not be significantly different.}
+Second, the level curve must surround the point given by the \meta{seed}
+paramter, and third, the inequality must be true at this seed point.
+
+The command works by searching rightward from \meta{seed} until it
+encounters the first point on the level curve. It then tries to find a
+nearby point on the level curve and joins it to the first one, and
+continues similarly until it finds it has returned near the starting
+point. The meaning of ``nearby point on the level curve'' is the
+intersection of the level curve with a circle of radius \meta{step}
+centered at the previously found point. If the region defined by the
+inequality extends beyond the bounds of the picture (as set by the
+\cs{mfpic} command), the region is truncated and the resulting curve
+will follow along the picture's border.
+
+Since the algorithm only approximates the level set, a tolerance (how
+close the points are to actually being \emph{on} the level curve) is
+chosen which gives two decimal places more accuracy than \meta{step}.
+The value of \meta{step} is interpreted in \emph{graph} units and
+so should be a pure number. The \oarg{\meta{spec}} is either \oarg{p},
+in which case the calculated points are joined with straight lines, or
+\oarg{s\meta{tension}} as in \cs{function}. The default is
+\oarg{s}: a smooth curve with the current default tension.
+
+In general, choosing a \meta{step} that corresponds to a few millimeters
+works reasonably well. For example, if the graph unit is 1cm (for
+example, \cs{mfpicunit=1cm} and no scaling is used), then
+\meta{step}${}= 0.5$ might be a reasonable first choice. If the level
+set is reasonably smooth and \oarg{s} is used, then the result will
+match the actual curve to within .005cm, which is approximately .14pt,
+which is less than half the thickness of the standard pen used to draw
+it.
+
+Be warned that there is a limit: there should not be more than 2000
+steps in the completed curve. In a figure which is 10-by-10 graph units,
+a level curve without too much oscillation would probably be less than
+80 units in length and a step size of .04 would probably produce under
+2000 steps. This should be accurate enough for most purposes. If you
+\emph{really} need more, the value of the \MF{} variable
+\verb$max_points$ must be changed. This can be done with
+\cs{setmfvariable} (see section~\ref{variables}).
+
+As a special case, if \meta{step} is 0, the maximum of width and height
+of the figure (as given by the arguments to the \env{mfpic} environment)
+is divided by 100. For example, in a 5-by-10 graph, giving a step size
+of $0$ will actually select \meta{step}${}= 10/100 = 0.1$.
+
+The algorithm used will produce imprecise results if there are two
+points on the curve closer than \meta{step} in straight-line distance,
+but much further apart when measured along the curve.
+
+\begin{cd}\pagelabel{DEgraph}
+\cs{DEgraph}\oarg{\meta{spec}}%
+ \marg{\meta{$x_0$},\meta{$y_0$},\meta{$\Delta s$},\meta{$N$}}%
+ \marg{$f(\mathtt{x},\mathtt{y})$}\\
+\cs{DEtrajectory}\oarg{\meta{spec}}%
+ \marg{\meta{$p_0$},\meta{$\Delta s$},\meta{$N$}}%
+ \marg{$\mathbf{F}(\mathtt{x},\mathtt{y},\mathtt{t})$}%
+\index{DEgraph@\cs{DEgraph}}%
+\index{DEtrajectory@\cs{DEtrajectory}}%
+\end{cd}
+
+The first of these plots the graph of the solution of the differential
+equation
+$$
+ \frac{dy}{dx} = f(x,y)\,,\quad y(x_0) = y_0\,.
+$$
+The \meta{$\Delta s$} parameter is a step size and the \meta{$N$}
+parameter is the number of steps. The step size is \emph{not} an
+increment in the $x$ variable. Rather is is (roughly) the distance from
+one point to the next along the graph as \MF{} computes them. That is,
+\MF{} computes using a variable $x$-step $\Delta x$, chosen so that
+$\sqrt{\Delta x^2 + \Delta y^2}$ is approximately \meta{$\Delta s$}. The
+algorithm used is a modified 4-step Ringe-Kutta method.
+
+The second macro, \cs{DEtrajectory} draws the path traced by the
+solution $(x(t),y(t))$ of
+$$
+ \left( \frac{dx}{dt},\frac{dy}{dt} \right) = \mathbf{F}(x,y,t)\,,
+ \quad (x(0),y(0)) = p_0\,.
+$$
+This is not a \emph{graph}, since the dependence on $t$ cannot be shown
+in two dimensions (a third dimension would be needed). The parameter
+\meta{$p_0$} should be an ordered pair of numbers, the \meta{$\Delta s$} and
+\meta{$N$} are as for \cs{DEgraph}. The function $\mathbf{F}(x,y,t)$
+should be either a pair-valued expression or an ordered pair of numeric
+expressions. The variables must be literally \texttt{x}, \texttt{y} and
+\texttt{t}. The expressions do not have to explicitly depend on these
+variables. In fact, the \cs{DEgraph} macro is implemented using the same
+internal macro as \cs{DEtrajectory} with $\mathbf{F}(x,y,t) = (1,
+f(x,y))$ and $p_0 = (x_0,y_0)$.
+
+Notice that the trajectory starts at $t=0$. If you need some other
+starting value $t=a$, then replace $t$ in the formula for
+$\mathbf{F}(x,y,t)$ with $(t+a)$.
+
+It is possible to use a negative value of $\Delta s$ in both these
+macros. For \cs{DEgraph} this produces the graph to the left of $x=x_0$,
+and for \cs{DEtrajectory} it produces the trajectory with time running
+backward. For the latter, it is also equivalent to replacing
+$\mathbf{F}(x,y,t)$ by its negative.
+
+The purpose of making \meta{$\Delta s$} a distance rather than an
+$x$-increment or a $t$-increment (as the Runge-Kutta method is taught in
+the usual mathematics courses) is stability: even very simple
+differential equations can have graphs the tend to $\infty$ in finite
+time. These macros, however, never travel more than a distance $N\Delta
+s$ from the starting point.
+
+If you want to use \mfp{} to illustrate the results of the standard
+Runge-Kutta method or other methods, you can use the \prog{mfpic4ode}
+package. That package also includes the Euler method and the two-step
+Runge-Kutta method. It loads \mfp{} if it has not already been loaded.
+Like \mfp{}, it works in plain \TeX{} (with \verb$\input mfpic4ode$) or
+\LaTeX{} (with \verb$\usepackage{mfpic4ode}$).
+
+
+\subsection{Plotting external data files}\label{external}
+
+\begin{cd}\pagelabel{datafile}
+\cs{datafile}\oarg{\meta{spec}}\marg{\meta{file}}\\
+\cs{smoothdata}\oarg{\meta{tension}}\\
+\cs{unsmoothdata}%
+\index{datafile@\cs{datafile}}%
+\index{smoothdata@\cs{smoothdata}}%
+\index{unsmoothdata@\cs{unsmoothdata}}
+\end{cd}
+
+The figure macro \cs{datafile} produces a curve connecting the points
+listed in the file \meta{file}. (The context makes it clear whether this
+meaning of \cs{datafile} or that of subsection~\ref{list} is meant.) The
+\meta{spec} may be \texttt{p} to produce a polygonal path, or \texttt{s}
+followed by a tension value (as in \cs{curve}) to produce a smooth path.
+If no \meta{spec} is given, the default is initially \texttt{p}, but
+\cs{smoothdata} may be used to change this. Thus, after the command
+\cs{smoothdata}\oarg{\meta{tension}} the default \oarg{\meta{spec}} is
+changed to \oarg{s\meta{tension}}. If the tension parameter is not
+supplied it defaults to \mfc{1.0} (or the value set by the
+\cs{settension} command if one has been used).
+
+The command \cs{unsmoothdata} restores the default \oarg{\meta{spec}} to
+\oarg{p}.
+
+By default, each non-blank line in the file is assumed to contain at
+least two numbers, separated by whitespace (blanks or tabs). The first
+two numbers on each line are assumed to represent the $x$- and
+$y$-coordinates of a point. Initial blank lines in the file are ignored,
+as are comments. The comment character in the data file is assumed to be
+\texttt{\%}, but it can be reset using \cs{mfpdatacomment} (below). Any
+blank line other than at the start of the file causes the curve to
+terminate. The \cs{datafile} command may be preceded by any of the
+prefix commands, so that, for example, a closed curve could be formed
+with \cs{lclosed}\cs{datafile}\marg{data.dat}.
+
+The \index{datafile@\cs{datafile}}\cs{datafile} command has another use,
+independent of the above description. We saw in subsection~\ref{list}
+that any \mfp{} command (other than one that prints text labels) that
+takes as its last argument a list of points (or numerical values)
+separated by commas, can have that list replaced with a reference to an
+external data file. For example, if a file \file{ptlist.dat} contains
+two or more numerical values per line separated by whitespace, then one
+can draw a dot at each of the points corresponding to the first pair of
+numbers on each line with the following.
+\begin{verbatim}
+\point\datafile{ptlist.dat}
+\end{verbatim}
+In fact there is no essential difference between `\cs{datafile}\oarg{p}'
+and `\cs{polyline}\cs{datafile}', and no difference between
+`\cs{datafile}\oarg{s}' and `\cs{curve}\cs{datafile}'.
+Here is the full list (omitting aliases) of \mfp{} macros that allow
+this usage of \cs{datafile}\index{datafile@\cs{datafile}}:
+
+\begin{itemize}
+\raggedright
+\item Numeric data:
+ \cs{barchart}, \cs{dashpattern}, \cs{numericarray},
+ \cs{piechart}, and all the axis marks commands.
+\item Point or vector data:
+ \cs{cbeziers}, \cs{closedcbeziers}, \cs{closedcomputedspline},
+ \cs{closedcspline}, \cs{closedmfbezier}, \cs{closedqbeziers},
+ \cs{closedqspline}, \cs{computedspline}, \cs{convexcurve},
+ \cs{convexcyclic}, \cs{cspline}, \cs{curve}, \cs{cyclic},
+ \cs{fcncurve}, \cs{fcnspline}, \cs{mfbezier},
+ \cs{periodicfcnspline}, \cs{plotsymbol}, \cs{point}, \cs{polygon},
+ \cs{polyline}, \cs{putmfpimage}, \cs{qbeziers}, \cs{qspline},
+ \cs{turtle}, and \cs{pairarray}.
+\end{itemize}
+In addition \cs{setarray} and \cs{globalsetarray} (with the numeric or
+pair data type) allow this usage.
+
+\begin{cd}\pagelabel{mfpdatacomment}
+\cs{mfpdatacomment}\cs{}\meta{char}%
+\index{mfpdatacomment@\cs{mfpdatacomment}}
+\end{cd}
+
+Changes \meta{char} to a comment character and changes the usual \TeX{}
+comment character \texttt{\%} to an ordinary character \emph{while reading a
+datafile for drawing}.
+
+\begin{cd}\pagelabel{using}
+\cs{using}\marg{\meta{in-pattern}}\marg{\meta{out-pattern}}%
+\index{using@\cs{using}}
+\end{cd}
+
+Used to change the assumptions about the format of the data file. For
+example, if there are four numbers on each line separated by commas, to
+plot the third against the second (in that order) you can say
+\cs{using}\marg{\#1,\#2,\#3,\#4}\marg{(\#3,\#2)}. This means the
+following: Everything on a line up to the first comma is assigned to
+parameter \texttt{\#1}, everything from there up to the second comma is
+assigned to parameter \texttt{\#2}, etc. Everything from the third comma
+to the end of line is assigned to \texttt{\#4}. When the line is
+processed by \TeX{} a \MF{} pair is produced representing a point on the
+curve. \CMF{} pair expressions can be used in the output portion of
+\cs{using}. For example \cs{using}\marg{\#1,\#2,\#3}\marg{(\#2,\#1)/10}
+or even \cs{using}\marg{\#1 \#2 \#3}\marg{polar(\#1,\#2)} if the data
+are polar coordinates. The default assumptions of the \cs{datafile}
+command (numbers separated by spaces, with the first two determining the
+$(x,y)$ pair) corresponds to the following setting.
+\begin{verbatim}
+\using{#1 #2 #3}{(#1,#2)}
+\end{verbatim}
+The \cs{using} command cannot normally be used in the replacement text
+of another command. Or rather, it can be so used, but then each
+\texttt{\#} has to be doubled. If a \cs{using} declaration occurs in an
+\env{mfpic} environment it is local to that environment. Otherwise it
+affects all subsequent ones.
+
+\begin{cd}\pagelabel{sequence}
+\cs{sequence}%
+\index{sequence@\cs{sequence}}
+\end{cd}
+
+As a special case, you can plot any number against its sequence
+position, with something like
+\cs{using}\marg{\#1 \#2}\marg{(\cs{sequence},\#1)}. Here, the macro
+\cs{sequence} will take on the values \texttt{1}, \texttt{2}, etc. as
+lines are read from the file.
+
+\begin{cd}\pagelabel{usingpairdefault}
+\cs{usingpairdefault}\\
+\cs{usingnumericdefault}%
+\index{usingpairdefault@\cs{usingpairdefault}}%
+\index{usingnumericdefault@\cs{usingnumericdefault}}
+\end{cd}
+
+The command \cs{usingpairdefault} restores the above described default
+for pair data. The command \cs{usingnumericdefault} is the equivalent of
+\cs{using}\marg{\#1 \#2}\marg{\#1}, a useful default for numeric data.
+
+Note that the default value of \cs{using} appears to reference three
+arguments. If there are only two numbers on a line separated by
+whitespace, this will still work because of \TeX{}'s argument matching
+rules. \TeX{}'s file reading mechanism normally converts the EOL to a
+space, but there are exceptions so \mfp{} internally adds a space at
+the end of each line read in to be on the safe side. Then the default
+definition of \cs{using} reads everything up to the first space as
+\texttt{\#1} (whitespace is normally compressed to a single space by
+\TeX{}'s reading mechanism), then everything to the second space (the one
+added at the end of the line, perhaps) is \texttt{\#2}, then everything
+to the EOL is \texttt{\#3}. This might assign an empty argument to
+\texttt{\#3}, but it is discarded anyway.
+
+If the numerical data contain percentages with explicit \texttt{\%} signs,
+then choose another comment character with \cs{mfpdatacomment}. This
+will change \texttt{\%} to an ordinary character \emph{in the data file}.
+However, in your \cs{using} command it would still be read as a comment.
+The following allows one to overcome this.
+
+\begin{cd}\pagelabel{makepercentother}
+\cs{makepercentother}\\
+\cs{makepercentcomment}%
+\index{makepercentother@\cs{makepercentother}}%
+\index{makepercentcomment@\cs{makepercentcomment}}
+\end{cd}
+
+Here is an example or their use:
+\begin{verbatim}
+\makepercentother
+\using{#1% #2 #3}{(#1/100,#2)}
+\makepercentcomment
+\end{verbatim}
+
+Here is an analysis of the meaning of this example: everything in a
+line, up to the first percent followed by a space is assigned to
+parameter \texttt{\#1}, everything from there to the next space is
+assigned to \texttt{\#2} and the rest of the line (which may be empty)
+is \texttt{\#3}. On the output side in the above example, the percentage
+is divided by 100 to convert it to a fraction, and plotted against the
+second parameter. Note: normal comments should not be used between
+\cs{makepercentother} and \cs{makepercentcomment}, for obvious reasons.
+Moreover, the above construction will fail inside the argument of
+another command.
+
+\begin{cd}\pagelabel{plotdata}
+\cs{plotdata}\oarg{\meta{spec}}\marg{\meta{file}}%
+\index{plotdata@\cs{plotdata}}
+\end{cd}
+
+This plots several curves from a single file. The \meta{spec} and the
+command \cs{smoothdata} have the same effect on each curve as in the
+\cs{datafile} command. The data for each curve is a succession of
+nonblank lines separated from the data for the next curve by a single
+blank line. A \emph{pair} of successive blank lines is treated as the
+end of the data. No prefix macros are permitted in front of
+\cs{plotdata}.
+
+Each successive curve in the data file is drawn differently. By default,
+the first is drawn as a solid line the next dashed, the third dotted,
+etc., through a total of six different line types. A \cs{gendashed}
+command is used with predefined dash patterns named \mfc{dashtype0}
+through \mfc{dashtype5}. This behavior can be changed with:
+
+\begin{cd}\pagelabel{coloredlines}
+\cs{coloredlines}\\
+\cs{pointedlines}\\
+\cs{datapointsonly}\\
+\cs{dashedlines}%
+\index{coloredlines@\cs{coloredlines}}%
+\index{pointedlines@\cs{pointedlines}}%
+\index{datapointsonly@\cs{datapointsonly}}%
+\index{dashedlines@\cs{dashedlines}}
+\end{cd}
+
+The command \cs{coloredlines} causes \cs{plotdata} to use the rendering
+command \cs{draw} with a color option that cycles through eight
+different colors starting with black (hey! black is a color too). The
+command \cs{pointedlines} causes \cs{plotdata} to use the rendering
+command \cs{plot}, cycling through nine symbols. The command
+\cs{datapointsonly} causes \cs{plotdata} to use the rendering command
+\cs{plotnodes}, cycling through the same nine symbols. The data points
+become the nodes of the paths created and so only the data points are
+plotted. The command \cs{dashedlines} restores the default. See
+appendix~\ref{styles} for the details on the actual dash patterns,
+colors and symbols used.
+
+The command \cs{coloredlines} will produce a warning under the
+\opt{metafont} option and substitute \cs{dashedlines}. Under the
+\opt{metapost} option, this is the sole exception to the general rule
+that all curves are drawn in \gbc{drawcolor} by default: the
+\cs{plotdata} command after \cs{coloredlines} has been issued.
+
+Note that \mfp{} always creates a path internally. It is possible that
+your data is not path-like and what you want is a scatter-plot. Simply
+use \cs{datapointsonly} and the effect is the same: \MP{} builds a
+polygonal path connecting all the points in your file, but when it plots
+the path, it only places a dot (or other symbol) at each data point.
+
+If, for some reason, you do not like the default starting line style
+(say you want to start with a color other than black), you can use one
+of the following commands.
+
+\begin{cd}\pagelabel{mfplinetype}
+\cs{mfplinetype}\marg{\meta{num}}, or\\
+\cs{mfplinestyle}\marg{\meta{num}}%
+\index{mfplinetype@\cs{mfplinetype}}%
+\index{mfplinestyle@\cs{mfplinestyle}}
+\end{cd}
+
+Here \meta{num} is a non-negative number, less than the number of
+different drawing types available. The four previous commands reset the
+number to 0, so if you use one of them, issue \cs{mfplinetype}
+\emph{after} it. The different line styles are numbered starting from
+$0$. If two or more \cs{plotdata} commands are used in the same
+\env{mfpic} environment, the numbering in each continues where the one
+before left off (unless you issue one of the commands above in between).
+\cs{mfplinestyle} means the same as \cs{mfplinetype}, and is included
+for compatibility. See appendix~\ref{styles} to find out what dash pattern,
+color or symbol corresponds to each number by default. The commands
+below can be used to change the default dashes, colors, or symbols.
+
+\begin{cd}\pagelabel{reconfigureplot}
+\cs{reconfigureplot}\marg{dashes}\marg{\meta{pat$_1$},\dots,\meta{pat$_n$}}\\
+\cs{reconfigureplot}\marg{colors}\marg{\meta{clr$_1$},\dots,\meta{clr$_n$}}\\
+\cs{reconfigureplot}\marg{symbols}\marg{\meta{symb$_1$},\dots,\meta{symb$_n$}}%
+\index{reconfigureplot@\cs{reconfigureplot}}
+\end{cd}
+
+The first argument of \cs{reconfigureplot} is the rendering method to be
+changed: \texttt{dashes}, \texttt{colors} or \texttt{symbols}. The
+second argument is a list of dash patterns, colors, or symbols. The dash
+patterns should be names of patterns defined through the use of
+\cs{dashpattern}. The colors can be any color names already known to
+\MP{}, or color names defined using \cs{mfpdefinecolor}.
+The symbols can be any of those listed with the \cs{plotsymbol} command
+(see subsection~\ref{points}), or any known \MF{} path variable. The
+colors can also be \MP{} color constants or expressions, and the symbols
+can be expressions of type path. In recent \MP{} these `colors' can be
+\kw{numeric} (selecting gray), \kw{rgbcolor} or \kw{cmykcolor}. Within a
+\env{mfpic} environment, the changes made are local to that environment.
+Outside, they affect all subsequent environments.
+
+Using \cs{reconfigureplot}\marg{colors} under the \opt{metafont} option
+will have no effect, but may produce an error from \MF{} unless the
+colors used conform to the guidelines in subsection~\ref{MFcolor}.
+This also holds for \cs{defaultplot}\marg{colors} (below).
+
+\begin{cd}\pagelabel{defaultplot}
+\cs{defaultplot}\marg{dashes}\\
+\cs{defaultplot}\marg{colors}\\
+\cs{defaultplot}\marg{symbols}
+\index{defaultplot@\cs{defaultplot}}
+\end{cd}
+
+The command \cs{defaultplot} restores the built-in defaults for the
+indicated method of rendering in \cs{plotdata}.
+
+The commands \cs{using}, \cs{mfpdatacomment} and \cs{sequence} have the
+same meaning here (for \cs{plotdata}) as they do for \cs{datafile}
+(above). The sequence numbering for \cs{sequence} starts over with each
+new curve.
+
+
+\section{Labels and Captions.}\label{labels}
+
+\subsection{Setting text}\label{text}
+
+If option \opt{metafont} is in effect macros \cs{tlabel}, \cs{tlabels},
+\cs{axislabels} and \cs{tcaption} do not affect the \MF{} file
+(\file{\meta{file}.mf}) at all, but are added to the picture by \TeX{}. If
+\opt{metapost} is in effect but \opt{mplabels} is not, they do not
+affect the \MP{} file. In these cases, if these macros are the only
+changes or additions to your document, there is no need to repeat the
+processing with \MF{} or \MP{} nor the reprocessing with \TeX{} in order
+to complete your \TeX{} document.
+
+\begin{cd}\pagelabel{tlabel}
+\cs{tlabel}\oarg{\meta{just}}\parg{\meta{x},\meta{y}}\marg{\meta{labeltext}}\\
+\cs{tlabel}\oarg{\meta{just}}\marg{\meta{pair-list}}\marg{\meta{label text}}\\
+\cs{tlabels}\marg{\meta{params$_1$} \meta{params$_2$} $\ldots$}%
+\index{tlabel@\cs{tlabel}}%
+\index{tlabels@\cs{tlabels}}
+\end{cd}
+
+These place \TeX{} text or math on the graph. The special form
+\cs{tlabels} (note the plural) essentially just applies \cs{tlabel} to
+each set of parameters listed in its argument. That is, each
+\meta{params$_k$} is a valid set of parameters for a \cs{tlabel}
+command. These can be separated by spaces, newlines, or nothing at all.
+They should \emph{not} be separated by blank lines.
+
+The last required parameter is ordinary \TeX{} text. The pair
+\parg{\meta{x},\meta{y}} gives the coordinates of a point in the graph
+where the text will be placed. It may optionally be enclosed in braces,
+\verb${$ and \verb$}$. If braces are used, any number of coordinate
+pairs may be listed, separated by commas. This is what is meant by
+\meta{pair-list} in the above syntax. If \opt{mplabels} is in effect,
+the \meta{pair-list} can be any list of expressions recognized as a pair
+by \MP{}.
+
+The optional parameter \oarg{\meta{just}} specifies the
+\emph{justification}, the relative placement of the label with respect
+to the point with coordinates \parg{\meta{x},\meta{y}}. It is a
+two-character sequence in which the first character is one of \texttt{t}
+(top), \texttt{c} (center), \texttt{b} (bottom), or \texttt{B}
+(Baseline), to specify vertical placement, and the second character is
+one of \texttt{l} (left), \texttt{c} (center), or \texttt{r} (right), to
+specify horizontal placement. These letters specify what part of the
+\emph{text} is to be placed at the given point, so \texttt{r} puts the
+right end of the text there---which means the text will be left of the
+point. The default justification is \oarg{Bl}: the left end of the
+baseline of the text is placed at the coordinates.
+
+When \opt{mplabels} is in effect, the two characters may optionally be
+followed by a number, specifying an angle in degrees to rotate the text
+about the point \parg{\meta{x},\meta{y}}. If the angle is supplied
+without \opt{mplabels} it is ignored after a warning. If the angle is
+absent, there is no rotation. Note that the rotation takes place after
+the placement and uses the given point as the center of rotation. For
+example, \oarg{cr} will place the text left of the point, while
+\oarg{cr180} will rotate it around to the right side of the point (and
+upsidedown, of course).
+
+There should be no spaces before, between, or after the first two
+characters. However the number, if present, is only required to be a
+valid \MP{} numerical expression containing no bracket characters; as
+such, it may contain some spaces (e.g., around operations as in
+\texttt{45 + 30}).
+
+A multiline \cs{tlabel} may be specified by explicit line breaks, which
+are indicated by the \bbsl{} command or the \cs{cr} command. This is a
+very rudimentary feature. By default it left justifies the lines and
+causes \cs{tlabel} to redefine \bbsl. One can center a line by putting
+\cs{hfil} as the first thing in the line, and right justify by putting
+\cs{hfill} there (these are \TeX{} primitives). Redefining \bbsl{} can
+interfere with \LaTeX{}'s definition. For better control in \LaTeX{} use
+\cs{shortstack} inside the label (or a \env{tabular} environment or some
+other environment which always initializes \bbsl{} with its own
+definition).
+
+If the label goes beyond the bounds of the graph in any direction, the
+space reserved for the graph is expanded to make room for it. (Note:
+this behavior is very much different from that of the \LaTeX{}
+\env{picture} environment.)
+
+If the \opt{mplabels} option is in effect, \cs{tlabel} will write a
+\mfc{btex $\ldots$ etex} group to the output file, allowing \MP{} to
+arrange for typesetting the label. Normally, the label becomes part of
+the picture, rather than being laid on top of it, and can be covered up
+by any filling macros that follow, or clipped off by \cs{gclip}.
+However, under the \opt{overlaylabels} option (or after the command
+\cs{overlaylabels}), labels are saved and added to the picture at the
+very end. This may prevent some special effects, but it makes the
+behavior of labels much more consistent through all the 12 permissable
+settings of the options \opt{metapost}, \opt{mplabels}, \opt{clip}, and
+\opt{truebbox}.
+
+There is another command, \cs{startbacktext}, which also save the labels
+and adds them later, but \emph{under} the rest of the picture as
+background text. Thus, they will not be clipped, but may be covered up.
+Since erasing regions with \cs{gclear} actually covers up those regions
+with white, labels saved as background text may appear to have portions
+erased.
+
+\begin{cd}\pagelabel{everytlabel}
+\cs{everytlabel}\marg{\meta{\TeX{}-code}}%
+\index{everytlabel@\cs{everytlabel}}
+\end{cd}
+
+One problem with multiline \cs{tlabel}s is that each line of their
+contents constitutes a separate group. This makes it difficult to change
+the \cs{baselineskip} (for example) inside a label. The command
+\cs{everytlabel} saves it's contents in a token register and the code is
+issued in each \cs{tlabel}, as the last thing before the actual line(s)
+of text. Any switch you want to apply to every line can be supplied. For
+example
+\begin{verbatim}
+\everytlabel{\bf\baselineskip 10pt}
+\end{verbatim}
+will make every line of every \cs{tlabel}'s text come out bold with 10
+point baselines. The effect of \cs{everytlabel} is local to the
+\env{mfpic} environment, if it is issued inside one. Note that each line
+of a tlabel is wrapped in a box, but the commands of \cs{everytlabel}
+are outside all of them, so no actual text should be produced by the
+contents of \cs{everytlabel}.
+
+Using \cs{tlabel} without an optional argument is equivalent to
+specifying \oarg{Bl}. Use the following command to change this
+behavior.
+
+\begin{cd}\pagelabel{tlabeljustify}
+\cs{tlabeljustify}\marg{\meta{just}}%
+\index{tlabeljustify@\cs{tlabeljustify}}
+\end{cd}
+
+After this command the placement of all subsequent labels without
+optional argument will be as specified in this command. For example,
+\cs{tlabeljustify}\marg{cr45} would cause all subsequent \cs{tlabel}
+commands lacking an optional argument to be placed as if the argument
+\oarg{cr45} were used in each. If \opt{mplabels} is not in effect at the
+time of this command, the rotation part will be saved in case that
+option is turned on later, but a warning message will be issued. If
+\opt{mplabels} is not turned on later, that rotation will be ignored by
+\cs{tlabel}.
+
+\begin{cd}\pagelabel{tlabeloffset}
+\cs{tlabeloffset}\marg{\meta{hlen}}\marg{\meta{vlen}}\\
+\cs{tlpointsep}\marg{\meta{len}}\\
+\cs{tlpathsep}\marg{\meta{len}}\\
+\cs{tlabelsep}\marg{\meta{len}}%
+\index{tlabeloffset@\cs{tlabeloffset}}%
+\index{tlabelsep@\cs{tlabelsep}}%
+\index{tlpathsep@\cs{tlpathsep}}%
+\index{tlpointsep@\cs{tlpointsep}}
+\end{cd}
+
+The first command causes all subsequent \cs{tlabel} commands to shift
+the label right by \meta{hlen} and up by \meta{vlen} (negative lengths
+cause it to be shifted left and down, respectively).
+
+The \cs{tlpointsep} command causes labels to be shifted by the given
+amount in a direction that depends on the optional positioning
+parameter. For example, if the first letter is \texttt{t} the label is
+shifted down by the amount \meta{len} and if the second letter is
+\texttt{l} it is also shifted right. In all cases it is shifted
+\emph{away} from the point of placement (unless the dimension is
+negative). If \texttt{c} or \texttt{B} is the first parameter, no
+vertical shift takes place, and if \texttt{c} is the second, there is no
+horizontal shift. This is intended to be used in cases where something
+has been drawn at that particular point, in order to separate the text
+from the drawing.
+
+Prior to version 0.8, this separation also defined the separation
+between the label and those curves designed to frame the label
+such as \cs{tlabelrect} (subsection~\ref{surrounding}). Now the two
+separations are independent and \cs{tlpathsep} is used to set the
+separation between the label and such paths.
+
+For backward compatability, the command \cs{tlabelsep} is still
+available and sets both separations to the same value.
+
+\begin{cd}\pagelabel{axislabels}
+\cs{axislabels}\marg{\meta{axis}}\oarg{\meta{just}}%
+ \marg{\marg{\meta{text$_1$}}\meta{$n_1$},%
+ \marg{\meta{text$_2$}}\meta{$n_2$},$\ldots$}%
+\index{axislabels@\cs{axislabels}}
+\end{cd}
+
+This command places the given \TeX{} text (\meta{text$_k$}) at the given
+positions (\meta{$n_k$}) on the given axis, \meta{axis}, which must be a
+single letter and one of \texttt{l}, \texttt{b}, \texttt{r}, \texttt{t},
+\texttt{x}, or \texttt{y}. The text is placed as in \cs{tlabels}
+(including the taking into account of \cs{tlpointsep} and
+\cs{tlableoffset}), except that the default justification depends on the
+axis (the settings of \cs{tlabeljustify} are ignored). In the case of
+the border axes, the default is to place the label outside the axis and
+centered. So, for example, for the bottom axis it is \oarg{tc}. The
+defaults for the $x$- and $y$-axis are below and left, respectively. The
+optional \meta{just} can be used to change this. For example, to place
+the labels \emph{inside} the left border axis, use \oarg{cl}. If
+\opt{mplabels} is in effect, rotations can be included in the
+justification parameter. For example, to place the text strings
+`first', `second' and `third' just below the positions 1, 2 and 3
+on the $x$-axis, rotated so they read upwards at a 90 degree angle, one
+can use \cs{axislabels}\marg{x}\oarg{cr90}\marg{\marg{first}1,
+\marg{second}2, \marg{third}3}.
+
+\begin{cd}\pagelabel{plottext}
+\cs{plottext}\oarg{\meta{just}}\marg{\meta{text}}\marg{($x_0$,$y_0$),
+ ($x_1$,$y_1$), $\ldots$}%
+\index{plottext@\cs{plottext}}
+\end{cd}
+
+Similar in effect to \cs{point} and \cs{plotsymbol}, \cs{plottext}
+places a copy of \meta{text} at each of the listed points. Since \mfp{}
+version 0.9, when \cs{tlabel} was enhanced to allow lists of points, it
+is implemented by an equivalent \cs{tlabel} command and is only kept for
+backward compatibility. It differs from \cs{tlabel} when the optional
+argument is absent: the default justification is \oarg{cc} regardless of
+the setting of \cs{tlabeljustify}.
+
+\begin{cd}\pagelabel{mfpverbtex}
+\cs{mfpverbtex}\marg{\meta{\TeX{}-cmds}}%
+\index{mfpverbtex@\cs{mfpverbtex}}
+\end{cd}
+
+This writes a \mfc{verbatimtex} block to the \file{.mp} file. It makes
+sense only if the \opt{mplabels} option is used and so only for \MP{}.
+The \meta{\TeX{}-cmds} in the argument are written to the \file{.mp}
+file, preceded by the \MP{} command \mfc{verbatimtex} and followed by
+\mfc{etex}. Line breaks within the \meta{\TeX{}-cmd} are preserved.
+There is also a linebreak between the end of \meta{\TeX-cmds} and the
+\mfc{etex}. The \cs{mfpverbtex} command must come before any \cs{tlabel}
+that is to be affected by it. Any settings common to all \env{mfpic}
+environments should be in a \cs{mfpverbtex} command preceding all such
+environments.
+
+It may be issued at any point after \mfp{} is loaded, and any number of
+times. If it is issued after \cs{opengraphsfile}, its contents are
+immediately written to the \file{.mp} file. If it is issued before
+\cs{opengraphsfile}, its contents are saved and written when the file is
+opened (successive uses being cummulative). In this case its contents
+will precede the boilerplate \TeX{} code that \mfp{} writes. If you wish
+to redefine some of that code, you need to use \cs{mfpverbtex} after
+\cs{opengraphsfile}.
+
+Because of the way \MP{} handles \mfc{verbatimtex} material, the effects
+cannot be constrained by any grouping unless one places \TeX{} grouping
+commands within \meta{\TeX{}-cmds}. However, \mfp{} itself places
+grouping commands into the output file at the beginning and end of each
+picture, so definitions written by a \cs{mfpverbtex} are local to any
+picture in which it occurs. Prior to version 0.8, \mfp{} did not write
+comments that occured within the \meta{\TeX{}-cmds}. Now they will be
+preserved, and can be used to place the `\verb$%&latex$' line that some
+\TeX{} distributions permit as a signal that latex should be run to
+produce the labels.
+
+This command attempts a near-verbatim writing of the \meta{\TeX{}-cmds}
+and, as with all verbatim-like commands, it should not be used in the
+argument of another command.
+
+\begin{cd}\pagelabel{backtext}
+\cs{startbacktext} \dots \cs{stopbacktext}%
+\index{startbacktext@\cs{startbacktext}}%
+\index{stopbacktext@\cs{stopbacktext}}
+\end{cd}
+
+When \TeX{} adds labels (\cs{nomplabels}) they have to be positioned
+either on top of a complete figure, or placed under a complete figure.
+The most reasonable choice (and happily the easiest to implement) is to
+put them on top. When \MP{} is placing labels (option \opt{mplabel}) the
+same can be forced with the option \opt{overlaylabels}, but otherwise
+they are placed as they occur, with later drawing commands perhaps
+putting their results on top of the labels or clipping parts of them off.
+
+Sometimes it is useful to place some label as a background (not on top),
+and yet not have it clipped by later commands. The effect of the command
+\cs{startbacktext} is that \cs{tlabel} commands are saved in a special
+place until the command \cs{stopbacktext}. Then, at \cs{endmfpic} the
+rest of the figure is simply place on top of them. Since labels in \MP{}
+files can only consist of characters from some font, if one wants to
+include a graphic in the background (for example, via
+\cs{includegraphics}), one needs to switch off \opt{mplabels}:
+\begin{verbatim}
+\nomplabels
+\startbacktext
+ \tlabel[cc](0,0){\includegraphics{mygraph}}
+\stopbacktext
+\usemplabels
+\end{verbatim}
+As with other labels, it is permitted to switch \opt{mplabels} off and
+on while creating background text. If there are both kinds of labels
+within the background text area the ones handled by \TeX{} will be
+further back than the ones handled by \MP{}. Within a given type,
+earlier ones are further back than later ones.
+
+\Mfp{} normally uses a naming scheme like \cs{cmd} \dots \cs{endcmd} and
+tries to arrange that \env{cmd} can be used as an environment. As
+currently written, the extra grouping added by \cs{begin}\marg{cmd} and
+\cs{end}\marg{cmd} would break the code that implements background text,
+so we have named these in a different way to avoid suggesting this
+possiblity. There should be at most one of these pairs in any
+\env{mfpic} environment. It can occur anywhere in the environment, but
+the two commands must not be inside any grouping.
+
+Under the \opt{metapost} option, the \cs{gclear} command doesn't really
+clear a space, but rather paints the space over with white. Any
+background text will not be visible through such `holes'. This is a
+limitation of \MP{}.
+
+\begin{cd}\pagelabel{tcaption}
+\cs{tcaption}\oarg{\meta{maxwd},\meta{linewd}}\marg{\meta{caption text}}%
+\index{tcaption@\cs{tcaption}}
+\end{cd}
+
+Places a \TeX{} caption at the bottom of the graph. (Not to be confused
+with \LaTeX{}'s similar \cs{caption} command.) The macro will
+automatically break lines which are too much wider than the graph---if
+the \cs{tcaption} line exceeds \meta{maxwd} times the width of the
+graph, then lines will be broken to form lines at most \meta{linewd}
+times the width of the graph. The default settings for \meta{maxwd} and
+\meta{linewd} are 1.2 and 1.0, respectively. \cs{tcaption} may typeset
+its argument twice (as might \LaTeX{}'s \cs{caption}), the first time as
+a single line to test its width, then again if that was too wide.
+Therefore, the user is advised \emph{not} to include any global
+assignments in the caption text.
+
+If the \cs{tcaption} and graph have different widths, the two are
+centered relative to each other. If the \cs{tcaption} takes multiple
+lines, then the default is to set lines both left- and right-justified
+(except for the last line) with no indentation on the first line. If the
+option \opt{raggedcaptions} is in effect, the lines are only
+left-justified and ragged on the right. Finally, if the option
+\opt{centeredcaptions} is in effect, each line of the caption will be
+centered (under \opt{raggedcaptions} they will be ragged on both sides).
+
+In a \cs{tcaption}, explicit line breaks may be specified by using the
+\bbsl{} command. The separation between the bottom of the picture and
+the caption can be changed by increasing or decreasing the skip
+\cs{mfpiccaptionskip}\index{mfpiccaptionskip@\cs{mfpiccaptionskip}}
+(a `rubber' length in Lamport's terminology).
+
+Many \mfp{} users find the \cs{tcaption} command too limiting (one
+cannot, for example, place the caption to the side of the figure). It is
+common to use some other method (such as \LaTeX{}'s \cs{caption} command
+in a \env{figure} environment). The dimensions \cs{mfpicheight} and
+\cs{mfpicwidth} (see section~\ref{parameters}) might be a convenience
+for plain \TeX{} users who want to roll their own caption macros.
+
+
+\subsection{Curves surrounding text}\label{surrounding}
+
+\begin{cd}\pagelabel{tlabelrect}
+\cs{tlabelrect}\oarg{\meta{rad}}\oarg{\meta{just}}%
+ \meta{pair}\marg{\meta{text}}\\
+\cs{tlabelrect*...}%
+\index{tlabelrect@\cs{tlabelrect}}
+\end{cd}
+
+This figure macro and the following two methods of surounding a bit of
+text with a curve share some common characteristics which will be
+described here. The commands all take an optional argument that can
+modify the shape of the curve. After that come arguments exactly as for
+the \cs{tlabel} command except that only a single point is permitted,
+not a list. (So \meta{pair} is either of the form
+\parg{\meta{x},\meta{y}} or the same enclosed in braces, or for
+\opt{mplabels} a pair expression in braces.) After processing the
+surrounding curve, a \cs{tlabel} is applied to those arguments unless a
+\texttt{*} is present. In order for the second optional argument (the
+optional justification argument for the \cs{tlabel} command) to be
+recognized as the second, the first optional argument must also be
+present. An empty first optional argument is permitted, causing the
+default value to be used. The default for the justification argument is
+\texttt{cc}, for compatibility with past \mfp{} versions, in which these
+commands all centered the figure around the point and no justification
+parameter existed. This default can be changed with the
+\cs{tlpathjustify} command below.
+
+The plain rectangle version produces a frame separated from the text on
+all sides by the amount defined with \cs{tlpathsep}. All other versions
+produce the smallest described curve that contains this rectangle.
+
+These commands may be preceded by prefix macros (see the sections
+\ref{modifier}~and \ref{rendering}, above). They all have a
+`star-form' which produces the curve but omits placing the text.
+All have the effect of rendering the path \emph{before} placing any
+text. For example, \cs{gclear}\cs{tlabelrect}\dots\ will clear the
+rectangle and then place the following text in the cleared space.
+
+The optional argument of \cs{tlabelrect}, \meta{rad}, is a dimension,
+defaulting to \dim{0pt}, that produces rounded corners made from
+quarter-circles of the given radius. If the corners are rounded, the
+sides are expanded slightly so the resulting shape still encompasses the
+rectangle mentioned above. There is one special case for the optional
+argument \meta{rad}: if the keyword `\texttt{roundends}' is used instead
+of a dimension, the radius will be chosen to make the nearest quarter
+circles just meet, so the narrow side of the rectangle is a half circle.
+
+\begin{cd}\pagelabel{tlabeloval}
+\cs{tlabeloval}\oarg{\meta{mult}}\oarg{\meta{just}}%
+ \meta{pair}\marg{\meta{text}}\\
+\cs{tlabeloval*...}%
+\index{tlabeloval@\cs{tlabeloval}}
+\end{cd}
+
+This figure macro is similar to \cs{tlabelrect}, except it produces an
+ellipse. The ellipse is calculated to have the same ratio of width to
+height as the rectangle mentioned above. The optional \meta{mult} is a
+multiplier that increases or decreases this ratio. Values of \meta{mult}
+larger than 1 increase the width and decrease the height.
+
+\begin{cd}\pagelabel{tlabelellipse}
+\cs{tlabelellipse}\oarg{\meta{ratio}}\oarg{\meta{just}}%
+ \meta{pair}\marg{\meta{text}}\\
+\cs{tlabelellipse*...}\\
+\cs{tlabelcircle}\oarg{\meta{just}}\meta{pair}\marg{\meta{text}}\\
+\cs{tlabelcircle*...}%
+\index{tlabelellipse@\cs{tlabelellipse}}%
+\index{tlabelcircle@\cs{tlabelcircle}}
+\end{cd}
+
+This figure macro produces the smallest ellipse centered at the point
+that encompasses the rectangle defined above, and that has a ratio of
+width to height equal to \meta{ratio}, then places the text. The default
+ratio is $1$, which produces a circle. We also provide the command
+\cs{tlabelcircle}, which takes only the \oarg{\meta{just}} optional
+argument. Internally, it just processes any \texttt{*} and calls
+\cs{tlabelellipse} with parameter 1.
+
+In the above \cs{tlabel...} curves, the optional parameter should be
+positive. If it is zero, all the curves silently revert to
+\cs{tlabelrect}. If it is negative, it is silently accepted. In the case
+of \cs{tlabelrect} this causes the quarter-circles at the corners to be
+indented rather than convex. In the other cases, there is no visible
+effect, but in all cases the sense of the curve is reversed.
+
+\begin{cd}\pagelabel{tlpathjustify}
+\cs{tlpathjustify}\marg{\meta{just}}%
+\index{tlpathjustify@\cs{tlpathjustify}}
+\end{cd}
+
+This can be used to change the default justification for \cs{tlabelrect}
+and friends. The \meta{just} parameter is exactly as in
+\cs{tlabeljustify} in subsection~\ref{text}.
+
+
+\section{Saving and Reusing an \mfp{} Picture.}\label{saving}
+
+These commands have been changed from versions prior to 0.3.14 in order
+to behave more like the \LaTeX{}'s \cs{savebox}, and also to allow the
+reuse of an allocated box. Past files that use \cs{savepic} will have to
+be edited to add \cs{newsavepic} commands that allocate the \TeX{}
+boxes.
+
+\begin{cd}\pagelabel{newsavepic}
+\cs{newsavepic}\marg{\meta{picname}}\\
+\cs{savepic}\marg{\meta{picname}}\\
+\cs{usepic}\marg{\meta{picname}}%
+\index{newsavepic@\cs{newsavepic}}%
+\index{savepic@\cs{savepic}}%
+\index{usepic@\cs{usepic}}
+\end{cd}
+
+\cs{newsavepic} allocates a box (like \LaTeX{}'s \cs{newsavebox}) in which
+to save a picture. As in \cs{newsavebox}, \meta{picname} is a control
+sequence. Example: \cs{newsavepic}\marg{\cs{foo}}. In a \LaTeX{}
+document, \cs{newsavepic} is actually defined to be \cs{newsavebox}.
+
+\cs{savepic} saves the \emph{next} \cs{mfpic} picture in the named box,
+which should have been previously allocated with \cs{newsavepic}. (This
+command should not be used \emph{inside} an \env{mfpic} environment.)
+The next picture will not be placed, but saved in the box for later use.
+This is primarily intended as a convenience. One \emph{could} use
+\begin{ex}
+ \cs{savebox}\marg{\meta{picname}}\marg{\meta{entire \env{mfpic}
+ environment}},
+\end{ex}
+but \cs{savepic} avoids having to place the \env{mfpic} environment in
+braces, and avoids one extra level of \TeX{} grouping. It also avoids
+reading the entire \env{mfpic} environment as a parameter, which would
+nullify \mfp{}'s efforts to preserve line breaks in parameters
+written to the \MF{} output file. If you repeat \cs{savepic} with the
+same \meta{picname}, the old contents are replaced with the next
+picture.
+
+\cs{usepic} copies the picture that had been saved in the named box.
+This may be repeated as often as liked to create multiple copies of one
+picture. The \cs{usepic} command is essentially a clone of the \LaTeX{}
+\cs{usebox} command. Since the contents of the saved picture are only
+defined during the \TeX{} run, \cs{usebox} cannot be used in the
+\TeX-commands argument of the \cs{tlabel} command while \opt{mplabels}
+is in effect.
+
+
+\section{Picture Frames.}\label{frames}
+
+When \TeX{} is run but before \MF{} or \MP{} has been run on the output
+file, \mfp{} detects that the \file{.tfm} file is missing or that
+the first \MP{} figure file \file{\meta{file}.1} is missing. In these
+cases, the \env{mfpic} environment draws only a rectangular frame with
+dimensions equal to the nominal size of the picture, containing the
+figure number (and any text placed by \cs{tlabel} and its relatives
+without \opt{mplabels} in effect). The command(s) used internally to do
+this are made available to the user.
+
+\begin{cd}\pagelabel{mfpframe}
+\cs{mfpframe}\oarg{\meta{fsep}}%
+ \meta{ material-to-be-framed }%
+\cs{endmfpframe}\\
+\cs{mfpframed}\oarg{\meta{fsep}}\marg{\meta{material-to-be-framed}}%
+\index{mfpframed@\cs{mfpframed}}%
+\index{endmfpframe@\cs{endmfpframe}}%
+\index{mfpframe@\cs{mfpframe}}
+\end{cd}
+
+These commands surround their contents with a rectangular frame
+consisting of lines with thickness \cs{mfpframethickness} separated from
+the contents by the \meta{fsep} if specified, otherwise by the value of
+the dimension \cs{mfpframesep}. The default value of the \TeX{}
+dimensions \cs{mfpframesep} and \cs{mfpframethickness} are \dim{2pt} and
+\dim{0.4pt}, respectively. The \cs{mfpframe} $\ldots$ \cs{endmfpframe}
+version is preferred around \env{mfpic} environments or verbatim
+material since it avoids reading the enclosed material before
+appropriate \cs{catcode} changes go into effect. In \LaTeX{}, one can
+also use environment syntax: \cs{begin}\marg{mfpframe} $\ldots$
+\cs{end}\marg{mfpframe}.
+
+An alternative way to frame \env{mfpic} pictures is to save them with
+\cs{savepic} (see previous section) and issue a corresponding
+\cs{usepic} command inside any framing environment or command of the user's
+choice or devising.
+
+
+\section{Affine Transforms.}\label{transforms}
+
+Coordinate transformations that keep parallel lines in parallel are
+called \emph{affine transforms}. These include translation, rotation,
+reflection, scaling and skewing (slanting). For the \MF{} coordinate
+system only (that is, for paths, but not for \cs{tlabel} nor
+\cs{tcaption}) \mfp{} provides the ability to apply \MF{} affine
+transforms.
+
+
+\subsection{Transforming the \MF{} coordinate system}\label{affine}
+
+\begin{cd}\pagelabel{coords}
+\cs{coords} \dots \cs{endcoords}%
+\index{coords@\cs{coords}}%
+\index{endcoords@\cs{endcoords}}
+\end{cd}
+
+All affine transforms are restricted to the innermost enclosing
+\cs{coords}$\ldots$\cs{endcoords} pair. If there is \emph{no} such
+enclosure, then the transforms will apply to the rest of the \env{mfpic}
+environment. In \LaTeX{}, one can use the environment named
+\env{coords}.
+
+\medskip
+\noindent Transforms provided by \mfp{}:
+
+\nobreak
+\begin{cd}\pagelabel{applyT}%
+\begin{tabular}[b]{@{}ll@{}}
+ \cs{rotate}\marg{\meta{$\theta$}}%
+ \index{rotate@\cs{rotate}}%
+ & Rotate around origin by \meta{$\theta$} degrees.\\
+ \cs{rotatearound}\marg{\meta{$p$}}\marg{\meta{$\theta$}}%
+ \index{rotatearound@\cs{rotatearound}}%
+ & Rotate around point \meta{$p$} by \meta{$\theta$} degrees.\\
+ \cs{turn}\oarg{\meta{p}}\marg{\meta{$\theta$}}%
+ \index{turn@\cs{turn}}%
+ & Rotate around point \meta{p} (origin is default) by
+ \meta{$\theta$}.\\
+ \cs{reflectabout}\marg{\meta{$p_1$}}\marg{\meta{$p_1$}}%
+ \index{reflectabout@\cs{reflectabout}}%
+ & Reflect in the line through points \meta{$p_1$} and \meta{$p_2$}.\\
+ \cs{mirror}\marg{\meta{$p_1$}}\marg{\meta{$p_2$}}%
+ \index{mirror@\cs{mirror}}%
+ & Same as \cs{reflectabout}.\\
+ \cs{shift}\marg{\meta{v}}%
+ \index{shift@\cs{shift}}%
+ & Shift origin by the vector \meta{v}.\\
+ \cs{scale}\marg{\meta{s}}%
+ \index{scale@\cs{scale}}%
+ & Scale uniformly by a factor of \meta{s}.\\
+ \cs{xscale}\marg{\meta{s}}%
+ \index{xscale@\cs{xscale}}%
+ & Scale only the $x$ coordinates by a factor of \meta{s}.\\
+ \cs{yscale}\marg{\meta{s}}%
+ \index{yscale@\cs{yscale}}%
+ & Scale only the $y$ coordinates by a factor of \meta{s}.\\
+ \cs{zscale}\marg{\meta{pair}}%
+ \index{zscale@\cs{zscale}}%
+ & Scale by the length of vector \meta{v}, and rotate by its
+ angle.\\
+ \cs{xslant}\marg{\meta{s}}%
+ \index{xslant@\cs{xslant}}%
+ & Skew in $x$ direction by the multiple \meta{s} of $y$.\\
+ \cs{yslant}\marg{\meta{s}}%
+ \index{yslant@\cs{yslant}}%
+ & Skew in $y$ direction by the multiple \meta{s} of $x$.\\
+ \cs{zslant}\marg{\meta{pair}}%
+ \index{zslant@\cs{zslant}}%
+ & See \mfc{zslanted} in \file{grafbase.dtx}.\\
+ \cs{boost}\marg{\meta{$\chi$}}%
+ \index{boost@\cs{boost}}%
+ & Special relativity boost by $\chi$, see \mfc{boost} in
+ \file{grafbase.dtx}.\\
+ \cs{xyswap}%
+ \index{xyswap@\cs{xyswap}}%
+ & Exchange the values of $x$ and $y$.\\
+ \cs{applyT}\marg{\meta{transformer}}%
+ \index{applyT@\cs{applyT}}%
+ & Apply the \meta{transformer}.
+\end{tabular}
+\end{cd}
+
+\cs{applyT} is for \MF{} hackers. Any code is permitted that satisfies
+\MF{}'s syntax for a \meta{transformer} (see D.~E.~Knuth, ``The
+\MF{}book'', page~73), although no effort is made to correctly write
+\TeX{} special characters nor to preserve linebreaks in the code.
+
+When any of these commands is issued, the effect is to transform all
+subsequent figures (within the enclosing \env{coords} or \env{mfpic}
+environment). In particular, attention may need to be paid to whether
+these transformations move (part of) the figure outside the space
+allotted by the \cs{mfpic} command parameters.
+
+A not-so-obvious point is that if several of these transformations are
+applied in succession, then the most recent is applied first, so that
+figures are transformed as if the transformations were applied in the
+reverse order of their occurrence. This is similar to the application of
+prefix macros (as well as application of transformations in mathematics:
+$S T z$ usually means to apply $S$ to the result of $T z$).
+
+Finally, some of these may not produce what the unwary user might expect
+if the \env{mfpic} environment was started with unequal scaling. For
+example, in such a case a rotated rectangle will not have right angles
+unless the rotation is by a multiple of 90 degrees. The reason for this:
+the scaling given by the \cs{mfpic} command is applied last and
+slanted lines subjected to unequal horizontal and verical scaling will
+change have their angles changed.
+
+
+\subsection{Transforming paths}\label{transformation}
+
+In the previous section we discussed transformations of the \MF{}
+coordinate system. Those macros affect the \emph{drawing} of paths and
+other figures, but do not change the actual paths. We will explain the
+distinction after introducing two macros for storing and reusing
+figures.
+
+\begin{cd}\pagelabel{store}
+\cs{store}\marg{\meta{path variable}}\marg{\meta{path}}\\
+\cs{store}\marg{\meta{path variable}}\meta{path}%
+\index{store@\cs{store}}
+\end{cd}
+
+This stores the following \meta{path} in the specified \MF{} \meta{path
+variable}. Any valid \MF{} symbolic token will do, in particular, any
+sequence of letters and underscores. You should be careful to make the
+name distinctive to avoid overwriting the definition of some internal
+variable. The stored path may later be used as a figure macro
+using \cs{mfobj} (below). The \meta{path} may be any of the figure
+macros (such as \cs{curve}\marg{(0,0),(1,0),(1,1)}) or the result of
+modifying it. For example:
+\begin{verbatim}
+\store{pth}\lclosed\reverse\curve{(0,0),(1,0),(1,1)}
+\end{verbatim}
+
+In fact, \cs{store} is a prefix macro that does nothing to the following
+curve except store it. It acts as a rendering macro with a null
+rendering, so the curve is not made visible unless other rendering
+macros appear before or after it. It allows the following path to be an
+argument, that is, enclosed in braces. This is solely to support files
+written for past \mfp{} versions in which \cs{store} was \emph{not}
+defined as a prefix macro.
+
+One use of \cs{store} is to create a shorthand for a path that is
+otherwise long and tedious to type. Another is to create `symbols' or
+`arrowheads' for use in \cs{plotsymbol}, \cs{arrowhead} and related
+commands.
+
+\begin{cd}\pagelabel{mfobj}
+\cs{mfobj}\marg{\meta{path expression}}\\
+\cs{mpobj}\marg{\meta{path expression}}%
+\index{mfobj@\cs{mfobj}}%
+\index{mpobj@\cs{mpobj}}
+\end{cd}
+
+This figure macro produces the path represented by \meta{path
+expression}, which is either a path variable in which a path was
+previously stored, or a valid \MF{} expression combining such variables
+and constant paths. This allows the use of path variables or
+expressions as figure macros, permitting all prefix operations, etc..
+Here are some examples of the use of \cs{store} and \cs{mfobj}.
+
+\nobreak
+\begin{verbatim}
+\store{my_f}{\cyclic{...}} % Store a closed curve.
+\dotted\mfobj{my_f} % Now draw it dotted,
+\hatch\mfobj{my_f} % and hatch its interior
+% Create two symbols
+% one outline:
+\store{MyTriang}{\polyline{(-.5,-.5),(.5,-.5),(0,.5),(-.5,-.5)}
+% one solid:
+\store{MySolidTriang}\polygon{(-.5,-.5),(.5,-.5),(0,.5)}
+% Use them as symbols:
+\plotsymbols{MyTriang}{(0,0),(2,2)}
+\arrowmid{MySolidTriang}\polyline{(1,1),(0,2)}
+\end{verbatim}
+
+\emph{Note}: If a stored path has the same starting point as ending
+point, but is \emph{not} closed then it will behave like \texttt{Circle}
+(for example) when used in \cs{plotsymbol}: only its outline is drawn,
+and its interior is erased when \opt{clearsymbols} is in effect. If a
+closed path is stored, it behaves like \texttt{SolidCircle}: it is not
+drawn, but rather filled. If a path is stored that satisfies neither, it
+behaves like \texttt{Asterisk}, being simply drawn in all circumstances.
+
+The two forms \cs{mfobj} and \cs{mpobj} are absolutely equivalent; they
+differ only in spelling.
+
+It should be noted that every \mfp{} figure is implicitly stored in the
+object \gbc{curpath}. So you can use \cs{mfobj}\marg{curpath} and get
+the path defined by the most recently completed figure macro (possibly
+modified by prefixes).
+
+Getting back to coordinate transforms, if one changes the coordinate
+system and then stores and draws a curve, say by
+\begin{verbatim}
+\coords
+ \rotate{45 deg}
+ \store{xx}{\rect{(0,0),(1,1)}}
+ \dashed\mfobj{xx}
+\endcoords
+\end{verbatim}
+one will get a transformed picture, but the object \cs{mfobj}\marg{xx}
+will contain the simple, unrotated rectangular path and drawing it later
+(outside the \env{coords} environment) will prove that. This is because
+the \texttt{coords} environment works at the drawing level, not at the
+definition level.
+
+In oversimplified terms, \cs{dashed} invokes the transformation, but not
+\cs{store}. More precisely, the rendering macros have the side effect of
+adding ink to the page (or subtracting it). To know where to place this
+ink, a calculation is performed that translates graph coordinates to
+actual positions. The above transforms work by modify the parameters
+used in that calculation. On the other hand, \cs{store} merely stores
+the output of the immediately following prefix or figure macro. See the
+beginning of section~\ref{modifier} for a discussion of input, output
+and side effects of \mfp{} prefix and figure macros.
+
+The following transformation prefixes provide a means of actually
+creating and storing a transformed path. In the terms just discussed,
+their input is a path, their output is the transformed path, and they
+have no side effects.
+
+\begin{cd}\pagelabel{shiftpath}
+\cs{rotatepath}\marg{\meta{$p$},\meta{$\theta$}}$\ldots$\\
+\cs{shiftpath}\marg{\meta{v}}$\ldots$\\
+\cs{scalepath}\marg{\meta{$p$},\meta{s}}$\ldots$\\
+\cs{xscalepath}\marg{\meta{x},\meta{s}}$\ldots$\\
+\cs{yscalepath}\marg{\meta{y},\meta{s}}$\ldots$\\
+\cs{slantpath}\marg{\meta{y},\meta{s}}$\ldots$\\
+\cs{xslantpath}\marg{\meta{y},\meta{s}}$\ldots$\\
+\cs{yslantpath}\marg{\meta{x},\meta{s}}$\ldots$\\
+\cs{reflectpath}\marg{\meta{$p_1$},\meta{$p_2$}}$\ldots$\\
+\cs{xyswappath}$\ldots$\\
+\cs{transformpath}\marg{\meta{transformer}}$\ldots$%
+\index{rotatepath@\cs{rotatepath}}%
+\index{shiftpath@\cs{shiftpath}}%
+\index{scalepath@\cs{scalepath}}%
+\index{xscalepath@\cs{xscalepath}}%
+\index{yscalepath@\cs{yscalepath}}%
+\index{slantpath@\cs{slantpath}}%
+\index{xslantpath@\cs{xslantpath}}%
+\index{yslantpath@\cs{yslantpath}}%
+\index{reflectpath@\cs{reflectpath}}%
+\index{xyswappath@\cs{xyswappath}}%
+\index{transformpath@\cs{transformpath}}
+\end{cd}
+
+These are modifying macros that all return the result of applying an
+affine transformation to the following path. They differ in the
+transformation applied and the data needed in the mandatory argument. I
+have found them extremely useful, and better than \env{coords}
+environments when I need to draw a figure, together with several
+slightly different versions of it. If \cs{store} is used just before one
+of these prefixes, it stores the transformed path rather than the
+original.
+
+\cs{rotatepath} rotates the following path by \meta{$\theta$} degrees
+about point \meta{$p$}.
+
+\cs{shiftpath} shifts the following path by the vector \meta{v}.
+
+\cs{scalepath} scales (magnifies or shrinks) the following path by the
+factor \meta{s}, in such a way that the point \meta{$p$} is kept fixed.
+That is
+\begin{verbatim}
+\scalepath{(0,0),2}\rect{(0,0),(1,1)}
+\end{verbatim}
+is essentially the same as \cs{rect}\marg{(0,0),(2,2)}, while
+\begin{verbatim}
+\scalepath{(1,1),2}\rect{(0,0),(1,1)}
+\end{verbatim}
+is the same as \cs{rect}\marg{(-1,-1),(1,1)}. In both cases the
+rectangle is doubled in size. In the first case the lower left corner
+stays the same, while in the second case the the upper right corner
+stays the same.
+
+\cs{xscalepath} is similar to \cs{scalepath}, but only the $x$-direction
+is scaled, and all points with first coordinate equal to \meta{x} remain
+fixed. \cs{yscalepath} is similar, except the $y$-direction is affected.
+
+\cs{slantpath} applies a slant transformation to the following path,
+keeping points with second coordinate equal to \meta{y} fixed. That is,
+a point $p$ on the path is moved right by an amount proportional to the
+height of $p$ above the line $y={}$\meta{y}, with $s$ being the
+proportionality factor. Points below that line move left. Vertical lines
+in the path will acquire a slope of $1/s$, while horizontal lines stay
+horizontal.
+
+\cs{xslantpath} is an alias for \cs{slantpath}
+
+\cs{yslantpath} is similar to \cs{xslantpath}, but exchanges the roles
+of $x$ and $y$ coordinates.
+
+\cs{reflectpath} returns the mirror image of the following path, where
+the line determined by the points \meta{$p_1$} and \meta{$p_2$} is the
+mirror.
+
+\cs{xyswappath} returns the path with the roles of $x$ and $y$
+exchanged. This is similar in some respects to
+\cs{reflectpath}\marg{(0,0),(1,1)}, and produces the same result if the
+$x$ and $y$ scales of the picture are the same. However,
+\cs{reflectpath} compensates for such different scales (so the path
+shape remains the same), while \cs{xyswappath} does not. However, after
+a swap, verticals become horizontal and horizontals become vertical.
+(It is impossible, when the scales are different, for an affine transform
+to both preserve shape and exchange horizontal and vertical lines.)
+
+This compensation for different scales is also done for \cs{rotatepath},
+so the resulting path always has the same shape after the rotation as
+before. None of the other path transformation prefixes compensate for
+different scales, and none of the coordinate system transformations of
+the previous subsection do it.
+
+For \MF{} or \MP{} power users, \cs{transformpath} can take any
+`transformer' and transform the following path with it. Here, a
+\emph{transformer} is the same as in the previous section. Examples are
+\mfc{scaled}, \mfc{shifted(1,1)}, and \mfc{rotatedabout(0,1)}. Note that
+using this last transformer with \cs{transformpath} is almost like
+\cs{rotatepath}\marg{(0,1)}, but it does not compensate for different
+scales.
+
+All these prefixes change only the path that follows, not any rendering
+of it that follows. For example:
+\begin{verbatim}
+\gfill\rotatepath{(0,0),90}\dashed\rect{(0,0),(1,1)}
+\end{verbatim}
+will not produce a rotated dashed rectangle. Rather the original
+rectangle will be dashed, and the rotated rectangle will be filled.
+
+One complication is the handling of the default rendering. One expects
+\begin{verbatim}
+\rect{(0,0),(1,1)}
+\end{verbatim}
+to draw a rectangle, and
+\begin{verbatim}
+\rotatepath{(0,0),45}\rect{(0,0),(1,1)}
+\end{verbatim}
+to draw a rotated rectangle (but not the original). That is, a
+transformation + figure is treated as if it were a single figure. But
+what would one expect in the following?
+\begin{verbatim}
+\rotatepath{(0,0),45}\dashed\rect{(0,0),(1,1)}
+\end{verbatim}
+What one will get is the original dashed and the rotated one with the
+default rendering (typically drawn with solid lines). That is, these
+prefixes cannot see the renderings that occur later in the sequence.
+They add the default rendering as if those didn't exist. If something
+other than this is desired, one can either rearrange the prefixes or add
+a \phantomsection\label{norenderexample}\cs{norender} in appropriate
+places. For example, to add a shifted arrowhead without drawing the
+shifted path:
+\begin{verbatim}
+\arrow\norender\shiftpath{(0,1)}\arrow\draw\lines{(0,0),(8,8)}
+\end{verbatim}
+
+
+\section{Parameters.}\label{parameters}
+
+There are many parameters in \mfp{} which the user can modify to
+obtain different effects, such as different arrowhead size or shape.
+Most of these parameters have been described already in the context of
+macros they modify, but they are all described together here.
+
+Many of the parameters are stored by \TeX{} as dimensions, and so are
+available even if there is no \MF{} file open; changes to them are not
+subject to the usual \TeX{} rules of scope however: they are local
+only to \env{mfpic} environments if set inside one, otherwise
+they are global. This is for consistency: other parameters are stored by
+\MF{} (so the macros to change them will have no effect unless a \MF{}
+file is open) and the changes are subject to \MF{}'s rules of scope---to
+the \mfp{} user, this means that changes inside the \cs{mfpic} $\ldots$
+\cs{endmfpic} environment are local to that environment, but other
+\TeX{} groupings have no effect on scope. Some commands (notably those
+that set the axismargins and \cs{tlabel} parameters) change both \TeX{}
+parameters and \MF{} parameters, and it is important to keep them
+consistent.
+
+There are a few parameters that do obey \TeX{} grouping, but only inside
+\env{mfpic} environments. These are noted where the parameter is
+described.
+
+All parameters are initialized when \prog{mfpic} is loaded. We give the
+initial value or state in each of these descriptions.
+
+\begin{cd}\pagelabel{mfpicunit}
+\cs{mfpicunit}%
+\index{mfpicunit@\cs{mfpicunit}}
+\end{cd}
+
+This dimension stores the basic unit length for \mfp{} pictures. The $x$
+and $y$ scales in the \cs{mfpic} macro are multiples of this unit. The
+initial value is \dim{1pt}. It is global outside an \env{mfpic}
+environment. Changes made to it inside an \env{mfpic} environment have
+no effect and are lost at the end of the environment.
+
+\begin{cd}\pagelabel{pointsize}
+\cs{pointsize}%
+\index{pointsize@\cs{pointsize}}
+\end{cd}
+
+This dimension stores the diameter of the circle drawn by the
+\cs{point} macro and the diameter of the symbols drawn by \cs{plot},
+\cs{plotsymbol} and \cs{plotnodes}. The initial value is \dim{2pt}.
+
+\begin{cd}\pagelabel{pointfilltrue}
+\cs{pointfilltrue}, \cs{pointfillfalse}%
+\index{pointfilltrue@\cs{pointfilltrue}}%
+\index{pointfillfalse@\cs{pointfillfalse}}
+\end{cd}
+
+This \TeX{} boolean switch determines whether the circle drawn by
+\cs{point} will be filled or open (outline drawn, inside erased).
+The initial state is \texttt{true}: filled. This value is local to any \TeX{}
+group inside an \env{mfpic} environment. Outside such it is global.
+
+\begin{cd}\pagelabel{drawpen}
+\cs{pen}\marg{\meta{size}}\\
+\cs{drawpen}\marg{\meta{size}}\\
+\cs{penwd}\marg{\meta{size}}%
+\index{pen@\cs{pen}}%
+\index{drawpen@\cs{drawpen}}%
+\index{penwd@\cs{penwd}}
+\end{cd}
+
+These commands establishes the width of the normal drawing pen (that is,
+the thickness of lines, whether solid or dashed). The initial value is
+\dim{0.5bp}. This width is stored by \MF{}. This has no effect on the
+size of dots for \cs{dotted}, \cs{shade}, \cs{grid}, etc. It also has no
+effect on the lines drawn for hatching. There exist three aliases for
+this command, the first two to maintain backward compatibility, the last
+one for consistency with other dimension changing commands. Publishers
+generally recommended authors to use at least a width of one-half point
+for drawings submitted for publication.
+
+\begin{cd}\pagelabel{shadewd}
+\cs{shadewd}\marg{\meta{diam}}%
+\index{shadewd@\cs{shadewd}}
+\end{cd}
+
+This command sets the diameter of the dots used in the shading macro.
+The drawing and hatching pens are unaffected by this. The initial value
+is \dim{0.5bp}, and the value is stored by \MF{}.
+
+\begin{cd}\pagelabel{hatchwd}
+\cs{hatchwd}\marg{\meta{size}}%
+\index{hatchwd@\cs{hatchwd}}
+\end{cd}
+
+This sets the line thickness used in the hatching macros. The drawing
+pen and shading dots are unaffected by this. The initial value is
+\dim{0.5bp}, and the value is stored by \MF{}.
+
+\begin{cd}\pagelabel{polkadotwd}
+\cs{polkadotwd}\marg{\meta{diam}}%
+\index{polkadotwd@\cs{polkadotwd}}
+\end{cd}
+
+This sets the diameter of the dots used in the \cs{polkadot} macro. The
+initial value is \dim{5bp}, and the value is stored by \MF{}.
+
+\begin{cd}\pagelabel{headlen}
+\cs{headlen}%
+\index{headlen@\cs{headlen}}
+\end{cd}
+
+This dimension stores the length of the arrowhead drawn by the
+\cs{arrow} macro. The initial value is \dim{3pt}.
+
+\begin{cd}\pagelabel{axisheadlen}
+\cs{axisheadlen}%
+\index{axisheadlen@\cs{axisheadlen}}
+\end{cd}
+
+This dimension stores the length of the arrowhead drawn by the
+\cs{axes}, \cs{xaxis} and \cs{yaxis} macros, and by the macros \cs{axis}
+and \cs{doaxes} when applied to the parameters \texttt{x} and
+\texttt{y}. The initial value is \dim{5pt}.
+
+\begin{cd}\pagelabel{sideheadlen}
+\cs{sideheadlen}%
+\index{sideheadlen@\cs{sideheadlen}}
+\end{cd}
+
+This dimension stores the length of the arrowhead drawn by the \cs{axis}
+and \cs{doaxes} macros when applied to \texttt{l}, \texttt{b},
+\texttt{r} or \texttt{t}. The initial value is \dim{0pt} (that is, the
+default is not to put arrowheads on border axes).
+
+\begin{cd}\pagelabel{headshape}
+\cs{headshape}\marg{\meta{ratio}}\marg{\meta{tension}}\marg{\meta{filled}}%
+\index{headshape@\cs{headshape}}
+\end{cd}
+
+This establishes the shape of the \gbc{Arrowhead} drawn by the
+\cs{arrow...} and \cs{axes} macros. It also establishes the shape of
+\gbc{Leftharpoon} and \gbc{Rightharpoon}. The value of \meta{ratio} is
+the ratio of the width of the arrowhead to its length; \meta{tension} is
+the tension of the B\'ezier curves; and \meta{filled} is a \MF{} boolean
+value indicating whether the arrowheads are to be filled (if \mfc{true})
+or open. The initial values are $1$, $1$, and \mfc{false}, respectively.
+Setting \meta{tension} to the literal keyword `\mfc{infinity}' will make
+the sides of the arrowheads straight lines. The harpoon heads are
+arranged to be exactly half of the full arrowhead. The \meta{ratio},
+\meta{tension} and \meta{filled} values are stored by \MF{}.
+
+After \cs{headshape} is used, the symbols \gbc{Arrowhead},
+\gbc{Leftharpoon}, and \gbc{Rightharpoon} take on the new shape if used
+in one of the \cs{plot...} commands.
+
+\begin{cd}\pagelabel{dashlen}
+\cs{dashlen}, \cs{dashspace}%
+\index{dashlen@\cs{dashlen}}
+\end{cd}
+
+These dimensions store, respectively, the length of dashes and the
+length of spaces between dashes, for lines drawn by the \cs{dashed}
+macro. The \cs{dashed} macro may adjust the dashes and the spaces
+between by as much as $1/n$ of their value, where $n$ is the number of
+spaces appearing in the curve, in order not to have partial dashes at
+the ends. The initial values are both \dim{4pt}. The dashes will
+actually be longer (and the spaces shorter) by the thickness of the pen
+used when they are drawn.
+
+\begin{cd}\pagelabel{dashlineset}
+\cs{dashlineset}, \cs{dotlineset}%
+\index{dashlineset@\cs{dashlineset}}%
+\index{dotlineset@\cs{dotlineset}}
+\end{cd}
+
+These macros provide shorthands for certain settings of the \cs{dashlen}
+and \cs{dashspace} dimensions. The macro \cs{dashlineset} sets both
+values to \dim{4pt}, while \cs{dotlineset} sets \cs{dashlen} to
+\dim{1pt} and \cs{dashspace} to \dim{2pt}. They are kept mainly for
+backward compatibility.
+
+\begin{cd}\pagelabel{hashlen}
+\cs{hashlen}%
+\index{hashlen@\cs{hashlen}}
+\end{cd}
+
+This dimension stores the length of the axis hash marks drawn by the
+\cs{xmarks} and \cs{ymarks} macros. The initial value is \dim{4pt}.
+
+\begin{cd}\pagelabel{shadespace}
+\cs{shadespace}%
+\index{shadespace@\cs{shadespace}}
+\end{cd}
+
+This dimension establishes the spacing between dots drawn by the
+\cs{shade} macro. The initial value is \dim{1pt}.
+
+\begin{cd}\pagelabel{darkershade}
+\cs{darkershade}, \cs{lightershade}%
+\index{darkershade@\cs{darkershade}}%
+\index{lightershade@\cs{lightershade}}
+\end{cd}
+
+These macros both multiply the \cs{shadespace} dimension by constant
+factors, $5/6=.833333$ and $6/5=1.2$ respectively, to provide convenient
+standard settings for several levels of shading. Under \MF{} it is
+possible that using one of these macros can have no visible effect. See
+the discussion of the \cs{shade} macro in subsection~\ref{filling}.
+
+\begin{cd}\pagelabel{polkadotspace}
+\cs{polkadotspace}%
+\index{polkadotspace@\cs{polkadotspace}}
+\end{cd}
+
+This dimension establishes the spacing between the centers of the dots
+used for the macro \cs{polkadot}. The initial value is \dim{10pt}.
+
+\begin{cd}\pagelabel{dotsize}
+\cs{dotsize}, \cs{dotspace}%
+\index{dotsize@\cs{dotsize}}\index{dotspace@\cs{dotspace}}%
+\end{cd}
+
+These \TeX{} dimensions establishes the size and spacing between the
+centers of the dots used in the \cs{dotted} macro. The initial values
+are \dim{0.5pt} and \dim{3pt}.
+
+\begin{cd}\pagelabel{griddotsize}
+\cs{griddotsize}%
+\index{griddotsize@\cs{griddotsize}}%
+\end{cd}
+
+This dimension gives the default sizes of dots in the \cs{grid} and
+\cs{plrgridpoints} commands. The initial value is \dim{0.5pt}
+
+\begin{cd}\pagelabel{symbolspace}
+\cs{symbolspace}%
+\index{symbolspace@\cs{symbolspace}}
+\end{cd}
+
+Similar to \cs{dotspace}, this \TeX{} dimension establishes the space
+between the centers of symbols placed by the macro
+\cs{plot}\marg{\meta{symbol}}$\ldots\,$. Its initial value is \dim{5pt}.
+
+\begin{cd}\pagelabel{hatchspace}
+\cs{hatchspace}%
+\index{hatchspace@\cs{hatchspace}}
+\end{cd}
+
+This dimension establishes the spacing between lines drawn by the
+\cs{hatch} macro. The initial value is \dim{3pt}.
+
+\begin{cd}
+\cs{tlpointsep}\marg{\meta{separation}}\\
+\cs{tlpathsep}\marg{\meta{separation}}\\
+\cs{tlabelsep}\marg{\meta{separation}}%
+\index{tlpointsep@\cs{tlpointsep}}%
+\index{tlpathsep@\cs{tlpathsep}}%
+\index{tlabelsep@\cs{tlabelsep}}
+\end{cd}
+
+The first macro establishes the separation between a label and its
+nominal position. It affects text written with any of the commands
+\cs{tlabel}, \cs{tlabels}, \cs{axislabels} or \cs{plottext}. The second
+sets the separation between the text and the curve defined by the
+commands \cs{tlabelrect}, \cs{tlabeloval} or \cs{tlabelellipse}. The
+third sets both of these separations to the same value. It is for
+backward compatibility: in the past there was only one dimension used
+for both purposes. The initial value of each is \dim{0pt}. The values
+are stored by both \TeX{} and \MF{}.
+
+\begin{cd}
+\cs{tlabeloffset}\marg{\meta{hlen}}\marg{\meta{vlen}}%
+\index{tlabeloffset@\cs{tlabeloffset}}
+\end{cd}
+
+This macro establishes a uniform offset that applies to all labels. It
+affects text written with any of the commands \cs{tlabel}, \cs{tlabels},
+\cs{axislabels} or \cs{plottext}. The initial state is to have both
+horizontal and vertical offsets of \dim{0pt}. The values are stored by
+both \TeX{} and \MF{}.
+
+\begin{cd}\pagelabel{mfpdataperline}
+\cs{mfpdataperline}%
+\index{mfpdataperline@\cs{mfpdataperline}}
+\end{cd}
+
+When \mfp{} is reading from data files and writing to the output file,
+this macro stores the maximum number of data points that will be written
+on a single line in the output file. Its initial definition is
+\cs{def}\cs{mfpdataperline}\marg{5}. Any such definition (or
+redefinition) obeys \emph{all} \TeX{} groupings.
+
+\begin{cd}\pagelabel{mfpicheight}
+\cs{mfpicheight}, \cs{mfpicwidth}%
+\index{mfpicheight@\cs{mfpicheight}}%
+\index{mfpicwidth@\cs{mfpicwidth}}
+\end{cd}
+
+These dimensions store the height and width of the figure created by the
+most recently completed \env{mfpic} environment. This might perhaps be
+of interest to hackers or to aid in precise positioning of the graphics.
+They are meant to be read-only: the \cs{endmfpic} command globally sets
+them equal to the height and width of the picture, but \mfp{} does not
+otherwise make any use of them. As they are not to be changed, grouping
+is irrelevent, but when \mfp{} sets them, it does so globally. These are
+set even if the picture is saved with \cs{savepic}. If they are needed
+for the corresponding \cs{usepic}, and that occurs after another
+\env{mfpic} environment, they should be copied to other length commands
+right after the \env{mfpic} environment that set them.
+
+\begin{cd}\pagelabel{mfpiccaptionskip}
+\cs{mfpiccaptionskip}%
+\index{mfpiccaptionskip@\cs{mfpiccaptionskip}}
+\end{cd}
+
+This skip register (`rubber length' in \LaTeX) stores the space between
+a picture and the caption produced with \cs{tcaption}. It is local to
+all \TeX{} groups. If changed inside an \env{mfpic} environment it will
+affect only the \cs{tcaption} command in that picture. It's initial
+setting is \cs{medskipamount}, producing the same space as a
+\cs{medskip}.
+
+
+\section{For Advanced Users.}\label{advanced}
+
+\subsection{Splines}\label{splines}
+
+\begin{cd}\pagelabel{qspline}
+\cs{qspline}\marg{\meta{list}}\\
+\cs{closedqspline}\marg{\meta{list}}\\
+\cs{cspline}\marg{\meta{list}}\\
+\cs{closedcspline}\marg{\meta{list}}%
+\index{qspline@\cs{qspline}}%
+\index{closedqspline@\cs{closedqspline}}%
+\index{cspline@\cs{cspline}}%
+\index{closedcspline@\cs{closedcspline}}%
+\end{cd}
+
+These figure macros use alternative ways of defining curves. In each case,
+\meta{list} is a comma separated list of ordered pairs. These represent
+not the points the curve passes through, but the \emph{control points}.
+The first two produce quadratic B-splines and the last two produce cubic
+B-splines. If you don't know what B-splines are, or don't know what
+control points are, it is recommended you not use these commands.
+
+For \cs{qspline}, the curve will pass through the midpoints of the line
+segments joining the points in the list, tangent to that line segment.
+
+For the \cs{cspline}, the list also defines line segments. Divide these
+into equal thirds at two points on each segment. Connect these
+\emph{division points only} to obtain line segments. Each \emph{odd
+numbered} segment is the middle third of one of the original line
+segments. The \cs{cspline} curve passes through the midpoint of each
+\emph{even numbered} line segment, tangent to it.
+
+\begin{cd}\pagelabel{computedspline}
+\cs{computedspline}\marg{\meta{list}}\\
+\cs{closedcomputedspline}\marg{\meta{list}}%
+\index{computedspline@\cs{computedspline}}%
+\index{closedcomputedspline@\cs{closedcomputedspline}}%
+\end{cd}
+
+These figure macros both produce cubic splines. For these you \emph{do}
+provide the list of points the curves are to pass through. They become
+the nodes, and then the control points are computed from them. The nodes
+do not uniquely determine the control points so extra equations are
+required. For the first version, the extra equations give the path zero
+curvature at the endpoints (a \emph{relaxed} spline). For the closed
+version, the extra equations are those that close the curve smoothly.
+The portions of the spline that connect one node to the next are
+parametrized cubic B\'eziers, they are computed so that the first and
+second derivatives (with respect to the parameter) of adjacent curves
+match at the common node.
+
+\begin{cd}\pagelabel{fcnspline}
+\cs{fcnspline}\marg{\meta{list}}\\
+\cs{periodicfcnspline}\marg{\meta{list}}%
+\index{fcnspline@\cs{fcnspline}}%
+\index{periodicfcnspline@\cs{periodicfcnspline}}%
+\end{cd}
+
+These figure macros use cubic spline equations (as in
+\cs{computedspline} above) to produce a smooth graph of a function based
+on a list of points with increasing $x$-values. See \cs{fcncurve} in
+section~\ref{curves} for another way to do this. As in the computed
+splines, above, the spline equations at the nodes do not provide
+sufficient information to compute all control points. In the basic
+version, \cs{fcnspline}, extra equations produce a graph with zero
+curvature at the endpoints (a relaxed spline), while the periodic
+version uses equations that make the first and second derivatives at the
+last point match those at the first point.
+
+\begin{cd}\pagelabel{cbclosed}
+\cs{cbclosed}$\ldots$\\
+\cs{qbclosed}$\ldots$%
+\index{cbclosed@\cs{cbclosed}}%
+\index{qbclosed@\cs{qbclosed}}
+\end{cd}
+
+These are modifying macros that close the following path. The first
+closes with a cubic B-spline, the second with a quadratic B-spline. They
+will close any given curve, but the command \cs{cbclosed} is meant to
+close a cubic B-spline (see above). That is, \cs{cbclosed}\cs{cspline}
+should produce the same result as \cs{closedcspline} with the same
+argument. The corresponding statements are true of \cs{qbclosed}: it is
+meant to close a quadratic B-spline and \cs{qbclosed}\cs{qspline} should
+produce the same result as \cs{closedqspline} with the same argument.
+
+
+\subsection{B\'eziers}
+
+The power user, having noticed that \cs{curve} and \cs{cyclic} insert
+some direction modifiers into the path created, may have decided that
+there is no \mfp{} command to create a simple \MF{} default style path,
+for example \mfc{(1,1)..(0,1)..(0,0)..cycle}. If so, he or she has forgotten
+about \cs{mfobj}: the command
+\begin{verbatim}
+\mfobj{(1,1)..(0,1)..(0,0)..cycle}
+\end{verbatim}
+will produce, in the \file{.mf} file, exactly this path, but surround it
+with the \TeX{} wrapping needed to make \mfp{}'s prefix macro system work.
+However, the syntax of more complicated paths can be extremely lengthy,
+so we offer this interface:
+
+\begin{cd}\pagelabel{mfbezier}
+ \cs{mfbezier}\oarg{\meta{tens}}\marg{\meta{list}}\\
+ \cs{closedmfbezier}\oarg{\meta{tens}}\marg{\meta{list}}%
+\index{mfbezier@\cs{mfbezier}}%
+\index{closedmfbezier@\cs{closedmfbezier}}
+\end{cd}
+
+These figure macros uses the \MF{} path join operator `\mfc{..tension
+\meta{tens}..}' to connect the points in the list. If the tension option
+\oarg{\meta{tens}} is omitted, the value set by \cs{settension}
+(initially 1) is used. One can get a cyclic path by prepending
+\cs{bclosed} (with matching tension option), but it will not produce the
+same result as \cs{closedmfbezier}. These are cubic B\'ezier's (but you
+know that if you are a power user). Quadratic B\'eziers (as in
+\LaTeX{}'s picture environment) can be obtained with the following:
+
+\begin{cd}\pagelabel{qbeziers}
+ \cs{qbeziers}\marg{\meta{list}}\\
+ \cs{closedqbeziers}\marg{\meta{list}}%
+\index{qbeziers@\cs{qbeziers}}%
+\index{closedqbeziers@\cs{closedqbeziers}}
+\end{cd}
+
+These figure macros produce \emph{quadratic} B\'ezier curves, the
+equivalent of a sequence of \LaTeX{} \cs{qbezier} commands. Note the
+plural forms, to distinguish the first from the \LaTeX{} command, and to
+indicate that they can draw a \emph{series} of quadratic B\'eziers.
+
+In the \meta{list}, the first, third, fifth, etc., are the points to
+connect, while the second, fourth, etc., are the control points. The
+open version requires an ending point, and so needs an odd number of
+points in the list. The closed version assumes the first point is the
+ending, and so requires an even number in the list. If the number of
+ponts is wrong, no error is produced: the last point is simply repeated
+to get the required number.
+
+The curve will not automatically be smooth; that depends on the choice
+of the control points.
+
+\begin{cd}\pagelabel{cbeziers}
+ \cs{cbeziers}\marg{\meta{list}}\\
+ \cs{closedcbeziers}\marg{\meta{list}}%
+\index{cbeziers@\cs{cbeziers}}%
+\index{closedcbeziers@\cs{closedcbeziers}}
+\end{cd}
+
+These figure macros produce a series of \emph{cubic} B\'ezier curves. In
+the \meta{list}, the first, fourth, seventh, etc., are the points to
+connect, while the second and third, fifth and sixth, etc., are pairs of
+control points. The closed version uses the starting point as the ending
+point, and so needs a number of points divisible by $3$ ($n=3k$). The
+open version requires an explicitly given ending node (so $n=3k+1$).
+If the number of ponts is wrong, no error is produced: the last point
+or last two points are simply repeated to get the required number.
+
+The curves will not automatically be smooth; that depends on the choice
+of the control points. Cubic B\'eziers are how curves are represented in
+PostScript files, and how a number of vector drawing programs represent
+curves.
+
+
+\subsection{Raw \MF{} code}\label{mfcode}
+
+\begin{cd}\pagelabel{mfsrc}
+\cs{mfsrc}\marg{\meta{metafont code}}\\
+\cs{mfcmd}\marg{\meta{metafont code}}\\
+\cs{mflist}\marg{\meta{metafont code}}%
+\index{mfsrc@\cs{mfsrc}}%
+\index{mfcmd@\cs{mfcmd}}%
+\index{mflist@\cs{mflist}}%
+\end{cd}
+
+These all write the \meta{metafont code} directly to the \MF{} file,
+using a \TeX{} \cs{write} command. Line breaks within \meta{metafont
+code} are preserved.%
+ \footnote{Under most circumstances, but not if the command (plus its
+ argument) is part of the argument of another macro.} %
+Almost all the \mfp{} drawing macros invoke one of these. Because of the
+way \TeX{} reads and processes macro arguments, not all drawing macros
+preserve line breaks (nor do they all need to). However, the ones that
+operate on long lists of pair or numeric data (for example, \cs{point},
+\cs{curve}, etc.), do preserve line breaks in that data. The difference
+in these is minor: \cs{mfsrc} writes its argument without change,
+\cs{mfcmd} appends a semicolon (`\mfc{;}') to the code, while
+\cs{mflist} surrounds its argument with parentheses and then appends a
+semicolon.
+
+Using these can have some rather bizarre consequences, though, so it is
+not recommended to the unwary. It is, however, currently the only way to
+make use of \MF{}'s equation solving ability. Here's an oversimplified
+example:
+\begin{verbatim}
+\mfpic[20]{-0.5}{1.5}{0}{1.5}
+\mfsrc{z1=(0,0);
+ z2-z3=(1,2);
+ z2+2z3=(1,-1);} % z2=(1,1), z3=(0,-1)
+\arc[t]{z1,z2,z3}
+\endmfpic
+\end{verbatim}
+
+Check out the sample \file{forfun.tex} for a more extensive example. It
+should produce the word `\textsf{mfpic}' in blue, outlined in green in a
+box with yellow background.
+
+
+\subsection{Creating \MF{} variables}\label{variables}
+
+\begin{cd}\pagelabel{setmfvariable}
+\cs{setmfvariable}\marg{\meta{type}}\marg{\meta{name}}\marg{\meta{value}}\\
+\cs{setmpvariable}\marg{\meta{type}}\marg{\meta{name}}\marg{\meta{value}}\\
+\cs{globalsetmfvariable}\marg{\meta{type}}\marg{\meta{name}}\marg{\meta{value}}\\
+\cs{globalsetmpvariable}\marg{\meta{type}}\marg{\meta{name}}\marg{\meta{value}}\\
+\cs{setmfnumeric}\marg{\meta{name}}\marg{\meta{value}}\\
+\cs{setmfpair} \marg{\meta{name}}\marg{\meta{value}}\\
+\cs{setmfboolean}\marg{\meta{name}}\marg{\meta{value}}\\
+\cs{setmfcolor} \marg{\meta{name}}\marg{\meta{value}}%
+\index{setmfvariable@\cs{setmfvariable}}%
+\index{setmpvariable@\cs{setmpvariable}}%
+\index{globalsetmfvariable@\cs{globalsetmfvariable}}%
+\index{globalsetmpvariable@\cs{globalsetmpvariable}}%
+\index{setmfnumeric@\cs{setmfnumeric}}%
+\index{setmfpair@\cs{setmfpair}}%
+\index{setmfboolean@\cs{setmfboolean}}%
+\index{setmfcolor@\cs{setmfcolor}}%
+\end{cd}
+
+These formerly internal \mfp{} macros can be use to define symbolic
+names for any \MF{} or \MP{} variable type. The last four are
+abbreviations for the first used with an appropriate value for
+\meta{type}. For example,
+\cs{setmfvariable}\marg{pair}\marg{X}\marg{(2,0)} can be abbreviated
+\cs{setmfpair}\marg{X}\marg{(2,0)}. Note that these overwrite any
+variable with the specified \meta{name}. For certain internal names,
+\MF{} will issue an error, but usually the variable is silently
+redefined.
+
+The commands \cs{setmpvariable} and \cs{globalsetmpvariable} (note the
+\texttt{mp} instead of \texttt{mf}) are just alternative spellings . You
+can use either spelling with either the \opt{metafont} or \opt{metapost}
+option.
+
+The \meta{value} must be a constant of the appropriate type or a \MF{}
+expression returning the appropriate type. It can also be (or include)
+other variables previously defined. The \cs{setmfcolor} command has been
+enhanced so that in recent \MP{} the \meta{value} can be any of the
+three types of colors \MP{} allows: \kw{numeric} (for grayscale color),
+\kw{rgbcolor} or \kw{cmykcolor}. The data type of \meta{value} will be
+examined, and the variable \meta{name} will be declared to be a variable
+of the appropriate type. The same is true of
+\cs{setmfvariable}\marg{color}.
+
+As an example of their use, since dimensions are numeric data types in
+\MF{}, the command
+\begin{verbatim}
+\setmfnumeric{my_spc}{5pt}
+\setmfnumeric{my_dia}{.8pt}
+\end{verbatim}
+would set the \MF{} variables \verb$my_spc$ and \verb$my_dia$ to the
+values \texttt{5pt} and \texttt{.8pt}, respectively. After that, these
+variables can be used in any \emph{drawing} command where a dimension is
+required:
+\begin{verbatim}
+\plot[my_dia,my_spc]{Triangle}\rect{(0,0),(1,1)}
+\end{verbatim}
+will plot the rectangle with small triangles of diameter \dim{.8pt},
+spaced \dim{5pt} apart.
+
+The knowledgeable user may realize that \mfc{path} and \gbc{picture} are
+\MF{} data types, and may want use them in \cs{setmfvariable}. It is
+also true that at some level, \mfp{} figure macros produce a path and
+\cs{mfpimage} produces a picture. However, \mfp{} commands cannot be
+used in the value portion of \cs{setmfvariable}. The \TeX{} code that
+most \mfp{} commands produce would be meaningless to \MF{}. You can
+store the path produced by figure macros with \cs{store}, and store
+pictures in variables with \cs{mfpimage} or even \cs{tile}.
+
+With the obvious exception of the \cs{globalsetmfvariable} command, these
+commands define the variable locally. That is, the variable will revert
+to any previous definition (or become undefined) at the end of the
+\env{mfpic} environment it is defined in. It is in fact local to any
+\MF{} group. In \mfp{}, only \cs{connect} {\dots} \cs{endconnect},
+\cs{mfpimage} {\dots} \cs{endmfpimage}, and \cs{mfpic} {\dots}
+\cs{endmfpic} create \MF{} groups in the graph file.
+
+A warning about variable names. \CMF{} and \MP{} allow multi-part
+variable names like `\mfc{arrowhead length}' or `\mfc{X.r}' The part
+after the first space or `.' is called a \mfc{suffix}. In \MF{},
+variable settings are global unless explicitly made local. The code of
+the \cs{set...} commands does make the variable setting local. However,
+\MF{} syntax forbids this localization when a variable name has a
+suffix. Moreover, if you localize a variable, \MF{} will localize all
+variables with that name plus any suffix. Even more, localizing a
+variable renders all variables with the same name plus suffix locally
+undefined. The command \cs{globalsetmfvariable} simply omits the
+localization part, so suffixes are permitted, but it cannot `globalize'
+something that has previously been localized within the same group.
+
+For example, suppose you use the example code in subsection~\ref{arrows}
+and define a custom arrowhead path \gbc{myAH} and the corresponding
+clearing path \gbc{myAH.clear}. Suppose now you try to make this head
+the default for the \cs{arrow} command by doing the following.
+\begin{verbatim}
+\setmfvariable{path}{Arrowhead}{myAH}
+\end{verbatim}
+Then this assignments is local and makes \gbc{Arrowhead.clear} undefined
+(locally). You cannot use \cs{setmfvariable} to define
+\gbc{Arrowhead.clear}; that will produce an error from \MF{}. You need
+to do
+\begin{verbatim}
+\setmfvariable{path}{Arrowhead}{myAH}
+\globalsetmfvariable{path}{Arrowhead.clear}{myAH.clear}
+\end{verbatim}
+and \emph{both} assignments will be local. To make both assignments
+global, use the global version in both.
+
+
+\begin{cd}\pagelabel{patharr}
+\cs{patharr}\marg{\meta{name}}$\ldots$\cs{endpatharr}%
+\index{patharr@\cs{patharr}}%
+\index{endpatharr@\cs{endpatharr}}
+\end{cd}
+
+This pair of macros, acting as an environment, accumulate all enclosing
+paths, in order, into a path array named \meta{name}. A path array is a
+collection of paths with a common base name indexed by integers from 1
+to the number of paths. Any path in the array can be accessed by means
+of \cs{mfobj}. For example, after
+\begin{verbatim}
+\patharr{pa}
+ \rect{(0,0),(1,1)} \circle{(.5,.5), .5}
+\endpatharr
+\end{verbatim}
+then \cs{mfobj}\marg{pa[1]} refers to the rectangle and
+\cs{mfobj}\marg{pa[2]} refers to the circle. In case explicit numbers
+are used, \MF{} allows \gbc{pa1} as an abbreviation for \gbc{pa[1]}.
+However, if a numeric variable or some expression is used (e.g.,
+\gbc{pa[n+1]}) the square brackets are required.
+
+This command can only be used in an \env{mfpic} environment. For this
+reason, the definitions it makes are global.
+
+\emph{Note}: In \LaTeX{}, this pair of macros can be used in the form of a
+\LaTeX{}-style environment called \env{patharr}---as in
+\cs{begin}\marg{patharr}$\ldots$\cs{end}\marg{patharr}.
+
+\begin{cd}\pagelabel{setarray}
+\cs{setarray}\marg{\meta{type}}\marg{\meta{var}}\marg{\meta{list}}\\
+\cs{globalsetarray}\marg{\meta{type}}\marg{\meta{var}}\marg{\meta{list}}\\
+\cs{pairarray}\marg{\meta{var}}\marg{\meta{list-of-points}}\\
+\cs{numericarray}\marg{\meta{var}}\marg{\meta{list-of-numbers}}\\
+\cs{colorarray}\marg{\meta{var}}\marg{\meta{list-of-colors}}\\
+\cs{rgbcolorarray}\marg{\meta{var}}\marg{\meta{list-of-rgbcolors}}\\
+\cs{cmykcolorarray}\marg{\meta{var}}\marg{\meta{list-of-cmykcolors}}%
+\index{setarray@\cs{setarray}}%
+\index{globalsetarray@\cs{globalsetarray}}%
+\index{pairarray@\cs{pairarray}}%
+\index{numericarray@\cs{numericarray}}%
+\index{colorarray@\cs{colorarray}}%
+\index{rgbcolorarray@\cs{rgbcolorarray}}%
+\index{cmykcolorarray@\cs{cmykcolorarray}}
+\end{cd}
+
+These enable the simultaneous definition of variables.
+For example, after
+\begin{verbatim}
+\pairarray{X}{(0,1),(1,1),(0,0),(1,0)}
+\end{verbatim}
+the variables \mfc{X1}, \mfc{X2}, \mfc{X3}, and \mfc{X4} are equal to
+the given points in that order. And then
+\begin{verbatim}
+\polyline{X1,X2,X3,X4}
+\end{verbatim}
+will draw the lines connecting these four points. The index may
+optionally be put in square brackets and may be separated from the name
+by any number of spaces. That is, \verb$\polyline{X[1],X[2]}$ and
+\verb$\polyline{X 1,X 2}$ are the same as \verb$\polyline{X1,X2}$ to
+\MF{}. If a numeric \emph{expression} is used instead of an explicit
+number, square brackets \emph{must} surround it: \gbc{X[1+1]},
+\gbc{X[2]}, \gbc{X2} and \codebox{X 2} are all the same. For all these
+array commands, the variable \gbc{X} by itself (not followed by any
+digit or brackets) becomes a numeric variable equal to the number of
+elements in the array. Except for \cs{globalsetarray}, the arrays are
+defined locally if these commands occur in an \env{mfpic} environment,
+global otherwise.
+
+Array variables may be used only where the values are processed only by
+\MF{} or \MP{}, they are unknown to \TeX{}. In particular, they cannot be
+used in commands that position text unless \opt{mplabels} is in effect.
+Variables may be used in the \meta{list} parameters of commands,
+but they must have been previously defined or otherwise known to \MF{}.
+
+Since arrays must all be variables of the same type, one cannot mix rgb
+and cmyk colors. The \verb$\colorarray$ command requires rgb colors (for
+compatibility with early \MP{}).
+
+Several commands in \mfp{} define arrays of objects that can be used in
+other commands. The main ones are \cs{regpolygon}, \cs{piechart} and
+\cs{barchart}. These arrays are always global (either because their
+use is restricted to an \env{mfpic} environment or for backward
+compatibility with the time when they were so restricted).
+
+Using \cs{regpolygon}\marg{\meta{num}}\marg{X}\marg{...}\marg{...} causes a
+pair array named \gbc{X} to be defined having \meta{num} elements (and
+the additional pair \gbc{X0} for the center). This is in addition to
+creating the actual figure. The variable \gbc{X} alone becomes a numeric
+equated to \meta{num}.
+
+Using \cs{piechart} (or \cs{mfppiechart}) causes the following arrays to
+become defined (or redefined):
+\begin{itemize}
+ \item \gbc{piewedge}, a path array describing the wedges of the chart.
+ To access \gbc{piewedge[1]}, for example, one could use
+ \cs{mfobj}\marg{piewedge[1]}. This is almost exactly the
+ same as the \mfp{} command \cs{piewdge}\marg{1} without
+ optional arguments.
+ \item \gbc{pieangle}, a numeric array, gives the starting angles of
+ the wedges.
+ \item \gbc{piedirection}, a pair array, gives the unit vectors
+ pointing from the center of the piechart through middles of the
+ wedges. For example, if \cs{pieangle1} is 0 and \gbc{pieangle2}
+ is 90 degrees, then \gbc{piedirection1} is $(\cos 45,\sin 45)$,
+ the unit vector whose angle is $45$ degrees.
+\end{itemize}
+
+Using \cs{barchart} (or \cs{mfpbarchart} or any of its aliases) causes
+the following arrays to become defined (or redefined). The exact meaning
+depends on whether bars are horizontal or vertical. The following
+describes horizontal bars; exchange the roles of $x$ and $y$ if they are
+vertical (also change `right' to `top', etc.):
+\begin{itemize}
+ \item \gbc{barstart}, a numeric array, gives the position on the
+ $y$-axis of the leading edge of the bars.
+ \item \gbc{barbegin}, numeric, gives the $x$-coordinate of the
+ leftmost end of the bars.
+ \item \gbc{barend}, numeric, gives the $x$-coordinate of the rightmost
+ end of the bars.
+ \item \gbc{chartbar}, a path array, gives the actual bars. For
+ example, \gbc{chartbar2} is the rectangle with opposite corners
+ \gbc{(barbegin2,barstart2)} and \gbc{(barend2,barstart2+barwd)},
+ where the numeric variable \gbc{barwd} is the thickness of the
+ bar (which is a height for horizontal bars).
+ \item \gbc{barlength}, the same as \gbc{barend}. This is for backward
+ compatibility; the name was chosen at a time when all the bars
+ had one side on an axis.
+\end{itemize}
+
+
+\subsection{Miscelaneous pair expressions}\label{pairexpressions}
+
+A useful \MF{} operator that produces points is the intermediation
+operator, whose syntax is
+\begin{cd}
+\texttt{(\meta{num})[\meta{$p_1$},\meta{$p_2$}]}
+\end{cd}
+That is, a number or numeric expression in parentheses followed by
+literal brackets (this is \emph{not} an optional argument) containing
+two points or pair expressions separated by a comma. It returns an
+intermediate point on the line through \meta{$p_1$} and \meta{$p_2$}.
+The formula for the returned value is $p_1 + \mbox{\meta{num}}(p_2 -
+p_1)$. The midpoint is obtained with $\mbox{\meta{num}} = .5$. If the
+\meta{num} is a pure number, the parentheses can be omitted, but they
+are required if it is any other numeric expression. Values of \meta{num}
+larger than 1 or less than zero produce points on the line that lie
+outside the segment from $p_1$ to $p_2$. This operator can also be
+applied to numbers or (in \MP{}) to colors (of the same type). So that
+\codebox{(2/3)[3,6] = 5} and \codebox{.7[green,blue] = (0,.3,.7)}. See
+section~\ref{colors} for a description of colors in \MP{} and \MF{}.
+
+\begin{cd}
+ \gbc{pathpoint(\meta{frac},\meta{name})}
+\end{cd}
+This is another useful \MF{} command. It requires a number, \meta{frac},
+and the \emph{name} of a previously defined \MF{} path variable.
+(Defined, for example, using \cs{store}; see
+subsection~\ref{transformation}). It returns the point on the path that
+is approximately that fraction of the path's length from the start of
+the path. For example to draw a line from $(0,0)$ to the midpoint of an
+arc, do the following:
+\begin{verbatim}
+\store{myarc}\draw\arc{(1,0),(0,2),90}
+\polyline{(0,0), pathpoint(.5,myarc)}
+\end{verbatim}
+\CMF{} has no general command for calculating the lengths of paths;
+\CMP{} does, but it is quite slow. Thus neither program has an efficient
+method for finding the described point, so \mfp{} uses \MF\slash\MP{} macros
+that are faster, but less accurate than they could be. Still, the
+results should (except in pathological cases) be accurate to within a
+couple of percent of the length of the path. If they are not, adjust the
+value of the fraction. These remarks about accuracy also hold for any
+other command (such as \cs{partpath} in subsection~\ref{reversal}) that
+take the fraction of a path length as a parameter.
+
+The \gbc{pathpoint} command is not a basic \MF{} command, but is defined
+by the \prog{grafbase} macros that accompany \mfp{}.
+
+\MF{} pairs can conveniently be viewed as complex numbers. So
+\file{grafbase} also contains some functions useful in complex analysis
+(my research field). In what follows \gbc{a}, \gbc{z} and \gbc{w} denote
+pair variables or constants, and each function interprets them as
+complex numbers. Also \gbc{t} denotes an angle in radians. There are
+both numeric and pair valued functions, the type of each is noted after
+the description:
+
+\def\Arg{\mathop{\mathrm{Arg}}}
+
+\noindent
+\begin{tabular}{@{}lp{4.2in}}
+\gbc{Arg z} & The principle argument of $z$ in radians (numeric).\\
+\gbc{Log z} & The principle logarithm of $z$ (pair).\\
+\gbc{cis t} & $(\cos t, \sin t)$, same as \gbc{dir degrees(t)} (pair).\\
+\gbc{zexp w} & The complex exponential, $e^w$ (pair).\\
+\gbc{zsqrt w} & The (principal) complex square root: that $z$ with
+ $-\pi/2 \le \Arg z \le \pi/2$ and $z^2 = w$ (pair).\\
+\gbc{sgn z} & The signum, $\sgn (0,0) = (0,0)$ otherwise
+ $\sgn z = z/|z|$ (pair).\\
+\gbc{conj z} & The complex conjugate, $\bar z$ (pair).\\
+\gbc{Moebius(a) z} & The M\"obius transformation $(z+a)/(1+\bar{a}z)$ (pair)\\
+\gbc{pshdist(z,w)} & The pseudohyperbolic distance between $z$ and
+ $w$: $|z-w| / |1-\bar{w}z|$ (numeric).\\
+\gbc{kelvin(z)} & The Kelvin transform $1/\bar z$ (pair)
+\end{tabular}
+
+\CMF{} will happily add and subtract pairs but to multiply and divide
+complex numbers requires new operations. These are given by \codebox{(z
+zmul w)} and \codebox{(z zdiv w)}. They operate on pairs and produce
+pairs.
+
+
+\subsection{Manipulating \MF{} picture variables}
+
+\begin{cd}\pagelabel{tile}
+\cs{tile}\marg{\meta{tilename},\meta{unit},\meta{wd},\meta{ht},\meta{clip}}\\
+ \ \meta{\mfp{} drawing commands}\\
+\cs{endtile}%
+\index{tile@\cs{tile}}%
+\index{endtile@\cs{endtile}}
+\end{cd}
+
+In this environment, all drawing commands contribute to a \emph{tile}. A
+\emph{tile} is a rectangular picture which may be used to fill the
+interior of closed paths. Actually, a tile is a composite object. After
+\cs{tile}\marg{Nick, ... } $\ldots$ \cs{endtile} a picture variable
+\gbc{Nick.pic} is created as well as numeric variable \gbc{Nick.wd} and
+\gbc{Nick.ht}. These are needed by the \cs{tess} command, below.
+
+The units of drawing are given by \meta{unit}, which should be an
+explicit dimension (like \dim{1pt} or \dim{.2in}). The tile's horizontal
+dimensions are $0$ to $\meta{wd}\cdot\meta{unit}$ and its vertical
+dimensions $0$ to $\meta{ht}\cdot\meta{unit}$, so \meta{wd} and
+\meta{ht} should be pure numbers. If \meta{clip} is \mfc{true} then the
+drawing is clipped to be within the tile's boundary.
+
+By using this macro, you can design your own fill patterns (to use them,
+see the \cs{tess} macro below), but see the warning about memory use by
+the \cs{tess} command. The \meta{tilename} is globally defined by this
+command.
+
+\begin{cd}\pagelabel{tess}
+\cs{tess}\marg{\meta{tilename}}$\ldots$%
+\index{tess@\cs{tess}}
+\end{cd}
+
+This rendering macro tiles the interior of a closed path with a
+tessellation comprised of copies of the \emph{tile} specified by
+\meta{tilename}. The tile must have been previously created by
+\cs{tile}\marg{\meta{tilename}, ... }. Tiling an open curve is
+technically an error, but the \MF{} code responds by drawing the path
+and not doing any tiling. The \MF{} code places shifted copies of the
+tile picture in a rectangular grid sufficient to cover the region, then
+clips it to the closed path before drawing it.
+
+Tiling large regions with complicated tiles can exceed the capacity of
+some versions of \MP{}. There is less of a problem with \MF{}. This is not
+because \MF{} has greater capacity, but because of the natural
+difference between bitmaps and vector graphics.
+
+In \MP{}, the tiles are copied with whatever color they are given when
+they are defined. They can be multicolored.
+
+Before version 0.8, \cs{tile} was the only way to create a picture
+variable, and the only way to draw this picture was with the \cs{tess}
+command. Now we have the following command to place multiple copies of
+a picture:
+
+\begin{cd}\pagelabel{putmfpimage}
+ \cs{putmfpimage}\marg{\meta{name}}\marg{\meta{list}}%
+\index{putmfpimage@\cs{putmfpimage}}
+\end{cd}
+
+This take the name of a picture variable and copies the picture at each
+location in the \meta{list}, which should be a comma-separated list of
+coordinate pairs in graph coordinates. The picture is copied so that its
+\emph{reference point} is placed at each of the locations. The reference
+point of a picture created with \cs{tile} is its lower left corner.
+
+\begin{cd}\pagelabel{mfpimage}
+ \cs{mfpimage}\oarg{\meta{refpt}}\marg{\meta{picname}}\\
+ \ \meta{\mfp{} drawing commands}\\
+ \cs{endmfpimage}%
+\index{mfpimage@\cs{mfpimage}}%
+\index{endmfpimage@\cs{endmfpimage}}
+\end{cd}
+
+This is another way to create a picture variable. The drawing commands
+within the \env{mfpimage} environment contribute not to the current
+\mfp{} picture, but rather to the picture variable named in \meta{picname}.
+Otherwise, they operate exactly as they would outside this environment,
+using the same coordinate system and the same default values of all
+parameters, etc. (unlike the \env{tile} environment, which defines its
+own coordinate system). The picture is created with its reference point
+at the point \meta{refpt} given in the optional argument. The default is
+\texttt{(0,0)}. For example:
+\begin{verbatim}
+\mfpimage[(1,1)]{Jan}
+ \fill\rect{(0,0),(1,1)}
+ \fill\rect{(1,1),(2,2)}
+ \rect{(0,0),(2,2)}
+\endmfpimage
+\end{verbatim}
+produces a simple 2-by-2 chessboard with its reference point at the
+center point $(1,1)$. One can then write something like
+\begin{verbatim}
+\putmfpimage{Jan}{(1,1),(3,1),(1,3),(3,3)}
+\end{verbatim}
+to get a 4-by-4 chessboard: the picture \mfc{Jan} copied with its
+center at each of the listed points.
+
+The behavior of \cs{tlabel} in an \env{mfpimage} environment depends on
+the setting. If \opt{mplabels} is turned off, then labels are added by
+\TeX{} and are \emph{not} included as part of the named \MF{} or \MP{}
+picture variable. They are placed on the current picture as if the
+\env{mfpimage} environment were not there at all. If \opt{mplabels} is
+turned on and \opt{overlaylabels} is also turned on, or if the
+\env{mfpimage} environment is between \cs{startbacktext} and
+\cs{stopbacktext}, then the labels will be saved and placed when the
+\env{mfpic} environment ends and \emph{not} added to the named picture
+variable. Thus, to include text labels in the named picture variable,
+you must have \opt{mplabels} on, \opt{overlaylabels} off, and
+\env{mfpimage} outside any \cs{startbacktext}\slash\cs{stopbacktext}.
+
+The picture created by \cs{mfpimage} is locally defined. That is, it
+becomes undefined at the end of the current \env{mfpic} environment. If
+one needs it to be global, one can use \cs{globalsetmfvariable} (see
+subsection~\ref{variables}) to copy it to another variable. For example.
+the command
+\begin{verbatim}
+ \globalsetmfvariable{picture}{Dan}{Jan}
+\end{verbatim}
+would make \gbc{Dan} globally defined to be equal to the current value
+of the picture \gbc{Jan}. Note that picture variables can consume a lot
+of \MF{}'s memory. Copying one variable to another doubles the amount of
+memory, at least until the end of the \env{mfpic} environment.
+
+You can use \cs{putmfpimage} inside a \env{mfpimage} environment,
+provided the picture being placed has been previously defined. Nesting a
+\env{mfpimage} inside another has not been tested at all and so is not
+recommended. But if it works, the inner image would be local to the
+environment created by the outer one, and so would be of limited use.
+One can use the \LaTeX{} environment construct \cs{begin}\marg{mfpimage}
+$\ldots$ \cs{end}\marg{mfpimage} in a LaTeX document instead of
+\cs{mfpimage} $\ldots$ \cs{endmfpimage}.
+
+
+\subsection{\CMF{} loops}\label{loops}
+
+All the \mfp{} loop commands create a loop (in the \MF{} language) in
+the output file. The \MF{} commands in that loop are executed repeatedly
+by \MF{} or \MP{}. From the point of view of \TeX{}, however each
+command occurs only once. Starting with version 0.9, these loops can be
+created inside or outside the \env{mfpic} drawing environment. If
+outside, they must not contain any drawing commands, but can contain
+commands that set variables, perform computations, etc.
+
+\begin{cd}\pagelabel{mfpfor}
+\cs{mfpfor}\marg{\meta{for-loop header}}\\
+ \ \meta{\mfp{} commands}\\
+\cs{endmfpfor}%
+\index{mfpfor@\cs{mfpfor}}%
+\index{endmfpfor@\cs{endmfpfor}}
+\end{cd}
+
+This creates a for-loop in the \MF{} output file. The \cs{mfpfor} writes
+the start of the loop and \cs{endmfpfor} writes the end. Any code
+written in the output file between them is executed repeatedly by
+\MF{}, according to the information in \meta{for-loop header}. There are
+two types of headers possible, illustrated by the following examples.
+\begin{verbatim}
+\mfpfor{center = (0,0), (1,0), (0,1)}
+ \gfill\circle{center,1}
+\endmfpfor
+\end{verbatim}
+This example will fill three circles of radius 1 with centers at the
+three given points. This type of header has the format
+\begin{display}
+ \mfc{\meta{variable} = \meta{list}}
+\end{display}
+where \meta{variable} should be a simple variable name and \meta{list}
+is a comma separated list of items of the appropriate data type. In the
+above, \gbc{center} is equated to pairs, but in the following
+\begin{verbatim}
+\mfpfor{radius = 1,3,4}
+ \dotted\circle{(0,0),radius}
+\endmfpfor
+\end{verbatim}
+\gbc{radius} gets numeric values.
+
+The other type of header uses a stepped variable:
+\begin{verbatim}
+\mfpfor{level = 3 step 2 until 9}
+ \circle{(0,0),sqrt(level)}
+\endmfpfor
+\end{verbatim}
+This will cause the \MF{} variable \gbc{level} to step through the
+values 3, 5, 7 and 9 and the circles with radius $\sqrt{3}$, $\sqrt{5}$,
+etc. will be drawn. This type of header has the format
+\begin{display}
+ \mfc{\meta{variable} = \meta{start} step \meta{delta} until \meta{stop}}
+\end{display}
+where \meta{variable} is as before, while \meta{start}, \meta{delta} and
+\meta{stop} are numeric values. If \meta{delta} is positive the loop is
+skipped entirely if \meta{stop} is less than \meta{start}. Otherwise the
+loop is executed successively with the variable equal to \meta{start},
+then $\meta{start} + \meta{delta}$ then $\meta{start} + 2\meta{delta}$,
+etc., as long as the variable is not greater than \meta{stop}. The
+behavior is similar if \meta{delta} is negative, except the loop is
+repeated only as long as the variable is not less than \meta{stop}. If
+\meta{delta} is \mfc{0}, then the \MF{} run will generate an error.
+
+Note that the index variable (\gbc{center} and \gbc{radius} in the above
+two examples) is a temporary \MF{} variable. If \opt{mplabels} is turned
+on, this variable will work as expected in the \emph{location} parameter
+of a \cs{tlabel} command, but if it is used in the \emph{label} part, it
+will be interpreted as \TeX{} code and printed as is. The index variable
+reverts to its previous state outside the loop. That is, if it existed
+before the loop, it regains its previous value after the loop, and if it
+was undefined before the loop, it is again undefined after.
+
+The single word `\mfc{upto}' can be used as an abbreviation for
+``\codebox{step 1 until}'' and `\mfc{downto}' for ``\codebox{step -1 until}''
+in for-loop headers. Spaces are not significant in for-loop headers,
+except to distinguish the keywords (e.g. \mfc{step}) from variable names
+that might be used (e.g., for \meta{start}).
+
+\begin{cd}\pagelabel{mfpwhile}
+ \cs{mfpwhile}\marg{\meta{condition}}\\
+ \ \meta{\mfp{} commands}\\
+ \cs{endmfpwhile}%
+\index{mfpwhile@\cs{mfpwhile}}%
+\index{endmfpwhile@\cs{endmfpwhile}}
+\end{cd}
+
+The \meta{condition} should be an expression that can be either true or
+false about a \MF{} variable that changes at some time during the loop
+body. The loop body is executed (by \MF) as long as the condition is
+true. Example:
+\begin{verbatim}
+\setmfvariable{numeric}{R}{20}
+\mfpwhile{R > 1}
+ \rect{(0,0), (R,3R)}
+ \mfcmd{R:=R/2}
+\endmfpwhile
+\end{verbatim}
+There are no \mfp{} commands to \emph{systematically} change a variable,
+so in this example we have resorted to directly writing a \MF{} assignment
+command via \cs{mfcmd} (see subsection~\ref{mfcode} above) that reduces
+\mfc{R} by half. The loop will be executed with \mfc{R} having the
+successive values $20$, $10$, $5$, $2.5$, and $1.25$. The resulting
+picture could have been achieved with \cs{mfpfor} using this list of
+values.
+
+\begin{cd}\pagelabel{mfploop}
+\cs{mfploop}\\
+ \ \meta{\mfp{} commands}\\
+\cs{mfpuntil}\marg{\meta{condition}}\\
+ \ \meta{\mfp{} commands}\\
+\cs{endmfploop}%
+\index{mfploop@\cs{mfploop}}%
+\index{mfpuntil@\cs{mfpuntil}}%
+\index{endmfploop@\cs{endmfploop}}%
+\end{cd}
+
+The body of this loop will be repeated until the \meta{condition}
+becomes true. The condition should be some expression that can be either
+true or false about a variable that changes during the loop execution.
+It should eventually become true. If an \env{mfploop} environment does
+not contain an \cs{mfpuntil} command, then the \cs{endmfploop} command
+will generate a warning message. If the warning is ignored, and the user
+has not otherwise arranged for loop termination,%
+ \footnote{Perhaps by means of \cs{mfsrc} commands. It is because of
+ this possibility that only a warning is produced and not an error.
+ If the warning becomes annoying, adding \cs{mfpuntil\marg{false}} to
+ the loop will silence it. This command will never break the loop
+ because the condition \mfc{false} (of course) never becomes true.}
+the \file{.mf} file will contain an infinite loop. The \cs{mfpuntil}
+command will break the loop at whatever point it occurs. Example:
+\begin{verbatim}
+\setmfvariable{numeric}{R}{20}
+\mfploop
+ \mfcmd{R:=R/2}
+ \mfpuntil{R <= 1}
+ \rect{(0,0), (R,3R)}
+\endmfploop
+\end{verbatim}
+This will draw rectangles with $R$ equal to $10$, $5$, $2.5$, and
+$1.25$. On the next execution of the loop the condition \mfc{R<=1} is
+true, and the break occurs before the next rectangle is drawn. Note that
+any \cs{mfpwhile} could be encoded with \cs{mfploop}. In fact, the code
+written to the output file by
+\begin{display}
+ \cs{mfpwhile}\marg{\meta{condition}}
+\end{display}
+is identical to that written by
+\begin{display}
+ \cs{mfploop}\cs{mfpuntil}\marg{not \meta{condition}}
+\end{display}
+
+The command \cs{mfpuntil} can also be used in \env{mfpfor} and
+\env{mfpwhile} environments to break the loop prematurely when the given
+condition becomes true.
+
+All three of these loop structures bracket the inner code in a \TeX{}
+group. In a \LaTeX{} document, the usual \cs{begin}\slash\cs{end} style can
+be used. For example,
+\begin{verbatim}
+\begin{mfpfor}{radius = 1,3,4}
+ \circle{(0,0),radius}
+\end{mfpfor}
+\end{verbatim}
+
+Just to be clear: in all the examples, what is written to the figure
+file is a \emph{single} circle or rectangle drawing command, bracketed
+by code that causes \MF{} to execute it several times with different
+values for the variable. From \TeX{}'s point of view, there is only one
+\mfp{} drawing command.
+
+
+\subsection{Miscellaneous}\label{misc}
+
+\begin{cd}\pagelabel{mfmode}
+\cs{mfmode}\marg{\meta{mode-name}}\\
+\cs{mfresolution}\marg{\meta{DPI}}%
+\end{cd}
+
+When working with \MF{}, the code in \file{grafbase.mf} needs to know
+the resolution at which to make the font with all the figures. If the
+wrong resolution is assumed, the figure may end up appearing wrongly
+scaled or have other problems (especially with shading). If your DVI
+viewing/printing program and the file \file{modes.mf} are correctly
+configured, nothing may need to be done. If not, as a last resort, you
+can set the \MF{} mode or the \MF{} resolution in your \file{.tex} file
+with these commands. If you don't know what that means, ask a guru, but
+then you should probably be using \MP{} and not \MF{}.
+
+Note that this is a \emph{last resort}. The code in \file{grafbase.mf}
+first checks if \mfc{mode} has been defined, then checks if
+\mfc{localfont} is defined and only then checks if the resolution has
+been set by this method (if all three fail, it uses a value of 600 DPI).
+
+\begin{cd}\pagelabel{noship}
+\cs{noship}\\%
+\cs{stopshipping}\\%
+\cs{resumeshipping}%
+\index{noship@\cs{noship}}%
+\index{stopshipping@\cs{stopshipping}}%
+\index{resumeshipping@\cs{resumeshipping}}
+\end{cd}
+
+\cs{stopshipping} turns off character shipping (by \MF{} to the TFM and
+GF files, or by \MP{} to appropriate \EPS{} output file) until
+\cs{resumeshipping} occurs. If you want just one character not shipped,
+just use \cs{noship} inside that \env{mfpic} environment. This is useful
+if all one wishes to do in the current \env{mfpic} environment is to
+make tiles (see above) or define picture variables with \cs{mfpimage} or
+path arrays with \cs{patharr}. While \cs{mfpimage} defines the picture
+locally, one can globally copy it to another variable with
+\cs{globalsetmfvariable} (see subsection~\ref{variables}).
+
+\begin{cd}\pagelabel{assignmfvalue}
+\cs{assignmfvalue}\marg{\meta{\TeX{}-macro}}\marg{\meta{MF-expr}}\\
+\cs{assignmpvalue}\marg{\meta{\TeX{}-macro}}\marg{\meta{MF-expr}}\\
+\cs{globalassignmfvalue}\marg{\meta{\TeX{}-macro}}\marg{\meta{MF-expr}}\\
+\cs{globalassignmpvalue}\marg{\meta{\TeX{}-macro}}\marg{\meta{MF-expr}}%
+\index{assignmfvalue@\cs{assignmfvalue}}%
+\index{assignmpvalue@\cs{assignmpvalue}}%
+\index{globalassignmfvalue@\cs{globalassignmfvalue}}%
+\index{globalassignmpvalue@\cs{globalassignmpvalue}}%
+\end{cd}
+
+The command names spelled with `\texttt{mp}' are no different than the
+ones spelled with `\texttt{mf}'. You can use either spelling with
+either the \opt{metafont} or \opt{metapost} option.
+
+These commands causes the \meta{MF-expr} to be written to the output
+file for \MF{} to evaluate. The resulting value is then written to the
+\file{.log} file of that \MF{} run. On the next \TeX{} run, if
+\opt{mfpreadlog} (see section~\ref{readlog}) is in effect, the macro
+\meta{\TeX{}-macro} will be defined to produce the resulting value. For
+example:
+\begin{verbatim}
+\setmfnumeric{s}{2}
+\assignmfvalue{\val}{exp s}
+\tlabel(1,2){$e^s = \val$}
+\end{verbatim}
+After \MF{} is run and then \TeX{} run a second time, \cs{val} will
+acquire the definition `7.38905', the value of \gbc{exp s} when
+\gbc{s=2} (i.e., $e^2$, correct to at least the fourth decimal place).
+If \opt{mplabels} is in effect, the correct label is written to the
+figure file only during this second run, and a second \MP{} run will be
+required. In many cases (when using \pdfTeX{}, for example, or when the
+label changes the figure dimensions), a third \TeX{} run will be
+required to make the figure correct when it is included in the document.
+
+Before \MF{} is run to evaluate the expression, the macro produces
+`???'. Thus, it cannot be used in places where a number is needed (as in
+the position arguments of a \cs{tlabel} command). Note also that if a
+command defined by \cs{assignmfvalue} is used in a tlabel with
+\opt{mplabels} in effect, then \opt{mplabels} must be in effect during
+the \cs{assignmfvalue} command as well.
+
+The `\texttt{global}' version makes the definition of the
+\meta{\TeX{}-macro} global, surviving the current group. In particular,
+it can be used in other pictures. The plain versions create commands
+that are only locally defined. Past versions of this manual stated that
+you can say
+\begin{display}
+ \cs{global}\cs{assignmfvalue}
+\end{display}
+to define the macro globally. This turns out not to be true in all
+cases. If a global definition is needed, use the global versions above.
+
+Because of the asynchronous nature of the definition process, using
+\cs{assignmfvalue} with the same macro name more than once in the same
+\env{mfpic} environment will not work. The macro becomes defined
+upon reading the logfile during the execution of \cs{opengraphsfile},
+and it will end up with the last definition encountered. (The same is
+true for uses outside \env{mfpic} environments: the macro acquires the
+last such definition.) Moreover, the definition is associated to a
+picture by number. Which means that reordering the environments or
+changing the numbering by any means will require the \TeX{}-\MF{}-\TeX{}
+sequence (or more) to be repeated.
+
+If the \meta{\TeX{}-macro} is already defined, no warning will be issued
+and the command will be redefined, so be careful in the name chosen.
+If \opt{mplabels} is turned off when \cs{assignmfvalue} is used, but
+turned on before the \meta{\TeX{}-macro} is used in a \cs{tlabel}
+command, the macro definition will not be written to the \file{.mp}
+file, and either an error message, or incorrect label will result
+when \MP{} tries to make the tlabel.
+
+The concept and much of the code for \cs{assignmfvalue} came from Werner
+Lemberg. However, I have rewritten it substantially to conform to \mfp{}
+conventions and so any errors are my responsibility.
+
+\begin{cd}\pagelabel{cutoffafter}
+\cs{cutoffafter}\marg{\meta{obj}}\dots\\
+\cs{cutoffbefore}\marg{\meta{obj}}\dots\\
+\index{cutoffafter@\cs{cutoffafter}}%
+\index{cutoffbefore@\cs{cutoffbefore}}%
+\end{cd}
+
+These prefix macros modify the following path by cutting part of it off.
+They take an `object' (a variable in which a path was
+previously stored using \cs{store}) and uses it to trim off one end of the
+following path. \cs{cutoffbefore} cuts off the part of the path
+\emph{before} its first intersection with the object, while
+\cs{cutoffafter} cuts off the part \emph{after} the last intersection.
+If the path does not intersect the object, nothing is cut off. If the
+object and the path intersect in more than one point, as little as
+possible (usually%
+ \footnote{\MF{}'s methods for finding the `first' point of
+ intersection do not always find the actual first one.}) %
+is cut off. This is reliable only when there is a unique point of
+intersection.
+
+These macros can be used to create a curve that starts or ends
+right at another figure without having to know the point where the two
+curves intersect.
+
+\begin{cd}\pagelabel{random}
+\cs{randomlines}\marg{\meta{maxshift}}\dots\\
+\cs{randomizepath}\marg{\meta{maxshift}, \meta{weirdness}}\dots
+\index{randomizepath@\cs{randomizepath}}%
+\index{randomlines@\cs{randomlines}}
+\end{cd}
+
+These modify the following path by applying random shifts to the nodes
+of a path. The first one, \cs{randomlines} then simply connects those
+new points by straight lines, while the second one also applies
+randomization to the control vectors. The \meta{maxshift} argument is
+either a positive number (in graph units) that limits the distance a
+node can be moved, or it is an ordered pair of positive numbers, in
+which case the first limits the horizontal distance and the second
+limits the vertical. If \meta{maxshift} is larger than the distance
+between nodes, cusps or loops are likely in the result.
+
+For \cs{randomizepath} the \meta{weirdness} parameter controls how the
+control vectors are modified. Roughly speaking the control vectors are
+randomly rotated up to $30\langle\mathit{weirdness}\rangle$ degrees and
+randomly scaled up or down by a factor of
+$2^{\langle\mathit{weirdness}\rangle}$. (A ``control vector'' is a
+vector pointing from a node to one of its control points.) However, this
+is done in a way that preserves smoothness at each node where the path
+is smooth. Values of \meta{weirdness} greater than 1 are probably much
+too weird.
+
+\begin{cd}\pagelabel{brownianmotion}
+\cs{brownianmotion}\marg{\meta{start},\meta{num},\meta{scale}}\\%
+\cs{browniangraph}\marg{\meta{num},\meta{scale}}\\%
+\cs{randomwalk}\marg{\meta{start},\meta{num},\meta{scale}}%
+\index{brownianmotion@\cs{brownianmotion}}%
+\index{browniangraph@\cs{browniangraph}}%
+\index{randomwalk@\cs{randomwalk}}
+\end{cd}
+
+These figure macros build a few standard kinds of random paths. The
+\cs{brownianmotion} path starts at the point \meta{start}, then proceeds
+in a straight line in a random direction a random distance. This is
+repeated \meta{num} times to form a polyline. The random process used is
+a Gaussian in each coordinate, scaled so that the random distance has a
+standard deviation equal to \meta{scale}. Thus, \meta{start} is a
+coordinate pair in graph coordinates, \meta{num} is a positive whole
+number and \meta{scale} is a positive real number (in graph units). In
+rare cases, the random distance can become quite large, but on average
+it will be about $0.56\times{}$\meta{scale}. The size of the resultant
+path (its bounding box) can also be, in rare cases, quite large, but it
+is usually on the order of $\sqrt{\meta{num}}$ times \meta{scale}.
+
+The second path, \cs{browniangraph}, represents the graph of a
+one-dimensional Brownian motion. It is random only in the vertical
+direction as the rightward motion represents the uniform passage of
+time. It starts at $(0,0)$ and the \meta{scale} is both the constant
+rightward step as well as the standard deviation for the $y$-coordinate.
+Users will need to apply a shift if they want to change the starting
+point, and a vertical scaling if they want a scale factor different from
+the step size.
+
+Despite their names, the paths produced are technically not Brownian
+motion, but rather `Gaussian random walks'. However, for small
+\meta{scale} and large \meta{num} they can be used to approximate
+Brownian motion.
+
+Finally, \cs{randomwalk} is just like \cs{brownianmotion} except that
+only the direction is random. The distance is always equal to
+\meta{scale}.%
+ \footnote{This is only one kind of an infinite variety of possible
+ random walks. See \url{http://en.wikipedia.org/wiki/Random_walk} for a
+ discussion. \Mfp{} implementation of other kinds is left to the
+ interested user (for example, using \cs{turtle} with random
+ displacements).}
+
+There can be a problem with the size of \meta{num} in these three
+macros. Numbers greater than a certain \MF/\MP{} parameter called
+\verb$max_points$ (see the discussing at \cs{levelcurve} in
+section~\ref{plotting}) will produce an error from \MF{} or \MP{}. But
+also sharp turns will take up space in something called the
+\emph{rounding table}. This has no bearing on \MP{}, and in \MF{} it
+only matters if the parameter \mfc{autorounding} is positive. \Mfp{}
+leaves \mfc{autorounding} at the default of $2$, since this value makes
+drawings in \MF{} look best. In this case, the value of \meta{num}
+should be less than about $500$.
+
+\begin{cd}\pagelabel{mftitle}
+\cs{mftitle}\marg{\meta{title}}%
+\index{mftitle@\cs{mftitle}}
+\end{cd}
+
+Write the string \meta{title} to the \MF{} file, and use it as a \MF{}
+message. (See \textit{The \MF{}book}, chapter 22, page 187, for two uses of
+this.)
+
+\begin{cd}\pagelabel{tmtitle}
+\cs{tmtitle}\marg{\meta{title}}%
+\index{tmtitle@\cs{tmtitle}}
+\end{cd}
+
+Write the text \meta{title} to the \TeX{} document, and to the log file,
+and use it implicitly in \cs{mftitle}. This macro forms a local group
+around its argument.
+
+\medskip
+
+Since \TeX{} is limited to 256 dimension registers, and since dimensions
+are so important to typesetting and drawing, it is common to use up all
+256 when drawing packages are loaded. Therefore \mfp{} uses font
+dimensions to store dimension values. The following is the command that
+handles the allocation of these dimensions.
+
+\begin{cd}\pagelabel{newfdim}
+\cs{newfdim}\marg{\meta{fdim}}%
+\index{newfdim@\cs{newfdim}}
+\end{cd}
+
+This create a new global font dimension named \meta{fdim}, which is a
+\TeX{} control sequence (with backslash). It can be used almost like
+an ordinary \TeX{} dimension. One exception is that the \TeX{} commands
+\cs{advance}, \cs{multiply} and \cs{divide} cannot be applied directly
+to font dimensions (nor \LaTeX{}'s \cs{addtolength}); however, the font
+dimension can be copied to a temporary \TeX{} dimension register, which
+can then be manipulated and copied back (using \cs{setlength} in \LaTeX{},
+if desired). Another exception is that all changes to a font dimension
+are global in scope. Also beware that \cs{newfdim} uses font dimensions
+from a single font, the \file{dummy} font, which most \TeX{} systems
+ought to have. (You'll know if yours doesn't, because \mfp{} will fail
+upon loading!) Also, implementations of \TeX{} differ in the number of
+font dimensions allowed per font. \Mfp{} currently uses font dimensions
+23 through 52, which should be OK.
+
+Almost all of \mfp{}'s basic dimension parameters are font dimensions.
+We arrange for them to be local to \env{mfpic} environments by saving
+their values at the start and restoring them at the end.
+
+\begin{cd}\pagelabel{setmfpicgraphic}
+\cs{setmfpicgraphic}\marg{\meta{filename}}%
+\index{setmfpicgraphic@\cs{setmfpicgraphic}}
+\end{cd}
+
+This is the command that is invoked to place the graphic created. See
+appendix~\ref{graphics} for a discussion of its use and its default
+definition. It is a user-level macro so that it can be redefined in
+unusual cases. It operates on the output of the following macro:
+
+\begin{cd}\pagelabel{setfilename}
+\cs{setfilename}\marg{\meta{file}}\marg{\meta{num}}%
+\index{setfilename@\cs{setfilename}}
+\end{cd}
+
+\Mfp's figure inclusion code ultimately executes
+\cs{setmfpicgraphic} on the result of applying \cs{setfilename} to two
+arguments: the file name specified in the \cs{opengraphsfile} command
+and the number of the current picture. Normally \cs{setfilename} just
+puts them together with the `\texttt{.}' separator (because that is
+usually the way \MP{} names its output), but this can be redefined if
+the \MP{} output undergoes further processing or conversion to another
+format in which the name is changed. Any redefinition of
+\cs{setfilename} must come before \cs{opengraphsfile} because that
+command tests for the existence of the first figure. After any
+redefinition, \cs{setfilename} must be a macro with two arguments that
+creates the actual filename from the above two parts. It should also be
+completely expandable. See the appendices, subsection~\ref{graphics} for
+further dicussion.
+
+\begin{cd}\pagelabel{setfilenametemplate}
+\cs{setfilenametemplate}\marg{\meta{template}}%
+\index{setfilenametemplate@\cs{setfilenametemplate}}
+\end{cd}
+
+With the \opt{metapost} option, when you write
+\cs{opengraphsfile}\marg{figs}, a file \file{figs.mp} is created. By
+default, running \MP{} on it results in files named \file{figs.1},
+\file{figs.2}, etc. Recent \MP{} allows the output filenames to be
+modified. As of \mfp{} version 1.00, you can do this to some extent from
+your \file{.tex} file. One needs to define a template that tells \MP{}
+how to construct the output file name from the `jobname' and the figure
+number. This is done with the above command. In \meta{template} you can
+put any plain characters, plus the two special tokens: \verb$\_$ and
+\verb$\#$. Each figure's filename is constructed by replacing these
+tokens with the \MP{} jobname and the figure number, respectively. For
+example, with the jobname \file{figs},
+\begin{verbatim}
+\setfilenametemplate{my\_-\#.mps}
+\end{verbatim}
+will cause the figure files to have names \file{myfigs-1.mps},
+\file{myfigs-2.mps}, etc., instead of the defaults. \Mfp{} adjusts the
+definition of \cs{setfilename} accordingly, so that the correct
+filenames are used.
+
+Do not use this command unless you know your version of \MP{} is recent
+enough to have this capability. Under the \opt{metafont} option, this
+command is simply ignored, but \mfp{} has no way of checking the \MP{}
+version on its own.
+
+If you are using \LaTeX{}, the \verb$\includegraphics$ command requires
+that the included figure file be recognized as \MP{} output. In practice,
+this usually means its extension \emph{must} be \texttt{.mps}. As an
+exception, it may also be the current figure number (the default if
+\verb$\setfilenametemplate$ is not used), because \mfp{} has always
+arranged for that to be recognized. The user may also issue a
+\verb$\DeclareGraphicsRule$ command to get other extensions recognized.
+See the documentation of the \prog{graphics} package.
+
+
+\begin{cd}\pagelabel{preparemfpicgraphic}
+\cs{preparemfpicgraphic}\marg{\meta{filename}}%
+\index{preparemfpicgraphic@\cs{preparemfpicgraphic}}
+\end{cd}
+
+This command is automatically invoked before \cs{setmfpicgraphic} to
+make any preparations needed. The default definition is to do nothing
+except when the \prog{graphics} package is used. That package provides
+no clean way to determine the bounding box of the graphic after it is
+included. Since \mfp{} needs this information, this command redefines an
+internal command of the \prog{graphics} package to make the data
+available. If \cs{setmfpicgraphic} is redefined then this may also have
+to be redefined.
+
+\begin{cd}\pagelabel{getmfpicoffset}
+\cs{getmfpicoffset}\marg{\meta{filename}}%
+\index{getmfpicoffset@\cs{getmfpicoffset}}
+\end{cd}
+
+This command is automatically invoked after \cs{setmfpicgraphic} to
+store the offset of the lower left corner of the figure in the macros
+\cs{mfpicllx} and \cs{mfpiclly}. If \cs{setmfpicgraphic} is redefined
+then this may also have to be redefined.
+
+\begin{cd}\pagelabel{ifmfpmpost}
+\cs{ifmfpmpost}%
+\index{ifmfpmpost@\cs{ifmfpmpost}}
+\end{cd}
+
+Users wishing to write code that adjusts its behavior to the graph file
+processor can use this to test which option is in effect. The macro
+\cs{usemetapost} sets it true and \cs{usemetafont} sets it false. There
+are no commands \cs{mfpmposttrue} nor \cs{mfpmpostfalse}, since the user
+should not be changing the setting once it is set: a great deal of
+\mfp{} internal code depends on them, and on keeping them consistent
+with the \cs{opengraphsfile} commands reading of these booleans.
+
+\begin{cd}\pagelabel{mfpicversion}
+\cs{mfpicversion}%
+\index{mfpicversion@\cs{mfpicversion}}
+\end{cd}
+
+This expands to the current \mfp{} version multiplied by 100. At this
+writing, it produces `\texttt{\mfpicversion}' because the version is
+\mfpversion. It can be used to test the version:
+\begin{verbatim}
+\ifx\mfpicversion\undefined \def\mfpicversion{0}\fi
+\ifnum\mfpicversion<70 ... \else ... \fi
+\end{verbatim}
+\cs{mfpicversion} was added in version 0.7.
+
+
+Most of \mfp{}'s commands have arguments with parts delimited by commas
+and parentheses. In most cases this is no problem because they are
+written unchanged to the \file{.mf} and there they are parsed just fine.
+Some commands' arguments, however, have to be parsed by both \TeX{} and
+\MF{}. Examples are \cs{tlabel} (sometimes, under \opt{mplabels}), and
+\cs{pointdef}. One might be tempted to use \MP{} expressions there and
+that works fine as long as they do not contain commas or parentheses. In
+such cases, they can sometimes be enclosed in braces to prevent \TeX{}
+seeing these elements as delimiters, but sometimes these braces might
+get written to the \file{.mf} (or \file{.mp}) output and cause a \MF{}
+(\MP{}) error. In such cases the following work-around might be possible:
+\begin{verbatim}
+\def\identity#1{#1}
+\pointdef{A}(\identity{angle (1,2)},3)
+\rect{(0,0),\A}
+\end{verbatim}
+
+The braces prevent \TeX{}'s argument parsing from seeing the first comma
+as a delimiter, but upon writing to the \file{.mf}, any \cs{identity}
+commands are expanded and only the contents appear in the output. (\TeX{}
+parses the argument to assign meanings to \cs{Ax} and \cs{Ay}.)
+
+If the \prog{babel} package is loaded with certain options, the comma
+may become a special character. In that case, one may need to deactivate
+babel shorthands before some \mfp{} code. One might use \cs{everymfpic}
+to do this in every \env{mfpic} environment. In some cases, one may need
+to reactivate babel shorthands insided \cs{tlabel}, and one might use
+\cs{everytlabel} for this purpose. See your \prog{babel} documentation
+for the commands to do these things.
+
+\clearpage
+
+\def\sectionmark#1{\markright {\thesection\quad#1}}%
+\def\subsectionmark#1{}
+\def\subsubsectionmark#1{}
+\thispagestyle{plain}
+\chapter{Appendices}\label{appendices}
+
+
+\section{Acknowledgements.}\label{acknowledgements}
+
+Tom would like to thank all of the people at Dartmouth as well as out in
+the network world for testing \mfp{} and sending him back
+comments. He would particularly like to thank:
+
+Geoffrey Tobin
+for his many suggestions, especially about cleaning up the \MF{} code,
+enforcing dimensions, fixing the dotted line computations, and speeding
+up the shading routines (through this process, Geoffrey and Tom managed
+to teach each other many of the subtleties of \MF{}), and for keeping
+track of \mfp{} for nearly a year while Tom finished his thesis;
+
+Bryan Green
+for his many suggestions, some of which (including his rewriting the
+\cs{tcaption} macro) ultimately led to the current version's ability to
+put graphs in-line or side-by-side; and
+
+Uwe Bonnes and
+Jarom\'\i r Kuben,
+who worked out rewrites of \mfp{} during Tom's working hiatus and who
+each contributed several valuable ideas.
+
+Some credit also belongs to
+Anthony Stark,
+whose work on a FIG to \MF{} converter has had a serious impact on the
+development of many of \mfp{}'s capabilities.
+
+Finally, Tom would like to thank
+Alan Vlach,
+the other \TeX{}nician at Berry College, for helping him decide on the
+format of many of the macros, and for helping with testing.
+
+\medskip
+Dan Luecking would like to echo Tom's thanks to all of the above,
+especially Geoffrey Tobin and Jarom\'\i r Kuben. And to add the names
+Taco Hoekwater, for comments, advice and suggestions, Werner Lemberg,
+for the \cs{assignmfvalue} command, and Zaimi Sami~Alex for suggestions.
+
+But mostly, he'd like to thank Tom Leathrum for starting it all.
+
+
+\section{Changes History.}\label{changes}
+
+See the file \file{changes.txt} for a somewhat sporadic history of
+changes to \mfp{}. See the file \file{README} for changes added since
+the previous version, and for any known problems.
+
+
+%\clearpage
+\section{Summary of Options.}\label{summary}
+
+Unless otherwise stated, any of the command forms will be local to the
+current \env{mfpic} environment if used inside. Otherwise it will affect
+all later environments.
+
+\medskip
+% \shortstack doesn't allow [t] aligment:
+\def\stack#1{{\tabular[t]{@{}l@{}}#1\endtabular}}
+
+% Use halign so it will break over 2 pages
+{\openup\jot
+\halign to \textwidth
+ {#\hfil\quad\tabskip0ptplus 1fil&
+ #\hfil\quad&
+ \vtop{\parindent0pt\rightskip0pt plus 1fil\relax
+ \hsize.5\hsize\normalbaselines
+ \strut#\strut}\tabskip0pt \cr
+\textsc{Option}:& \textsc{Command form(s)}:& \textsc{Restrictions}:\cr
+\noalign{\smallskip\hrule\smallskip}
+\opt{metapost}&
+ \cs{usemetapost}&
+ Command must come before \cs{opengraphsfile}.
+ Incompatible with \opt{metafont} option.\cr
+\opt{metafont}&
+ \cs{usemetafont}&
+ The default. Command must come before
+ \cs{opengraphsfile}. Incompatible with \opt{metapost}
+ option. \cr
+\opt{mplabels}&
+ \stack{\cs{usemplabels},\\ \cs{nomplabels}}&
+ Requires \opt{metapost}. If command is used inside an
+ \env{mfpic} environment, it should come before
+ \cs{tlabel} commands to be affected. \cr
+\opt{overlaylabels}&
+ \stack{\cs{overlaylabels},\\ \cs{nooverlaylabels}}&
+ Has no effect without \opt{metapost}. \cr
+\opt{truebbox}&
+ \stack{\cs{usetruebbox},\\ \cs{notruebbox}}&
+ Has no effect without \opt{metapost}. \cr
+\opt{clip}&
+ \stack{\cs{clipmfpic},\\ \cs{noclipmfpic}}&
+ No restrictions. \cr
+\opt{clearsymbols}&
+ \stack{\cs{clearsymbols},\\ \cs{noclearsymbols}}&
+ No restrictions. \cr
+\stack{\opt{centeredcaptions}\\ \opt{raggedcaptions}}&
+ \stack{\cs{usecenteredcaptions},\\ \cs{nocenteredcaptions}\\
+ \cs{useraggedcaptions},\\ \cs{noraggedcaptions}}&
+ If command is used inside an \env{mfpic} environment, it
+ should come before the \cs{tcaption} command.\cr
+\opt{debug}&
+ \stack{\cs{mfpicdebugtrue},\\\cs{mfpicdebugfalse}}&
+ To turn on debugging while \file{mfpic.tex} is loading,
+ issue \cs{def}\cs{mfpicdebug}\marg{true}.\cr
+\stack{\opt{draft}\\ \opt{final}\\ \opt{nowrite}}&
+ \stack{\cs{mfpicdraft}\\ \cs{mfpicfinal}\\ \cs{mfpicnowrite}}&
+ Should not be used together. Command forms should come
+ before \cs{opengraphsfile} \cr
+\opt{mfpreadlog}&
+ \cs{mfpreadlog}&
+ Needed for \cs{assignmfvalue}. Must occur before
+ \cs{opengraphsfile}. \cr
+}}
+
+
+%\clearpage
+\section{Plotting Styles for \cs{plotdata}.}\label{styles}
+
+When \cs{plotdata} passes from one curve to the next, it increments a
+counter and uses that counter to select a dash pattern, color, or
+symbol. It uses predefined dash patterns named \mfc{dashtype0} through
+\mfc{dashtype5}, or predefined colors named \mfc{colortype0} through
+\mfc{colortype7}, or predefined symbols named \mfc{pointtype0} through
+\mfc{pointtype8}. Here follows a description of each of these variables.
+These variables must not be used in the second argument of
+\cs{reconfigureplot}, whose purpose is to redefine these variables.
+
+\medskip
+Under \cs{dashedlines}, we have the following dash patterns:
+
+\medskip
+\begin{tabular}{@{}lll}
+\textsc{Name}&\textsc{Pattern}&\textsc{Meaning}\cr
+\hline
+\vbox to 10pt{}%
+\mfc{dashtype0}& \dim{0bp} & solid line \\
+\mfc{dashtype1}& \dim{3bp,4bp} & dashes \\
+\mfc{dashtype2}& \dim{0bp,4bp} & dots \\
+\mfc{dashtype3}& \dim{0bp,4bp,3bp,4bp} & dot-dash \\
+\mfc{dashtype4}& \dim{0bp,4bp,3bp,4bp,0bp,4bp}& dot-dash-dot \\
+\mfc{dashtype5}& \dim{0bp,4bp,3bp,4bp,3bp,4bp}& dot-dash-dash
+\end{tabular}
+
+\medskip
+Under \cs{coloredlines}, we have the following colors. Except for
+\mfc{black} and \mfc{red}, each color is altered as indicated. This is
+an attempt to make the colors more equal in visibility against a white
+background. (The success of this attempt varies greatly with the output
+or display device.) Four of the eight colors use the cmyk model
+when the \MP{} version is at least $1.000$.
+
+\medskip
+\begin{tabular}{@{}llll}
+\textsc{Name}&\textsc{Color}&\textsc{(r,g,b)}&\textsc{(c,m,y,k)}\\
+\hline
+\vbox to 10pt{}%
+\mfc{colortype0}& black & $( 0, 0, 0)$&(0,0,0,1)\\
+\mfc{colortype1}& red & $( 1, 0, 0)$&\\
+\mfc{colortype2}& blue & $( .2, .2, 1)$&\\
+\mfc{colortype3}& orange & $(.66,.34, 0)$&\\
+\mfc{colortype4}& green & $( 0, .8, 0)$&\\
+\mfc{colortype5}& magenta& $(.85, 0,.85)$&(0,.85,0,.15)\\
+\mfc{colortype6}& cyan & $( 0,.85,.85)$&(.85,0,0,.15)\\
+\mfc{colortype7}& yellow & $(.85,.85, 0)$&(0,0,.85,.15)\\
+\end{tabular}
+
+\medskip
+
+Under \cs{pointedlines} and \cs{datapointsonly}, the following symbols
+are used. Internally each is referred to by the numeric name, but they
+are identical to the more descriptive name. Syntactically, all are \MF{}
+path variables. (The order changed between versions 0.6 and 0.7.)
+
+\medskip
+\begin{tabular}{@{}ll}
+\textsc{Name}&\textsc{Description}\\
+\hline
+\vbox to 10pt{}%
+\mfc{pointtype0}& \mfc{Circle} \\
+\mfc{pointtype1}& \mfc{Cross} \\
+\mfc{pointtype2}& \mfc{SolidDiamond} \\
+\mfc{pointtype3}& \mfc{Square} \\
+\mfc{pointtype4}& \mfc{Plus} \\
+\mfc{pointtype5}& \mfc{Triangle} \\
+\mfc{pointtype6}& \mfc{SolidCircle} \\
+\mfc{pointtype7}& \mfc{Star} \\
+\mfc{pointtype8}& \mfc{SolidTriangle}
+\end{tabular}
+
+
+\section{Special Considerations When Using \CMF{}.}\label{mfconsiderations}
+
+The most important restriction in \MF{} is on the size of a picture.
+Coordinates in \MF{} ultimately refer to pixel units in the font that is
+output. These are required to be less than 4096, so an absolute limit on
+the size of a picture is whatever length a row of 4095 pixels is. In
+fonts prepared for a LaserJet4 (600 DPI), this means 6.825 inches
+(17.3355cm). For a 1200 DPI pronter, the limit is 3.4125 inches.
+
+A similar limit holds for numbers input, and the values of variables:
+\MF{} will return an error for `\mfc{sin 4096}'. Intermediate values
+can be greater (\mfc{sin (2*2048)} will cause no error), but final,
+stored results are subject to the limit. An \mfp{} example that
+generated an error recently was:
+\begin{verbatim}
+\mfpicunit 1mm
+\mfpic[10]{-3}{7}{-3.5}{5}
+ \function{-4.5,4,.1}{x*x}
+\endmfpic
+\end{verbatim}
+The problem was the value of $4.5*4.5 = 20.25$: after multiplying by the
+\cs{mfpic} scaling factor, the \cs{mfpicunit} in inches, and the DPI
+value, this produces $20.25\times10\times0.03937\times600 > 4783$ pixel
+units. The error did not occur at the point of creating the font, but
+merely at the point of storing the path in an internal variable for
+manipulation and drawing. Thus, the fact that this particular picture
+was clipped to a much smaller size for printing did not help.
+
+In \MP{}, the limit on numeric values is only 8 times as high: $32768$.
+However, that is independent of printer resolution and is interpreted as
+\PS{} points (\TeX{}'s `big points'). At $72$ points to the inch, this
+allows figures to be about 12.64 yards (11.56$\,$m).
+
+
+\section{Special Considerations When Using \CMP{}.}\label{mpconsiderations}
+
+\subsection{Required support}
+
+To use \mfp{} with \MP{}, the following support is needed (besides a
+working \MP{} installation):
+
+\medskip\noindent
+\begin{tabular}{@{}lp{4.2in}}
+\TeX{} format &support needed\\
+\hline
+plain \TeX{} &The file \file{epsf.tex} or \file{epsf.sty}\\
+\LaTeX{}209 &(No longer supported, but plain \TeX{} methods
+ might work)\\
+\LaTeX{} &The package \prog{graphics} or \prog{graphicx}\\
+\pdfLaTeX{} &The package \prog{graphics} or
+ \prog{graphicx} with option \opt{pdftex}\\
+plain \pdfTeX{} &\raggedright The files \file{supp-pdf.mkii} or
+ \file{supp-pdf.tex} and (possibly)
+ \file{supp-mis.tex}\tabularnewline
+In all cases &\raggedright The files \file{grafbase.mp},
+ \file{dvipsnam.mp} and \file{mfpicdef.tex} plus,
+ of course, \file{mfpic.tex} (and \file{mfpic.sty}
+ for \LaTeX{})
+\end{tabular}
+
+\medskip
+The files \file{grafbase.mp} and \file{dvipsnam.mp} should be in a
+directory searched by \MP{}. If \MP{} cannot find the
+file \file{grafbase.mp}, then by default it will try to input
+\file{grafbase.mf}, which is generally fatal (and always futile).
+
+The remaining files should be in directories searched by the appropriate
+\TeX{} variant. The file \file{mfpicdef.tex} is input by \TeX{} when
+\MP{} is processing labels in \file{.mp} files created by \mfp{}. The
+user is free to add commands of his own to that file, but be warned that
+updates to \mfp{} will overwrite it. Better to create ones own file (say
+\file{mydefs.tex}) and arrange its input via
+\verb$\mfpverbtex{\input mydefs.tex}$
+
+In case \pdfLaTeX{} is used, the \prog{graphics} package is given the
+\opt{pdftex} option. This option requires the file \file{pdftex.def}
+which currently inputs one of the \file{supp-pdf} files. Early versions
+of \file{supp-pdf.tex} will input \file{supp-mis.tex}. These three files
+should be supplied with most \TeX{} installations.%
+ \footnote{They are part of the Con\TeX{}t distribuition. At this writing,
+ these files, plus a few others, can also be found at\\
+ \file{CTAN/graphics/metapost/contrib/tools/mptopdf/tex/context/base/}.} %
+Older versions had some bugs in connection with the \prog{babel}
+package. One workaround was to load the \prog{graphics} package and
+\mfp{} before \prog{babel}.
+
+If the user loads one of the above required files or packages before the
+\mfp{} macros are loaded then \mfp{} will not reload them. \Mfp{} will
+load whichever one it decides is required. In the \LaTeXe{} case, \mfp{}
+will load the \prog{graphics} package. If the user wishes
+\prog{graphicx}, then that package must be loaded before \mfp{}.
+
+
+\subsection{\CMP{} is not \MF{}}
+
+\PS{} is not a pixel oriented language and so neither is \MP{}. The model
+for drawing objects is completely different between \MF{} and \MP{}, and
+so one cannot always expect the same results. \CMP{} support in
+\mfp{} was carefully written so that files successfully printed
+with \mfp{} using \MF{} would be just as successfully printed
+using \MP{}. Nevertheless, it frequently chokes on files that make use of
+the \cs{mfsrc} command for writing code directly to the \file{.mf} file.
+While \file{grafbase.mp} is closely based on \file{grafbase.mf}, some of
+the code had to be completely rewritten.
+
+Pictures in \MP{} are stored as (possibly nested) sequences of objects,
+where objects are things like points, paths, contours, sub-pictures,
+etc. In \MF{}, pictures are stored as a grid of pixels. Pictures that are
+relatively simple in one program might be very complex in the other and
+even exceed memory allocated for their storage. Two examples are the
+\cs{polkadot} and \cs{hatch} commands. When the polkadot space and size
+are both too small, a \cs{polkadot}-ed region has been known to exceed
+\MP{} capacity, while being well within \MF{} capacity. In \MP{} the
+memory consumed by \cs{hatch} goes up in direct proportion to the linear
+dimensions of the figure being hatched, while in \MF{} it goes up in
+proportion to the area (except in horizontal hatching), and then the
+reverse can happen, with \MF{}'s capacity exeeded far sooner that \MP{}'s.
+
+In \MP{} it is important to note that each
+prefix modifies the result of the entire following sequence. In essence
+prefixes can be viewed as being applied in the opposite order to their
+occurrence. Example:
+\begin{verbatim}
+\dashed\gfill\rect{(0,0),(1,1)}
+\end{verbatim}
+This adds the dashed outline to the filled rectangle. That is, first the
+rectangle is defined, then it is filled, then the outline is drawn in
+dashed lines. This makes a difference when colors other than black are
+used. Drawing is done with the center of the virtual pen stroked along
+the boundary curve(s), so half of its width falls inside the
+rectangle. On the other hand, filling is done right up to the boundary.
+In this example, the dashed lines are drawn on top of part of the fill.
+In the reverse order, the fill would cover part of the dashed outline.
+
+
+\subsection{Graphic inclusion}\label{graphics}
+
+It may be impossible to completely cater to all possible methods of
+graphic inclusions with automatic tests. The macro that is invoked
+to include the \PS{} graphic is \cs{setmfpicgraphic} and the user
+may (carefully!) redefine this to suit special circumstances. Actually,
+\mfp{} runs the following sequence:
+
+\begin{ex}
+ \cs{preparemfpicgraphic}\marg{\meta{filename}}\\
+ \cs{setmfpicgraphic}\marg{\meta{filename}}\\
+ \cs{getmfpicoffset}\marg{\meta{filename}}%
+\index{preparemfpicgraphic@\cs{preparemfpicgraphic}}%
+\index{setmfpicgraphic@\cs{setmfpicgraphic}}%
+\index{getmfpicoffset@\cs{getmfpicoffset}}
+\end{ex}
+
+The following are the default definitions for \cs{setmfpicgraphic}:
+
+\medskip\noindent
+\begin{tabular}{@{}ll}
+plain \TeX{}&
+ \cs{def}\cs{setmfpicgraphic}\texttt{\#1}\marg{\cs{epsfbox}%
+ \marg{\#1}}\\
+\LaTeX{}209& (No longer supported, but likely the plain \TeX{}
+definition will be selected.)\\
+\LaTeX{}&
+ \cs{def}\cs{setmfpicgraphic}\texttt{\#1}\marg{\cs{includegraphics}%
+ \marg{\#1}}\\
+\pdfLaTeX{}&
+ \cs{def}\cs{setmfpicgraphic}\texttt{\#1}\marg{\cs{includegraphics}%
+ \marg{\#1}}\\
+\pdfTeX{}&
+ \cs{def}\cs{setmfpicgraphic}\texttt{\#1}\marg{\cs{convertMPtoPDF}%
+ \marg{\#1}\marg{1}\marg{1}}
+\end{tabular}
+
+\medskip
+Moreover, since \MP{} by default writes files with numeric extensions,
+we add code to each figure, so that these graphics are correctly
+recognized as \EPS{} or \prog{MPS}. For example, to the figure with
+extension \file{.1}, we add the equivalent of one of the following
+\begin{itemize}
+ \item[] \cs{DeclareGraphicsRule}\marg{.1}\marg{eps}\marg{.1}\marg{} in
+ \LaTeXe{}.
+ \item[] \cs{DeclareGraphicsRule}\marg{.1}\marg{mps}\marg{.1}\marg{} in
+ \pdfLaTeX{}.
+\end{itemize}
+
+After running the command \cs{setmfpicgraphic}, \mfp{} runs
+\cs{getmfpicoffset} to store the lower left corner of the bounding box
+of the figure in two macros \cs{mfpicllx} and \cs{mfpiclly}. All the
+above versions of \cs{setmfpicgraphic} (except \cs{includegraphics})
+make this information available; the definition of \cs{getmfpicoffset}
+merely copies it into these two macros. What \mfp{} does in the
+case of \cs{includegraphics} is to modify (locally) the definition of an
+internal command of the \prog{graphics} package so that it copies the
+information to those macros, and then \cs{getmfpicoffset} does nothing.
+This internal modification is accomplished by the macro
+\cs{preparemfpicgraphic}. Changes to \cs{setmfpicgraphic} might require
+changing either or both of \cs{preparemfpicgraphic} and
+\cs{getmfpicoffset}. All three of these commands are fed the graphic's
+file name as the only argument, although only \cs{setmfpicgraphic}
+currently does anything with it.
+
+One possible reason for wanting to redefine \cs{setmfpicgraphic} might
+be to rescale all pictures. This is \emph{definitely not} a good idea. A
+good deal of \mfp{}'s figure placemant code assumes that the size of the
+figure is consistent with the coordinate system set up by the \cs{mfpic}
+command. With \opt{mplabels} plus \opt{truebbox} it might work, but
+(i)~it has \emph{not} been considered in writing the \mfp{} code,
+(ii)~it will then scale all the text as well as the figure, and (iii)~it
+will scale all line thickness, which should normally be a design choice
+independent of the size of a picture. To rescale all pictures, one need
+only change \cs{mfpicunit} and rerun \TeX{} and \MP{}.
+
+A better reason might be to allow the conversion of your \MP{} figures
+to some other format. Then redefining \cs{setmfpicgraphic} could enable
+including the appropriate file in the appropriate format.
+
+The filename argument mentioned above is actually the result obtained by
+running the macro \cs{setfilename}\index{setfilename@\cs{setfilename}}.
+The command \cs{setfilename} gets two arguments: the name of the \MP{}
+output file (set in the \cs{opengraphsfile} command) without extension,
+and the number of the picture. The default definition of
+\cs{setfilename} merely inserts a dot between the two arguments.%
+ \footnote{Unless modified by \cs{setfilenametemplate}, of course.
+ See subsection~\ref{misc}.}
+That is \cs{setfilename}\marg{fig}\marg{1} produces \file{fig.1}. You
+can redefine this behavior also. Any changes to \cs{setfilename} must
+come after the \mfp{} macros are input and before the
+\cs{opengraphsfile} command. Any changes to \cs{setmfpicgraphic} must
+come after the \mfp{} macros are input and before any \cs{mfpic}
+commands, but it is best to place it before the \cs{opengraphsfile}
+command.
+
+As \mfp{} is currently written, \cs{setfilename} must be
+\emph{completely expandable}, which means it should contain no
+definitions, no assignments such as \cs{setcounter}, and no
+calculations.%
+ \footnote{But appropriate use of \cs{numexpr} (in \eTeX) for
+ calculations is probably OK.}
+To test whether a proposed definition is completely
+expandable, put
+\begin{verbatim}
+\message{***\setfilename{file}{1}***}
+\end{verbatim}
+after the definition in a \file{.tex} file and view the result on the
+terminal or in the \file{.log} file. You should see only your expected
+filename between the asterisks.
+
+
+\section{\prog{Mfpic} and the Rest of the World.}
+
+\subsection{The literature}
+
+This author has personal knowledge of one mathematical article
+which definitely uses \mfp{} to create diagrams, and that is this
+author's joint paper with J.~Duncan and C.~M.~McGregor: \textit{On the
+value of pi for norms in $\mathbf{R}^2$} in the College Mathematics
+Journal, vol.~35, pages 84--92. Oddly enough, it was McGregor and not I
+who chose to use \mfp{} for the illustrations.
+
+There also exists a book that makes use of \mfp{}: \textit{Introduction
+to functional equations: theory and problem solving strategies for
+mathematical competitions and beyond} by Costas Efthimiou,
+MSRI/Mathematical Circles Library, vol. 6, 2011.
+
+There are at least two major publications where \mfp{} has garnered more
+than a cursory mention. The most up-to-date is a section in \textit{The
+\LaTeX{} Graphics Companion} by Michel Goossens, Sebastian Rahtz and
+Frank Mittelbach. It describes a version prior to the introduction of
+\MP{} support, but it correctly describes a subset of its current
+commands and abilities. \textit{The \LaTeX{} Companion} (Second Edition)
+mentions \mfp{}, but only in its annotation of the bibliography entry
+for \textit{\TeX{} Unbound} (see below).
+
+The other is \textit{\TeX{} Unbound} by Alan Hoenig, which contains a
+chapter on \mfp{}. Unfortunately, it describes a version that was
+replaced in 1996 with version 0.2.10.9. The following summarizes the
+differences between the description%
+ \footnote{While I'm at it: \textit{\TeX{} Unbound} occasionally
+ refers to \mfp{} using a logo-like formatting in which the `MF' is
+ in a special font and the `I' is lowered. This `logo' may suggest
+ a relationship between \mfp{} and \PiCTeX{}. There is no such
+ relationship, and there is no official logo-like designation for
+ \mfp{}.} %
+found in Chapter 15 and \mfp{} versions 0.2.10.9 through the
+current one:
+
+\cs{wedge} is now renamed \cs{sector} to avoid conflict with the \TeX{}
+command of the same name. The syntax is slightly different from that
+given for \cs{wedge}:
+\begin{ex}
+ \cs{sector}\marg{(\meta{x},\meta{y}), \meta{radius}, \meta{angle1},
+ \meta{angle2}}
+\end{ex}
+
+The macro \cs{plr}\marg{(\meta{$r_0$},\meta{$\theta_0$}),%
+(\meta{$r_1$},\meta{$\theta_1$}),$\ldots$} is now used to convert polar
+coordinate pairs to rectangular coordinates and the commands
+\cs{plrcurve}, \cs{plrcyclic}, \cs{plrlines} and \cs{plrpoint} were
+dropped from \mfp{}. Now use
+\begin{ex}
+ \cs{curve}\marg{\cs{plr}\marg{(\meta{$r_0$},\meta{$\theta_0$}),%
+ (\meta{$r_1$},\meta{$\theta_1$}),$\ldots$}}
+\end{ex}
+instead of
+\begin{ex}
+ \cs{plrcurve}\marg{(\meta{$r_0$},\meta{$\theta_0$}),%
+ (\meta{$r_1$},\meta{$\theta_1$}),$\ldots$}
+\end{ex}
+and similarly for \cs{plrcyclic}, \cs{plrlines} and \cs{plrpoint}.
+
+\cs{fill} is now renamed \cs{gfill} to avoid conflict with the \LaTeX{}
+command of the same name.
+
+\cs{rotate}, which rotates a following figure about a point, is now
+renamed \cs{rotatepath} to avoid confusion with a similar name for a
+transformation (see below).
+
+\cs{white} is now renamed \cs{gclear} because \cs{white} is too likely
+to be chosen for, or confused with, a color command.
+
+\smallskip
+The following affine transform commands were changed from a third person
+indicative form (which could be confused with a plural noun) to an
+imperative form:
+
+\begin{ex}
+\begin{tabular}{@{}ll}
+ Old name: & New name:\\
+ \cs{boosts} & \cs{boost}\\
+ \cs{reflectsabout} & \cs{reflectabout}\\
+ \cs{rotatesaround} & \cs{rotatearound}\\
+ \cs{rotates} & \cs{rotate}\\
+ \cs{scales} & \cs{scale}\\
+ \cs{shifts} & \cs{shift}\\
+ \cs{xscales} & \cs{xscale}\\
+ \cs{xslants} & \cs{xslant}\\
+ \cs{xyswaps} & \cs{xyswap}\\
+ \cs{yscales} & \cs{yscale}\\
+ \cs{yslants} & \cs{yslant}\\
+ \cs{zscales} & \cs{zscale}\\
+ \cs{zslants} & \cs{zslant}
+\end{tabular}
+\end{ex}
+
+\cs{caption} and \cs{label} are now renamed \cs{tcaption} and
+\cs{tlabel} to avoid conflict with the \LaTeX{} commands.
+
+\cs{mfcmd} was renamed \cs{mfsrc} for clarity, and (in version 0.7) a
+new \cs{mfcmd} was defined, which is pretty much the same except it appends
+a semicolon to its argument.
+
+\smallskip
+There is a misprint: \cs{axisheadlin} should be \cs{axisheadlen}.
+
+Finally, the \LaTeX{} template on page 496 is no longer the only
+possiblity: recent \mfp{} may be loaded with \cs{usepackage}.
+
+
+\subsection{Other programs}
+
+There exists a program, \prog{fig2mfpic} that produces \mfp{} code as
+output. The code produced (as of this writing) is somewhat old and
+mostly incompatible with the description in this manual. Fortunately, it
+is accompanied by the appropriate versions of files \file{mfpic.tex} and
+\file{grafbase.mf}. Unfortunately, the names conflict with the current
+filenames and so they should only be used in circumstances where no
+substitution will occur, say in a local directory together with the
+other sources for the document being produced. Moreover, the
+documentation in this manual may not apply to the code produced. However
+the information in \textit{\TeX{} Unbound} may apply.
+
+There exist a package, \prog{circuit\_macros}, that can produce a
+variety of output formats, one of which is \mfp{} code. One writes a
+file (don't ask me what it consists of) and apparently processes it with
+\prog{m4} and then (perhaps) \prog{dpic} to produce the output. The
+\mfp{} code produced appears to be compatible with the current \mfp{}.
+
+\renewcommand\mfpindexheading{%
+ \section{Index of commands, options and parameters.}}
+
+\let\oldcs\cs
+\renewcommand{\cs}[1]{\leavevmode\mytt{\llap{\char`\\}#1}}
+
+\renewcommand\headingprefix[1]{\textbf{\large #1}}
+\InputIfFileExists{\jobname.ind}{}{\mfpindexheading}
+
+\let\cs\oldcs
+
+\columnseprule 0pt
+\columnsep 35pt
+\twocolumn[\section{List of commands by type.}]
+\parindent0pt
+\parskip0pt plus .3pt\relax
+\makeatletter
+\renewcommand\@idxitem{\par\hangindent 10\p@}
+\let\item\@idxitem
+\makeatother
+
+
+\subsection{Figures}
+
+ \item \cs{arc}, \pageref{arc}
+ \item \cs{axis}, \pageref{axis}
+ \item \cs{axisline}, \pageref{axisline}
+ \item \cs{belowfcn}, \pageref{belowfcn}
+ \item \cs{border}, \pageref{axisline}
+ \item \cs{brownianmotion}, \pageref{brownianmotion}
+ \item \cs{browniangraph}, \pageref{brownianmotion}
+ \item \cs{btwnfcn}, \pageref{btwnfcn}
+ \item \cs{btwnplrfcn}, \pageref{btwnfcn}
+ \item \cs{cbeziers}, \cs{closedcbeziers}, \pageref{cbeziers}
+ \item \cs{chartbar}, \pageref{chartbar}
+ \item \cs{circle}, \pageref{circle}
+ \item \cs{computedspline},\\
+ \cs{closedcomputedspline}, \pageref{computedspline}
+ \item \cs{convexcurve}, \cs{closedconvexcurve}, \pageref{convexcurve}
+ \item \cs{convexcyclic}, \pageref{convexcurve}
+ \item \cs{cspline}, \cs{closedcspline}, \pageref{qspline}
+ \item \cs{curve}, \cs{closedcurve}, \pageref{curve}
+ \item \cs{cyclic}, \pageref{curve}
+ \item \cs{datafile}, \pageref{datafile}
+ \item \cs{DEgraph}, \pageref{DEgraph}
+ \item \cs{DEtrajectory}, \pageref{DEgraph}
+ \item \cs{ellipse}, \pageref{ellipse}
+ \item \cs{fcncurve}, \pageref{fcncurve}
+ \item \cs{fcnspline}, \pageref{fcnspline}
+ \item \cs{fullellipse}, \pageref{fullellipse}
+ \item \cs{function}, \pageref{function}
+ \item \cs{ganttbar}, \pageref{chartbar}
+ \item \cs{gbrace}, \pageref{gbrace}
+ \item \cs{graphbar}, \pageref{chartbar}
+ \item \cs{halfellipse}, \pageref{fullellipse}
+ \item \cs{histobar}, \pageref{chartbar}
+ \item \cs{hypergeodesic}, \pageref{hypergeodesic}
+ \item \cs{levelcurve}, \pageref{levelcurve}
+ \item \cs{lines}, \pageref{polyline}
+ \item \cs{mfbezier}, \cs{closedmfbezier}, \pageref{mfbezier}
+ \item \cs{mfobj}, \cs{mpobj}, \pageref{mfobj}
+ \item \cs{parafcn}, \pageref{parafcn}
+ \item \cs{periodicfcnspline}, \pageref{fcnspline}
+ \item \cs{piewedge}, \pageref{piewedge}
+ \item \cs{plrfcn}, \pageref{plrfcn}
+ \item \cs{plrregion}, \pageref{belowfcn}
+ \item \cs{polygon}, \pageref{polygon}
+ \item \cs{polyline}, \pageref{polyline}
+ \item \cs{pshcircle}, \pageref{pshcircle}
+ \item \cs{qbeziers}, \cs{closedqbeziers}, \pageref{qbeziers}
+ \item \cs{quarterellipse}, \pageref{fullellipse}
+ \item \cs{qspline}, \cs{closedqspline}, \pageref{qspline}
+ \item \cs{randomwalk}, \pageref{brownianmotion}
+ \item \cs{rect}, \pageref{rect}
+ \item \cs{regpolygon}, \pageref{regpolygon}
+ \item \cs{sector}, \pageref{sector}
+ \item \cs{tlabelcircle}, \pageref{tlabelellipse}
+ \item \cs{tlabelellipse}, \pageref{tlabelellipse}
+ \item \cs{tlabeloval}, \pageref{tlabeloval}
+ \item \cs{tlabelrect}, \pageref{tlabelrect}
+ \item \cs{turtle}, \pageref{turtle}
+
+
+\subsection{Renderings}
+
+ \item \cs{areagradient}, \pageref{areagradient}
+ \item \cs{corkscrew}, \pageref{corkscrew}
+ \item \cs{dashed}, \pageref{dashed}
+ \item \cs{dotted}, \pageref{dotted}
+ \item \cs{doubledraw}, \pageref{doubledraw}
+ \item \cs{draw}, \pageref{draw}
+ \item \cs{gclear}, \pageref{gclear}
+ \item \cs{gclip}, \pageref{gclip}
+ \item \cs{gendashed}, \pageref{gendashed}
+ \item \cs{gfill}, \pageref{gfill}
+ \item \cs{gradient}, \pageref{gradient}
+ \item \cs{hatch}, \pageref{hatch}
+ \item \cs{lhatch}, \pageref{hatch}
+ \item \cs{plot}, \pageref{plot}
+ \item \cs{plotdata}, \pageref{plotdata}
+ \item \cs{plotnodes}, \pageref{plotnodes}
+ \item \cs{polkadot}, \pageref{polkadot}
+ \item \cs{radialgradient}, \pageref{radialgradient}
+ \item \cs{rhatch}, \pageref{hatch}
+ \item \cs{sinewave}, \pageref{zigzag}
+ \item \cs{shade}, \pageref{shade}
+ \item \cs{tess}, \pageref{tess}
+ \item \cs{thatch}, \pageref{thatch}
+ \item \cs{xhatch}, \pageref{hatch}
+ \item \cs{zigzag}, \pageref{zigzag}
+
+
+\subsection{Arrows}
+
+ \item \cs{arrow}, \pageref{arrow}
+ \item \cs{arrowhead}, \pageref{arrowhead}
+ \item \cs{arrowmid}, \pageref{arrowhead}
+ \item \cs{arrowtail}, \pageref{arrowhead}
+
+
+\subsection{Modifying figures}
+
+ \item \cs{bclosed}, \pageref{lclosed}
+ \item \cs{cbclosed}, \pageref{cbclosed}
+ \item \cs{connect}, \cs{endconnect}, \pageref{connect}
+ \item \cs{cutoffafter}, \pageref{cutoffafter}
+ \item \cs{cutoffbefore}, \pageref{cutoffafter}
+ \item \cs{interpolatepath}, \pageref{interpolatepath}
+ \item \cs{lclosed}, \pageref{lclosed}
+ \item \cs{makesector}, \pageref{makesector}
+ \item \cs{parallelpath}, \pageref{parallelpath}
+ \item \cs{partpath}, \pageref{partpath}
+ \item \cs{qbclosed}, \pageref{cbclosed}
+ \item \cs{randomizepath}, \pageref{random}
+ \item \cs{randomlines}, \pageref{random}
+ \item \cs{reflectpath}, \pageref{shiftpath}
+ \item \cs{reverse}, \pageref{reverse}
+ \item \cs{reversepath}, \pageref{reverse}
+ \item \cs{rotatepath}, \pageref{shiftpath}
+ \item \cs{scalepath}, \pageref{shiftpath}
+ \item \cs{sclosed}, \pageref{lclosed}
+ \item \cs{shiftpath}, \pageref{shiftpath}
+ \item \cs{slantpath}, \pageref{shiftpath}
+ \item \cs{subpath}, \pageref{partpath}
+ \item \cs{transformpath}, \pageref{shiftpath}
+ \item \cs{trimpath}, \pageref{partpath}
+ \item \cs{xscalepath}, \pageref{shiftpath}
+ \item \cs{xslantpath}, \pageref{shiftpath}
+ \item \cs{xyswappath}, \pageref{shiftpath}
+ \item \cs{yscalepath}, \pageref{shiftpath}
+ \item \cs{yslantpath}, \pageref{shiftpath}
+
+
+\subsection{Lengths}
+
+ \item \cs{axisheadlen}, \pageref{axisheadlen}
+ \item \cs{dashlen}, \pageref{dashlen}
+ \item \cs{dotsize}, \pageref{dotsize}
+ \item \cs{dotspace}, \pageref{dotsize}
+ \item \cs{griddotsize}, \pageref{griddotsize}
+ \item \cs{hashlen}, \pageref{hashlen}
+ \item \cs{hatchspace}, \pageref{hatchspace}
+ \item \cs{headlen}, \pageref{headlen}
+ \item \cs{mfpiccaptionskip}, \pageref{mfpiccaptionskip}
+ \item \cs{mfpicheight}, \pageref{mfpicheight}
+ \item \cs{mfpicunit}, \pageref{mfpicunit}
+ \item \cs{mfpicwidth}, \pageref{mfpicheight}
+ \item \cs{pointsize}, \pageref{pointsize}
+ \item \cs{polkadotspace}, \pageref{polkadotspace}
+ \item \cs{shadespace}, \pageref{shadespace}
+ \item \cs{sideheadlen}, \pageref{sideheadlen}
+ \item \cs{symbolspace}, \pageref{symbolspace}
+
+
+\subsection{Coordinate transformation}
+
+ \item \cs{applyT}, \pageref{applyT}
+ \item \cs{boost}, \pageref{applyT}
+ \item \cs{coords}, \cs{endcoords}, \pageref{coords}
+ \item \cs{mirror}, \pageref{applyT}
+ \item \cs{reflectabout}, \pageref{applyT}
+ \item \cs{rotate}, \pageref{applyT}
+ \item \cs{rotatearound}, \pageref{applyT}
+ \item \cs{scale}, \pageref{applyT}
+ \item \cs{shift}, \pageref{applyT}
+ \item \cs{turn}, \pageref{applyT}
+ \item \cs{xscale}, \pageref{applyT}
+ \item \cs{xslant}, \pageref{applyT}
+ \item \cs{xyswap}, \pageref{applyT}
+ \item \cs{yscale}, \pageref{applyT}
+ \item \cs{yslant}, \pageref{applyT}
+ \item \cs{zscale}, \pageref{applyT}
+ \item \cs{zslant}, \pageref{applyT}
+
+
+\subsection{Symbols, axes, grids, marks}
+
+ \item \cs{axes}, \pageref{axes}
+ \item \cs{axis}, \pageref{axis}
+ \item \cs{axismarks}, \pageref{axismarks}
+ \item \cs{bmarks}, \pageref{axismarks}
+ \item \cs{doaxes}, \pageref{axis}
+ \item \cs{grid}, \pageref{grid}
+ \item \cs{gridarcs}, \pageref{plrgrid}
+ \item \cs{gridlines}, \pageref{grid}
+ \item \cs{gridpoints}, \pageref{grid}
+ \item \cs{gridrays}, \pageref{plrgrid}
+ \item \cs{hgridlines}, \pageref{grid}
+ \item \cs{lattice}, \pageref{grid}
+ \item \cs{lmarks}, \pageref{axismarks}
+ \item \cs{plotsymbol}, \pageref{plotsymbol}
+ \item \cs{plrgridpoints}, \pageref{plrgrid}
+ \item \cs{plrgrid}, \pageref{plrgrid}
+ \item \cs{plrpatch}, \pageref{plrgrid}
+ \item \cs{plrvectorfield}, \pageref{vectorfield}
+ \item \cs{point}, \pageref{point}
+ \item \cs{putmfpimage}, \pageref{putmfpimage}
+ \item \cs{rmarks}, \pageref{axismarks}
+ \item \cs{tmarks}, \pageref{axismarks}
+ \item \cs{vectorfield}, \pageref{vectorfield}
+ \item \cs{vgridlines}, \pageref{grid}
+ \item \cs{xaxis}, \pageref{axes}
+ \item \cs{xmarks}, \pageref{axismarks}
+ \item \cs{yaxis}, \pageref{axes}
+ \item \cs{ymarks}, \pageref{axismarks}
+
+
+\subsection{Symbol names}
+
+ \item \gbc{Arrowhead}, \pageref{arrowhead}
+ \item \gbc{Asterisk}, \pageref{plotsymbol}
+ \item \gbc{Circle}, \pageref{plotsymbol}
+ \item \gbc{Crossbar}, \pageref{arrowhead}
+ \item \gbc{Cross}, \pageref{plotsymbol}
+ \item \gbc{Diamond}, \pageref{plotsymbol}
+ \item \gbc{Leftbar}, \pageref{arrowhead}
+ \item \gbc{Leftharpoon}, \pageref{arrowhead}
+ \item \gbc{Lefthook}, \pageref{arrowhead}
+ \item \gbc{Plus}, \pageref{plotsymbol}
+ \item \gbc{Rightbar}, \pageref{arrowhead}
+ \item \gbc{Rightharpoon}, \pageref{arrowhead}
+ \item \gbc{Righthook}, \pageref{arrowhead}
+ \item \gbc{SolidCircle}, \pageref{plotsymbol}
+ \item \gbc{SolidDiamond}, \pageref{plotsymbol}
+ \item \gbc{SolidSquare}, \pageref{plotsymbol}
+ \item \gbc{SolidStar}, \pageref{plotsymbol}
+ \item \gbc{SolidTriangle}, \pageref{plotsymbol}
+ \item \gbc{Square}, \pageref{plotsymbol}
+ \item \gbc{Star}, \pageref{plotsymbol}
+ \item \gbc{Triangle}, \pageref{plotsymbol}
+
+
+\subsection{Setting options}
+
+ \item \cs{clearsymbols}, \pageref{clearsymbols}
+ \item \cs{clipmfpic}, \pageref{clip}
+ \item \cs{mfpicdebugfalse}, \pageref{debug}
+ \item \cs{mfpicdebugtrue}, \pageref{debug}
+ \item \cs{mfpicdraft}, \pageref{draft}
+ \item \cs{mfpicfinal}, \pageref{draft}
+ \item \cs{mfpicnowrite}, \pageref{draft}
+ \item \cs{mfpreadlog}, \pageref{readlog}
+ \item \cs{nocenteredcaptions}, \pageref{centeredcaptions}
+ \item \cs{noclearsymbols}, \pageref{clearsymbols}
+ \item \cs{noclipmfpic}, \pageref{clip}
+ \item \cs{nomplabels}, \pageref{mplabels}
+ \item \cs{nooverlaylabels}, \pageref{overlaylabels}
+ \item \cs{noraggedcaptions}, \pageref{raggedcaptions}
+ \item \cs{notruebbox}, \pageref{truebbox}
+ \item \cs{overlaylabels}, \pageref{overlaylabels}
+ \item \cs{usecenteredcaptions}, \pageref{centeredcaptions}
+ \item \cs{usemetafont}, \pageref{metapost}
+ \item \cs{usemetapost}, \pageref{metapost}
+ \item \cs{usemplabels}, \pageref{mplabels}
+ \item \cs{useraggedcaptions}, \pageref{raggedcaptions}
+ \item \cs{usetruebbox}, \pageref{truebbox}
+
+
+\subsection{Setting values}
+
+ \item \cs{axismargin}, \pageref{axismargin}
+ \item \cs{darkershade}, \pageref{darkershade}
+ \item \cs{dashlineset}, \pageref{dashlineset}
+ \item \cs{dashpattern}, \pageref{dashpattern}
+ \item \cs{dotlineset}, \pageref{dashlineset}
+ \item \cs{drawpen}, \pageref{drawpen}
+ \item \cs{globalsetmfvariable}, \pageref{setmfvariable}
+ \item \cs{hatchwd}, \pageref{hatchwd}
+ \item \cs{headshape}, \pageref{headshape}
+ \item \cs{lightershade}, \pageref{darkershade}
+ \item \cs{mfpicnumber}, \pageref{mfpicnumber}
+ \item \cs{mfplinestyle}, \pageref{mfplinetype}
+ \item \cs{mfplinetype}, \pageref{mfplinetype}
+ \item \cs{pen}, \pageref{drawpen}
+ \item \cs{penwd}, \pageref{drawpen}
+ \item \cs{polkadotwd}, \pageref{polkadotwd}
+ \item \cs{setallaxismargins}, \pageref{axismargin}
+ \item \cs{setallbordermarks}, \pageref{setaxismarks}
+ \item \cs{setaxismargins}, \pageref{axismargin}
+ \item \cs{setaxismarks}, \pageref{setaxismarks}
+ \item \cs{setbordermarks}, \pageref{setaxismarks}
+ \item \cs{setmfboolean}, \pageref{setmfvariable}
+ \item \cs{setmfcolor}, \pageref{setmfvariable}
+ \item \cs{setmfnumeric}, \pageref{setmfvariable}
+ \item \cs{setmfpair}, \pageref{setmfvariable}
+ \item \cs{setmfvariable}, \pageref{setmfvariable}
+ \item \cs{settension}, \pageref{settension}
+ \item \cs{setxmarks}, \pageref{setaxismarks}
+ \item \cs{setymarks}, \pageref{setaxismarks}
+ \item \cs{shadewd}, \pageref{shadewd}
+
+
+\subsection{Setting colors}
+
+ \item \cs{backgroundcolor}, \pageref{drawcolor}
+ \item \cs{drawcolor}, \pageref{drawcolor}
+ \item \cs{fillcolor}, \pageref{drawcolor}
+ \item \cs{hatchcolor}, \pageref{drawcolor}
+ \item \cs{headcolor}, \pageref{drawcolor}
+ \item \cs{mfpdefinecolor}, \pageref{mfpdefinecolor}
+ \item \cs{pointcolor}, \pageref{drawcolor}
+ \item \cs{tlabelcolor}, \pageref{drawcolor}
+
+
+\subsection{Defining arrays}
+
+ \item \cs{barchart}, \pageref{barchart}
+ \item \cs{bargraph}, \pageref{barchart}
+ \item \cs{colorarray}, \pageref{setarray}
+ \item \cs{gantt}, \pageref{barchart}
+ \item \cs{globalsetarray}, \pageref{setarray}
+ \item \cs{histogram}, \pageref{barchart}
+ \item \cs{mfpbarchart}, \pageref{barchart}
+ \item \cs{mfpbargraph}, \pageref{barchart}
+ \item \cs{mfpgantt}, \pageref{barchart}
+ \item \cs{mfphistogram}, \pageref{barchart}
+ \item \cs{mfppiechart}, \pageref{piechart}
+ \item \cs{numericarray}, \pageref{setarray}
+ \item \cs{pairarray}, \pageref{setarray}
+ \item \cs{patharr}, \cs{endpatharr}, \pageref{patharr}
+ \item \cs{piechart}, \pageref{piechart}
+ \item \cs{setarray}, \pageref{setarray}
+
+
+\subsection{Changing behavior}
+
+ \item \cs{coloredlines}, \pageref{coloredlines}
+ \item \cs{dashedlines}, \pageref{coloredlines}
+ \item \cs{datapointsonly}, \pageref{coloredlines}
+ \item \cs{defaultplot}, \pageref{defaultplot}
+ \item \cs{everytlabel}, \pageref{everytlabel}
+ \item \cs{everymfpic}, \cs{everyendmfpic}, \pageref{everymfpic}
+ \item \cs{makepercentcomment}, \pageref{makepercentother}
+ \item \cs{makepercentother}, \pageref{makepercentother}
+ \item \cs{mfpdatacomment}, \pageref{mfpdatacomment}
+ \item \cs{mfpdataperline}, \pageref{mfpdataperline}
+ \item \cs{mfpverbtex}, \pageref{mfpverbtex}
+ \item \cs{noship}, \pageref{noship}
+ \item \cs{pointedlines}, \pageref{coloredlines}
+ \item \cs{pointfillfalse}, \cs{pointfilltrue}, \pageref{pointfilltrue}
+ \item \cs{reconfigureplot}, \pageref{reconfigureplot}
+ \item \cs{resumeshipping}, \pageref{noship}
+ \item \cs{setrender}, \pageref{setrender}
+ \item \cs{smoothdata}, \pageref{datafile}
+ \item \cs{stopshipping}, \pageref{noship}
+ \item \cs{tlabeljustify}, \pageref{tlabeljustify}
+ \item \cs{tlabeloffset}, \pageref{tlabeloffset}
+ \item \cs{tlabelsep}, \pageref{tlabeloffset}
+ \item \cs{tlpathjustify}, \pageref{tlpathjustify}
+ \item \cs{tlpathsep}, \pageref{tlabeloffset}
+ \item \cs{tlpointsep}, \pageref{tlabeloffset}
+ \item \cs{unsmoothdata}, \pageref{datafile}
+ \item \cs{using}, \pageref{using}
+ \item \cs{usingnumericdefault}, \pageref{usingpairdefault}
+ \item \cs{usingpairdefault}, \pageref{usingpairdefault}
+
+
+\subsection{Files and environments}
+
+ \item \cs{closegraphsfile}, \pageref{opengraphsfile}
+ \item \cs{mfpframe}, \cs{endmfpframe}, \pageref{mfpframe}
+ \item \cs{mfpic}, \cs{endmfpic}, \pageref{mfpic}
+ \item \cs{opengraphsfile}, \pageref{opengraphsfile}
+ \item \cs{setfilename}, \pageref{setfilename}
+ \item \cs{setfilenametemplate}, \pageref{setfilenametemplate}
+
+
+\subsection{Text}
+
+ \item \cs{axislabels}, \pageref{axislabels}
+ \item \cs{plottext}, \pageref{plottext}
+ \item \cs{startbacktext}, \pageref{backtext}
+ \item \cs{stopbacktext}, \pageref{backtext}
+ \item \cs{tcaption}, \pageref{tcaption}
+ \item \cs{tlabel}, \pageref{tlabel}
+ \item \cs{tlabels}, \pageref{tlabel}
+
+
+\subsection{Miscellaneous}
+
+ \item \cs{assignmfvalue}, \cs{assignmpvalue}, \pageref{assignmfvalue}
+ \item \cs{fdef}, \pageref{fdef}
+ \item \cs{getmfpicoffset}, \pageref{getmfpicoffset}
+ \item \cs{globalassignmfvalue},\\
+ \cs{globalassignmpvalue}, \pageref{assignmfvalue}
+ \item \cs{ifmfpmpost}, \pageref{ifmfpmpost}
+ \item \cs{mfcmd}, \pageref{mfsrc}
+ \item \cs{mflist}, \pageref{mfsrc}
+ \item \cs{mfmode}, \pageref{mfmode}
+ \item \cs{mfpfor}, \cs{endmfpfor}, \pageref{mfpfor}
+ \item \cs{mfpframed}, \pageref{mfpframe}
+ \item \cs{mfpicversion}, \pageref{mfpicversion}
+ \item \cs{mfpimage}, \cs{endmfpimage}, \pageref{mfpimage}
+ \item \cs{mfploop}, \cs{endmfploop}, \pageref{mfploop}
+ \item \cs{mfpuntil}, \pageref{mfploop}
+ \item \cs{mfpwhile}, \cs{endmfpwhile}, \pageref{mfpwhile}
+ \item \cs{mfresolution}, \pageref{mfmode}
+ \item \cs{mfsrc}, \pageref{mfsrc}
+ \item \cs{mftitle}, \pageref{mftitle}
+ \item \cs{newfdim}, \pageref{newfdim}
+ \item \cs{newsavepic}, \pageref{newsavepic}
+ \item \cs{plr}, \pageref{plr}
+ \item \cs{pointdef}, \pageref{pointdef}
+ \item \cs{preparemfpicgraphic}, \pageref{preparemfpicgraphic}
+ \item \cs{savepic}, \pageref{newsavepic}
+ \item \cs{sequence}, \pageref{sequence}
+ \item \cs{setmfpicgraphic}, \pageref{setmfpicgraphic}
+ \item \cs{store}, \pageref{store}
+ \item \cs{tile}, \cs{endtile}, \pageref{tile}
+ \item \cs{tmtitle}, \pageref{tmtitle}
+ \item \cs{usepic}, \pageref{newsavepic}
+
+
+\end{document}
+
diff --git a/graphics/mfpic/install.txt b/graphics/mfpic/install.txt
new file mode 100644
index 0000000000..8c8df9a5c4
--- /dev/null
+++ b/graphics/mfpic/install.txt
@@ -0,0 +1,106 @@
+% File: install.txt
+% A part of mfpic 1.10 2012/12/03
+%
+
+This is version 1.10 of mfpic. See README for a list of files and a
+brief description of each.
+
+Generating and installing the files
+-----------------------------------
+
+This sections is unnecessary if you get
+ http://mirror.ctan.org/install/graphics/mfpic.tds.zip
+when it becomes available. Just unzip it in a texmf directory.
+Alternatively, you can get the entire graphics/mfpic/ directory from
+http://mirror.ctan.org/ and move those files as described below
+
+-- If you have acquired only mfpic.ins, mfpic.dtx and grafbase.dtx, put
+ the three in the same temporary directory and change to that
+ directory. Run latex (or tex) on mfpic.ins, which should produce
+ these six files:
+ mfpic.tex grafbase.mf
+ mfpic.sty grafbase.mp
+ mfpicdef.tex dvipsnam.mp
+
+-- If you have an older version of mfpic, remove any old files with the
+ same names as the above from your TeX directories, or ensure that the
+ following procedure overwrites them (back them up first, if you wish).
+
+-- Copy mfpic.tex and mfpicdef.tex where TeX and LaTeX will find them,
+ and mfpic.sty where LaTeX will find it. On any TDS compliant system
+ (such as TeXLive, MacTeX and MiKTeX) they can all be put in
+ $TEXMF/tex/generic/mfpic/ (where $TEXMF indicates a directory serving
+ as a root of a texmf tree).
+
+-- Copy grafbase.mp and dvipsnam.mp where MetaPost will find them, for
+ example $TEXMF/metapost/mfpic/ .
+
+-- Copy grafbase.mf where Metafont will find it. For example,
+ $TEXMF/metafont/mfpic/ .
+
+-- Copy mfpguide.pdf, mfpic-doc.pdf. mfpcard.pdf where documentation is
+ kept. For example, $TEXMF/doc/generic/mfpic/ . Optionally, copy the
+ *.tex versions of these, plus mfpdoc.sty, lcheadings.ist and
+ coil.mps, as well as examples/*.* either to the documentation area or
+ to the same place as mfpic.tex. Also optional: copy the two .dtx
+ files and mfpic.ins to the source area
+ ($TEXMF/source/generic/mfpic/).
+
+-- If required by your TeX system (most do): update the tex filename
+ database.
+
+There is one optional step that may be useful if you plan to make use of
+mfpic's support for Metafont (you may skip this if you only wish to use
+its MetaPost support): find the file modes.mf on your system. Typically
+this will be in $TEXMF/metafont/misc/ . Find, near the end of that file,
+a line similar to
+
+ localfont := ljfour;
+
+Replace, if necessary, the string "ljfour" by one of the modes defined
+in that file. At minimum, select one whose resolution (DPI) matches both
+your printer and the configuration of your dvi viewer. If you make such
+a change, regenerate the mf.base file (fmtutil on MacTeX or TeXLive;
+MiKTeX Options in MiKTeX). On some systems this may be named plain.base.
+
+Read mfpguide.pdf before trying anything further. If you are already
+familiar with mfpic (version 0.2.10.9 or later) you can probably get
+going right away.
+
+If you want to read the documented source code for mfpic, run pdflatex
+on mfpic.dtx and grafbase.dtx three times each. Then run makeindex for
+each:
+ makeindex -s gind.ist -o mfpic.ind mfpic.idx
+ makeindex -s gind.ist -o grafbase.ind grafbase.idx
+and then pdflatex again.
+
+------------------------------------------------------------------------
+
+If you desire to remake mfpic-doc.pdf, make sure mfpic-doc.tex and
+mfpdoc.sty are in the current directory or where LaTeX can find them.
+Make sure that coil.mps is also where LaTeX can find it. Edit, if you
+like, the paper size option in the \documentclass command in
+mfpic-doc.tex. (The document uses Times for the main font family,
+LuxiMono for a typewriter font, and CMSS for a sans serif font. Packages
+mathptmx amd luximono are required.) Then run
+ pdflatex mfpic-doc
+three times. Make sure lcheadings.ist is where makeindex can find it
+and run
+ makeindex -s lcheadings.ist -o mfpic-doc.ind mfpic-doc.idx
+Then
+ pdflatex mfpic-doc
+at least 2 more times.
+
+You could do something similar for mfpguide.tex:
+ pdflatex mfpguide
+ mpost guide.mp
+ pdflatex mfpguide
+ pdflatex mfpguide
+This relies on the mfpic package itself.
+
+\sig
+Dan Luecking (luecking at uark dot edu)
+Department of Mathematical Sciences
+University of Arkansas
+Fayetteville, Arkansas 72701-1201
+U.S.A
diff --git a/graphics/mfpic/metafont/grafbase.mf b/graphics/mfpic/metafont/grafbase.mf
new file mode 100644
index 0000000000..25f9a9cf76
--- /dev/null
+++ b/graphics/mfpic/metafont/grafbase.mf
@@ -0,0 +1,4055 @@
+%%
+%% This is file `grafbase.mf',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% grafbase.dtx (with options: `MF')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2002--2012, Daniel H. Luecking
+%%
+%% Mfpic may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3c of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Mfpic has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. There are several Base Interpreters associated
+%% with mfpic: plain TeX, LaTeX, plain Metafont and plain MetaPost.
+%%
+if (known grafbaseversion) or (known grafbase):
+ message "Grafbase (" & jobname & "): You have loaded grafbase more "
+ & "than once! Please make sure that it is loaded only once.";
+ endinput;
+fi
+boolean grafbase; grafbase := true;
+
+string fileversion, filedate;
+fileversion := "1.10"; filedate := "2012/12/03";
+
+message " Loading grafbase macros, version " & fileversion & ", " &
+ filedate & ".";
+message " ";
+
+def GBmsg expr s = message "Grafbase (" & jobname & "): " & s;
+enddef;
+def GBwarn expr s = GBmsg "Warning, " & s; enddef;
+def GBerrmsg (expr s) expr t = errhelp t;
+ errmessage "Grafbase (" & jobname & "): " & s; errhelp "";
+enddef;
+
+boolean MFPIC; MFPIC := false;
+
+def checkversions (expr g)=
+ numeric grafbaseversion; grafbaseversion := g;
+ if unknown mfpicversion: % no mfpic, or < 0.63
+ GBmsg "Recent mfpic not detected.";
+ elseif g = mfpicversion:
+ MFPIC := true;
+ else:
+ message "";
+ GBwarn "Version mismatch: "
+ & "mfpic and grafbase versions do not match.";
+ message "";
+ fi
+enddef;
+
+checkversions (110);
+
+if unknown base_name : input plain;
+elseif not string base_name: input plain;
+elseif base_name <> "plain": input plain;
+fi
+
+if not boolean debug: boolean debug; debug := false; fi
+
+def GBdebug =
+ begingroup
+ save >>; def >> = message " " & enddef;
+ message "Grafbase DEBUG";
+enddef;
+def GBenddebug =
+ message "End DEBUG";
+ >> "";
+ endgroup
+enddef;
+
+vardef mftitle expr t =
+ if string t: t; message t; fi
+enddef;
+
+boolean METAFONT, METAPOST;
+METAPOST := known color Carl Philipp Emanuel Bach;
+if METAPOST: METAFONT := false; else: METAFONT := true; fi
+
+if METAPOST:
+ GBerrmsg ("wrong compiler.")
+ "This file is for Metafont. For Metapost, use grafbase.mp.";
+fi
+
+if unknown mode:
+ GBerrmsg ("Metafont mode is unknown.")
+ "Set mode to a known mode, perhaps ljfour. "
+ & "If you proceed, localfont will be tried. "
+ & "If that is unknown, a generic mode will be tried.";
+ if known localfont: mode := localfont;
+ else:
+ if unknown GBresolution: GBresolution := 600 fi;
+ mode_def GBgeneric =
+ mode_param (pixels_per_inch, GBresolution);
+ mode_param (blacker, 0);
+ mode_param (fillin, 0);
+ mode_param (o_correction, 1);
+ mode_common_setup_;
+ enddef;
+ mode := GBgeneric;
+ fi
+fi
+mode_setup;
+if debug:
+ GBdebug;
+ >> "pixels_per_inch = " & decimal pixels_per_inch;
+ GBenddebug;
+fi
+
+font_identifier := "MFpic graphics";
+font_coding_scheme := "Arbitrary";
+interim designsize := 128pt#;
+
+if unknown aspect_ratio: aspect_ratio := 1; fi
+if unknown hppp: hppp := 1 fi;
+if unknown currenttransform:
+ transform currenttransform;
+ currenttransform := identity yscaled aspect_ratio;
+fi
+
+interim warningcheck := 0;
+interim turningcheck := 0;
+
+numeric unitlen, xscale, yscale, xneg, xpos, yneg, ypos;
+
+unitlen := 1 bp#;
+xscale := 7.2;
+yscale := 7.2;
+xneg := 0; xpos := 10;
+yneg := 0; ypos := 10;
+
+newinternal deg, pi, radian;
+deg := 1; pi := 3.14159;
+radian := 57.29578;
+numeric degree; degree := deg;
+
+newinternal penwd; penwd := 0.5pt;
+pen drawpen;
+
+def resizedrawpen (expr s) =
+ interim penwd := s;
+ setvariable (pen) (drawpen) pencircle scaled penwd;
+ save currentpen; pen currentpen; pickup drawpen;
+enddef;
+
+numeric hatchwd; hatchwd := 0.5bp;
+pen hatchpen; hatchpen := pencircle scaled hatchwd;
+
+boolean clipall; clipall := false;
+boolean ClipOn; ClipOn := false;
+path ClipPath[]; numeric ClipPath; ClipPath = 0;
+boolean truebbox; truebbox := false;
+
+def DoClip (suffix v) =
+ if ClipOn and (ClipPath > 0): clipsto (v, ClipPath); fi
+enddef;
+
+def noclip (text t) =
+ hide ( setboolean (ClipOn) false; t)
+enddef;
+
+boolean showbbox; showbbox := false;
+
+let color = numeric; color black, white;
+let rgbcolor = numeric;
+let cmykcolor = numeric;
+black := 0; white := 1;
+def withcolor text t = enddef;
+def _wc_ = withcolor enddef;
+
+color currentcolor, drawcolor, fillcolor, hatchcolor,
+ headcolor, pointcolor, tlabelcolor, background;
+currentcolor := fillcolor := drawcolor := hatchcolor :=
+ headcolor := pointcolor := tlabelcolor := black;
+background := white;
+
+vardef snapto expr t =
+ if numeric t:
+ if unknown t: 0
+ elseif t < 0: 0
+ elseif t > 1: 1
+ else: t
+ fi
+ else:
+ GBerrmsg ("Improper expression type.")
+ "The argument to `snapto' must be a numeric.";
+ fi
+
+enddef;
+
+vardef rgbgray (expr g) = (snapto g) * white enddef;
+vardef cmykgray (expr g) = cmyk(0,0,0,1 - snapto g) enddef;
+
+vardef knowncolor expr clr = (known clr) and (iscolor clr) enddef;
+
+vardef grayscalegray (expr g) = snapto g enddef;
+vardef gray (expr g) = grayscalegray (g) enddef;
+vardef cmyk (expr c, m, y, k) = rgb (1-c-k, 1-m-k, 1-y-k) enddef;
+vardef makegray primary clr =
+ if knowncolor clr: clr else: black fi
+enddef;
+def makergb = makegray enddef;
+def makecmyk = makegray enddef;
+vardef iscolor expr clr = (color clr) enddef;
+
+vardef forceclr (expr c) =
+ if unknown c :
+ if numeric c: grayscaleblack
+ elseif rgbcolor c: rgbblack
+ elseif cmykcolor c: cmykblack
+ else: black
+ fi
+ elseif numeric c: gray (c)
+ elseif iscolor c: c
+ else: black
+ fi
+enddef;
+vardef named (suffix c) = forceclr (c) enddef;
+
+vardef togray (expr r, g, b) =
+ gray (sqrt((2r*r + 4g*g + b*b)/7))
+enddef;
+
+vardef rgbtogray (expr r, g, b) =
+ togray(snapto r, snapto g, snapto b)
+enddef;
+vardef cmyktogray (expr c, m, y, k) =
+ rgbtogray (1-c-k,1-m-k,1-y-k)
+enddef;
+
+vardef cmyktorgb (expr c,m,y,k) =
+ rgb(1-c-k,1-m-k,1-y-k)
+enddef;
+vardef rgbtocmyk (expr r,g,b) =
+ cmyk(1-r,1-g,1-b,0)
+enddef;
+
+vardef rgb (expr r, g, b) =
+ togray (snapto r, snapto g, snapto b)
+enddef;
+vardef RGB (expr R, G, B) =
+ rgb (R/255, G/255, B/255)
+enddef;
+
+def list (suffix v) (text lst) =
+ v := 0; for _itm = lst: v[incr v] := _itm; endfor
+ if v = 0:
+ GBerrmsg ("No list to process!")
+ "An attempt was made to produce an array from a "
+ & "list of expressions having no valid entries.";
+ fi
+enddef;
+
+def map (text proc) (text lst) =
+ hide (_map := 0;)
+ for _a = lst:
+ if _map = 0: hide (_map := 1;) else: , fi
+ proc (_a)
+ endfor
+enddef;
+
+vardef knownnumericarray suffix arr =
+ setboolean (_kna) (known arr) and (numeric arr);
+ if _kna :
+ _kna := (arr = floor arr) and (arr >= 1);
+ for _idx = 1 upto arr :
+ exitif not _kna;
+ _kna := (known arr[_idx]) and (numeric arr[_idx]);
+ endfor
+ fi
+ _kna
+enddef;
+
+def copyarray (suffix src, dest) =
+ for _idx = 1 upto src: dest[_idx] := src[_idx]; endfor
+ dest := src;
+enddef;
+
+def maparr (text proc) (suffix p) =
+ for _idx = 1 upto p: proc (p[_idx]); endfor
+enddef;
+
+def textpairs = gsetarray (pair) enddef;
+
+def setuniquepairs (suffix p) (text t) =
+ save p; pair p[];
+ setpairs (_up) (t);
+ if _up > 0:
+ p := 1; p1 := _up1;
+ for _i = 2 upto _up:
+ if _up[_i] <> p[p]: p[incr p] := _up[_i]; fi
+ endfor
+ else:
+ p := 0;
+ fi
+enddef;
+
+vardef chpair (text proc) (expr p) =
+ (proc (xpart p), proc (ypart p))
+enddef;
+
+vardef floorpair (expr p) = (floor (xpart p), floor (ypart p))
+enddef;
+vardef ceilingpair (expr p) = (ceiling (xpart p), ceiling (ypart p))
+enddef;
+
+def hroundpair (expr p) = (hround (xpart p), hround (ypart p))
+enddef;
+vardef goodpair (expr p) = hroundpair(p.t_) enddef;
+
+vardef emin (expr a, b) = if a < b: a else: b fi enddef;
+vardef emax (expr a, b) = if a > b: a else: b fi enddef;
+
+vardef pairmin (expr z, w) =
+ ( emin (xpart z, xpart w), emin (ypart z, ypart w ) )
+enddef;
+vardef pairmax (expr z, w) =
+ ( emax (xpart z, xpart w), emax (ypart z, ypart w ) )
+enddef;
+
+vardef minpair (suffix p) = setpair (_mp) p1;
+ for _idx = 2 upto p - 1: _mp := pairmin (_mp, p[_idx]); endfor
+ pairmin (_mp, p[p])
+enddef;
+vardef maxpair (suffix p) = setpair (_mp) p1;
+ for _idx = 2 upto p - 1: _mp := pairmax (_mp, p[_idx]); endfor
+ pairmax (_mp, p[p])
+enddef;
+
+primarydef Z xprod W = (xpart Z * ypart W - xpart W * ypart Z)
+enddef;
+
+def force_initial (expr p) (suffix f) =
+ hide( setnumeric (_n) length f;
+ f := p
+ if _n = 0:
+ {0,0}
+ else:
+ ..controls post0 (f) and pre 1 (f).. subpath (1,_n) of f
+ fi;)
+enddef;
+
+def force_terminal (expr p) (suffix f) =
+ hide(setpath (_f) reverse f;
+ force_initial (p) (_f);
+ f := reverse _f;)
+enddef;
+
+def force_equal_ends (suffix f, g) =
+ hide(save _p; pair _p;
+ _p := .5[pnt[length f] (f), pnt0(g)];
+ force_terminal (_p) (f); force_initial (_p) (g);)
+enddef;
+
+def replace_ends_of_cycle (expr p) (suffix f) =
+hide(
+if cycle f:
+ save _n; _n := length f;
+ f := p
+ if _n = 0: &cycle
+ else: .. controls post0 (f) and pre 1 (f) ..
+ if _n = 1: cycle
+ else: subpath (1, _n - 1) of f ..
+ controls post[_n - 1](f) and pre[_n](f) .. cycle
+ fi
+ fi;
+fi)
+enddef;
+
+pair thetimes;
+numeric _Xtime, _Ytime;
+tertiarydef a intersects b =
+ begingroup
+ thetimes := a intersectiontimes b;
+ _Xtime := xpart thetimes;
+ _Ytime := ypart thetimes;
+ (_Xtime > -1)
+ endgroup
+enddef;
+
+tertiarydef a misses b = ((a intersectiontimes b) < origin) enddef;
+
+vardef makepicture (expr s) =
+ if picture s: s
+ elseif path s: picpath (s)
+ else: nullpicture
+ fi
+enddef;
+
+vardef onepointpath (expr cyclic, q) =
+ q if cyclic: &cycle else: {0,0} fi
+enddef;
+
+vardef fallbackpath (expr cyclic, p) (text t) =
+ onepointpath (cyclic, p)
+enddef;
+
+def even = not odd enddef;
+
+primarydef a divides b =
+ ((b mod a) = 0)
+enddef;
+
+vardef image (text t) =
+ newpicture (currentpicture);
+ t;
+ currentpicture
+enddef;
+
+def beginimage =
+ begingroup
+ newpicture (currentpicture);
+enddef;
+def endimage =
+ ; currentpicture
+ endgroup
+enddef;
+
+def makeimage (suffix name) (expr refpt) =
+ setpair (_image_reference_point) zconv (refpt);
+ setpicture (name) beginimage
+enddef;
+def concludeimage =
+ endimage shifted
+ -goodpair (_image_reference_point)
+enddef;
+
+def setvariable (text kind) (suffix name) =
+ save name; kind name; name :=
+enddef;
+def gsetvariable (text kind) (suffix name) = kind name; name :=
+enddef;
+
+def setnumeric (suffix name) = save name; name := enddef;
+def setboolean = setvariable (boolean) enddef;
+def setpair = setvariable (pair) enddef;
+def setpath = setvariable (path) enddef;
+def setpicture = setvariable (picture) enddef;
+def setstring = setvariable (string) enddef;
+def settransform = setvariable (transform) enddef;
+def setpen = setvariable (pen) enddef;
+def settension (suffix tn) expr tens =
+ setnumeric (tn) if tens > 0: tens else: default_tension fi;
+enddef;
+def fixtension (suffix tn) = if tn < .75: tn := .75; fi enddef;
+
+def newpicture (suffix pic) = setpicture (pic) nullpicture; enddef;
+def convertpath (suffix g) expr f = setpath (g) zconv (f); enddef;
+
+def setarray (text kind) (suffix name) =
+ save name; kind name[]; list (name)
+enddef;
+def setpairs = setarray (pair) enddef;
+def gsetarray (text kind) (suffix name) =
+ numeric name; kind name[]; list (name)
+enddef;
+
+
+def setbbox (suffix ll, ur) =
+ save ll, ur; pair ll, ur; getbbox (ll, ur)
+enddef;
+
+def setsplit (suffix s) expr ss =
+ setnumeric (s) emax (1, ceiling ss);
+enddef;
+
+def setrgbcolor = setcolor enddef;
+def setcmykcolor = setcolor enddef;
+def setcolor = setvariable (color) enddef;
+def gsetcolor = gsetvariable (color) enddef;
+
+setcolor(rgbblack) rgb(0,0,0);
+setcolor(red) rgb(1,0,0);
+setcolor(green) rgb(0,1,0);
+setcolor(blue) rgb(0,0,1);
+setcolor(rgbwhite) rgb(1,1,1);
+setcolor(cmykwhite) cmyk(0,0,0,0);
+setcolor(cyan) cmyk(1,0,0,0); % Maybe these should
+setcolor(magenta) cmyk(0,1,0,0); % be rbg for backward
+setcolor(yellow) cmyk(0,0,1,0); % compatibility?
+setcolor(cmykblack) cmyk(0,0,0,1);
+setcolor(grayscaleblack) gray(0);
+setcolor(grayscalewhite) gray(1);
+
+def setoutputtemplate text garbage = enddef;
+
+vardef GBromannumeral (expr X) =
+ save Y, _tmp, U; string U;
+
+ Y.m := X div 1000; % thousands digit
+ _tmp := X - 1000Y.m; % hundreds digits and lower
+ Y.c := _tmp div 100; % hundreds
+ _tmp := _tmp - 100Y.c; % tens and units
+ Y.x := _tmp div 10; % tens
+ Y.i := _tmp - 10Y.x; % units
+
+ strrepeat("m", Y.m) &
+ GBromandigit("c", "d", "m", Y.c) &
+ GBromandigit("x", "l", "c", Y.x) &
+ GBromandigit("i", "v", "x", Y.i)
+enddef;
+
+vardef GBromandigit (expr bot, mid, top, n) =
+ if n > 9 : top & strrepeat(bot, n-10) % shouldn't happen
+ elseif n > 8 :
+ bot & top % "ix"
+ elseif n > 4 : mid & strrepeat (bot, n-5) % "v"--"viii"
+ elseif n > 3 :
+ bot & mid % "iv"
+ else: strrepeat (bot, n) % ""--"iii" for 0--3
+ fi
+enddef;
+
+vardef strrepeat (expr st, rep) =
+ "" for i = 1 upto rep: & st endfor
+enddef;
+
+transform ztr, vtr;
+def setztr =
+ if debug:
+ GBdebug;
+ >> "charwd = " & decimal charwd & "pt#";
+ >> "charht = " & decimal charht & "pt#";
+ >> "w_ = " & decimal w_ & " pixels";
+ >> "h_ = " & decimal h_ & " pixels";
+ >> "unitlen = " & decimal unitlen & "pt#";
+ >> "hppp = " & decimal hppp;
+ >> "xneg = " & decimal xneg;
+ >> "xpos = " & decimal xpos;
+ >> "yneg = " & decimal yneg;
+ >> "ypos = " & decimal ypos;
+ >> "xscale = " & decimal xscale;
+ >> "yscale = " & decimal yscale;
+ GBenddebug;
+ fi
+ save ztr, vtr;
+ transform ztr, vtr;
+ vtr := identity xscaled xscale yscaled yscale scaled (unitlen*hppp);
+ ztr := identity shifted (-xneg, -yneg) transformed vtr;
+ if debug:
+ GBdebug;
+ >> "ztr is";
+ show ztr;
+ >> "vtr is";
+ show vtr;
+ GBenddebug;
+ fi
+enddef;
+
+vardef zconv (expr a) = a transformed ztr enddef;
+vardef invzconv (expr a) = a transformed (inverse ztr) enddef;
+vardef vconv (expr v) = v transformed vtr enddef;
+vardef invvconv (expr v) = v transformed (inverse vtr) enddef;
+
+def active_plane = currentpicture enddef;
+
+def initpic =
+ setztr;
+ resizedrawpen (penwd);
+ if ClipOn: ClipPath := 1;
+ ClipPath1 := rect (origin, (w_, h_));
+ fi
+ if debug:
+ GBdebug;
+ >> "Drawing nominal bounding box around picture";
+ GBenddebug;
+ noclip ( safedraw rect (origin, (w_, h_)) );
+ fi
+enddef;
+
+def mfpicenv = enddef;
+def endmfpicenv = enddef;
+def bounds (expr a, b, c, d) =
+ xneg := a; xpos := b;
+ yneg := c; ypos := d;
+enddef;
+
+string extra_beginmfpic; extra_beginmfpic := "";
+string extra_endmfpic; extra_endmfpic := "";
+
+def beginmfpic (expr ch) =
+ begingroup
+ gcode := ch;
+ save w_, h_, d_;
+ charwd := (xpos-xneg)*xscale*unitlen;
+ charht := (ypos-yneg)*yscale*unitlen;
+ chardp := 0;
+ charcode := if known ch: byte ch else: 0 fi;
+ w_ := hround (charwd*hppp);
+ h_ := vround (charht*hppp);
+ d_ := vround (chardp*hppp);
+ charic := 0; clearxy; clearit; clearpen;
+ scantokens extra_beginchar;
+ initpic;
+ scantokens extra_beginmfpic;
+enddef;
+
+def endmfpic =
+ scantokens extra_endmfpic;
+ if debug:
+ GBdebug;
+ >> "TFM charwd = " & decimal charwd & "pt#";
+ >> "TFM charht = " & decimal charht & "pt#";
+ GBenddebug;
+ fi
+ DoClip (active_plane);
+ if clipall: clipto (active_plane) rect (origin, (w_, h_)); fi
+ if showbbox: noclip ( safedraw rect (origin, (w_, h_)) ); fi
+ scantokens extra_endchar;
+ if proofing > 0: makebox (proofrule); fi
+ chardx := w_; % desired width of character in pixels
+ shipit;
+ if displaying > 0: makebox (screenrule); showit; fi
+ endgroup
+enddef;
+
+pair label_adjust;
+label_adjust := origin;
+numeric label_sep, labelpath_sep ;
+label_sep := 0; labelpath_sep := 0;
+def verbatimtex text t = enddef;
+
+vardef newgblabel (expr hf, vf, BL, r) (text s) (text pts) =
+enddef;
+
+vardef gblabel (expr a, b, c, d, r) (text s) (text t) =
+ newgblabel (b, d, (c = 0) and (d = 0), r) (s) (t);
+enddef;
+
+vardef ref_shift (expr hf, vf, BL, ll, ur) =
+ - ( (hf)[xpart ll, xpart ur],
+ (vf)[if BL: 0 else: (ypart ll) fi, ypart ur] )
+enddef;
+
+vardef thegblabel (expr z, r, p) =
+ ((p shifted z) rotated r) shifted label_adjust
+enddef;
+
+vardef textrect (expr lbl, rad, loc) =
+ textrectx (.5, .5, false, 0) (origin, lbl, rad, loc)
+enddef;
+vardef textoval (expr lbl, mult, loc) =
+ xellipse (true, .5, .5, false, 0) (origin, lbl, mult, loc)
+enddef;
+vardef textellipse (expr lbl, rat, loc) =
+ xellipse (false, .5, .5, false, 0) (origin, lbl, rat, loc)
+enddef;
+
+boolean roundends; roundends := true;
+vardef textrectx (expr a, b, c, rot, xy, lbl, rad, loc) =
+ save ll, ur, _r, f, zz;
+ pair ll, ur, zz; path f;
+ pathdims (xy, lbl) (ll, ur);
+ readjustdims (ll, ur) (labelpath_sep)
+ _r := if numeric rad: rad
+ elseif not boolean rad: 0
+ elseif rad: emin (xpart(ur-ll), ypart (ur-ll))/sqrt(2)
+ else: 0
+ fi;
+ if _r = 0:
+ f := rect (ll, ur);
+ else:
+ save p, q;
+ pair p[]; path q;
+ p1 := ur - _r*dir(45);
+ p3 := ll + _r*dir(45);
+ p2 := (xpart p3, ypart p1);
+ p4 := (xpart p1, ypart p3);
+ q := if _r < 0: reverse fi quartercircle scaled 2_r;
+ f :=
+ (q shifted p1)--(q rotated 90 shifted p2)
+ --(q rotated 180 shifted p3)
+ --(q rotated -90 shifted p4)--cycle;
+
+ fi
+ readjustdims (ll, ur) (label_sep - labelpath_sep);
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), rot, f))
+ shifted loc
+enddef;
+
+def textovalx = xellipse (true) enddef;
+def textellipsex = xellipse (false) enddef;
+
+vardef xellipse (expr aspect, a, b, c, r, xy, lbl, mult, loc) =
+ if mult = 0:
+ textrectx (a, b, c, r) (xy, lbl, 0, loc)
+ else:
+ save ll, ur, cc, ww, hh, f;
+ pair ll, ur, cc; path f;
+ pathdims (xy, lbl) (ll, ur);
+ readjustdims (ll, ur) (labelpath_sep)
+ cc := .5[ll, ur];
+ (ww, hh) = ur - cc;
+ if (ww = 0) or (hh = 0):
+ f = (ll--ur);
+ else:
+ save aa, bb;
+ aa := ww ++ if aspect: ww else: hh fi *mult;
+ bb := hh ++ if aspect: hh else: ww fi /mult;
+ f := ellipse (cc, aa, bb, 0);
+ fi
+ readjustdims (ll, ur) (label_sep - labelpath_sep);
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), r, f))
+ shifted loc
+ fi
+enddef;
+
+def pathdims (expr xy, lbl) (suffix ll, ur) =
+ if pair lbl:
+ ll := xy; ur := lbl;
+ else:
+ ll := ur := origin;
+ fi
+enddef;
+
+def readjustdims (suffix ll, ur) (expr s) =
+ ll := ll - s*(1,1);
+ ur := ur + s*(1,1);
+enddef;
+
+newinternal reallysmall; reallysmall := 3epsilon;
+newinternal nottoosmall; nottoosmall := eps/2 + 2epsilon;
+def signof (expr X) = if X < 0: - fi enddef;
+def TruncateWarn expr s =
+ GBwarn s & " is too large or undefined, so it will be truncated.";
+enddef;
+
+vardef secd primary X =
+ setnumeric (temp) cosd(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Secant or Tangent";
+ temp := signof (temp) reallysmall;
+ fi
+ 1/temp
+enddef;
+vardef tand primary X = sind(X)*secd(X) enddef;
+
+vardef cscd primary X =
+ setnumeric (temp) sind(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Cosecant or Cotangent";
+ temp := signof(temp) reallysmall;
+ fi
+ 1/temp
+enddef;
+vardef cotd primary X = cosd(X)*cscd(X) enddef;
+
+vardef acos primary X =
+ if abs X > 1:
+ TruncateWarn "Argument of arccosine";
+ angle (signof(X) 1, 0)
+ else:
+ angle (X, 1 +-+ X)
+ fi
+enddef;
+vardef asin primary X =
+ if abs X > 1:
+ TruncateWarn "Argument of arcsine";
+ angle (0, signof(X) 1)
+ else:
+ angle (1 +-+ X, X)
+ fi
+enddef;
+vardef atan primary X = angle (1, X) enddef;
+
+vardef sin primary X = sind (X*radian) enddef;
+vardef cos primary X = cosd (X*radian) enddef;
+vardef tan primary X = tand (X*radian) enddef;
+vardef cot primary X = cotd (X*radian) enddef;
+vardef sec primary X = secd (X*radian) enddef;
+vardef csc primary X = cscd (X*radian) enddef;
+
+vardef degrees (expr t) = t*radian enddef;
+vardef radians (expr t) = t/radian enddef;
+
+vardef invcos primary X = radians (acos X) enddef;
+vardef invsin primary X = radians (asin X) enddef;
+vardef invtan primary X = radians (atan X) enddef;
+
+vardef exp primary X = mexp (256 * X) enddef;
+vardef ln primary X = (mlog X) / 256 enddef;
+vardef log primary X = ln (X) enddef;
+vardef logbase (expr B) primary X = (mlog X)/(mlog B) enddef;
+vardef logtwo primary X = logbase( 2) (X) enddef;
+vardef logten primary X = logbase(10) (X) enddef;
+
+vardef cosh primary X =
+ setnumeric (temp) 2 exp (-abs(X));
+ if temp < reallysmall:
+ TruncateWarn "Cosh";
+ temp := reallysmall;
+ fi
+ 1/temp + temp/4
+enddef;
+
+vardef sinh primary X =
+ setnumeric (temp) 2 exp (-abs(X));
+ if temp < reallysmall:
+ TruncateWarn "Sinh";
+ temp := reallysmall;
+ fi
+ signof (X) (1/temp - temp/4)
+enddef;
+
+vardef sech primary X =
+ setnumeric (temp) exp(-(abs (X)));
+ 2temp/(1 + temp*temp)
+enddef;
+
+vardef tanh primary X =
+ setnumeric (temp) exp(-2(abs (X)));
+ signof (X) (1 - temp)/(1 + temp)
+enddef;
+
+vardef csch primary X =
+ save temp, tempa; temp := exp(-(abs (X)));
+ tempa := (1 - temp*temp)/2;
+ if tempa < reallysmall:
+ TruncateWarn "Csch";
+ tempa := reallysmall;
+ fi
+ signof (X) temp / tempa
+enddef;
+
+vardef coth primary X =
+ setnumeric (temp) tanh(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Coth";
+ temp := signof (X) reallysmall;
+ fi
+ 1/temp
+enddef;
+
+vardef acosh primary y =
+ if y < 1:
+ TruncateWarn "acosh";
+ 0
+ else:
+ ln (y + (y +-+ 1))
+ fi
+enddef;
+
+vardef asinh primary y = ln (y + (y ++ 1)) enddef;
+
+vardef atanh primary y =
+ if abs (y) < 1:
+ (ln (1 + y) - ln (1 - y))/2
+ else:
+ TruncateWarn "atanh";
+ signof (y) infinity
+ fi
+enddef;
+
+vardef Arg primary Z = (angle Z)/radian enddef;
+vardef Log primary Z = (ln (abs Z), Arg Z) enddef;
+vardef cis primary T = dir (T*radian) enddef;
+vardef zexp primary Z = (exp (xpart Z)) * cis (ypart Z) enddef;
+vardef sgn primary Z = if not (Z = origin): unitvector fi Z
+enddef;
+vardef zsqrt primary Z =
+ if Z = origin: origin else: sqrt(abs(Z)) * dir ((angle Z)/2) fi
+enddef;
+vardef conj primary Z = (xpart Z, -ypart Z) enddef;
+
+primarydef Z zmul W = Z zscaled W enddef;
+primarydef Z zdiv W =
+ Z zmul ( unitvector (conj W) / (abs W) )
+enddef;
+
+vardef Moebius (expr A) primary Z =
+ save _D; pair _D;
+ _D := (1, 0) + (Z zscaled (conj A));
+ (Z + A)/(abs _D) rotated (- angle _D)
+enddef;
+vardef pshdist (expr Z,W) = abs(Moebius(-W)(Z)) enddef;
+vardef pshdist_hp (expr Z,W) = abs(Z-W)/abs(Z-conj(W)) enddef;
+vardef kelvin (expr Z) =
+ save tmp_; tmp_ = abs(Z);
+ if tmp_ = 0:
+ (infinity, infinity)
+ elseif tmp_ < reallysmall:
+ infinity*unitvector Z
+ else:
+ (1/tmp_)*unitvector Z
+ fi
+enddef;
+
+vardef polar primary p = (xpart p) * dir (ypart p) enddef;
+def id (expr x) = x enddef;
+
+primarydef x**y =
+ if y=2: x*x
+ elseif (x = floor x) and (abs y = floor y):
+ 1 for n=1 upto y: *x endfor
+ else: takepower y of x
+ fi
+enddef;
+let ^ = **;
+
+transform T_stack[];
+numeric T_stack; T_stack := 0;
+
+def T_push (expr T) = T_stack[incr T_stack] := T; enddef;
+def T_pop (suffix $) =
+ if T_stack > 0:
+ $ := T_stack[T_stack];
+ T_stack := T_stack - 1;
+ fi
+enddef;
+
+def bcoords = hide ( T_push (ztr) ) enddef;
+def ecoords = hide ( T_pop (ztr); vtr := vectorpart ztr ) enddef;
+
+vardef vectorpart primary T = T shifted -(origin transformed T)
+enddef;
+
+def apply_t (text Transformer) =
+ ztr := identity Transformer transformed ztr;
+ vtr := vectorpart ztr;
+enddef;
+
+def xslant = slanted enddef; % (x+sy, y).
+def yslant primary s = % (x, y+sx).
+ transformed
+ begingroup
+ save T; transform T;
+ origin transformed T = origin;
+ (1, 0) transformed T = (1, s);
+ (0, 1) transformed T = (0, 1);
+ T
+ endgroup
+enddef;
+
+def zslant primary p = % (xu+yv, xv+yu), where p = (u, v).
+ transformed
+ begingroup
+ save T; transform T;
+ xpart T = ypart T = 0;
+ xxpart T = yypart T = xpart p;
+ xypart T = yxpart T = ypart p;
+ T
+ endgroup
+enddef;
+
+def xyswap = zslant (0, 1) enddef;
+def boost primary X = zslant (cosh X, sinh X) enddef;
+
+vardef transformedpath (text Transformer) expr f = f Transformer
+enddef;
+
+def rotatedpath (expr p, th) =
+ transformedpath (
+ transformed vtr
+ rotatedaround (p transformed vtr, th)
+ transformed (inverse vtr)
+ )
+enddef;
+def reflectedpath (expr p, q) =
+ transformedpath (
+ transformed vtr
+ reflectedabout (p transformed vtr, q transformed vtr)
+ transformed (inverse vtr)
+ )
+enddef;
+
+def scaledpath (expr p, s) =
+ transformedpath (shifted -p scaled s shifted p)
+enddef;
+def xscaledpath (expr a, s) =
+ transformedpath (shifted (-a, 0) xscaled s shifted (a, 0))
+enddef;
+def yscaledpath (expr b, s) =
+ transformedpath (shifted (0, -b) yscaled s shifted (0, b))
+enddef;
+
+def slantedpath = xslantedpath enddef;
+def xslantedpath (expr b, s) =
+ transformedpath (shifted (0, -b) slanted s shifted (0, b))
+enddef;
+def yslantedpath (expr a, s) =
+ transformedpath (shifted (-a, 0) yslant s shifted (0, a))
+enddef;
+
+def shiftedpath (expr v) = transformedpath (shifted v) enddef;
+
+def xyswappedpath = transformedpath (xyswap) enddef;
+
+vardef partialpath (expr a, b) expr f =
+ save flag, flo, fhi, lo, hi, n;
+ boolean flag; flag = true;
+ convertpath (g) f;
+ n := length f;
+
+ flo := snapto emin(a,b);
+ if flo = 0:
+ lo := 0;
+ elseif flo < 1:
+ setuplengtharray (cum, tot, idx) g;
+ flag := false;
+ lo := gettime (cum, idx) (flo*tot);
+ else:
+ lo := n;
+ fi
+
+ fhi := snapto emax (a,b);
+ if flo = fhi:
+ hi := lo;
+ elseif fhi < 1:
+ if flag: setuplengtharray (cum, tot, idx) g; fi
+ hi := gettime (cum, idx) (fhi*tot);
+ else:
+ hi := n;
+ fi
+
+ if a > b: reverse fi subpath (lo, hi) of f
+enddef;
+
+vardef gsubpath (expr a, b) expr f = subpath (a, b) of f enddef;
+
+def setuplengtharray (suffix cum, tot, idx) =
+ save cum, tot, idx; idx := 0; tot := makelengtharray (cum)
+enddef;
+
+vardef pathtime@# (suffix p) =
+ if @# <= 0: 0
+ elseif @# >= 1: length p
+ else:
+ setuplengtharray (cum, tot, idx) p;
+ gettime (cum, idx) (@#*tot)
+ fi
+enddef;
+
+vardef pathpoint (expr frac) (suffix p) =
+ convertpath (_pp) p; pnt[pathtime[frac] (_pp)] (p)
+enddef;
+
+def mono (suffix u) = cull u keeping (1, infinity); enddef;
+
+def andto (suffix u) (expr v) =
+ mono (u); addto u also v; cull u keeping (2, 2);
+enddef;
+primarydef u picand v =
+ begingroup setpicture (t) u; andto (t, v); t endgroup
+enddef;
+
+def orto (suffix u) (expr v) =
+ mono (u); addto u also v; cull u keeping (1, infinity);
+enddef;
+primarydef u picor v =
+ begingroup setpicture (t) u; orto (t, v); t endgroup
+enddef;
+
+def xorto (suffix u) (expr v) =
+ mono (u); addto u also v; cull u keeping (1, 1);
+enddef;
+primarydef u picxor v =
+ begingroup setpicture (t) u; xorto (t, v); t endgroup
+enddef;
+
+def subto (suffix u) (expr v) =
+ mono (u); addto u also -v; cull u keeping (1, infinity);
+enddef;
+primarydef u picsub v =
+ begingroup setpicture (t) u; mono (t); subto (t, v); t endgroup
+enddef;
+
+def coloraddto (expr clr) (suffix u) (expr v) =
+ if clr < white:
+ orto (u, v);
+ else:
+ subto (u, v);
+ fi;
+enddef;
+
+def coloraddon (expr clr) (suffix v) =
+ if clr < white:
+ _orto (active_plane, v);
+ else:
+ _subto (active_plane, v);
+ fi;
+enddef;
+
+def _orto (suffix u, v) =
+ mono (u); mono (v);
+ addto u also v;
+cull u keeping (1, 2);
+enddef;
+
+def _subto (suffix u, v) =
+ mono (u); mono (v); addto u also -v; cull u keeping (1, 1);
+enddef;
+
+vardef interior expr c =
+ newpicture (v);
+ addto v contour (c.t_);
+ cull v dropping (0,0);
+ v
+enddef;
+
+vardef interiors suffix cc =
+ newpicture (_ints);
+ for _idx = 1 upto cc:
+ addto _ints also interior cc[_idx]);
+ endfor
+ mono (_ints);
+ _ints
+enddef;
+
+def clipto (suffix vt) expr c =
+ if path c:
+ andto (vt, interior c);
+ fi
+enddef;
+def clipsto (suffix vt, cc) =
+ andto (vt, interiors cc);
+enddef;
+
+vardef Clipped (suffix vt) expr c =
+ setpicture (_Cl) vt; clipto (_Cl) c; _Cl
+enddef;
+def clip = Clipped enddef;
+
+vardef picneg (suffix vt) expr c =
+ setpicture (_pn) interior c;
+ _subto (_pn, vt);
+ _pn
+enddef;
+
+def shpath (suffix v) (expr q, f) =
+ addto v doublepath (f.t_) withpen (q.t_);
+enddef;
+
+numeric minpenwd;
+minpenwd := 1; % 1 pixel
+vardef picpath expr d =
+ newpicture (v);
+ if penwd >= minpenwd:
+ shpath (v, drawpen) (d);
+ mono (v);
+ fi
+ v
+enddef;
+
+def picdot (suffix v) (expr w, p) =
+ addto v also
+ (w shifted goodpair (p));
+enddef;
+
+vardef setdot (expr apath, sc) =
+ if cycle apath: interior
+ else: picpath
+ fi
+ (apath scaled emax (ceiling (sc), minpenwd))
+enddef;
+
+numeric shadepicsize; shadepicsize := 0.8bp;
+vardef shadepic (suffix dims) (expr grparam) =
+ pair dims;
+ setnumeric (_frac) 2*emin (grparam, 1 - grparam);
+ save _hp, _vp, _dotwd, _dotht;
+ if aspect_ratio < 1:
+ _vp := emax (2, hround (shadepicsize.o_));
+ _hp := hround (_vp._o_);
+ _dotwd := hround (_hp*sqrt _frac);
+ _dotht := if _dotwd = 0: 0
+ else: hround (_hp*_vp*_frac/_dotwd)
+ fi;
+ else:
+ _hp := emax (2, hround (shadepicsize));
+ _vp := hround (_hp.o_);
+ _dotht := hround (_vp*sqrt _frac);
+ _dotwd := if _dotht = 0: 0
+ else: hround (_hp*_vp*_frac/_dotht)
+ fi;
+ fi
+ dims := ( _hp, _vp._o_ );
+ newpicture (_shp);
+ addto _shp contour rect (origin, (_dotwd, _dotht));
+ picdot (_shp, _shp, dims);
+ dims := 2dims; mono (_shp);
+ if grparam >= .5: _shp
+ else: (interior (rect (origin, dims))) picsub _shp
+ fi
+enddef;
+
+vardef shaded (expr clr) expr c =
+ if cycle c:
+ if (clr <= black) or (clr >= white):
+ interior c
+ else:
+ save shdims, shpic;
+ picture shpic; pair shdims;
+ shpic := shadepic (shdims) (clr);
+ setbbox (ll, ur) c;
+ newpicture (vsh);
+ fillwith (vsh) (shpic, shdims, ll, ur);
+ clipto (vsh) c; vsh
+ fi
+ else: picpath c % should we? or just make it null?
+ fi
+enddef;
+
+vardef fillwith (suffix v) (expr pic, dims, ll, ur) =
+ newpicture (b);
+ save fwdims, _ll, _ur; pair fwdims, _ll, _ur;
+ fwdims := goodpair (dims);
+ _ll := floorpair (ll.t_);
+ _ur := ur.t_;
+ for s = xpart _ll step xpart fwdims until xpart _ur:
+ addto b also pic shifted (s, 0);
+ endfor
+ for s = ypart _ll step ypart fwdims until ypart _ur:
+ addto v also b shifted (0, s);
+ endfor
+ mono (v);
+enddef;
+
+def thatchf (suffix v) (expr CT, sp, a, b) =
+ begingroup
+ setnumeric (_sp) signof (ypart b - ypart a) abs(sp);
+ for _y = _sp*( ceiling ((ypart a)/_sp) ) step _sp until ypart b:
+ shpath (v, hatchpen)
+ ( ( (xpart a, _y)--(xpart b, _y) ) transformed CT );
+ endfor
+ mono (v);
+ endgroup
+enddef;
+
+def axialgradientf (suffix clr, v) (expr theta, sp, a, b) =
+ begingroup
+ save _hh, _sp, _nn, _y;
+ _hh := ypart b - ypart a;
+ _sp := signof (_hh) abs(sp);
+ _nn := emax (1, round (_hh/_sp));
+ _sp := _hh/_nn + signof (_hh) epsilon;
+ _nn := _nn-1;
+ setpath (_p) rect ((xpart a, 0),(xpart b, _sp));
+ _y := ypart a;
+ for _i = 0 upto _nn:
+ if (clr(_i/_nn)) < white :
+ addto v also shaded (clr(_i/_nn)) ( _p shifted (0,_y))
+ rotated theta;
+ fi
+ _y := _y + _sp;
+ endfor
+ mono (v);
+ endgroup
+enddef;
+
+def areagradientf (suffix clr, v) (expr sp, tp, a, b) =
+begingroup
+ save _ww, _hh, _sp, _tp, _nn, _mm, _x, _y;
+ _ww := xpart b - xpart a;
+ _hh := ypart b - ypart a;
+ _sp := signof (_ww) abs(sp);
+ _tp := signof (_hh) abs(tp);
+ _nn := emax (1, round (_ww/_sp));
+ _mm := emax (1, round (_hh/_tp));
+ _sp := _ww/_nn + signof (_ww) epsilon;
+ _tp := _hh/_mm + signof (_hh) epsilon;
+ _mm := _mm-1; _nn := _nn-1;
+ setpath (_p) rect (origin,(_sp,_tp));
+ _x := xpart a; y_a := ypart a;
+ for _i = 0 upto _nn:
+ _y := y_a;
+ for _j = 0 upto _mm:
+ if (clr(_i/_nn,_j/_mm)) < white:
+ addto v also shaded (clr(_i/_nn,_j/_mm)) (_p shifted (_x,_y));
+ fi
+ _y := _y + _tp;
+ endfor
+ _x := _x + _sp;
+ endfor
+ mono (v);
+endgroup
+enddef;
+
+path unitcircle;
+unitcircle := fullcircle scaled 2;
+def radialgradientf (suffix clr, v) (expr sp, ctr, rad) =
+ begingroup
+ save _sp, _r, _nn;
+ _nn := emax (1, round (rad/sp));
+ _sp := rad/_nn + epsilon;
+ _nn := _nn - 1;
+ _r := _sp;
+ % fill the small center circle first
+ if (clr(0)) < white :
+ addto v also shaded (clr(0)) (unitcircle scaled _r shifted ctr);
+ fi
+ for _i = 1 upto _nn:
+ if (clr(_i/_nn)) < white :
+ addto v also shaded (clr(_i/_nn))
+ (unitcircle scaled (_r + _sp) -- reverse unitcircle scaled _r
+ --cycle) shifted ctr;
+ fi
+ _r := _r + _sp;
+ endfor
+ mono (v);
+ endgroup
+enddef;
+
+def tile (suffix atile) (expr unit, width, height, clipit) =
+ picture atile.pic; atile.pic := nullpicture;
+ pair atile.dims;
+ atile.dims := round ((width, height)*unit);
+ begingroup
+ save active_plane;
+ def active_plane = atile.pic enddef;
+ save ztr, vtr; transform ztr, vtr;
+ ztr := identity scaled unit; vtr := ztr;
+ save xneg, xpos, yneg, ypos;
+ xneg := 0; xpos := width; yneg := 0; ypos := height;
+ save ClipOn; boolean ClipOn;
+ if clipit:
+ ClipOn := true;
+ setarray (path) (ClipPath) (rect(origin, atile.dims));
+ else:
+ ClipOn := false;
+ fi
+enddef;
+def endtile =
+ DoClip (active_plane);
+ endgroup
+enddef;
+
+vardef is_tile (suffix atile) =
+ (known atile.pic ) and (picture atile.pic) and
+ (known atile.dims) and (pair atile.dims )
+enddef;
+
+vardef pnt@# (expr p) = point @# of p enddef;
+vardef pre@# (expr p) = precontrol @# of p enddef;
+vardef post@# (expr p) = postcontrol @# of p enddef;
+
+numeric bbox_split; bbox_split := 4;
+def getbbox (suffix ll, ur) expr g =
+ setsplit (_s) bbox_split;
+ ur := ll := pnt 0 (g);
+ for _j = 1 upto length g:
+ ll := pairmin (ll, pnt[_j] (g)); ur := pairmax (ur, pnt[_j] (g));
+ endfor
+ for _j = 1 upto _s*(length g):
+ ctrlsbbox (ll, ur) subpath ((_j-1)/_s, _j/_s) of g;
+ endfor
+ if showbbox: noclip ( safedraw rect (ll, ur) ); fi
+enddef;
+
+def ctrlsbbox (suffix ll, ur) expr p =
+ ll := pairmin ( pairmin (ll, post0 (p)), pre 1 (p) );
+ ur := pairmax ( pairmax (ur, post0 (p)), pre 1 (p) );
+enddef;
+
+def getradius (suffix rad) expr g =
+ setsplit (_s) bbox_split;
+ rad := abs (pnt0 (g));
+ for _j = 1 upto length g:
+ rad := emax(rad, abs(pnt[_j] (g)));
+ endfor
+ for _j = 1 upto _s*(length g):
+ ctrlsradius (rad) subpath ((_j-1)/_s, _j/_s) of g;
+ endfor
+enddef;
+
+def ctrlsradius (suffix rad) expr p =
+ rad := emax( emax (rad, abs(post0 (p))), abs(pre1 (p) ))
+enddef;
+
+def safedraw = colorsafedraw (drawcolor) enddef;
+def colorsafedraw (expr clr) expr d =
+ begingroup
+ setpicture (v) picpath d;
+ DoClip (v); coloraddon (clr, v);
+ endgroup
+enddef;
+
+def NoCycle (expr s) expr p =
+ GBwarn s & " cannot be applied to an open path."
+ & " The path will be drawn instead.";
+ safedraw p;
+enddef;
+
+vardef isgray (expr X) = (X > black) and (X < white) enddef;
+
+def safefill = colorsafefill (fillcolor) enddef;
+vardef colorsafefill (expr clr) expr c =
+ if cycle c:
+ setpicture (v) interior c;
+ DoClip (v);
+ if isgray (clr):
+ _subto (active_plane) (v);
+ v := nullpicture;
+ v := shaded (clr) c;
+ fi
+ coloraddon (clr, v);
+ else: NoCycle("fill") c;
+ fi
+enddef;
+def safeunfill expr c =
+ if cycle c: noclip (colorsafefill (background) c);
+ else: NoCycle("unfill") c;
+ fi
+enddef;
+
+def safeclip expr c =
+ if cycle c: clipto (active_plane) c;
+ else: NoCycle("clip") c;
+ fi
+enddef;
+
+def store (suffix fs) expr f =
+hide (
+ if (not path f) and (not pair f):
+ GBerrmsg ("Improper expression type.")
+ "The second argument to `store' must be a path or pair.";
+ fi
+ if not path fs: path fs; fi
+ fs := f
+)
+enddef;
+vardef stored (suffix fs) expr f = store (fs) f; f enddef;
+
+def drawn = colordrawn (drawcolor) enddef;
+vardef colordrawn (expr clr) expr f =
+ colorsafedraw (clr) (zconv (f)); f
+enddef;
+
+def zigzag = colorzigzag (drawcolor) enddef;
+def colorzigzag (expr clr) = colorwiggle (false, clr, 0) enddef;
+def sinewave = colorsinewave (drawcolor) enddef;
+def colorsinewave = colorwiggle (true) enddef;
+
+vardef colorwiggle (expr smth, clr, tens, blen, elen, len, wid) expr f
+=
+ convertpath (g) f;
+ setuplengtharray (cumlen, totlen, ct) g;
+ save B;
+ if cycle f:
+ B := 0;
+ else:
+ B := abs(blen)/_rescale_factor;
+ totlen := totlen - B - abs(elen)/_rescale_factor;
+ fi
+ setnumeric (n) 2*round (totlen/len*_rescale_factor);
+ if n < 2:
+ colorsafedraw (clr) g;
+ else:
+ save T, U, X, Y, Z, p;
+ pair U, X, Y, Z; path p;
+ T := if cycle f: 0 else: gettime (cumlen, ct) (B) fi;
+ Z := pnt[T] (g);
+ p :=if not cycle f: (subpath (0,T) of g)
+ if smth: {curl 0} ..tension tens.. else: -- fi
+ fi
+ for i = 1 upto n:
+ hide(
+ T := gettime (cumlen, ct) (B+(i/n)*totlen);
+ X := Z; Z := pnt[T] (g);
+ Y := .5[X,Z]; U := sgn (Z-X);
+ )
+ (Y + (U zscaled (0, if even i: - fi wid)))
+ if smth: {U}..tension tens.. else: -- fi
+ endfor
+ if cycle f: cycle
+ else: if smth: {curl 0} fi (subpath (T, length g) of g)
+ fi;
+ newpicture (v);
+ if smth:
+ save n, k;
+ n := length p; k = n div 50;
+ for i = 0 step 50 until 50*(k-1):
+ shpath (v, drawpen) (subpath (i,i+50) of p);
+ endfor
+ shpath (v, drawpen) (subpath (50k,n) of p);
+ else: shpath (v, drawpen) (p);
+ fi
+ DoClip(v); coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+def corkscrew = colorcorkscrew (drawcolor) enddef;
+vardef colorcorkscrew (expr clr, tens, blen, elen, len, wid) expr f =
+ convertpath (g) f;
+ setuplengtharray (cumlen, totlen, ct) g;
+ save B;
+ if cycle f:
+ B := 0;
+ else:
+ B := abs(blen)/_rescale_factor;
+ totlen := totlen - B - abs(elen)/_rescale_factor;
+ fi
+ setnumeric (n) round (totlen/len*_rescale_factor);
+ if n < 2:
+ colorsafedraw (clr) g;
+ else:
+ save T, U, X, Y, Z, p;
+ pair U, X, Y, Z; path p;
+ T := if cycle f: 0 else: gettime (cumlen, ct) (B) fi;
+ Z := pnt[T] (g);
+ p :=if (not cycle f) and (B > 0): (subpath (0,T) of g)-- fi
+ for i = 1 upto n:
+ hide(
+ T := gettime (cumlen, ct) (B+(i/n)*totlen);
+ X := Z; Z := pnt[T] (g);
+ Y := .5[X,Z]; U := sgn (Z-X);
+ )
+ (X + (U zscaled (0,-wid))){ U}..tension tens..
+ (Y + (U zscaled (0, wid))){-U}..tension tens..
+ endfor
+ if cycle f: cycle
+ else:
+ {U}(Z + (U zscaled (0,-wid)))
+ if elen <> 0: --(subpath(T, length g) of g) fi
+ fi;
+ newpicture (v);
+ save n, k;
+ n := length p; k = n div 50;
+ for i = 0 step 50 until 50*(k-1):
+ shpath (v, drawpen) (subpath (i,i+50) of p);
+ endfor
+ shpath (v, drawpen) (subpath (50k,n) of p);
+ DoClip(v); coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+def filled = colorfilled (fillcolor) enddef;
+vardef colorfilled (expr clr) expr c =
+ colorsafefill (clr) zconv (c); c
+enddef;
+vardef unfilled expr c = safeunfill zconv (c); c enddef;
+vardef Clip expr c = safeclip zconv (c); c enddef;
+
+numeric shadewd; shadewd := 0.5bp;
+path shadedotpath;
+shadedotpath := fullcircle;
+
+vardef shade (expr sp) expr f =
+ convertpath (g) f;
+ setnumeric (gr) 1 - (.88*abs(shadewd)/sp)**2;
+ if not cycle g: NoCycle("shade") g;
+ elseif gr <= 0: safefill g;
+ else:
+ setbbox (ll, ur) g;
+ ll := floorpair (ll);
+ % setpair (dv) ceiling (sp/(sqrt 2))*(1,1);
+ % test hex spacing:
+ setpair (dv) ( ceiling(.5sp), ceiling(.5sp*sqrt 3) );
+ setpicture (sh) setdot (shadedotpath, abs(shadewd));
+ newpicture (v);
+ fillwith (v) (sh, 2dv, ll, ur);
+ newpicture (w);
+ addto w also v shifted goodpair (dv);
+ DoClip (v); DoClip (w);
+ clipto (v) (g); clipto (w) (g);
+ _orto (active_plane, v);
+ v := nullpicture;
+ _orto (active_plane, w);
+ fi
+ f
+enddef;
+
+polkadotwd := 5bp;
+mindotspace := 1bp;
+path polkadotpath; polkadotpath := fullcircle;
+
+vardef polkadot (expr sp) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("polkadot") g;
+ elseif sp <= emax (2*polkadotwd/3, mindotspace):
+ safefill g;
+ else:
+ setbbox (ll, ur) g;
+ save dx, dy, dshift; pair dshift;
+ dx := sp/2; dy := dx*sqrt 3;
+ dshift := (xpart(ur - ll) mod dx, ypart (ur - ll) mod dy)/2;
+ save p, dims; pair p, dims;
+ p := ll + dshift;
+ dims := 2(dx, dy);
+ setpicture (thepolkadot) setdot (polkadotpath, polkadotwd);
+ newpicture (v);
+ fillwith (v) (thepolkadot, dims, p, ur);
+ fillwith (v) (thepolkadot, dims, p + (dx, dy), ur);
+ DoClip (v); clipto (v) g;
+ if isgray (fillcolor):
+ _subto (active_plane) (v);
+ v := nullpicture;
+ thepolkadot :=
+ shaded (fillcolor) polkadotpath scaled ceiling (polkadotwd);
+ fillwith (v) (thepolkadot, dims, p, ur);
+ fillwith (v) (thepolkadot, dims, p + (dx, dy), ur);
+ DoClip (v); clipto (v) g;
+ fi
+ coloraddon (fillcolor, v);
+ fi
+ f
+enddef;
+
+def thatch = colorthatch (hatchcolor) enddef;
+vardef colorthatch (expr clr) (expr sp, theta) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("hatch") g;
+ elseif sp <= abs(hatchwd): colorsafefill (clr) g;
+ else:
+ newpicture (v);
+ setbbox (ll, ur) g rotated -theta;
+ thatchf (v, identity rotated theta, sp, ll, ur);
+ DoClip (v); clipto (v) (g);
+ coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+def hhatch (expr sp) = thatch (sp, 0) enddef;
+def vhatch (expr sp) = thatch (sp, 90) enddef;
+def lhatch (expr sp) = thatch (sp, -45) enddef;
+def rhatch (expr sp) = thatch (sp, 45) enddef;
+
+def xhatch = colorxhatch (hatchcolor) enddef;
+def colorxhatch (expr clr, sp) =
+ colorthatch (clr) (sp, 45) colorthatch (clr) (sp, -45)
+enddef;
+
+vardef axialgradient (suffix clr) (expr sp, theta) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("axialgradient") g;
+ else:
+ newpicture (_grd);
+ setbbox (ll, ur) g rotated -theta;
+ axialgradientf (clr, _grd) (theta, sp, ll, ur);
+ DoClip (_grd); clipto (_grd) (g);
+ safeunfill g;
+ _orto (active_plane, _grd);
+ fi
+ f
+enddef;
+
+vardef areagradient (suffix clr) (expr sp, tp) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("areagradient") g;
+ else:
+ newpicture (_agr);
+ setbbox (ll, ur) g;
+ areagradientf (clr, _agr) (sp, tp, ll, ur);
+ DoClip (_agr); clipto (_agr) (g);
+ safeunfill g;
+ _orto (active_plane, _agr);
+ fi
+ f
+enddef;
+
+vardef radialgradient (suffix clr) (expr sp, ctr) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("radialgradient") g;
+ else:
+ setpair (_ctr) zconv (ctr);
+ newpicture (_agr);
+ save _rad;
+ getradius (_rad) g shifted - _ctr;
+ radialgradientf (clr, _agr) (sp, _ctr, _rad);
+ DoClip (_agr); clipto (_agr) (g);
+ safeunfill g;
+ _orto (active_plane, _agr);
+ fi
+ f
+enddef;
+
+vardef NoTile (suffix atile) expr g =
+ GBwarn str atile & " is not a valid tile for tess()."
+ & " The path will be drawn instead.";
+ safedraw g;
+enddef;
+vardef tess (suffix atile) expr c =
+ convertpath (_g) c;
+ if not cycle _g: NoCycle("tess") _g;
+ elseif not is_tile (atile): NoTile (atile) _g;
+ else:
+ setbbox (_ll, _ur) _g;
+ newpicture (_ts);
+ fillwith (_ts) (atile.pic, atile.dims, _ll, _ur);
+ DoClip (_ts); clipto (_ts) _g;
+ _orto (active_plane, _ts);
+ fi
+ c
+enddef;
+
+if unknown segment_split: segment_split := 8; fi
+if unknown dashsize: dashsize := 3bp; fi
+if unknown dashgap: dashgap := dashsize + 2penwd; fi
+if unknown dash_finish: dash_finish := .5; fi
+if unknown dash_start: dash_start := .5; fi
+if unknown _rescale_factor: _rescale_factor := 0.1in; fi
+
+numeric last_dot_size; last_dot_size := 0;
+vardef gendashed (suffix pat) expr f =
+ convertpath (_g) f;
+ save _dpat;
+ if not mkdasharrays (pat) (_dpat):
+ GBwarn "Dash pattern " & str pat
+ & " undefined. Path will be drawn instead.";
+ safedraw _g;
+ elseif _dpat.rep < 2:
+ safedraw _g;
+ else:
+ save _dl;
+ forsuffixes _s = start, rep, finish:
+ _dl._s := 0;
+ for i = 1 upto _dpat._s:
+ _dpat._s[i] := _dpat._s[i]/_rescale_factor;
+ _dl._s := _dl._s + _dpat._s[i];
+ endfor
+ endfor
+
+ if _dl.rep = 0:
+ GBwarn "Dash pattern " & str pat & " has length 0. "
+ & "Path will be drawn instead.";
+ safedraw _g;
+ else:
+ setuplengtharray (_cumlen, _totlen, _ct) _g;
+ save _n, _sf, _no_dots;
+ boolean _no_dots; _no_dots := true;
+ _sf := scale_adjust (_n, _dl) (_totlen);
+ if _n < 0: safedraw _g;
+ else:
+ forsuffixes _s = start, rep, finish:
+ for _i = 1 upto _dpat._s:
+ if (_dpat._s[_i] = 0) and _no_dots: _no_dots := false;
+ else: _dpat._s[_i] := _dpat._s[_i]*_sf;
+ fi
+ endfor
+ _dl._s := _dl._s*_sf;
+ endfor
+ if _no_dots:
+ else:
+ if unknown plot_pic:
+ save plot_pic; path plot_pic;
+ plot_pic := dotpath;
+ fi;
+ last_dot_size :=
+ if known plot_pic.size: plot_pic.size else: penwd fi;
+ setpicture (dashingdot) makesymbol (plot_pic, last_dot_size);
+ fi
+ save _t, _d, _v;
+ picture _v; _v := nullpicture;
+ _d0 := 0; _t0 := 0;
+ dashit (_dpat.start) (_v);
+ if _n > 0:
+ save _m; _m := ceiling sqrt(_n);
+ for _j = 0 step _m until _n - 1:
+ for _i = 0 upto _m - 1:
+ exitif (_i + _j) > _n - 1;
+ _d0 := _dl.start + (_j + _i)*_dl.rep;
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ dashit (_dpat.rep) (_v);
+ endfor
+ DoClip (_v);
+ coloraddon (drawcolor, _v);
+ _v := nullpicture;
+ endfor
+ fi
+
+ _d0 := _totlen - _dl.finish;
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ dashit (_dpat.finish) (_v);
+ DoClip (_v);
+ coloraddon (drawcolor, _v);
+ fi
+ fi
+ fi
+ f
+enddef;
+
+vardef makelengtharray (suffix clen) suffix p =
+ setsplit (_s) segment_split;
+ numeric clen[];
+ clen := _s * length p; clen0 := 0;
+ for _i = 1 upto clen:
+ clen[_i] := clen[_i-1] + abs (pnt[_i/_s] (p) - pnt[(_i-1)/_s] (p))
+ / _rescale_factor;
+ endfor
+ clen[clen]
+enddef;
+
+vardef scale_adjust (suffix n, pl) (expr lngth) =
+ n := (lngth - pl.start - pl.finish)/pl.rep;
+ n := if n < 0: -1 else: round(n) fi;
+ lngth/(pl.start + emax (n, 0)*pl.rep + pl.finish)
+enddef;
+
+vardef gettime (suffix arr, ct) (expr lngth) =
+ setnumeric (_gtl) emax (arr[ct], emin (arr[arr], lngth));
+ setsplit (_s) segment_split;
+ forever: exitif inrange (arr[ct], arr[ct+1]) (_gtl);
+ next ct;
+ endfor
+ if arr[ct] = arr[ct+1]: ct
+ else: ( ct + (_gtl - arr[ct]) / (arr[ct+1] - arr[ct]) )
+ fi /_s
+enddef;
+
+def next suffix X = X := X + 1; enddef;
+
+def dashit (suffix pos) (suffix pic) =
+ for _k = 1 upto pos:
+ if odd _k:
+ if pos[_k] = 0:
+ _d1 := _d0; _t1 := _t0;
+ picdot (pic, dashingdot, pnt [_t0] (_g));
+ else:
+ _d1 := _d0 + pos[_k];
+ _t1 := gettime (_cumlen, _ct) (_d1);
+ shpath (pic, drawpen) (subpath (_t0, _t1) of _g);
+ fi
+ else:
+ _d0 := _d1 + pos[_k];
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ fi
+ endfor
+enddef;
+
+def dashpat (suffix pat) (text t) =
+ list (pat) (t);
+ if (pat = 0) or (odd (pat) and (pat > 1)):
+ pat[incr pat] := 0;
+ fi
+enddef;
+
+vardef mkdasharrays (suffix src, dest) =
+ save _bad; boolean _bad; _bad := false;
+ forsuffixes _s = start, rep, finish:
+ numeric dest._s, dest._s[];
+ boolean _bad._s;
+ if knownnumericarray src._s:
+ copyarray (src._s) (dest._s);
+ _bad._s := false;
+ else:
+ _bad := _bad._s := true;
+ fi
+ endfor
+ % _bad = one of the three arrays not copied.
+ if _bad:
+ if knownnumericarray src: _bad := false;
+ if _bad.rep: % make dest.rep = src
+ copyarray (src) (dest.rep);
+ fi
+ if _bad.start: % shrink first dash to get dest.start
+ copyarray (src) (dest.start);
+ dest.start1 := dash_start*src1;
+ fi
+ if _bad.finish: % use partial first dash for dest.finish
+ dest.finish := 1;
+ dest.finish1 := dash_finish*src1;
+ fi
+ fi
+ fi
+ not _bad
+enddef;
+
+vardef Dashed (expr dlen, dgap) expr f =
+ save dashes; dashpat (dashes) (dlen, dgap);
+ gendashed (dashes) f
+enddef;
+
+def DASHED = Dashed enddef;
+ def dashed = Dashed enddef;
+
+vardef doplot (expr spath, sc, dgap) expr f =
+ save dots; dashpat (dots) (0, dgap);
+ setpicture (plot_pic) makesymbol (spath, sc);
+ plot_pic.size := sc;
+ gendashed (dots) f
+enddef;
+
+path dotpath; dotpath := fullcircle;
+def dotted = doplot (dotpath) enddef;
+
+vardef plotnodes (expr symbol, size) expr f =
+ if size > 0:
+ save pln; pair pln[];
+ pln := 0;
+ for _a = 0 upto (length f) if cycle f: - 1 fi:
+ pln[incr pln] := pnt[_a] (f);
+ endfor
+ dosymbols (drawcolor, symbol, size) (pln);
+ fi
+ f
+enddef;
+
+def showcontrols = colorshowcontrols (pointcolor) enddef;
+vardef colorshowcontrols (expr clr, syma, symb, size) expr f =
+ save shpre, shpost;
+ pair shpre[], shpost[];
+ shpre := 0; shpost := 0;
+ for a = 0 upto (length f) if cycle f: - 1 fi:
+ shpre [incr shpre] := pre [a] (f);
+ shpost[incr shpost] := post[a] (f);
+ colorsafedraw (clr)
+ (zconv (shpre[shpre]--pnt[a](f)--shpost[shpost]));
+ endfor
+ if size > 0:
+ if not numeric syma: dosymbols (clr, syma, size) (shpre) ; fi
+ if not numeric symb: dosymbols (clr, symb, size) (shpost); fi
+ fi
+ f
+enddef;
+
+def doubledraw = colordoubledraw (drawcolor) enddef;
+vardef colordoubledraw (expr clr, sep) expr f =
+ convertpath (g) f;
+ colorsafedraw (clr) (parapath ( sep/2) g);
+ colorsafedraw (clr) (parapath (-sep/2) g);
+ f
+enddef;
+
+vardef makesymbol (expr spath, sc) =
+ if picture spath :
+ setpicture (v) spath; mono (v); v
+ elseif path spath: setdot (spath, sc)
+ else:
+ GBwarn "Undefined symbol for plotting, "
+ & "dotpath will be used instead.";
+ setdot (dotpath, sc)
+ fi
+enddef;
+
+vardef bpoint (expr ptwd, b) =
+ fullcircle scaled ptwd shifted b
+enddef;
+
+def pointd (expr ptwd, filled) (text t) =
+ if filled:
+ plotsymbol (SolidCircle, ptwd) (t);
+ else:
+ begingroup;
+ setboolean (clearsymbols) true;
+ plotsymbol (Circle, ptwd) (t);
+ endgroup
+ fi
+enddef;
+
+boolean clearsymbols; clearsymbols := false;
+vardef clearable (expr pth) =
+ if path pth:
+ ( pnt0 (pth) = pnt[length pth] (pth) ) and (not cycle pth)
+ and (length pth > 0)
+ else: false
+ fi
+enddef;
+
+def clearopenpath expr f =
+ if clearable (f): safeunfill f & cycle; fi
+enddef;
+
+def plotsymbol = colorplotsymbol (pointcolor) enddef;
+def colorplotsymbol (expr clr, spath, sc) (text t) =
+ if sc > 0:
+ begingroup
+ setpairs (_cpls) (t);
+ if _cpls > 0: dosymbols (clr, spath, sc) (_cpls); fi
+ endgroup
+ fi
+enddef;
+
+def dosymbols (expr clr, spath, sc) (suffix arr) =
+ if clearsymbols and clearable (spath):
+ addsymbols (background, makesymbol (spath&cycle, sc)) (arr);
+ fi
+ addsymbols (clr, makesymbol (spath, sc)) (arr);
+enddef;
+
+def addsymbols (expr clr, symb) (suffix arr) =
+ newpicture (_pls);
+ for _idx = 1 upto arr:
+ picdot (_pls, symb, zconv (arr[_idx]));
+ endfor
+ DoClip (_pls); coloraddon (clr, _pls);
+enddef;
+
+def putimage (suffix pic) (text t) =
+ newpicture (_pti);
+ for _itm = t:
+ addto _pti also
+ (pic shifted goodpair (zconv (_itm)));
+ DoClip (_pti); addto active_plane also _pti;
+ _pti := nullpicture;
+ endfor
+ mono active_plane
+enddef;
+
+def arrowdraw (expr hlen) (expr f) =
+ store (curpath) headpath (hlen, 0, 0) drawn f;
+enddef;
+
+def xaxis (expr hlen) = arrowdraw (hlen) ((xneg, 0)--(xpos, 0));
+enddef;
+def yaxis (expr hlen) = arrowdraw (hlen) ((0, yneg)--(0, ypos));
+enddef;
+def axes (expr hlen) = xaxis (hlen); yaxis (hlen); enddef;
+
+laxis := baxis := raxis := taxis := 0;
+
+vardef xlow = xneg + laxis enddef;
+vardef xhigh = xpos - raxis enddef;
+vardef ylow = yneg + baxis enddef;
+vardef yhigh = ypos - taxis enddef;
+
+vardef axisline.x = (xlow, 0)--(xhigh, 0) enddef;
+vardef axisline.y = (0, ylow)--(0, yhigh) enddef;
+vardef axisline.l = axisline.y shifted (xlow, 0) enddef;
+vardef axisline.b = axisline.x shifted (0, ylow) enddef;
+vardef axisline.r = axisline.y shifted (xhigh, 0) enddef;
+vardef axisline.t = axisline.x shifted (0, yhigh) enddef;
+
+vardef axis@# (expr len) = headpath (len, 0, 0) axisline@# enddef;
+
+vardef borderrect =
+ rect((xlow,ylow),(xhigh,yhigh))
+enddef;
+
+vardef between (expr A, B, X) = (A < X) and (X < B) enddef;
+vardef inrange (expr A, B, X) = (A <= X) and (X <= B) enddef;
+
+vardef inbounds (expr Z) =
+ inrange (xlow, xhigh) (xpart Z) and inrange (ylow, yhigh) (ypart Z)
+enddef;
+
+tertiarydef X isbetween P = between (xpart P, ypart P, X) enddef;
+tertiarydef X isinrange P = inrange (xpart P, ypart P, X) enddef;
+tertiarydef P contains X = between (xpart P, ypart P, X) enddef;
+
+numeric inside, outside, centered, onleft, onright, ontop, onbottom;
+inside := -2;
+outside := -1;
+onright := 1;
+onleft := 2;
+centered := .5[onright, onleft];
+onbottom := onright;
+ontop := onleft;
+ltick := rtick := ttick := btick := inside;
+xtick := ytick := centered;
+
+vardef axismarks (expr inang, tp, loc, pdir) (expr len) (text t) =
+ save _tp, _U, _P, _tic, _ticang;
+ pair _U, _P; path _tic;
+ _ticang := if tp < 0: inang else: 90 fi;
+ _tp := abs(tp) - 1;
+ _U := unitvector (vconv (pdir)) rotated _ticang;
+ _tic := (-_U--(0,0)) shifted (_tp*_U) scaled len;
+ for _a = t:
+ safedraw (_tic shifted zconv (loc + _a*pdir));
+ endfor
+enddef;
+
+def xmarks = axismarks ( 90, xtick, origin, right) enddef;
+def ymarks = axismarks (-90, ytick, origin, up) enddef;
+def lmarks = axismarks (-90, ltick, (xlow, 0), up) enddef;
+def bmarks = axismarks ( 90, btick, (0, ylow), right) enddef;
+def rmarks = axismarks ( 90, rtick, (xhigh, 0), up) enddef;
+def tmarks = axismarks (-90, ttick, (0, yhigh), right) enddef;
+
+path griddotpath; griddotpath := fullcircle;
+def grid = vargrid (0.5bp) enddef;
+vardef vargrid (expr dsize, xsp, ysp) =
+ save gdot, gridpic; picture gdot, gridpic;
+ gdot := setdot (griddotpath, dsize);
+ gridpic := nullpicture;
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ for m = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ picdot (gridpic, gdot, zconv ((n*xsp, m*ysp)));
+ endfor
+ endfor
+ coloraddon (pointcolor, gridpic);
+enddef;
+def vgrid = vargrid enddef;
+
+def hgridlines (expr ysp) =
+ for n = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ safedraw zconv ((xlow, n*ysp)--(xhigh, n*ysp));
+ endfor
+enddef;
+def vgridlines (expr xsp) =
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ safedraw zconv ((n*xsp, ylow)--(n*xsp, yhigh));
+ endfor
+enddef;
+def gridlines (expr xsp, ysp) =
+ vgridlines (xsp); hgridlines (ysp);
+enddef;
+
+def vectorfield (expr len, xsp, ysp) (text fcn) (text cond) =
+ save _vf, _is_OK;
+ vardef _vf (expr x,y) = ((0,0)--(fcn)) shifted (x,y) enddef;
+ vardef _is_OK (expr x,y) = cond enddef;
+ mkvectorfield (len, xsp, ysp) (_vf, _is_OK);
+enddef;
+
+vardef mkvectorfield (expr len, xsp, ysp) (suffix vf, isOK) =
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ for m = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ if isOK (n*xsp,m*ysp): arrowdraw (len) (vf(n*xsp,m*ysp)); fi
+ endfor
+ endfor
+enddef;
+
+def plrvectorfield (expr len, rsp, tsp) (text fcn) (text cond) =
+ save _vf, _is_OK, _A, _B, _C, _D;
+ _A := xlow; _B := xhigh;
+ _C := ylow; _D := yhigh;
+ vardef _vf (expr r,t) = ((0,0)--(fcn)) shifted (r*dir t) enddef;
+ vardef _is_OK (expr r,t) =
+ save _X, _Y; _X := r*cosd t; _Y := r*sind t;
+ (cond) and between (_A, _B) (_X) and between (_C, _D) (_Y)
+ enddef;
+ mkplrvectorfield (len, rsp, tsp) (_vf, _is_OK);
+enddef;
+
+vardef mkplrvectorfield (expr len, rsp, tsp) (suffix vf, isOK) =
+ save rmin, rmax, tmin, tmax;
+ getpolarbounds;
+ if rmin = 0:
+ if isOK (0,tmin): arrowdraw (len) (vf (0,tmin)); fi
+ rmin := rsp;
+ fi
+ for n = ceiling (rmin/rsp) upto floor (rmax/rsp):
+ for m = ceiling (tmin/tsp) upto floor (tmax/tsp):
+ if isOK (n*rsp,m*tsp): arrowdraw (len) (vf (n*rsp,m*tsp)); fi
+ endfor
+ endfor
+enddef;
+
+def patcharcs (suffix X) (expr rstart, rstop, rstep, tstart, tstop) =
+ for rad = (if rstart = 0: rstep else: rstart fi)
+ step rstep until rstop:
+ orto (X, picpath zconv (arcplr (origin, tstart, tstop, rad)) );
+ endfor
+enddef;
+def patchrays (suffix X) (expr tstart, tstop, tstep, rstart, rstop) =
+ for _ang = tstart step tstep until tstop:
+ orto (X) (picpath zconv ((rstart*dir _ang)--(rstop*dir _ang)));
+ endfor
+enddef;
+
+def plrpatch (expr rstart, rstop, rstep, tstart, tstop, tstep) =
+begingroup
+ newpicture (v);
+ patcharcs (v) (rstart, rstop, rstep, tstart, tstop);
+ coloraddon (drawcolor, v);
+ v := nullpicture;
+ patchrays (v) (tstart, tstop, tstep, rstart, rstop);
+ coloraddon (drawcolor, v);
+endgroup
+enddef;
+
+def gridarcs (expr rstep) =
+ beginpolargrid;
+ if rmin = 0:
+ picdot (gridpic, setdot (griddotpath, penwd), zconv (origin));
+ fi
+ rmin := rstep * floor (rmin/rstep + 1);
+ rmax := rstep * ceiling (rmax/rstep - 1);
+ patcharcs (gridpic) (rmin, rmax, rstep, tmin, tmax);
+ endpolargrid (drawcolor, .5penwd);
+enddef;
+
+def gridrays (expr tstep) =
+ beginpolargrid;
+ tmin := tstep * ceiling (tmin/tstep);
+ tmax := tstep * floor (tmax/tstep);
+ patchrays (gridpic) (tmin, tmax, tstep, rmin, rmax);
+ endpolargrid (drawcolor, .5penwd);
+enddef;
+
+def polargrid (expr rstep, tstep) =
+ gridarcs (rstep); gridrays (tstep);
+enddef;
+
+def polargridpoints (expr dsize, rstep, tstep) =
+ beginpolargrid;
+ setpicture (gdot) setdot (griddotpath, dsize);
+ if rmin = 0:
+ picdot (gridpic, gdot, zconv (origin));
+ rmin := rstep;
+ fi
+ for n = ceiling (rmin/rstep) upto floor (rmax/rstep):
+ for m = ceiling (tmin/tstep) upto floor (tmax/tstep):
+ picdot ( gridpic, gdot, zconv ( polar ((n*rstep, m*tstep)) ) );
+ endfor
+ endfor
+ endpolargrid (pointcolor, .5dsize);
+enddef;
+
+def beginpolargrid =
+begingroup;
+ save rmax, rmin, tmax, tmin;
+ getpolarbounds;
+ newpicture (gridpic);
+enddef;
+
+def getpolarbounds =
+ save p, r, t;
+ pair p[];
+ p0 := (xneg, yneg); p1 := (xneg, ypos);
+ p2 := (xpos, ypos); p3 := (xpos, yneg);
+ r0 := abs(p0); rmax := r0;
+ for j = 1 upto 3:
+ r[j] := abs(p[j]);
+ if rmax < r[j]: rmax := r[j]; fi
+ endfor
+ rmin := 0;
+ if between (xneg, xpos) (0) and between (yneg, ypos) (0):
+ tmin := 0; tmax := 360;
+ elseif (p0 = origin): tmin := 0; tmax := 90;
+ elseif (p1 = origin): tmin := -90; tmax := 0;
+ elseif (p2 = origin): tmin := -180; tmax := -90;
+ elseif (p3 = origin): tmin := 90; tmax := 180;
+ else:
+ tmax := tmin := t0 := angle p0;
+ for j = 1 upto 3:
+ t := t0 + anglefromto (p0, p[j]);
+ if tmax < t: tmax := t; fi
+ if tmin > t: tmin := t; fi
+ endfor
+ if between (xneg, xpos) (0):
+ rmin := emin (abs(yneg), abs(ypos));
+ elseif between (yneg, ypos) (0):
+ rmin := emin (abs(xneg), abs(xpos));
+ else:
+ rmin := min (r0, r1, r2, r3);
+ fi
+ fi
+enddef;
+
+
+def endpolargrid (expr clr, size)=
+ clipto (gridpic) rect ( zconv ((xneg, yneg)) - size*(1,1),
+ zconv ((xpos, ypos)) + size*(1,1) );
+ coloraddon (clr, gridpic);
+ endgroup
+enddef;
+
+vardef polarpatch (expr rstart, rstop, rstep, tstart, tstop, tstep) =
+ plrpatch (rstart, rstop, rstep, tstart, tstop, tstep);
+ safedraw zconv ( arcplr (origin, tstart, tstop, rstop) );
+ safedraw zconv ( ((rstart, 0)--(rstop, 0)) rotated tstop );
+enddef;
+
+vardef rect (expr ll, ur) =
+ ll--(xpart ur, ypart ll)--ur--(xpart ll, ypart ur)--cycle
+enddef;
+vardef triangle (expr A, B, C) = A--B--C--cycle enddef;
+
+vardef regularpolygon (expr n) (suffix Bob) (text eqns) =
+ pair Bob[]; Bob := emax (round (abs (n)), 2);
+ eqns;
+ for _uncle = 1 upto Bob - 1:
+ (Bob1 - Bob0) rotated (360/Bob*_uncle) = Bob[_uncle+1] - Bob0;
+ endfor
+ mkpoly (true) (Bob)
+enddef;
+
+vardef altitudept expr n of t =
+ save A, B, C, zz; pair A, B, C, zz;
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ zz = whatever[B,C];
+ zz = pnt[n](t) + whatever*((C-B) rotated 90);
+ zz
+enddef;
+
+vardef altitude expr n of t =
+ (pnt[n](t))--(altitudept n of t)
+enddef;
+
+vardef medianpt expr n of t =
+ 0.5[pnt[n + 1] (t), pnt[n + 2] (t)]
+enddef;
+
+vardef median expr n of t =
+ (pnt[n](t))--(medianpt n of t)
+enddef;
+
+vardef anglebisectorpt expr n of t =
+ save A, B, C; pair A, B, C;
+ A := pnt[n ] (t);
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ save zz; pair zz;
+ zz = whatever[B,C];
+ zz = A + whatever*((B-A) rotated (.5*cornerangle (A,B,C)));
+ zz
+enddef;
+
+vardef anglebisector expr n of t =
+ (pnt[n](t))--(anglebisectorpt n of t)
+enddef;
+
+vardef anglefromto (expr u, v) =
+ if (u = origin) or (v = origin): 0
+ else: angle (v rotated (-angle u))
+ fi
+enddef;
+
+vardef cornerangle (expr A, B, C) =
+ if (A = B) or (A = C) :
+ if (B = C) : 60
+ else: 90
+ fi
+ else: anglefromto (B - A, C - A)
+ fi
+enddef;
+
+vardef mkpath (expr smooth, tens, cyclic) (suffix pts) =
+ if smooth: mksmooth (tens)
+ else: mkpoly
+ fi (cyclic, pts)
+enddef;
+
+vardef mkpoly (expr cyclic) (suffix pts) =
+ for _i = 1 upto pts-1: pts[_i]-- endfor
+ pts[pts] if cyclic: -- cycle else: {0,0} fi
+enddef;
+
+vardef polyline (expr cyclic) (text t) =
+ setpairs (_pl) (t);
+ if _pl=0: NoPoints ("polyline", _pl); fi
+ mkpoly (cyclic, _pl)
+enddef;
+
+def NoPoints (expr s) (suffix pts) =
+ GBwarn s & " attempted with empty list."; pts[incr pts] := origin;
+enddef;
+
+vardef turtle (text t) =
+ setnumeric (_tu) 0;
+ setpair (_tmp) origin;
+ pair _tu[];
+ for _a = t:
+ _tmp := _tmp + _a;
+ _tu[incr _tu] := _tmp;
+ endfor
+ if _tu = 0: NoPoints("turtle", _tu); fi
+ mkpoly (false, _tu)
+enddef;
+
+vardef brownianpath (expr start, num, sc) =
+ setnumeric (_brp) 1;
+ setpair (_tmp) start;
+ pair _brp[]; _brp1 := _tmp;
+ for _idx := 1 upto num:
+ _tmp := _tmp + sc/(sqrt 2)*(normaldeviate,normaldeviate);
+ _brp[incr _brp] := _tmp;
+ endfor
+ mkpoly (false, _brp)
+enddef;
+vardef randomwalk (expr start, num, dst) =
+ setnumeric (_rdw) 1;
+ setpair (_tmp) start;
+ pair _rdw[]; _rdw1 := _tmp;
+ for _idx := 1 upto num:
+ _tmp := _tmp + dst*dir(uniformdeviate(360));
+ _rdw[incr _rdw] := _tmp;
+ endfor
+ mkpoly (false, _rdw)
+enddef;
+vardef browniangraph (expr num, scst) =
+ setnumeric (_brg) 1;
+ pair _tmp, _brg[]; _tmp := _brg1 := (0,0);
+ for _idx := 1 upto num:
+ _tmp := _tmp + scst*(1,normaldeviate);
+ _brg[incr _brg] := _tmp;
+ endfor
+ mkpoly (false, _brg)
+enddef;
+
+vardef mksmooth (expr tens, cyclic) (suffix pts) =
+ if pts = 1: onepointpath (cyclic, pts1)
+ else:
+ settension (_tn) tens; fixtension (_tn);
+ pts1 if cyclic: {pts[2]-pts[pts]} fi
+ for _i = 2 upto pts-1:
+ ..tension _tn..pts[_i]{pts[_i+1]-pts[_i-1]}
+ endfor
+ ..tension _tn..pts[pts]
+ if cyclic: {pts[1]-pts[pts-1]}..tension _tn..cycle fi
+ fi
+enddef;
+
+vardef mktenser (expr tens, cyclic) (suffix pts) =
+ if pts = 1: onepointpath (cyclic, pts1)
+ else:
+ settension (_tn) tens; fixtension (_tn);
+ pts1 if cyclic: {pts[2]-pts[pts]} fi
+ for _i = 2 upto pts-1:
+ ..tension atleast _tn..pts[_i]{pts[_i+1]-pts[_i-1]}
+ endfor
+ ..tension atleast _tn..pts[pts]
+ if cyclic: {pts[1]-pts[pts-1]}..tension atleast _tn..cycle fi
+ fi
+enddef;
+
+vardef mkconvex (expr tens, cyclic) (suffix pts) =
+ save _B, _d, _tmp; pair _d[];
+ settension (_tn) tens; fixtension (_tn);
+ if pts < 4: mktenser (_tn, cyclic) (pts)
+ else:
+ for _j = 2 upto pts - 1:
+ _B[_j] := sqrt(abs((pts[_j]-pts[_j-1])xprod(pts[_j+1]-pts[_j])));
+ endfor
+ if cyclic:
+ _B1 := sqrt(abs((pts1 - pts[pts])xprod(pts2 - pts1)));
+ _B[pts] := sqrt(abs((pts[pts]-pts[pts-1])xprod(pts1 - pts[pts])));
+ else:
+ _B1 := _B2;
+ _B[pts] := _B[pts-1];
+ fi
+ for _j = 2 upto pts - 1:
+ _tmp := _B[_j-1] + _B[_j+1];
+ _d[_j] :=
+ if _tmp = 0: origin % signal to use curl1
+ else:
+ ( _B[_j+1]*(pts[_j] - pts[_j-1]) +
+ _B[_j-1]*(pts[_j+1] - pts[_j]) )/_tmp
+ fi;
+ endfor
+ if cyclic:
+ _tmp := _B[pts] + _B2;
+ _d1 :=
+ if _tmp = 0: origin
+ else:
+ (_B2*(pts1 - pts[pts]) + _B[pts]*(pts2 - pts1))/_tmp
+ fi;
+ _tmp := _B[pts-1] + _B1;
+ _d[pts] :=
+ if _tmp = 0: origin
+ else:
+ ( _B1*(pts[pts] - pts[pts-1]) +
+ _B[pts-1]*(pts1 - pts[pts]) )/_tmp
+ fi;
+ else:
+ _d1 := origin; _d[pts] := origin;
+ fi
+ pts1
+ for _j = 1 upto pts-1:
+ {if _d[_j] = origin: curl1 else: _d[_j] fi}
+ ..tension atleast _tn..pts[_j+1]
+ endfor
+ {if _d[pts] = origin: curl1 else: _d[pts] fi}
+ if cyclic: ..tension atleast _tn..cycle fi
+ fi
+enddef;
+
+numeric default_tension; default_tension := 1;
+def curve = tcurve (default_tension) enddef;
+vardef tcurve (expr tens, cyclic) (text t) =
+ setpairs (_tc) (t);
+ if _tc=0: NoPoints("curve", _tc); fi
+ mksmooth (tens, cyclic, _tc)
+enddef;
+
+def ccurve = tccurve (default_tension) enddef;
+vardef tccurve (expr tens, cyclic) (text t) =
+ setuniquepairs (_tcc) (t);
+ if _tcc=0: NoPoints("ccurve", _tcc); fi
+ mkconvex (tens, cyclic, _tcc)
+enddef;
+
+vardef mkbezier (expr tens, cyclic) (suffix pts) =
+ settension (_tn) tens; fixtension (_tn);
+ pts1
+ for _i = 2 upto pts: ..tension _tn..pts[_i] endfor
+ if cyclic: ..tension _tn..cycle else: {0,0} fi
+enddef;
+
+def bezier = tbezier (default_tension) enddef;
+vardef tbezier (expr tens, cyclic) (text t) =
+ setpairs (_tbs) (t);
+ if _tbs=0: NoPoints ("bezier", _tbs); fi
+ mkbezier (tens, cyclic) (_tbs)
+enddef;
+
+vardef mkqbezier (expr cyclic) (suffix pts) =
+ pts1
+ if pts=1: {0,0}
+ else:
+ for _i = 2 step 2 until pts - 1:
+ ..controls 1/3[pts[_i], pts[_i-1]]
+ and 1/3[pts[_i], pts[_i+1]].. pts[_i+1]
+ endfor
+ if cyclic:
+ ..controls 1/3[ pts[pts], pts[pts - 1] ]
+ and 1/3[ pts[pts], pts1 ]..cycle
+ fi
+ fi
+enddef;
+
+vardef qbezier (expr cyclic) (text t) =
+ setpairs (_qbz) (t);
+ if _qbz=0: NoPoints ("qbezier", _qbz);
+ else:
+ if (cyclic and odd _qbz) or (not cyclic and even _qbz):
+ _qbz[incr _qbz] := _qbz[_qbz-1];
+ fi
+ mkqbezier (cyclic) (_qbz)
+ fi
+enddef;
+
+vardef mkcbezier (expr cyclic) (suffix pts) =
+ pts1
+ if pts=1: {0,0}
+ else:
+ for _i = 1 step 3 until pts - 3:
+ ..controls pts[_i+1] and pts[_i+2] .. pts[_i+3]
+ endfor
+ if cyclic:
+ ..controls pts[pts - 1] and pts[pts]..cycle
+ fi
+ fi
+enddef;
+
+vardef cbezier (expr cyclic) (text t) =
+ setpairs (_cbz) (t);
+ if _cbz=0: NoPoints ("qbezier", _cbz);
+ else:
+ % Need 0 mod 3 for cyclic, otherwise 1 mod 3
+ setnumeric (_mdt) _cbz mod 3;
+ if cyclic:
+ if _mdt <> 0: _cbz[incr _cbz] := _cbz[_cbz-1]; fi
+ if _mdt = 1 : _cbz[incr _cbz] := _cbz1; fi
+ else: % need 1 more, duplicate next to last
+ if _mdt = 0:
+ _cbz := _cbz + 1;
+ _cbz[_cbz] := _cbz[_cbz-1];
+ _cbz[_cbz-1] := _cbz[_cbz-2];
+ fi
+ if _mdt = 2: % need 2 more, duplicate last 2.
+ _cbz := _cbz + 2; % add 2 slots
+ _cbz[_cbz] := _cbz[_cbz-2]; % fill them
+ _cbz[_cbz-1] := _cbz[_cbz-2]; % with last node
+ _cbz[_cbz-2] := _cbz[_cbz-3]; % orig last slot = orig previous.
+ fi
+ fi
+ mkcbezier (cyclic) (_cbz)
+ fi
+enddef;
+
+vardef fcncontrol (expr ftens, X, Y, Z) =
+ Y if (xpart(Z-Y) <> 0) and (xpart(Y-X) <> 0):
+ + xpart(Z-Y)/3/xpart(Z-X)*(Z - X)/ftens fi
+enddef;
+
+vardef mkfcnpath (expr ftens) (suffix q) =
+ settension (_tn) ftens;
+ if _tn <= 0: _tn := 1; fi
+ for _i = 1 upto q - 1:
+ q[_i]..controls fcncontrol (_tn) (q[_i-1], q[_i], q[_i+1])
+ and fcncontrol (_tn) (q[_i+2], q[_i+1], q[_i])..
+ endfor
+ q[q]{0,0}
+enddef;
+
+def fcncurve = functioncurve (default_tension) enddef;
+def tfcncurve = functioncurve enddef;
+vardef functioncurve (expr ftens) (text t) =
+ settension (_ftens) ftens; if _ftens < 1/3: _ftens := 1/3; fi
+ setuniquepairs (_fc) (t);
+ if _fc=0: NoPoints ("functioncurve", _fc); fi
+ if _fc > 1: _fc0 := _fc1; _fc[_fc+1] := _fc[_fc]; fi
+ mkfcnpath (_ftens) (_fc)
+enddef;
+
+def openqbs = qspline (false) enddef;
+def closedqbs = qspline (true) enddef;
+
+vardef mkqbs (suffix b) =
+ 0.5[ b1, b2]
+ if b<3: {0,0}
+ else:
+ for _i = 2 upto b-1:
+ ..controls 1/6[ b[_i], b[_i-1] ] and 1/6[ b[_i], b[_i+1] ]..
+ 0.5[ b[_i], b[_i+1] ]
+ endfor
+ fi
+enddef;
+
+vardef qspline (expr cyclic) (text t) =
+ setpairs (_qs) (t);
+ if _qs=0: NoPoints ("qspline", _qs); fi
+ if _qs=1: _qs[incr _qs] := _qs1; fi
+ if cyclic:
+ _qs[incr _qs] := _qs1; _qs[incr _qs] := _qs2;
+ fi
+ mkqbs (_qs) if cyclic: & cycle fi
+enddef;
+
+vardef mkcbs (suffix b) =
+ (b[1]+4b[2]+b[3])/6
+ if b < 4: {0,0}
+ else:
+ for _i = 3 upto b-1:
+ ..controls 1/3[ b[_i-1], b[_i] ] and 1/3[ b[_i], b[_i-1] ]
+ .. (b[_i-1] + 4b[_i] + b[_i+1])/6
+ endfor
+ fi
+enddef;
+
+def mkopencbs = mkcbs enddef;
+vardef mkclosedcbs (suffix b) =
+ mkcbs (b) & opencbs (b[b-2],b[b-1],b[b], b1, b2, b3) & cycle
+enddef;
+
+def opencbs = cspline (false) enddef;
+def closedcbs = cspline (true) enddef;
+
+vardef cspline (expr cyclic) (text t) =
+ setpairs (_cs) (t);
+ if _cs=0: NoPoints ("cspline", _cs); fi
+ for _idx = _cs upto 2: _cs[incr _cs] := _cs[_idx]; endfor
+ if cyclic:
+ for _idx = 1 upto 3: _cs[incr _cs] := _cs[_idx]; endfor
+ fi
+ mkcbs (_cs) if cyclic: & cycle fi
+enddef;
+
+def init_spline_eqns (suffix pts) =
+ save _spl_pre, _spl_post;
+ pair _spl_pre[], _spl_post[];
+ for j= 2 upto pts - 1:
+ _spl_post[j] + _spl_pre[j] = 2pts[j];
+ _spl_pre[j+1]+2_spl_pre[j] = 2_spl_post[j]+_spl_post[j-1];
+ endfor
+enddef;
+
+def closed_spline_eqns (suffix pts) =
+ _spl_post1 + _spl_pre1 = 2pts1;
+ _spl_post[pts] + _spl_pre[pts] = 2pts[pts];
+ _spl_pre2 + 2_spl_pre1 = 2_spl_post1 + _spl_post[pts];
+ _spl_pre1+2_spl_pre[pts] = 2_spl_post[pts]+_spl_post[pts-1];
+enddef;
+
+def relaxed_spline_eqns (suffix pts) =
+ _spl_pre2 + pts1 = 2_spl_post1;
+ pts[pts] + _spl_post[pts-1] = 2_spl_pre[pts];
+enddef;
+
+vardef mksplinepath (expr closed) (suffix pts) =
+ pts1..controls _spl_post1 and
+ for j = 2 upto pts if not closed: -1 fi:
+ _spl_pre[j]..pts[j]..controls _spl_post[j] and
+ endfor
+ if closed: _spl_pre1..cycle else: _spl_pre[pts]..pts[pts] fi
+enddef;
+
+def mkspline (expr closed) (suffix pts) =
+ init_spline_eqns (pts);
+ if closed: closed_spline_eqns (pts);
+ else: relaxed_spline_eqns (pts);
+ fi
+ mksplinepath (closed) (pts)
+enddef;
+
+vardef dospline (expr closed) (text the_list) =
+ setpairs (_sp) (the_list);
+ if _sp=0: NoPoints ("dospline", _sp); fi
+ if _sp=1: _sp[incr _sp] := _sp1; fi
+ mkspline (closed) (_sp)
+enddef;
+
+def init_fcnspl_eqns (suffix pts) =
+ save _dx, _sl; numeric _dx[], _sl[];
+ _dx1 := xpart (pts2 - pts1);
+ for j = 2 upto pts - 1:
+ _dx[j] := xpart (pts[j+1] - pts[j]);
+ _sl[j + 1]*_dx[j] + _sl[j-1]*_dx[j-1] + 2_sl[j]*(_dx[j] + _dx[j-1])
+ = 3*ypart(pts[j+1] - pts[j-1]);
+ endfor
+enddef;
+
+def periodic_fcnspl_eqns (suffix pts) =
+ _sl1 = _sl[pts];
+ _sl2*_dx1 + 2_sl1*_dx1 + 2_sl[pts]*_dx[pts-1] + _sl[pts-1]*_dx[pts-1]
+ = 3 * ypart (pts[2] - pts[pts-1]);
+enddef;
+
+def relaxed_fcnspl_eqns (suffix pts) =
+ _sl2*_dx1 + 2_sl1*_dx1 = 3 * ypart(pts2 - pts1);
+ _sl[pts-1]*_dx[pts-1] + 2_sl[pts]*_dx[pts-1]
+ = 3 * ypart(pts[pts] - pts[pts-1]);
+enddef;
+
+vardef mkfcnsplpath (suffix pts) =
+ pts1..controls (pts1 + (1, _sl1)/3*_dx1) and
+ for j = 2 upto pts - 1:
+ (pts[j] - (1, _sl[j])/3*_dx[j-1]) ..pts[j]..
+ controls (pts[j] + (1,_sl[j])/3*_dx[j]) and
+ endfor
+ (pts[pts] - (1,_sl[pts])*_dx[pts-1]/3)..pts[pts]
+enddef;
+
+vardef mkfcnspline (expr periodic) (suffix pts) =
+ init_fcnspl_eqns (pts);
+ if periodic: periodic_fcnspl_eqns (pts);
+ else: relaxed_fcnspl_eqns (pts);
+ fi
+ mkfcnsplpath (pts)
+enddef;
+
+vardef fcnspline (expr periodic) (text the_list) =
+ setpairs (_fs) (the_list);
+ if _fs<2:
+ if _fs=0: NoPoints ("fcnspline", _fs); fi
+ onepointpath (false, _fs1)
+ else:
+ mkfcnspline (periodic) (_fs)
+ fi
+enddef;
+
+vardef mkarc (expr center, begpt, endpt, sweep) =
+ if (sweep = 0): begpt--endpt
+ else:
+ setnumeric (n) ceiling (abs(sweep)/45);
+ setpair (d) (begpt - center) rotated (signof (sweep) 90);
+ begpt{d}
+ for j = 1 upto n-1:
+ ..(begpt rotatedabout (center, j/n*sweep)){d rotated (j/n*sweep)}
+ endfor ..endpt{d rotated sweep}
+ fi
+enddef;
+
+vardef arc (expr center, begpt, sweep) =
+ if (center = begpt) or (sweep = 0): begpt--begpt
+ else:
+ mkarc (center, begpt, begpt rotatedabout (center, sweep), sweep)
+ fi
+enddef;
+def arccps = arc enddef;
+
+vardef arcpps (expr begpt, endpt, sweep) =
+ if (begpt = endpt) or (sweep = 0): begpt--endpt
+ else:
+ setpair (cd) unitvector (endpt-begpt);
+ if abs(sweep) <= 45:
+ begpt{cd rotated (-sweep/2)}..endpt{cd rotated (sweep/2)}
+ elseif abs(sweep) <= 90:
+ save m; pair m;
+ m = begpt + whatever*( cd rotated (-sweep/4));
+ m = 0.5[begpt, endpt] + whatever*(cd rotated 90);
+ begpt{cd rotated (-sweep/2)}..m{cd}..endpt{cd rotated (sweep/2)}
+ else:
+ setnumeric (ang) 90 - ((sweep/2) mod 180);
+ if abs(ang) = 90:
+ GBwarn "undefined arc. A line segment will be used instead.";
+ begpt--endpt
+ else:
+ save c; pair c;
+ c = begpt + whatever*(cd rotated ang);
+ c = if abs(ang) < 30:
+ (0.5)[begpt, endpt] + whatever*(cd rotated 90)
+ else:
+ endpt + whatever*(-cd rotated -ang)
+ fi;
+ mkarc (c, begpt, endpt, sweep)
+ fi
+ fi
+ fi
+enddef;
+
+vardef arcpp (expr small, begpt, endpt, rad) =
+ save full, diam, chord, ang;
+ full := signof (rad) 360;
+ diam := 2rad;
+ chord := abs(endpt-begpt);
+ if chord < abs(diam):
+ ang := if not small: full - fi 2*asin (chord/diam);
+ else: ang := signof (rad) 180;
+ fi
+ arcpps (begpt, endpt, ang)
+enddef;
+def arcppr (expr begpt, endpt, rad, small) =
+ arcpp (small, begpt, endpt, rad)
+enddef;
+
+vardef arcplr (expr center, frtheta, totheta, rad) =
+ if rad = 0: center--center
+ else:
+ mkarc (center, center + rad*dir frtheta,
+ center + rad*dir totheta, totheta - frtheta)
+ fi
+enddef;
+
+vardef arcalt (expr center, radius, frtheta, totheta) =
+ arcplr (center, frtheta, totheta, radius)
+enddef;
+
+vardef arcppp (expr first, second, third) =
+ arcpps (first, second, 2*cornerangle (third, first, second)) &
+ arcpps (second, third, 2*cornerangle (first, second, third))
+enddef;
+
+vardef ellipse (expr center, radx, rady, angle) =
+ fullcircle xscaled (2*radx) yscaled (2*rady) rotated angle
+ shifted center
+enddef;
+
+vardef circle (expr center, rad) =
+ fullcircle scaled (2*rad) shifted center
+enddef;
+
+vardef circlecp (expr center, point) =
+ mkarc (center, point, point, 360) & cycle
+enddef;
+
+vardef circleppp (expr one, two, three) =
+ arcpps (one, two, 2*cornerangle (three, one, two))
+ & arcpps (two, three, 2*cornerangle (one, two, three))
+ & arcpps (three, one, 2*cornerangle (two, three, one))
+ & cycle
+enddef;
+
+vardef circlepps (expr one, two, sweep) =
+ save ang, full;
+ full := signof (sweep) 360;
+ ang := sweep mod full;
+ arcpps (one, two, ang) & arcpps (two, one, full - ang) & cycle
+enddef;
+
+vardef circlepp (expr small, one, two, rad) =
+ arcpp (small, one, two, rad) & arcpp (not small, two, one, rad)
+ & cycle
+enddef;
+
+def circleppr (expr one, two, rad, small) =
+ circleppr (one, two, rad, small)
+enddef;
+
+vardef quarterellipse(expr A,B,C) =
+ save T_;
+ transform T_;
+ (1,0) transformed T_ = A;
+ (1,1) transformed T_ = B;
+ (0,1) transformed T_ = C;
+ quartercircle scaled 2 transformed T_
+enddef;
+
+vardef halfellipse (expr A,B,C) =
+ save P_; pair P_;
+ P_ = (C - A)/2;
+ quarterellipse (A, B - P_, B) & quarterellipse (B, B + P_, C)
+enddef;
+
+vardef fullellipse (expr C, A, B) =
+ save P_; pair P_;
+ P_ := 2[A,C];
+ halfellipse (A,B,P_) & halfellipse (P_,2[B,C],A) & cycle
+enddef;
+
+vardef pathcenter expr p =
+ save a, cntr, n; pair cntr, a[];
+ n := length p;
+ a1 = pnt 0 (p);
+ a3 = pnt [n/2] (p);
+ if cycle p:
+ a2 = pnt [ n/4] (p);
+ a4 = pnt [3n/4] (p);
+ else:
+ a2 := a3;
+ a4 := pnt[n] (p);
+ fi
+ cntr = .5[a1, a3] + whatever*((a3 - a1) rotated 90);
+ cntr = .5[a2, a4] + whatever*((a4 - a2) rotated 90);
+ cntr
+enddef;
+
+vardef circumcircle expr t =
+ circleppp (pnt0 (t), pnt1 (t), pnt2 (t))
+enddef;
+
+vardef incircle expr t =
+ save A, B, C; pair A, B, C;
+ A := pnt0 (t);
+ B := pnt1 (t);
+ C := pnt2 (t);
+ save a, b, c, D, E, F;
+ D := abs (B-A) = a + b;
+ E := abs (C-B) = b + c;
+ F := abs (A-C) = a + c;
+ circleppp ((a/D)[A,B], (b/E)[B,C], (c/F)[C,A])
+enddef;
+
+vardef excircle expr n of t =
+ save A, B, C; pair A, B, C;
+ A := pnt[n] (t);
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ save a, b, c, D, E, F;
+ D := abs (B-A) = a - b;
+ E := abs (C-B) = b + c;
+ F := abs (C-A) = a - c;
+ circleppp ((a/D)[A,B], (b/E)[B,C], (c/F)[A,C])
+enddef;
+
+vardef ninepointcircle expr t =
+ circleppp (medianpt 0 of t, medianpt 1 of t, medianpt 2 of t)
+enddef;
+
+vardef pshcircle (expr disk, ctr, rad) =
+ if disk:
+ if rad >= 1 :
+ if rad > 1:
+ GBerrmsg ("Impossible radius of pseudohyperbolic circle.")
+ "The radius of a pseudohyperbolic circle can be at most 1.";
+ fi
+ circle ((0,0),1)
+ elseif abs(ctr) >= 1 :
+ if abs(ctr) > 1:
+ GBerrmsg ("Impossible center of pseudohyperbolic circle.")
+ "The center of this pseudohyperbolic circle must be in "
+ & "the unit disk.";
+ fi
+ onepointpath (true,ctr)
+ else:
+ save _r, _dnm;
+ _r := abs(ctr);
+ _dnm := 1 - _r*_r*rad*rad;
+ circle ((1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm)
+ fi
+ else:
+ if rad >= 1 :
+ GBerrmsg ("Impossible radius of pseudohyperbolic circle.")
+ "The radius of a pseudohyperbolic circle must be less than 1.";
+ onepointpath (true,ctr)
+ elseif ypart ctr <= 0:
+ if ypart ctr < 0:
+ GBerrmsg ("Impossible center of pseudohyperbolic circle.")
+ "The center of this pseudohyperbolic circle must be in "
+ & "the upper half-plane.";
+ fi
+ onepointpath (true,ctr)
+ else:
+ save _y, _dnm;
+ _y := ypart ctr;
+ _dnm := 1 - rad*rad;
+ circle ((xpart ctr, (1 + rad*rad)/_dnm * _y), 2rad/_dnm*_y)
+ fi
+ fi
+enddef;
+
+vardef UHPgeodesic (expr A, B) =
+ if xpart A = xpart B:
+ A--B
+ else:
+ save ang_, C_; pair C_;
+ if abs(ypart A) < abs(ypart B):
+ C_ := conj B;
+ else:
+ C_ := conj A;
+ fi
+ if ypart C_ = 0: % both on x-axis
+ ang_ := anglefromto(up, B - A);
+ else:
+ ang_ := anglefromto(A - C_, B - C_);
+ fi
+ arcpps(A, B, 2ang_)
+ fi
+enddef;
+
+vardef UDgeodesic (expr A, B) =
+ save a_, b_;
+ a_ := abs(A); b_ = abs(B);
+ if (a_ = 0) or (b_ = 0):
+ A--B
+ elseif angle A = angle B:
+ A--B
+ else: % note: A, B and B-A are all nonzero from this point
+ save ang_;
+ if a_ = 1:
+ ang_ := anglefromto (if b_>1: A else: -A fi, B-A)
+ elseif b_ = 1:
+ ang_ := anglefromto (A-B, if a_>1: B else: -B fi)
+ else:
+ save C_; pair C_;
+ % reflecting A
+ if a_ < eps:
+ C_ := unitvector A;
+ ang_1 := anglefromto(a_*A - C_, a_*B - C_);
+ else:
+ C_ := (1/a_)*unitvector A;
+ ang_1 := anglefromto(A - C_, B - C_);
+ fi
+ % reflecting B
+ if b_ < eps:
+ C_ := unitvector B;
+ ang_2 := anglefromto(b_*A - C_, b_*B - C_);
+ else:
+ C_ := (1/b_)*unitvector B;
+ ang_2 := anglefromto(A - C_, B - C_);
+ fi
+ ang_ := if abs(ang_1) < abs(ang_2): ang_1 else: ang_2 fi;
+ fi
+ arcpps(A, B, 2ang_)
+ fi
+enddef;
+
+vardef barycenter expr t =
+ save m; m := length t if not cycle t: + 1 fi;
+ pnt0(t)/m for k = 1 upto m - 1: + pnt[k](t)/m endfor
+enddef;
+
+vardef sector (expr center, rad, frtheta, totheta) =
+ center -- arcalt (center, rad, frtheta, totheta) -- cycle
+enddef;
+
+vardef mkbrace (expr S, C, E) =
+ save R_, U_, V_, Z_;
+ pair U_, V_, Z_[];
+ U_ := unitvector (E-S);
+ V_ := U_ rotated 90;
+
+ R_ := 0.5*(C-S) dotprod V_;
+ if R_ = 0:
+ S--C
+ else:
+ if R_ < 0 : V_ := -V_; R_ := -R_; fi
+ V_ := R_*V_; U_ := R_*U_;
+ Z_1 := S + V_ + U_;
+ Z_2 := C - V_ - U_;
+ Z_3 := C - V_ + U_;
+ Z_4 := E + V_ - U_;
+ S{V_}..{U_}Z_1--Z_2{U_}..{V_}C{-V_}..{U_}Z_3--Z_4{U_}..{-V_}E
+ fi
+enddef;
+
+vardef mkfcn (expr sm, tens) (expr bmin, bmax, bst) (text pf) =
+ save _p; pair _p[]; _p := 0;
+ save _dx, _n, _r; numeric _dx, _n, _r;
+ if bmax = bmin: _n := 1;
+ else:
+ _r := bmax - bmin;
+ _dx := max (abs(bst), nottoosmall*abs(_r), epsilon);
+ _n := emax (round(abs(_r)/_dx), 1);
+ fi
+ for _i = 0 upto _n: _p[incr _p] := pf(bmin + _i/_n*_r); endfor
+ mkpath (sm, tens, false, _p)
+enddef;
+
+def tfcn (expr sm) = mkfcn (sm, default_tension) enddef;
+
+def parafcn (expr sm) = tparafcn (sm, default_tension) enddef;
+vardef tparafcn (expr sm, tn) (expr bmin, bmax, bst) (text pf) =
+ save _fp; vardef _fp (expr t) = pf enddef;
+ mkfcn (sm, tn) (bmin, bmax, bst) (_fp)
+enddef;
+
+vardef xfcn (expr sm) (expr xmin, xmax, st) (text _fx) =
+ save _fp; vardef _fp (expr _x) = (_x, _fx(_x)) enddef;
+ mkfcn (sm, default_tension) (xmin, xmax, st) (_fp)
+enddef;
+
+def function (expr sm) = tfunction (sm, default_tension) enddef;
+vardef tfunction (expr sm, tens, xmin, xmax, st) (text _fx) =
+ save _fp; vardef _fp (expr x) = (x, _fx) enddef;
+ mkfcn (sm, tens) (xmin, xmax, st) (_fp)
+enddef;
+
+def btwnfcn (expr sm) = tbtwnfcn (sm, default_tension) enddef;
+vardef tbtwnfcn (expr sm, tn, xlo, xhi, st)(text _fx)(text _gx) =
+ tfunction (sm, tn) (xlo, xhi, st) (_fx) --
+ ( reverse tfunction (sm, tn) (xlo, xhi, st) (_gx) ) -- cycle
+enddef;
+
+def belowfcn (expr sm) = tbelowfcn (sm, default_tension) enddef;
+vardef tbelowfcn (expr sm, tn, xlo, xhi, st)(text _fx) =
+ (xlo,0)--(xhi,0)--
+ (reverse tfunction (sm, tn, xlo, xhi, st)(_fx))--cycle
+enddef;
+
+vardef rfcn (expr sm, tmin, tmax, st) (text ft) =
+ save _fq; vardef _fq (expr t) = (ft(t)) * (dir t) enddef;
+ mkfcn (sm, default_tension) (tmin, tmax, st) (_fq)
+enddef;
+
+def plrfcn (expr sm) = tplrfcn (sm, default_tension) enddef;
+vardef tplrfcn (expr sm, tens, tmin, tmax, st) (text ft) =
+ save _fq; vardef _fq (expr t) = (ft) * (dir t) enddef;
+ mkfcn (sm, tens) (tmin, tmax, st) (_fq)
+enddef;
+
+def btwnplrfcn (expr sm) = tbtwnplrfcn (sm, default_tension) enddef;
+vardef tbtwnplrfcn (expr sm, tn, tlo, thi, st)(text _ft)(text _gt)=
+ tplrfcn (sm, tn, tlo, thi, st) (_ft) --
+ ( reverse tplrfcn (sm, tn, tlo, thi, st) (_gt) ) -- cycle
+enddef;
+
+def plrregion (expr sm) = tplrregion (sm, default_tension) enddef;
+vardef tplrregion (expr sm, tn, tlo, thi, st) (text _ft) =
+ (0,0)--tplrfcn (sm, tn, tlo, thi, st ) (_ft)--cycle
+enddef;
+
+numeric tolerancefactor;
+tolerancefactor := .02;
+
+vardef mklevelset (expr sm, tens, X, Y, t, a, b, c, d) =
+ save _inside_;
+ vardef _inside_ (expr U, V) =
+ inside_levelset(U, V) and between(a, b)(U) and between(c, d)(V)
+ enddef;
+ if not _inside_ (X, Y):
+ GBwarn "Invalid seed point for levelset.";
+ pairmax((a,c), pairmin((X,Y), (b,d)))&cycle
+ else:
+ save ls, W, A, B, prev, curr, seed;
+ pair ls[], prev, curr, seed;
+ seed := (X,Y);
+ ls := 0; W := 0;
+
+ save _first_, _next_, get_next;
+ vardef _first_ (expr U) = _inside_ (U, Y) enddef;
+ vardef _next_ (expr ang) =
+ _inside_ (X_curr + t * cosd ang, Y_curr + t * sind ang)
+ enddef;
+ def get_next (expr angA, angB) =
+ X_curr := xpart curr; Y_curr := ypart curr;
+ ls[incr ls] := curr + t * dir (solve _next_ (angA, angB));
+ prev := curr; curr := ls[ls];
+ W := W + anglefromto (prev - seed, curr - seed);
+ enddef;
+
+ interim tolerance := t*tolerancefactor;
+ ls[incr ls] := (solve _first_ (X, b), Y);
+ curr := ls[ls];
+ interim tolerance := radian*tolerancefactor;
+ get_next (180, 0);
+ for n = 3 upto max_points:
+ A := angle (curr - prev);
+ get_next (A + 120, A - 120);
+ exitif ((abs(W) > 180) or (ls > 10))
+ and (abs(ls[ls] - ls1) < 1.2t);
+ endfor
+ mkpath (sm, tens, true) (ls)
+ fi
+enddef;
+
+numeric max_points;
+max_points := 2000;
+
+def levelset (expr s) = tlevelset (s, default_tension) enddef;
+vardef tlevelset (expr smth, tens, seed, seg) (text cond) =
+ save inside_levelset, _t;
+ vardef inside_levelset (expr x, y) = cond enddef;
+ _t := if seg <= 0: emax (xpos-xneg, ypos-yneg)/max_points * 20
+ else: seg fi;
+ mklevelset (smth, tens, xpart seed, ypart seed, _t)
+ (xneg, xpos, yneg, ypos)
+enddef;
+
+def RKIV (expr sm) = tRKIV (sm, default_tension)
+enddef;
+vardef tRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) =
+ save _trj, _ztr, _dz, _ztmp, _ctm;
+ pair _trj[], % The trajectory
+ _ztr, % current point
+ _dz[], % array[4] of displacements
+ _ztmp; % current point for calculating velocity
+ _trj := N+1; % ultimate size of _trj array
+ _trj1 := _ztr := zstart;
+ save _tt, % current time
+ _dt, % current time step
+ _th; % current time plus half a step
+ _tt := 0;
+ for _idx := 2 upto _trj:
+ _dt := ds/emax(1,abs(_RHS_(_tt,_ztr)));
+ _th := _tt + .5_dt;
+ _dz1 := _dt*_RHS_(_tt, _ztr); % displacement for current point
+ _ztmp := _ztr + .5_dz1; % 1st midpoint
+ % use _th instead of twice calculating (_tt + .5_dt)
+ _dz2 := _dt*_RHS_(_th, _ztmp); % displacement for 1st midpoint
+ _ztmp := _ztr + .5_dz2; % 2nd midpoint
+ _dz3 := _dt*_RHS_(_th, _ztmp); % displacement for 2nd midpoint
+ _ztmp := _ztr + _dz3; % temporary end point
+ % get time for next loop now since we need it in the next line:
+ _tt := _tt + _dt;
+ _dz4 := _dt*_RHS_(_tt, _ztmp); % displacement for end point
+ % get next point
+ _ztr := _ztr + (_dz1 + 2_dz2 + 2_dz3 + _dz4)/6;
+ _trj[_idx] := _ztr;
+ endfor
+ mkpath (sm, tens, false, _trj)
+enddef;
+
+def xyRKIV (expr sm) = txyRKIV (sm, default_tension)
+enddef;
+vardef txyRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) =
+ save _fgxy, __fgxy;
+ vardef __fgxy (expr t, x, y) = _RHS_ enddef;
+ vardef _fgxy (expr t, Z) = __fgxy(t, xpart Z, ypart Z) enddef;
+ tRKIV (sm, tens, zstart, ds, N) (_fgxy)
+enddef;
+
+def odeRKIV (expr sm) = todeRKIV (sm, default_tension)
+enddef;
+vardef todeRKIV (expr sm, tens, xstart, ystart, ds, N)
+(text _fxy) =
+ txyRKIV (sm, tens, (xstart, ystart), ds, N) ((1, _fxy))
+enddef;
+
+vardef lclosed expr f =
+ f
+ if not cycle f:
+ if pnt0(f) = pnt[infinity](f): & else: -- fi cycle
+ fi
+enddef;
+
+def sclosed = sclosedt (default_tension) enddef;
+vardef sclosedt (expr t) expr f =
+ if cycle f: f
+ else: save n; n := length f;
+ if n = 0: f&cycle
+ elseif n = 1: pnt0(f)..tension t..pnt1(f)..tension t..cycle
+ else:
+ (pnt0 (f)) { (pnt1(f)) - (pnt[n] (f)) }..tension t
+ ..(subpath (1, n-1) of f)..tension t
+ ..(pnt[n](f)) { pnt0(f) - pnt[n-1](f) }
+ ..tension t..cycle
+ fi
+ fi
+enddef;
+
+def bclosed = bclosedt (default_tension) enddef;
+vardef bclosedt (expr t) expr f =
+ f
+ if not cycle f:
+ if pnt0(f) = pnt[infinity](f): & else: ..tension t.. fi cycle
+ fi
+enddef;
+
+def uclosed = bclosed enddef;
+def uclosedt = bclosedt enddef;
+
+def cbcontrols (suffix b, t) =
+ b1 := 2[t3, t2];
+ b2 := 2[t2, t1];
+ b3 := 2[b1, b2];
+ b4 := 2[b2, b3];
+enddef;
+
+vardef cbclosed expr f =
+ save n; n := length f;
+ if cycle f: f
+ elseif n = 0: f&cycle
+ else:
+ save p, q, t; pair p[], q[], t[];
+ t1 := pnt0(f); t2 := post0(f); t3 := pre1(f);
+ cbcontrols (p, t); % defines p1 to p4
+ t1 := pnt[n](f); t2 := pre[n](f); t3 := post[n-1](f);
+ cbcontrols (q, t); % defines q1 to q4
+ f..controls q2 and q3..opencbs (q1,q4,p4,p1)
+ ..controls p3 and p2..cycle
+ fi
+enddef;
+
+vardef qbclosed expr f =
+ if cycle f: f
+ else: save n; n := length f;
+ if n = 0: f&cycle
+ else:
+ save p; pair p[]; p := 4;
+ p1 := (3/2)[pnt[n](f), pre[n](f)];
+ p2 := 2[p1, pnt[n](f)];
+ p4 := (3/2)[pnt 0 (f), post0 (f)];
+ p3 := 2[p4, pnt 0 (f)];
+ f & mkqbs (p) & cycle
+ fi
+ fi
+enddef;
+
+vardef makesector expr p = (pathcenter p)--p--cycle enddef;
+
+vardef arccomplement expr p =
+ if cycle p: onepointpath (false, pnt0(p))
+ else:
+ setnumeric (nn) length p;
+ setpairs (pp) (pnt0(p), pnt[.5nn](p), pnt[nn](p));
+ arcpps (pp3,pp1,2*cornerangle(pp2,pp3,pp1))
+ fi
+enddef;
+
+path cuttings;
+vardef cutoffbefore (expr b) expr f =
+ save t, n; n := length f;
+ if n > 0:
+ for k = 1 upto n:
+ exitif (subpath (0,k) of f) intersects b;
+ endfor
+ if _Xtime < 0:
+ cuttings := pnt0 (f){0,0};
+ f
+ else:
+ cuttings := subpath (0,_Xtime) of f;
+ subpath (_Xtime, n) of f
+ fi
+ else: f
+ fi
+enddef;
+
+vardef cutoffafter (expr b) expr f =
+ setpath (g) cutoffbefore (b) reverse f;
+ cuttings := reverse cuttings;
+ reverse g
+enddef;
+
+vardef trimmedpath (expr btrim, etrim) expr f =
+ save g, h; path g, h;
+ g := invvconv (fullcircle scaled 2btrim) shifted pnt0(f);
+ h := invvconv (fullcircle scaled 2etrim) shifted pnt[length f] (f);
+ cutoffafter (h) cutoffbefore (g) f
+enddef;
+
+vardef predirection@# (expr p) =
+ - postdirection[length p - @#] (reverse p)
+enddef;
+
+vardef postdirection@# (expr p) =
+ save _n; _n := length (p);
+ setpair (v) __dir (subpath (@#, @# + _n) of p);
+ if v = origin:
+ v := - __dir (subpath (@#, @# - _n) of p);
+ fi
+ v
+enddef;
+
+vardef __dir (expr p) =
+ save v, w; pair v, w; w := pnt0 (p);
+ v := origin;
+ for n = 1 upto length (p):
+ v := post[n-1] (p) - w; exitif v <> origin;
+ v := pre [ n ] (p) - w; exitif v <> origin;
+ v := pnt [ n ] (p) - w; exitif v <> origin;
+ endfor
+ sgn v
+enddef;
+
+vardef trivial expr p = (__dir (p) = origin) enddef;
+
+newinternal hdwdr, hdten;
+boolean hfilled;
+
+def headshape (expr wr, tens, fil) =
+ interim hdwdr := wr;
+ interim hdten := if tens>0: tens else: default_tension fi;
+ if hdten < .75: hdten := .75; fi
+ setboolean (hfilled) fil;
+ mkheadpaths;
+enddef;
+def mkheadpaths =
+ save Arrowhead, Leftharpoon, Rightharpoon;
+ path Arrowhead, Leftharpoon, Rightharpoon,
+ Arrowhead.clear, Leftharpoon.clear, Rightharpoon.clear;
+ Rightharpoon := (0,0){down}..tension hdten..(.5hdwdr,-1);
+ Rightharpoon.clear := Rightharpoon--(.5hdwdr,0)--cycle;
+ Leftharpoon := (reverse Rightharpoon) xscaled -1;
+ Leftharpoon.clear := (reverse Rightharpoon.clear) xscaled -1;
+ Arrowhead := Leftharpoon & Rightharpoon;
+ Arrowhead.clear := Leftharpoon.clear & Rightharpoon.clear & cycle;
+ if hfilled:
+ Arrowhead := Arrowhead--cycle;
+ Rightharpoon := Rightharpoon--(0,-1)--cycle;
+ Leftharpoon := Leftharpoon--(0,-1)--cycle;
+ fi
+enddef;
+headshape (1,1,false);
+
+def head = ahead (headcolor) enddef;
+
+vardef ahead (expr clr, front, back, hwr, tens, filled) =
+ settension (_tn) tens; fixtension (_tn);
+ if front <> back:
+ setpair (side) (hwr/2) * ((front-back) rotated 90);
+ setpath (f) (back + side)..tension _tn..
+ {front-back}front{back-front}..tension _tn..(back - side);
+ if clearhead:
+ safeunfill (back - side)--(front-side)--(front+side)--
+ (back+side) & f & cycle;
+ colorsafedraw (background) (back - side)--(front-side)--
+ (front+side)--(back+side) & f & cycle;
+ fi
+ if filled:
+ f := f--cycle;
+ colorsafefill (clr) f;
+ fi
+ colorsafedraw (clr) f;
+ fi
+enddef;
+
+def headpath = Gheadpath (false) (Arrowhead) enddef;
+def headpathx = Gheadpath (true) (Arrowhead) enddef;
+
+def colorheadpath = colorGheadpath (false) (Arrowhead) enddef;
+def colorheadpathx = colorGheadpath (true) (Arrowhead) enddef;
+
+def Gheadpath (expr trim) (suffix ah) =
+ colorGheadpath (trim) (ah) (headcolor)
+enddef;
+vardef colorGheadpath
+(expr trim) (suffix ah) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known ah) and (path ah):
+ convertpath (_g) f;
+ setpair (_P) predirection[length _g] (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ setnumeric (_ang) anglefromto (up, _P);
+ _P := pnt[length _g] (_g) - pos * _P;
+ setpair (_tip) if known ah.tip: ah.tip else: origin fi;
+
+ if trim:
+ if known ah.clear:
+ safeunfill (ah.clear shifted - _tip)
+ scaled sc
+ rotated _ang
+ shifted _P;
+ fi
+ setnumeric (_ys) max(bp, penwd, last_dot_size);
+ safeunfill cut_path
+ xscaled ceiling sc yscaled ceiling _ys
+ rotated _ang shifted _P;
+ fi
+ if cycle ah: colorsafefill else: colorsafedraw fi (clr)
+ (ah shifted -_tip)
+ scaled sc
+ rotated _ang
+ shifted _P;
+ fi
+ fi
+ f
+enddef;
+
+path cut_path;
+cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle;
+
+def tailpath (suffix sh) = colortailpath (sh) (headcolor) enddef;
+vardef colortailpath (suffix sh) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known sh) and (path sh):
+ convertpath (_g) f;
+ setpair(_P) postdirection0 (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ if cycle sh: colorsafefill else: colorsafedraw fi (clr)
+ (sh if known sh.tip: shifted -sh.tip fi)
+ scaled sc
+ rotated anglefromto (up, _P)
+ shifted (pnt0 (_g) + pos * _P);
+ fi
+ fi
+ f
+enddef;
+
+def midpath (suffix sh) = colormidpath (sh) (headcolor) enddef;
+vardef colormidpath (suffix sh) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known sh) and (path sh):
+ convertpath (_g) f;
+ setnumeric (_t) pathtime[pos] (_g);
+ setpair (_P) postdirection[_t] (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ if cycle sh: colorsafefill else: colorsafedraw fi (clr)
+ sh scaled sc
+ rotated anglefromto (up, _P)
+ shifted (pnt[_t] (_g));
+ fi
+ fi
+ f
+enddef;
+
+vardef signeddeviate primary X =
+ (uniformdeviate 1)[-X,X]
+enddef;
+vardef scaledeviate (expr W, A) =
+ 2 ** (signeddeviate W) * dir A
+enddef;
+vardef polardeviate primary R =
+ (uniformdeviate abs(R)) * dir uniformdeviate 360
+enddef;
+vardef xydeviate primary Z =
+ (signeddeviate (xpart Z), signeddeviate (ypart Z))
+enddef;
+
+vardef randompair (expr maxshift) =
+ if numeric maxshift: polardeviate (maxshift)
+ elseif pair maxshift: xydeviate (maxshift)
+ else: (0,0)
+ fi
+enddef;
+
+vardef detrivialized expr f =
+ save g; path p, g[]; g := 0;
+ for k = 1 upto length f:
+ p := subpath (k-1,k) of f;
+ if not trivial p: g[incr g] := p; fi
+ endfor
+ if g = 0: onepointpath (cycle f, pnt0(f))
+ else: g1 for k = 2 upto g: &g[k] endfor if cycle f: &cycle fi
+ fi
+enddef;
+
+vardef randompath (expr maxshift, weirdness) expr f =
+ save g, n; path g;
+ g := detrivialized f;
+ n := length g;
+ if n = 0:
+ f shifted randompair (maxshift)
+ else:
+ save X, U, V;
+ pair X[], U[], V[];
+ if cycle g: n := n - 1; fi
+ for k = 0 upto n:
+ X[k] := pnt[k](g);
+ U[k] := X[k] - pre[k](g);
+ V[k] := post[k](g) - X[k];
+ endfor
+ save A, B;
+ for k := 0 upto n:
+ X[k] := X[k] shifted randompair (maxshift);
+ A := anglefromto (U[k],V[k]);
+ B := signeddeviate (30weirdness);
+ U[k] := X[k] - (U[k] zscaled scaledeviate (weirdness,B));
+ B := B - A + A * (2 ** signeddeviate weirdness);
+ V[k] := X[k] + (V[k] zscaled scaledeviate (weirdness,B));
+ endfor
+ X0 for k = 1 upto n:
+ .. controls V[k-1] and U[k] .. X[k]
+ endfor
+ if cycle g:
+ .. controls V[n] and U0 .. cycle
+ fi
+ fi
+enddef;
+
+vardef randomlines (expr maxshift) expr f =
+ save g, n; path g;
+ g := detrivialized f;
+ n := length g;
+ if n = 0:
+ f shifted randompair (maxshift)
+ else:
+ if cycle g: n := n - 1; fi
+ (pnt0(g) shifted randompair (maxshift))
+ for k = 1 upto n:
+ -- (pnt[k](g) shifted randompair (maxshift))
+ endfor
+ if cycle g:
+ -- cycle
+ fi
+ fi
+enddef;
+
+vardef interpolatedpath (expr t, P) expr Q =
+ if not path Q:
+ GBerrmsg ("Improper argument to interpolatedpath.")
+ "The last argument to interpolatedpath must be a path.";
+ if pair P: onepointpath(false, P)
+ else:
+ if path P:
+ P
+ else:
+ onepointpath (false, origin)
+ fi
+ fi
+ elseif pair P:
+ interpolated_pair_path (t, cycle Q, P, Q)
+ elseif not path P:
+ GBerrmsg ("Improper argument to interpolatedpath.")
+ "The second argument to interpolatedpath must be a pair "
+ & "or a path.";
+ Q
+ else:
+ if t=0: Q
+ elseif t=1: P
+ else:
+ save P_, Q_; path P_, Q_;
+ P_ := detrivialized P;
+ Q_ := detrivialized Q;
+ if length P_ = 0:
+ interpolated_pair_path (t, cycle Q, pnt0(P_), Q)
+ elseif length Q_ = 0:
+ interpolated_pair_path (t, cycle Q, pnt0(Q_), P)
+ else:
+ save G, H, n, m, k, r;
+ path G[], H[];
+ G := H := 0;
+ n := length P_; m := length Q_;
+ k := gcd(n, m);
+ r := m/k;
+ for I=0 upto n-1:
+ for J=0 upto r-1:
+ G[incr G] := subpath (I+J/r, I+(J+1)/r) of P_;
+ endfor
+ endfor
+ r := n/k;
+ for I=0 upto m-1:
+ for J=0 upto r-1:
+ H[incr H] := subpath (I+J/r, I+(J+1)/r) of Q_;
+ endfor
+ endfor
+ for N = 1 upto G-1:
+ force_equal_ends(G[N], G[N+1]);
+ force_equal_ends(H[N], H[N+1]);
+ endfor
+ interpolated_segment (t, G1, H1)
+ for N = 2 upto G: & interpolated_segment (t, G[N], H[N])
+ endfor if (pnt0(G1)=pnt1(G[G])) and (cycle Q): & cycle fi
+ fi
+ fi
+ fi
+enddef;
+
+vardef interpolated_pair_path (expr t, cyclic, P, Q) =
+ save N; N := length Q;
+ if N=0: onepointpath (cyclic, (t)[pnt0(Q),P])
+ else:
+ (t)[pnt0(Q),P]..controls (t)[post0(Q),P] and
+ for n=1 upto N - 1:
+ (t)[pre[n](Q),P]..(t)[pnt[n](Q),P]..controls (t)[post[n](Q),P]
+ and
+ endfor
+ (t)[pre[N](Q),P].. if cyclic: cycle else: (t)[pnt[N](Q),P] fi
+ fi
+enddef;
+
+vardef interpolated_segment (expr t, S, T) =
+ (t)[ pnt0(S), pnt0(T)]..controls
+ (t)[ post0(S), post0(T)] and (t)[ pre1(S), pre1(T)]..
+ (t)[ pnt1(S), pnt1(T)]
+enddef;
+
+vardef parasegment (expr d, segs, f) =
+ if d = 0: f
+ else:
+ save u, v, t; pair u[], v[];
+ for n = 0 upto segs:
+ t := n/segs;
+ u[n] := postdirection [t] (f);
+ v[n] := pnt[t] (f) + (u[n] zscaled (0,d));
+ endfor
+ v0{u0}
+ for n = 1 upto segs: ...v[n]{u[n]} endfor
+ fi
+enddef;
+
+vardef parapath (expr d) expr f =
+ if d = 0:
+ f
+ else:
+ save a, g, h, p, q, s, t, u, v, w;
+ path g[], h, p[], q[];
+ numeric a, s, t;
+ pair u, v, w, w[];
+ s := emax(3, emin(segment_split, ceiling(max_points/5/length f)));
+ p := 0;
+ for i = 1 upto length f:
+ h := subpath (i-1, i) of f;
+ if not trivial h:
+ q[incr p] := h;
+ p[p] := parasegment (d, s, h);
+ fi
+ endfor
+ if p = 0:
+ f
+ else:
+ a := if d>0: - fi 180;
+ h := p1;
+ for i = 1 upto p-1:
+ u := predirection 1 (q[i]);
+ v := postdirection 0 (q[i+1]);
+ w1 := pnt 1 (q[i]) - (u zscaled (0,d));
+ w2 := pnt 0 (q[i+1]) - (v zscaled (0,d));
+ w3 := pnt [infinity] (h);
+ w4 := pnt 0 (p[i+1]);
+ g0 := arcpps(w3, w1, a);
+ g1 := h & g0;
+ g2 := arcpps(w2, w4, a) & p[i+1];
+ if (p[i] & g0) intersects reverse g2:
+ s := length g2 - _Ytime;
+ t := length h - length p[i] + _Xtime;
+ g1 := subpath (0, t) of g1;
+ g2 := subpath (s, length g2) of g2;
+ force_equal_ends (g1, g2);
+ h := g1 & g2;
+ else:
+ h := h .. p[i+1];
+ fi
+ endfor
+
+ if cycle f:
+ u := predirection 1 (q[p]);
+ v := postdirection 0 (q[1]);
+ w1 := pnt 1 (q[p]) - (u zscaled (0,d));
+ w2 := pnt 0 (q[1]) - (v zscaled (0,d));
+ w3 := pnt [infinity] (h);
+ w4 := pnt 0 (p[1]);
+ g3 := arcpps(w3, w1, a);
+ g0 := arcpps(w2, w4, a);
+ g1 := g0 & h & g3;
+ g2 := g0 & p[1];
+ if (p[p] & g3) intersects reverse g2:
+ s := length g2 - _Ytime;
+ t := length g0 + length h - length p[p] + _Xtime;
+ g1 := subpath (s, t) of g1;
+ force_equal_ends (g1, g1);
+ h := g1 & cycle;
+ else:
+ h := h..cycle;
+ fi
+ fi
+ h
+ fi
+ fi
+enddef;
+
+vardef turnangle@# (expr f) =
+ anglefromto(predirection@# (f), postdirection@#(f))
+enddef;
+
+def setdatadashes (text lst) =
+ save __type; __type := 0;
+ forsuffixes _itm = lst:
+ if knownnumericarray _itm :
+ copyarray (_itm) (__type[__type]);
+ next __type;
+ else: GBwarn "Improper dash pattern in setdatadashes.";
+ fi
+ endfor
+ if __type > 1:
+ save dashtype; dashtype := __type;
+ for _j = 0 upto dashtype - 1:
+ copyarray (__type[_j]) (dashtype[_j]);
+ endfor
+ else:
+ SetdataWarn "dashes";
+ fi
+enddef;
+def getdashpat expr n = dashtype[n mod dashtype] enddef;
+
+def SetdataWarn expr s =
+ GBwarn "command setdata"& s &"() failed. Previous values retained.";
+enddef;
+
+numeric Solid, Simpledash, Simpledot, Dotdash, Dotdashdot, Dotdashdash;
+dashpat (Solid) (0);
+dashpat (Simple_dash) (3bp, 4bp);
+dashpat (Simple_dot) (0, 4bp);
+dashpat (Dot_dash) (0, 4bp, 3bp, 4bp);
+dashpat (Dot_dash_dot) (0, 4bp, 3bp, 4bp, 0, 4bp);
+dashpat (Dot_dash_dash) (0, 4bp, 3bp, 4bp, 3bp, 4bp);
+
+numeric dashtype, dashtype[], dashtype[][];
+def defaultdashes =
+ setdatadashes (Solid, Simple_dash, Simple_dot,
+ Dot_dash, Dot_dash_dot, Dot_dash_dash);
+enddef;
+defaultdashes;
+
+def setdatasymbols (text lst) =
+ save __type; path __type[];
+ __type := 0;
+ for _itm = lst:
+ if (known _itm) and (path _itm):
+ __type[__type] := _itm;
+ next __type;
+ else:
+ GBwarn "Improper symbol in setdatasymbols().";
+ fi
+ endfor
+ if __type > 1:
+ save pointtype; pointtype := __type;
+ path pointtype[];
+ for _j = 0 upto pointtype - 1:
+ pointtype[_j] := __type[_j];
+ endfor
+ else:
+ SetdataWarn "symbols";
+ fi
+enddef;
+def getsymbol expr n := pointtype[n mod pointtype] enddef;
+
+def DeclareGBSymbols (text S) =
+ forsuffixes _itm = S:
+ path _itm;
+ path _itm.clear;
+ pair _itm.tip;
+ endfor
+enddef;
+DeclareGBSymbols(
+ Triangle, Square, Circle, Diamond, Star, Plus, Cross,
+ Asterisk, Crossbar, Leftbar, Rightbar, Righthook,
+ Lefthook, SolidTriangle, SolidSquare, SolidCircle,
+ SolidDiamond, SolidStar
+);
+
+vardef undo_cycle expr f = subpath (0, length f) of f enddef;
+
+SolidTriangle := (up--(dir 210)--(dir -30)--cycle) scaled .78;
+Triangle := undo_cycle SolidTriangle;
+
+Triangle.clear := SolidTriangle.clear :=
+ ((dir -30)--(cosd 30,1)--(cosd 210,1)--(dir 210)--up--cycle)
+ scaled .78;
+
+SolidSquare := (up--(-1,1)--(-1,-1)--(1,-1)--(1,1)--cycle) scaled .443;
+Square := undo_cycle SolidSquare;
+
+SolidCircle := fullcircle rotated 90;
+Circle := undo_cycle SolidCircle;
+Circle.clear := SolidCircle.clear :=
+ halfcircle--(-.5,.5)--(.5,.5)--cycle;
+
+SolidDiamond := (up--left--down--right--cycle)
+ scaled .522 yscaled 1.44;
+Diamond := undo_cycle SolidDiamond;
+Diamond.clear := SolidDiamond.clear :=
+ (right--(1,1)--(-1,1)--left--up--cycle) scaled .522 yscaled 1.44;
+
+Plus := ((0,0)--up--down--(0,0)--left--right) scaled .65;
+Plus.clear := (right--(1,1)--(-1,1)--(left)--cycle) scaled .65;
+
+Cross := ((0,0)--(dir 45)--(dir -135)--(0,0)--(dir -45)--(dir 135))
+ scaled .65;
+Cross.clear :=
+ ((0,0)--(dir -45)--dir(45)--(dir 135)--(dir -135)--cycle) scaled .65;
+
+Asterisk := ((0,0)--up--down--(0,0)--(dir 30)--(dir -150)
+ --(0,0)--(dir -30)--(dir 150)) scaled .6;
+Asterisk.clear := ((0,0)--(dir -30)--(cosd 30,1)--(cosd 150,1)
+ --(dir -150)--cycle) scaled .6;
+
+Crossbar := ((0,0)--left--right) scaled .65;
+Crossbar.clear := rect (right,(-1,.5)) scaled .65;
+
+Leftbar := ((0,0)--left);
+Rightbar := ((0,0)--right);
+Leftbar.clear := rect((0,0),(-1,.5));
+Rightbar.clear := rect((0,0),(1,.5));
+
+Righthook := arcpps((0,0),(1,0),180);
+Lefthook := Righthook xscaled -1;
+Righthook.clear := Righthook--cycle;
+Lefthook.clear := Lefthook--cycle;
+
+vardef mkstar (expr n, m) (suffix A) =
+ save ang; ang := 360/n;
+ A1 := up; A3 := up rotated ang;
+ A2 = (whatever)[A1, A1 rotated ( ang*m)];
+ A2 = (whatever)[A3, A3 rotated (-ang*m)];
+ for i = 4 upto 2n:
+ A[i] := A[i-2] rotated ang;
+ endfor
+ A := 2n;
+ mkpoly (true, A)
+enddef;
+
+save _A; pair _A[];
+SolidStar := mkstar (5, 2, _A) scaled .84;
+Star := undo_cycle SolidStar;
+Star.clear := polyline (true)
+ (_A9, _A10, _A1, _A2, _A3, (xpart _A3, 1), (xpart _A9, 1))
+ scaled .84;
+SolidStar.clear := Star.clear;
+
+forsuffixes S =
+ Triangle, Square, Circle, Diamond, Star, Plus, Cross,
+ Asterisk, Crossbar, Leftbar, Rightbar, Righthook,
+ Lefthook, SolidTriangle, SolidSquare, SolidCircle,
+ SolidDiamond, SolidStar :
+ S.tip := point 0 of S;
+endfor
+
+vardef gcd (expr n, m) =
+ save a, b, r;
+ a := emax (abs(m), abs(n));
+ b := emin (abs(m), abs(n));
+ if b > 0:
+ forever:
+ r := a mod b;
+ exitif r < 1;
+ a := b; b := r;
+ endfor
+ b
+ else:
+ a
+ fi
+enddef;
+
+vardef lcm (expr n, m) =
+ n/gcd(n, m)*m
+enddef;
+
+numeric pointtype; path pointtype[];
+def defaultsymbols =
+ setdatasymbols( Circle, Cross, SolidDiamond, Square, Plus,
+ Triangle, SolidCircle, Star, SolidTriangle);
+enddef;
+defaultsymbols;
+
+def computepie (suffix dat) (expr sign, ang, cent, rad) (text data) =
+begingroup
+ save _tot, _max, _toobig;
+ _max := 0; dat := 0;
+ for _val = data:
+ dat[incr dat] := _val;
+ _max := emax (_max, _val);
+ endfor
+ if dat=0: GBwarn "piechart attempted with empty list.";
+ _toobig := 1;
+ else:
+ _toobig := infinity/dat;
+ fi
+ if _max > _toobig:
+ for _idx = 1 upto dat:
+ dat[_idx] := dat[_idx]/_toobig;
+ endfor
+ fi
+ for _idx = 2 upto dat:
+ dat[_idx] := dat[_idx - 1] + dat[_idx];
+ endfor
+ _tot := dat[dat];
+ for _idx = dat downto 2:
+ dat[_idx] := ang + sign*dat[_idx-1]/_tot*360;
+ endfor
+ dat1 := ang; dat[dat + 1] := ang + 360sign;
+endgroup
+enddef;
+
+def piechart (expr sign, ang, cent, rad) (text data) =
+ save _dat;
+ computepie (_dat) (sign, ang, cent, rad) (data);
+ mkpiewedges (_dat, cent, rad);
+enddef;
+
+def mkpiewedges (suffix dat) (expr cent, rad) =
+ numeric piewedge, piedirection, pieangle, pieangle[];
+ pair piecenter, piedirection[];
+ path piewedge[];
+ piecenter := cent;
+ piedirection := pieangle := piewedge := dat;
+ for _idx = 1 upto dat:
+ pieangle[_idx] := dat[_idx];
+ piewedge[_idx] := sector (piecenter, rad, dat[_idx], dat[_idx+1]);
+ piedirection[_idx] := dir(0.5[ dat[_idx], dat[_idx+1] ]);
+ endfor
+enddef;
+
+def namedpiechart (suffix nm) (expr sign, ang, cent, rad) (text data) =
+ save _dat;
+ computepie (_dat) (sign, ang, cent, rad) (data);
+ setnumeric (nm) _dat;
+ pair nm.center, nm.direction[];
+ path nm.wedge[];
+ nm.center := cent;
+ for _idx = 1 upto _dat:
+ nm.wedge[_idx] := sector (cent, rad, _dat[_idx], _dat[_idx+1]);
+ nm.direction[_idx] := dir(0.5[ _dat[_idx], _dat[_idx+1] ]);
+ endfor
+enddef;
+
+def barchart (expr firstbar, sep, r, vert)(text data) =
+ numeric barbegin, barbegin[],
+ barend, barend[],
+ barlength, barlength[],
+ barstart, barstart[],
+ chartbar, barwd;
+ path chartbar[];
+ chartbar := 0; barwd := r*sep;
+ for _itm = data:
+ barend[incr chartbar]
+ := if pair _itm: ypart _itm else: _itm fi;
+ barbegin[chartbar] := if pair _itm: xpart _itm else: 0 fi;
+ endfor
+ barbegin := barend := barlength := barstart := chartbar;
+ for _nn = 1 upto chartbar:
+ barstart[_nn] := firstbar + sep*(_nn-1);
+ barlength[_nn] := barend[_nn];
+ chartbar[_nn] := rect ((barbegin[_nn], 0), ( barend[_nn], barwd))
+ shifted (0, barstart[_nn]) if vert: xyswap fi;
+ endfor
+enddef;
+
+def namedbarchart (suffix nm) (expr first, sep, r, vert) (text data) =
+ save nm;
+begingroup
+ save _bb, _ee, _ww;
+ path nm.bar[];
+ nm := 0; _ww := r*sep;
+ for _itm = data:
+ _ee := if pair _itm: ypart _itm else: _itm fi;
+ _bb := if pair _itm: xpart _itm else: 0 fi;
+ nm.bar[incr nm] := rect ((_bb, 0), ( _ee, _ww) )
+ shifted (0, first + sep*(nm-1)) if vert: xyswap fi;
+ endfor
+endgroup
+enddef;
+
+picture totalpicture;
+boolean totalnull, currentnull;
+def clearit =
+ currentpicture := totalpicture := nullpicture;
+ currentnull := totalnull := true;
+enddef;
+
+def keepit =
+ addto totalpicture also currentpicture;
+ mono (totalpicture);
+ currentpicture := nullpicture;
+ totalnull := totalnull or currentnull;
+ currentnull := true;
+enddef;
+
+def addto_currentpicture =
+ currentnull := false;
+ addto currentpicture
+enddef;
+
+def mergeit (text do) =
+ if totalnull:
+ do currentpicture
+ elseif currentnull:
+ do totalpicture
+ else:
+ begingroup
+ save _v_; picture _v_;
+ _v_ := currentpicture;
+ addto _v_ also totalpicture;
+ do _v_
+ endgroup
+ fi
+enddef;
+
+boolean noship; noship := false;
+def shipit = if noship: else: mergeit (shipout) fi enddef;
+
+def showit_ = mergeit (show_) enddef;
+def show_ suffix v = display v inwindow currentwindow enddef;
+
+numeric gcode; gcode := 0;
+
+% end grafbase.mf
+endinput.
+%%
+%% End of file `grafbase.mf'.
diff --git a/graphics/mfpic/metapost/dvipsnam.mp b/graphics/mfpic/metapost/dvipsnam.mp
new file mode 100644
index 0000000000..be004a7e09
--- /dev/null
+++ b/graphics/mfpic/metapost/dvipsnam.mp
@@ -0,0 +1,118 @@
+%%
+%% This is file `dvipsnam.mp',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% grafbase.dtx (with options: `dvips')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2002--2012, Daniel H. Luecking
+%%
+%% Mfpic may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3c of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Mfpic has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. There are several Base Interpreters associated
+%% with mfpic: plain TeX, LaTeX, plain Metafont and plain MetaPost.
+%%
+if unknown grafbaseversion:
+ if unknown mpversion:
+ let cmykcolor=color;
+ vardef cmyk (expr c, m, y, k) =
+ (max(1-c-k,0), max(1-m-k,0), max(1-y-k,0))
+ enddef;
+ else:
+ vardef cmyk (expr c, m, y, k) = (c, m, y, k) enddef;
+ fi
+fi
+
+cmykcolor Apricot, Aquamarine, Bittersweet, Black, Blue, BlueGreen,
+BlueViolet, BrickRed, Brown, BurntOrange, CadetBlue, CarnationPink,
+Cerulean, CornflowerBlue, Cyan, Dandelion, DarkOrchid, Emerald,
+ForestGreen, Fuchsia, Goldenrod, Gray, Green, GreenYellow, JungleGreen,
+Lavender, LimeGreen, Magenta, Mahogany, Maroon, Melon, MidnightBlue,
+Mulberry, NavyBlue, OliveGreen, Orange, OrangeRed, Orchid, Peach,
+Periwinkle, PineGreen, Plum, ProcessBlue, Purple, RawSienna, Red,
+RedOrange, RedViolet, Rhodamine, RoyalBlue, RoyalPurple, RubineRed,
+Salmon, SeaGreen, Sepia, SkyBlue, SpringGreen, Tan, TealBlue, Thistle,
+Turquoise, Violet, VioletRed, White, WildStrawberry, Yellow,
+YellowGreen, YellowOrange;
+
+Apricot := cmyk(0,0.32,0.52,0);
+Aquamarine := cmyk(0.82,0,0.30,0);
+Bittersweet := cmyk(0,0.75,1,0.24);
+Black := cmyk(0,0,0,1);
+Blue := cmyk(1,1,0,0);
+BlueGreen := cmyk(0.85,0,0.33,0);
+BlueViolet := cmyk(0.86,0.91,0,0.04);
+BrickRed := cmyk(0,0.89,0.94,0.28);
+Brown := cmyk(0,0.81,1,0.60);
+BurntOrange := cmyk(0,0.51,1,0);
+CadetBlue := cmyk(0.62,0.57,0.23,0);
+CarnationPink := cmyk(0,0.63,0,0);
+Cerulean := cmyk(0.94,0.11,0,0);
+CornflowerBlue := cmyk(0.65,0.13,0,0);
+Cyan := cmyk(1,0,0,0);
+Dandelion := cmyk(0,0.29,0.84,0);
+DarkOrchid := cmyk(0.40,0.80,0.20,0);
+Emerald := cmyk(1,0,0.50,0);
+ForestGreen := cmyk(0.91,0,0.88,0.12);
+Fuchsia := cmyk(0.47,0.91,0,0.08);
+Goldenrod := cmyk(0,0.10,0.84,0);
+Gray := cmyk(0,0,0,0.50);
+Green := cmyk(1,0,1,0);
+GreenYellow := cmyk(0.15,0,0.69,0);
+JungleGreen := cmyk(0.99,0,0.52,0);
+Lavender := cmyk(0,0.48,0,0);
+LimeGreen := cmyk(0.50,0,1,0);
+Magenta := cmyk(0,1,0,0);
+Mahogany := cmyk(0,0.85,0.87,0.35);
+Maroon := cmyk(0,0.87,0.68,0.32);
+Melon := cmyk(0,0.46,0.50,0);
+MidnightBlue := cmyk(0.98,0.13,0,0.43);
+Mulberry := cmyk(0.34,0.90,0,0.02);
+NavyBlue := cmyk(0.94,0.54,0,0);
+OliveGreen := cmyk(0.64,0,0.95,0.40);
+Orange := cmyk(0,0.61,0.87,0);
+OrangeRed := cmyk(0,1,0.50,0);
+Orchid := cmyk(0.32,0.64,0,0);
+Peach := cmyk(0,0.50,0.70,0);
+Periwinkle := cmyk(0.57,0.55,0,0);
+PineGreen := cmyk(0.92,0,0.59,0.25);
+Plum := cmyk(0.50,1,0,0);
+ProcessBlue := cmyk(0.96,0,0,0);
+Purple := cmyk(0.45,0.86,0,0);
+RawSienna := cmyk(0,0.72,1,0.45);
+Red := cmyk(0,1,1,0);
+RedOrange := cmyk(0,0.77,0.87,0);
+RedViolet := cmyk(0.07,0.90,0,0.34);
+Rhodamine := cmyk(0,0.82,0,0);
+RoyalBlue := cmyk(1,0.50,0,0);
+RoyalPurple := cmyk(0.75,0.90,0,0);
+RubineRed := cmyk(0,1,0.13,0);
+Salmon := cmyk(0,0.53,0.38,0);
+SeaGreen := cmyk(0.69,0,0.50,0);
+Sepia := cmyk(0,0.83,1,0.70);
+SkyBlue := cmyk(0.62,0,0.12,0);
+SpringGreen := cmyk(0.26,0,0.76,0);
+Tan := cmyk(0.14,0.42,0.56,0);
+TealBlue := cmyk(0.86,0,0.34,0.02);
+Thistle := cmyk(0.12,0.59,0,0);
+Turquoise := cmyk(0.85,0,0.20,0);
+Violet := cmyk(0.79,0.88,0,0);
+VioletRed := cmyk(0,0.81,0,0);
+White := cmyk(0,0,0,0);
+WildStrawberry := cmyk(0,0.96,0.39,0);
+Yellow := cmyk(0,0,1,0);
+YellowGreen := cmyk(0.44,0,0.74,0);
+YellowOrange := cmyk(0,0.42,1,0);
+
+endinput.
+%%
+%% End of file `dvipsnam.mp'.
diff --git a/graphics/mfpic/metapost/grafbase.mp b/graphics/mfpic/metapost/grafbase.mp
new file mode 100644
index 0000000000..64f6395181
--- /dev/null
+++ b/graphics/mfpic/metapost/grafbase.mp
@@ -0,0 +1,4051 @@
+%%
+%% This is file `grafbase.mp',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% grafbase.dtx (with options: `MP')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2002--2012, Daniel H. Luecking
+%%
+%% Mfpic may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3c of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Mfpic has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. There are several Base Interpreters associated
+%% with mfpic: plain TeX, LaTeX, plain Metafont and plain MetaPost.
+%%
+if (known grafbaseversion) or (known grafbase):
+ message "Grafbase (" & jobname & "): You have loaded grafbase more "
+ & "than once! Please make sure that it is loaded only once.";
+ endinput;
+fi
+boolean grafbase; grafbase := true;
+
+string fileversion, filedate;
+fileversion := "1.10"; filedate := "2012/12/03";
+
+message " Loading grafbase macros, version " & fileversion & ", " &
+ filedate & ".";
+message " ";
+
+def GBmsg expr s = message "Grafbase (" & jobname & "): " & s;
+enddef;
+def GBwarn expr s = GBmsg "Warning, " & s; enddef;
+def GBerrmsg (expr s) expr t = errhelp t;
+ errmessage "Grafbase (" & jobname & "): " & s; errhelp "";
+enddef;
+
+boolean MFPIC; MFPIC := false;
+
+def checkversions (expr g)=
+ numeric grafbaseversion; grafbaseversion := g;
+ if unknown mfpicversion: % no mfpic, or < 0.63
+ GBmsg "Recent mfpic not detected.";
+ elseif g = mfpicversion:
+ MFPIC := true;
+ else:
+ message "";
+ GBwarn "Version mismatch: "
+ & "mfpic and grafbase versions do not match.";
+ message "";
+ fi
+enddef;
+
+checkversions (110);
+
+if unknown base_name : input plain;
+elseif not string base_name: input plain;
+elseif base_name <> "plain": input plain;
+fi
+
+if not boolean debug: boolean debug; debug := false; fi
+
+def GBdebug =
+ begingroup
+ save >>; def >> = message " " & enddef;
+ message "Grafbase DEBUG";
+enddef;
+def GBenddebug =
+ message "End DEBUG";
+ >> "";
+ endgroup
+enddef;
+
+vardef mftitle expr t =
+ if string t: t; message t; fi
+enddef;
+
+boolean METAFONT, METAPOST;
+METAPOST := known color Carl Philipp Emanuel Bach;
+if METAPOST: METAFONT := false; else: METAFONT := true; fi
+
+
+if METAFONT:
+ GBerrmsg ("wrong compiler.")
+ "This file is for Metapost. For Metafont, use grafbase.mf.";
+fi
+
+numeric metapostversion;
+boolean has_cmyk;
+boolean has_filenametemplate; % e.g., filenametemplate "%j.%n;
+boolean has_outputtemplate; % e.g., outputtemplate := "%j.%n;
+if unknown mpversion:
+ % prior to introduction of cmykcolor and output filename templates.
+ % Latest such version was 0.641.
+ metapostversion := 0.641;
+ has_cmyk := false;
+ has_filenametemplate := false;
+ has_outputtemplate := false;
+else:
+ metapostversion := scantokens (mpversion);
+ has_cmyk := true;
+ has_filenametemplate := true;
+ if metapostversion < 1.200:
+ has_outputtemplate := false;
+ else:
+ has_outputtemplate := true;
+ fi
+fi
+
+pt# := pt; bp# := bp;
+def t_ = transformed currenttransform enddef;
+if unknown aspect_ratio: aspect_ratio := 1; fi
+if unknown hppp: hppp := 1 fi;
+if unknown currenttransform:
+ transform currenttransform;
+ currenttransform := identity yscaled aspect_ratio;
+fi
+
+interim warningcheck := 0;
+
+numeric unitlen, xscale, yscale, xneg, xpos, yneg, ypos;
+
+unitlen := 1 bp#;
+xscale := 7.2;
+yscale := 7.2;
+xneg := 0; xpos := 10;
+yneg := 0; ypos := 10;
+
+newinternal deg, pi, radian;
+deg := 1; pi := 3.14159;
+radian := 57.29578;
+numeric degree; degree := deg;
+
+newinternal penwd; penwd := 0.5pt;
+pen drawpen;
+
+def resizedrawpen (expr s) =
+ interim penwd := s;
+ setvariable (pen) (drawpen) pencircle scaled penwd;
+ save currentpen; pen currentpen; pickup drawpen;
+enddef;
+
+numeric hatchwd; hatchwd := 0.5bp;
+pen hatchpen; hatchpen := pencircle scaled hatchwd;
+
+boolean clipall; clipall := false;
+boolean ClipOn; ClipOn := false;
+path ClipPath[]; numeric ClipPath; ClipPath = 0;
+boolean truebbox; truebbox := false;
+
+def DoClip (suffix v) =
+ if ClipOn and (ClipPath > 0): clipsto (v, ClipPath); fi
+enddef;
+
+def noclip (text t) =
+ hide ( setboolean (ClipOn) false; t)
+enddef;
+
+boolean showbbox; showbbox := false;
+
+if not has_cmyk: let rgbcolor = color; let cmykcolor = color; fi
+def _wc_ = withcolor enddef;
+
+color currentcolor, drawcolor, fillcolor, hatchcolor,
+ headcolor, pointcolor, tlabelcolor, background;
+currentcolor := fillcolor := drawcolor := hatchcolor :=
+ headcolor := pointcolor := tlabelcolor := black;
+background := white;
+
+vardef snapto expr t =
+ if numeric t:
+ if unknown t: 0
+ elseif t < 0: 0
+ elseif t > 1: 1
+ else: t
+ fi
+ else:
+ GBerrmsg ("Improper expression type.")
+ "The argument to `snapto' must be a numeric.";
+ fi
+
+enddef;
+
+vardef rgbgray (expr g) = (snapto g) * white enddef;
+vardef cmykgray (expr g) = cmyk(0,0,0,1 - snapto g) enddef;
+
+def colorchoice (expr clr) (text D)(text N)(text R)(text C) =
+ if unknown clr: D
+ elseif numeric clr: N
+ elseif rgbcolor clr: R
+ elseif cmykcolor clr: C
+ else: D
+ fi
+enddef;
+
+if has_cmyk :
+ vardef grayscalegray (expr g) = snapto g enddef;
+ vardef gray (expr g) = grayscalegray (g) enddef;
+ vardef cmyk (expr c, m, y, k) =
+ (snapto c, snapto m, snapto y, snapto k)
+ enddef;
+
+ vardef makecmyk primary clr =
+ colorchoice (clr)(cmykblack)(cmykgray(clr))
+ (rgbtocmyk(redpart clr,greenpart clr,bluepart clr))
+ (clr)
+ enddef;
+ vardef makergb primary clr =
+ colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)
+ (cmyktorgb(cyanpart clr, magentapart clr,
+ yellowpart clr, blackpart clr))
+ enddef;
+ vardef makegray primary clr =
+ colorchoice (clr)(grayscaleblack)(grayscalegray(clr))
+ (rgbtogray (redpart clr, greenpart clr, bluepart clr))
+ (cmyktogray(cyanpart clr, magentapart clr,
+ yellowpart clr, blackpart clr))
+ enddef;
+ vardef iscolor expr clr =
+ (rgbcolor clr) or (cmykcolor clr) or (numeric clr) or (boolean clr)
+ enddef;
+else:
+ vardef gray (expr g) = rgbgray(g) enddef;
+ vardef grayscalegray (expr g) = rgbgray(g) enddef;
+ vardef cmyk (expr c, m, y, k) = rgb (1-c-k, 1-m-k, 1-y-k) enddef;
+ vardef makergb primary clr =
+ colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)()
+ enddef;
+ vardef makegray primary clr =
+ colorchoice (clr)(rgbblack)(rgbgray(clr))
+ (rgbtogray (redpart clr, greenpart clr, bluepart clr))()
+ enddef;
+ def makecmyk = makergb enddef;
+ vardef iscolor expr clr = (color clr) enddef;
+fi
+
+vardef knowncolor expr clr = (known clr) and (iscolor clr) enddef;
+
+vardef forceclr (expr c) =
+ if unknown c :
+ if numeric c: grayscaleblack
+ elseif rgbcolor c: rgbblack
+ elseif cmykcolor c: cmykblack
+ else: black
+ fi
+ elseif numeric c: gray (c)
+ elseif iscolor c: c
+ else: black
+ fi
+enddef;
+vardef named (suffix c) = forceclr (c) enddef;
+
+vardef togray (expr r, g, b) =
+ gray (sqrt((2r*r + 4g*g + b*b)/7))
+enddef;
+
+vardef rgbtogray (expr r, g, b) =
+ togray(snapto r, snapto g, snapto b)
+enddef;
+vardef cmyktogray (expr c, m, y, k) =
+ rgbtogray (1-c-k,1-m-k,1-y-k)
+enddef;
+
+vardef cmyktorgb (expr c,m,y,k) =
+ rgb(1-c-k,1-m-k,1-y-k)
+enddef;
+vardef rgbtocmyk (expr r,g,b) =
+ cmyk(1-r,1-g,1-b,0)
+enddef;
+
+vardef rgb (expr r, g, b) =
+ (snapto r, snapto g, snapto b)
+enddef;
+vardef RGB (expr R, G, B) =
+ rgb (R/255, G/255, B/255)
+enddef;
+
+def list (suffix v) (text lst) =
+ v := 0; for _itm = lst: v[incr v] := _itm; endfor
+ if v = 0:
+ GBerrmsg ("No list to process!")
+ "An attempt was made to produce an array from a "
+ & "list of expressions having no valid entries.";
+ fi
+enddef;
+
+def map (text proc) (text lst) =
+ hide (_map := 0;)
+ for _a = lst:
+ if _map = 0: hide (_map := 1;) else: , fi
+ proc (_a)
+ endfor
+enddef;
+
+vardef knownnumericarray suffix arr =
+ setboolean (_kna) (known arr) and (numeric arr);
+ if _kna :
+ _kna := (arr = floor arr) and (arr >= 1);
+ for _idx = 1 upto arr :
+ exitif not _kna;
+ _kna := (known arr[_idx]) and (numeric arr[_idx]);
+ endfor
+ fi
+ _kna
+enddef;
+
+def copyarray (suffix src, dest) =
+ for _idx = 1 upto src: dest[_idx] := src[_idx]; endfor
+ dest := src;
+enddef;
+
+def maparr (text proc) (suffix p) =
+ for _idx = 1 upto p: proc (p[_idx]); endfor
+enddef;
+
+def textpairs = gsetarray (pair) enddef;
+
+def setuniquepairs (suffix p) (text t) =
+ save p; pair p[];
+ setpairs (_up) (t);
+ if _up > 0:
+ p := 1; p1 := _up1;
+ for _i = 2 upto _up:
+ if _up[_i] <> p[p]: p[incr p] := _up[_i]; fi
+ endfor
+ else:
+ p := 0;
+ fi
+enddef;
+
+vardef chpair (text proc) (expr p) =
+ (proc (xpart p), proc (ypart p))
+enddef;
+
+vardef floorpair (expr p) = (floor (xpart p), floor (ypart p))
+enddef;
+vardef ceilingpair (expr p) = (ceiling (xpart p), ceiling (ypart p))
+enddef;
+
+vardef emin (expr a, b) = if a < b: a else: b fi enddef;
+vardef emax (expr a, b) = if a > b: a else: b fi enddef;
+
+vardef pairmin (expr z, w) =
+ ( emin (xpart z, xpart w), emin (ypart z, ypart w ) )
+enddef;
+vardef pairmax (expr z, w) =
+ ( emax (xpart z, xpart w), emax (ypart z, ypart w ) )
+enddef;
+
+vardef minpair (suffix p) = setpair (_mp) p1;
+ for _idx = 2 upto p - 1: _mp := pairmin (_mp, p[_idx]); endfor
+ pairmin (_mp, p[p])
+enddef;
+vardef maxpair (suffix p) = setpair (_mp) p1;
+ for _idx = 2 upto p - 1: _mp := pairmax (_mp, p[_idx]); endfor
+ pairmax (_mp, p[p])
+enddef;
+
+primarydef Z xprod W = (xpart Z * ypart W - xpart W * ypart Z)
+enddef;
+
+def force_initial (expr p) (suffix f) =
+ hide( setnumeric (_n) length f;
+ f := p
+ if _n = 0:
+ {0,0}
+ else:
+ ..controls post0 (f) and pre 1 (f).. subpath (1,_n) of f
+ fi;)
+enddef;
+
+def force_terminal (expr p) (suffix f) =
+ hide(setpath (_f) reverse f;
+ force_initial (p) (_f);
+ f := reverse _f;)
+enddef;
+
+def force_equal_ends (suffix f, g) =
+ hide(save _p; pair _p;
+ _p := .5[pnt[length f] (f), pnt0(g)];
+ force_terminal (_p) (f); force_initial (_p) (g);)
+enddef;
+
+def replace_ends_of_cycle (expr p) (suffix f) =
+hide(
+if cycle f:
+ save _n; _n := length f;
+ f := p
+ if _n = 0: &cycle
+ else: .. controls post0 (f) and pre 1 (f) ..
+ if _n = 1: cycle
+ else: subpath (1, _n - 1) of f ..
+ controls post[_n - 1](f) and pre[_n](f) .. cycle
+ fi
+ fi;
+fi)
+enddef;
+
+pair thetimes;
+numeric _Xtime, _Ytime;
+tertiarydef a intersects b =
+ begingroup
+ thetimes := a intersectiontimes b;
+ _Xtime := xpart thetimes;
+ _Ytime := ypart thetimes;
+ (_Xtime > -1)
+ endgroup
+enddef;
+
+tertiarydef a misses b = ((a intersectiontimes b) < origin) enddef;
+
+vardef makepicture (expr s) =
+ if picture s: s
+ elseif string s: s infont defaultfont scaled defaultscale
+ elseif path s: picpath (s)
+ else: nullpicture
+ fi
+enddef;
+
+vardef onepointpath (expr cyclic, q) =
+ q if cyclic: &cycle else: {0,0} fi
+enddef;
+
+vardef fallbackpath (expr cyclic, p) (text t) =
+ onepointpath (cyclic, p)
+enddef;
+
+def even = not odd enddef;
+
+primarydef a divides b =
+ ((b mod a) = 0)
+enddef;
+
+def beginimage =
+ begingroup
+ newpicture (currentpicture);
+enddef;
+def endimage =
+ ; currentpicture
+ endgroup
+enddef;
+
+def makeimage (suffix name) (expr refpt) =
+ setpair (_image_reference_point) zconv (refpt);
+ setpicture (name) beginimage
+enddef;
+def concludeimage =
+ endimage shifted
+ -_image_reference_point
+enddef;
+
+def setvariable (text kind) (suffix name) =
+ save name; kind name; name :=
+enddef;
+def gsetvariable (text kind) (suffix name) = kind name; name :=
+enddef;
+
+def setnumeric (suffix name) = save name; name := enddef;
+def setboolean = setvariable (boolean) enddef;
+def setpair = setvariable (pair) enddef;
+def setpath = setvariable (path) enddef;
+def setpicture = setvariable (picture) enddef;
+def setstring = setvariable (string) enddef;
+def settransform = setvariable (transform) enddef;
+def setpen = setvariable (pen) enddef;
+def settension (suffix tn) expr tens =
+ setnumeric (tn) if tens > 0: tens else: default_tension fi;
+enddef;
+def fixtension (suffix tn) = if tn < .75: tn := .75; fi enddef;
+
+def newpicture (suffix pic) = setpicture (pic) nullpicture; enddef;
+def convertpath (suffix g) expr f = setpath (g) zconv (f); enddef;
+
+def setarray (text kind) (suffix name) =
+ save name; kind name[]; list (name)
+enddef;
+def setpairs = setarray (pair) enddef;
+def gsetarray (text kind) (suffix name) =
+ numeric name; kind name[]; list (name)
+enddef;
+
+
+def setbbox (suffix ll, ur) =
+ save ll, ur; pair ll, ur; getbbox (ll, ur)
+enddef;
+
+def setsplit (suffix s) expr ss =
+ setnumeric (s) emax (1, ceiling ss);
+enddef;
+
+if has_cmyk:
+ def setrgbcolor = setvariable (rgbcolor) enddef;
+ def setcmykcolor = setvariable (cmykcolor) enddef;
+ def setcolor (suffix name) expr val =
+ if boolean val : setboolean
+ elseif numeric val : setnumeric
+ elseif rgbcolor val : setrgbcolor
+ elseif cmykcolor val : setcmykcolor
+ % this should give a suitable error message:
+ else: setvariable (color)
+ fi (name) val;
+ enddef;
+ def gsetcolor (suffix name) expr val =
+ if boolean val : boolean name;
+ elseif numeric val : numeric name;
+ elseif rgbcolor val : rgbcolor name;
+ elseif cmykcolor val : cmykcolor name;
+ else: color name;
+ fi name := val;
+ enddef;
+else:
+ def setrgbcolor = setcolor enddef;
+ def setcmykcolor = setcolor enddef;
+ def setcolor = setvariable (color) enddef;
+ def gsetcolor = gsetvariable (color) enddef;
+fi
+
+setcolor(rgbblack) rgb(0,0,0);
+setcolor(red) rgb(1,0,0);
+setcolor(green) rgb(0,1,0);
+setcolor(blue) rgb(0,0,1);
+setcolor(rgbwhite) rgb(1,1,1);
+setcolor(cmykwhite) cmyk(0,0,0,0);
+setcolor(cyan) cmyk(1,0,0,0); % Maybe these should
+setcolor(magenta) cmyk(0,1,0,0); % be rbg for backward
+setcolor(yellow) cmyk(0,0,1,0); % compatibility?
+setcolor(cmykblack) cmyk(0,0,0,1);
+setcolor(grayscaleblack) gray(0);
+setcolor(grayscalewhite) gray(1);
+
+if has_outputtemplate:
+ def setoutputtemplate = outputtemplate := enddef;
+elseif has_filenametemplate:
+ def setoutputtemplate = filenametemplate enddef;
+else:
+ def setoutputtemplate text garbage = enddef;
+fi
+
+vardef GBromannumeral (expr X) =
+ save Y, _tmp, U; string U;
+
+ Y.m := X div 1000; % thousands digit
+ _tmp := X - 1000Y.m; % hundreds digits and lower
+ Y.c := _tmp div 100; % hundreds
+ _tmp := _tmp - 100Y.c; % tens and units
+ Y.x := _tmp div 10; % tens
+ Y.i := _tmp - 10Y.x; % units
+
+ strrepeat("m", Y.m) &
+ GBromandigit("c", "d", "m", Y.c) &
+ GBromandigit("x", "l", "c", Y.x) &
+ GBromandigit("i", "v", "x", Y.i)
+enddef;
+
+vardef GBromandigit (expr bot, mid, top, n) =
+ if n > 9 : top & strrepeat(bot, n-10) % shouldn't happen
+ elseif n > 8 :
+ bot & top % "ix"
+ elseif n > 4 : mid & strrepeat (bot, n-5) % "v"--"viii"
+ elseif n > 3 :
+ bot & mid % "iv"
+ else: strrepeat (bot, n) % ""--"iii" for 0--3
+ fi
+enddef;
+
+vardef strrepeat (expr st, rep) =
+ "" for i = 1 upto rep: & st endfor
+enddef;
+
+transform ztr, vtr;
+def setztr =
+ if debug:
+ GBdebug;
+ >> "w_ = " & decimal w_ & "bp";
+ >> "h_ = " & decimal h_ & "bp";
+ >> "unitlen = " & decimal unitlen & "bp";
+ >> "xneg = " & decimal xneg;
+ >> "xpos = " & decimal xpos;
+ >> "yneg = " & decimal yneg;
+ >> "ypos = " & decimal ypos;
+ >> "xscale = " & decimal xscale;
+ >> "yscale = " & decimal yscale;
+ GBenddebug;
+ fi
+ save ztr, vtr;
+ transform ztr, vtr;
+ vtr := identity xscaled xscale yscaled yscale scaled (unitlen*hppp);
+ ztr := identity shifted (-xneg, -yneg) transformed vtr;
+ if debug:
+ GBdebug;
+ >> "ztr is";
+ show ztr;
+ >> "vtr is";
+ show vtr;
+ GBenddebug;
+ fi
+enddef;
+
+vardef zconv (expr a) = a transformed ztr enddef;
+vardef invzconv (expr a) = a transformed (inverse ztr) enddef;
+vardef vconv (expr v) = v transformed vtr enddef;
+vardef invvconv (expr v) = v transformed (inverse vtr) enddef;
+
+def active_plane = currentpicture enddef;
+
+boolean overlaylabels, underlaylabels, havebackground;
+overlaylabels := false;
+underlaylabels := false;
+havebackground := false;
+
+def initpic =
+ setztr;
+ resizedrawpen (penwd);
+ if ClipOn: ClipPath := 1;
+ ClipPath1 := rect (origin, (w_, h_));
+ fi
+ if debug:
+ GBdebug;
+ >> "Drawing nominal bounding box around picture";
+ GBenddebug;
+ noclip ( safedraw rect (origin, (w_, h_)) );
+ fi
+ newpicture (foreground_labels);
+ newpicture (background_labels);
+ havebackground := false;
+ save labelbb; pair labelbb.ll, labelbb.ur;
+ labelbb.ll := labelbb.ur := origin;
+enddef;
+
+def mfpicenv = enddef;
+def endmfpicenv = enddef;
+def bounds (expr a, b, c, d) =
+ xneg := a; xpos := b;
+ yneg := c; ypos := d;
+enddef;
+
+string extra_beginmfpic; extra_beginmfpic := "";
+string extra_endmfpic; extra_endmfpic := "";
+
+def beginmfpic (expr ch) =
+ beginfig (ch);
+ gcode := ch;
+ save w_, h_, d_;
+ charwd := (xpos-xneg)*xscale*unitlen;
+ charht := (ypos-yneg)*yscale*unitlen;
+ chardp := 0;
+ w_ := charwd;
+ h_ := charht;
+ d_ := chardp;
+ initpic;
+ scantokens extra_beginmfpic;
+enddef;
+
+def endmfpic =
+ scantokens extra_endmfpic;
+ if debug:
+ GBdebug;
+ >> "width = " & decimal w_ & "bp";
+ >> "height = " & decimal h_ & "bp";
+ GBenddebug;
+ fi
+ DoClip (active_plane);
+ if clipall: clipto (active_plane) rect (origin, (w_, h_)); fi
+ if showbbox: noclip ( safedraw rect (origin, (w_, h_)) ); fi
+ save _ll, _ur;
+ pair _ll, _ur;
+ if truebbox:
+ _ll := llcorner active_plane;
+ _ur := urcorner active_plane;
+ elseif clipall:
+ _ll := origin;
+ _ur := (w_,h_);
+ else: % expand to accomodate labels
+ _ll := pairmin ((0, 0 ), labelbb.ll);
+ _ur := pairmax ((w_, h_), labelbb.ur);
+ fi
+ _ur := pairmax (_ur, _ll + eps*(1, 1));
+ setbounds active_plane to rect (_ll, _ur);
+ if havebackground:
+ addto background_labels also active_plane;
+ active_plane := background_labels;
+ background_labels := nullpicture;
+ fi
+ addto active_plane also foreground_labels;
+ foreground_labels := nullpicture;
+ endfig;
+enddef;
+
+pair label_adjust;
+label_adjust := origin;
+numeric label_sep, labelpath_sep ;
+label_sep := 0; labelpath_sep := 0;
+
+vardef newgblabel (expr hf, vf, BL, r) (expr s) (text pts) =
+ save _lab, _ll, _ur; picture _lab; pair _ll, _ur;
+ _lab := makepicture (s);
+ pathdims (origin, _lab) (_ll, _ur);
+ readjustdims (_ll, _ur) (label_sep);
+ _lab := thegblabel (ref_shift (hf, vf, BL, _ll, _ur), r, _lab);
+ save _b; pair _b;
+ for _itm = pts:
+ _b := zconv (_itm);
+ if overlaylabels:
+ addto foreground_labels also _lab shifted _b _wc_ tlabelcolor;
+ elseif underlaylabels:
+ addto background_labels also _lab shifted _b _wc_ tlabelcolor;
+ havebackground := true;
+ else:
+ addto active_plane also _lab shifted _b _wc_ tlabelcolor;
+ labelbb.ll := pairmin (_b + llcorner _lab, labelbb.ll);
+ labelbb.ur := pairmax (_b + urcorner _lab, labelbb.ur);
+ fi
+ endfor
+enddef;
+
+vardef gblabel (expr a, b, c, d, r) (expr s) (text t) =
+ newgblabel (b, d, (c = 0) and (d = 0), r) (s) (t);
+enddef;
+
+vardef ref_shift (expr hf, vf, BL, ll, ur) =
+ - ( (hf)[xpart ll, xpart ur],
+ (vf)[if BL: 0 else: (ypart ll) fi, ypart ur] )
+enddef;
+
+vardef thegblabel (expr z, r, p) =
+ ((p shifted z) rotated r) shifted label_adjust
+enddef;
+
+vardef textrect (expr lbl, rad, loc) =
+ textrectx (.5, .5, false, 0) (origin, lbl, rad, loc)
+enddef;
+vardef textoval (expr lbl, mult, loc) =
+ xellipse (true, .5, .5, false, 0) (origin, lbl, mult, loc)
+enddef;
+vardef textellipse (expr lbl, rat, loc) =
+ xellipse (false, .5, .5, false, 0) (origin, lbl, rat, loc)
+enddef;
+
+boolean roundends; roundends := true;
+vardef textrectx (expr a, b, c, rot, xy, lbl, rad, loc) =
+ save ll, ur, _r, f, zz;
+ pair ll, ur, zz; path f;
+ pathdims (xy, lbl) (ll, ur);
+ readjustdims (ll, ur) (labelpath_sep)
+ _r := if numeric rad: rad
+ elseif not boolean rad: 0
+ elseif rad: emin (xpart(ur-ll), ypart (ur-ll))/sqrt(2)
+ else: 0
+ fi;
+ if _r = 0:
+ f := rect (ll, ur);
+ else:
+ save p, q;
+ pair p[]; path q;
+ p1 := ur - _r*dir(45);
+ p3 := ll + _r*dir(45);
+ p2 := (xpart p3, ypart p1);
+ p4 := (xpart p1, ypart p3);
+ q := if _r < 0: reverse fi quartercircle scaled 2_r;
+ f :=
+ (q shifted p1)--(q rotated 90 shifted p2)
+ --(q rotated 180 shifted p3)
+ --(q rotated -90 shifted p4)--cycle;
+
+ fi
+ readjustdims (ll, ur) (label_sep - labelpath_sep);
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), rot, f))
+ shifted loc
+enddef;
+
+def textovalx = xellipse (true) enddef;
+def textellipsex = xellipse (false) enddef;
+
+vardef xellipse (expr aspect, a, b, c, r, xy, lbl, mult, loc) =
+ if mult = 0:
+ textrectx (a, b, c, r) (xy, lbl, 0, loc)
+ else:
+ save ll, ur, cc, ww, hh, f;
+ pair ll, ur, cc; path f;
+ pathdims (xy, lbl) (ll, ur);
+ readjustdims (ll, ur) (labelpath_sep)
+ cc := .5[ll, ur];
+ (ww, hh) = ur - cc;
+ if (ww = 0) or (hh = 0):
+ f = (ll--ur);
+ else:
+ save aa, bb;
+ aa := ww ++ if aspect: ww else: hh fi *mult;
+ bb := hh ++ if aspect: hh else: ww fi /mult;
+ f := ellipse (cc, aa, bb, 0);
+ fi
+ readjustdims (ll, ur) (label_sep - labelpath_sep);
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), r, f))
+ shifted loc
+ fi
+enddef;
+
+def pathdims (expr xy, lbl) (suffix ll, ur) =
+ if pair lbl:
+ ll := xy; ur := lbl;
+ else:
+ setpicture (_lbl) makepicture (lbl);
+ ll := llcorner _lbl;
+ ur := urcorner _lbl;
+ fi
+enddef;
+
+def readjustdims (suffix ll, ur) (expr s) =
+ ll := ll - s*(1,1);
+ ur := ur + s*(1,1);
+enddef;
+
+newinternal reallysmall; reallysmall := 3epsilon;
+newinternal nottoosmall; nottoosmall := eps/2 + 2epsilon;
+def signof (expr X) = if X < 0: - fi enddef;
+def TruncateWarn expr s =
+ GBwarn s & " is too large or undefined, so it will be truncated.";
+enddef;
+
+vardef secd primary X =
+ setnumeric (temp) cosd(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Secant or Tangent";
+ temp := signof (temp) reallysmall;
+ fi
+ 1/temp
+enddef;
+vardef tand primary X = sind(X)*secd(X) enddef;
+
+vardef cscd primary X =
+ setnumeric (temp) sind(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Cosecant or Cotangent";
+ temp := signof(temp) reallysmall;
+ fi
+ 1/temp
+enddef;
+vardef cotd primary X = cosd(X)*cscd(X) enddef;
+
+vardef acos primary X =
+ if abs X > 1:
+ TruncateWarn "Argument of arccosine";
+ angle (signof(X) 1, 0)
+ else:
+ angle (X, 1 +-+ X)
+ fi
+enddef;
+vardef asin primary X =
+ if abs X > 1:
+ TruncateWarn "Argument of arcsine";
+ angle (0, signof(X) 1)
+ else:
+ angle (1 +-+ X, X)
+ fi
+enddef;
+vardef atan primary X = angle (1, X) enddef;
+
+vardef sin primary X = sind (X*radian) enddef;
+vardef cos primary X = cosd (X*radian) enddef;
+vardef tan primary X = tand (X*radian) enddef;
+vardef cot primary X = cotd (X*radian) enddef;
+vardef sec primary X = secd (X*radian) enddef;
+vardef csc primary X = cscd (X*radian) enddef;
+
+vardef degrees (expr t) = t*radian enddef;
+vardef radians (expr t) = t/radian enddef;
+
+vardef invcos primary X = radians (acos X) enddef;
+vardef invsin primary X = radians (asin X) enddef;
+vardef invtan primary X = radians (atan X) enddef;
+
+vardef exp primary X = mexp (256 * X) enddef;
+vardef ln primary X = (mlog X) / 256 enddef;
+vardef log primary X = ln (X) enddef;
+vardef logbase (expr B) primary X = (mlog X)/(mlog B) enddef;
+vardef logtwo primary X = logbase( 2) (X) enddef;
+vardef logten primary X = logbase(10) (X) enddef;
+
+vardef cosh primary X =
+ setnumeric (temp) 2 exp (-abs(X));
+ if temp < reallysmall:
+ TruncateWarn "Cosh";
+ temp := reallysmall;
+ fi
+ 1/temp + temp/4
+enddef;
+
+vardef sinh primary X =
+ setnumeric (temp) 2 exp (-abs(X));
+ if temp < reallysmall:
+ TruncateWarn "Sinh";
+ temp := reallysmall;
+ fi
+ signof (X) (1/temp - temp/4)
+enddef;
+
+vardef sech primary X =
+ setnumeric (temp) exp(-(abs (X)));
+ 2temp/(1 + temp*temp)
+enddef;
+
+vardef tanh primary X =
+ setnumeric (temp) exp(-2(abs (X)));
+ signof (X) (1 - temp)/(1 + temp)
+enddef;
+
+vardef csch primary X =
+ save temp, tempa; temp := exp(-(abs (X)));
+ tempa := (1 - temp*temp)/2;
+ if tempa < reallysmall:
+ TruncateWarn "Csch";
+ tempa := reallysmall;
+ fi
+ signof (X) temp / tempa
+enddef;
+
+vardef coth primary X =
+ setnumeric (temp) tanh(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Coth";
+ temp := signof (X) reallysmall;
+ fi
+ 1/temp
+enddef;
+
+vardef acosh primary y =
+ if y < 1:
+ TruncateWarn "acosh";
+ 0
+ else:
+ ln (y + (y +-+ 1))
+ fi
+enddef;
+
+vardef asinh primary y = ln (y + (y ++ 1)) enddef;
+
+vardef atanh primary y =
+ if abs (y) < 1:
+ (ln (1 + y) - ln (1 - y))/2
+ else:
+ TruncateWarn "atanh";
+ signof (y) infinity
+ fi
+enddef;
+
+vardef Arg primary Z = (angle Z)/radian enddef;
+vardef Log primary Z = (ln (abs Z), Arg Z) enddef;
+vardef cis primary T = dir (T*radian) enddef;
+vardef zexp primary Z = (exp (xpart Z)) * cis (ypart Z) enddef;
+vardef sgn primary Z = if not (Z = origin): unitvector fi Z
+enddef;
+vardef zsqrt primary Z =
+ if Z = origin: origin else: sqrt(abs(Z)) * dir ((angle Z)/2) fi
+enddef;
+vardef conj primary Z = (xpart Z, -ypart Z) enddef;
+
+primarydef Z zmul W = Z zscaled W enddef;
+primarydef Z zdiv W =
+ Z zmul ( unitvector (conj W) / (abs W) )
+enddef;
+
+vardef Moebius (expr A) primary Z =
+ save _D; pair _D;
+ _D := (1, 0) + (Z zscaled (conj A));
+ (Z + A)/(abs _D) rotated (- angle _D)
+enddef;
+vardef pshdist (expr Z,W) = abs(Moebius(-W)(Z)) enddef;
+vardef pshdist_hp (expr Z,W) = abs(Z-W)/abs(Z-conj(W)) enddef;
+vardef kelvin (expr Z) =
+ save tmp_; tmp_ = abs(Z);
+ if tmp_ = 0:
+ (infinity, infinity)
+ elseif tmp_ < reallysmall:
+ infinity*unitvector Z
+ else:
+ (1/tmp_)*unitvector Z
+ fi
+enddef;
+
+vardef polar primary p = (xpart p) * dir (ypart p) enddef;
+def id (expr x) = x enddef;
+
+primarydef x**y =
+ if y=2: x*x
+ elseif (x = floor x) and (abs y = floor y):
+ 1 for n=1 upto y: *x endfor
+ else: takepower y of x
+ fi
+enddef;
+let ^ = **;
+
+transform T_stack[];
+numeric T_stack; T_stack := 0;
+
+def T_push (expr T) = T_stack[incr T_stack] := T; enddef;
+def T_pop (suffix $) =
+ if T_stack > 0:
+ $ := T_stack[T_stack];
+ T_stack := T_stack - 1;
+ fi
+enddef;
+
+def bcoords = hide ( T_push (ztr) ) enddef;
+def ecoords = hide ( T_pop (ztr); vtr := vectorpart ztr ) enddef;
+
+vardef vectorpart primary T = T shifted -(origin transformed T)
+enddef;
+
+def apply_t (text Transformer) =
+ ztr := identity Transformer transformed ztr;
+ vtr := vectorpart ztr;
+enddef;
+
+def xslant = slanted enddef; % (x+sy, y).
+def yslant primary s = % (x, y+sx).
+ transformed
+ begingroup
+ save T; transform T;
+ origin transformed T = origin;
+ (1, 0) transformed T = (1, s);
+ (0, 1) transformed T = (0, 1);
+ T
+ endgroup
+enddef;
+
+def zslant primary p = % (xu+yv, xv+yu), where p = (u, v).
+ transformed
+ begingroup
+ save T; transform T;
+ xpart T = ypart T = 0;
+ xxpart T = yypart T = xpart p;
+ xypart T = yxpart T = ypart p;
+ T
+ endgroup
+enddef;
+
+def xyswap = zslant (0, 1) enddef;
+def boost primary X = zslant (cosh X, sinh X) enddef;
+
+vardef transformedpath (text Transformer) expr f = f Transformer
+enddef;
+
+def rotatedpath (expr p, th) =
+ transformedpath (
+ transformed vtr
+ rotatedaround (p transformed vtr, th)
+ transformed (inverse vtr)
+ )
+enddef;
+def reflectedpath (expr p, q) =
+ transformedpath (
+ transformed vtr
+ reflectedabout (p transformed vtr, q transformed vtr)
+ transformed (inverse vtr)
+ )
+enddef;
+
+def scaledpath (expr p, s) =
+ transformedpath (shifted -p scaled s shifted p)
+enddef;
+def xscaledpath (expr a, s) =
+ transformedpath (shifted (-a, 0) xscaled s shifted (a, 0))
+enddef;
+def yscaledpath (expr b, s) =
+ transformedpath (shifted (0, -b) yscaled s shifted (0, b))
+enddef;
+
+def slantedpath = xslantedpath enddef;
+def xslantedpath (expr b, s) =
+ transformedpath (shifted (0, -b) slanted s shifted (0, b))
+enddef;
+def yslantedpath (expr a, s) =
+ transformedpath (shifted (-a, 0) yslant s shifted (0, a))
+enddef;
+
+def shiftedpath (expr v) = transformedpath (shifted v) enddef;
+
+def xyswappedpath = transformedpath (xyswap) enddef;
+
+vardef partialpath (expr a, b) expr f =
+ save flag, flo, fhi, lo, hi, n;
+ boolean flag; flag = true;
+ convertpath (g) f;
+ n := length f;
+
+ flo := snapto emin(a,b);
+ if flo = 0:
+ lo := 0;
+ elseif flo < 1:
+ setuplengtharray (cum, tot, idx) g;
+ flag := false;
+ lo := gettime (cum, idx) (flo*tot);
+ else:
+ lo := n;
+ fi
+
+ fhi := snapto emax (a,b);
+ if flo = fhi:
+ hi := lo;
+ elseif fhi < 1:
+ if flag: setuplengtharray (cum, tot, idx) g; fi
+ hi := gettime (cum, idx) (fhi*tot);
+ else:
+ hi := n;
+ fi
+
+ if a > b: reverse fi subpath (lo, hi) of f
+enddef;
+
+vardef gsubpath (expr a, b) expr f = subpath (a, b) of f enddef;
+
+def setuplengtharray (suffix cum, tot, idx) =
+ save cum, tot, idx; idx := 0; tot := makelengtharray (cum)
+enddef;
+
+vardef pathtime@# (suffix p) =
+ if @# <= 0: 0
+ elseif @# >= 1: length p
+ else:
+ setuplengtharray (cum, tot, idx) p;
+ gettime (cum, idx) (@#*tot)
+ fi
+enddef;
+
+vardef pathpoint (expr frac) (suffix p) =
+ convertpath (_pp) p; pnt[pathtime[frac] (_pp)] (p)
+enddef;
+
+def coloraddto (expr clr) (suffix u) (expr v) =
+ addto u also v _wc_ clr;
+enddef;
+
+def orto (suffix u) (expr v) = addto u also v; enddef;
+
+def coloraddon (expr clr) (suffix v) =
+ addto active_plane also v _wc_ clr;
+enddef;
+
+def _orto (suffix u, v) =
+ addto u also v;
+enddef;
+
+vardef interior expr c =
+ newpicture (v);
+ addto v contour (c.t_);
+ v
+enddef;
+
+vardef interiors suffix cc =
+ newpicture (_ints);
+ for _idx = 1 upto cc:
+ addto _ints also interior cc[_idx]);
+ endfor
+ _ints
+enddef;
+
+def clipto (suffix vt) expr c =
+ if path c:
+ clip vt to c;
+ fi
+enddef;
+def clipsto (suffix vt, cc) =
+ begingroup
+ save _cl, _cl_; picture _cl, _cl_; _cl_ := nullpicture;
+ for _idx = 1 upto cc:
+ _cl := vt; clip _cl to cc[_idx]; addto _cl_ also _cl;
+ endfor
+ vt := _cl_;
+ endgroup
+enddef;
+
+vardef Clipped (suffix vt) expr c =
+ setpicture (_Cl) vt; clipto (_Cl) c; _Cl
+enddef;
+
+vardef picneg (suffix vt) expr c =
+ setpicture (_cl) vt; clip _cl to c;
+ newpicture (_pn);
+ addto _pn also (interior c ) _wc_ fillcolor;
+ addto _pn also _cl _wc_ background;
+ _pn
+enddef;
+
+def shpath (suffix v) (expr q, f) =
+ addto v doublepath (f.t_) withpen (q.t_);
+enddef;
+
+numeric minpenwd;
+minpenwd := .05bp; % 1 pixel at 1440dpi
+vardef picpath expr d =
+ newpicture (v);
+ if penwd >= minpenwd:
+ shpath (v, drawpen) (d);
+ fi
+ v
+enddef;
+
+def picdot (suffix v) (expr w, p) =
+ addto v also
+ (w shifted p);
+enddef;
+
+vardef setdot (expr apath, sc) =
+ if cycle apath: interior
+ else: picpath
+ fi
+ (apath scaled emax (sc, minpenwd))
+enddef;
+
+vardef shaded (expr clr) expr c =
+ if cycle c:
+ newpicture (v);
+ addto v contour c _wc_ clr;
+ v
+ else: picpath c % should we? or just make it null?
+ fi
+enddef;
+
+vardef fillwith (suffix v) (expr pic, dims, ll, ur) =
+ newpicture (b);
+ for s = xpart ll step xpart dims until xpart ur:
+ addto b also pic shifted (s, 0);
+ endfor
+ for s = ypart ll step ypart dims until ypart ur:
+ addto v also b shifted (0, s);
+ endfor
+enddef;
+
+def thatchf (suffix v) (expr CT, sp, a, b) =
+ begingroup
+ setnumeric (_sp) signof (ypart b - ypart a) abs(sp);
+ for _y = _sp*( ceiling ((ypart a)/_sp) ) step _sp until ypart b:
+ shpath (v, hatchpen)
+ ( ( (xpart a, _y)--(xpart b, _y) ) transformed CT );
+ endfor
+ endgroup
+enddef;
+
+def axialgradientf (suffix clr, v) (expr theta, sp, a, b) =
+ begingroup
+ save _hh, _sp, _nn, _y;
+ _hh := ypart b - ypart a;
+ _sp := signof (_hh) abs(sp);
+ _nn := emax (1, round (_hh/_sp));
+ _sp := _hh/_nn + signof (_hh) epsilon;
+ _nn := _nn-1;
+ setpath (_p) rect ((xpart a, 0),(xpart b, _sp));
+ _y := ypart a;
+ for _i = 0 upto _nn:
+ addto v contour (_p shifted (0,_y)) rotated theta
+ withcolor clr(_i/_nn);
+ _y := _y + _sp;
+ endfor
+ endgroup
+enddef;
+
+def areagradientf (suffix clr, v) (expr sp, tp, a, b) =
+begingroup
+ save _ww, _hh, _sp, _tp, _nn, _mm, _x, _y;
+ _ww := xpart b - xpart a;
+ _hh := ypart b - ypart a;
+ _sp := signof (_ww) abs(sp);
+ _tp := signof (_hh) abs(tp);
+ _nn := emax (1, round (_ww/_sp));
+ _mm := emax (1, round (_hh/_tp));
+ _sp := _ww/_nn + signof (_ww) epsilon;
+ _tp := _hh/_mm + signof (_hh) epsilon;
+ _mm := _mm-1; _nn := _nn-1;
+ setpath (_p) rect (origin,(_sp,_tp));
+ _x := xpart a; y_a := ypart a;
+ for _i = 0 upto _nn:
+ _y := y_a;
+ for _j = 0 upto _mm:
+ addto v contour (_p shifted (_x,_y)) withcolor
+ clr(_i/_nn,_j/_mm);
+ _y := _y + _tp;
+ endfor
+ _x := _x + _sp;
+ endfor
+endgroup
+enddef;
+
+path unitcircle;
+unitcircle := fullcircle scaled 2;
+def radialgradientf (suffix clr, v) (expr sp, ctr, rad) =
+ begingroup
+ save _sp, _r, _nn;
+ _nn := emax (1, round (rad/sp));
+ _sp := rad/_nn + epsilon;
+ _nn := _nn - 1;
+ _r := _sp;
+ % fill the small center circle first
+ addto v contour (unitcircle scaled _r shifted ctr)
+ withcolor clr(0);
+ for _i = 1 upto _nn:
+ addto v contour
+ (unitcircle scaled (_r + _sp) -- reverse unitcircle scaled _r
+ --cycle) shifted ctr withcolor clr(_i/_nn);
+ _r := _r + _sp;
+ endfor
+ endgroup
+enddef;
+
+def tile (suffix atile) (expr unit, width, height, clipit) =
+ picture atile.pic; atile.pic := nullpicture;
+ pair atile.dims;
+ atile.dims := (width, height)*unit;
+ begingroup
+ save active_plane;
+ def active_plane = atile.pic enddef;
+ save ztr, vtr; transform ztr, vtr;
+ ztr := identity scaled unit; vtr := ztr;
+ save xneg, xpos, yneg, ypos;
+ xneg := 0; xpos := width; yneg := 0; ypos := height;
+ save ClipOn; boolean ClipOn;
+ if clipit:
+ ClipOn := true;
+ setarray (path) (ClipPath) (rect(origin, atile.dims));
+ else:
+ ClipOn := false;
+ fi
+enddef;
+def endtile =
+ DoClip (active_plane);
+ endgroup
+enddef;
+
+vardef is_tile (suffix atile) =
+ (known atile.pic ) and (picture atile.pic) and
+ (known atile.dims) and (pair atile.dims )
+enddef;
+
+vardef pnt@# (expr p) = point @# of p enddef;
+vardef pre@# (expr p) = precontrol @# of p enddef;
+vardef post@# (expr p) = postcontrol @# of p enddef;
+
+numeric bbox_split; bbox_split := 4;
+def getbbox (suffix ll, ur) expr g =
+ ll := llcorner g; ur := urcorner g;
+ if showbbox: noclip ( safedraw rect (ll, ur) ); fi
+enddef;
+
+def getradius (suffix rad) expr g =
+ setsplit (_s) bbox_split;
+ rad := abs (pnt0 (g));
+ for _j = 1 upto length g:
+ rad := emax(rad, abs(pnt[_j] (g)));
+ endfor
+ for _j = 1 upto _s*(length g):
+ ctrlsradius (rad) subpath ((_j-1)/_s, _j/_s) of g;
+ endfor
+enddef;
+
+def ctrlsradius (suffix rad) expr p =
+ rad := emax( emax (rad, abs(post0 (p))), abs(pre1 (p) ))
+enddef;
+
+def safedraw = colorsafedraw (drawcolor) enddef;
+def colorsafedraw (expr clr) expr d =
+ begingroup
+ setpicture (v) picpath d;
+ DoClip (v); coloraddon (clr, v);
+ endgroup
+enddef;
+
+def NoCycle (expr s) expr p =
+ GBwarn s & " cannot be applied to an open path."
+ & " The path will be drawn instead.";
+ safedraw p;
+enddef;
+
+def safefill = colorsafefill (fillcolor) enddef;
+vardef colorsafefill (expr clr) expr c =
+ if cycle c:
+ setpicture (v) interior c;
+ DoClip (v);
+ coloraddon (clr, v);
+ else: NoCycle("fill") c;
+ fi
+enddef;
+def safeunfill expr c =
+ if cycle c: noclip (colorsafefill (background) c);
+ else: NoCycle("unfill") c;
+ fi
+enddef;
+
+def safeclip expr c =
+ if cycle c: clipto (active_plane) c;
+ else: NoCycle("clip") c;
+ fi
+enddef;
+
+def store (suffix fs) expr f =
+hide (
+ if (not path f) and (not pair f):
+ GBerrmsg ("Improper expression type.")
+ "The second argument to `store' must be a path or pair.";
+ fi
+ if not path fs: path fs; fi
+ fs := f
+)
+enddef;
+vardef stored (suffix fs) expr f = store (fs) f; f enddef;
+
+def drawn = colordrawn (drawcolor) enddef;
+vardef colordrawn (expr clr) expr f =
+ colorsafedraw (clr) (zconv (f)); f
+enddef;
+
+def zigzag = colorzigzag (drawcolor) enddef;
+def colorzigzag (expr clr) = colorwiggle (false, clr, 0) enddef;
+def sinewave = colorsinewave (drawcolor) enddef;
+def colorsinewave = colorwiggle (true) enddef;
+
+vardef colorwiggle (expr smth, clr, tens, blen, elen, len, wid) expr f
+=
+ convertpath (g) f;
+ setuplengtharray (cumlen, totlen, ct) g;
+ save B;
+ if cycle f:
+ B := 0;
+ else:
+ B := abs(blen)/_rescale_factor;
+ totlen := totlen - B - abs(elen)/_rescale_factor;
+ fi
+ setnumeric (n) 2*round (totlen/len*_rescale_factor);
+ if n < 2:
+ colorsafedraw (clr) g;
+ else:
+ save T, U, X, Y, Z, p;
+ pair U, X, Y, Z; path p;
+ T := if cycle f: 0 else: gettime (cumlen, ct) (B) fi;
+ Z := pnt[T] (g);
+ p :=if not cycle f: (subpath (0,T) of g)
+ if smth: {curl 0} ..tension tens.. else: -- fi
+ fi
+ for i = 1 upto n:
+ hide(
+ T := gettime (cumlen, ct) (B+(i/n)*totlen);
+ X := Z; Z := pnt[T] (g);
+ Y := .5[X,Z]; U := sgn (Z-X);
+ )
+ (Y + (U zscaled (0, if even i: - fi wid)))
+ if smth: {U}..tension tens.. else: -- fi
+ endfor
+ if cycle f: cycle
+ else: if smth: {curl 0} fi (subpath (T, length g) of g)
+ fi;
+ newpicture (v);
+ shpath (v, drawpen) (p);
+ DoClip(v); coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+def corkscrew = colorcorkscrew (drawcolor) enddef;
+vardef colorcorkscrew (expr clr, tens, blen, elen, len, wid) expr f =
+ convertpath (g) f;
+ setuplengtharray (cumlen, totlen, ct) g;
+ save B;
+ if cycle f:
+ B := 0;
+ else:
+ B := abs(blen)/_rescale_factor;
+ totlen := totlen - B - abs(elen)/_rescale_factor;
+ fi
+ setnumeric (n) round (totlen/len*_rescale_factor);
+ if n < 2:
+ colorsafedraw (clr) g;
+ else:
+ save T, U, X, Y, Z, p;
+ pair U, X, Y, Z; path p;
+ T := if cycle f: 0 else: gettime (cumlen, ct) (B) fi;
+ Z := pnt[T] (g);
+ p :=if (not cycle f) and (B > 0): (subpath (0,T) of g)-- fi
+ for i = 1 upto n:
+ hide(
+ T := gettime (cumlen, ct) (B+(i/n)*totlen);
+ X := Z; Z := pnt[T] (g);
+ Y := .5[X,Z]; U := sgn (Z-X);
+ )
+ (X + (U zscaled (0,-wid))){ U}..tension tens..
+ (Y + (U zscaled (0, wid))){-U}..tension tens..
+ endfor
+ if cycle f: cycle
+ else:
+ {U}(Z + (U zscaled (0,-wid)))
+ if elen <> 0: --(subpath(T, length g) of g) fi
+ fi;
+ newpicture (v);
+ shpath (v, drawpen) (p);
+ DoClip(v); coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+def filled = colorfilled (fillcolor) enddef;
+vardef colorfilled (expr clr) expr c =
+ colorsafefill (clr) zconv (c); c
+enddef;
+vardef unfilled expr c = safeunfill zconv (c); c enddef;
+vardef Clip expr c = safeclip zconv (c); c enddef;
+
+numeric shadewd; shadewd := 0.5bp;
+path shadedotpath;
+shadedotpath := fullcircle;
+
+vardef shade (expr sp) expr f =
+ convertpath (g) f;
+ setnumeric (gr) 1 - (.88*abs(shadewd)/sp)**2;
+ if not cycle g: NoCycle("shade") g;
+ elseif gr <= 0: safefill g;
+ else:
+ colorsafefill (gr*white) g;
+ fi
+ f
+enddef;
+
+polkadotwd := 5bp;
+mindotspace := 1bp;
+path polkadotpath; polkadotpath := fullcircle;
+
+vardef polkadot (expr sp) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("polkadot") g;
+ elseif sp <= emax (2*polkadotwd/3, mindotspace):
+ safefill g;
+ else:
+ setbbox (ll, ur) g;
+ save dx, dy, dshift; pair dshift;
+ dx := sp/2; dy := dx*sqrt 3;
+ dshift := (xpart(ur - ll) mod dx, ypart (ur - ll) mod dy)/2;
+ save p, dims; pair p, dims;
+ p := ll + dshift;
+ dims := 2(dx, dy);
+ setpicture (thepolkadot) setdot (polkadotpath, polkadotwd);
+ newpicture (v);
+ fillwith (v) (thepolkadot, dims, p, ur);
+ fillwith (v) (thepolkadot, dims, p + (dx, dy), ur);
+ DoClip (v); clipto (v) g;
+ coloraddon (fillcolor, v);
+ fi
+ f
+enddef;
+
+def thatch = colorthatch (hatchcolor) enddef;
+vardef colorthatch (expr clr) (expr sp, theta) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("hatch") g;
+ elseif sp <= abs(hatchwd): colorsafefill (clr) g;
+ else:
+ newpicture (v);
+ setbbox (ll, ur) g rotated -theta;
+ thatchf (v, identity rotated theta, sp, ll, ur);
+ DoClip (v); clipto (v) (g);
+ coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+def hhatch (expr sp) = thatch (sp, 0) enddef;
+def vhatch (expr sp) = thatch (sp, 90) enddef;
+def lhatch (expr sp) = thatch (sp, -45) enddef;
+def rhatch (expr sp) = thatch (sp, 45) enddef;
+
+def xhatch = colorxhatch (hatchcolor) enddef;
+def colorxhatch (expr clr, sp) =
+ colorthatch (clr) (sp, 45) colorthatch (clr) (sp, -45)
+enddef;
+
+vardef axialgradient (suffix clr) (expr sp, theta) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("axialgradient") g;
+ else:
+ newpicture (_grd);
+ setbbox (ll, ur) g rotated -theta;
+ axialgradientf (clr, _grd) (theta, sp, ll, ur);
+ DoClip (_grd); clipto (_grd) (g);
+ _orto (active_plane, _grd);
+ fi
+ f
+enddef;
+
+vardef areagradient (suffix clr) (expr sp, tp) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("areagradient") g;
+ else:
+ newpicture (_agr);
+ setbbox (ll, ur) g;
+ areagradientf (clr, _agr) (sp, tp, ll, ur);
+ DoClip (_agr); clipto (_agr) (g);
+ _orto (active_plane, _agr);
+ fi
+ f
+enddef;
+
+vardef radialgradient (suffix clr) (expr sp, ctr) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("radialgradient") g;
+ else:
+ setpair (_ctr) zconv (ctr);
+ newpicture (_agr);
+ save _rad;
+ getradius (_rad) g shifted - _ctr;
+ radialgradientf (clr, _agr) (sp, _ctr, _rad);
+ DoClip (_agr); clipto (_agr) (g);
+ _orto (active_plane, _agr);
+ fi
+ f
+enddef;
+
+vardef NoTile (suffix atile) expr g =
+ GBwarn str atile & " is not a valid tile for tess()."
+ & " The path will be drawn instead.";
+ safedraw g;
+enddef;
+vardef tess (suffix atile) expr c =
+ convertpath (_g) c;
+ if not cycle _g: NoCycle("tess") _g;
+ elseif not is_tile (atile): NoTile (atile) _g;
+ else:
+ setbbox (_ll, _ur) _g;
+ newpicture (_ts);
+ fillwith (_ts) (atile.pic, atile.dims, _ll, _ur);
+ DoClip (_ts); clipto (_ts) _g;
+ _orto (active_plane, _ts);
+ fi
+ c
+enddef;
+
+if unknown segment_split: segment_split := 8; fi
+if unknown dashsize: dashsize := 3bp; fi
+if unknown dashgap: dashgap := dashsize + 2penwd; fi
+if unknown dash_finish: dash_finish := .5; fi
+if unknown dash_start: dash_start := .5; fi
+if unknown _rescale_factor: _rescale_factor := 0.1in; fi
+
+numeric last_dot_size; last_dot_size := 0;
+vardef gendashed (suffix pat) expr f =
+ convertpath (_g) f;
+ save _dpat;
+ if not mkdasharrays (pat) (_dpat):
+ GBwarn "Dash pattern " & str pat
+ & " undefined. Path will be drawn instead.";
+ safedraw _g;
+ elseif _dpat.rep < 2:
+ safedraw _g;
+ else:
+ save _dl;
+ forsuffixes _s = start, rep, finish:
+ _dl._s := 0;
+ for i = 1 upto _dpat._s:
+ _dpat._s[i] := _dpat._s[i]/_rescale_factor;
+ _dl._s := _dl._s + _dpat._s[i];
+ endfor
+ endfor
+
+ if _dl.rep = 0:
+ GBwarn "Dash pattern " & str pat & " has length 0. "
+ & "Path will be drawn instead.";
+ safedraw _g;
+ else:
+ setuplengtharray (_cumlen, _totlen, _ct) _g;
+ save _n, _sf, _no_dots;
+ boolean _no_dots; _no_dots := true;
+ _sf := scale_adjust (_n, _dl) (_totlen);
+ if _n < 0: safedraw _g;
+ else:
+ forsuffixes _s = start, rep, finish:
+ for _i = 1 upto _dpat._s:
+ if (_dpat._s[_i] = 0) and _no_dots: _no_dots := false;
+ else: _dpat._s[_i] := _dpat._s[_i]*_sf;
+ fi
+ endfor
+ _dl._s := _dl._s*_sf;
+ endfor
+ if _no_dots:
+ else:
+ if unknown plot_pic:
+ save plot_pic; path plot_pic;
+ plot_pic := dotpath;
+ fi;
+ last_dot_size :=
+ if known plot_pic.size: plot_pic.size else: penwd fi;
+ setpicture (dashingdot) makesymbol (plot_pic, last_dot_size);
+ fi
+ save _t, _d, _v;
+ picture _v; _v := nullpicture;
+ _d0 := 0; _t0 := 0;
+ dashit (_dpat.start) (_v);
+ if _n > 0:
+ save _m; _m := ceiling sqrt(_n);
+ for _j = 0 step _m until _n - 1:
+ for _i = 0 upto _m - 1:
+ exitif (_i + _j) > _n - 1;
+ _d0 := _dl.start + (_j + _i)*_dl.rep;
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ dashit (_dpat.rep) (_v);
+ endfor
+ DoClip (_v);
+ coloraddon (drawcolor, _v);
+ _v := nullpicture;
+ endfor
+ fi
+
+ _d0 := _totlen - _dl.finish;
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ dashit (_dpat.finish) (_v);
+ DoClip (_v);
+ coloraddon (drawcolor, _v);
+ fi
+ fi
+ fi
+ f
+enddef;
+
+vardef makelengtharray (suffix clen) suffix p =
+ setsplit (_s) segment_split;
+ numeric clen[];
+ clen := _s * length p; clen0 := 0;
+ for _i = 1 upto clen:
+ clen[_i] := clen[_i-1] + abs (pnt[_i/_s] (p) - pnt[(_i-1)/_s] (p))
+ / _rescale_factor;
+ endfor
+ clen[clen]
+enddef;
+
+vardef scale_adjust (suffix n, pl) (expr lngth) =
+ n := (lngth - pl.start - pl.finish)/pl.rep;
+ n := if n < 0: -1 else: round(n) fi;
+ lngth/(pl.start + emax (n, 0)*pl.rep + pl.finish)
+enddef;
+
+vardef gettime (suffix arr, ct) (expr lngth) =
+ setnumeric (_gtl) emax (arr[ct], emin (arr[arr], lngth));
+ setsplit (_s) segment_split;
+ forever: exitif inrange (arr[ct], arr[ct+1]) (_gtl);
+ next ct;
+ endfor
+ if arr[ct] = arr[ct+1]: ct
+ else: ( ct + (_gtl - arr[ct]) / (arr[ct+1] - arr[ct]) )
+ fi /_s
+enddef;
+
+def next suffix X = X := X + 1; enddef;
+
+def dashit (suffix pos) (suffix pic) =
+ for _k = 1 upto pos:
+ if odd _k:
+ if pos[_k] = 0:
+ _d1 := _d0; _t1 := _t0;
+ picdot (pic, dashingdot, pnt [_t0] (_g));
+ else:
+ _d1 := _d0 + pos[_k];
+ _t1 := gettime (_cumlen, _ct) (_d1);
+ shpath (pic, drawpen) (subpath (_t0, _t1) of _g);
+ fi
+ else:
+ _d0 := _d1 + pos[_k];
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ fi
+ endfor
+enddef;
+
+def dashpat (suffix pat) (text t) =
+ list (pat) (t);
+ if (pat = 0) or (odd (pat) and (pat > 1)):
+ pat[incr pat] := 0;
+ fi
+enddef;
+
+vardef mkdasharrays (suffix src, dest) =
+ save _bad; boolean _bad; _bad := false;
+ forsuffixes _s = start, rep, finish:
+ numeric dest._s, dest._s[];
+ boolean _bad._s;
+ if knownnumericarray src._s:
+ copyarray (src._s) (dest._s);
+ _bad._s := false;
+ else:
+ _bad := _bad._s := true;
+ fi
+ endfor
+ % _bad = one of the three arrays not copied.
+ if _bad:
+ if knownnumericarray src: _bad := false;
+ if _bad.rep: % make dest.rep = src
+ copyarray (src) (dest.rep);
+ fi
+ if _bad.start: % shrink first dash to get dest.start
+ copyarray (src) (dest.start);
+ dest.start1 := dash_start*src1;
+ fi
+ if _bad.finish: % use partial first dash for dest.finish
+ dest.finish := 1;
+ dest.finish1 := dash_finish*src1;
+ fi
+ fi
+ fi
+ not _bad
+enddef;
+
+vardef Dashed (expr dlen, dgap) expr f =
+ save dashes; dashpat (dashes) (dlen, dgap);
+ gendashed (dashes) f
+enddef;
+
+def DASHED = Dashed enddef;
+
+vardef doplot (expr spath, sc, dgap) expr f =
+ save dots; dashpat (dots) (0, dgap);
+ setpicture (plot_pic) makesymbol (spath, sc);
+ plot_pic.size := sc;
+ gendashed (dots) f
+enddef;
+
+path dotpath; dotpath := fullcircle;
+def dotted = doplot (dotpath) enddef;
+
+vardef plotnodes (expr symbol, size) expr f =
+ if size > 0:
+ save pln; pair pln[];
+ pln := 0;
+ for _a = 0 upto (length f) if cycle f: - 1 fi:
+ pln[incr pln] := pnt[_a] (f);
+ endfor
+ dosymbols (drawcolor, symbol, size) (pln);
+ fi
+ f
+enddef;
+
+def showcontrols = colorshowcontrols (pointcolor) enddef;
+vardef colorshowcontrols (expr clr, syma, symb, size) expr f =
+ save shpre, shpost;
+ pair shpre[], shpost[];
+ shpre := 0; shpost := 0;
+ for a = 0 upto (length f) if cycle f: - 1 fi:
+ shpre [incr shpre] := pre [a] (f);
+ shpost[incr shpost] := post[a] (f);
+ colorsafedraw (clr)
+ (zconv (shpre[shpre]--pnt[a](f)--shpost[shpost]));
+ endfor
+ if size > 0:
+ if not numeric syma: dosymbols (clr, syma, size) (shpre) ; fi
+ if not numeric symb: dosymbols (clr, symb, size) (shpost); fi
+ fi
+ f
+enddef;
+
+def doubledraw = colordoubledraw (drawcolor) enddef;
+vardef colordoubledraw (expr clr, sep) expr f =
+ convertpath (g) f;
+ colorsafedraw (clr) (parapath ( sep/2) g);
+ colorsafedraw (clr) (parapath (-sep/2) g);
+ f
+enddef;
+
+vardef centerit (expr pic) =
+ pic shifted -(0.5[urcorner pic, llcorner pic])
+enddef;
+
+vardef makesymbol (expr spath, sc) =
+ if picture spath :
+ spath
+ elseif path spath: setdot (spath, sc)
+ elseif string spath:
+ spath infont defaultfont scaled defaultscale
+ else:
+ GBwarn "Undefined symbol for plotting, "
+ & "dotpath will be used instead.";
+ setdot (dotpath, sc)
+ fi
+enddef;
+
+vardef bpoint (expr ptwd, b) =
+ fullcircle scaled ptwd shifted b
+enddef;
+
+def pointd (expr ptwd, filled) (text t) =
+ if filled:
+ plotsymbol (SolidCircle, ptwd) (t);
+ else:
+ begingroup;
+ setboolean (clearsymbols) true;
+ plotsymbol (Circle, ptwd) (t);
+ endgroup
+ fi
+enddef;
+
+boolean clearsymbols; clearsymbols := false;
+vardef clearable (expr pth) =
+ if path pth:
+ ( pnt0 (pth) = pnt[length pth] (pth) ) and (not cycle pth)
+ and (length pth > 0)
+ else: false
+ fi
+enddef;
+
+def clearopenpath expr f =
+ if clearable (f): safeunfill f & cycle; fi
+enddef;
+
+def plotsymbol = colorplotsymbol (pointcolor) enddef;
+def colorplotsymbol (expr clr, spath, sc) (text t) =
+ if sc > 0:
+ begingroup
+ setpairs (_cpls) (t);
+ if _cpls > 0: dosymbols (clr, spath, sc) (_cpls); fi
+ endgroup
+ fi
+enddef;
+
+def dosymbols (expr clr, spath, sc) (suffix arr) =
+ if clearsymbols and clearable (spath):
+ addsymbols (background, makesymbol (spath&cycle, sc)) (arr);
+ fi
+ addsymbols (clr, makesymbol (spath, sc)) (arr);
+enddef;
+
+def addsymbols (expr clr, symb) (suffix arr) =
+ newpicture (_pls);
+ for _idx = 1 upto arr:
+ picdot (_pls, symb, zconv (arr[_idx]));
+ endfor
+ DoClip (_pls); coloraddon (clr, _pls);
+enddef;
+
+def putimage (suffix pic) (text t) =
+ newpicture (_pti);
+ for _itm = t:
+ addto _pti also
+ (pic shifted zconv (_itm));
+ DoClip (_pti); addto active_plane also _pti;
+ _pti := nullpicture;
+ endfor
+enddef;
+
+def arrowdraw (expr hlen) (expr f) =
+ store (curpath) headpath (hlen, 0, 0) drawn f;
+enddef;
+
+def xaxis (expr hlen) = arrowdraw (hlen) ((xneg, 0)--(xpos, 0));
+enddef;
+def yaxis (expr hlen) = arrowdraw (hlen) ((0, yneg)--(0, ypos));
+enddef;
+def axes (expr hlen) = xaxis (hlen); yaxis (hlen); enddef;
+
+laxis := baxis := raxis := taxis := 0;
+
+vardef xlow = xneg + laxis enddef;
+vardef xhigh = xpos - raxis enddef;
+vardef ylow = yneg + baxis enddef;
+vardef yhigh = ypos - taxis enddef;
+
+vardef axisline.x = (xlow, 0)--(xhigh, 0) enddef;
+vardef axisline.y = (0, ylow)--(0, yhigh) enddef;
+vardef axisline.l = axisline.y shifted (xlow, 0) enddef;
+vardef axisline.b = axisline.x shifted (0, ylow) enddef;
+vardef axisline.r = axisline.y shifted (xhigh, 0) enddef;
+vardef axisline.t = axisline.x shifted (0, yhigh) enddef;
+
+vardef axis@# (expr len) = headpath (len, 0, 0) axisline@# enddef;
+
+vardef borderrect =
+ rect((xlow,ylow),(xhigh,yhigh))
+enddef;
+
+vardef between (expr A, B, X) = (A < X) and (X < B) enddef;
+vardef inrange (expr A, B, X) = (A <= X) and (X <= B) enddef;
+
+vardef inbounds (expr Z) =
+ inrange (xlow, xhigh) (xpart Z) and inrange (ylow, yhigh) (ypart Z)
+enddef;
+
+tertiarydef X isbetween P = between (xpart P, ypart P, X) enddef;
+tertiarydef X isinrange P = inrange (xpart P, ypart P, X) enddef;
+tertiarydef P contains X = between (xpart P, ypart P, X) enddef;
+
+numeric inside, outside, centered, onleft, onright, ontop, onbottom;
+inside := -2;
+outside := -1;
+onright := 1;
+onleft := 2;
+centered := .5[onright, onleft];
+onbottom := onright;
+ontop := onleft;
+ltick := rtick := ttick := btick := inside;
+xtick := ytick := centered;
+
+vardef axismarks (expr inang, tp, loc, pdir) (expr len) (text t) =
+ save _tp, _U, _P, _tic, _ticang;
+ pair _U, _P; path _tic;
+ _ticang := if tp < 0: inang else: 90 fi;
+ _tp := abs(tp) - 1;
+ _U := unitvector (vconv (pdir)) rotated _ticang;
+ _tic := (-_U--(0,0)) shifted (_tp*_U) scaled len;
+ for _a = t:
+ safedraw (_tic shifted zconv (loc + _a*pdir));
+ endfor
+enddef;
+
+def xmarks = axismarks ( 90, xtick, origin, right) enddef;
+def ymarks = axismarks (-90, ytick, origin, up) enddef;
+def lmarks = axismarks (-90, ltick, (xlow, 0), up) enddef;
+def bmarks = axismarks ( 90, btick, (0, ylow), right) enddef;
+def rmarks = axismarks ( 90, rtick, (xhigh, 0), up) enddef;
+def tmarks = axismarks (-90, ttick, (0, yhigh), right) enddef;
+
+path griddotpath; griddotpath := fullcircle;
+def grid = vargrid (0.5bp) enddef;
+vardef vargrid (expr dsize, xsp, ysp) =
+ save gdot, gridpic; picture gdot, gridpic;
+ gdot := setdot (griddotpath, dsize);
+ gridpic := nullpicture;
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ for m = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ picdot (gridpic, gdot, zconv ((n*xsp, m*ysp)));
+ endfor
+ endfor
+ coloraddon (pointcolor, gridpic);
+enddef;
+def vgrid = vargrid enddef;
+
+def hgridlines (expr ysp) =
+ for n = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ safedraw zconv ((xlow, n*ysp)--(xhigh, n*ysp));
+ endfor
+enddef;
+def vgridlines (expr xsp) =
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ safedraw zconv ((n*xsp, ylow)--(n*xsp, yhigh));
+ endfor
+enddef;
+def gridlines (expr xsp, ysp) =
+ vgridlines (xsp); hgridlines (ysp);
+enddef;
+
+def vectorfield (expr len, xsp, ysp) (text fcn) (text cond) =
+ save _vf, _is_OK;
+ vardef _vf (expr x,y) = ((0,0)--(fcn)) shifted (x,y) enddef;
+ vardef _is_OK (expr x,y) = cond enddef;
+ mkvectorfield (len, xsp, ysp) (_vf, _is_OK);
+enddef;
+
+vardef mkvectorfield (expr len, xsp, ysp) (suffix vf, isOK) =
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ for m = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ if isOK (n*xsp,m*ysp): arrowdraw (len) (vf(n*xsp,m*ysp)); fi
+ endfor
+ endfor
+enddef;
+
+def plrvectorfield (expr len, rsp, tsp) (text fcn) (text cond) =
+ save _vf, _is_OK, _A, _B, _C, _D;
+ _A := xlow; _B := xhigh;
+ _C := ylow; _D := yhigh;
+ vardef _vf (expr r,t) = ((0,0)--(fcn)) shifted (r*dir t) enddef;
+ vardef _is_OK (expr r,t) =
+ save _X, _Y; _X := r*cosd t; _Y := r*sind t;
+ (cond) and between (_A, _B) (_X) and between (_C, _D) (_Y)
+ enddef;
+ mkplrvectorfield (len, rsp, tsp) (_vf, _is_OK);
+enddef;
+
+vardef mkplrvectorfield (expr len, rsp, tsp) (suffix vf, isOK) =
+ save rmin, rmax, tmin, tmax;
+ getpolarbounds;
+ if rmin = 0:
+ if isOK (0,tmin): arrowdraw (len) (vf (0,tmin)); fi
+ rmin := rsp;
+ fi
+ for n = ceiling (rmin/rsp) upto floor (rmax/rsp):
+ for m = ceiling (tmin/tsp) upto floor (tmax/tsp):
+ if isOK (n*rsp,m*tsp): arrowdraw (len) (vf (n*rsp,m*tsp)); fi
+ endfor
+ endfor
+enddef;
+
+def patcharcs (suffix X) (expr rstart, rstop, rstep, tstart, tstop) =
+ for rad = (if rstart = 0: rstep else: rstart fi)
+ step rstep until rstop:
+ orto (X, picpath zconv (arcplr (origin, tstart, tstop, rad)) );
+ endfor
+enddef;
+def patchrays (suffix X) (expr tstart, tstop, tstep, rstart, rstop) =
+ for _ang = tstart step tstep until tstop:
+ orto (X) (picpath zconv ((rstart*dir _ang)--(rstop*dir _ang)));
+ endfor
+enddef;
+
+def plrpatch (expr rstart, rstop, rstep, tstart, tstop, tstep) =
+begingroup
+ newpicture (v);
+ patcharcs (v) (rstart, rstop, rstep, tstart, tstop);
+ coloraddon (drawcolor, v);
+ v := nullpicture;
+ patchrays (v) (tstart, tstop, tstep, rstart, rstop);
+ coloraddon (drawcolor, v);
+endgroup
+enddef;
+
+def gridarcs (expr rstep) =
+ beginpolargrid;
+ if rmin = 0:
+ picdot (gridpic, setdot (griddotpath, penwd), zconv (origin));
+ fi
+ rmin := rstep * floor (rmin/rstep + 1);
+ rmax := rstep * ceiling (rmax/rstep - 1);
+ patcharcs (gridpic) (rmin, rmax, rstep, tmin, tmax);
+ endpolargrid (drawcolor, .5penwd);
+enddef;
+
+def gridrays (expr tstep) =
+ beginpolargrid;
+ tmin := tstep * ceiling (tmin/tstep);
+ tmax := tstep * floor (tmax/tstep);
+ patchrays (gridpic) (tmin, tmax, tstep, rmin, rmax);
+ endpolargrid (drawcolor, .5penwd);
+enddef;
+
+def polargrid (expr rstep, tstep) =
+ gridarcs (rstep); gridrays (tstep);
+enddef;
+
+def polargridpoints (expr dsize, rstep, tstep) =
+ beginpolargrid;
+ setpicture (gdot) setdot (griddotpath, dsize);
+ if rmin = 0:
+ picdot (gridpic, gdot, zconv (origin));
+ rmin := rstep;
+ fi
+ for n = ceiling (rmin/rstep) upto floor (rmax/rstep):
+ for m = ceiling (tmin/tstep) upto floor (tmax/tstep):
+ picdot ( gridpic, gdot, zconv ( polar ((n*rstep, m*tstep)) ) );
+ endfor
+ endfor
+ endpolargrid (pointcolor, .5dsize);
+enddef;
+
+def beginpolargrid =
+begingroup;
+ save rmax, rmin, tmax, tmin;
+ getpolarbounds;
+ newpicture (gridpic);
+enddef;
+
+def getpolarbounds =
+ save p, r, t;
+ pair p[];
+ p0 := (xneg, yneg); p1 := (xneg, ypos);
+ p2 := (xpos, ypos); p3 := (xpos, yneg);
+ r0 := abs(p0); rmax := r0;
+ for j = 1 upto 3:
+ r[j] := abs(p[j]);
+ if rmax < r[j]: rmax := r[j]; fi
+ endfor
+ rmin := 0;
+ if between (xneg, xpos) (0) and between (yneg, ypos) (0):
+ tmin := 0; tmax := 360;
+ elseif (p0 = origin): tmin := 0; tmax := 90;
+ elseif (p1 = origin): tmin := -90; tmax := 0;
+ elseif (p2 = origin): tmin := -180; tmax := -90;
+ elseif (p3 = origin): tmin := 90; tmax := 180;
+ else:
+ tmax := tmin := t0 := angle p0;
+ for j = 1 upto 3:
+ t := t0 + anglefromto (p0, p[j]);
+ if tmax < t: tmax := t; fi
+ if tmin > t: tmin := t; fi
+ endfor
+ if between (xneg, xpos) (0):
+ rmin := emin (abs(yneg), abs(ypos));
+ elseif between (yneg, ypos) (0):
+ rmin := emin (abs(xneg), abs(xpos));
+ else:
+ rmin := min (r0, r1, r2, r3);
+ fi
+ fi
+enddef;
+
+
+def endpolargrid (expr clr, size)=
+ clipto (gridpic) rect ( zconv ((xneg, yneg)) - size*(1,1),
+ zconv ((xpos, ypos)) + size*(1,1) );
+ coloraddon (clr, gridpic);
+ endgroup
+enddef;
+
+vardef polarpatch (expr rstart, rstop, rstep, tstart, tstop, tstep) =
+ plrpatch (rstart, rstop, rstep, tstart, tstop, tstep);
+ safedraw zconv ( arcplr (origin, tstart, tstop, rstop) );
+ safedraw zconv ( ((rstart, 0)--(rstop, 0)) rotated tstop );
+enddef;
+
+vardef rect (expr ll, ur) =
+ ll--(xpart ur, ypart ll)--ur--(xpart ll, ypart ur)--cycle
+enddef;
+vardef triangle (expr A, B, C) = A--B--C--cycle enddef;
+
+vardef regularpolygon (expr n) (suffix Bob) (text eqns) =
+ pair Bob[]; Bob := emax (round (abs (n)), 2);
+ eqns;
+ for _uncle = 1 upto Bob - 1:
+ (Bob1 - Bob0) rotated (360/Bob*_uncle) = Bob[_uncle+1] - Bob0;
+ endfor
+ mkpoly (true) (Bob)
+enddef;
+
+vardef altitudept expr n of t =
+ save A, B, C, zz; pair A, B, C, zz;
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ zz = whatever[B,C];
+ zz = pnt[n](t) + whatever*((C-B) rotated 90);
+ zz
+enddef;
+
+vardef altitude expr n of t =
+ (pnt[n](t))--(altitudept n of t)
+enddef;
+
+vardef medianpt expr n of t =
+ 0.5[pnt[n + 1] (t), pnt[n + 2] (t)]
+enddef;
+
+vardef median expr n of t =
+ (pnt[n](t))--(medianpt n of t)
+enddef;
+
+vardef anglebisectorpt expr n of t =
+ save A, B, C; pair A, B, C;
+ A := pnt[n ] (t);
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ save zz; pair zz;
+ zz = whatever[B,C];
+ zz = A + whatever*((B-A) rotated (.5*cornerangle (A,B,C)));
+ zz
+enddef;
+
+vardef anglebisector expr n of t =
+ (pnt[n](t))--(anglebisectorpt n of t)
+enddef;
+
+vardef anglefromto (expr u, v) =
+ if (u = origin) or (v = origin): 0
+ else: angle (v rotated (-angle u))
+ fi
+enddef;
+
+vardef cornerangle (expr A, B, C) =
+ if (A = B) or (A = C) :
+ if (B = C) : 60
+ else: 90
+ fi
+ else: anglefromto (B - A, C - A)
+ fi
+enddef;
+
+vardef mkpath (expr smooth, tens, cyclic) (suffix pts) =
+ if smooth: mksmooth (tens)
+ else: mkpoly
+ fi (cyclic, pts)
+enddef;
+
+vardef mkpoly (expr cyclic) (suffix pts) =
+ for _i = 1 upto pts-1: pts[_i]-- endfor
+ pts[pts] if cyclic: -- cycle else: {0,0} fi
+enddef;
+
+vardef polyline (expr cyclic) (text t) =
+ setpairs (_pl) (t);
+ if _pl=0: NoPoints ("polyline", _pl); fi
+ mkpoly (cyclic, _pl)
+enddef;
+
+def NoPoints (expr s) (suffix pts) =
+ GBwarn s & " attempted with empty list."; pts[incr pts] := origin;
+enddef;
+
+vardef turtle (text t) =
+ setnumeric (_tu) 0;
+ setpair (_tmp) origin;
+ pair _tu[];
+ for _a = t:
+ _tmp := _tmp + _a;
+ _tu[incr _tu] := _tmp;
+ endfor
+ if _tu = 0: NoPoints("turtle", _tu); fi
+ mkpoly (false, _tu)
+enddef;
+
+vardef brownianpath (expr start, num, sc) =
+ setnumeric (_brp) 1;
+ setpair (_tmp) start;
+ pair _brp[]; _brp1 := _tmp;
+ for _idx := 1 upto num:
+ _tmp := _tmp + sc/(sqrt 2)*(normaldeviate,normaldeviate);
+ _brp[incr _brp] := _tmp;
+ endfor
+ mkpoly (false, _brp)
+enddef;
+vardef randomwalk (expr start, num, dst) =
+ setnumeric (_rdw) 1;
+ setpair (_tmp) start;
+ pair _rdw[]; _rdw1 := _tmp;
+ for _idx := 1 upto num:
+ _tmp := _tmp + dst*dir(uniformdeviate(360));
+ _rdw[incr _rdw] := _tmp;
+ endfor
+ mkpoly (false, _rdw)
+enddef;
+vardef browniangraph (expr num, scst) =
+ setnumeric (_brg) 1;
+ pair _tmp, _brg[]; _tmp := _brg1 := (0,0);
+ for _idx := 1 upto num:
+ _tmp := _tmp + scst*(1,normaldeviate);
+ _brg[incr _brg] := _tmp;
+ endfor
+ mkpoly (false, _brg)
+enddef;
+
+vardef mksmooth (expr tens, cyclic) (suffix pts) =
+ if pts = 1: onepointpath (cyclic, pts1)
+ else:
+ settension (_tn) tens; fixtension (_tn);
+ pts1 if cyclic: {pts[2]-pts[pts]} fi
+ for _i = 2 upto pts-1:
+ ..tension _tn..pts[_i]{pts[_i+1]-pts[_i-1]}
+ endfor
+ ..tension _tn..pts[pts]
+ if cyclic: {pts[1]-pts[pts-1]}..tension _tn..cycle fi
+ fi
+enddef;
+
+vardef mktenser (expr tens, cyclic) (suffix pts) =
+ if pts = 1: onepointpath (cyclic, pts1)
+ else:
+ settension (_tn) tens; fixtension (_tn);
+ pts1 if cyclic: {pts[2]-pts[pts]} fi
+ for _i = 2 upto pts-1:
+ ..tension atleast _tn..pts[_i]{pts[_i+1]-pts[_i-1]}
+ endfor
+ ..tension atleast _tn..pts[pts]
+ if cyclic: {pts[1]-pts[pts-1]}..tension atleast _tn..cycle fi
+ fi
+enddef;
+
+vardef mkconvex (expr tens, cyclic) (suffix pts) =
+ save _B, _d, _tmp; pair _d[];
+ settension (_tn) tens; fixtension (_tn);
+ if pts < 4: mktenser (_tn, cyclic) (pts)
+ else:
+ for _j = 2 upto pts - 1:
+ _B[_j] := sqrt(abs((pts[_j]-pts[_j-1])xprod(pts[_j+1]-pts[_j])));
+ endfor
+ if cyclic:
+ _B1 := sqrt(abs((pts1 - pts[pts])xprod(pts2 - pts1)));
+ _B[pts] := sqrt(abs((pts[pts]-pts[pts-1])xprod(pts1 - pts[pts])));
+ else:
+ _B1 := _B2;
+ _B[pts] := _B[pts-1];
+ fi
+ for _j = 2 upto pts - 1:
+ _tmp := _B[_j-1] + _B[_j+1];
+ _d[_j] :=
+ if _tmp = 0: origin % signal to use curl1
+ else:
+ ( _B[_j+1]*(pts[_j] - pts[_j-1]) +
+ _B[_j-1]*(pts[_j+1] - pts[_j]) )/_tmp
+ fi;
+ endfor
+ if cyclic:
+ _tmp := _B[pts] + _B2;
+ _d1 :=
+ if _tmp = 0: origin
+ else:
+ (_B2*(pts1 - pts[pts]) + _B[pts]*(pts2 - pts1))/_tmp
+ fi;
+ _tmp := _B[pts-1] + _B1;
+ _d[pts] :=
+ if _tmp = 0: origin
+ else:
+ ( _B1*(pts[pts] - pts[pts-1]) +
+ _B[pts-1]*(pts1 - pts[pts]) )/_tmp
+ fi;
+ else:
+ _d1 := origin; _d[pts] := origin;
+ fi
+ pts1
+ for _j = 1 upto pts-1:
+ {if _d[_j] = origin: curl1 else: _d[_j] fi}
+ ..tension atleast _tn..pts[_j+1]
+ endfor
+ {if _d[pts] = origin: curl1 else: _d[pts] fi}
+ if cyclic: ..tension atleast _tn..cycle fi
+ fi
+enddef;
+
+numeric default_tension; default_tension := 1;
+def curve = tcurve (default_tension) enddef;
+vardef tcurve (expr tens, cyclic) (text t) =
+ setpairs (_tc) (t);
+ if _tc=0: NoPoints("curve", _tc); fi
+ mksmooth (tens, cyclic, _tc)
+enddef;
+
+def ccurve = tccurve (default_tension) enddef;
+vardef tccurve (expr tens, cyclic) (text t) =
+ setuniquepairs (_tcc) (t);
+ if _tcc=0: NoPoints("ccurve", _tcc); fi
+ mkconvex (tens, cyclic, _tcc)
+enddef;
+
+vardef mkbezier (expr tens, cyclic) (suffix pts) =
+ settension (_tn) tens; fixtension (_tn);
+ pts1
+ for _i = 2 upto pts: ..tension _tn..pts[_i] endfor
+ if cyclic: ..tension _tn..cycle else: {0,0} fi
+enddef;
+
+def bezier = tbezier (default_tension) enddef;
+vardef tbezier (expr tens, cyclic) (text t) =
+ setpairs (_tbs) (t);
+ if _tbs=0: NoPoints ("bezier", _tbs); fi
+ mkbezier (tens, cyclic) (_tbs)
+enddef;
+
+vardef mkqbezier (expr cyclic) (suffix pts) =
+ pts1
+ if pts=1: {0,0}
+ else:
+ for _i = 2 step 2 until pts - 1:
+ ..controls 1/3[pts[_i], pts[_i-1]]
+ and 1/3[pts[_i], pts[_i+1]].. pts[_i+1]
+ endfor
+ if cyclic:
+ ..controls 1/3[ pts[pts], pts[pts - 1] ]
+ and 1/3[ pts[pts], pts1 ]..cycle
+ fi
+ fi
+enddef;
+
+vardef qbezier (expr cyclic) (text t) =
+ setpairs (_qbz) (t);
+ if _qbz=0: NoPoints ("qbezier", _qbz);
+ else:
+ if (cyclic and odd _qbz) or (not cyclic and even _qbz):
+ _qbz[incr _qbz] := _qbz[_qbz-1];
+ fi
+ mkqbezier (cyclic) (_qbz)
+ fi
+enddef;
+
+vardef mkcbezier (expr cyclic) (suffix pts) =
+ pts1
+ if pts=1: {0,0}
+ else:
+ for _i = 1 step 3 until pts - 3:
+ ..controls pts[_i+1] and pts[_i+2] .. pts[_i+3]
+ endfor
+ if cyclic:
+ ..controls pts[pts - 1] and pts[pts]..cycle
+ fi
+ fi
+enddef;
+
+vardef cbezier (expr cyclic) (text t) =
+ setpairs (_cbz) (t);
+ if _cbz=0: NoPoints ("qbezier", _cbz);
+ else:
+ % Need 0 mod 3 for cyclic, otherwise 1 mod 3
+ setnumeric (_mdt) _cbz mod 3;
+ if cyclic:
+ if _mdt <> 0: _cbz[incr _cbz] := _cbz[_cbz-1]; fi
+ if _mdt = 1 : _cbz[incr _cbz] := _cbz1; fi
+ else: % need 1 more, duplicate next to last
+ if _mdt = 0:
+ _cbz := _cbz + 1;
+ _cbz[_cbz] := _cbz[_cbz-1];
+ _cbz[_cbz-1] := _cbz[_cbz-2];
+ fi
+ if _mdt = 2: % need 2 more, duplicate last 2.
+ _cbz := _cbz + 2; % add 2 slots
+ _cbz[_cbz] := _cbz[_cbz-2]; % fill them
+ _cbz[_cbz-1] := _cbz[_cbz-2]; % with last node
+ _cbz[_cbz-2] := _cbz[_cbz-3]; % orig last slot = orig previous.
+ fi
+ fi
+ mkcbezier (cyclic) (_cbz)
+ fi
+enddef;
+
+vardef fcncontrol (expr ftens, X, Y, Z) =
+ Y if (xpart(Z-Y) <> 0) and (xpart(Y-X) <> 0):
+ + xpart(Z-Y)/3/xpart(Z-X)*(Z - X)/ftens fi
+enddef;
+
+vardef mkfcnpath (expr ftens) (suffix q) =
+ settension (_tn) ftens;
+ if _tn <= 0: _tn := 1; fi
+ for _i = 1 upto q - 1:
+ q[_i]..controls fcncontrol (_tn) (q[_i-1], q[_i], q[_i+1])
+ and fcncontrol (_tn) (q[_i+2], q[_i+1], q[_i])..
+ endfor
+ q[q]{0,0}
+enddef;
+
+def fcncurve = functioncurve (default_tension) enddef;
+def tfcncurve = functioncurve enddef;
+vardef functioncurve (expr ftens) (text t) =
+ settension (_ftens) ftens; if _ftens < 1/3: _ftens := 1/3; fi
+ setuniquepairs (_fc) (t);
+ if _fc=0: NoPoints ("functioncurve", _fc); fi
+ if _fc > 1: _fc0 := _fc1; _fc[_fc+1] := _fc[_fc]; fi
+ mkfcnpath (_ftens) (_fc)
+enddef;
+
+def openqbs = qspline (false) enddef;
+def closedqbs = qspline (true) enddef;
+
+vardef mkqbs (suffix b) =
+ 0.5[ b1, b2]
+ if b<3: {0,0}
+ else:
+ for _i = 2 upto b-1:
+ ..controls 1/6[ b[_i], b[_i-1] ] and 1/6[ b[_i], b[_i+1] ]..
+ 0.5[ b[_i], b[_i+1] ]
+ endfor
+ fi
+enddef;
+
+vardef qspline (expr cyclic) (text t) =
+ setpairs (_qs) (t);
+ if _qs=0: NoPoints ("qspline", _qs); fi
+ if _qs=1: _qs[incr _qs] := _qs1; fi
+ if cyclic:
+ _qs[incr _qs] := _qs1; _qs[incr _qs] := _qs2;
+ fi
+ mkqbs (_qs) if cyclic: & cycle fi
+enddef;
+
+vardef mkcbs (suffix b) =
+ (b[1]+4b[2]+b[3])/6
+ if b < 4: {0,0}
+ else:
+ for _i = 3 upto b-1:
+ ..controls 1/3[ b[_i-1], b[_i] ] and 1/3[ b[_i], b[_i-1] ]
+ .. (b[_i-1] + 4b[_i] + b[_i+1])/6
+ endfor
+ fi
+enddef;
+
+def mkopencbs = mkcbs enddef;
+vardef mkclosedcbs (suffix b) =
+ mkcbs (b) & opencbs (b[b-2],b[b-1],b[b], b1, b2, b3) & cycle
+enddef;
+
+def opencbs = cspline (false) enddef;
+def closedcbs = cspline (true) enddef;
+
+vardef cspline (expr cyclic) (text t) =
+ setpairs (_cs) (t);
+ if _cs=0: NoPoints ("cspline", _cs); fi
+ for _idx = _cs upto 2: _cs[incr _cs] := _cs[_idx]; endfor
+ if cyclic:
+ for _idx = 1 upto 3: _cs[incr _cs] := _cs[_idx]; endfor
+ fi
+ mkcbs (_cs) if cyclic: & cycle fi
+enddef;
+
+def init_spline_eqns (suffix pts) =
+ save _spl_pre, _spl_post;
+ pair _spl_pre[], _spl_post[];
+ for j= 2 upto pts - 1:
+ _spl_post[j] + _spl_pre[j] = 2pts[j];
+ _spl_pre[j+1]+2_spl_pre[j] = 2_spl_post[j]+_spl_post[j-1];
+ endfor
+enddef;
+
+def closed_spline_eqns (suffix pts) =
+ _spl_post1 + _spl_pre1 = 2pts1;
+ _spl_post[pts] + _spl_pre[pts] = 2pts[pts];
+ _spl_pre2 + 2_spl_pre1 = 2_spl_post1 + _spl_post[pts];
+ _spl_pre1+2_spl_pre[pts] = 2_spl_post[pts]+_spl_post[pts-1];
+enddef;
+
+def relaxed_spline_eqns (suffix pts) =
+ _spl_pre2 + pts1 = 2_spl_post1;
+ pts[pts] + _spl_post[pts-1] = 2_spl_pre[pts];
+enddef;
+
+vardef mksplinepath (expr closed) (suffix pts) =
+ pts1..controls _spl_post1 and
+ for j = 2 upto pts if not closed: -1 fi:
+ _spl_pre[j]..pts[j]..controls _spl_post[j] and
+ endfor
+ if closed: _spl_pre1..cycle else: _spl_pre[pts]..pts[pts] fi
+enddef;
+
+def mkspline (expr closed) (suffix pts) =
+ init_spline_eqns (pts);
+ if closed: closed_spline_eqns (pts);
+ else: relaxed_spline_eqns (pts);
+ fi
+ mksplinepath (closed) (pts)
+enddef;
+
+vardef dospline (expr closed) (text the_list) =
+ setpairs (_sp) (the_list);
+ if _sp=0: NoPoints ("dospline", _sp); fi
+ if _sp=1: _sp[incr _sp] := _sp1; fi
+ mkspline (closed) (_sp)
+enddef;
+
+def init_fcnspl_eqns (suffix pts) =
+ save _dx, _sl; numeric _dx[], _sl[];
+ _dx1 := xpart (pts2 - pts1);
+ for j = 2 upto pts - 1:
+ _dx[j] := xpart (pts[j+1] - pts[j]);
+ _sl[j + 1]*_dx[j] + _sl[j-1]*_dx[j-1] + 2_sl[j]*(_dx[j] + _dx[j-1])
+ = 3*ypart(pts[j+1] - pts[j-1]);
+ endfor
+enddef;
+
+def periodic_fcnspl_eqns (suffix pts) =
+ _sl1 = _sl[pts];
+ _sl2*_dx1 + 2_sl1*_dx1 + 2_sl[pts]*_dx[pts-1] + _sl[pts-1]*_dx[pts-1]
+ = 3 * ypart (pts[2] - pts[pts-1]);
+enddef;
+
+def relaxed_fcnspl_eqns (suffix pts) =
+ _sl2*_dx1 + 2_sl1*_dx1 = 3 * ypart(pts2 - pts1);
+ _sl[pts-1]*_dx[pts-1] + 2_sl[pts]*_dx[pts-1]
+ = 3 * ypart(pts[pts] - pts[pts-1]);
+enddef;
+
+vardef mkfcnsplpath (suffix pts) =
+ pts1..controls (pts1 + (1, _sl1)/3*_dx1) and
+ for j = 2 upto pts - 1:
+ (pts[j] - (1, _sl[j])/3*_dx[j-1]) ..pts[j]..
+ controls (pts[j] + (1,_sl[j])/3*_dx[j]) and
+ endfor
+ (pts[pts] - (1,_sl[pts])*_dx[pts-1]/3)..pts[pts]
+enddef;
+
+vardef mkfcnspline (expr periodic) (suffix pts) =
+ init_fcnspl_eqns (pts);
+ if periodic: periodic_fcnspl_eqns (pts);
+ else: relaxed_fcnspl_eqns (pts);
+ fi
+ mkfcnsplpath (pts)
+enddef;
+
+vardef fcnspline (expr periodic) (text the_list) =
+ setpairs (_fs) (the_list);
+ if _fs<2:
+ if _fs=0: NoPoints ("fcnspline", _fs); fi
+ onepointpath (false, _fs1)
+ else:
+ mkfcnspline (periodic) (_fs)
+ fi
+enddef;
+
+vardef mkarc (expr center, begpt, endpt, sweep) =
+ if (sweep = 0): begpt--endpt
+ else:
+ setnumeric (n) ceiling (abs(sweep)/45);
+ setpair (d) (begpt - center) rotated (signof (sweep) 90);
+ begpt{d}
+ for j = 1 upto n-1:
+ ..(begpt rotatedabout (center, j/n*sweep)){d rotated (j/n*sweep)}
+ endfor ..endpt{d rotated sweep}
+ fi
+enddef;
+
+vardef arc (expr center, begpt, sweep) =
+ if (center = begpt) or (sweep = 0): begpt--begpt
+ else:
+ mkarc (center, begpt, begpt rotatedabout (center, sweep), sweep)
+ fi
+enddef;
+def arccps = arc enddef;
+
+vardef arcpps (expr begpt, endpt, sweep) =
+ if (begpt = endpt) or (sweep = 0): begpt--endpt
+ else:
+ setpair (cd) unitvector (endpt-begpt);
+ if abs(sweep) <= 45:
+ begpt{cd rotated (-sweep/2)}..endpt{cd rotated (sweep/2)}
+ elseif abs(sweep) <= 90:
+ save m; pair m;
+ m = begpt + whatever*( cd rotated (-sweep/4));
+ m = 0.5[begpt, endpt] + whatever*(cd rotated 90);
+ begpt{cd rotated (-sweep/2)}..m{cd}..endpt{cd rotated (sweep/2)}
+ else:
+ setnumeric (ang) 90 - ((sweep/2) mod 180);
+ if abs(ang) = 90:
+ GBwarn "undefined arc. A line segment will be used instead.";
+ begpt--endpt
+ else:
+ save c; pair c;
+ c = begpt + whatever*(cd rotated ang);
+ c = if abs(ang) < 30:
+ (0.5)[begpt, endpt] + whatever*(cd rotated 90)
+ else:
+ endpt + whatever*(-cd rotated -ang)
+ fi;
+ mkarc (c, begpt, endpt, sweep)
+ fi
+ fi
+ fi
+enddef;
+
+vardef arcpp (expr small, begpt, endpt, rad) =
+ save full, diam, chord, ang;
+ full := signof (rad) 360;
+ diam := 2rad;
+ chord := abs(endpt-begpt);
+ if chord < abs(diam):
+ ang := if not small: full - fi 2*asin (chord/diam);
+ else: ang := signof (rad) 180;
+ fi
+ arcpps (begpt, endpt, ang)
+enddef;
+def arcppr (expr begpt, endpt, rad, small) =
+ arcpp (small, begpt, endpt, rad)
+enddef;
+
+vardef arcplr (expr center, frtheta, totheta, rad) =
+ if rad = 0: center--center
+ else:
+ mkarc (center, center + rad*dir frtheta,
+ center + rad*dir totheta, totheta - frtheta)
+ fi
+enddef;
+
+vardef arcalt (expr center, radius, frtheta, totheta) =
+ arcplr (center, frtheta, totheta, radius)
+enddef;
+
+vardef arcppp (expr first, second, third) =
+ arcpps (first, second, 2*cornerangle (third, first, second)) &
+ arcpps (second, third, 2*cornerangle (first, second, third))
+enddef;
+
+vardef ellipse (expr center, radx, rady, angle) =
+ fullcircle xscaled (2*radx) yscaled (2*rady) rotated angle
+ shifted center
+enddef;
+
+vardef circle (expr center, rad) =
+ fullcircle scaled (2*rad) shifted center
+enddef;
+
+vardef circlecp (expr center, point) =
+ mkarc (center, point, point, 360) & cycle
+enddef;
+
+vardef circleppp (expr one, two, three) =
+ arcpps (one, two, 2*cornerangle (three, one, two))
+ & arcpps (two, three, 2*cornerangle (one, two, three))
+ & arcpps (three, one, 2*cornerangle (two, three, one))
+ & cycle
+enddef;
+
+vardef circlepps (expr one, two, sweep) =
+ save ang, full;
+ full := signof (sweep) 360;
+ ang := sweep mod full;
+ arcpps (one, two, ang) & arcpps (two, one, full - ang) & cycle
+enddef;
+
+vardef circlepp (expr small, one, two, rad) =
+ arcpp (small, one, two, rad) & arcpp (not small, two, one, rad)
+ & cycle
+enddef;
+
+def circleppr (expr one, two, rad, small) =
+ circleppr (one, two, rad, small)
+enddef;
+
+vardef quarterellipse(expr A,B,C) =
+ save T_;
+ transform T_;
+ (1,0) transformed T_ = A;
+ (1,1) transformed T_ = B;
+ (0,1) transformed T_ = C;
+ quartercircle scaled 2 transformed T_
+enddef;
+
+vardef halfellipse (expr A,B,C) =
+ save P_; pair P_;
+ P_ = (C - A)/2;
+ quarterellipse (A, B - P_, B) & quarterellipse (B, B + P_, C)
+enddef;
+
+vardef fullellipse (expr C, A, B) =
+ save P_; pair P_;
+ P_ := 2[A,C];
+ halfellipse (A,B,P_) & halfellipse (P_,2[B,C],A) & cycle
+enddef;
+
+vardef pathcenter expr p =
+ save a, cntr, n; pair cntr, a[];
+ n := length p;
+ a1 = pnt 0 (p);
+ a3 = pnt [n/2] (p);
+ if cycle p:
+ a2 = pnt [ n/4] (p);
+ a4 = pnt [3n/4] (p);
+ else:
+ a2 := a3;
+ a4 := pnt[n] (p);
+ fi
+ cntr = .5[a1, a3] + whatever*((a3 - a1) rotated 90);
+ cntr = .5[a2, a4] + whatever*((a4 - a2) rotated 90);
+ cntr
+enddef;
+
+vardef circumcircle expr t =
+ circleppp (pnt0 (t), pnt1 (t), pnt2 (t))
+enddef;
+
+vardef incircle expr t =
+ save A, B, C; pair A, B, C;
+ A := pnt0 (t);
+ B := pnt1 (t);
+ C := pnt2 (t);
+ save a, b, c, D, E, F;
+ D := abs (B-A) = a + b;
+ E := abs (C-B) = b + c;
+ F := abs (A-C) = a + c;
+ circleppp ((a/D)[A,B], (b/E)[B,C], (c/F)[C,A])
+enddef;
+
+vardef excircle expr n of t =
+ save A, B, C; pair A, B, C;
+ A := pnt[n] (t);
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ save a, b, c, D, E, F;
+ D := abs (B-A) = a - b;
+ E := abs (C-B) = b + c;
+ F := abs (C-A) = a - c;
+ circleppp ((a/D)[A,B], (b/E)[B,C], (c/F)[A,C])
+enddef;
+
+vardef ninepointcircle expr t =
+ circleppp (medianpt 0 of t, medianpt 1 of t, medianpt 2 of t)
+enddef;
+
+vardef pshcircle (expr disk, ctr, rad) =
+ if disk:
+ if rad >= 1 :
+ if rad > 1:
+ GBerrmsg ("Impossible radius of pseudohyperbolic circle.")
+ "The radius of a pseudohyperbolic circle can be at most 1.";
+ fi
+ circle ((0,0),1)
+ elseif abs(ctr) >= 1 :
+ if abs(ctr) > 1:
+ GBerrmsg ("Impossible center of pseudohyperbolic circle.")
+ "The center of this pseudohyperbolic circle must be in "
+ & "the unit disk.";
+ fi
+ onepointpath (true,ctr)
+ else:
+ save _r, _dnm;
+ _r := abs(ctr);
+ _dnm := 1 - _r*_r*rad*rad;
+ circle ((1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm)
+ fi
+ else:
+ if rad >= 1 :
+ GBerrmsg ("Impossible radius of pseudohyperbolic circle.")
+ "The radius of a pseudohyperbolic circle must be less than 1.";
+ onepointpath (true,ctr)
+ elseif ypart ctr <= 0:
+ if ypart ctr < 0:
+ GBerrmsg ("Impossible center of pseudohyperbolic circle.")
+ "The center of this pseudohyperbolic circle must be in "
+ & "the upper half-plane.";
+ fi
+ onepointpath (true,ctr)
+ else:
+ save _y, _dnm;
+ _y := ypart ctr;
+ _dnm := 1 - rad*rad;
+ circle ((xpart ctr, (1 + rad*rad)/_dnm * _y), 2rad/_dnm*_y)
+ fi
+ fi
+enddef;
+
+vardef UHPgeodesic (expr A, B) =
+ if xpart A = xpart B:
+ A--B
+ else:
+ save ang_, C_; pair C_;
+ if abs(ypart A) < abs(ypart B):
+ C_ := conj B;
+ else:
+ C_ := conj A;
+ fi
+ if ypart C_ = 0: % both on x-axis
+ ang_ := anglefromto(up, B - A);
+ else:
+ ang_ := anglefromto(A - C_, B - C_);
+ fi
+ arcpps(A, B, 2ang_)
+ fi
+enddef;
+
+vardef UDgeodesic (expr A, B) =
+ save a_, b_;
+ a_ := abs(A); b_ = abs(B);
+ if (a_ = 0) or (b_ = 0):
+ A--B
+ elseif angle A = angle B:
+ A--B
+ else: % note: A, B and B-A are all nonzero from this point
+ save ang_;
+ if a_ = 1:
+ ang_ := anglefromto (if b_>1: A else: -A fi, B-A)
+ elseif b_ = 1:
+ ang_ := anglefromto (A-B, if a_>1: B else: -B fi)
+ else:
+ save C_; pair C_;
+ % reflecting A
+ if a_ < eps:
+ C_ := unitvector A;
+ ang_1 := anglefromto(a_*A - C_, a_*B - C_);
+ else:
+ C_ := (1/a_)*unitvector A;
+ ang_1 := anglefromto(A - C_, B - C_);
+ fi
+ % reflecting B
+ if b_ < eps:
+ C_ := unitvector B;
+ ang_2 := anglefromto(b_*A - C_, b_*B - C_);
+ else:
+ C_ := (1/b_)*unitvector B;
+ ang_2 := anglefromto(A - C_, B - C_);
+ fi
+ ang_ := if abs(ang_1) < abs(ang_2): ang_1 else: ang_2 fi;
+ fi
+ arcpps(A, B, 2ang_)
+ fi
+enddef;
+
+vardef barycenter expr t =
+ save m; m := length t if not cycle t: + 1 fi;
+ pnt0(t)/m for k = 1 upto m - 1: + pnt[k](t)/m endfor
+enddef;
+
+vardef sector (expr center, rad, frtheta, totheta) =
+ center -- arcalt (center, rad, frtheta, totheta) -- cycle
+enddef;
+
+vardef mkbrace (expr S, C, E) =
+ save R_, U_, V_, Z_;
+ pair U_, V_, Z_[];
+ U_ := unitvector (E-S);
+ V_ := U_ rotated 90;
+
+ R_ := 0.5*(C-S) dotprod V_;
+ if R_ = 0:
+ S--C
+ else:
+ if R_ < 0 : V_ := -V_; R_ := -R_; fi
+ V_ := R_*V_; U_ := R_*U_;
+ Z_1 := S + V_ + U_;
+ Z_2 := C - V_ - U_;
+ Z_3 := C - V_ + U_;
+ Z_4 := E + V_ - U_;
+ S{V_}..{U_}Z_1--Z_2{U_}..{V_}C{-V_}..{U_}Z_3--Z_4{U_}..{-V_}E
+ fi
+enddef;
+
+vardef mkfcn (expr sm, tens) (expr bmin, bmax, bst) (text pf) =
+ save _p; pair _p[]; _p := 0;
+ save _dx, _n, _r; numeric _dx, _n, _r;
+ if bmax = bmin: _n := 1;
+ else:
+ _r := bmax - bmin;
+ _dx := max (abs(bst), nottoosmall*abs(_r), epsilon);
+ _n := emax (round(abs(_r)/_dx), 1);
+ fi
+ for _i = 0 upto _n: _p[incr _p] := pf(bmin + _i/_n*_r); endfor
+ mkpath (sm, tens, false, _p)
+enddef;
+
+def tfcn (expr sm) = mkfcn (sm, default_tension) enddef;
+
+def parafcn (expr sm) = tparafcn (sm, default_tension) enddef;
+vardef tparafcn (expr sm, tn) (expr bmin, bmax, bst) (text pf) =
+ save _fp; vardef _fp (expr t) = pf enddef;
+ mkfcn (sm, tn) (bmin, bmax, bst) (_fp)
+enddef;
+
+vardef xfcn (expr sm) (expr xmin, xmax, st) (text _fx) =
+ save _fp; vardef _fp (expr _x) = (_x, _fx(_x)) enddef;
+ mkfcn (sm, default_tension) (xmin, xmax, st) (_fp)
+enddef;
+
+def function (expr sm) = tfunction (sm, default_tension) enddef;
+vardef tfunction (expr sm, tens, xmin, xmax, st) (text _fx) =
+ save _fp; vardef _fp (expr x) = (x, _fx) enddef;
+ mkfcn (sm, tens) (xmin, xmax, st) (_fp)
+enddef;
+
+def btwnfcn (expr sm) = tbtwnfcn (sm, default_tension) enddef;
+vardef tbtwnfcn (expr sm, tn, xlo, xhi, st)(text _fx)(text _gx) =
+ tfunction (sm, tn) (xlo, xhi, st) (_fx) --
+ ( reverse tfunction (sm, tn) (xlo, xhi, st) (_gx) ) -- cycle
+enddef;
+
+def belowfcn (expr sm) = tbelowfcn (sm, default_tension) enddef;
+vardef tbelowfcn (expr sm, tn, xlo, xhi, st)(text _fx) =
+ (xlo,0)--(xhi,0)--
+ (reverse tfunction (sm, tn, xlo, xhi, st)(_fx))--cycle
+enddef;
+
+vardef rfcn (expr sm, tmin, tmax, st) (text ft) =
+ save _fq; vardef _fq (expr t) = (ft(t)) * (dir t) enddef;
+ mkfcn (sm, default_tension) (tmin, tmax, st) (_fq)
+enddef;
+
+def plrfcn (expr sm) = tplrfcn (sm, default_tension) enddef;
+vardef tplrfcn (expr sm, tens, tmin, tmax, st) (text ft) =
+ save _fq; vardef _fq (expr t) = (ft) * (dir t) enddef;
+ mkfcn (sm, tens) (tmin, tmax, st) (_fq)
+enddef;
+
+def btwnplrfcn (expr sm) = tbtwnplrfcn (sm, default_tension) enddef;
+vardef tbtwnplrfcn (expr sm, tn, tlo, thi, st)(text _ft)(text _gt)=
+ tplrfcn (sm, tn, tlo, thi, st) (_ft) --
+ ( reverse tplrfcn (sm, tn, tlo, thi, st) (_gt) ) -- cycle
+enddef;
+
+def plrregion (expr sm) = tplrregion (sm, default_tension) enddef;
+vardef tplrregion (expr sm, tn, tlo, thi, st) (text _ft) =
+ (0,0)--tplrfcn (sm, tn, tlo, thi, st ) (_ft)--cycle
+enddef;
+
+numeric tolerancefactor;
+tolerancefactor := .02;
+
+vardef mklevelset (expr sm, tens, X, Y, t, a, b, c, d) =
+ save _inside_;
+ vardef _inside_ (expr U, V) =
+ inside_levelset(U, V) and between(a, b)(U) and between(c, d)(V)
+ enddef;
+ if not _inside_ (X, Y):
+ GBwarn "Invalid seed point for levelset.";
+ pairmax((a,c), pairmin((X,Y), (b,d)))&cycle
+ else:
+ save ls, W, A, B, prev, curr, seed;
+ pair ls[], prev, curr, seed;
+ seed := (X,Y);
+ ls := 0; W := 0;
+
+ save _first_, _next_, get_next;
+ vardef _first_ (expr U) = _inside_ (U, Y) enddef;
+ vardef _next_ (expr ang) =
+ _inside_ (X_curr + t * cosd ang, Y_curr + t * sind ang)
+ enddef;
+ def get_next (expr angA, angB) =
+ X_curr := xpart curr; Y_curr := ypart curr;
+ ls[incr ls] := curr + t * dir (solve _next_ (angA, angB));
+ prev := curr; curr := ls[ls];
+ W := W + anglefromto (prev - seed, curr - seed);
+ enddef;
+
+ interim tolerance := t*tolerancefactor;
+ ls[incr ls] := (solve _first_ (X, b), Y);
+ curr := ls[ls];
+ interim tolerance := radian*tolerancefactor;
+ get_next (180, 0);
+ for n = 3 upto max_points:
+ A := angle (curr - prev);
+ get_next (A + 120, A - 120);
+ exitif ((abs(W) > 180) or (ls > 10))
+ and (abs(ls[ls] - ls1) < 1.2t);
+ endfor
+ mkpath (sm, tens, true) (ls)
+ fi
+enddef;
+
+numeric max_points;
+max_points := 2000;
+
+def levelset (expr s) = tlevelset (s, default_tension) enddef;
+vardef tlevelset (expr smth, tens, seed, seg) (text cond) =
+ save inside_levelset, _t;
+ vardef inside_levelset (expr x, y) = cond enddef;
+ _t := if seg <= 0: emax (xpos-xneg, ypos-yneg)/max_points * 20
+ else: seg fi;
+ mklevelset (smth, tens, xpart seed, ypart seed, _t)
+ (xneg, xpos, yneg, ypos)
+enddef;
+
+def RKIV (expr sm) = tRKIV (sm, default_tension)
+enddef;
+vardef tRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) =
+ save _trj, _ztr, _dz, _ztmp, _ctm;
+ pair _trj[], % The trajectory
+ _ztr, % current point
+ _dz[], % array[4] of displacements
+ _ztmp; % current point for calculating velocity
+ _trj := N+1; % ultimate size of _trj array
+ _trj1 := _ztr := zstart;
+ save _tt, % current time
+ _dt, % current time step
+ _th; % current time plus half a step
+ _tt := 0;
+ for _idx := 2 upto _trj:
+ _dt := ds/emax(1,abs(_RHS_(_tt,_ztr)));
+ _th := _tt + .5_dt;
+ _dz1 := _dt*_RHS_(_tt, _ztr); % displacement for current point
+ _ztmp := _ztr + .5_dz1; % 1st midpoint
+ % use _th instead of twice calculating (_tt + .5_dt)
+ _dz2 := _dt*_RHS_(_th, _ztmp); % displacement for 1st midpoint
+ _ztmp := _ztr + .5_dz2; % 2nd midpoint
+ _dz3 := _dt*_RHS_(_th, _ztmp); % displacement for 2nd midpoint
+ _ztmp := _ztr + _dz3; % temporary end point
+ % get time for next loop now since we need it in the next line:
+ _tt := _tt + _dt;
+ _dz4 := _dt*_RHS_(_tt, _ztmp); % displacement for end point
+ % get next point
+ _ztr := _ztr + (_dz1 + 2_dz2 + 2_dz3 + _dz4)/6;
+ _trj[_idx] := _ztr;
+ endfor
+ mkpath (sm, tens, false, _trj)
+enddef;
+
+def xyRKIV (expr sm) = txyRKIV (sm, default_tension)
+enddef;
+vardef txyRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) =
+ save _fgxy, __fgxy;
+ vardef __fgxy (expr t, x, y) = _RHS_ enddef;
+ vardef _fgxy (expr t, Z) = __fgxy(t, xpart Z, ypart Z) enddef;
+ tRKIV (sm, tens, zstart, ds, N) (_fgxy)
+enddef;
+
+def odeRKIV (expr sm) = todeRKIV (sm, default_tension)
+enddef;
+vardef todeRKIV (expr sm, tens, xstart, ystart, ds, N)
+(text _fxy) =
+ txyRKIV (sm, tens, (xstart, ystart), ds, N) ((1, _fxy))
+enddef;
+
+vardef lclosed expr f =
+ f
+ if not cycle f:
+ if pnt0(f) = pnt[infinity](f): & else: -- fi cycle
+ fi
+enddef;
+
+def sclosed = sclosedt (default_tension) enddef;
+vardef sclosedt (expr t) expr f =
+ if cycle f: f
+ else: save n; n := length f;
+ if n = 0: f&cycle
+ elseif n = 1: pnt0(f)..tension t..pnt1(f)..tension t..cycle
+ else:
+ (pnt0 (f)) { (pnt1(f)) - (pnt[n] (f)) }..tension t
+ ..(subpath (1, n-1) of f)..tension t
+ ..(pnt[n](f)) { pnt0(f) - pnt[n-1](f) }
+ ..tension t..cycle
+ fi
+ fi
+enddef;
+
+def bclosed = bclosedt (default_tension) enddef;
+vardef bclosedt (expr t) expr f =
+ f
+ if not cycle f:
+ if pnt0(f) = pnt[infinity](f): & else: ..tension t.. fi cycle
+ fi
+enddef;
+
+def uclosed = bclosed enddef;
+def uclosedt = bclosedt enddef;
+
+def cbcontrols (suffix b, t) =
+ b1 := 2[t3, t2];
+ b2 := 2[t2, t1];
+ b3 := 2[b1, b2];
+ b4 := 2[b2, b3];
+enddef;
+
+vardef cbclosed expr f =
+ save n; n := length f;
+ if cycle f: f
+ elseif n = 0: f&cycle
+ else:
+ save p, q, t; pair p[], q[], t[];
+ t1 := pnt0(f); t2 := post0(f); t3 := pre1(f);
+ cbcontrols (p, t); % defines p1 to p4
+ t1 := pnt[n](f); t2 := pre[n](f); t3 := post[n-1](f);
+ cbcontrols (q, t); % defines q1 to q4
+ f..controls q2 and q3..opencbs (q1,q4,p4,p1)
+ ..controls p3 and p2..cycle
+ fi
+enddef;
+
+vardef qbclosed expr f =
+ if cycle f: f
+ else: save n; n := length f;
+ if n = 0: f&cycle
+ else:
+ save p; pair p[]; p := 4;
+ p1 := (3/2)[pnt[n](f), pre[n](f)];
+ p2 := 2[p1, pnt[n](f)];
+ p4 := (3/2)[pnt 0 (f), post0 (f)];
+ p3 := 2[p4, pnt 0 (f)];
+ f & mkqbs (p) & cycle
+ fi
+ fi
+enddef;
+
+vardef makesector expr p = (pathcenter p)--p--cycle enddef;
+
+vardef arccomplement expr p =
+ if cycle p: onepointpath (false, pnt0(p))
+ else:
+ setnumeric (nn) length p;
+ setpairs (pp) (pnt0(p), pnt[.5nn](p), pnt[nn](p));
+ arcpps (pp3,pp1,2*cornerangle(pp2,pp3,pp1))
+ fi
+enddef;
+
+vardef cutoffbefore (expr b) expr f =
+ save t, n; n := length f;
+ if n > 0:
+ for k = 1 upto n:
+ exitif (subpath (0,k) of f) intersects b;
+ endfor
+ if _Xtime < 0:
+ cuttings := pnt0 (f){0,0};
+ f
+ else:
+ cuttings := subpath (0,_Xtime) of f;
+ subpath (_Xtime, n) of f
+ fi
+ else: f
+ fi
+enddef;
+
+vardef cutoffafter (expr b) expr f =
+ setpath (g) cutoffbefore (b) reverse f;
+ cuttings := reverse cuttings;
+ reverse g
+enddef;
+
+vardef trimmedpath (expr btrim, etrim) expr f =
+ save g, h; path g, h;
+ g := invvconv (fullcircle scaled 2btrim) shifted pnt0(f);
+ h := invvconv (fullcircle scaled 2etrim) shifted pnt[length f] (f);
+ cutoffafter (h) cutoffbefore (g) f
+enddef;
+
+vardef predirection@# (expr p) =
+ - postdirection[length p - @#] (reverse p)
+enddef;
+
+vardef postdirection@# (expr p) =
+ save _n; _n := length (p);
+ setpair (v) __dir (subpath (@#, @# + _n) of p);
+ if v = origin:
+ v := - __dir (subpath (@#, @# - _n) of p);
+ fi
+ v
+enddef;
+
+vardef __dir (expr p) =
+ save v, w; pair v, w; w := pnt0 (p);
+ v := origin;
+ for n = 1 upto length (p):
+ v := post[n-1] (p) - w; exitif v <> origin;
+ v := pre [ n ] (p) - w; exitif v <> origin;
+ v := pnt [ n ] (p) - w; exitif v <> origin;
+ endfor
+ sgn v
+enddef;
+
+vardef trivial expr p = (__dir (p) = origin) enddef;
+
+newinternal hdwdr, hdten;
+boolean hfilled;
+
+def headshape (expr wr, tens, fil) =
+ interim hdwdr := wr;
+ interim hdten := if tens>0: tens else: default_tension fi;
+ if hdten < .75: hdten := .75; fi
+ setboolean (hfilled) fil;
+ mkheadpaths;
+enddef;
+def mkheadpaths =
+ save Arrowhead, Leftharpoon, Rightharpoon;
+ path Arrowhead, Leftharpoon, Rightharpoon,
+ Arrowhead.clear, Leftharpoon.clear, Rightharpoon.clear;
+ Rightharpoon := (0,0){down}..tension hdten..(.5hdwdr,-1);
+ Rightharpoon.clear := Rightharpoon--(.5hdwdr,0)--cycle;
+ Leftharpoon := (reverse Rightharpoon) xscaled -1;
+ Leftharpoon.clear := (reverse Rightharpoon.clear) xscaled -1;
+ Arrowhead := Leftharpoon & Rightharpoon;
+ Arrowhead.clear := Leftharpoon.clear & Rightharpoon.clear & cycle;
+ if hfilled:
+ Arrowhead := Arrowhead--cycle;
+ Rightharpoon := Rightharpoon--(0,-1)--cycle;
+ Leftharpoon := Leftharpoon--(0,-1)--cycle;
+ fi
+enddef;
+headshape (1,1,false);
+
+def head = ahead enddef;
+
+vardef ahead (expr clr, front, back, hwr, tens, filled) =
+ settension (_tn) tens; fixtension (_tn);
+ if front <> back:
+ setpair (side) (hwr/2) * ((front-back) rotated 90);
+ setpath (f) (back + side)..tension _tn..
+ {front-back}front{back-front}..tension _tn..(back - side);
+ if clearhead:
+ safeunfill (back - side)--(front-side)--(front+side)--
+ (back+side) & f & cycle;
+ colorsafedraw (background) (back - side)--(front-side)--
+ (front+side)--(back+side) & f & cycle;
+ fi
+ if filled:
+ f := f--cycle;
+ colorsafefill (clr) f;
+ fi
+ colorsafedraw (clr) f;
+ fi
+enddef;
+
+def headpath = Gheadpath (false) (Arrowhead) enddef;
+def headpathx = Gheadpath (true) (Arrowhead) enddef;
+
+def colorheadpath = colorGheadpath (false) (Arrowhead) enddef;
+def colorheadpathx = colorGheadpath (true) (Arrowhead) enddef;
+
+def Gheadpath (expr trim) (suffix ah) =
+ colorGheadpath (trim) (ah) (headcolor)
+enddef;
+vardef colorGheadpath
+(expr trim) (suffix ah) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known ah) and (path ah):
+ convertpath (_g) f;
+ setpair (_P) predirection[length _g] (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ setnumeric (_ang) anglefromto (up, _P);
+ _P := pnt[length _g] (_g) - pos * _P;
+ setpair (_tip) if known ah.tip: ah.tip else: origin fi;
+
+ if trim:
+ if known ah.clear:
+ safeunfill (ah.clear shifted - _tip)
+ scaled sc
+ rotated _ang
+ shifted _P;
+ fi
+ setnumeric (_ys) max(bp, penwd, last_dot_size);
+ safeunfill cut_path
+ xscaled sc yscaled _ys
+ rotated _ang shifted _P;
+ fi
+ if cycle ah: colorsafefill else: colorsafedraw fi (clr)
+ (ah shifted -_tip)
+ scaled sc
+ rotated _ang
+ shifted _P;
+ fi
+ fi
+ f
+enddef;
+
+path cut_path;
+cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle;
+
+def tailpath (suffix sh) = colortailpath (sh) (headcolor) enddef;
+vardef colortailpath (suffix sh) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known sh) and (path sh):
+ convertpath (_g) f;
+ setpair(_P) postdirection0 (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ if cycle sh: colorsafefill else: colorsafedraw fi (clr)
+ (sh if known sh.tip: shifted -sh.tip fi)
+ scaled sc
+ rotated anglefromto (up, _P)
+ shifted (pnt0 (_g) + pos * _P);
+ fi
+ fi
+ f
+enddef;
+
+def midpath (suffix sh) = colormidpath (sh) (headcolor) enddef;
+vardef colormidpath (suffix sh) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known sh) and (path sh):
+ convertpath (_g) f;
+ setnumeric (_t) pathtime[pos] (_g);
+ setpair (_P) postdirection[_t] (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ if cycle sh: colorsafefill else: colorsafedraw fi (clr)
+ sh scaled sc
+ rotated anglefromto (up, _P)
+ shifted (pnt[_t] (_g));
+ fi
+ fi
+ f
+enddef;
+
+vardef signeddeviate primary X =
+ (uniformdeviate 1)[-X,X]
+enddef;
+vardef scaledeviate (expr W, A) =
+ 2 ** (signeddeviate W) * dir A
+enddef;
+vardef polardeviate primary R =
+ (uniformdeviate abs(R)) * dir uniformdeviate 360
+enddef;
+vardef xydeviate primary Z =
+ (signeddeviate (xpart Z), signeddeviate (ypart Z))
+enddef;
+
+vardef randompair (expr maxshift) =
+ if numeric maxshift: polardeviate (maxshift)
+ elseif pair maxshift: xydeviate (maxshift)
+ else: (0,0)
+ fi
+enddef;
+
+vardef detrivialized expr f =
+ save g; path p, g[]; g := 0;
+ for k = 1 upto length f:
+ p := subpath (k-1,k) of f;
+ if not trivial p: g[incr g] := p; fi
+ endfor
+ if g = 0: onepointpath (cycle f, pnt0(f))
+ else: g1 for k = 2 upto g: &g[k] endfor if cycle f: &cycle fi
+ fi
+enddef;
+
+vardef randompath (expr maxshift, weirdness) expr f =
+ save g, n; path g;
+ g := detrivialized f;
+ n := length g;
+ if n = 0:
+ f shifted randompair (maxshift)
+ else:
+ save X, U, V;
+ pair X[], U[], V[];
+ if cycle g: n := n - 1; fi
+ for k = 0 upto n:
+ X[k] := pnt[k](g);
+ U[k] := X[k] - pre[k](g);
+ V[k] := post[k](g) - X[k];
+ endfor
+ save A, B;
+ for k := 0 upto n:
+ X[k] := X[k] shifted randompair (maxshift);
+ A := anglefromto (U[k],V[k]);
+ B := signeddeviate (30weirdness);
+ U[k] := X[k] - (U[k] zscaled scaledeviate (weirdness,B));
+ B := B - A + A * (2 ** signeddeviate weirdness);
+ V[k] := X[k] + (V[k] zscaled scaledeviate (weirdness,B));
+ endfor
+ X0 for k = 1 upto n:
+ .. controls V[k-1] and U[k] .. X[k]
+ endfor
+ if cycle g:
+ .. controls V[n] and U0 .. cycle
+ fi
+ fi
+enddef;
+
+vardef randomlines (expr maxshift) expr f =
+ save g, n; path g;
+ g := detrivialized f;
+ n := length g;
+ if n = 0:
+ f shifted randompair (maxshift)
+ else:
+ if cycle g: n := n - 1; fi
+ (pnt0(g) shifted randompair (maxshift))
+ for k = 1 upto n:
+ -- (pnt[k](g) shifted randompair (maxshift))
+ endfor
+ if cycle g:
+ -- cycle
+ fi
+ fi
+enddef;
+
+vardef interpolatedpath (expr t, P) expr Q =
+ if not path Q:
+ GBerrmsg ("Improper argument to interpolatedpath.")
+ "The last argument to interpolatedpath must be a path.";
+ if pair P: onepointpath(false, P)
+ else:
+ if path P:
+ P
+ else:
+ onepointpath (false, origin)
+ fi
+ fi
+ elseif pair P:
+ interpolated_pair_path (t, cycle Q, P, Q)
+ elseif not path P:
+ GBerrmsg ("Improper argument to interpolatedpath.")
+ "The second argument to interpolatedpath must be a pair "
+ & "or a path.";
+ Q
+ else:
+ if t=0: Q
+ elseif t=1: P
+ else:
+ save P_, Q_; path P_, Q_;
+ P_ := detrivialized P;
+ Q_ := detrivialized Q;
+ if length P_ = 0:
+ interpolated_pair_path (t, cycle Q, pnt0(P_), Q)
+ elseif length Q_ = 0:
+ interpolated_pair_path (t, cycle Q, pnt0(Q_), P)
+ else:
+ save G, H, n, m, k, r;
+ path G[], H[];
+ G := H := 0;
+ n := length P_; m := length Q_;
+ k := gcd(n, m);
+ r := m/k;
+ for I=0 upto n-1:
+ for J=0 upto r-1:
+ G[incr G] := subpath (I+J/r, I+(J+1)/r) of P_;
+ endfor
+ endfor
+ r := n/k;
+ for I=0 upto m-1:
+ for J=0 upto r-1:
+ H[incr H] := subpath (I+J/r, I+(J+1)/r) of Q_;
+ endfor
+ endfor
+ for N = 1 upto G-1:
+ force_equal_ends(G[N], G[N+1]);
+ force_equal_ends(H[N], H[N+1]);
+ endfor
+ interpolated_segment (t, G1, H1)
+ for N = 2 upto G: & interpolated_segment (t, G[N], H[N])
+ endfor if (pnt0(G1)=pnt1(G[G])) and (cycle Q): & cycle fi
+ fi
+ fi
+ fi
+enddef;
+
+vardef interpolated_pair_path (expr t, cyclic, P, Q) =
+ save N; N := length Q;
+ if N=0: onepointpath (cyclic, (t)[pnt0(Q),P])
+ else:
+ (t)[pnt0(Q),P]..controls (t)[post0(Q),P] and
+ for n=1 upto N - 1:
+ (t)[pre[n](Q),P]..(t)[pnt[n](Q),P]..controls (t)[post[n](Q),P]
+ and
+ endfor
+ (t)[pre[N](Q),P].. if cyclic: cycle else: (t)[pnt[N](Q),P] fi
+ fi
+enddef;
+
+vardef interpolated_segment (expr t, S, T) =
+ (t)[ pnt0(S), pnt0(T)]..controls
+ (t)[ post0(S), post0(T)] and (t)[ pre1(S), pre1(T)]..
+ (t)[ pnt1(S), pnt1(T)]
+enddef;
+
+vardef parasegment (expr d, segs, f) =
+ if d = 0: f
+ else:
+ save u, v, t; pair u[], v[];
+ for n = 0 upto segs:
+ t := n/segs;
+ u[n] := postdirection [t] (f);
+ v[n] := pnt[t] (f) + (u[n] zscaled (0,d));
+ endfor
+ v0{u0}
+ for n = 1 upto segs: ...v[n]{u[n]} endfor
+ fi
+enddef;
+
+vardef parapath (expr d) expr f =
+ if d = 0:
+ f
+ else:
+ save a, g, h, p, q, s, t, u, v, w;
+ path g[], h, p[], q[];
+ numeric a, s, t;
+ pair u, v, w, w[];
+ s := emax(3, emin(segment_split, ceiling(max_points/5/length f)));
+ p := 0;
+ for i = 1 upto length f:
+ h := subpath (i-1, i) of f;
+ if not trivial h:
+ q[incr p] := h;
+ p[p] := parasegment (d, s, h);
+ fi
+ endfor
+ if p = 0:
+ f
+ else:
+ a := if d>0: - fi 180;
+ h := p1;
+ for i = 1 upto p-1:
+ u := predirection 1 (q[i]);
+ v := postdirection 0 (q[i+1]);
+ w1 := pnt 1 (q[i]) - (u zscaled (0,d));
+ w2 := pnt 0 (q[i+1]) - (v zscaled (0,d));
+ w3 := pnt [infinity] (h);
+ w4 := pnt 0 (p[i+1]);
+ g0 := arcpps(w3, w1, a);
+ g1 := h & g0;
+ g2 := arcpps(w2, w4, a) & p[i+1];
+ if (p[i] & g0) intersects reverse g2:
+ s := length g2 - _Ytime;
+ t := length h - length p[i] + _Xtime;
+ g1 := subpath (0, t) of g1;
+ g2 := subpath (s, length g2) of g2;
+ force_equal_ends (g1, g2);
+ h := g1 & g2;
+ else:
+ h := h .. p[i+1];
+ fi
+ endfor
+
+ if cycle f:
+ u := predirection 1 (q[p]);
+ v := postdirection 0 (q[1]);
+ w1 := pnt 1 (q[p]) - (u zscaled (0,d));
+ w2 := pnt 0 (q[1]) - (v zscaled (0,d));
+ w3 := pnt [infinity] (h);
+ w4 := pnt 0 (p[1]);
+ g3 := arcpps(w3, w1, a);
+ g0 := arcpps(w2, w4, a);
+ g1 := g0 & h & g3;
+ g2 := g0 & p[1];
+ if (p[p] & g3) intersects reverse g2:
+ s := length g2 - _Ytime;
+ t := length g0 + length h - length p[p] + _Xtime;
+ g1 := subpath (s, t) of g1;
+ force_equal_ends (g1, g1);
+ h := g1 & cycle;
+ else:
+ h := h..cycle;
+ fi
+ fi
+ h
+ fi
+ fi
+enddef;
+
+vardef turnangle@# (expr f) =
+ anglefromto(predirection@# (f), postdirection@#(f))
+enddef;
+
+def setdatadashes (text lst) =
+ save __type; __type := 0;
+ forsuffixes _itm = lst:
+ if knownnumericarray _itm :
+ copyarray (_itm) (__type[__type]);
+ next __type;
+ else: GBwarn "Improper dash pattern in setdatadashes.";
+ fi
+ endfor
+ if __type > 1:
+ save dashtype; dashtype := __type;
+ for _j = 0 upto dashtype - 1:
+ copyarray (__type[_j]) (dashtype[_j]);
+ endfor
+ else:
+ SetdataWarn "dashes";
+ fi
+enddef;
+def getdashpat expr n = dashtype[n mod dashtype] enddef;
+
+def SetdataWarn expr s =
+ GBwarn "command setdata"& s &"() failed. Previous values retained.";
+enddef;
+
+numeric Solid, Simpledash, Simpledot, Dotdash, Dotdashdot, Dotdashdash;
+dashpat (Solid) (0);
+dashpat (Simple_dash) (3bp, 4bp);
+dashpat (Simple_dot) (0, 4bp);
+dashpat (Dot_dash) (0, 4bp, 3bp, 4bp);
+dashpat (Dot_dash_dot) (0, 4bp, 3bp, 4bp, 0, 4bp);
+dashpat (Dot_dash_dash) (0, 4bp, 3bp, 4bp, 3bp, 4bp);
+
+numeric dashtype, dashtype[], dashtype[][];
+def defaultdashes =
+ setdatadashes (Solid, Simple_dash, Simple_dot,
+ Dot_dash, Dot_dash_dot, Dot_dash_dash);
+enddef;
+defaultdashes;
+
+def setdatasymbols (text lst) =
+ save __type; path __type[];
+ __type := 0;
+ for _itm = lst:
+ if (known _itm) and (path _itm):
+ __type[__type] := _itm;
+ next __type;
+ else:
+ GBwarn "Improper symbol in setdatasymbols().";
+ fi
+ endfor
+ if __type > 1:
+ save pointtype; pointtype := __type;
+ path pointtype[];
+ for _j = 0 upto pointtype - 1:
+ pointtype[_j] := __type[_j];
+ endfor
+ else:
+ SetdataWarn "symbols";
+ fi
+enddef;
+def getsymbol expr n := pointtype[n mod pointtype] enddef;
+
+def DeclareGBSymbols (text S) =
+ forsuffixes _itm = S:
+ path _itm;
+ path _itm.clear;
+ pair _itm.tip;
+ endfor
+enddef;
+DeclareGBSymbols(
+ Triangle, Square, Circle, Diamond, Star, Plus, Cross,
+ Asterisk, Crossbar, Leftbar, Rightbar, Righthook,
+ Lefthook, SolidTriangle, SolidSquare, SolidCircle,
+ SolidDiamond, SolidStar
+);
+
+vardef undo_cycle expr f = subpath (0, length f) of f enddef;
+
+SolidTriangle := (up--(dir 210)--(dir -30)--cycle) scaled .78;
+Triangle := undo_cycle SolidTriangle;
+
+Triangle.clear := SolidTriangle.clear :=
+ ((dir -30)--(cosd 30,1)--(cosd 210,1)--(dir 210)--up--cycle)
+ scaled .78;
+
+SolidSquare := (up--(-1,1)--(-1,-1)--(1,-1)--(1,1)--cycle) scaled .443;
+Square := undo_cycle SolidSquare;
+
+SolidCircle := fullcircle rotated 90;
+Circle := undo_cycle SolidCircle;
+Circle.clear := SolidCircle.clear :=
+ halfcircle--(-.5,.5)--(.5,.5)--cycle;
+
+SolidDiamond := (up--left--down--right--cycle)
+ scaled .522 yscaled 1.44;
+Diamond := undo_cycle SolidDiamond;
+Diamond.clear := SolidDiamond.clear :=
+ (right--(1,1)--(-1,1)--left--up--cycle) scaled .522 yscaled 1.44;
+
+Plus := ((0,0)--up--down--(0,0)--left--right) scaled .65;
+Plus.clear := (right--(1,1)--(-1,1)--(left)--cycle) scaled .65;
+
+Cross := ((0,0)--(dir 45)--(dir -135)--(0,0)--(dir -45)--(dir 135))
+ scaled .65;
+Cross.clear :=
+ ((0,0)--(dir -45)--dir(45)--(dir 135)--(dir -135)--cycle) scaled .65;
+
+Asterisk := ((0,0)--up--down--(0,0)--(dir 30)--(dir -150)
+ --(0,0)--(dir -30)--(dir 150)) scaled .6;
+Asterisk.clear := ((0,0)--(dir -30)--(cosd 30,1)--(cosd 150,1)
+ --(dir -150)--cycle) scaled .6;
+
+Crossbar := ((0,0)--left--right) scaled .65;
+Crossbar.clear := rect (right,(-1,.5)) scaled .65;
+
+Leftbar := ((0,0)--left);
+Rightbar := ((0,0)--right);
+Leftbar.clear := rect((0,0),(-1,.5));
+Rightbar.clear := rect((0,0),(1,.5));
+
+Righthook := arcpps((0,0),(1,0),180);
+Lefthook := Righthook xscaled -1;
+Righthook.clear := Righthook--cycle;
+Lefthook.clear := Lefthook--cycle;
+
+vardef mkstar (expr n, m) (suffix A) =
+ save ang; ang := 360/n;
+ A1 := up; A3 := up rotated ang;
+ A2 = (whatever)[A1, A1 rotated ( ang*m)];
+ A2 = (whatever)[A3, A3 rotated (-ang*m)];
+ for i = 4 upto 2n:
+ A[i] := A[i-2] rotated ang;
+ endfor
+ A := 2n;
+ mkpoly (true, A)
+enddef;
+
+save _A; pair _A[];
+SolidStar := mkstar (5, 2, _A) scaled .84;
+Star := undo_cycle SolidStar;
+Star.clear := polyline (true)
+ (_A9, _A10, _A1, _A2, _A3, (xpart _A3, 1), (xpart _A9, 1))
+ scaled .84;
+SolidStar.clear := Star.clear;
+
+forsuffixes S =
+ Triangle, Square, Circle, Diamond, Star, Plus, Cross,
+ Asterisk, Crossbar, Leftbar, Rightbar, Righthook,
+ Lefthook, SolidTriangle, SolidSquare, SolidCircle,
+ SolidDiamond, SolidStar :
+ S.tip := point 0 of S;
+endfor
+
+vardef gcd (expr n, m) =
+ save a, b, r;
+ a := emax (abs(m), abs(n));
+ b := emin (abs(m), abs(n));
+ if b > 0:
+ forever:
+ r := a mod b;
+ exitif r < 1;
+ a := b; b := r;
+ endfor
+ b
+ else:
+ a
+ fi
+enddef;
+
+vardef lcm (expr n, m) =
+ n/gcd(n, m)*m
+enddef;
+
+numeric pointtype; path pointtype[];
+def defaultsymbols =
+ setdatasymbols( Circle, Cross, SolidDiamond, Square, Plus,
+ Triangle, SolidCircle, Star, SolidTriangle);
+enddef;
+defaultsymbols;
+
+def setdatacolors (text lst) =
+ setnumeric (__type) 0;
+ % First, just count and store the known colors in the list
+ for _itm = lst:
+ if knowncolor _itm :
+ if __type = 0 : def _datacolors = _itm enddef;
+ else:
+ expandafter def
+ expandafter _datacolors
+ expandafter = _datacolors, _itm enddef;
+ fi
+ next __type;
+ else: GBwarn "Improper color in setdatacolors().";
+ fi
+ endfor
+ if __type > 1:
+ save colortype, _tmpstr;
+ colortype := 0;
+ % colortype[] is an array of strings:
+ string colortype[], _tmpstr;
+ for _itm = _datacolors: %
+ % Each string is the name of some color variable
+ _tmpstr := "colortype_" & GBromannumeral(colortype);
+ setcolor (scantokens(_tmpstr)) _itm;
+ colortype[colortype] := _tmpstr;
+ next colortype;
+ endfor
+ else:
+ SetdataWarn "colors";
+ fi
+enddef;
+def getcolor expr n = (scantokens (colortype[n mod colortype])) enddef;
+
+numeric colortype; string colortype[];
+
+setcolor (dRed) (1, 0, 0);
+setcolor (dBlue) (.2,.2,1);
+setcolor (dOrange) (1,.34,0);
+setcolor (dGreen) (0,.80,0);
+setcolor (dBlack) cmykblack;
+if has_cmyk :
+ setcolor (dCyan) cyan;
+ setcolor (dMagenta) magenta;
+ setcolor (dYellow) yellow;
+else: % rgb colors seem to be lighter than the cmyk equivalents.
+ setcolor (dCyan) cmyk(.85,0,0,.15);
+ setcolor (dMagenta) cmyk(0,.85,0,.15);
+ setcolor (dYellow) cmyk(0,0,.85,.15);
+fi
+def defaultcolors =
+ setdatacolors(dBlack, dRed, dBlue, dOrange,
+ dGreen, dMagenta, dCyan, dYellow);
+enddef;
+defaultcolors;
+
+def computepie (suffix dat) (expr sign, ang, cent, rad) (text data) =
+begingroup
+ save _tot, _max, _toobig;
+ _max := 0; dat := 0;
+ for _val = data:
+ dat[incr dat] := _val;
+ _max := emax (_max, _val);
+ endfor
+ if dat=0: GBwarn "piechart attempted with empty list.";
+ _toobig := 1;
+ else:
+ _toobig := infinity/dat;
+ fi
+ if _max > _toobig:
+ for _idx = 1 upto dat:
+ dat[_idx] := dat[_idx]/_toobig;
+ endfor
+ fi
+ for _idx = 2 upto dat:
+ dat[_idx] := dat[_idx - 1] + dat[_idx];
+ endfor
+ _tot := dat[dat];
+ for _idx = dat downto 2:
+ dat[_idx] := ang + sign*dat[_idx-1]/_tot*360;
+ endfor
+ dat1 := ang; dat[dat + 1] := ang + 360sign;
+endgroup
+enddef;
+
+def piechart (expr sign, ang, cent, rad) (text data) =
+ save _dat;
+ computepie (_dat) (sign, ang, cent, rad) (data);
+ mkpiewedges (_dat, cent, rad);
+enddef;
+
+def mkpiewedges (suffix dat) (expr cent, rad) =
+ numeric piewedge, piedirection, pieangle, pieangle[];
+ pair piecenter, piedirection[];
+ path piewedge[];
+ piecenter := cent;
+ piedirection := pieangle := piewedge := dat;
+ for _idx = 1 upto dat:
+ pieangle[_idx] := dat[_idx];
+ piewedge[_idx] := sector (piecenter, rad, dat[_idx], dat[_idx+1]);
+ piedirection[_idx] := dir(0.5[ dat[_idx], dat[_idx+1] ]);
+ endfor
+enddef;
+
+def namedpiechart (suffix nm) (expr sign, ang, cent, rad) (text data) =
+ save _dat;
+ computepie (_dat) (sign, ang, cent, rad) (data);
+ setnumeric (nm) _dat;
+ pair nm.center, nm.direction[];
+ path nm.wedge[];
+ nm.center := cent;
+ for _idx = 1 upto _dat:
+ nm.wedge[_idx] := sector (cent, rad, _dat[_idx], _dat[_idx+1]);
+ nm.direction[_idx] := dir(0.5[ _dat[_idx], _dat[_idx+1] ]);
+ endfor
+enddef;
+
+def barchart (expr firstbar, sep, r, vert)(text data) =
+ numeric barbegin, barbegin[],
+ barend, barend[],
+ barlength, barlength[],
+ barstart, barstart[],
+ chartbar, barwd;
+ path chartbar[];
+ chartbar := 0; barwd := r*sep;
+ for _itm = data:
+ barend[incr chartbar]
+ := if pair _itm: ypart _itm else: _itm fi;
+ barbegin[chartbar] := if pair _itm: xpart _itm else: 0 fi;
+ endfor
+ barbegin := barend := barlength := barstart := chartbar;
+ for _nn = 1 upto chartbar:
+ barstart[_nn] := firstbar + sep*(_nn-1);
+ barlength[_nn] := barend[_nn];
+ chartbar[_nn] := rect ((barbegin[_nn], 0), ( barend[_nn], barwd))
+ shifted (0, barstart[_nn]) if vert: xyswap fi;
+ endfor
+enddef;
+
+def namedbarchart (suffix nm) (expr first, sep, r, vert) (text data) =
+ save nm;
+begingroup
+ save _bb, _ee, _ww;
+ path nm.bar[];
+ nm := 0; _ww := r*sep;
+ for _itm = data:
+ _ee := if pair _itm: ypart _itm else: _itm fi;
+ _bb := if pair _itm: xpart _itm else: 0 fi;
+ nm.bar[incr nm] := rect ((_bb, 0), ( _ee, _ww) )
+ shifted (0, first + sep*(nm-1)) if vert: xyswap fi;
+ endfor
+endgroup
+enddef;
+
+picture totalpicture;
+boolean totalnull, currentnull;
+def clearit =
+ currentpicture := totalpicture := nullpicture;
+ currentnull := totalnull := true;
+enddef;
+
+def keepit =
+ addto totalpicture also currentpicture;
+ currentpicture := nullpicture;
+ totalnull := totalnull or currentnull;
+ currentnull := true;
+enddef;
+
+def addto_currentpicture =
+ currentnull := false;
+ addto currentpicture
+enddef;
+
+def mergeit (text do) =
+ if totalnull:
+ do currentpicture
+ elseif currentnull:
+ do totalpicture
+ else:
+ begingroup
+ save _v_; picture _v_;
+ _v_ := currentpicture;
+ addto _v_ also totalpicture;
+ do _v_
+ endgroup
+ fi
+enddef;
+
+boolean noship; noship := false;
+def shipit = if noship: else: mergeit (shipout) fi enddef;
+
+numeric gcode; gcode := 0;
+
+input dvipsnam.mp;
+% end grafbase.mp
+endinput.
+%%
+%% End of file `grafbase.mp'.
diff --git a/graphics/mfpic/source/grafbase.dtx b/graphics/mfpic/source/grafbase.dtx
new file mode 100644
index 0000000000..8b7346720d
--- /dev/null
+++ b/graphics/mfpic/source/grafbase.dtx
@@ -0,0 +1,9710 @@
+% \iffalse
+% File: grafbase.dtx
+% A part of mfpic 1.10 2012/12/03
+%
+% -------------------------------------------------------------------
+%
+% Copyright 2002--2012, Daniel H. Luecking
+%
+% Mfpic may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License, either version 1.3b of this license or (at
+% your option) any later version. The latest version of this license is in
+% <http://www.latex-project.org/lppl.txt>
+% and version 1.3c or later is part of all distributions of LaTeX version
+% 2008/12/01 or later.
+%
+% Mfpic has maintenance status "author-maintained". The Current Maintainer
+% is Daniel H. Luecking. There are several Base Interpreters: plain TeX, LaTeX,
+% plain Metafont and plain MetaPost.
+%
+%<*driver>
+\ProvidesFile{grafbase.dtx}
+ [2012/12/03 v1.10. Metafont/post macros to interface with mfpic.]%
+\documentclass{ltxdoc}
+\usepackage{docmfp}
+
+\addtolength{\textwidth}{.5878pt}
+
+\def\mytt{\upshape\mdseries\ttfamily}
+\renewcommand\marg[1]{{\mytt \{#1\}}}
+\renewcommand\oarg[1]{{\mytt [#1]}}
+\renewcommand\parg[1]{{\mytt (#1)}}
+\renewcommand{\meta}[1]{{$\langle$\rmfamily\itshape#1$\rangle$}}
+\DeclareRobustCommand\cs[1]{{\mytt\char`\\#1}}
+\def\prog#1{{\mdseries\scshape #1}}
+\def\grafbase{\prog{grafbase}}
+\def\Grafbase{\prog{Grafbase}}
+\def\mfpic{\prog{mfpic}}
+\def\Mfpic{\prog{Mfpic}}
+\def\MF{\prog{meta\-font}}
+\def\MP{\prog{meta\-post}}
+\def\PS{\prog{Post\-Script}}
+\def\CMF{\prog{Meta\-font}}
+\def\CMP{\prog{Meta\-post}}
+\def\opt#1{{\sffamily\upshape#1}}
+\def\mfc#1{{\mytt#1}}
+\let\env\mfc
+\let\file\mfc
+\let\gbc\mfc
+\renewcommand\{{{\mytt\char`\{}}
+\renewcommand\}{{\mytt\char`\}}}
+\renewcommand\|{${}\mathrel{|}{}$}
+
+\makeatletter
+\let\HD@SetMacroIndent\@gobble
+\newcommand\bsl{{\mytt\@backslashchar}}
+% Stupid lists!
+\def\@listi{\leftmargin\leftmargini
+ \parsep \z@ \@plus\p@ \@minus\z@
+ \topsep 4\p@ \@plus\p@ \@minus2\p@
+ \itemsep\parsep}
+\let\@listI\@listi \@listi
+\renewcommand\labelitemi{\normalfont\bfseries \textendash}
+\renewcommand\labelitemii{\textasteriskcentered}
+\renewcommand\labelitemiii{\textperiodcentered}
+\leftmargini\parindent
+% Stupid index!
+\def\usage#1{\textrm{#1}}
+\def\index@prologue{\section*{Index}\markboth{Index}{Index}}
+\def\IndexParms{%
+ \parindent \z@ \columnsep 15pt
+ \parskip 0pt plus 1pt
+ \rightskip 5pt plus2em \mathsurround \z@
+ \parfillskip=-5pt \small
+ % less hanging:
+ \def\@idxitem{\par\hangindent 20pt}%
+ \def\subitem{\@idxitem\hspace*{15pt}}%
+ \def\subsubitem{\@idxitem\hspace*{25pt}}%
+ \def\indexspace{\par\vspace{10pt plus 2pt minus 3pt}}}
+\renewcommand\routinestring{}
+\renewcommand\variablestring{\space(var.)}
+% Why does every command have to be indexed twice?
+\renewcommand\SpecialMfpIndex[3]{\@bsphack
+ \index{%
+ \string#1\actualchar
+ \string\verb\quotechar*\verbatimchar\string#1\verbatimchar
+ #2 \encapchar usage}%
+ \@esphack}
+\def\close@crossref{\SpecialEscapechar{:}}
+\makeatother
+\def\VariableIndex#1{\SpecialMfpIndex{#1}{\variablestring}{}}
+\def\RoutineIndex #1{\SpecialMfpIndex{#1}{}{}}
+
+\def\pdfTeX{\textrm{pdf\kern.04em\TeX}}
+\def\pdfLaTeX{\textrm{pdf\kern.06em\LaTeX}}
+\def\ConTeXt{\textrm{Con\kern-.16em\TeX\kern-0.06em t}}
+\def\PiCTeX{\textrm{P\kern-.13em\lower.3ex\hbox{I}C\TeX}}
+
+\title{The \grafbase{} macros\thanks{This file has version number
+ \fileversion, last revised \filedate. The code described here
+ was developed by several people, notably Thomas Leathrum,
+ Geoffrey Tobin and Dan Luecking. Dan wrote this documentation.}}
+\author{Dan Luecking}
+\date{\filedate}
+\SpecialEscapechar{:}
+\def\bslash{:}
+\DisableCrossrefs
+\CodelineIndex
+\AlsoImplementation
+
+\begin{document}
+ \DeleteShortVerb{\|}
+ \DocInput{grafbase.dtx}
+\end{document}
+%</driver>
+%\fi
+%
+% \CheckSum{1631}
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+% \catcode`\_=12
+% \GetFileInfo{grafbase.dtx}
+% \maketitle
+%
+% \begin{abstract}
+% Macros are defined for use with \mfpic{}. The latter is a set of \TeX{}
+% macros which allows a \file{.tex} file to write a \file{.mf} or
+% \file{.mp} file that, with the help of these macros and \MF{} (or \MP),
+% can be used to create pictures in the document, especially mathematical
+% pictures. There are two versions of \grafbase, one for \MF{} and one for
+% \MP{}. As they are more alike than different (95\% of the code is
+% identical), we document both here.
+%
+% This file documents the \grafbase{} source code. The user manual for
+% \mfpic{} is distributed as \file{mfpic-doc.pdf}, produced from
+% \file{mfpic-doc.tex}. An introductory guide to \mfpic{} is available
+% in \file{mfpguide.pdf}, produced from \file{mfpguide.tex}
+% \end{abstract}
+%
+% \StopEventually{\PrintIndex}
+% \tableofcontents
+%
+%
+%
+% \section{Introduction}\label{intro}
+%
+%
+% \subsection{Identification and checks}\label{checks}
+%
+% \DescribeVariable{grafbaseversion} We use \mfc{grafbaseversion} to
+% check if \prog{grafbase} has been previously loaded, later we use it
+% to check a mismatch with the version of \mfpic{} (if used).
+% \gbc{grafbase} was used in previous versions. If either is known, we
+% bail out. The \gbc{grafbase} boolean is really never needed, but it
+% has been around since I took over. It is possible to write files that
+% change behavior when \grafbase{} is loaded, however if they say
+% ``\gbc{if grafbase:}, they can only be called with \gbc{grafbase} a
+% known boolean.
+%
+% \VariableIndex{fileversion} \gbc{fileversion} and
+% \VariableIndex{filedate} \gbc{filedate} provide identifying information.
+%
+% \DescribeRoutine{GBmsg}
+% These are used fairly consistently and identify the source of the
+% message delivered as being `\gbc{Grafbase}'.
+% \DescribeRoutine{GBwarn}
+% Warnings are delivered by \gbc{GBwarn}. The macro \gbc{GBerrmsg} takes
+% care of both the
+% \DescribeRoutine{GBerrmsg}
+% error message and the \mfc{errhelp} string.
+% \begin{macrocode}
+%<*MF|MP>
+if (known grafbaseversion) or (known grafbase):
+ message "Grafbase (" & jobname & "): You have loaded grafbase more "
+ & "than once! Please make sure that it is loaded only once.";
+ endinput;
+fi
+boolean grafbase; grafbase := true;
+
+string fileversion, filedate;
+fileversion := "1.10"; filedate := "2012/12/03";
+
+message " Loading grafbase macros, version " & fileversion & ", " &
+ filedate & ".";
+message " ";
+
+def GBmsg expr s = message "Grafbase (" & jobname & "): " & s;
+enddef;
+def GBwarn expr s = GBmsg "Warning, " & s; enddef;
+def GBerrmsg (expr s) expr t = errhelp t;
+ errmessage "Grafbase (" & jobname & "): " & s; errhelp "";
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeVariable{MFPIC}
+% The \gbc{MFPIC} variable is not yet used at all.
+% It might be possible (at some point) to optimize things for \mfpic{} use
+% whenever \gbc{mfpicversion} is defined, but so far we don't do anything
+% except test the version and set this boolean.
+%
+% \DescribeVariable{mfpicversion}
+% The output file written by the \mfpic{} macros includes a test that
+% \gbc{mfpicversion} and \mfc{grafbaseversion} are the same,
+% but that would fail to catch a new \grafbase{} with an old \mfpic. So
+% we also put a test here with
+% \DescribeRoutine{checkversions}
+% \gbc{checkversions}, though it alone would fail to catch the use
+% of older versions of \grafbase{} with current versions of \mfpic. Newer
+% versions of \mfpic{} signal their version before inputting
+% \file{grafbase}. Unfortunately (for error checking), \grafbase{} can
+% also be used without \mfpic, so if \gbc{mfpicversion} is unknown, we
+% merely write a message.
+% \begin{macrocode}
+boolean MFPIC; MFPIC := false;
+
+def checkversions (expr g)=
+ numeric grafbaseversion; grafbaseversion := g;
+ if unknown mfpicversion: % no mfpic, or < 0.63
+ GBmsg "Recent mfpic not detected.";
+ elseif g = mfpicversion:
+ MFPIC := true;
+ else:
+ message "";
+ GBwarn "Version mismatch: "
+ & "mfpic and grafbase versions do not match.";
+ message "";
+ fi
+enddef;
+
+checkversions (110);
+
+% \end{macrocode}
+%
+% We try to make sure that the macros of \file{plain.mf} or
+% \file{plain.mp} (where \mfc{base_name} is defined to be \mfc{"plain"})
+% are available.
+% \begin{macrocode}
+if unknown base_name : input plain;
+elseif not string base_name: input plain;
+elseif base_name <> "plain": input plain;
+fi
+
+% \end{macrocode}
+%
+% \DescribeRoutine{GBdebug}
+% The \gbc{debug} flag is for developers, who should set it before
+% inputing \file{grafbase}.
+% \DescribeRoutine{GBenddebug}
+% These two routines start and end debug messages.
+%
+% \DescribeRoutine{mftitle}
+% The \gbc{mftitle} macro is useful when debugging.
+% It will put its argument, which should be a string, as a TFM comment,
+% and also print it to the terminal and log file.
+% \begin{macrocode}
+if not boolean debug: boolean debug; debug := false; fi
+
+def GBdebug =
+ begingroup
+ save >>; def >> = message " " & enddef;
+ message "Grafbase DEBUG";
+enddef;
+def GBenddebug =
+ message "End DEBUG";
+ >> "";
+ endgroup
+enddef;
+
+vardef mftitle expr t =
+ if string t: t; message t; fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeVariable{METAPOST}
+% We try to determine which of \MF{} or \MP{} is using these macros.
+% Perhaps one day we'll merge both versions of \grafbase{} in one file and
+% use the following boolean. For now, we only use it to catch cases where
+% the \grafbase{} file is being used by the wrong compiler.
+%
+% Of course, \MP{} natively knows about colors but \MF{} doesn't, so we
+% use that to set a boolean \gbc{METAPOST}. We don't simply check if
+% `\mfc{blue}' is \mfc{known} because `\mfc{blue}' is certainly a legal
+% variable name in \MF. Instead we check `\mfc{known color X}' for
+% some unlikely \gbc{X}. In \MP, `\gbc{color X}' is either true or
+% false (\gbc{X} is a color or it isn't) and therefore always known, so
+% `\gbc{known color X}' is always true.
+%
+% In \MF{} `\mfc{color X}' is an identifier (presumably unknown) with the
+% base name \mfc{color} and suffix \mfc{X}.
+% \begin{macrocode}
+boolean METAFONT, METAPOST;
+METAPOST := known color Carl Philipp Emanuel Bach;
+if METAPOST: METAFONT := false; else: METAFONT := true; fi
+
+%<*MF>
+if METAPOST:
+ GBerrmsg ("wrong compiler.")
+ "This file is for Metafont. For Metapost, use grafbase.mp.";
+fi
+%</MF>
+
+%<*MP>
+if METAFONT:
+ GBerrmsg ("wrong compiler.")
+ "This file is for Metapost. For Metafont, use grafbase.mf.";
+fi
+
+% \end{macrocode}
+%
+% \MP{} now exists in a couple of slightly incompatible versions.
+% Versions 1.000 and later (beta versions 0.9xx also) have native support for
+% \texttt{CMYK} colors with a \mfc{cmykcolor} data type. They also
+% support grayscale colors (i.e., \mfc{withcolor} will accept a numeric
+% expression), and have the alias \mfc{rgbcolor} for \mfc{color}.
+% It also has a means to set the name of the output file: the
+% \mfc{filenametemplate} command. In versions 1.2 and later, this is
+% deprecated in favor of setting the internal string variable
+% \mfc{outputtemplate}.
+% \begin{macrocode}
+numeric metapostversion;
+boolean has_cmyk;
+boolean has_filenametemplate; % e.g., filenametemplate "%j.%n;
+boolean has_outputtemplate; % e.g., outputtemplate := "%j.%n;
+if unknown mpversion:
+ % prior to introduction of cmykcolor and output filename templates.
+ % Latest such version was 0.641.
+ metapostversion := 0.641;
+ has_cmyk := false;
+ has_filenametemplate := false;
+ has_outputtemplate := false;
+else:
+ metapostversion := scantokens (mpversion);
+ has_cmyk := true;
+ has_filenametemplate := true;
+ if metapostversion < 1.200:
+ has_outputtemplate := false;
+ else:
+ has_outputtemplate := true;
+ fi
+fi
+
+%</MP>
+% \end{macrocode}
+%
+%
+% \subsection{Setting up the font, \MF{} only}\label{font}
+%
+% Font-related housekeeping is only for \MF{}. \MF{} only produces
+% fonts, so we have to define the variables it thinks are needed for
+% fonts.
+%
+% \DescribeVariable{GBgeneric}
+% We intercept the \mfc{mode} variable before \mfc{mode_setup} can set
+% \mfc{proof} mode. We used to set \mfc{mode := cx} (and later
+% \mfc{ljfour}) if \mfc{mode} was unknown. For a while we just issued an
+% error message. In this version we define a 600dpi mode called
+% \mfc{GBgeneric} as a fallback (neither \gbc{mode} nor \gbc{localfont}
+% known).
+%
+% The font identifier and coding scheme are just for information and end
+% up as comments in the \file{.tfm} file (in all capitals). The design
+% size just needs to be rather large for graphics, and \mfc{128pt\#} is
+% anyway the default if we didn't set it ourselves.
+% \begin{macrocode}
+%<*MF>
+if unknown mode:
+ GBerrmsg ("Metafont mode is unknown.")
+ "Set mode to a known mode, perhaps ljfour. "
+ & "If you proceed, localfont will be tried. "
+ & "If that is unknown, a generic mode will be tried.";
+ if known localfont: mode := localfont;
+ else:
+ if unknown GBresolution: GBresolution := 600 fi;
+ mode_def GBgeneric =
+ mode_param (pixels_per_inch, GBresolution);
+ mode_param (blacker, 0);
+ mode_param (fillin, 0);
+ mode_param (o_correction, 1);
+ mode_common_setup_;
+ enddef;
+ mode := GBgeneric;
+ fi
+fi
+mode_setup;
+if debug:
+ GBdebug;
+ >> "pixels_per_inch = " & decimal pixels_per_inch;
+ GBenddebug;
+fi
+
+font_identifier := "MFpic graphics";
+font_coding_scheme := "Arbitrary";
+interim designsize := 128pt#;
+
+%</MF>
+% \end{macrocode}
+%
+% \Mfpic-generated files make reference to \mfc{aspect_ratio} and
+% \mfc{pt\#}, while \MP{} has no need for them. Rather than make
+% \mfpic{} write different things, and to make the files intended for
+% \MF{} also work with \MP, we define them in the obvious way. We also
+% add a definition of \mfc{hppp} and \gbc{t_} to simplify maintenance of
+% two versions of the \file{grafbase} files. Then we define
+% \gbc{currenttransform} for \MP{} sake.
+% \begin{macrocode}
+%<MP>pt# := pt; bp# := bp;
+%<MP>def t_ = transformed currenttransform enddef;
+if unknown aspect_ratio: aspect_ratio := 1; fi
+if unknown hppp: hppp := 1 fi;
+if unknown currenttransform:
+ transform currenttransform;
+ currenttransform := identity yscaled aspect_ratio;
+fi
+
+% \end{macrocode}
+%
+% Don't complain when variables get too large. For \MF{} this \emph{must}
+% be after \mfc{mode_setup}. Also don't complain if a clockwise path is
+% filled (only \MF{} worries about this).
+% \begin{macrocode}
+interim warningcheck := 0;
+%<MF>interim turningcheck := 0;
+
+% \end{macrocode}
+%
+%
+% \subsection{Initializations}\label{init}
+%
+% \VariableIndex{unitlen}
+% \VariableIndex{xscale}
+% \VariableIndex{yscale}
+% \VariableIndex{xneg}
+% \VariableIndex{xpos}
+% \VariableIndex{yneg}
+% \VariableIndex{ypos}
+% The following are the various variables determining the extent of a
+% picture. These variables would normally be set by a user for each
+% picture, or by \mfpic, but we give them default values anyway. They
+% give a nominal picture size of one inch with a graph unit corresponding
+% to $1/10$ inch.
+% \begin{macrocode}
+numeric unitlen, xscale, yscale, xneg, xpos, yneg, ypos;
+
+unitlen := 1 bp#;
+xscale := 7.2;
+yscale := 7.2;
+xneg := 0; xpos := 10;
+yneg := 0; ypos := 10;
+
+% \end{macrocode}
+%
+% \DescribeVariable{deg}
+% \VariableIndex{degree}
+% We support both degrees and radians for angles. In \MF, one degree is
+% the unit of angle.
+% \DescribeVariable{radian}
+% One radian is $180/\pi$ degrees. We also define \gbc{pi} so a user can
+% say \gbc{pi/2*radian} for almost the same effect as \gbc{90deg}.
+% \DescribeVariable{pi}
+% But not quite: because of \MF{}'s precision limits, the former is about
+% 90.00025 degrees. \MF{}'s precision is 16 binary places, or slightly
+% under 5 decimals. The accuracy of \gbc{pi} and \gbc{radian} below is the
+% maximum possible. If we \emph{define} \gbc{radian} by its mathematical
+% definition \gbc{radian:=180/pi}, then \gbc{radian} and formulas
+% containing it are even less accurate. (Coincidentally, defining
+% \gbc{radian} as below, and then \gbc{pi := 180/radian} produces exactly
+% the same value for \gbc{pi} as below.)
+% \begin{macrocode}
+newinternal deg, pi, radian;
+deg := 1; pi := 3.14159;
+radian := 57.29578;
+numeric degree; degree := deg;
+
+% \end{macrocode}
+%
+% \VariableIndex{drawpen}
+% \VariableIndex{penwd}
+% \DescribeRoutine{resizedrawpen}
+% Since we need to do this frequently, we define a macro that changes the
+% pen width for subsequent drawing. This enables the file written by
+% \mfpic{} to be less cluttered. At least that was the original reason.
+% Now it gives us the opportunity to localize changes to \mfc{currentpen}
+% and \gbc{drawpen}. (We already had this for different
+% \gbc{beginmfpic}, since that reinitializes drawpen, but now it is local
+% to other groups as well.)
+%
+% \VariableIndex{hatchpen}
+% We could do this for the hatching pen, but it doesn't seem to change as
+% often. The \mfc{pickup} command performs \mfc{yscaled aspect_ratio}, but
+% so does the \gbc{shpath}, the only other place pens are required. In
+% fact, we wouldn't need to \mfc{pickup} the pen at all, except power
+% users may want to rely on \gbc{drawpen} always being the current pen. We
+% make its diameter \mfc{.5pt} for backward compatibility. But many
+% journal publisher (e.g., AMS) recommend no smaller than \mfc{.5bp} for
+% author-supplied drawings.
+%
+% \VariableIndex{hatchwd}
+% The default \gbc{hatchwd} used to be larger, but it seemed ugly to me.
+% (Backward compatibility---what's that?).
+% \begin{macrocode}
+newinternal penwd; penwd := 0.5pt;
+pen drawpen;
+
+def resizedrawpen (expr s) =
+ interim penwd := s;
+ setvariable (pen) (drawpen) pencircle scaled penwd;
+ save currentpen; pen currentpen; pickup drawpen;
+enddef;
+
+numeric hatchwd; hatchwd := 0.5bp;
+pen hatchpen; hatchpen := pencircle scaled hatchwd;
+
+% \end{macrocode}
+%
+% \DescribeVariable{clipall}
+% We have two booleans related to clipping. One, \gbc{clipall} is meant to
+% be turned on just once (per picture), and it causes the \gbc{endmfpic}
+% code to clip the current picture to the boundaries defined by the
+% picture size variables. The other,
+% \DescribeVariable{ClipOn}
+% \gbc{ClipOn}, is meant to be turned on and off. While on, most drawing
+% macros (all?) will clip their result to the current \emph{clipping path
+% array}.
+% \DescribeVariable{ClipPath}
+% The clipping path array is an array of paths: \gbc{ClipPath[\,]} together
+% with a numeric \gbc{ClipPath}. The numeric variable contains the number
+% of clipping paths; the paths are \gbc{ClipPath[1]} through
+% \gbc{ClipPath[ClipPath]}. A macro later on is defined to loop through
+% the array, clipping the current picture to the union of their interiors.
+%
+% \DescribeVariable{truebbox}
+% The \gbc{truebbox} boolean sets the bounding box of the picture to its
+% natural size in \MP. The default behavior of \MP{} is to output a
+% bounding box that is the natural size of the graphic. The \grafbase{}
+% default is to override this default, setting \gbc{truebbox} to
+% \mfc{false}. \CMF's default behavior is to force the user to specify the
+% bounding box, and provides no natural way to obtain any information
+% about the actual extent of the ink. So, for now, this boolean is only
+% for \MP.
+%
+% \DescribeRoutine{DoClip}
+% This is for the frequent conditional code to implement \gbc{ClipOn}.
+% The command \gbc{clipsto} is defined later.
+%
+% \DescribeRoutine{noclip}
+% For debugging we sometimes want to make sure something is drawn
+% without clipping being applied. For this we have \gbc{noclip}.
+% \begin{macrocode}
+boolean clipall; clipall := false;
+boolean ClipOn; ClipOn := false;
+path ClipPath[]; numeric ClipPath; ClipPath = 0;
+boolean truebbox; truebbox := false;
+
+def DoClip (suffix v) =
+ if ClipOn and (ClipPath > 0): clipsto (v, ClipPath); fi
+enddef;
+
+def noclip (text t) =
+ hide ( setboolean (ClipOn) false; t)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeVariable{showbbox}
+% The boolean \gbc{showbbox} is for debugging the \gbc{*bbox} macros.
+% \begin{macrocode}
+boolean showbbox; showbbox := false;
+
+% \end{macrocode}
+%
+%
+% \subsubsection{Colors}\label{colors}
+%
+% Of course colors are only recognized by \MP. The colors \mfc{black},
+% \mfc{white}, \mfc{red}, \mfc{green} and \mfc{blue} are part of
+% \file{plain.mp}. We define other standard colors to get all eight
+% colors where the coordinates are 0 or 1.
+%
+% \DescribeRoutine{color}
+% We define \MF{} replacements for some of the \MP{} color variables and
+% macros. Our point of view will be: make each color variable a numeric in
+% \MF{}. Each will lie between $0$ and $1$ representing shades of gray.
+% For \emph{drawing} commands we will only distinguish between nonwhite
+% (black, ${}<1$) and white (${}\ge1$). For filling commands we will allow
+% levels in between, and fill with an approximation using a version of
+% the \gbc{shade} macro.
+% \begin{macrocode}
+%<*MF>
+let color = numeric; color black, white;
+let rgbcolor = numeric;
+let cmykcolor = numeric;
+black := 0; white := 1;
+def withcolor text t = enddef;
+%</MF>
+%<MP>if not has_cmyk: let rgbcolor = color; let cmykcolor = color; fi
+def _wc_ = withcolor enddef;
+
+% \end{macrocode}
+%
+% \VariableIndex{currentcolor}
+% \VariableIndex{drawcolor}
+% \VariableIndex{fillcolor}
+% \VariableIndex{hatchcolor}
+% \VariableIndex{headcolor}
+% \VariableIndex{pointcolor}
+% \VariableIndex{tlabelcolor}
+% We also define some color variables whose names reflect their use.
+% Thus, \gbc{fillcolor} is used for filling, etc. The color
+% \gbc{currentcolor} isn't used anywhere yet. The color
+% \mfc{background} is used in \MP{} for unfilling a region.
+% \begin{macrocode}
+color currentcolor, drawcolor, fillcolor, hatchcolor,
+ headcolor, pointcolor, tlabelcolor, background;
+currentcolor := fillcolor := drawcolor := hatchcolor :=
+ headcolor := pointcolor := tlabelcolor := black;
+background := white;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{snapto}
+% The \gbc{snapto} macro truncates numerics to the $[0,1]$ range, but also
+% returns a value ($0$) for unknown input. It used to do the same for
+% nonnumeric input, but that should be an error. It would have made at
+% least one of our bugs easier to find if it had produced an error message
+% back then.
+% \begin{macrocode}
+vardef snapto expr t =
+ if numeric t:
+ if unknown t: 0
+ elseif t < 0: 0
+ elseif t > 1: 1
+ else: t
+ fi
+ else:
+ GBerrmsg ("Improper expression type.")
+ "The argument to `snapto' must be a numeric.";
+ fi
+
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{cmykgray}
+% \DescribeRoutine{rgbgray}
+% Now we deal with all the color functions and utilities that enable
+% \mfpic{} users to use colors without knowing what they are doing.
+% Since colors now come in three flavors, we start with gray levels in
+% the three models. In early \MP{}, the \gbc{cmyk} function will return
+% an \opt{rgb} color, so there is will be no difference between these
+% two. In \MF{} \gbc{white} is a numeric and \gbc{cmyk} returns a
+% numeric, so these can be used with \MF{}, and both produce the same
+% result.
+% \begin{macrocode}
+vardef rgbgray (expr g) = (snapto g) * white enddef;
+vardef cmykgray (expr g) = cmyk(0,0,0,1 - snapto g) enddef;
+
+% \end{macrocode}
+%
+%
+% \DescribeRoutine{colorchoice}
+% The \gbc{colorchoice} function (like \cs{mathchoice} in \TeX{}, after
+% which it was named) returns one of four bits of code: \gbc{D} (default)
+% if the first argument is unknown or not one of the recognized color
+% models, \gbc{N} if it is numeric, \gbc{R} if it is \mfc{rgbcolor}, and
+% \gbc{C} if it is \mfc{cmykcolor}. These arguments have to be \mfc{text}:
+% if they were `\mfc{expr}' \MP{} would try to evaluate them, with
+% possible errors since some of them apply functions that are not relevant
+% to the other types.
+%
+% Since this is mostly used to return values inside vardef's, it is
+% important this not be followed by a semicolon. If it is used in
+% another context, semicolons would normally be part of the arguments.
+% \begin{macrocode}
+%<*MP>
+def colorchoice (expr clr) (text D)(text N)(text R)(text C) =
+ if unknown clr: D
+ elseif numeric clr: N
+ elseif rgbcolor clr: R
+ elseif cmykcolor clr: C
+ else: D
+ fi
+enddef;
+
+% \end{macrocode}
+% In recent \MP{}, all the color functions are essentially no-ops. In
+% early \MP{}, they all return an \opt{rgb} color expression. In \MF{}
+% they all return a numeric. It is easiest if we simply separate the three
+% cases (MF, old MP and recent MP) and write the code for each, rather
+% than load all the functions with three-way booleans (often containing
+% nested booleans).
+%
+% \DescribeRoutine{gray}
+% \DescribeRoutine{cmyk}
+% For all three engines we require a definition of the color functions
+% \gbc{gray(g)}, \gbc{rgb(r,g,b)}, and \gbc{cmyk(c,m,y,k)}, as well as
+% conversion functions (see below), and the boolean function
+% \gbc{iscolor}. The first three have to return numerics for \MF{},
+% colors for early \MP{}, and the associated color type for recent \MP{}.
+% We delay the definition of \gbc{rgb} because it only requires
+% distinguishing \MF{} from \MP.
+%
+% \DescribeRoutine{grayscalegray}
+% The grayscale version should return a numeric in recent \MP{}, so
+% it needs a different definition for early \MP{}. Thus, it occurs
+% in the conditional code. Oddly, its definition is the same for \MF{}
+% and recent \MP{}.
+% \begin{macrocode}
+if has_cmyk :
+ vardef grayscalegray (expr g) = snapto g enddef;
+ vardef gray (expr g) = grayscalegray (g) enddef;
+ vardef cmyk (expr c, m, y, k) =
+ (snapto c, snapto m, snapto y, snapto k)
+ enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{makecmyk}
+% \DescribeRoutine{makergb}
+% \DescribeRoutine{makegray}
+% In \gbc{makecmyk} and all the other `\gbc{make}' conversions, the
+% default is to return black in the appropriate model, numerics produce
+% gray in the appropriate model, and cmyk or rgb is either retained
+% unchanged or converted to the appropriate model.
+%
+% \DescribeRoutine{iscolor}
+% A variable is taken to be a color if it can validly follow
+% \mfc{withcolor}. This includes boolean, though we hope no one tries to
+% use that.
+% \begin{macrocode}
+ vardef makecmyk primary clr =
+ colorchoice (clr)(cmykblack)(cmykgray(clr))
+ (rgbtocmyk(redpart clr,greenpart clr,bluepart clr))
+ (clr)
+ enddef;
+ vardef makergb primary clr =
+ colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)
+ (cmyktorgb(cyanpart clr, magentapart clr,
+ yellowpart clr, blackpart clr))
+ enddef;
+ vardef makegray primary clr =
+ colorchoice (clr)(grayscaleblack)(grayscalegray(clr))
+ (rgbtogray (redpart clr, greenpart clr, bluepart clr))
+ (cmyktogray(cyanpart clr, magentapart clr,
+ yellowpart clr, blackpart clr))
+ enddef;
+ vardef iscolor expr clr =
+ (rgbcolor clr) or (cmykcolor clr) or (numeric clr) or (boolean clr)
+ enddef;
+else:
+% \end{macrocode}
+%
+% In early \MP{} \gbc{colorchoice} is only a three-way choice, since
+% \mfc{cmykcolor} is not a data type, but numeric can still be
+% interpreted as a gray. For a numeric or an actual rgbcolor, the first or
+% second branch would be taken. If \gbc{clr} is neither of those then
+% \mfc{cmykcolor}, being equal to \mfc{rgbcolor}, would also be false.
+% Therefore, in the context of early \MP{}, it is irrelevant what goes in
+% the last argument, so we leave it empty.
+%
+% \DescribeRoutine{makecmyk}
+% \DescribeRoutine{makergb}
+% \DescribeRoutine{makegray}
+% The \gbc{make*} functions are simpler in early \MP{}, though not as
+% simple as in \MF{}. Ditto
+% \DescribeRoutine{iscolor}
+% \gbc{iscolor}. The parentheses in \gbc{iscolor} are necessary to force
+% \MP{} to see this \mfc{color} as the start of a boolean expression and
+% not a type declaration.
+% \begin{macrocode}
+ vardef gray (expr g) = rgbgray(g) enddef;
+ vardef grayscalegray (expr g) = rgbgray(g) enddef;
+ vardef cmyk (expr c, m, y, k) = rgb (1-c-k, 1-m-k, 1-y-k) enddef;
+ vardef makergb primary clr =
+ colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)()
+ enddef;
+ vardef makegray primary clr =
+ colorchoice (clr)(rgbblack)(rgbgray(clr))
+ (rgbtogray (redpart clr, greenpart clr, bluepart clr))()
+ enddef;
+ def makecmyk = makergb enddef;
+ vardef iscolor expr clr = (color clr) enddef;
+fi
+
+%</MP>
+% \end{macrocode}
+%
+% \DescribeRoutine{knowncolor}
+% Once we have \gbc{iscolor} all we need to do is add a test for
+% \mfc{known} to get this boolean test.
+% \begin{macrocode}
+vardef knowncolor expr clr = (known clr) and (iscolor clr) enddef;
+
+% \end{macrocode}
+%
+% These are the \MF{} versions. Everything pretty much returns its
+% numeric argument or $0$ (black).
+% \begin{macrocode}
+%<*MF>
+vardef grayscalegray (expr g) = snapto g enddef;
+vardef gray (expr g) = grayscalegray (g) enddef;
+vardef cmyk (expr c, m, y, k) = rgb (1-c-k, 1-m-k, 1-y-k) enddef;
+vardef makegray primary clr =
+ if knowncolor clr: clr else: black fi
+enddef;
+def makergb = makegray enddef;
+def makecmyk = makegray enddef;
+vardef iscolor expr clr = (color clr) enddef;
+
+%</MF>
+% \end{macrocode}
+%
+% \DescribeRoutine{forceclr}
+% \DescribeRoutine{named}
+% This is only used in the \gbc{named} function to force a color. In
+% \MF{} the tests are all `\mfc{if numeric}'. In early \MP{} `\mfc{if
+% cmykcolor}' is the same as `\mfc{if rgbcolor}'.
+% \begin{macrocode}
+vardef forceclr (expr c) =
+ if unknown c :
+ if numeric c: grayscaleblack
+ elseif rgbcolor c: rgbblack
+ elseif cmykcolor c: cmykblack
+ else: black
+ fi
+ elseif numeric c: gray (c)
+ elseif iscolor c: c
+ else: black
+ fi
+enddef;
+vardef named (suffix c) = forceclr (c) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{togray}
+% \DescribeRoutine{rgbtogray}
+% \DescribeRoutine{cmyktogray}
+% \DescribeRoutine{cmyktorgb}
+% \DescribeRoutine{rgbtocmyk}
+% These are used for the conversions. Strictly speaking they do not
+% `convert' as they all take multiple numeric arguments rather than any
+% sort of color. As \mfc{rgbcolor} exists in both early and recent
+% \MP{} as the same data type, we need only distinguish \MF{} from \MP{}
+% \DescribeRoutine{rgb}
+% in the function \gbc{rgb},
+% \begin{macrocode}
+vardef togray (expr r, g, b) =
+ gray (sqrt((2r*r + 4g*g + b*b)/7))
+enddef;
+
+vardef rgbtogray (expr r, g, b) =
+ togray(snapto r, snapto g, snapto b)
+enddef;
+vardef cmyktogray (expr c, m, y, k) =
+ rgbtogray (1-c-k,1-m-k,1-y-k)
+enddef;
+
+vardef cmyktorgb (expr c,m,y,k) =
+ rgb(1-c-k,1-m-k,1-y-k)
+enddef;
+vardef rgbtocmyk (expr r,g,b) =
+ cmyk(1-r,1-g,1-b,0)
+enddef;
+
+vardef rgb (expr r, g, b) =
+%<MF> togray (snapto r, snapto g, snapto b)
+%<MP> (snapto r, snapto g, snapto b)
+enddef;
+vardef RGB (expr R, G, B) =
+ rgb (R/255, G/255, B/255)
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Arrays}\label{arrays}
+%
+% \gbc{ClipPath} is a typical example of an array. Arrays are based on the
+% fact that a variable can be of a different type from (and can be almost
+% completely unrelated to) the variables formed by putting numeric
+% suffixes on it.
+%
+% \DescribeRoutine{list}
+% The \gbc{list} macro is essentially due to Frank Michielsen, and assigns
+% a \emph{list} (i.e., a comma separated sequence of expressions) to an
+% array. Note that the items in the list have to be the same type, and the
+% same type as \mfc{v[\,]}. But \mfc{v} itself must be numeric.
+%
+% \DescribeRoutine{map}
+% The \gbc{map} macro takes two text parameters. The first is any
+% procedure, the second is a list of expressions. The procedure is applied
+% to each expression and the resulting new expressions are separated by
+% commas, that is, a new list is generated (for use in \mfc{for} loops).
+% This is full of possibilities for errors. One reared its head because
+% the original version started with a comma indicating an empty starting
+% expression (normally it would be ignored and that turn through the loop
+% skipped). However, it managed to produce an error in a reasonable
+% but unforeseen usage (which I've since forgotten) and so I added the
+% \gbc{_map} variable that skips the comma on the first time through the
+% loop. This routine is currently only used in the code that \mfpic's \
+% \cs{plr} writes.
+% \begin{macrocode}
+def list (suffix v) (text lst) =
+ v := 0; for _itm = lst: v[incr v] := _itm; endfor
+ if v = 0:
+ GBerrmsg ("No list to process!")
+ "An attempt was made to produce an array from a "
+ & "list of expressions having no valid entries.";
+ fi
+enddef;
+
+def map (text proc) (text lst) =
+ hide (_map := 0;)
+ for _a = lst:
+ if _map = 0: hide (_map := 1;) else: , fi
+ proc (_a)
+ endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{knownnumericarray}
+% Checks if a suffix is the name of an array. Requires \gbc{arr} to be a
+% known positive integer, and all the variables \gbc{arr[n]} to be known
+% for \gbc{n} from 1 to \gbc{arr}. Since we so far only need it for
+% numeric arrays, we also check if each entry is numeric.
+% \begin{macrocode}
+vardef knownnumericarray suffix arr =
+ setboolean (_kna) (known arr) and (numeric arr);
+ if _kna :
+ _kna := (arr = floor arr) and (arr >= 1);
+ for _idx = 1 upto arr :
+ exitif not _kna;
+ _kna := (known arr[_idx]) and (numeric arr[_idx]);
+ endfor
+ fi
+ _kna
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{copyarray}
+% This makes some code much more readable. It simply steps through an
+% array and copies the values into another array. It is only used for
+% numeric arrays so far, but could be used for any kind.
+% \begin{macrocode}
+def copyarray (suffix src, dest) =
+ for _idx = 1 upto src: dest[_idx] := src[_idx]; endfor
+ dest := src;
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{maparr}
+% The \gbc{maparr} macro applies a procedure \gbc{proc} to each member of
+% array \gbc{p[\,]} with \gbc{p} members. It returns nothing. It is currently
+% unused, although it was once used for things like \gbc{maxpair}.
+% \begin{macrocode}
+def maparr (text proc) (suffix p) =
+ for _idx = 1 upto p: proc (p[_idx]); endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{textpairs}
+% This macro takes a suffix (name of an array to be constructed) and a
+% list of pairs, and assigns them to the array. It is normally called from
+% another macro, which does any necessary \mfc{save}-ing of the variable
+% used for the array name. We used to include \mfc{save} in this macro,
+% but ran into a problem once when the argument had a suffix. You can't
+% apply \mfc{save} to a variable with a suffix. Moreover, `\mfc{save p}'
+% also renders \mfc{p.x} unknown, so I judged it best to let whoever calls
+% this macro decide what to save. Actually, now it expands to the more
+% general command \gbc{gsetarray} with type \gbc{pair}. That command
+% then reads the suffix argument that should follow.
+%
+% Since the above change was made, macros evolved so that \emph{all} uses
+% of \gbc{textpairs} are now preceeded by \gbc{save}. Thus, I have now
+% replaced them all with calls to \gbc{setpairs} (it calls \gbc{setarray},
+% which \emph{does} \gbc{save} the variable). In all those cases, the
+% `\gbc{saved}' variable is a temporary local array.
+%
+% \DescribeRoutine{setuniquepairs}
+% This does the same but omits any pair if it is identical to the previous
+% one. It \mfc{save}\,s the variable, since all its uses are internal
+% and require that.
+% \begin{macrocode}
+def textpairs = gsetarray (pair) enddef;
+
+def setuniquepairs (suffix p) (text t) =
+ save p; pair p[];
+ setpairs (_up) (t);
+ if _up > 0:
+ p := 1; p1 := _up1;
+ for _i = 2 upto _up:
+ if _up[_i] <> p[p]: p[incr p] := _up[_i]; fi
+ endfor
+ else:
+ p := 0;
+ fi
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Utilities}\label{utilities}
+%
+% \DescribeRoutine{chpair}
+% This applies a procedure \gbc{proc} (which maps numeric to numeric) to
+% each part of pair \gbc{p}, and returns the resultant pair. I've decided
+% not to use it (for efficiency), but to leave it defined for backward
+% compatibility.\\
+% \DescribeRoutine{floorpair}
+% \gbc{floorpair} applies \mfc{floor} to both parts of a pair.\\
+% \DescribeRoutine{ceilingpair}
+% \gbc{ceilingpair} does the same with \gbc{ceiling}.\\
+% \DescribeRoutine{hroundpair}
+% \gbc{hroundpair} does the same with \gbc{hround}.
+%
+% All three could use \gbc{chpair} with \gbc{proc} equal to \mfc{floor},
+% \mfc{ceiling} and \mfc{hround}, but I now code them directly.
+%
+% \DescribeRoutine{goodpair}
+% This last one is used (only in \MF{}) to adjust pairs to the pixel grid.
+% It is the only place \gbc{hroundpair} is used. None of these is used in
+% the \MP{} version.
+% \begin{macrocode}
+vardef chpair (text proc) (expr p) =
+ (proc (xpart p), proc (ypart p))
+enddef;
+
+vardef floorpair (expr p) = (floor (xpart p), floor (ypart p))
+enddef;
+vardef ceilingpair (expr p) = (ceiling (xpart p), ceiling (ypart p))
+enddef;
+
+%<*MF>
+def hroundpair (expr p) = (hround (xpart p), hround (ypart p))
+enddef;
+vardef goodpair (expr p) = hroundpair(p.t_) enddef;
+
+%</MF>
+% \end{macrocode}
+%
+% \DescribeRoutine{emin}
+% The macro \gbc{emin} differs from \prog{plain}'s \mfc{min} in that it
+% allows only two values. It can therefore be coded simply, without the
+% overhead of a \mfc{for}-loop.
+% \DescribeRoutine{emax}
+% \gbc{emax} is analogous. Both are needed so often that it is possible a
+% significant amount of time is saved with these versions.
+%
+% \DescribeRoutine{pairmin}
+% The macro \gbc{pairmin} operates on two pairs, returning a pair having
+% the smaller of the two xparts and the smaller of the two yparts. Of
+% course
+% \DescribeRoutine{pairmax}
+% \gbc{pairmax} is analogous, producing the maximum.
+%
+% \DescribeRoutine{minpair}
+% The \gbc{minpair} macro returns the pair comprising the minimum $x$ and
+% minimum $y$ coordinates of all pairs in the array \gbc{p[\,]}.
+% \DescribeRoutine{maxpair}
+% \gbc{maxpair} is analogous. Somehow, both of them have disappeared from
+% \grafbase. They were formerly used only in the \gbc{*bbox} macros.
+% That code used a loop to build an array of control points and these
+% routines would \emph{each} loop through that. The current code uses one
+% loop (instead of three) through the control points, updating both the
+% maximum and minimum at each one.
+% \begin{macrocode}
+vardef emin (expr a, b) = if a < b: a else: b fi enddef;
+vardef emax (expr a, b) = if a > b: a else: b fi enddef;
+
+vardef pairmin (expr z, w) =
+ ( emin (xpart z, xpart w), emin (ypart z, ypart w ) )
+enddef;
+vardef pairmax (expr z, w) =
+ ( emax (xpart z, xpart w), emax (ypart z, ypart w ) )
+enddef;
+
+vardef minpair (suffix p) = setpair (_mp) p1;
+ for _idx = 2 upto p - 1: _mp := pairmin (_mp, p[_idx]); endfor
+ pairmin (_mp, p[p])
+enddef;
+vardef maxpair (suffix p) = setpair (_mp) p1;
+ for _idx = 2 upto p - 1: _mp := pairmax (_mp, p[_idx]); endfor
+ pairmax (_mp, p[p])
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{xprod}
+% A binary operation between pairs $z\sb1$ and $z\sb2$ that returns the
+% cross product $x\sb1 y\sb2 - x\sb2 y\sb1$. This gives, among other
+% things, twice the area of the triangle with two sides $z\sb1$ and
+% $z\sb2$. It is used only in \gbc{mkconvex}.
+% \begin{macrocode}
+primarydef Z xprod W = (xpart Z * ypart W - xpart W * ypart Z)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{force_initial}
+% The command \gbc{force_initial} modifies a path so that it has all the
+% same points and controls as before, except its first point is replaced
+% with \mfc{p}.
+% \DescribeRoutine{force_terminal}
+% The command \gbc{force_terminal} replaces the last point. This is for
+% cases where, theoretically, paths \gbc{f} and \gbc{g} should meet at an
+% endpoint, but do not due to finite precision. Instead of doing
+% \mfc{f..g}, which adds a random tiny segment, we adjust the endpoints to
+% exactly match the other and do \mfc{f\&g}, producing a join without an
+% additional segment.
+%
+% \DescribeRoutine{force_equal_ends}
+% The command \gbc{force_equal_ends} forces the last point of the first
+% path and the first point of the second to equal the average of their
+% original values. It is the only one of these four actually used anywhere
+% else in \grafbase.
+% \DescribeRoutine{replace_ends_of_cycle}
+% The command \gbc{replace_ends_of_cycle} applies something similar to a
+% cycle.
+% \begin{macrocode}
+def force_initial (expr p) (suffix f) =
+ hide( setnumeric (_n) length f;
+ f := p
+ if _n = 0:
+ {0,0}
+ else:
+ ..controls post0 (f) and pre 1 (f).. subpath (1,_n) of f
+ fi;)
+enddef;
+
+def force_terminal (expr p) (suffix f) =
+ hide(setpath (_f) reverse f;
+ force_initial (p) (_f);
+ f := reverse _f;)
+enddef;
+
+def force_equal_ends (suffix f, g) =
+ hide(save _p; pair _p;
+ _p := .5[pnt[length f] (f), pnt0(g)];
+ force_terminal (_p) (f); force_initial (_p) (g);)
+enddef;
+
+def replace_ends_of_cycle (expr p) (suffix f) =
+hide(
+if cycle f:
+ save _n; _n := length f;
+ f := p
+ if _n = 0: &cycle
+ else: .. controls post0 (f) and pre 1 (f) ..
+ if _n = 1: cycle
+ else: subpath (1, _n - 1) of f ..
+ controls post[_n - 1](f) and pre[_n](f) .. cycle
+ fi
+ fi;
+fi)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{intersects}
+% A binary relation, with the precedence level (almost) that of other
+% relations, produces \mfc{true} if \MF{} determines that the paths
+% intersect, false otherwise. It also
+% \DescribeVariable{thetimes}
+% sets the pair variable \gbc{thetimes} and its parts \gbc{_Xtime} and
+% \gbc{_Ytime}. Then
+% \DescribeRoutine{misses}
+% \gbc{misses} is the opposite relation, used when the intersection point
+% is not needed. It only occurs in the (unused) code of \gbc{tightbbox}.
+% \begin{macrocode}
+pair thetimes;
+numeric _Xtime, _Ytime;
+tertiarydef a intersects b =
+ begingroup
+ thetimes := a intersectiontimes b;
+ _Xtime := xpart thetimes;
+ _Ytime := ypart thetimes;
+ (_Xtime > -1)
+ endgroup
+enddef;
+
+tertiarydef a misses b = ((a intersectiontimes b) < origin) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{makepicture}
+% The \gbc{makepicture} command takes any expression and does what it can
+% to make a picture from it.
+%
+% \DescribeRoutine{onepointpath}
+% The \gbc{onepointpath} command takes a point and forces it to be a path.
+% If a vardef takes a list of points and it \emph{must} return a path that
+% perhaps \emph{must} be cyclic, it can use this as a fallback. If an
+% \mfpic{} command such as \cs{arc} receives an invalid optional
+% parameter, it won't know what command to write to the output file. It
+% can use
+% \DescribeRoutine{fallbackpath}
+% \gbc{fallbackpath} as long as the first parameter is a point.
+%
+% \DescribeRoutine{even}
+% \DescribeRoutine{divides}
+% Of course \gbc{even} means \gbc{not odd}. The relation \gbc{divides}
+% is true if the right side is an integer multiple of the left.
+% \begin{macrocode}
+vardef makepicture (expr s) =
+ if picture s: s
+%<MP> elseif string s: s infont defaultfont scaled defaultscale
+ elseif path s: picpath (s)
+ else: nullpicture
+ fi
+enddef;
+
+vardef onepointpath (expr cyclic, q) =
+ q if cyclic: &cycle else: {0,0} fi
+enddef;
+
+vardef fallbackpath (expr cyclic, p) (text t) =
+ onepointpath (cyclic, p)
+enddef;
+
+def even = not odd enddef;
+
+primarydef a divides b =
+ ((b mod a) = 0)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{image}
+% The \mfc{image} macro exists in \file{plain.mp} but not \file{plain.mf}.
+% The purpose is to just use the \file{plain} \MF{} and \grafbase{} macros
+% as you normally would, but wrap the whole thing in parentheses preceded
+% by \gbc{X := image} to get all those things drawn on the picture
+% variable \gbc{X}.
+%
+% \DescribeRoutine{beginimage}
+% Instead of making lengthy drawing code a parameter, one might prefer an
+% environment-like syntax, writing \gbc{X := beginimage } at the start
+% and
+% \DescribeRoutine{endimage}
+% \gbc{endimage} at the end.
+%
+% \DescribeRoutine{makeimage}
+% This is for the \mfpic{} command \cs{mfpimage}. It takes a suffix
+% parameter (the name of the picture variable) and a coordinate pair (in
+% graph coordinates). The drawing commands, up to the following
+% \gbc{endimage}, draw on this picture variable with the given pair as the
+% reference point.
+% \begin{macrocode}
+%<*MF>
+vardef image (text t) =
+ newpicture (currentpicture);
+ t;
+ currentpicture
+enddef;
+
+%</MF>
+def beginimage =
+ begingroup
+ newpicture (currentpicture);
+enddef;
+def endimage =
+ ; currentpicture
+ endgroup
+enddef;
+
+def makeimage (suffix name) (expr refpt) =
+ setpair (_image_reference_point) zconv (refpt);
+ setpicture (name) beginimage
+enddef;
+def concludeimage =
+ endimage shifted
+%<MF> -goodpair (_image_reference_point)
+%<MP> -_image_reference_point
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{setvariable}
+% This is are mainly to save space in \mfpic-generated files. In \grafbase{}
+% itself the \mfc{save} is often inconvenient, but it turns out there are
+% many cases where it \emph{is} used; enough so that we have abbreviations
+% \RoutineIndex{setnumeric}\gbc{setnumeric},
+% \RoutineIndex{setboolean}\gbc{setboolean},
+% \RoutineIndex{setpair}\gbc{setpair},
+% \RoutineIndex{setpath}\gbc{setpath},
+% \RoutineIndex{setpicture}\gbc{setpicture},
+% and \RoutineIndex{setstring}\gbc{setstring}, together with the
+% common uses \RoutineIndex{newpicture}\gbc{newpicture} and
+% \RoutineIndex{convertpath}\gbc{convertpath}. There is also a
+% \gbc{setcolor}, but that has such a different definition that we reserve
+% it for later.
+%
+% For completeness, we also include the remaining two abbreviations,
+% \RoutineIndex{setpen}\gbc{setpen} and
+% \RoutineIndex{settransform}\gbc{settransform}, even though they are not
+% used anywhere in \grafbase{}.
+%
+% \DescribeRoutine{gsetvariable}
+% The macro \gbc{gsetvariable} is the global version. It has no
+% abbreviations, but it is occasionally needed for \mfpic{}. The only
+% difference between it and the local version is the lack of a
+% \gbc{save}. None of these commands take the value as a parameter. That
+% should follow, and is picked up by the ending \mfc{:=}.
+%
+% \DescribeRoutine{setarray}
+% Then \gbc{setarray} is the array version. It takes the same parameters
+% as \gbc{setvariable}, but what should follow is a list of expressions in
+% parentheses. It calls \gbc{list} to read each item into
+% \gbc{name1}, \gbc{name2}, etc. There is also has a global version
+% \DescribeRoutine{gsetarray}
+% \gbc{gsetarray}.
+% \DescribeRoutine{setpairs}
+% \gbc{setpairs} is an abbreviation for arrays
+% of pairs. Historically, it came first.
+% \begin{macrocode}
+def setvariable (text kind) (suffix name) =
+ save name; kind name; name :=
+enddef;
+def gsetvariable (text kind) (suffix name) = kind name; name :=
+enddef;
+
+def setnumeric (suffix name) = save name; name := enddef;
+def setboolean = setvariable (boolean) enddef;
+def setpair = setvariable (pair) enddef;
+def setpath = setvariable (path) enddef;
+def setpicture = setvariable (picture) enddef;
+def setstring = setvariable (string) enddef;
+def settransform = setvariable (transform) enddef;
+def setpen = setvariable (pen) enddef;
+def settension (suffix tn) expr tens =
+ setnumeric (tn) if tens > 0: tens else: default_tension fi;
+enddef;
+def fixtension (suffix tn) = if tn < .75: tn := .75; fi enddef;
+
+def newpicture (suffix pic) = setpicture (pic) nullpicture; enddef;
+def convertpath (suffix g) expr f = setpath (g) zconv (f); enddef;
+
+def setarray (text kind) (suffix name) =
+ save name; kind name[]; list (name)
+enddef;
+def setpairs = setarray (pair) enddef;
+def gsetarray (text kind) (suffix name) =
+ numeric name; kind name[]; list (name)
+enddef;
+
+% \end{macrocode}
+% The next are slightly different, but seem to belong here.
+
+% \DescribeRoutine{setbbox}
+% In \gbc{setbbox} we save and initialize \emph{two} pair variables and
+% set them to the bounding box of a path that should follow.
+%
+% \DescribeRoutine{setsplit}
+% There are a couple of routines that modify a variable to make sure it is
+% positive and integral. In a couple of places two routine \emph{must} use
+% the same value. Here we isolate the code that does the modification, and
+% then both routines call \gbc{setsplit}.
+% \begin{macrocode}
+def setbbox (suffix ll, ur) =
+ save ll, ur; pair ll, ur; getbbox (ll, ur)
+enddef;
+
+def setsplit (suffix s) expr ss =
+ setnumeric (s) emax (1, ceiling ss);
+enddef;
+
+%<*MP>
+if has_cmyk:
+ def setrgbcolor = setvariable (rgbcolor) enddef;
+ def setcmykcolor = setvariable (cmykcolor) enddef;
+ def setcolor (suffix name) expr val =
+ if boolean val : setboolean
+ elseif numeric val : setnumeric
+ elseif rgbcolor val : setrgbcolor
+ elseif cmykcolor val : setcmykcolor
+ % this should give a suitable error message:
+ else: setvariable (color)
+ fi (name) val;
+ enddef;
+ def gsetcolor (suffix name) expr val =
+ if boolean val : boolean name;
+ elseif numeric val : numeric name;
+ elseif rgbcolor val : rgbcolor name;
+ elseif cmykcolor val : cmykcolor name;
+ else: color name;
+ fi name := val;
+ enddef;
+else:
+ def setrgbcolor = setcolor enddef;
+ def setcmykcolor = setcolor enddef;
+ def setcolor = setvariable (color) enddef;
+ def gsetcolor = gsetvariable (color) enddef;
+fi
+%</MP>
+%<*MF>
+def setrgbcolor = setcolor enddef;
+def setcmykcolor = setcolor enddef;
+def setcolor = setvariable (color) enddef;
+def gsetcolor = gsetvariable (color) enddef;
+%</MF>
+
+% \end{macrocode}
+%
+% And then the standard colors. Using the color functions ensures that
+% they are defined in \MF{} as well as all versions of \MP{}. In early
+% \MP{} they are all \mfc{rgbcolor}, in \MF{} they are all numeric. In
+% recent \MP{}, they have the type correspondimg to the name of the
+% color function, with \gbc{gray()} being numeric.
+% \begin{macrocode}
+setcolor(rgbblack) rgb(0,0,0);
+setcolor(red) rgb(1,0,0);
+setcolor(green) rgb(0,1,0);
+setcolor(blue) rgb(0,0,1);
+setcolor(rgbwhite) rgb(1,1,1);
+setcolor(cmykwhite) cmyk(0,0,0,0);
+setcolor(cyan) cmyk(1,0,0,0); % Maybe these should
+setcolor(magenta) cmyk(0,1,0,0); % be rbg for backward
+setcolor(yellow) cmyk(0,0,1,0); % compatibility?
+setcolor(cmykblack) cmyk(0,0,0,1);
+setcolor(grayscaleblack) gray(0);
+setcolor(grayscalewhite) gray(1);
+
+%<*MP>
+if has_outputtemplate:
+ def setoutputtemplate = outputtemplate := enddef;
+elseif has_filenametemplate:
+ def setoutputtemplate = filenametemplate enddef;
+else:
+ def setoutputtemplate text garbage = enddef;
+fi
+%</MP>
+%<MF>def setoutputtemplate text garbage = enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{GBromannumeral}
+% We will append roman numerals to the ends of a variable name to
+% emulate an array. This will be needed when our `array' consists of
+% colors with different types. \MP{} doesn't permit true arrays to
+% contain different types. We use `\gbc{GB}' in the name because a
+% package exists that defines \mfc{romannumeral} differently
+%
+% \DescribeRoutine{GBromandigit}
+% Roman numerals can conveniently be computed one digit at a time. The
+% algorithm is the same for each digit, differing only in the letters
+% used. Thus we define \gbc{GBromandigit} and call it three times with
+% different sets of letters.
+%
+% \DescribeRoutine{strrepeat}
+% The helper macro \gbc{strrepeat} creates a new string by concatenating
+% \mfc{rep} copies of the string \mfc{str}.
+% \begin{macrocode}
+vardef GBromannumeral (expr X) =
+ save Y, _tmp, U; string U;
+
+ Y.m := X div 1000; % thousands digit
+ _tmp := X - 1000Y.m; % hundreds digits and lower
+ Y.c := _tmp div 100; % hundreds
+ _tmp := _tmp - 100Y.c; % tens and units
+ Y.x := _tmp div 10; % tens
+ Y.i := _tmp - 10Y.x; % units
+
+ strrepeat("m", Y.m) &
+ GBromandigit("c", "d", "m", Y.c) &
+ GBromandigit("x", "l", "c", Y.x) &
+ GBromandigit("i", "v", "x", Y.i)
+enddef;
+
+vardef GBromandigit (expr bot, mid, top, n) =
+ if n > 9 : top & strrepeat(bot, n-10) % shouldn't happen
+ elseif n > 8 :
+ bot & top % "ix"
+ elseif n > 4 : mid & strrepeat (bot, n-5) % "v"--"viii"
+ elseif n > 3 :
+ bot & mid % "iv"
+ else: strrepeat (bot, n) % ""--"iii" for 0--3
+ fi
+enddef;
+
+vardef strrepeat (expr st, rep) =
+ "" for i = 1 upto rep: & st endfor
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{The \grafbase{} Coordinate System}\label{coordinate}
+%
+% We need to make a distinction between graph units, sharped units, and
+% device units. In \MF, a device unit is 1 pixel. On a LaserJet IV, one
+% inch is 600 pixels. When constructing a character, \MF{} uses the pixel
+% as its unit. Since this differs from one printing device to another,
+% \file{plain.mf} arranges for \emph{sharped} units (the name comes from the
+% convention that they are written using a name that ends in \mfc{\#}). The
+% dimension \mfc{1pt\#} in \MF{} is arbitrarily set to 1, and other
+% units defined by conversion factors (\mfc{in\#=72.27}; neither \MF{}
+% nor \MP{} makes a distinction between distances and numbers: \mfc{2pt}
+% just means \mfc{2} times the value of \mfc{pt}). When one needs to
+% draw something actually \emph{one point long}, then \mfc{1pt} is used.
+% It is defined to equal \mfc{pt\#*hppp}, where \mfc{hppp} stands for
+% ``horizontal pixels per point'' and its value is usually set by
+% \mfc{mode_setup}. So \mfc{1pt} is $600/72.27$ (pixels) if
+% \mfc{mode} is \mfc{ljfour}.
+%
+% Often, when we want numbers not to become too large, we do calculations,
+% define paths, etc., in sharped units, then draw by scaling to device
+% units. In \grafbase{} we take this one step further: a horizontal graph
+% unit (i.e., the difference between the graph points $(0,0)$ and $(1,0)$)
+% represents \gbc{unitlen*xscale} sharped units, and
+% \gbc{unitlen*xscale*hppp} actual pixels. The \grafbase{} macros do much
+% of the calculations in graph units.
+%
+% In \MP, there is no difference between device and sharped units.
+% The \emph{postscript point} or \emph{big point} (1/72 inches) is the
+% unit in \MP: \mfc{bp = 1}.
+%
+% Some things need to be in graph units (for example, positions within a
+% graph defined by the user) or independent of units (standard shapes)
+% that scale appropriately when scales change. Other things (thickness of
+% lines) are a design decision that either should be independent of scale
+% or should scale in a nonobvious way. The diameter of the drawing pen is
+% one of the latter things, so the default pen width is in device units.
+% Also for the hatching pen.
+%
+% When drawing a path we want to use device coordinates. When defining
+% paths, we typically want to use graph coordinates. The macros that do
+% the drawing, therefore, need to convert from one to the other. In
+% addition, for inclusion of the picture in a \TeX{} document, we normally
+% want the lower left corner of the graph space to have device coordinates
+% $(0,0)$.
+%
+%
+% \subsection{The main transforms}\label{ztr}
+%
+% \DescribeVariable{vtr}
+% We therefore have two transforms: \gbc{vtr} is the \emph{vector} or
+% linear transform for pair quantities that remain invariant under shifts,
+% and
+% \DescribeVariable{ztr}
+% \gbc{ztr} is a \emph{point} or affine transformation for pair quantities
+% that change appropriately under shifts.
+%
+% The quantities \gbc{xneg}, \gbc{xpos}, \gbc{yneg}, and \gbc{ypos} are
+% in \emph{graph} coordinates. Shifting by \gbc{(-xneg, -yneg)} transforms
+% the lower left corner to $(0,0)$. Multiplication by \gbc{xscale} and
+% \gbc{yscale} converts to multiples of \gbc{unitlen} and multiplication
+% by \gbc{unitlen} gets us sharped coordinates. For \MF{},
+% multiplication by \mfc{hppp} converts to device coordinates, while for
+% \MP{} sharped and device are the same (the printer's PostScript
+% rasterizing engine---\prog{GhostScript} perhaps---does the final
+% conversion to actual pixels).
+%
+% In \MF{}, \mfc{currenttransform} (via the macro \mfc{.t_}, defined by
+% \mfc{mode_setup}) takes care of the aspect ratio. In \MP{} the final
+% rasterizer should do this.
+%
+% \gbc{charwd} and \gbc{charht} are sharped coordinates defined by the
+% startup code \gbc{beginmfpic}, while \gbc{w_} and \gbc{h_} are the
+% corresponding device (pixel) coordinates
+%
+% \DescribeRoutine{setztr}
+% This macro does the defining of \gbc{ztr} and \gbc{vtr}. It is called
+% by \gbc{beginmfpic}, at which time all the necessary quantities should be
+% known.
+% \begin{macrocode}
+transform ztr, vtr;
+def setztr =
+ if debug:
+ GBdebug;
+%<*MF>
+ >> "charwd = " & decimal charwd & "pt#";
+ >> "charht = " & decimal charht & "pt#";
+ >> "w_ = " & decimal w_ & " pixels";
+ >> "h_ = " & decimal h_ & " pixels";
+ >> "unitlen = " & decimal unitlen & "pt#";
+ >> "hppp = " & decimal hppp;
+%</MF>
+%<*MP>
+ >> "w_ = " & decimal w_ & "bp";
+ >> "h_ = " & decimal h_ & "bp";
+ >> "unitlen = " & decimal unitlen & "bp";
+%</MP>
+ >> "xneg = " & decimal xneg;
+ >> "xpos = " & decimal xpos;
+ >> "yneg = " & decimal yneg;
+ >> "ypos = " & decimal ypos;
+ >> "xscale = " & decimal xscale;
+ >> "yscale = " & decimal yscale;
+ GBenddebug;
+ fi
+ save ztr, vtr;
+ transform ztr, vtr;
+ vtr := identity xscaled xscale yscaled yscale scaled (unitlen*hppp);
+ ztr := identity shifted (-xneg, -yneg) transformed vtr;
+ if debug:
+ GBdebug;
+ >> "ztr is";
+ show ztr;
+ >> "vtr is";
+ show vtr;
+ GBenddebug;
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{zconv}
+% The macro \gbc{zconv} converts a variety of expressions from graph to
+% device coordinates. The expressions include pairs, paths, and transforms.
+% This is an affine transform. The inverse,
+% \DescribeRoutine{invzconv}
+% \gbc{invzconv}, converts a variety of expressions from device to graph
+% coordinates.
+%
+% \DescribeRoutine{vconv}
+% The vector version, \gbc{vconv}, converts a vector \gbc{v} from graph to
+% device coordinates. This is a linear (ie, vector) transform. Also,
+% \DescribeRoutine{invvconv}
+% \gbc{invvconv} converts a vector from device to graph coordinates.
+% \begin{macrocode}
+vardef zconv (expr a) = a transformed ztr enddef;
+vardef invzconv (expr a) = a transformed (inverse ztr) enddef;
+vardef vconv (expr v) = v transformed vtr enddef;
+vardef invvconv (expr v) = v transformed (inverse vtr) enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{The \gbc{mfpic} environment}\label{mfpic}
+%
+% \DescribeRoutine{active_plane}
+% \gbc{active_plane} is the active drawing plane. \mfc{currentpicture} is
+% unknown at this stage (because it's set in \gbc{beginmfpic}). We use a
+% \mfc{def}, and not a picture assignment, partly for this reason but also
+% because we can achieve special effects by redefining it (see the
+% \gbc{tile} macro).
+% \begin{macrocode}
+def active_plane = currentpicture enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{initpic}
+% \gbc{initpic} is called by \gbc{beginmfpic} after \gbc{w_} and
+% \gbc{h_} are defined. At this point \gbc{xneg}, \gbc{xscale}, etc.,
+% have known values and \gbc{setztr} can define the transforms that are
+% based on them. Also, the default \gbc{drawpen} is initialized and the
+% boundary of the graph space is assigned to the clipping array.
+%
+% If \gbc{underlaylabels} is true, we try to make them part of the
+% background, adding them to the picture variable \gbc{background_labels}.
+% Just before shipout, the picture is placed on top of these labels.
+%
+% If \gbc{overlaylabels} is \gbc{true}, we try to make labels in \MP{}
+% behave the same as labels in \TeX{} (for \mfpic) by adding the labels
+% on last. We do this by adding them to the picture variable
+% \gbc{foreground_labels} as they occur, then add that picture onto
+% \gbc{active_plane} just before shipout. For backward compatibility,
+% the default for \gbc{overlaylabels} is \gbc{false}.
+%
+% We initialize \gbc{foreground_labels} and \gbc{background_labels} here. The
+% pair variables \gbc{labelbb.ll} and \gbc{labelbb.ur} keep track of the
+% bounding box of added labels in case \gbc{overlaylabels},
+% \gbc{truebbox}, and \gbc{clipall} are all \gbc{false}.
+% \begin{macrocode}
+%<*MP>
+boolean overlaylabels, underlaylabels, havebackground;
+overlaylabels := false;
+underlaylabels := false;
+havebackground := false;
+
+%</MP>
+def initpic =
+ setztr;
+ resizedrawpen (penwd);
+ if ClipOn: ClipPath := 1;
+ ClipPath1 := rect (origin, (w_, h_));
+ fi
+ if debug:
+ GBdebug;
+ >> "Drawing nominal bounding box around picture";
+ GBenddebug;
+ noclip ( safedraw rect (origin, (w_, h_)) );
+ fi
+%<*MP>
+ newpicture (foreground_labels);
+ newpicture (background_labels);
+ havebackground := false;
+ save labelbb; pair labelbb.ll, labelbb.ur;
+ labelbb.ll := labelbb.ur := origin;
+%</MP>
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mfpicenv}
+% We define a \gbc{mfpicenv} environment for compatibility with older
+% \file{graphbase.mf} (mainly for \prog{fig2dev}'s \file{genmf.c}).
+% \DescribeRoutine{endmfpicenv}
+% Actually, I have no idea if \prog{fig2dev} even works with the current
+% \mfpic.
+%
+% \DescribeRoutine{bounds}
+% This also used to be unused, for compatibility only, but I decided it was a
+% convenient abbreviation and \mfpic{} uses it again.
+% \begin{macrocode}
+def mfpicenv = enddef;
+def endmfpicenv = enddef;
+def bounds (expr a, b, c, d) =
+ xneg := a; xpos := b;
+ yneg := c; ypos := d;
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{beginmfpic}
+% This is the figure wrapper. \mfpic{} used to begin with figure 1 and
+% progressively increment the number. The current value of \gbc{gcode} was
+% always equal to the current figure number. Now, \mfpic{} explicitly
+% writes the figure number, so we assign \gbc{gcode} to that number in
+% case any old files made use of the current number through the
+% \gbc{gcode} variable.
+%
+% Originally, \gbc{beginmfpic} defined \mfc{w}, \mfc{h} and \mfc{d}, but
+% that caused problems if an \mfpic{} user tried to store a path in a
+% variable named \gbc{h}, etc. So now we use the less obvious names ending
+% in underscore. Apart from this, the code below is a clone of
+% \file{plain.mf}'s \mfc{beginchar} (for \MF). In fact, it used to invoke
+% \mfc{beginchar}. For \MP, we invoke \mfc{beginfig} explicitly. This does
+% the \mfc{clear...} actions and \mfc{charcode} assignment.
+%
+% The `\mfc{extra_...mfpic}' strings provide a compiler-independent way
+% to add to the extra beginning and ending tokens.
+% \begin{macrocode}
+string extra_beginmfpic; extra_beginmfpic := "";
+string extra_endmfpic; extra_endmfpic := "";
+
+def beginmfpic (expr ch) =
+%<MP> beginfig (ch);
+%<MF> begingroup
+ gcode := ch;
+ save w_, h_, d_;
+ charwd := (xpos-xneg)*xscale*unitlen;
+ charht := (ypos-yneg)*yscale*unitlen;
+ chardp := 0;
+%<*MF>
+ charcode := if known ch: byte ch else: 0 fi;
+ w_ := hround (charwd*hppp);
+ h_ := vround (charht*hppp);
+ d_ := vround (chardp*hppp);
+ charic := 0; clearxy; clearit; clearpen;
+ scantokens extra_beginchar;
+%</MF>
+%<*MP>
+ w_ := charwd;
+ h_ := charht;
+ d_ := chardp;
+%</MP>
+ initpic;
+ scantokens extra_beginmfpic;
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{endmfpic}
+% For \MF, we again clone \file{plain.mf}'s \mfc{endchar}, adding support
+% for the \gbc{clipall} (clip to the graph rectangle), and \gbc{ClipOn}
+% (clip to some user specified array of paths), and \gbc{showbbox} (draw
+% the boundary of the graph for debugging purposes).
+% \begin{macrocode}
+def endmfpic =
+ scantokens extra_endmfpic;
+ if debug:
+ GBdebug;
+%<MF> >> "TFM charwd = " & decimal charwd & "pt#";
+%<MF> >> "TFM charht = " & decimal charht & "pt#";
+%<MP> >> "width = " & decimal w_ & "bp";
+%<MP> >> "height = " & decimal h_ & "bp";
+ GBenddebug;
+ fi
+ DoClip (active_plane);
+ if clipall: clipto (active_plane) rect (origin, (w_, h_)); fi
+ if showbbox: noclip ( safedraw rect (origin, (w_, h_)) ); fi
+%<*MF>
+ scantokens extra_endchar;
+ if proofing > 0: makebox (proofrule); fi
+ chardx := w_; % desired width of character in pixels
+ shipit;
+ if displaying > 0: makebox (screenrule); showit; fi
+ endgroup
+%</MF>
+% \end{macrocode}
+%
+% \MP's code is more involved due to the possibility to put typeset text
+% in a picture. In addition to the \gbc{clipall}, \gbc{ClipOn} and
+% \gbc{showbbox} support, we have support for labels and \gbc{truebbox}.
+% \begin{macrocode}
+%<*MP>
+ save _ll, _ur;
+ pair _ll, _ur;
+ if truebbox:
+ _ll := llcorner active_plane;
+ _ur := urcorner active_plane;
+% \end{macrocode}
+% We try to let the bbox include labels, even when they extend beyond the
+% nominal picture boundaries. However, they will have been clipped off if
+% \gbc{clipall} is set. In that case, we just set the bounding box to the
+% coordinates determined by \gbc{w_} and \gbc{h_}, otherwise we expand
+% them to the \gbc{labelbb} values.
+% \begin{macrocode}
+ elseif clipall:
+ _ll := origin;
+ _ur := (w_,h_);
+ else: % expand to accomodate labels
+ _ll := pairmin ((0, 0 ), labelbb.ll);
+ _ur := pairmax ((w_, h_), labelbb.ur);
+ fi
+% \end{macrocode}
+% A bounding box in the output PostScript code can have a side with
+% length 0 (e.g., a picture drawn with \mfpic{} that contains only
+% text placed by \TeX). This can cause division by 0 errors in some
+% cases. That's why we don't just let \MP{} determine the bounding box,
+% but force the upper and lower coordinates to differ.
+% \begin{macrocode}
+ _ur := pairmax (_ur, _ll + eps*(1, 1));
+ setbounds active_plane to rect (_ll, _ur);
+% \end{macrocode}
+% Finally, if \gbc{overlaylabels} or \gbc{underlaylabels} was true during
+% a \gbc{newgblabel} command, then the label was not added to
+% \mfc{currentpicture} but rather to \gbc{foreground_labels} or
+% \gbc{background_labels}. We add those pictures now, the former on top of
+% \mfc{currentpicture}, the latter underneath. This might extend the bbox
+% calculated above, but that is one of the effects we \emph{want} to
+% achieve. Picture variables can consume a lot of memory, so we clear
+% each one after we have added it. Unfortunately, we will temporarily
+% have two copies of the current picture in memory for background text, so
+% we perform this operation only if \gbc{havebackground} is true.
+% \begin{macrocode}
+ if havebackground:
+ addto background_labels also active_plane;
+ active_plane := background_labels;
+ background_labels := nullpicture;
+ fi
+ addto active_plane also foreground_labels;
+ foreground_labels := nullpicture;
+ endfig;
+%</MP>
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Text}\label{text}
+%
+% In the \MP{} version, \gbc{label_adjust}, \gbc{label_sep} and
+% \gbc{labelpath_sep} are the equivalent of \mfpic's \cs{tlabeloffset},
+% \cs{tlpointsep} and \cs{tlpathsep}. In the \MF{} version they are still
+% needed (in \gbc{textrect}, etc.) to place the paths that are to surround
+% the text that \TeX{} places.
+%
+% \gbc{label_adjust} is a vector displacement applied to all labels,
+% while \gbc{label_sep} is the distance from the label to
+% the point of placement, when that point is on the edges of the label's
+% bounding box. Both are in device coordinates (e.g., \mfc{3bp}).
+% Finally, \gbc{labelpath_sep} is the separation of a surrounding path
+% from the text.
+% \begin{macrocode}
+pair label_adjust;
+label_adjust := origin;
+numeric label_sep, labelpath_sep ;
+label_sep := 0; labelpath_sep := 0;
+% \end{macrocode}
+%
+% Another aspect of trying to make \mfpic's \file{.mp} and \file{.mf}
+% the same, we here define a version of \mfc{verbatimtex} for \MF. This
+% works only if \mfc{etex} is followed by a semicolon, and no semicolons
+% appear in the \TeX{} material. (There may be other forbidden things, and
+% certainly any parentheses have to be in matching pairs. Not so obvious
+% is that \cs{begingroup} and \cs{endgroup} have to be balanced: \MF{}
+% sees \cs{begingroup} as `\verb$\$' plus \mfc{begingroup}.) We would
+% like the output of \mfpic{} under the \opt{metapost} option to be usable
+% in \MF{} with minimal changes.
+% \begin{macrocode}
+%<MF>def verbatimtex text t = enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Placement of text, \MP{} only}\label{placement}
+%
+% \DescribeRoutine{newgblabel}
+% This is how \mfpic{} places labels when \opt{mplabels} is in effect.
+% Since labels will typically be \mfc{btex...etex}, which are picture
+% expressions, it will actually place any picture, \gbc{s}. If you feed it
+% a string or path, it will convert it to a picture (with the \mfc{infont}
+% operator or the \gbc{picpath} macro).
+%
+% The macro \gbc{newgblabel} takes 6 parameters. The first three
+% parameters could easily be condensed into two if \mfpic{} support were
+% all that was required, however I thought it best to make it general.
+% The parameters \gbc{hf} and \gbc{vf} are numeric, with \gbc{hf}
+% representing the fraction of the text that lies left of the point where
+% the text is placed and \gbc{vf} represents the fraction of
+% text that lies below that point. However, if the third parameter is
+% \mfc{true}, then \gbc{vf} is relative to the baseline (i.e., the depth
+% is ignored). In \mfpic{} this is only used with \gbc{vf = 0} to get
+% placement on the baseline.
+%
+% These three parameters correspond to the optional parameter of
+% \cs{tlabel} in \mfpic{} as follows:
+% \begin{itemize}
+% \item \gbc{hf} determines horizontal position: $0=\mathtt{l}$,
+% $.5=\mathtt{c}$, and $1 = \mathtt{r}$.
+% \item \gbc{vf} and \gbc{BL} determine vertical position. For placement
+% option \texttt{B}, $\mathtt{vf} = 0$ and \gbc{BL} is \mfc{true}. For the
+% rest, \gbc{BL} is \mfc{false} and \gbc{vf} corresponds as follows:
+% $0 = \mathtt{b}$, $.5 = \mathtt{c}$ and $1 = \mathtt{t}$.
+% \end{itemize}
+% The remaining parameters have the following meanings:
+% \begin{itemize}
+% \item \gbc{r} is degrees of rotation about the specified point.
+% \item \gbc{s} is a string or picture expression (typically
+% \mfc{btex ... etex} code)
+% \item \gbc{pts} is a list of pairs in graph coordinates.
+% \end{itemize}
+% First the bounding box of the picture is determined using
+% \gbc{pathdims}. (Why \texttt{\textit{path}dims}? Because it was written
+% for the paths that surround text, and was then incorporated into text
+% placement when \gbc{newgblabel} replace \gbc{gblabel}.) Then
+% \gbc{readjustdims} extends that box by \gbc{label_sep}, a new
+% reference point for the picture is calculated using
+% \DescribeRoutine{ref_shift}
+% \gbc{ref_shift}, and then \gbc{thegblabel} rotates it around the
+% reference point and adds the \gbc{label_adjust}. Finally, for each
+% \gbc{_itm} in \gbc{pts}, the result is shifted by \gbc{_itm}. If
+% \gbc{overlaylabels} is true, the label is placed on the picture
+% \gbc{foreground_labels} and added to \gbc{active_plane} at
+% \gbc{endmfpic}. If \gbc{underlaylabels} is true, it is placed in picture
+% \gbc{background_labels} and \gbc{active_plane} is placed on top of it.
+% Otherwise, it is added directly to \gbc{active_plane} and the
+% \gbc{labelbb} variables are adjusted.
+%
+% We also use \gbc{ref_shift} in \MF{} since the curves that surround text
+% require it.
+%
+% \DescribeRoutine{gblabel}
+% We keep \gbc{gblabel} for backward compatibility with old \mfpic{}
+% files, but it merely calls \gbc{newgblabel}. While the old \gbc{gblabel}
+% had the same flexibility as \gbc{newgblabel}, this one assumes that the
+% parameters are only those that \mfpic{} would write.
+%
+% We provide a null definition of newgblabel for \MF{} to allow \mfpic's
+% \file{.mp} files to be somewhat usable with minimal changes. It
+% requires a text parameter, since \MF{} would be unable to evaluate
+% \mfc{btex} expressions.
+% \begin{macrocode}
+%<*MP>
+vardef newgblabel (expr hf, vf, BL, r) (expr s) (text pts) =
+ save _lab, _ll, _ur; picture _lab; pair _ll, _ur;
+ _lab := makepicture (s);
+ pathdims (origin, _lab) (_ll, _ur);
+ readjustdims (_ll, _ur) (label_sep);
+ _lab := thegblabel (ref_shift (hf, vf, BL, _ll, _ur), r, _lab);
+ save _b; pair _b;
+ for _itm = pts:
+ _b := zconv (_itm);
+ if overlaylabels:
+ addto foreground_labels also _lab shifted _b _wc_ tlabelcolor;
+ elseif underlaylabels:
+ addto background_labels also _lab shifted _b _wc_ tlabelcolor;
+ havebackground := true;
+ else:
+ addto active_plane also _lab shifted _b _wc_ tlabelcolor;
+ labelbb.ll := pairmin (_b + llcorner _lab, labelbb.ll);
+ labelbb.ur := pairmax (_b + urcorner _lab, labelbb.ur);
+ fi
+ endfor
+%</MP>
+%<MF>vardef newgblabel (expr hf, vf, BL, r) (text s) (text pts) =
+enddef;
+
+% Assumes a+b=1 and either c+d=1 or c=d=0:
+%<MP>vardef gblabel (expr a, b, c, d, r) (expr s) (text t) =
+%<MF>vardef gblabel (expr a, b, c, d, r) (text s) (text t) =
+ newgblabel (b, d, (c = 0) and (d = 0), r) (s) (t);
+enddef;
+
+vardef ref_shift (expr hf, vf, BL, ll, ur) =
+ - ( (hf)[xpart ll, xpart ur],
+ (vf)[if BL: 0 else: (ypart ll) fi, ypart ur] )
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{thegblabel}
+% When \gbc{thegblabel} is called by the above, \gbc{p} is a text picture,
+% but it is also called by the \gbc{textrect}, etc., in which case \gbc{p}
+% is a path. This is why it is needed in the \MF{} version.
+% \begin{macrocode}
+vardef thegblabel (expr z, r, p) =
+ ((p shifted z) rotated r) shifted label_adjust
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Decorating the text, \MF{} or \MP{}}\label{decorating}
+%
+% The three macros \gbc{textrect}, \gbc{textoval} and \gbc{textellipse}
+% are designed to surround a bit of text with some curve. These macros
+% return the path in graph coordinates. In
+% \DescribeRoutine{textrect}
+% \gbc{textrect}, the path is a rectangle with optionally rounded corners.
+% The second parameter, \gbc{rad}, is the radius of quarter circles at the
+% corners (in device units). In the other two cases, the path is an
+% ellipse. They differ in the meaning of the second parameter.
+%
+% \DescribeRoutine{textoval}
+% In \gbc{textoval}, the second parameter \emph{multiplies} the ratio of
+% width to height of the text to produce the ratio for the ellipse. Thus,
+% with \gbc{mult}=1, the ratio will be the same as that of the text. In
+% \DescribeRoutine{textellipse}
+% \gbc{textellipse}, the second parameter \gbc{rat} is the actual value of
+% the ratio of width to height of the ellipse and a value of 1 produces a
+% circle. In either macro, if that parameter is 0, we draw a rectangle.
+%
+% The size of each path is determined so that, when the text is placed and
+% the path drawn, it passes through the four corners of the following
+% rectangle: the rectangle which just encloses the text plus the amount of
+% space on all sides determined by \gbc{labelpath_sep}. Note that this means
+% a rectangle with rounded corners will have larger height and width than
+% one without. These versions always center the surrounding path on the
+% the point \gbc{loc}. The extended versions (below) have the same
+% flexibility of placement as the commands that place the label being
+% surrounded.
+%
+% The first parameter \gbc{lbl} is either a pair representing the
+% height and width of the text (only possibility in \MF) or the actual
+% text. These macros are being kept for backward compatibity, but now they
+% call the extended versions that allow the path to follow arbitrary
+% text placement. The parameters \gbc{(.5,.5,false,0)} were those
+% assumed in the past version: centered at the point, with no rotation.
+%
+% The extended versions of \gbc{textoval} and \gbc{textellipse} are both
+% now implemented in a single command \gbc{xellipse}, with a boolean to
+% specify whether the aspect ratio of the text is used to calculate the
+% aspect of the ellipse.
+% \begin{macrocode}
+vardef textrect (expr lbl, rad, loc) =
+ textrectx (.5, .5, false, 0) (origin, lbl, rad, loc)
+enddef;
+vardef textoval (expr lbl, mult, loc) =
+ xellipse (true, .5, .5, false, 0) (origin, lbl, mult, loc)
+enddef;
+vardef textellipse (expr lbl, rat, loc) =
+ xellipse (false, .5, .5, false, 0) (origin, lbl, rat, loc)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{textrectx}
+% Macro \gbc{textrectx} is the extended version of \gbc{textrect} which
+% allows the same adjustments to the rectangle that we can apply to the
+% text it surrounds (via \gbc{newgblabel}). In fact, it calculates the
+% position in exactly the same manner as that macro, and the first 4
+% parameters encode that position in the same way.
+%
+% The placement of each path is: shifted and rotated by the same amount
+% as the text (by \gbc{ref_shift}) according to the first four parameters,
+% then shifted to the point given in the third parameter \gbc{loc}, and
+% finally shifted by the vector specified in \gbc{label_adjust}.
+%
+% \gbc{lbl} is either the upper right corner of the text or the label
+% itself. In the first case \gbc{xy} is the lower left corner, in the
+% second case it is a dummy parameter, the bounding box being obtained (in
+% \gbc{pathdims}) by measuring the label. For these extended macros, the
+% parameters \gbc{lbl}, \gbc{mult}, \gbc{rad}, and \gbc{loc} are as in
+% the unextended versions.
+%
+% \DescribeVariable{roundends}
+% The variable \gbc{roundends} is a boolean. We really only need it to be
+% a type distinguishable from any numeric value. \Mfpic{} users can
+% specify it rather than an explicit radius, and when the code of
+% \gbc{textrectx} detects this, it uses the maximum radius for the corners
+% (making the short side of the `rectangle' a semicircle). That is, if
+% \gbc{rad} is a boolean (and \mfc{true}) then the radius at the corners
+% is so chosen. If \gbc{rad} is \mfc{false} the corners are not rounded at
+% all.
+% \begin{macrocode}
+boolean roundends; roundends := true;
+vardef textrectx (expr a, b, c, rot, xy, lbl, rad, loc) =
+ save ll, ur, _r, f, zz;
+ pair ll, ur, zz; path f;
+ pathdims (xy, lbl) (ll, ur);
+ readjustdims (ll, ur) (labelpath_sep)
+ _r := if numeric rad: rad
+ elseif not boolean rad: 0
+ elseif rad: emin (xpart(ur-ll), ypart (ur-ll))/sqrt(2)
+ else: 0
+ fi;
+ if _r = 0:
+ f := rect (ll, ur);
+ else:
+ save p, q;
+ pair p[]; path q;
+ p1 := ur - _r*dir(45);
+ p3 := ll + _r*dir(45);
+ p2 := (xpart p3, ypart p1);
+ p4 := (xpart p1, ypart p3);
+% \end{macrocode}
+% We allow the rounding radius to be negative and make the corners
+% indented in that case. We no longer reverse the path in this case.
+% \begin{macrocode}
+ q := if _r < 0: reverse fi quartercircle scaled 2_r;
+ f :=
+ (q shifted p1)--(q rotated 90 shifted p2)
+ --(q rotated 180 shifted p3)
+ --(q rotated -90 shifted p4)--cycle;
+
+ fi
+ readjustdims (ll, ur) (label_sep - labelpath_sep);
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), rot, f))
+ shifted loc
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{textellipsex}
+% The macro \gbc{textellipsex} is a simlar extension for
+% \gbc{textellipse}. It and the related macro
+% \DescribeRoutine{textovalx}
+% \gbc{textovalx} now call a common macro with different values of a
+% boolean parameter.
+% \begin{macrocode}
+def textovalx = xellipse (true) enddef;
+def textellipsex = xellipse (false) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{xellipse}
+% In \gbc{xellipse}, \gbc{aa} and \gbc{bb} are the horizontal and
+% vertical radii of the resulting ellipse, while \gbc{ww} and \gbc{hh}
+% are half the width and height size of the text. If the boolean
+% \gbc{aspect} is true, the aspect ratio of the ellipse (i.e., \gbc{aa/bb})
+% equals \gbc{mult*ww/hh}, otherwise it equals \gbc{mult}.
+% \begin{macrocode}
+vardef xellipse (expr aspect, a, b, c, r, xy, lbl, mult, loc) =
+ if mult = 0:
+ textrectx (a, b, c, r) (xy, lbl, 0, loc)
+ else:
+ save ll, ur, cc, ww, hh, f;
+ pair ll, ur, cc; path f;
+ pathdims (xy, lbl) (ll, ur);
+ readjustdims (ll, ur) (labelpath_sep)
+ cc := .5[ll, ur];
+ (ww, hh) = ur - cc;
+ if (ww = 0) or (hh = 0):
+ f = (ll--ur);
+ else:
+ save aa, bb;
+% \end{macrocode}
+%
+% The \gbc{aa} and \gbc{bb} are now calculated in a way that decreases the
+% chance of overflow. As a side effect, negative \gbc{mult} no longer
+% reverses the path.
+% \begin{macrocode}
+ aa := ww ++ if aspect: ww else: hh fi *mult;
+ bb := hh ++ if aspect: hh else: ww fi /mult;
+ f := ellipse (cc, aa, bb, 0);
+ fi
+ readjustdims (ll, ur) (label_sep - labelpath_sep);
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), r, f))
+ shifted loc
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{pathdims}
+% This has been changed to make the code of \mfpic{} a bit simpler and
+% to aid in backward compatibility. It takes a couple of pairs (the actual
+% or nominal label bounding box corners) or something visible (picture,
+% string or path) and assigns suitable values to \gbc{ll} and \gbc{ur}.
+%
+% \DescribeRoutine{readjustdims}
+% This is used to add the separations needed to implement the effects of
+% \gbc{label_sep} and \gbc{labelpath_sep}.
+% \begin{macrocode}
+def pathdims (expr xy, lbl) (suffix ll, ur) =
+ if pair lbl:
+ ll := xy; ur := lbl;
+ else:
+%<MF> ll := ur := origin;
+%<*MP>
+ setpicture (_lbl) makepicture (lbl);
+ ll := llcorner _lbl;
+ ur := urcorner _lbl;
+%</MP>
+ fi
+enddef;
+
+def readjustdims (suffix ll, ur) (expr s) =
+ ll := ll - s*(1,1);
+ ur := ur + s*(1,1);
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Additional Functions}\label{functions}
+%
+% Complex variable functions are provided, which interpret a pair $(x, y)$
+% as the complex number $z = x + iy$. We also provide for the use of
+% radians, add the standard exponential and logarithms, and add the
+% hyperbolic functions and their inverses.
+%
+% Normally \mfc{infinity = 2**12 - epsilon} is the largest number allowed
+% (as a value involved in actual drawing in \MF). Since we set
+% \mfc{warningcheck=0}, values not assigned to a variable and not
+% written to the \file{.tfm} file (and any value in \MP) can be as high as
+% \mfc{2**15 - epsilon}, which is a speck smaller than \mfc{1/(2epsilon)}.
+% So \gbc{reallysmall} is the smallest number whose reciprocal is a
+% usable number. (\mfc{epsilon} is the smallest possible positive number
+% in \MF.)
+%
+% The value \gbc{eps/2 + epsilon} is the smallest value with
+% reciprocal less than \mfc{infinity}. I set \gbc{nottoosmall} to
+% \gbc{eps/2 + 2epsilon} to ensure that the same is true of
+% \gbc{2*(nottoosmall/2)}. This is probably not necessary as
+% \mfc{epsilon/2} should round up to \mfc{epsilon} and not be lost. But
+% it also ensures that \gbc{nottoosmall} equals \gbc{2*(nottoosmall/2)},
+% which could be useful.
+%
+% We set \gbc{secd x = 1/(cosd x)} unless \gbc{cosd x} is less than
+% \gbc{reallysmall}, then we set it equal to \gbc{1/reallysmall}. We do a
+% similar thing with \gbc{cscd}. (When such a substitution happens
+% \DescribeRoutine{TruncateWarn}
+% \gbc{TruncateWarn} prints a message that a truncation has taken place.)
+%
+% Why not just determine what number will produce arithmetic overflow and
+% test for that? Because I'm lazy: it would require a different number
+% for each of the functions. Instead, since \MF{} has no `arithmetic
+% underflow', I compute something that is guaranteed to work and occurs
+% in the formula for the function as a reciprocal (e.g., $t = e^{-|x|}$
+% for \gbc{cosh x}) and make sure the number is not too small to take its
+% reciprocal.
+%
+% \DescribeRoutine{signof}
+% This expands to a minus sign if its argument is negative, otherwise
+% nothing.
+% \begin{macrocode}
+newinternal reallysmall; reallysmall := 3epsilon;
+newinternal nottoosmall; nottoosmall := eps/2 + 2epsilon;
+def signof (expr X) = if X < 0: - fi enddef;
+def TruncateWarn expr s =
+ GBwarn s & " is too large or undefined, so it will be truncated.";
+enddef;
+
+% \end{macrocode}
+%
+% In addition to \mfc{sind} and \mfc{cosd} which take angles in degrees,
+% we define the remaining trig functions \gbc{tand}, \gbc{cotd},
+% \gbc{secd}, and \gbc{cscd}.
+%
+% We define \RoutineIndex{secd}\gbc{secd}, one of the simplest, to include
+% an out of range test (which also prevents division by 0). Then
+% \RoutineIndex{tand}\gbc{tand} can make use of it without any division.
+% We do the same with \RoutineIndex{cscd}\gbc{cscd} and
+% \RoutineIndex{cotd}\gbc{cotd}.
+% \begin{macrocode}
+vardef secd primary X =
+ setnumeric (temp) cosd(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Secant or Tangent";
+ temp := signof (temp) reallysmall;
+ fi
+ 1/temp
+enddef;
+vardef tand primary X = sind(X)*secd(X) enddef;
+
+vardef cscd primary X =
+ setnumeric (temp) sind(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Cosecant or Cotangent";
+ temp := signof(temp) reallysmall;
+ fi
+ 1/temp
+enddef;
+vardef cotd primary X = cosd(X)*cscd(X) enddef;
+
+% \end{macrocode}
+%
+% These are the inverse functions, which return an angle in degrees:
+% \RoutineIndex{acos}\gbc{acos}, \RoutineIndex{asin}\gbc{asin} and
+% \RoutineIndex{atan}\gbc{atan}.
+% \begin{macrocode}
+vardef acos primary X =
+ if abs X > 1:
+ TruncateWarn "Argument of arccosine";
+ angle (signof(X) 1, 0)
+ else:
+ angle (X, 1 +-+ X)
+ fi
+enddef;
+vardef asin primary X =
+ if abs X > 1:
+ TruncateWarn "Argument of arcsine";
+ angle (0, signof(X) 1)
+ else:
+ angle (1 +-+ X, X)
+ fi
+enddef;
+vardef atan primary X = angle (1, X) enddef;
+
+% \end{macrocode}
+%
+% Now the trig functions that take angles in radians:
+% \RoutineIndex{sin}\gbc{sin}, \RoutineIndex{cos}\gbc{cos},
+% \RoutineIndex{tan}\gbc{tan}, \RoutineIndex{cot}\gbc{cot},
+% \RoutineIndex{sec}\gbc{sec} and \RoutineIndex{csc}\gbc{csc}.
+% \begin{macrocode}
+vardef sin primary X = sind (X*radian) enddef;
+vardef cos primary X = cosd (X*radian) enddef;
+vardef tan primary X = tand (X*radian) enddef;
+vardef cot primary X = cotd (X*radian) enddef;
+vardef sec primary X = secd (X*radian) enddef;
+vardef csc primary X = cscd (X*radian) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{degrees}
+% It is useful to have a command to convert from radians to degrees and
+% one to
+% \DescribeRoutine{radians}
+% convert from degrees to radians. For example, \gbc{degrees(pi)} produces
+% (approximately) $180$ and \gbc{radians(180)} is approximately $\pi$.
+% \begin{macrocode}
+vardef degrees (expr t) = t*radian enddef;
+vardef radians (expr t) = t/radian enddef;
+
+% \end{macrocode}
+%
+% And the inverses (\RoutineIndex{invsin}\gbc{invsin},
+% \RoutineIndex{invcos}\gbc{invcos} and \RoutineIndex{invtan}\gbc{invtan})
+% that return angles in radians.
+% \begin{macrocode}
+vardef invcos primary X = radians (acos X) enddef;
+vardef invsin primary X = radians (asin X) enddef;
+vardef invtan primary X = radians (atan X) enddef;
+
+% \end{macrocode}
+%
+% Here we define the standard exponential function
+% \RoutineIndex{exp}\gbc{exp}. (The \MF{} function \mfc{mexp} has the
+% unusual base $e^{1/256}$ to avoid overflow.) The inverse of \gbc{exp} is
+% the natural logarithm (\RoutineIndex{ln}\gbc{ln} or
+% \RoutineIndex{log}\gbc{log}). We also have the general base logarithm
+% \RoutineIndex{logbase}\gbc{logbase} and its two special instances
+% \RoutineIndex{logtwo} \gbc{logtwo} and \RoutineIndex{logten}\gbc{logten}.
+% \begin{macrocode}
+vardef exp primary X = mexp (256 * X) enddef;
+vardef ln primary X = (mlog X) / 256 enddef;
+vardef log primary X = ln (X) enddef;
+vardef logbase (expr B) primary X = (mlog X)/(mlog B) enddef;
+vardef logtwo primary X = logbase( 2) (X) enddef;
+vardef logten primary X = logbase(10) (X) enddef;
+
+% \end{macrocode}
+%
+% The hyperbolic functions: \RoutineIndex{cosh}\gbc{cosh}
+% \RoutineIndex{sinh}\gbc{sinh}, \RoutineIndex{tanh}\gbc{tanh},
+% \RoutineIndex{sech}\gbc{sech}, \RoutineIndex{csch}\gbc{csch} and
+% \RoutineIndex{coth}\gbc{coth}.
+% \begin{macrocode}
+vardef cosh primary X =
+ setnumeric (temp) 2 exp (-abs(X));
+ if temp < reallysmall:
+ TruncateWarn "Cosh";
+ temp := reallysmall;
+ fi
+ 1/temp + temp/4
+enddef;
+
+vardef sinh primary X =
+ setnumeric (temp) 2 exp (-abs(X));
+ if temp < reallysmall:
+ TruncateWarn "Sinh";
+ temp := reallysmall;
+ fi
+ signof (X) (1/temp - temp/4)
+enddef;
+
+vardef sech primary X =
+ setnumeric (temp) exp(-(abs (X)));
+ 2temp/(1 + temp*temp)
+enddef;
+
+vardef tanh primary X =
+ setnumeric (temp) exp(-2(abs (X)));
+ signof (X) (1 - temp)/(1 + temp)
+enddef;
+
+vardef csch primary X =
+ save temp, tempa; temp := exp(-(abs (X)));
+ tempa := (1 - temp*temp)/2;
+ if tempa < reallysmall:
+ TruncateWarn "Csch";
+ tempa := reallysmall;
+ fi
+ signof (X) temp / tempa
+enddef;
+
+vardef coth primary X =
+ setnumeric (temp) tanh(X);
+ if abs(temp) < reallysmall:
+ TruncateWarn "Coth";
+ temp := signof (X) reallysmall;
+ fi
+ 1/temp
+enddef;
+
+% \end{macrocode}
+%
+% The inverses of some of the hyperbolic functions:
+% \RoutineIndex{acosh}\gbc{acosh}, \RoutineIndex{asinh}\gbc{asinh} and
+% \RoutineIndex{atanh}\gbc{atanh}.
+% \begin{macrocode}
+vardef acosh primary y =
+ if y < 1:
+ TruncateWarn "acosh";
+ 0
+ else:
+ ln (y + (y +-+ 1))
+ fi
+enddef;
+
+vardef asinh primary y = ln (y + (y ++ 1)) enddef;
+
+vardef atanh primary y =
+ if abs (y) < 1:
+ (ln (1 + y) - ln (1 - y))/2
+ else:
+ TruncateWarn "atanh";
+ signof (y) infinity
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \CMF's pair variables are a decent replacement for complex variables.
+% These give some of the more basic functions of standard complex
+% analysis: \RoutineIndex{Arg}\gbc{Arg}, \RoutineIndex{Log}\gbc{Log},
+% \RoutineIndex{cis}\gbc{cis}, \RoutineIndex{zexp}\gbc{zexp},
+% \RoutineIndex{sgn}\gbc{sgn}, \RoutineIndex{zsqrt}\gbc{zsqrt} and
+% \RoutineIndex{conj}\gbc{conj}.
+% \begin{macrocode}
+vardef Arg primary Z = (angle Z)/radian enddef;
+vardef Log primary Z = (ln (abs Z), Arg Z) enddef;
+vardef cis primary T = dir (T*radian) enddef;
+vardef zexp primary Z = (exp (xpart Z)) * cis (ypart Z) enddef;
+vardef sgn primary Z = if not (Z = origin): unitvector fi Z
+enddef;
+vardef zsqrt primary Z =
+ if Z = origin: origin else: sqrt(abs(Z)) * dir ((angle Z)/2) fi
+enddef;
+vardef conj primary Z = (xpart Z, -ypart Z) enddef;
+
+% \end{macrocode}
+%
+% DescribeRoutine{zmul}
+% Unfortunately, while \MF{} will happily add and subtract pairs, it
+% will not multiply or divide them without help. We provide alternatives
+% \DescribeRoutine{zdiv} here.
+% \begin{macrocode}
+primarydef Z zmul W = Z zscaled W enddef;
+primarydef Z zdiv W =
+ Z zmul ( unitvector (conj W) / (abs W) )
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{Moebius}
+% A less basic operation: the Moebius shift which takes the disk $|z| <
+% 1$ onto itself. It is a hyperbolic geometry analog of shifting points
+% in Euclidean geometry. Its mathematical definition (all variables are
+% complex numbers):
+% \[
+% M_a(z) = \frac{z + a}{1 + \bar az}
+% \]
+% Its inverse is $M_{-a}$.
+%
+% \DescribeRoutine{pshdist}
+% Related to \gbc{Moebius} is the pseudohyperbolic metric. The distance
+% between $z$ and $w$ in this metric is $|z-w|/|1 - \bar wz|$. There is
+% \DescribeRoutine{pshdist_hp}
+% also a version of this for the upper half-plane: $|z-w|/|z-\bar w|$.
+%
+% Closely related to all this is Kelvin transform. In complex notation
+% it is simply $1/\bar z = z/|z|^2$. The term ``Kelvin transform'' is
+% normally only used in real variables (of any dimension greater than 1).
+% \begin{macrocode}
+vardef Moebius (expr A) primary Z =
+ save _D; pair _D;
+ _D := (1, 0) + (Z zscaled (conj A));
+ (Z + A)/(abs _D) rotated (- angle _D)
+enddef;
+vardef pshdist (expr Z,W) = abs(Moebius(-W)(Z)) enddef;
+vardef pshdist_hp (expr Z,W) = abs(Z-W)/abs(Z-conj(W)) enddef;
+vardef kelvin (expr Z) =
+ save tmp_; tmp_ = abs(Z);
+ if tmp_ = 0:
+ (infinity, infinity)
+ elseif tmp_ < reallysmall:
+ infinity*unitvector Z
+ else:
+ (1/tmp_)*unitvector Z
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{polar}
+% \gbc{polar} converts a polar coordinate pair $(r, \theta)$ to the
+% corresponding rectangular coordinate pair.
+% \DescribeRoutine{id}
+% \gbc{id} returns its argument, which can be any expression of any type.
+% \begin{macrocode}
+vardef polar primary p = (xpart p) * dir (ypart p) enddef;
+def id (expr x) = x enddef;
+
+% \end{macrocode}
+%
+% The definition of powers (\gbc{x**y}) in \prog{plain} \MF{} and \MP{}
+% could be more accurate. In particular \gbc{x=2**10} ought to be an
+% integer (that is, satisfy \mfc{x=floor x}). Here we redefine
+% \prog{plain}'s \mfc{**}, intercepting the case of a positive integer
+% power of an integer.
+%
+% There are some negative powers, and some integer powers of nonintegers
+% that can also be calculated exactly within \MF{}'s limited precision,
+% but it is difficult to determine those cases programmatically. Computing
+% every integer power by repeated multiplication or division might
+% actually reduce accuracy in the nonexact cases, so we limit ourselves to
+% this one special case.
+% \begin{macrocode}
+primarydef x**y =
+ if y=2: x*x
+ elseif (x = floor x) and (abs y = floor y):
+ 1 for n=1 upto y: *x endfor
+ else: takepower y of x
+ fi
+enddef;
+let ^ = **;
+
+% \end{macrocode}
+%
+%
+% \section{Coordinate Systems and Transformations}\label{systems}
+%
+% \DescribeVariable{T_stack}
+% We want to define a localization of the current transform. To do
+% this we define a LIFO stack of transforms \gbc{T_stack[\,]}, and a pair of
+% macros.
+% \DescribeRoutine{T_push}
+% \gbc{T_push} puts its argument (a transform) on the stack, and
+% \DescribeRoutine{T_pop}
+% \gbc{T_pop} pops it off into its argument (a transform variable name).
+% We also define two localizing macros
+% \DescribeRoutine{bcoords}
+% \gbc{bcoords} that pushes our \gbc{ztr}
+% on the stack, and
+% \DescribeRoutine{ecoords}
+% \gbc{ecoords} that pops it off. We no longer put \gbc{vtr} on the stack,
+% since we can recalculate it whenever \gbc{ztr} is changed. \gbc{apply_t}
+% always did this, now \gbc{ecoords} does so as well.
+% \begin{macrocode}
+transform T_stack[];
+numeric T_stack; T_stack := 0;
+
+def T_push (expr T) = T_stack[incr T_stack] := T; enddef;
+def T_pop (suffix $) =
+ if T_stack > 0:
+ $ := T_stack[T_stack];
+ T_stack := T_stack - 1;
+ fi
+enddef;
+
+def bcoords = hide ( T_push (ztr) ) enddef;
+def ecoords = hide ( T_pop (ztr); vtr := vectorpart ztr ) enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Coordinate changes}\label{changes}
+%
+% \DescribeRoutine{apply_t}
+% Here we define a mechanism for changing \gbc{ztr} and \gbc{vtr} by
+% composing them with a new transform. Since a transform can be any affine
+% transform, we get \gbc{ztr} by composing with the transform, but we
+% calculate \gbc{vtr} from \gbc{ztr} by arranging that \mfc{origin
+% transformed vtr} is \mfc{origin}. The syntax is \gbc{apply_t(rotated
+% theta)} or \gbc{apply_t(transformed T)} if \mfc{T} is a variable or
+% expression of type transform. Thus the argument of \gbc{apply_t} is a
+% phrase which, were it to follow a path, would produce a transformed
+% path. Knuth calls such a phrase a \emph{transformer}.
+% \begin{macrocode}
+vardef vectorpart primary T = T shifted -(origin transformed T)
+enddef;
+
+def apply_t (text Transformer) =
+ ztr := identity Transformer transformed ztr;
+ vtr := vectorpart ztr;
+enddef;
+
+% \end{macrocode}
+%
+% And now we define some available transformers.
+% \RoutineIndex{xslant}\gbc{xslant}, \RoutineIndex{yslant}\gbc{yslant},
+% \RoutineIndex{zslant}\gbc{zslant}, \RoutineIndex{xyswap}\gbc{xyswap} and
+% \RoutineIndex{boost}\gbc{boost}. The only two that need comment are
+% \gbc{zslant} and \gbc{boost}. I know that boost comes from special
+% relativity, but I have no idea why zslant is a `slant'.
+% \begin{macrocode}
+def xslant = slanted enddef; % (x+sy, y).
+def yslant primary s = % (x, y+sx).
+ transformed
+ begingroup
+ save T; transform T;
+ origin transformed T = origin;
+ (1, 0) transformed T = (1, s);
+ (0, 1) transformed T = (0, 1);
+ T
+ endgroup
+enddef;
+
+def zslant primary p = % (xu+yv, xv+yu), where p = (u, v).
+ transformed
+ begingroup
+ save T; transform T;
+ xpart T = ypart T = 0;
+ xxpart T = yypart T = xpart p;
+ xypart T = yxpart T = ypart p;
+ T
+ endgroup
+enddef;
+
+def xyswap = zslant (0, 1) enddef;
+def boost primary X = zslant (cosh X, sinh X) enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Path transformation}\label{transformation}
+%
+% These are functions that accept and return a path in graph coordinates.
+% For the most part they are named and defined to apply a similarly named
+% transform to the path and return the result. There are two exceptions.
+% When we draw things, we expect that rotated and reflected objects appear
+% congruent to the originals. If we define a path in graph coordinates,
+% and the $x$ and $y$ directions are scaled differently, then simply
+% rotating the graph coordinates will distort angles. The same is true of
+% reflection. Therefore, we apply \gbc{vtr} (so we are in drawing
+% coordinates) then rotate or reflect, then apply \gbc{inverse vtr}. This
+% may be a mistake, or perhaps we should do it for all of these. For now,
+% I'm sticking with the scheme I inherited. One can always use
+% \gbc{coords} and \gbc{apply_t} if one wants the difference in scales
+% ignored.
+%
+% \DescribeRoutine{transformedpath}
+% This is a vardef that reads an undelimited path expression and returns
+% the path transformed by the text argument. All the others run this,
+% allowing it to grab the path expression.
+%
+% \DescribeRoutine{rotatedpath}
+% This returns the path rotated around point \gbc{p} by angle
+% \gbc{th} in degrees.
+%
+% \DescribeRoutine{reflectedpath}
+% This reflects the path through the line containing points \gbc{p} and
+% \gbc{q}.
+%
+% \DescribeRoutine{scaledpath}
+% This returns the path scaled so that distances from the point
+% \gbc{p} are multiplied by \gbc{s}.
+% \DescribeRoutine{xscaledpath}
+% \gbc{xscaledpath} is similar, but only the horizontal distances from
+% the line $x={}$\gbc{a} are multiplied by \gbc{s}. And with
+% \DescribeRoutine{yscaledpath}
+% \gbc{yscaledpath} the vertical distances from the line $y={}$\gbc{b} are
+% multiplied by \gbc{s}.
+%
+% \DescribeRoutine{xslantedpath}
+% The macro \gbc{xslantedpath} returns the path xslanted with line
+% $y = {}$\gbc{b} being the pivot rather than the $x$-axis.
+% \DescribeRoutine{slantedpath}
+% The command \gbc{slantedpath} is just an alias for \gbc{xslantedpath},
+% while
+% \DescribeRoutine{yslantedpath}
+% \gbc{yslantedpath} is the vertical version, yslanted with line $x =
+% {}$\gbc{a} being the pivot rather than the $y$-axis.
+%
+% \DescribeRoutine{shiftedpath}
+% This returns the path shifted by the vector (pair) \gbc{v}.
+%
+% \DescribeRoutine{xyswappedpath}
+% The command \gbc{xyswappedpath} returns the path in which all points
+% have had the coordinates exchanged $(a, b) \to (b, a)$. Note that this
+% is not the same as \gbc{reflectedpath ((0,0), (1,1))}, as it performs
+% the reflection in graph coordinates, as its name implies. If \gbc{vtr}
+% has not been changed (by \gbc{apply_t}) then \gbc{xyswappedpath} will
+% convert vertical lines to horizontal and vice versa. The
+% \gbc{reflectedpath} version will not when $x$ and $y$ are scaled
+% differently, for then the line \gbc{(0,0)--(1,1)} is not at a 45 degree
+% angle in device coordinates where drawing takes place.
+%
+% \begin{macrocode}
+vardef transformedpath (text Transformer) expr f = f Transformer
+enddef;
+
+def rotatedpath (expr p, th) =
+ transformedpath (
+ transformed vtr
+ rotatedaround (p transformed vtr, th)
+ transformed (inverse vtr)
+ )
+enddef;
+def reflectedpath (expr p, q) =
+ transformedpath (
+ transformed vtr
+ reflectedabout (p transformed vtr, q transformed vtr)
+ transformed (inverse vtr)
+ )
+enddef;
+
+def scaledpath (expr p, s) =
+ transformedpath (shifted -p scaled s shifted p)
+enddef;
+def xscaledpath (expr a, s) =
+ transformedpath (shifted (-a, 0) xscaled s shifted (a, 0))
+enddef;
+def yscaledpath (expr b, s) =
+ transformedpath (shifted (0, -b) yscaled s shifted (0, b))
+enddef;
+
+def slantedpath = xslantedpath enddef;
+def xslantedpath (expr b, s) =
+ transformedpath (shifted (0, -b) slanted s shifted (0, b))
+enddef;
+def yslantedpath (expr a, s) =
+ transformedpath (shifted (-a, 0) yslant s shifted (0, a))
+enddef;
+
+def shiftedpath (expr v) = transformedpath (shifted v) enddef;
+
+def xyswappedpath = transformedpath (xyswap) enddef;
+
+% \end{macrocode}
+%
+% It seems odd, in retrospect, that we got by with a user interface that
+% didn't include any subpath operations. But recently a user asked for the
+% ability to add an arrowhead to the \emph{middle} of a path, and it
+% seemed best to provide a subpath and use existing commands to add an
+% arrowhead on its end.
+%
+% \DescribeRoutine{partialpath}
+% The \gbc{partialpath} macro takes two fractions $\alpha$ and $\beta$
+% between 0 and 1, and a path \gbc{f}, and returns the subpath from
+% $\alpha * {} $\meta{length of \gbc{f}} to $\beta * {}$\meta{length of
+% \gbc{f}} of \gbc{f}. Since the \gbc{gettime} routine was written to
+% find the times for an increasing sequence of lengths, it was optimized
+% to save the index of the previous length and begin from there. Thus it
+% is more efficient to find the smaller of \gbc{a} and \gbc{b} first.
+%
+% Since running \gbc{gettime} would be a very inefficient way to get the
+% first or last point of a path we skip that if either fraction is $0$ or
+% $1$ (a common use is to get the first or last half of a path). We also
+% skip finding the second time if \gbc{a = b} (an unlikely choice, but
+% legal).
+%
+% \DescribeRoutine{gsubpath}
+% \gbc{gsubpath} is the same as \MF's subpath primitive, but follows the
+% prefix macro syntax of accepting a path expression (rather than a
+% primary) and wrapping the result in a \mfc{vardef}.
+% \begin{macrocode}
+vardef partialpath (expr a, b) expr f =
+ save flag, flo, fhi, lo, hi, n;
+ boolean flag; flag = true;
+ convertpath (g) f;
+ n := length f;
+
+ flo := snapto emin(a,b);
+ if flo = 0:
+ lo := 0;
+ elseif flo < 1:
+ setuplengtharray (cum, tot, idx) g;
+ flag := false;
+ lo := gettime (cum, idx) (flo*tot);
+ else:
+ lo := n;
+ fi
+
+ fhi := snapto emax (a,b);
+ if flo = fhi:
+ hi := lo;
+ elseif fhi < 1:
+ if flag: setuplengtharray (cum, tot, idx) g; fi
+ hi := gettime (cum, idx) (fhi*tot);
+ else:
+ hi := n;
+ fi
+
+ if a > b: reverse fi subpath (lo, hi) of f
+enddef;
+
+vardef gsubpath (expr a, b) expr f = subpath (a, b) of f enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{setuplengtharray}
+% This does the frequently repeated saving, rescaling and initializing
+% for those commands that need to convert distance along a path to the
+% corresponding time or point. A path variable should follow, but that
+% is picked up by the \gbc{makelengtharry} at the end.
+% \begin{macrocode}
+def setuplengtharray (suffix cum, tot, idx) =
+ save cum, tot, idx; idx := 0; tot := makelengtharray (cum)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{pathtime}
+% \gbc{pathtime} returns the time \mfc{t} such that \mfc{point t of p} is
+% \gbc{frac} of the distance along \gbc{p} from the start, and
+% \DescribeRoutine{pathpoint}
+% \gbc{pathpoint} returns the point itself. Because the \gbc{gettime}
+% routine requires it anyway, we truncate \gbc{frac} to the interval
+% $[0,1]$ and avoid calling that rather lengthy function at $0$ and $1$.
+%
+% The path in pathtime should be in device coordinates, whereas the
+% user-level command \gbc{pathpoint} expects it in graph coordinates.
+% In fact, since \gbc{pathpoint} would most likely be used in the
+% argument of some figure macro in \mfpic{}, it would require a
+% previously stored path, so we make the path a suffix parameter.
+% \begin{macrocode}
+vardef pathtime@# (suffix p) =
+ if @# <= 0: 0
+ elseif @# >= 1: length p
+ else:
+ setuplengtharray (cum, tot, idx) p;
+ gettime (cum, idx) (@#*tot)
+ fi
+enddef;
+
+vardef pathpoint (expr frac) (suffix p) =
+ convertpath (_pp) p; pnt[pathtime[frac] (_pp)] (p)
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Picture-level Operations}\label{picture}
+%
+%
+% \subsection{Bitwise logical operations}\label{logical}
+%
+% None of these operations are available in \MP. Mostly these are used by
+% higher level operations. Those higher level operations are available in
+% \MP, but need to be defined differently.
+%
+% We have two types of operations. One type is a binary operator that
+% takes two picture expressions and returns a picture, the other type
+% returns nothing, but merely modifies a given picture variable. These
+% take the name of a picture and a picture expression and modify the named
+% one. The binary operators are not used elsewhere in graphbase except
+% for \gbc{picsub}, which occurs only in \gbc{shadepic}. They are all
+% rather wasteful of memory.
+%
+% \DescribeRoutine{mono}
+% Here we define the bitwise logical operations: and, or, xor, and
+% difference. These mostly only work if all pixels have values 0 or 1.
+% Since \MF{} allows other integer values, we define a \gbc{mono} operator
+% that converts all pixels with weight ${}\ge 1$ to 1 and all pixels
+% with weight ${}\le 0$ to 0. It is important to note that we can apply
+% \gbc{mono} only to the suffix parameter in such things as \gbc{orto}.
+% The expression parameter needs to be prepared by the routine that calls
+% these. The return result is culled, so it consists only of 0s and 1s.
+% \begin{macrocode}
+%<*MF>
+def mono (suffix u) = cull u keeping (1, infinity); enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{andto, picand}
+% The bitwise and: in the resulting picture, a pixel is \emph{on} if and
+% only if it is \emph{on} in both \gbc{u} and \gbc{v}. \gbc{andto} is
+% only used in \gbc{interior} and \gbc{interiors}, \gbc{picand} is not
+% used at all.
+% \begin{macrocode}
+def andto (suffix u) (expr v) =
+ mono (u); addto u also v; cull u keeping (2, 2);
+enddef;
+primarydef u picand v =
+ begingroup setpicture (t) u; andto (t, v); t endgroup
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{orto, picor}
+% The inclusive or: in the result, a pixel is \emph{on} if and only if it
+% is \emph{on} in \gbc{u} or \gbc{v} or both. I've written these so that
+% it doesn't matter if the expression parameter is not mono. It
+% \emph{is} required that it have only positive pixels. The command
+% \gbc{orto} is only used three places: in \gbc{coloraddto}, which
+% is itself never used, and in \gbc{patcharcs} and \gbc{patchrays}. This
+% lack of use is because a less memory intensive version, \gbc{_orto}, is
+% defined later, and that is what we use. Usually we build a picture
+% in a variable \gbc{src} and add that onto another variable \gbc{dest}.
+% If one used \gbc{orto (dest, src)}, then \MF{} would evaluate \gbc{src}
+% and pass a \emph{copy} of it as the parameter of \gbc{orto}. This
+% doubles the memory used, so mostly we use \gbc{_orto}, which passes both
+% parameters as suffixes. \gbc{picor} is never used.
+% \begin{macrocode}
+def orto (suffix u) (expr v) =
+ mono (u); addto u also v; cull u keeping (1, infinity);
+enddef;
+primarydef u picor v =
+ begingroup setpicture (t) u; orto (t, v); t endgroup
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{xorto, picxor}
+% The exclusive or, also called the symmetric difference:
+% in the result, a pixel is \emph{on} if and only if it is \emph{on} in
+% \gbc{u} or \gbc{v}, but not both. These are not used elsewhere in
+% \grafbase.
+% \begin{macrocode}
+def xorto (suffix u) (expr v) =
+ mono (u); addto u also v; cull u keeping (1, 1);
+enddef;
+primarydef u picxor v =
+ begingroup setpicture (t) u; xorto (t, v); t endgroup
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{subto}
+% The nonsymmetric difference: in the result, a pixel is \emph{on} if
+% and only if it is \emph{on} in \gbc{u} and off in \gbc{v}. It is
+% unclear whether a \gbc{v} with negative weights will ever occur, but
+% if so, subtracting negative pixels ought to be like adding positive
+% ones, so I've changed \mfc{keeping (1,1)} to \gbc{keeping (1,infinity)}.
+% With this understanding, it doesn't matter here whether \gbc{v} is
+% not mono. As with \gbc{orto}, we have a more memory efficient
+% \gbc{_subto} and now use that everywhere. \gbc{subto} is only used in
+% \gbc{coloraddto}, which is not used anymore. The binop version
+% \DescribeRoutine{picsub}\gbc{picsub}
+% is used only in \gbc{shadepic}.
+% \begin{macrocode}
+def subto (suffix u) (expr v) =
+ mono (u); addto u also -v; cull u keeping (1, infinity);
+enddef;
+primarydef u picsub v =
+ begingroup setpicture (t) u; mono (t); subto (t, v); t endgroup
+enddef;
+
+%</MF>
+% \end{macrocode}
+%
+%
+% \subsection{Producing and modifying pictures}\label{pictures}
+%
+% Here we define some slightly higher level commands that make use (in \MF)
+% of the previous bitmap operations. In \MP, they mostly need different
+% definitions, but we have merged most of them by providing a \MP{}
+% alternative for the most frequently used bitmap operation in the
+% previous section, \gbc{orto}. These operations either return a picture
+% or modify a picture variable. They do not draw anything unless
+% \gbc{active_plane} is the modified picture. All curves, points,
+% dimension, etc., are in device coordinates.
+%
+% \DescribeRoutine{coloraddto}
+% This was once a useful abbreviation. In \MF{} it adds when the color
+% is not white, subtracts when it is. Grays are handles in \MF{} by
+% appropriate preparation of \gbc{u} and \gbc{v}. See, for example, the
+% code of \gbc{colorsafefill}. In \MP{} it is an abbreviation for the
+% basic \mfc{addto} operation. It was defined only so that \MP{} and \MF{}
+% can share the same higher level code.
+%
+% When the last parameter \gbc{v} is the name of picture we can save
+% memory if we pass the name rather than the value. Problems with picture
+% memory turned up in the shading macros for \MF{} and the dashing macros
+% for \MP{}.
+% \DescribeRoutine{coloraddon}
+% The macro \gbc{coloraddon} applies this memory-saving trick and has
+% completely replaced \gbc{coloraddto} in \grafbase{} code. Since
+% \gbc{coloraddto} turned out to be used only with \gbc{u} equal to
+% \gbc{active_plane}, we have eliminated that parameter from
+% \gbc{coloraddon}.
+%
+% The command \gbc{_orto} is like \gbc{orto}, but saves memory by passing
+% \emph{both} parameters by name. This also allows the application of
+% \gbc{mono} to both parameters. In addition to \gbc{coloraddon}, it is
+% used in \gbc{shade} and \gbc{tess}.
+% We also have \gbc{_subto}, an analogous version of \gbc{subto}.
+% \begin{macrocode}
+def coloraddto (expr clr) (suffix u) (expr v) =
+%<*MF>
+ if clr < white:
+ orto (u, v);
+ else:
+ subto (u, v);
+ fi;
+%</MF>
+%<MP> addto u also v _wc_ clr;
+enddef;
+
+%<MP>def orto (suffix u) (expr v) = addto u also v; enddef;
+%<MP>
+def coloraddon (expr clr) (suffix v) =
+%<*MF>
+ if clr < white:
+ _orto (active_plane, v);
+ else:
+ _subto (active_plane, v);
+ fi;
+%</MF>
+%<MP> addto active_plane also v _wc_ clr;
+enddef;
+
+def _orto (suffix u, v) =
+%<MF> mono (u); mono (v);
+ addto u also v;
+%<MF>cull u keeping (1, 2);
+enddef;
+
+%<*MF>
+def _subto (suffix u, v) =
+ mono (u); mono (v); addto u also -v; cull u keeping (1, 1);
+enddef;
+
+%</MF>
+% \end{macrocode}
+%
+% \DescribeRoutine{interior}
+% This takes the following expresion, \gbc{c}, which must be a
+% closed path, and returns the picture expression which is that path
+% filled. The cull command (\MF{} only) retains negative pixels
+% (converting them to positive). This way, clockwise contours are filled
+% also. \gbc{interior} is one of the most used commands throughout the
+% rest of \grafbase.
+%
+% We ignore color (new behavior with \mfpic{} version 0.7), since the
+% higher level commands now implement the coloring operations.
+% \begin{macrocode}
+vardef interior expr c =
+ newpicture (v);
+ addto v contour (c.t_);
+%<MF> cull v dropping (0,0);
+ v
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{interiors}
+% This is followed by the name of an array of closed paths and
+% returns the picture of the interiors of those closed paths. It builds
+% the returned picture from \mfc{nullpicture} by successively adding
+% the result of \gbc{interior} applied to each path in the array. This is
+% only used once by \grafbase, in \gbc{clipsto}, which might be a better
+% place to put the \mfc{for}-loop and not use this at all.
+% \begin{macrocode}
+vardef interiors suffix cc =
+ newpicture (_ints);
+ for _idx = 1 upto cc:
+ addto _ints also interior cc[_idx]);
+ endfor
+%<MF> mono (_ints);
+ _ints
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Clipping}\label{basicclipping}
+%
+% \DescribeRoutine{clipto}
+% \gbc{clipto} takes the name of a picture \gbc{vt} and a closed path
+% \gbc{c} and modifies the picture leaving only the part inside the path.
+% In \MP{} we just invoke the \mfc{clip} primitive.
+%
+% \DescribeRoutine{clipsto}
+% This is similar, except it takes an array of paths \gbc{cc} and
+% leaves what is interior to any of the paths. This is one case where
+% \MP{} requires a substantially different point of view. In \MF, we
+% create the interiors and `and' the result to the named picture. In \MP,
+% we have to create the picture which is \gbc{vt} clipped to each separate
+% path, and combine the results. \Grafbase{} only uses this in the
+% \gbc{DoClip} command.
+% \begin{macrocode}
+def clipto (suffix vt) expr c =
+ if path c:
+%<MF> andto (vt, interior c);
+%<MP> clip vt to c;
+ fi
+enddef;
+def clipsto (suffix vt, cc) =
+%<MF> andto (vt, interiors cc);
+%<*MP>
+ begingroup
+ save _cl, _cl_; picture _cl, _cl_; _cl_ := nullpicture;
+ for _idx = 1 upto cc:
+ _cl := vt; clip _cl to cc[_idx]; addto _cl_ also _cl;
+ endfor
+ vt := _cl_;
+ endgroup
+%</MP>
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{Clipped}
+% Here, rather than modify a given picture, \gbc{Clipped} is a vardef
+% returning the picture which is the result of clipping the given picture
+% to the path. This is not used elsewhere in \grafbase{} nor \mfpic.
+%
+% Having found out that \mfc{clipped} is a \MP{} primitive, I've
+% changed the name to the uppercase version.
+% \begin{macrocode}
+vardef Clipped (suffix vt) expr c =
+ setpicture (_Cl) vt; clipto (_Cl) c; _Cl
+enddef;
+%<MF>def clip = Clipped enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{picneg}
+% The reverse video is easy in \MF, where \gbc{picneg} takes a picture
+% name and a closed path, and returns the part of the picture inside the
+% path, but with pixels reversed. In \MP{} we can only approximate this:
+% we clip the given picture and add that (using color \gbc{background})
+% on top of the \gbc{interior} of the curve colored \gbc{fillcolor}. This
+% is not used elsewhere in \file{grafbase.mp} so it may not be really
+% important whether \gbc{fillcolor} and \mfc{background} are the right
+% choices.
+% \begin{macrocode}
+vardef picneg (suffix vt) expr c =
+%<*MF>
+ setpicture (_pn) interior c;
+ _subto (_pn, vt);
+%</MF>
+%<*MP>
+ setpicture (_cl) vt; clip _cl to c;
+ newpicture (_pn);
+ addto _pn also (interior c ) _wc_ fillcolor;
+ addto _pn also _cl _wc_ background;
+%</MP>
+ _pn
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{shpath}
+% \gbc{shpath} does most of the work of drawing curves in \grafbase. It is
+% called by \gbc{safedraw} which is used by almost all the commands that
+% somehow draw a curve. It takes the name of a picture, a pen expression
+% and a path expression. It draws the path on the picture with the pen.
+% Since we use this (ultimately) for almost all drawing of paths, we
+% automatically have the aspect ratio taken care of by the \mfc{.t_}
+% macro.
+%
+% \DescribeRoutine{picpath}
+% \gbc{picpath} accepts a path expression and returns a picture, which is
+% either \gbc{nullpicture} (\gbc{penwd} too small) or the path drawn with
+% \gbc{drawpen}. This is mostly how \gbc{shpath} gets used: curve drawing
+% commands produce a picture with \gbc{picpath} and that gets used.
+%
+% \begin{macrocode}
+def shpath (suffix v) (expr q, f) =
+ addto v doublepath (f.t_) withpen (q.t_);
+enddef;
+
+numeric minpenwd;
+%<MF>minpenwd := 1; % 1 pixel
+%<MP>minpenwd := .05bp; % 1 pixel at 1440dpi
+vardef picpath expr d =
+ newpicture (v);
+ if penwd >= minpenwd:
+ shpath (v, drawpen) (d);
+%<MF> mono (v);
+ fi
+ v
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{picdot}
+% This places a specified picture expression (\gbc{w}) at a specified
+% location (\gbc{p}) in a specified picture variable (\gbc{v}). It is used
+% a number of places. It's \MF{} version takes care of the aspect ratio
+% via \mfc{.t_}. This is how we draw points and symbols and dots along a
+% curve: make the symbol into a picture \gbc{w} and add that picture with
+% \gbc{picdot}.
+% \begin{macrocode}
+def picdot (suffix v) (expr w, p) =
+ addto v also
+%<MP> (w shifted p);
+%<MF> (w shifted goodpair (p));
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{setdot}
+% \gbc{setdot} is named for its use rather than what it does. It takes a
+% path and a scale (numeric expression) and returns a picture which is a
+% drawing of the filled interior of the path (if it is a cycle) or the
+% path itself (not a cycle). In \MF, we ensure that the scale is at least
+% one pixel (assumes that the \gbc{apath} has dimension about 1 and
+% \gbc{minpenwd} is 1). This usually assures that something is drawn. In
+% \MP, \gbc{minpenwd} has the same purpose (though it is probably not
+% necessary). This routine is used a number of times where dots are
+% needed. Not in \gbc{shaded} (just below) but later in \gbc{shade} (an
+% older command taking paths in graph coordinates), \gbc{polkadot} and
+% some grid-making commands.
+% \begin{macrocode}
+vardef setdot (expr apath, sc) =
+ if cycle apath: interior
+ else: picpath
+ fi
+%<MF> (apath scaled emax (ceiling (sc), minpenwd))
+%<MP> (apath scaled emax (sc, minpenwd))
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{shadepic}
+% We want to shade regions with a very regular pattern of black and white
+% pixels for best appearance. Experiments show that symmetric dots
+% (e.g., circles, squares) work better than non-symmetric (e.g.,
+% rectangular). Circular dots are not significantly better than square at
+% the size needed. I believe that the default result of \gbc{shade} looks
+% reasonably good on my system. (That happens to produce two 3-pixel by
+% 3-pixel square dots in a 8-pixel square on a 360dpi printer.) So we try
+% to produce something similar. That is, the shading picture is 1.6bp
+% (8 pixels at 360dpi) square.
+%
+% As a compromise (symmetric dots look better, but rectangular dots give
+% more gray levels) we allow dots to be rectangles $k\times (k+1)$-pixels
+% (assuming the aspect ratio is 1). This produces twice the number of
+% gray levels. In my 360dpi example we get 15 gray levels. The two
+% farthest apart (4 by 4 dots versus 3 by 4 dots) differ by 1/8 in
+% fraction of area of coverage (which we equate to grayness).
+%
+% Why can't we have 64 grey levels in a $8\times 8$ square? Clearly we
+% can in principle turn on any number of the 64 pixels. Unfortunately,
+% spread out patterns (which look best) tend to consume memory, while
+% clumpy patterns are hard to make good-looking. Compensating for aspect
+% ratios unequal to 1 is also pretty hard to do automatically.
+%
+% The parameter \gbc{dims} needs to be a pair variable, and it will be
+% assigned the actual dimensions of the picture returned. These routines
+% are complicated by the fact that we may have an aspect ratio unequal to
+% $1$. When \mfc{aspect_ratio = 1} the basic concept is simple: make an
+% $n\times n$ square with two dots, each nearly $k \times k$ and nearly
+% square, where $2k^2/n^2$ is the gray level needed.
+%
+% The calculations assume a gray level greater than $1/2$, so the final
+% picture will be mostly white (for darker grays, we use the
+% complementary gray level to construct the `reverse video', and then
+% reverse back). Under this assumption, we concentrate all the black
+% pixels into the lower left and upper right quadrant of the picture we
+% are creating, so most of the calculation determines one of these
+% quadrants. The scratch variables \gbc{_hp} and \gbc{_vp} give the number
+% of horizontal and vertical pixels in the lower left quadrant,
+% \gbc{_dotwd} and \gbc{_dotht} do the same for the actual dot. Then
+% \gbc{_shp} is first set equal to one dot; then a copy of itself is added
+% in the upper right quadrant. Finally, the suffix parameter \gbc{dims} is
+% equated to the nominal width and height of the picture, and either
+% \gbc{_shp} or its reverse is returned.
+% \begin{macrocode}
+%<*MF>
+numeric shadepicsize; shadepicsize := 0.8bp;
+vardef shadepic (suffix dims) (expr grparam) =
+ pair dims;
+ setnumeric (_frac) 2*emin (grparam, 1 - grparam);
+ save _hp, _vp, _dotwd, _dotht;
+ if aspect_ratio < 1:
+ _vp := emax (2, hround (shadepicsize.o_));
+ _hp := hround (_vp._o_);
+ _dotwd := hround (_hp*sqrt _frac);
+ _dotht := if _dotwd = 0: 0
+ else: hround (_hp*_vp*_frac/_dotwd)
+ fi;
+ else:
+ _hp := emax (2, hround (shadepicsize));
+ _vp := hround (_hp.o_);
+ _dotht := hround (_vp*sqrt _frac);
+ _dotwd := if _dotht = 0: 0
+ else: hround (_hp*_vp*_frac/_dotht)
+ fi;
+ fi
+ dims := ( _hp, _vp._o_ );
+ newpicture (_shp);
+ addto _shp contour rect (origin, (_dotwd, _dotht));
+ picdot (_shp, _shp, dims);
+ dims := 2dims; mono (_shp);
+ if grparam >= .5: _shp
+ else: (interior (rect (origin, dims))) picsub _shp
+ fi
+enddef;
+
+%</MF>
+% \end{macrocode}
+%
+% \DescribeRoutine{shaded}
+% This fills the interior of a contour (device coordinates) with copies of
+% \gbc{shadepic}. The routine \gbc{fillwith} is defined later, but its
+% name reflects its effect: a bounding rectangle (corners at \gbc{ll} and
+% \gbc{ur}) is filled with copies of a picture (in this case, the result
+% of \gbc{shadepic}), the picture having nominal dimensions \gbc{shdims}
+% in this case.
+%
+% It may seem odd that black and white return the same thing. That is
+% because white is handled in the calling routine by subtracting the
+% black result.
+%
+% The \gbc{setbbox} command was defined earlier, in
+% section~\ref{utilities}. The bounding rectangle it obtains is only
+% approximate in \MF{}, but that is sufficient, since we only use it to
+% produce things that are eventually clipped.
+%
+% We return \gbc{picpath} for non-cycles because I once thought to make
+% \gbc{shaded} a replacement for \gbc{setdot} to get gray dots (in the
+% \gbc{polkadot} routine). That turns out not to work, but this sort of
+% thing is also done in most of the rendering commands that require a
+% closed path.
+% \begin{macrocode}
+vardef shaded (expr clr) expr c =
+ if cycle c:
+%<*MP>
+ newpicture (v);
+ addto v contour c _wc_ clr;
+ v
+%</MP>
+%<*MF>
+ if (clr <= black) or (clr >= white):
+ interior c
+ else:
+ save shdims, shpic;
+ picture shpic; pair shdims;
+ shpic := shadepic (shdims) (clr);
+ setbbox (ll, ur) c;
+ newpicture (vsh);
+ fillwith (vsh) (shpic, shdims, ll, ur);
+ clipto (vsh) c; vsh
+ fi
+%</MF>
+ else: picpath c % should we? or just make it null?
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{fillwith}
+% This is one of the ways we obtain something other than a solid fill. The
+% routines \gbc{polkadot}, \gbc{tess} and (in \MF) \gbc{shade} and
+% \gbc{shaded} all use it.
+%
+% It takes a picture expression \gbc{pic}, along with its dimensions (the
+% pair \gbc{dims}) in device coordinates, plus the opposite corners,
+% \gbc{ll} and \gbc{ur}, of a boundingbox rectangle, and draws that
+% rectangle filled with copies of \gbc{pic}. Starting with \mfpic{}
+% version 0.8, it adds to a predefined picture passed by name. Thus the
+% calling routine must make sure that picture is initialized (it need
+% not be \mfc{nullpicture}).
+%
+% One might do this with one loop nested in another, but it turns out to
+% be much faster (surprisingly much!) to do two separate loops: the second
+% one stacking copies of the row built by the first loop.
+%
+% We try to do any rounding that might have been forgotten. This code
+% takes a mode's aspect ratio into account so that (most) calling routines
+% don't have to. (That is, \gbc{dims} should be measured in horizontal
+% pixels, while \gbc{fwdims} is in actual pixels. This could have been
+% written in terms of \gbc{picdot}, which already handles aspect, but it
+% has got to be more efficient to do the aspect ratio calculations once
+% rather than every time through the loop.)
+% \begin{macrocode}
+vardef fillwith (suffix v) (expr pic, dims, ll, ur) =
+ newpicture (b);
+%<*MF>
+ save fwdims, _ll, _ur; pair fwdims, _ll, _ur;
+ fwdims := goodpair (dims);
+ _ll := floorpair (ll.t_);
+ _ur := ur.t_;
+ for s = xpart _ll step xpart fwdims until xpart _ur:
+ addto b also pic shifted (s, 0);
+ endfor
+ for s = ypart _ll step ypart fwdims until ypart _ur:
+ addto v also b shifted (0, s);
+ endfor
+ mono (v);
+%</MF>
+%<*MP>
+ for s = xpart ll step xpart dims until xpart ur:
+ addto b also pic shifted (s, 0);
+ endfor
+ for s = ypart ll step ypart dims until ypart ur:
+ addto v also b shifted (0, s);
+ endfor
+%</MP>
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Hatching}\label{basichatching}
+%
+% \DescribeRoutine{thatchf}
+% This is the all-purpose macro called by the other macros that
+% fill a region with hatching. It takes the name of a picture \gbc{v},
+% a transform expression \gbc{CT}, a numeric expresion \gbc{sp} giving the
+% space between hatch lines, and two pairs, \gbc{a} and \gbc{b},
+% that represent the lower left and upper right limits of a rectangle.
+% The expression \gbc{sp} must be nonzero. The calling macros should take
+% care of that.
+%
+% It modifies the picture by adding to it the rectangle full of
+% hatching lines spaced \gbc{sp} apart. The rectangle is initially upright
+% and the lines horizontal, but they are drawn transformed by the
+% transform \gbc{CT}. This is how diagonal hatching is accomplished: the
+% transform is a rotation.
+%
+% We guard against \gbc{ypart a} being greater than \gbc{ypart b} or
+% \gbc{sp} being negative: \gbc{_sp} is \gbc{sp} modified to have the same
+% sign as \gbc{ypart (b - a)}. Thus, repeatedly adding it to \gbc{ypart a}
+% gets one to \gbc{ypart b}. We make the starting value an integer
+% multiple of \gbc{_sp} to make sure adjacent regions don't have jarringly
+% misaligned hatch lines. (I guess that's the reason; this algorithm
+% predates my involvement with \mfpic{}.)
+% \begin{macrocode}
+def thatchf (suffix v) (expr CT, sp, a, b) =
+ begingroup
+ setnumeric (_sp) signof (ypart b - ypart a) abs(sp);
+ for _y = _sp*( ceiling ((ypart a)/_sp) ) step _sp until ypart b:
+ shpath (v, hatchpen)
+ ( ( (xpart a, _y)--(xpart b, _y) ) transformed CT );
+ endfor
+%<MF> mono (v);
+ endgroup
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Gradient fills}\label{basicgradient}
+%
+% \CMP{} cannot do true gradients without some external help. Level-3
+% PostScript permits it, so recent \MP{} could do it by inserting
+% appropriate PS prologues and/or \MP{} specials. Doing that runs the
+% risk of introducing code not recognized by post-processors that expect
+% only what \MP\ natively offers. Therefore, we implement gradients by
+% filling a lot of thin regions with a range of different
+% colors.
+%
+% We have to drop down to pretty low-level operations since, before now,
+% we didn't need a command that added a colored region to a named
+% picture.
+%
+% For maximum flexibility, all our gradients pass variation in colors as a
+% function \mfc{clr} which must be previously \gbc{vardef}-ed and must
+% produce a color for each parameter value between $0$ and $1$.
+%
+% \DescribeRoutine{axialgradientf}
+% A linear gradient has colored rectangular strips that vary along a
+% single axis. The function parameter of \gbc{axialgradientf} takes one
+% variable and produces the color of each strip. \gbc{v} is a known
+% picture variable to which the resulting picture will be assigned,
+% \gbc{theta} is an angle, \gbc{a} and \gbc{b} are the opposite corners of
+% a rectangle. What is returned in \gbc{v} is a rectangular picture
+% rotated by \gbc{theta}.
+%
+% Normally, this is called by the \gbc{axialgradient} command which
+% declares the picture variable \gbc{v}, passes its angle parameter
+% \gbc{theta}, and computes the bounding box of a cyclic path for \gbc{a}
+% and \gbc{b}. The calling command will clip the result to the appropriate
+% path.
+%
+% The calculations with \gbc{signof} is for the same reason as in
+% \gbc{thatchf}. The other messy calculations try to cover the rectangle
+% exactly with an integer number of strips, with the first and last having
+% exactly the colors \gbc{clr(0)} and \gbc{clr(1)}.
+%
+% If the thickness of the strip is too small, memory problems might
+% result and appearence might suffer. Nevertheless we make no attempt to
+% enforce a minimum value.
+% \begin{macrocode}
+def axialgradientf (suffix clr, v) (expr theta, sp, a, b) =
+ begingroup
+ save _hh, _sp, _nn, _y;
+ _hh := ypart b - ypart a;
+ _sp := signof (_hh) abs(sp);
+ _nn := emax (1, round (_hh/_sp));
+ _sp := _hh/_nn + signof (_hh) epsilon;
+ _nn := _nn-1;
+ setpath (_p) rect ((xpart a, 0),(xpart b, _sp));
+ _y := ypart a;
+ for _i = 0 upto _nn:
+%<*MF>
+ if (clr(_i/_nn)) < white :
+ addto v also shaded (clr(_i/_nn)) ( _p shifted (0,_y))
+ rotated theta;
+ fi
+%</MF>
+%<*MP>
+ addto v contour (_p shifted (0,_y)) rotated theta
+ withcolor clr(_i/_nn);
+%</MP>
+ _y := _y + _sp;
+ endfor
+%<MF> mono (v);
+ endgroup
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{areagradientf}
+% The command \gbc{areagradientf} fills the rectangle determined by
+% corners \gbc{a} and \gbc{b} with pixels of dimension \gbc{sp} by
+% \gbc{tp}. Each pixel is filled with the color determined by \gbc{clr}.
+% This suffix parameter must be the name of a function taking two
+% parameters.
+%
+% The resulting rectangle is built on the picture variable whose name is
+% passed as the second parameter \gbc{v}. The calling routine is
+% \gbc{areagradient}, which determine the rectangle and initializes
+% the picture variable. It passes its other parameters unchanged.
+% \begin{macrocode}
+def areagradientf (suffix clr, v) (expr sp, tp, a, b) =
+begingroup
+ save _ww, _hh, _sp, _tp, _nn, _mm, _x, _y;
+ _ww := xpart b - xpart a;
+ _hh := ypart b - ypart a;
+ _sp := signof (_ww) abs(sp);
+ _tp := signof (_hh) abs(tp);
+ _nn := emax (1, round (_ww/_sp));
+ _mm := emax (1, round (_hh/_tp));
+ _sp := _ww/_nn + signof (_ww) epsilon;
+ _tp := _hh/_mm + signof (_hh) epsilon;
+ _mm := _mm-1; _nn := _nn-1;
+ setpath (_p) rect (origin,(_sp,_tp));
+ _x := xpart a; y_a := ypart a;
+ for _i = 0 upto _nn:
+ _y := y_a;
+ for _j = 0 upto _mm:
+%<*MF>
+ if (clr(_i/_nn,_j/_mm)) < white:
+ addto v also shaded (clr(_i/_nn,_j/_mm)) (_p shifted (_x,_y));
+ fi
+%</MF>
+%<*MP>
+ addto v contour (_p shifted (_x,_y)) withcolor
+ clr(_i/_nn,_j/_mm);
+%</MP>
+ _y := _y + _tp;
+ endfor
+ _x := _x + _sp;
+ endfor
+%<MF> mono (v);
+endgroup
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{radialgradientf}
+% The command \gbc{radialgradientf} fills the a circle determined by
+% center \gbc{ctr} and radius \gbc{rad} with concentric circular strips of
+% thickness \gbc{sp}. Each strip is filled with the color determined by
+% \gbc{clr}. This suffix parameter must be the name of a function of one
+% parameter.
+%
+% This command is called by \gbc{radialgradient}, which determines the
+% radius of a circle needed to cover a region and clips the picture
+% returned in \gbc{v} to that region.
+% \begin{macrocode}
+path unitcircle;
+unitcircle := fullcircle scaled 2;
+def radialgradientf (suffix clr, v) (expr sp, ctr, rad) =
+ begingroup
+ save _sp, _r, _nn;
+ _nn := emax (1, round (rad/sp));
+ _sp := rad/_nn + epsilon;
+ _nn := _nn - 1;
+ _r := _sp;
+ % fill the small center circle first
+%<*MF>
+ if (clr(0)) < white :
+ addto v also shaded (clr(0)) (unitcircle scaled _r shifted ctr);
+ fi
+%</MF>
+%<*MP>
+ addto v contour (unitcircle scaled _r shifted ctr)
+ withcolor clr(0);
+%</MP>
+ for _i = 1 upto _nn:
+%<*MF>
+ if (clr(_i/_nn)) < white :
+ addto v also shaded (clr(_i/_nn))
+ (unitcircle scaled (_r + _sp) -- reverse unitcircle scaled _r
+ --cycle) shifted ctr;
+ fi
+%</MF>
+%<*MP>
+ addto v contour
+ (unitcircle scaled (_r + _sp) -- reverse unitcircle scaled _r
+ --cycle) shifted ctr withcolor clr(_i/_nn);
+%</MP>
+ _r := _r + _sp;
+ endfor
+%<MF> mono (v);
+ endgroup
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Tiles}\label{tiles}
+%
+% Tesselations are a type of fill in which a rectangular pattern is
+% repeated throughout a region. The repeated rectangle is called a tile.
+% We provide here an environment in which the drawing commands add to a
+% picture variable other than \mfc{currentpicture}. We do this very simply
+% by redefining \gbc{active_plane}, localizing the redefinition between
+% \gbc{tile} and \gbc{endtile}
+%
+% \DescribeRoutine{tile}
+% The macro \gbc{tile} accepts one suffix parameter, the name of the tile,
+% followed by three numeric expressions and a boolean. \gbc{unit} should
+% be a dimension in device units and is the unit of length for all high
+% level drawing commands within the environment. \gbc{width} and
+% \gbc{height} specify the size of the tile in multiples of \gbc{unit}, and
+% \gbc{clipit} is a boolean that determines if the resulting picture is
+% clipped to the rectangle these parameters determine. For example,\\
+% \indent \gbc{tile (fred)(1in, 1, 2, true)} \\
+% starts a tile named \gbc{fred} which will be 1 inch wide and 2 inches
+% tall, and any marks that extend beyond this rectangle are clipped off.
+% The tile is enclosed in a group to delimit these changes to the basic
+% drawing parameters.
+% \DescribeRoutine{endtile}
+% The macro \gbc{endtile} merely implements the clipping and then closes
+% the group.
+%
+% In \MF, the picture should be a whole number of pixels in size, so that
+% the tiles fit perfectly together. The fact that shifts must be integer
+% values is only mildly relevant, because the placement code does the
+% rounding.
+%
+% For tesselation (filling with tiles) we need to know various properties
+% of the tile, so a tile is a composite object consisting of a picture,
+% \gbc{fred.pic} in our example (the actual tile) and a pair
+% \gbc{fred.dims} of the dimensions (in device units). We used to
+% save the \gbc{clipit} parameter in \gbc{atile.clipon}, but it was never
+% used. We also used to have separate numerics \gbc{atile.wd} and
+% \gbc{atile.ht} but they only got used together as a pair.
+% \begin{macrocode}
+def tile (suffix atile) (expr unit, width, height, clipit) =
+ picture atile.pic; atile.pic := nullpicture;
+ pair atile.dims;
+%<MF> atile.dims := round ((width, height)*unit);
+%<MP> atile.dims := (width, height)*unit;
+ begingroup
+% \end{macrocode}
+% We do a subset of what we do in \gbc{beginmfpic}, redefining
+% \gbc{active_plane} so that all drawing commands that add to it will
+% contribute to the tile, and adapting \gbc{ztr} to the tile dimensions.
+% Re also redefine \gbc{xneg}, et al., for the benefit of \gbc{levelset}.
+% \begin{macrocode}
+ save active_plane;
+ def active_plane = atile.pic enddef;
+ save ztr, vtr; transform ztr, vtr;
+ ztr := identity scaled unit; vtr := ztr;
+ save xneg, xpos, yneg, ypos;
+ xneg := 0; xpos := width; yneg := 0; ypos := height;
+% \end{macrocode}
+% To implement \gbc{clipit}, we set the current clipping path array
+% \gbc{ClipPath[\,]} to the boundary of the tile. Note that this turns off
+% user-defined clipping paths, which are unlikely to be correct for the
+% local tile coordinates.
+% \begin{macrocode}
+ save ClipOn; boolean ClipOn;
+ if clipit:
+ ClipOn := true;
+ setarray (path) (ClipPath) (rect(origin, atile.dims));
+ else:
+ ClipOn := false;
+ fi
+enddef;
+def endtile =
+ DoClip (active_plane);
+ endgroup
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{is_tile}
+% To test whether \gbc{atile} is really a tile, just see if the needed
+% components are defined and of the correct type.
+% \begin{macrocode}
+vardef is_tile (suffix atile) =
+ (known atile.pic ) and (picture atile.pic) and
+ (known atile.dims) and (pair atile.dims )
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Bounding Boxes of Paths}\label{bboxes}
+%
+% To fill a region with other than a solid fill, we normally fill a
+% rectangle with copies of a picture (or a path) and then clip to the
+% boundary curve. In order not to place too many copies, we try to find a
+% rectangle that is not too much larger than that region. For this we have
+% the macro \gbc{getbbox} which takes two pair variable and a path
+% expression, and sets the pairs to the lower left corner and upper right
+% corner, respectively, of a rectangle enclosing the path. The bounding
+% box macros are used on paths in device coordinates, but there is no
+% intrinsic reason that has to be so: they will return the bounding box in
+% whatever coordinates the supplied path is in.
+%
+% \DescribeRoutine{getbbox}
+% One can get a rather loose bounding rectangle by using the fact that
+% each segment of a path (from \mfc{point j of g} to \mfc{point j+1 of g})
+% is contained in the convex set determined by all 4 control points for
+% that segment. So we get a containing rectangle by getting the smallest
+% and largest values of the $x$- and $y$-coordinates of all those points.
+% We can get a considerably tighter fit if we cut each segment in half
+% (or more) before doing that. A calling routine is expected to save and
+% declare the suffixes \gbc{ll} and \gbc{ur}. Within \grafbase{} commands,
+% \gbc{getbbox} is always called by \gbc{setbbox}, which does this.
+%
+% \DescribeRoutine{ctrlsbbox}
+% There is a difference between ``\mfc{postcontrol 0 of (subpath (j,j+1/2)
+% of p)}'' and ``\mfc{postcontrol j of p}''. To gain the tighter box we have
+% to look at the former. \gbc{ctrlsbbox} just updates the previously found
+% corners \gbc{ll} and \gbc{ur} of the bounding box based on the controls
+% of the path segment \gbc{p}, and the calling routine \gbc{getbbox} passes
+% it half a segment at a time. We don't examine the endpoints of
+% the half-segment: one has already been examined by \gbc{getbbox} and
+% the other (a subdivision point of an original segment) lies on the line
+% segment connecting two control points, and so can't increase the bbox.
+%
+% We've given this potentially unlimited accuracy by allowing the number
+% of subdivisions (\gbc{bbox_split}) to be arbitrary. We choose 2 for the
+% default. The \gbc{setsplit} command (subsection~\ref{utilities}) ensures
+% that \gbc{_s} is integral and positive, just in case \gbc{bbox_split}
+% somehow isn't.
+%
+% This description applies only to \MF, because \MP{} has built-in
+% facilities for determining the bounding box.
+%
+% I have changed \gbc{ctrlsbbox} to have the same syntax as \gbc{getbbox}.
+% I don't know why I defined it differently.
+%
+% \RoutineIndex{pnt}
+% \RoutineIndex{pre}
+% \RoutineIndex{post}
+% I got tired of typing long expressions like ``\gbc{(precontrol length
+% p of p)}'', and now use the following abbreviations.
+% \begin{macrocode}
+vardef pnt@# (expr p) = point @# of p enddef;
+vardef pre@# (expr p) = precontrol @# of p enddef;
+vardef post@# (expr p) = postcontrol @# of p enddef;
+
+numeric bbox_split; bbox_split := 4;
+def getbbox (suffix ll, ur) expr g =
+%<MP> ll := llcorner g; ur := urcorner g;
+%<*MF>
+ setsplit (_s) bbox_split;
+ ur := ll := pnt 0 (g);
+ for _j = 1 upto length g:
+ ll := pairmin (ll, pnt[_j] (g)); ur := pairmax (ur, pnt[_j] (g));
+ endfor
+ for _j = 1 upto _s*(length g):
+ ctrlsbbox (ll, ur) subpath ((_j-1)/_s, _j/_s) of g;
+ endfor
+%</MF>
+ if showbbox: noclip ( safedraw rect (ll, ur) ); fi
+enddef;
+
+%<*MF>
+def ctrlsbbox (suffix ll, ur) expr p =
+ ll := pairmin ( pairmin (ll, post0 (p)), pre 1 (p) );
+ ur := pairmax ( pairmax (ur, post0 (p)), pre 1 (p) );
+enddef;
+
+%</MF>
+% \end{macrocode}
+%
+% \DescribeRoutine{getradius}
+% This is very similar to \gbc{getbbox}, but gets a ``bounding circle''
+% instead of a box. It is used to get nearly the smallest circle with a
+% given center that contains a path. The path is shifted to place the
+% center at the origin and then this function is called. Similarly,
+% \DescribeRoutine{ctrlsradius}
+% \gbc{ctrlsradius} is used like \gbc{ctrlsbbox}.
+% \begin{macrocode}
+def getradius (suffix rad) expr g =
+ setsplit (_s) bbox_split;
+ rad := abs (pnt0 (g));
+ for _j = 1 upto length g:
+ rad := emax(rad, abs(pnt[_j] (g)));
+ endfor
+ for _j = 1 upto _s*(length g):
+ ctrlsradius (rad) subpath ((_j-1)/_s, _j/_s) of g;
+ endfor
+enddef;
+
+def ctrlsradius (suffix rad) expr p =
+ rad := emax( emax (rad, abs(post0 (p))), abs(pre1 (p) ))
+enddef;
+
+% \end{macrocode}
+%
+% We also have \gbc{tightbbox} and \gbc{tbbox} in \MF{} but these are no
+% longer used so we'll omit them from \grafbase, but keep them in the
+% documentation for now.
+%
+% \DescribeRoutine{tightbbox}
+% Calculate tight bounding box points \gbc{ll} and \gbc{ur} for path
+% \gbc{g}. The tight bounding box is accurate to the limits of the
+% \mfc{solve} macro, which is the numeric \mfc{tolerance}, which we set to
+% \mfc{.5} (accurate enough, assuming pixel units). This is only called by
+% \gbc{tbbox}, which is never used.
+%
+% \gbc{xlimit(x)} returns a value of true if the path \gbc{g} doesn't
+% cross the vertical line at \gbc{x}. \gbc{ylimit(y)} is the same for the
+% horizontal line at \gbc{y}.
+% \begin{macrocode}
+%<*unused>
+def tightbbox (expr g) (suffix ll, ur) =
+begingroup
+ interim tolerance := .5;
+ ll := ( (solve _xlimit (-infinity, xpart pnt 0 (g))),
+ (solve _ylimit (-infinity, ypart pnt 0 (g))) );
+ ur := ( (solve _xlimit ( infinity, xpart pnt 0 (g))),
+ (solve _ylimit ( infinity, ypart pnt 0 (g))) );
+endgroup
+ if showbbox:
+ noclip ( safedraw rect (ll, ur) );
+ fi
+enddef;
+
+vardef _xlimit (expr x) =
+ ((x, -infinity)--(x, infinity)) misses g
+enddef;
+
+vardef _ylimit (expr y) =
+ ((-infinity, y)--(infinity, y)) misses g
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{tbbox}
+% \gbc{tbbox} simply calls \gbc{tightbbox} on each of an array of paths
+% and takes the maximum of all the upper right corners and the minimum of
+% all the lower left. Same syntax as \gbc{tightbbox} except that, instead
+% of a path parameter, \gbc{g} must be the name of an array of paths.
+% This macro is never used elsewhere in \grafbase.
+% \begin{macrocode}
+vardef tbbox (suffix g) (suffix ll, ur) =
+ save _gll, _gur; pair _gll, _gur;
+ tightbbox (g1, ll, ur);
+ for _idx = 2 upto g:
+ tightbbox (g[_idx], _gll, _gur);
+ ll := pairmin (ll, _gll); ur := pairmax (ll, _gur);
+ endfor
+ if showbbox: noclip ( safedraw rect (ll, ur) ); fi
+enddef;
+
+%</unused>
+% \end{macrocode}
+%
+%
+%
+% \section{Device Coordinate Rendering Commands}\label{basicrendering}
+%
+% We use the word `rendering' to refer to commands that accept a path
+% expression as one parameter and use it to modify the \gbc{active_plane}.
+% All the commands in this section expect paths, pairs and dimensions in
+% device coordinates.
+%
+%
+% \subsection{Drawing}\label{basicdrawing}
+%
+% \DescribeRoutine{safedraw}
+% \gbc{safedraw} accepts a path expression, and adds the result to
+% \gbc{active_plane}. It is the first drawing command to draw
+% exclusively on \gbc{active_plane}. This is the first of many uses of
+% \gbc{coloraddon}. In \MP{} it is basically the primitives \mfc{addto}
+% and \mfc{withcolor} applied to \gbc{active_plane}, but in \MF{} it adds
+% when the color is less than 1 (gray or black), otherwise it subtracts
+% (white).
+%
+% \RoutineIndex{colorsafedraw}
+% The command \gbc{safedraw} merely calls \gbc{colorsafedraw}, which then
+% calls \gbc{picpath}, which calls \gbc{shpath}. One reason for this
+% roundabout sequence is to support older files (where \gbc{colorsafedraw}
+% was not defined). Another is that color handling in \MF{} requires a
+% picture with pixels of weight 1 or 0 only (\gbc{picpath}). Moreover,
+% \gbc{shpath} guarantees that the mode's aspect ratio is respected.
+% \begin{macrocode}
+def safedraw = colorsafedraw (drawcolor) enddef;
+def colorsafedraw (expr clr) expr d =
+ begingroup
+ setpicture (v) picpath d;
+ DoClip (v); coloraddon (clr, v);
+ endgroup
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Filling}\label{basicfilling}
+%
+% \DescribeRoutine{NoCycle}
+% This is a common warning for all those commands that require a cycle
+% (closed path) but an open path is supplied. In addition to the warning
+% in those commands, we also call \gbc{safedraw} for debugging purposes.
+%
+% \DescribeRoutine{safefill}
+% \RoutineIndex{colorsafefill}
+% The basic \gbc{safefill} simply calls the colored version with the
+% default parameter \gbc{fillcolor}. \gbc{colorsafefill} takes a color as
+% its first parameter and a path expression as second. These commands fill
+% the path in the \gbc{active_plane}. In \MF, when the color is strictly
+% between $0$ and 1, a gray fill is simulated with the \gbc{shaded} macro.
+%
+% To simulate the effect of painting over in gray, the \MF{} version
+% clears the region before adding the shaded fill.
+%
+% \DescribeRoutine{safeunfill}
+% \gbc{safeunfill} is just \gbc{safefill} with the color \mfc{background}.
+% In \MF{}, when \gbc{background = white = 1}, this is detected by
+% \gbc{coloraddon} which then subtracts the picture. We do this inside
+% \gbc{noclip}, just because it seems a user would expect clipping only
+% when things are \emph{added}. In \MP{} the white is indeed added, but
+% conceptually, material is cleared away.
+% \begin{macrocode}
+def NoCycle (expr s) expr p =
+ GBwarn s & " cannot be applied to an open path."
+ & " The path will be drawn instead.";
+ safedraw p;
+enddef;
+
+%<MF>vardef isgray (expr X) = (X > black) and (X < white) enddef;
+%<MF>
+def safefill = colorsafefill (fillcolor) enddef;
+vardef colorsafefill (expr clr) expr c =
+ if cycle c:
+ setpicture (v) interior c;
+ DoClip (v);
+%<*MF>
+ if isgray (clr):
+ _subto (active_plane) (v);
+ v := nullpicture;
+ v := shaded (clr) c;
+ fi
+%</MF>
+ coloraddon (clr, v);
+ else: NoCycle("fill") c;
+ fi
+enddef;
+def safeunfill expr c =
+ if cycle c: noclip (colorsafefill (background) c);
+ else: NoCycle("unfill") c;
+ fi
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Clipping}\label{clipping}
+%
+% \DescribeRoutine{safeclip}
+% This applies \gbc{clipto} to the active drawing plane. It follows the
+% pattern started with \gbc{safefill} where commands that require a cycle
+% will \gbc{safedraw} non-cyclic paths.
+% \begin{macrocode}
+def safeclip expr c =
+ if cycle c: clipto (active_plane) c;
+ else: NoCycle("clip") c;
+ fi
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Graph Coordinate Rendering}\label{rendering}
+%
+% \DescribeRoutine{store}
+% Now we come to the highest level rendering operations. These are the
+% commands written to the output file by \mfpic. They accept a path in
+% \emph{graph} coordinates, convert it to device coordinates, rendering
+% the result, and return the original path. This way one can render a
+% path and pass it on to the preceding command for further processing.
+% This is how \mfpic{} implements multiple prefix macros. However, this
+% cannot be kept up because \MF{} abhors an isolated expression. Therefore
+% we provide a command that accepts a path and doesn't pass it on. In
+% theory, it could do nothing, but in \mfpic{} we store the path in
+% \gbc{curpath}, making every \mfpic{} figure a path assigment command
+% and the rendering is `merely' a side-effect.
+%
+% \DescribeRoutine{stored}
+% The macro \gbc{stored} performs \gbc{store}, but passes the same path as
+% its return value. This is used by \mfpic{} to implement the \cs{store}
+% command, allowing it to also be a prefix macro
+%
+% I don't know if \gbc{store} needs to employ \mfc{hide()}, but it seems
+% not to hurt.
+% \begin{macrocode}
+def store (suffix fs) expr f =
+hide (
+ if (not path f) and (not pair f):
+ GBerrmsg ("Improper expression type.")
+ "The second argument to `store' must be a path or pair.";
+ fi
+ if not path fs: path fs; fi
+ fs := f
+)
+enddef;
+vardef stored (suffix fs) expr f = store (fs) f; f enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Drawing}\label{drawing}
+%
+% \DescribeRoutine{drawn}
+% \RoutineIndex{colordrawn}
+% The command \gbc{drawn} merely calls \gbc{colordrawn} with the default
+% color \gbc{drawcolor}. Then \gbc{colordrawn} takes a color \gbc{clr}
+% and a path expression \gbc{f} and returns the same path. In between,
+% \gbc{zconv (f)} is subjected to \gbc{colorsafedraw}.
+% \begin{macrocode}
+def drawn = colordrawn (drawcolor) enddef;
+vardef colordrawn (expr clr) expr f =
+ colorsafedraw (clr) (zconv (f)); f
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{colorwiggle}
+% This is a multi-tasking command that can draw either zigzag or
+% sinewave shapes depending on the boolean first parameter. For \mfc{true}
+% we get smooth wiggles, for \mfc{false} we get jagged ones. In the
+% smooth case, a tension parameter allows an adjustment to the smoothness.
+% The command
+% \DescribeRoutine{zigzag}
+% \RoutineIndex{colorzigzag}
+% \gbc{zigzag} calls it with the value \mfc{false} and an arbitrary
+% value of the tension;
+% \DescribeRoutine{sinewave}
+% \RoutineIndex{colorsinewave}
+% \gbc{sinewave} calls it with \mfc{true}, allowing it to pick up the
+% tension parameter. All expect a quadruple of dimensions to follow
+%
+% The reason for using a loop (at the end) that draws the \gbc{sinewave}
+% path in pieces, is that all the turning can quickly exceed \MF{}'s limit
+% on the ``rounding table size''. I'd never heard of this until I ran
+% this without a loop and received the ``capacity exceeded'' message. This
+% turns out to be a problem mostly when the ratio of \gbc{len} to
+% \gbc{wid} is too small and the `humps' of the sine are more like
+% `bulbs'. However it is always a problem with \gbc{corkscrew} (below).
+%
+% There is no need for the loop in \MP{}, nor in \MF{} if
+% \mfc{autorounding} is set to $0$, but \mfpic's curved paths definitely
+% look better with the default \mfc{autorounding=2}.
+% \begin{macrocode}
+def zigzag = colorzigzag (drawcolor) enddef;
+def colorzigzag (expr clr) = colorwiggle (false, clr, 0) enddef;
+def sinewave = colorsinewave (drawcolor) enddef;
+def colorsinewave = colorwiggle (true) enddef;
+
+vardef colorwiggle (expr smth, clr, tens, blen, elen, len, wid) expr f
+=
+ convertpath (g) f;
+ setuplengtharray (cumlen, totlen, ct) g;
+ save B;
+ if cycle f:
+ B := 0;
+ else:
+ B := abs(blen)/_rescale_factor;
+ totlen := totlen - B - abs(elen)/_rescale_factor;
+ fi
+ setnumeric (n) 2*round (totlen/len*_rescale_factor);
+ if n < 2:
+ colorsafedraw (clr) g;
+ else:
+ save T, U, X, Y, Z, p;
+ pair U, X, Y, Z; path p;
+ T := if cycle f: 0 else: gettime (cumlen, ct) (B) fi;
+ Z := pnt[T] (g);
+ p :=if not cycle f: (subpath (0,T) of g)
+ if smth: {curl 0} ..tension tens.. else: -- fi
+ fi
+ for i = 1 upto n:
+ hide(
+ T := gettime (cumlen, ct) (B+(i/n)*totlen);
+ X := Z; Z := pnt[T] (g);
+ Y := .5[X,Z]; U := sgn (Z-X);
+ )
+ (Y + (U zscaled (0, if even i: - fi wid)))
+ if smth: {U}..tension tens.. else: -- fi
+ endfor
+ if cycle f: cycle
+ else: if smth: {curl 0} fi (subpath (T, length g) of g)
+ fi;
+ newpicture (v);
+%<MP> shpath (v, drawpen) (p);
+%<*MF>
+ if smth:
+ save n, k;
+ n := length p; k = n div 50;
+ for i = 0 step 50 until 50*(k-1):
+ shpath (v, drawpen) (subpath (i,i+50) of p);
+ endfor
+ shpath (v, drawpen) (subpath (50k,n) of p);
+ else: shpath (v, drawpen) (p);
+ fi
+%</MF>
+ DoClip(v); coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{corkscrew}
+% \RoutineIndex{colorcorkscrew}
+% The definition of \gbc{corkscrew} shares a lot of code with \gbc{zigzag}
+% and \gbc{sinewave}, but the middle is considerably different, so it is
+% not really possible to make a multipurpose command that can do all
+% three.
+% \begin{macrocode}
+def corkscrew = colorcorkscrew (drawcolor) enddef;
+vardef colorcorkscrew (expr clr, tens, blen, elen, len, wid) expr f =
+ convertpath (g) f;
+ setuplengtharray (cumlen, totlen, ct) g;
+ save B;
+ if cycle f:
+ B := 0;
+ else:
+ B := abs(blen)/_rescale_factor;
+ totlen := totlen - B - abs(elen)/_rescale_factor;
+ fi
+ setnumeric (n) round (totlen/len*_rescale_factor);
+ if n < 2:
+ colorsafedraw (clr) g;
+ else:
+ save T, U, X, Y, Z, p;
+ pair U, X, Y, Z; path p;
+ T := if cycle f: 0 else: gettime (cumlen, ct) (B) fi;
+ Z := pnt[T] (g);
+ p :=if (not cycle f) and (B > 0): (subpath (0,T) of g)-- fi
+ for i = 1 upto n:
+ hide(
+ T := gettime (cumlen, ct) (B+(i/n)*totlen);
+ X := Z; Z := pnt[T] (g);
+ Y := .5[X,Z]; U := sgn (Z-X);
+ )
+ (X + (U zscaled (0,-wid))){ U}..tension tens..
+ (Y + (U zscaled (0, wid))){-U}..tension tens..
+ endfor
+ if cycle f: cycle
+ else:
+ {U}(Z + (U zscaled (0,-wid)))
+ if elen <> 0: --(subpath(T, length g) of g) fi
+ fi;
+ newpicture (v);
+%<MP> shpath (v, drawpen) (p);
+%<*MF>
+ save n, k;
+ n := length p; k = n div 50;
+ for i = 0 step 50 until 50*(k-1):
+ shpath (v, drawpen) (subpath (i,i+50) of p);
+ endfor
+ shpath (v, drawpen) (subpath (50k,n) of p);
+%</MF>
+ DoClip(v); coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Filling, unfilling and clipping}\label{filling}
+%
+% \DescribeRoutine{filled}
+% \RoutineIndex{colorfilled}
+% The command \gbc{filled} calls \gbc{colorfilled} with the default color
+% \gbc{fillcolor}. Then \gbc{colorfilled} takes a color \gbc{clr} and a
+% path expression \gbc{c}, returning the same path after subjecting
+% \gbc{zconv (c)} to \gbc{colorsafefill}.
+% \DescribeRoutine{unfilled}
+% The macro \gbc{unfilled} returns the path after running \gbc{safeunfill}.
+%
+% \DescribeRoutine{Clip}
+% Finally, \gbc{Clip} is similar, running \gbc{safeclip}. The name
+% \gbc{clip} (lowercase) is taken: it is a \MP{} primitive.
+% \begin{macrocode}
+def filled = colorfilled (fillcolor) enddef;
+vardef colorfilled (expr clr) expr c =
+ colorsafefill (clr) zconv (c); c
+enddef;
+vardef unfilled expr c = safeunfill zconv (c); c enddef;
+vardef Clip expr c = safeclip zconv (c); c enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Shading}\label{shading}
+%
+% \DescribeRoutine{shade}
+% Shading is accomplished differently in \MP{} from \MF; however, many of
+% the same parameters are used for compatibility (so that \MP{} can be run
+% on a \file{.mf} created for \grafbase{} by \mfpic). In \MP, shading is
+% just filling with some level of gray. In \MF, we place a pattern of
+% small dots with the size and spacing adjustable. For compatibility,
+% \MP{} accepts these size and spacing parameters, but simply uses them to
+% calculate the darkness of gray.
+%
+% Ideally (i.e., for best appearance) one would shade with single pixels
+% placed in a regular pattern. Unfortunately, this is the most memory
+% intensive for \MF, which stores bitmaps by scanning each row of pixels,
+% and records where changes from black to white occur. We do use simple
+% dots, but make them quite a bit larger than one pixel. By default,
+% \gbc{0.5bp} in diameter, spaced (in \mfpic) a default \gbc{1pt} between
+% centers.
+%
+% The shape and size of the dots can be selected by defining
+% \gbc{shadedotpath} and \gbc{shadewd}. A closed path representing the
+% boundary of one dot of unit size, \gbc{shadedotpath} is initialized to a
+% circle.
+%
+% The parameter \gbc{sp} is the distance between the centers of the dots in
+% device coordinates, and \gbc{f} is the path to be filled in \emph{graph
+% coordinates}.
+%
+% As usual, if the path is not closed, we draw the curve instead. If the
+% spacing is too small relative to \gbc{shadewd}, we fill the curve.
+% Otherwise the \gbc{fillwith} macro is used to fill with copies of
+% a dot picture.
+% \begin{macrocode}
+numeric shadewd; shadewd := 0.5bp;
+path shadedotpath;
+shadedotpath := fullcircle;
+
+vardef shade (expr sp) expr f =
+ convertpath (g) f;
+% \end{macrocode}
+% It seems clear that the gray level (\gbc{gr}) should depend
+% quadratically on \gbc{shadewd/sp}. Also, there is a point where the
+% result is essentially black and a fill would be more efficient.
+% The value .88 is arrived at empirically and is a compromise so that
+% \MF{} and \MP{} produce similar levels of gray on both printers
+% available to me.
+% \begin{macrocode}
+ setnumeric (gr) 1 - (.88*abs(shadewd)/sp)**2;
+ if not cycle g: NoCycle("shade") g;
+ elseif gr <= 0: safefill g;
+ else:
+%<*MF>
+ setbbox (ll, ur) g;
+ ll := floorpair (ll);
+% \end{macrocode}
+%
+% What we do is draw a row of dots and stack the rows to fill a rectangle.
+% We call \gbc{fillwith} to draw these copies. We have to produce this
+% on a picture separate from \gbc{active_plane} so we can apply
+% \gbc{DoClip}. Adding one complex picture onto another means there is a
+% time at which the added picture and the result are in memory at the same
+% time. To save a little memory (at the cost of a little speed), we
+% divide the picture into two, each with half the complexity. We add the
+% one, then (I hope) recover the memory by equating it to \mfc{nullpicture}
+% before adding the second.
+%
+% Shifts of pictures need to be by integer number of pixels, but this is
+% ensured by \gbc{fillwith}, using \mfc{ceiling} to define \gbc{dv} is
+% more to ensure it is not rounded down to 0.
+% \begin{macrocode}
+ % setpair (dv) ceiling (sp/(sqrt 2))*(1,1);
+ % test hex spacing:
+ setpair (dv) ( ceiling(.5sp), ceiling(.5sp*sqrt 3) );
+ setpicture (sh) setdot (shadedotpath, abs(shadewd));
+ newpicture (v);
+ fillwith (v) (sh, 2dv, ll, ur);
+ newpicture (w);
+ addto w also v shifted goodpair (dv);
+ DoClip (v); DoClip (w);
+ clipto (v) (g); clipto (w) (g);
+ _orto (active_plane, v);
+ v := nullpicture;
+ _orto (active_plane, w);
+%</MF>
+% \end{macrocode}
+% In \MP{} we just fill with gray. The gray level having been calculated
+% at the beginning.
+% \begin{macrocode}
+%<*MP>
+ colorsafefill (gr*white) g;
+%</MP>
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{polkadot}
+% The macro \gbc{polkadot} is intended to fill a region with \emph{large}
+% dots. The diameter, \gbc{polkadotwd}, is initialized to \mfc{5bp}. The
+% code is similar to that of \gbc{shade}, but here we attempt a hexagonal
+% array: each dot surrounded by 6 equally spaced dots. Because of their
+% larger size and presumably larger spacing, we can be a little less
+% efficient and so we aim for improved visual appearance. We do what we
+% can to avoid unsightly slivers of partial dots, and only draw a dot if
+% its center lies in the bounding box.
+%
+% We also permit the circles to overlap, and only replace the code with a
+% fill if the dots overlap so much that no background can show (this assumes
+% that \gbc{polkadotpath} is a circle).
+%
+% If the space \gbc{sp} and \gbc{polkadotwd} are too small, there will
+% be a great many tiny dots. It is quite easy to overflow \MP{} capacity
+% and tiny paths don't rasterize at all well in \PS. In \MF, we already
+% have \gbc{shade} to place tiny dots. Therefore, we merely fill if
+% \gbc{sp} is less that a certain minimum, even if that minimum is greater
+% than \gbc{polkadotwd}.
+% \begin{macrocode}
+polkadotwd := 5bp;
+mindotspace := 1bp;
+path polkadotpath; polkadotpath := fullcircle;
+
+vardef polkadot (expr sp) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("polkadot") g;
+ elseif sp <= emax (2*polkadotwd/3, mindotspace):
+ safefill g;
+ else:
+ setbbox (ll, ur) g;
+% \end{macrocode}
+% As with \gbc{shade}, we shift alternate rows by half the spacing between
+% dot centers. The vertical shift is slightly larger (relatively speaking)
+% and the horizontal smaller. We apply a further horizontal and vertical
+% shift to avoid small pieces of dots. What it does is take only those dots
+% whose centers lie in the bounding box, and center the whole array
+% relative to that box.
+% \begin{macrocode}
+ save dx, dy, dshift; pair dshift;
+ dx := sp/2; dy := dx*sqrt 3;
+ dshift := (xpart(ur - ll) mod dx, ypart (ur - ll) mod dy)/2;
+% \end{macrocode}
+% Here, \gbc{p} is the center of the first dot in the lower left corner.
+% \begin{macrocode}
+ save p, dims; pair p, dims;
+ p := ll + dshift;
+ dims := 2(dx, dy);
+% \end{macrocode}
+% The extra \MF{} code is to clear what's under the dots in case they
+% are gray dots. And then to `gray' the dots when \gbc{fillcolor} demands
+% it.
+% \begin{macrocode}
+ setpicture (thepolkadot) setdot (polkadotpath, polkadotwd);
+ newpicture (v);
+ fillwith (v) (thepolkadot, dims, p, ur);
+ fillwith (v) (thepolkadot, dims, p + (dx, dy), ur);
+ DoClip (v); clipto (v) g;
+%<*MF>
+ if isgray (fillcolor):
+ _subto (active_plane) (v);
+ v := nullpicture;
+ thepolkadot :=
+ shaded (fillcolor) polkadotpath scaled ceiling (polkadotwd);
+ fillwith (v) (thepolkadot, dims, p, ur);
+ fillwith (v) (thepolkadot, dims, p + (dx, dy), ur);
+ DoClip (v); clipto (v) g;
+ fi
+%</MF>
+ coloraddon (fillcolor, v);
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Hatching}\label{hatching}
+%
+% \DescribeRoutine{thatch}
+% \RoutineIndex{colorthatch}
+% This command hatches the interior of path \gbc{f} (graph coordinates)
+% with lines at angle \gbc{theta}, spaced \gbc{sp} apart (device
+% coordinates). As usual an unclosed path is simply drawn. The thickness
+% of the lines is determined by \gbc{hatchwd}. If \gbc{sp} is not greater
+% than \gbc{abs(hatchwd)}, we simply fill. This will ensure \gbc{thatchf}
+% is called only for positive \gbc{sp}.
+%
+% We find the bounding box of the backward rotated path, so when that box
+% is filled with lines and rotated, it will cover the path. After calling
+% \gbc{thatchf} we add the picture, clipped to the path.
+% \begin{macrocode}
+def thatch = colorthatch (hatchcolor) enddef;
+vardef colorthatch (expr clr) (expr sp, theta) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("hatch") g;
+ elseif sp <= abs(hatchwd): colorsafefill (clr) g;
+ else:
+ newpicture (v);
+ setbbox (ll, ur) g rotated -theta;
+ thatchf (v, identity rotated theta, sp, ll, ur);
+ DoClip (v); clipto (v) (g);
+ coloraddon (clr, v);
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+% We offer some special cases, calling \gbc{thatch} with different angles.
+% These take only the spacing (in device coordinates) and a path
+% expression (in graph coordinates) as parameters.\\
+% \DescribeRoutine{hhatch}
+% \gbc{hhatch} has angle 0 and so produces horizontal lines;\\
+% \DescribeRoutine{vhatch}
+% \gbc{vhatch} produces vertical lines;\\
+% \DescribeRoutine{lhatch}
+% \gbc{lhatch} produces lines tilted to the left (running from upper left
+% to lower right);\\
+% \DescribeRoutine{rhatch}
+% \gbc{rhatch} produces lines running from lower left to upper right;
+% and\\
+% \DescribeRoutine{xhatch}
+% \gbc{xhatch} produces cross-hatching, and essentially runs \gbc{lhatch}
+% and \gbc{rhatch}.
+%
+% Color is a parameter only for \gbc{colorxhatch}. The reason for that
+% is to make code written by \mfpic{} simpler. The \mfpic{} commands for
+% the others actual write calls to \gbc{thatch} or \gbc{colorthatch}.
+%
+% \begin{macrocode}
+def hhatch (expr sp) = thatch (sp, 0) enddef;
+def vhatch (expr sp) = thatch (sp, 90) enddef;
+def lhatch (expr sp) = thatch (sp, -45) enddef;
+def rhatch (expr sp) = thatch (sp, 45) enddef;
+
+def xhatch = colorxhatch (hatchcolor) enddef;
+def colorxhatch (expr clr, sp) =
+ colorthatch (clr) (sp, 45) colorthatch (clr) (sp, -45)
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Gradients}
+%
+% \DescribeRoutine{axialgradient}
+% We pass a \mfc{vardef}-ed function that is to provide the range of
+% colors. It can output colors of different types if desired. Two
+% natural methods are: (1)~interpolate between colors of the same type:\\
+% \indent\mfc{vardef clrgrad (expr t) = (t)[red,blue] enddef}\\
+% and (2)~extract colors from a previously built array of colors:\\
+% \indent\mfc{vardef clrgrad (expr t)= A[round(t*N)]}\\
+% where, \mfc{A0}, \mfc{A1},\dots \mfc{A[N]} are colors (necessarily of
+% the same type).
+%
+% Since we simply fill strips with a single color, \gbc{sp} is the
+% thickness of the strip (in device units) and \gbc{theta} is the angle
+% by which these strips differ from being horizontal.
+% \begin{macrocode}
+vardef axialgradient (suffix clr) (expr sp, theta) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("axialgradient") g;
+ else:
+ newpicture (_grd);
+ setbbox (ll, ur) g rotated -theta;
+ axialgradientf (clr, _grd) (theta, sp, ll, ur);
+ DoClip (_grd); clipto (_grd) (g);
+%<MF> safeunfill g;
+ _orto (active_plane, _grd);
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{areagradient}
+% This fills a cyclic path with colored pixels, with the color
+% determined by the \mfc{vardef}-ed function \gbc{clr} which takes two
+% parameters. The size of the pixels is given in the last two parameters
+% \gbc{sp} and \gbc{tp} which are specified in device units.
+% \begin{macrocode}
+vardef areagradient (suffix clr) (expr sp, tp) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("areagradient") g;
+ else:
+ newpicture (_agr);
+ setbbox (ll, ur) g;
+ areagradientf (clr, _agr) (sp, tp, ll, ur);
+ DoClip (_agr); clipto (_agr) (g);
+%<MF> safeunfill g;
+ _orto (active_plane, _agr);
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{radialgradient}\label{getrad}
+% This fills a cyclic path with colored circular strips, with the color
+% determined by the \mfc{vardef}-ed function \gbc{clr} which takes one
+% parameters. The thickness of the strips is given in the last parameter
+% \gbc{sp} which are specified in device units. The command
+% \gbc{getradius} finds the distance from the center to the farthest point
+% of \gbc{f}. It was added (see section~\ref{bboxes}) solely for this use.
+% \begin{macrocode}
+vardef radialgradient (suffix clr) (expr sp, ctr) expr f =
+ convertpath (g) f;
+ if not cycle g: NoCycle("radialgradient") g;
+ else:
+ setpair (_ctr) zconv (ctr);
+ newpicture (_agr);
+ save _rad;
+ getradius (_rad) g shifted - _ctr;
+ radialgradientf (clr, _agr) (sp, _ctr, _rad);
+ DoClip (_agr); clipto (_agr) (g);
+%<MF> safeunfill g;
+ _orto (active_plane, _agr);
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Tesselations}\label{tess}
+%
+% \DescribeRoutine{tess}
+% Tesselation of the interior of a closed path means filling with copies
+% of a \emph{tile} (see subsection~\ref{tiles}). The path is in graph
+% units, the tile is a suffix parameter and is the name of a previously
+% defined tile. In fact, one can create the picture any way one likes (it
+% doesn't have to be with the \gbc{tile} environment). Thus \gbc{tess
+% (fred) f;} will work as long as \gbc{fred.pic} is a picture and
+% \gbc{fred.dims} is a pair giving its dimensions.
+% \begin{macrocode}
+vardef NoTile (suffix atile) expr g =
+ GBwarn str atile & " is not a valid tile for tess()."
+ & " The path will be drawn instead.";
+ safedraw g;
+enddef;
+vardef tess (suffix atile) expr c =
+ convertpath (_g) c;
+ if not cycle _g: NoCycle("tess") _g;
+ elseif not is_tile (atile): NoTile (atile) _g;
+ else:
+ setbbox (_ll, _ur) _g;
+ newpicture (_ts);
+ fillwith (_ts) (atile.pic, atile.dims, _ll, _ur);
+ DoClip (_ts); clipto (_ts) _g;
+ _orto (active_plane, _ts);
+ fi
+ c
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Dots and dashes}\label{dashes}
+%
+% \MP{} already has commands for drawing a dashed or dotted curve,
+% but \MF{} does not. Considerable effort went into making this possible
+% (before \MP{} even existed). The code is now reasonably fast and the
+% result is actually better quality than \MP{}'s native commands so we use
+% the same code in both versions. It does, however, use pretty much
+% memory in \MP{}.
+%
+% The \grafbase{} dashing code is designed to produce a whole number of
+% dashes on any curve to which it is applied, and (usually) to begin and
+% end with half a dash (so that when dashed curves abut, the result looks
+% decent). \MP{}'s own facilities do neither of these. In addition, the
+% dotting code is flexible enough that copies of any picture (not just a
+% circular dot) can be used to trace a path.
+%
+% The general command is \gbc{gendashed}, which takes a suffix parameter
+% (the name of a \emph{dashing pattern}, see below) and a path expression
+% in graph coordinates.
+%
+% A dashing pattern \gbc{pat} consists of three arrays, \gbc{pat.start},
+% which is used to draw the beginning of the path (half a dash in the
+% default \gbc{dashed} command), \gbc{pat.finish}, which is used to draw
+% the other end, and \gbc{pat.rep}, which is the repeating pattern for
+% drawing the rest of the curve. Each of these is an \emph{array} of
+% numerics. These should be lengths, in device units, and represent the
+% lengths of dashes and spaces.
+%
+% We start with some variables and their defaults, some of which are no
+% longer used. \gbc{segment_split} is used in the code for finding the
+% approximate length of a curve. This is needed to make adjustments in the
+% length of dashes and spaces so that a whole number of repeated patterns
+% are used. \gbc{dashsize} and \gbc{dashgap} are no longer used.
+% Originally they gave the lengths of default dashes and the spaces in
+% between. \gbc{dash_start} and \gbc{dash_finish} are the fractions of a
+% dash length that are used at the start and finish if the command
+% \gbc{dashpat} is used to create the dashing pattern.
+%
+% And \gbc{_rescale_factor} is used to adjust numbers downward and avoid
+% arithmetic overflow. For a 1200dpi \MF{} mode, a curve 4 inches long
+% will be over \mfc{infinity} pixels in length, but only 40 deci-inches.
+% Our default for this variable is just that: 1/10 inch.
+% \begin{macrocode}
+if unknown segment_split: segment_split := 8; fi
+if unknown dashsize: dashsize := 3bp; fi
+if unknown dashgap: dashgap := dashsize + 2penwd; fi
+if unknown dash_finish: dash_finish := .5; fi
+if unknown dash_start: dash_start := .5; fi
+if unknown _rescale_factor: _rescale_factor := 0.1in; fi
+
+% \end{macrocode}
+%
+% \DescribeRoutine{gendashed}
+% The main idea is to have a list of lengths represent the repeating
+% pattern of dashes and dots. These lengths represent a dash length,
+% followed by a gap length, etc., so there are an even number. To start
+% dashing a path, we normally take a fraction (\gbc{dash_start}) of the
+% first dash, then the rest of the pattern. We continue by repeating the
+% pattern as many times as will fit, then we finish off with a fraction
+% (\gbc{dash_finish}) of the first dash. A dash of length 0 is a dot. A
+% gap of length 0 is OK, but useless unless it's between a dot and a dash,
+% and you arrange for the dot's size to be different from \gbc{penwd}.
+%
+% We generalize this so that \gbc{pat.start} and \gbc{pat.finish} can be
+% any patterns, not necessarily related to \gbc{pat.rep}. Also `dots' can be
+% symbols like \gbc{Triangle}.
+%
+% When we tried to deal with arrays of dashing patterns, it became
+% rather a pain to deal with three arrays of arrays. So now we allow the
+% suffix \gbc{pat} to be a single array and call \gbc{mkdasharrays} to
+% produce \gbc{pat.start} and \gbc{pat.finish}. It returns \gbc{true} if
+% all three arrays are successfully produced.
+%
+% The variable \VariableIndex{last_dot_size} \gbc{last_dot_size} is
+% intended to allow the clearing path of arrowhead commands to encompass
+% a final dot larger than \gbc{penwd}.
+% \begin{macrocode}
+numeric last_dot_size; last_dot_size := 0;
+vardef gendashed (suffix pat) expr f =
+ convertpath (_g) f;
+ save _dpat;
+ if not mkdasharrays (pat) (_dpat):
+ GBwarn "Dash pattern " & str pat
+ & " undefined. Path will be drawn instead.";
+ safedraw _g;
+ elseif _dpat.rep < 2:
+ safedraw _g;
+ else:
+% \end{macrocode}
+%
+% After the following loop, \gbc{_dl.s} is the total length of the
+% corresponding \gbc{pat.s} in multiples of \gbc{_rescale_factor}, and
+% \gbc{_dpat.s[i]} has been converted to these units.
+% \begin{macrocode}
+ save _dl;
+ forsuffixes _s = start, rep, finish:
+ _dl._s := 0;
+ for i = 1 upto _dpat._s:
+ _dpat._s[i] := _dpat._s[i]/_rescale_factor;
+ _dl._s := _dl._s + _dpat._s[i];
+ endfor
+ endfor
+
+ if _dl.rep = 0:
+ GBwarn "Dash pattern " & str pat & " has length 0. "
+ & "Path will be drawn instead.";
+ safedraw _g;
+ else:
+% \end{macrocode}
+% Here \gbc{_g} is our path in device units, but \gbc{setuplengtharray}
+% computes lengths in multiples of \gbc{_rescale_factor} to avoid having
+% paths of length \gbc{infinity}.
+%
+% This is how we process a path mathematically: let $f(t)$, $0 \le t \le
+% k$ be the formula for the path \gbc{f}, $k$ being the number of segments
+% of \gbc{f}, we consider the polygon connecting the points $f(0), f(1/s),
+% f(2/s),\ldots,f(k)$ (where $s$ is \gbc{segment_split}) and compute the
+% length of \emph{that} path. Actually, we compute and save the cumulative
+% lengths at each vertex of this polygon, since we use that later to
+% determine `when' (i.e., at what values of $t$) to place a dot or draw
+% a dash. The command \gbc{setuplengtharray} does this, storing the
+% cumulative lengths in the array \gbc{_cumlen} and the total in
+% \gbc{_totlen}. It also initializes \gbc{_ct} the index into that array.
+% \begin{macrocode}
+ setuplengtharray (_cumlen, _totlen, _ct) _g;
+% \end{macrocode}
+% Now we adjust the dashes so that a whole number of patterns make up
+% the lengths of the approximating polygon. \gbc{scale_adjust} returns
+% the scaling factor, equates \gbc{_n} to the total number of
+% \gbc{pat.rep} to use. If the path length is too small compared to the
+% length of the start and finish patterns, this is equated to $-1$ as a
+% flag to draw the path instead. (recall \gbc{_dl.s} holds the length of
+% part \gbc{s}).
+%
+% After this we rescale the dashes and spaces stored in \gbc{_dpat}, and
+% the length of the patterns in \gbc{_dl}.
+% \begin{macrocode}
+ save _n, _sf, _no_dots;
+ boolean _no_dots; _no_dots := true;
+ _sf := scale_adjust (_n, _dl) (_totlen);
+ if _n < 0: safedraw _g;
+ else:
+ forsuffixes _s = start, rep, finish:
+ for _i = 1 upto _dpat._s:
+ if (_dpat._s[_i] = 0) and _no_dots: _no_dots := false;
+ else: _dpat._s[_i] := _dpat._s[_i]*_sf;
+ fi
+ endfor
+ _dl._s := _dl._s*_sf;
+ endfor
+% \end{macrocode}
+% The user has the capability to use something other than a small disk for
+% a dot by defining \gbc{plot_pic} (and preferably also storing its
+% diameter in \gbc{plot_pic.size}). The utility \gbc{makesymbol} is
+% defined later. It examines \gbc{plot_pic} and makes a picture depending
+% on what type of variable it is. The default \gbc{dotpath} is
+% \mfc{fullcircle}, but user may also change that to get different dots.
+% \gbc{makesymbol} scales by \gbc{penwd} \emph{only if the first
+% parameter is a path}. This is how to increase the dot size (the code in
+% \gbc{plot} uses this.)
+% \begin{macrocode}
+ if _no_dots:
+ else:
+ if unknown plot_pic:
+ save plot_pic; path plot_pic;
+ plot_pic := dotpath;
+ fi;
+ last_dot_size :=
+ if known plot_pic.size: plot_pic.size else: penwd fi;
+ setpicture (dashingdot) makesymbol (plot_pic, last_dot_size);
+ fi
+% \end{macrocode}
+% The macro \gbc{dashit} draws the dashes, computing where they go and
+% drawing the appropriate subpaths of \gbc{_g} or placing a dot at the
+% appropriate point. \gbc{dashit} returns nothing and assumes all the
+% information accumulated so far, so it can only be called by
+% \gbc{gendashed}.
+%
+% \gbc{_t} and \gbc{_d} are temporary variables used by
+% \gbc{dashit}, but we declare them here since we initialize them
+% differently for each call. \gbc{_d0} and \gbc{_d1} hold the
+% position along the curve of the ends of a dash in distance from the
+% start; \gbc{_t0} and \gbc{_t1} are the same, but in terms of time.
+% A macro \gbc{gettime} converts the first to the second. It uses the
+% cumulative length array \gbc{_cumlen} for this, and maintains
+% \gbc{_ct} as the current index into that array.
+% \begin{macrocode}
+ save _t, _d, _v;
+ picture _v; _v := nullpicture;
+ _d0 := 0; _t0 := 0;
+ dashit (_dpat.start) (_v);
+% \end{macrocode}
+% The parameters to \gbc{dashit} are the name of the part of the dashing
+% pattern that is being drawn, and a temporary picture variable. The
+% latter holds the picture until \gbc{DoClip} can process it.
+% The code of \gbc{dashit} leaves \gbc{_d0} pointing to the current
+% position on the curve, but for safety and to reduce accumulated
+% round-off error, we initialize it to what it should be before each call.
+%
+% The repeating pattern has the tendency to use lots of memory. Previously
+% I added all the dashes to \gbc{_v} and then added it all at once to
+% \gbc{active_plane}. The purpose was to be able to \gbc{DoClip} it once,
+% and add it once with \gbc{coloraddon} to get it drawn in color under \MF.
+% This was simplest, but a memory hog requiring $O(n)$ in memory, where
+% $n$ is the number of repeated patterns. Then we tried clipping and adding
+% within \gbc{dashit}. This was terribly slow, requiring $O(n)$ in time.
+% Now we use a standard programming trick: accumulate $m < n$ repetitions
+% before adding them, the memory should be $O(m)$ and the time $O(n/m)$.
+% Making $m$ about $\sqrt n$ seems to work well.
+% \begin{macrocode}
+ if _n > 0:
+ save _m; _m := ceiling sqrt(_n);
+ for _j = 0 step _m until _n - 1:
+ for _i = 0 upto _m - 1:
+ exitif (_i + _j) > _n - 1;
+ _d0 := _dl.start + (_j + _i)*_dl.rep;
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ dashit (_dpat.rep) (_v);
+ endfor
+ DoClip (_v);
+ coloraddon (drawcolor, _v);
+ _v := nullpicture;
+ endfor
+ fi
+
+ _d0 := _totlen - _dl.finish;
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ dashit (_dpat.finish) (_v);
+ DoClip (_v);
+ coloraddon (drawcolor, _v);
+ fi
+ fi
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{makelengtharray}
+% This takes an array name and a path expression (which is assumed to be
+% in device coordinates), computes the array of partial lengths (of the
+% polygon approximation), and returns the total length. To avoid numeric
+% overflow we rescale the lengths and so the array elements are in units
+% of \gbc{_rescale_factor}. At one point we used to rescale the path,
+% but that turned out to be unnecessary and made it harder to accomplish
+% several of the things we now do with this. We also save a little
+% memory by making the path a suffix parameter, which avoids the memory
+% used for the `capsule' of an expression parameter. So far all uses apply
+% it to a path variable and we have to remember to keep it that way.
+% \begin{macrocode}
+vardef makelengtharray (suffix clen) suffix p =
+ setsplit (_s) segment_split;
+ numeric clen[];
+ clen := _s * length p; clen0 := 0;
+ for _i = 1 upto clen:
+ clen[_i] := clen[_i-1] + abs (pnt[_i/_s] (p) - pnt[(_i-1)/_s] (p))
+ / _rescale_factor;
+ endfor
+ clen[clen]
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{scale_adjust}
+% Here \gbc{n} is a suffix defined by the calling routine,
+% \gbc{pl.\{start\|rep\|finish\}} are the lengths of corresponding parts
+% of a dashing pattern, \gbc{lngth} is the length of some path (determined
+% by the calling routine). It determines how many times \gbc{pl.rep} goes
+% into \gbc{lngth - pl.start - pl.finish}. If this is negative it remains
+% negative, otherwise it is rounded. \gbc{scale_adjust} then determines
+% and returns the scaling factor \gbc{sf} required to make
+% \gbc{sf*(pl.start + n*pl.rep + pl.finish)} equal to \gbc{lngth}.
+% \begin{macrocode}
+vardef scale_adjust (suffix n, pl) (expr lngth) =
+ n := (lngth - pl.start - pl.finish)/pl.rep;
+ n := if n < 0: -1 else: round(n) fi;
+ lngth/(pl.start + emax (n, 0)*pl.rep + pl.finish)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{gettime}
+% \gbc{arr} is an increasing array of lengths, defined by the calling
+% routine. \gbc{ct} is current index into that array; it will vary with
+% subsequent calls. Calling routine initializes it before the first call,
+% \gbc{gettime} updates it. \gbc{lngth} is a length interpreted as the
+% length along the path associated to the array.
+%
+% Since this array is generated by splitting the segments of the path at
+% times \gbc{i/segment_split} we first determine in which of these splits
+% the given distance is (i.e., find \gbc{ct} so that \gbc{lngth} lies
+% between \gbc{arr[ct-1]} and \gbc{arr[ct]}). To avoid problems with
+% round-off error, bad length parameter, etc., we force \gbc{lngth} to
+% satisfy this for some index between the current value of \gbc{ct} and
+% \gbc{arr} inclusive.
+%
+% Once we know what segment we are in, we determine the time by linear
+% interpolation between the times corresponding to \gbc{ct} and
+% \gbc{ct+1}. Note: in the \mfc{forever} loop, the exit must come before
+% the increment. The function \gbc{inrange} is defined in
+% section~\ref{axes}. It checks if the third argument is between the
+% first two, or equal to one of them.
+% \begin{macrocode}
+vardef gettime (suffix arr, ct) (expr lngth) =
+ setnumeric (_gtl) emax (arr[ct], emin (arr[arr], lngth));
+ setsplit (_s) segment_split;
+ forever: exitif inrange (arr[ct], arr[ct+1]) (_gtl);
+ next ct;
+ endfor
+ if arr[ct] = arr[ct+1]: ct
+ else: ( ct + (_gtl - arr[ct]) / (arr[ct+1] - arr[ct]) )
+ fi /_s
+enddef;
+
+def next suffix X = X := X + 1; enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{dashit}
+% No variables are saved or initialized; \gbc{gendashed} defines array
+% \gbc{_cumlen}, path \gbc{_g}, and initializes \gbc{_d0},
+% \gbc{_t0} and \gbc{_ct}.
+%
+% \gbc{pos} is one of the dashpattern arrays, so it consists of numerics
+% interpreted as lengths of dashes (odd index) and spaces (even index). In
+% the first case \gbc{_d0} and \gbc{_t0} will already be pointing to
+% the beginning of the dash and we get to the end of the dash by adding
+% the length of a dash (\gbc{pos[_j]}) to \gbc{_d0} (getting
+% \gbc{_d1}) and calling \gbc{gettime} (getting \gbc{_t1}). We draw
+% the subpath between those points. Unless \gbc{pos[_j] = 0}, in which case
+% a dot is placed.
+%
+% For even \gbc{j} (a space) we are at \gbc{_d1} and \gbc{_t1} and
+% we increment them to get \gbc{_d0} and \gbc{_t0} for the next
+% iteration.
+% \begin{macrocode}
+def dashit (suffix pos) (suffix pic) =
+ for _k = 1 upto pos:
+ if odd _k:
+ if pos[_k] = 0:
+ _d1 := _d0; _t1 := _t0;
+ picdot (pic, dashingdot, pnt [_t0] (_g));
+ else:
+ _d1 := _d0 + pos[_k];
+ _t1 := gettime (_cumlen, _ct) (_d1);
+ shpath (pic, drawpen) (subpath (_t0, _t1) of _g);
+ fi
+ else:
+ _d0 := _d1 + pos[_k];
+ _t0 := gettime (_cumlen, _ct) (_d0);
+ fi
+ endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{dashpat}
+% This is a utility to convert a list of lengths to an array. It is almost
+% the same as \gbc{list}, but it does make sure the array functions as
+% a dashing pattern. It needs to consist of either $1$ item (the signal to
+% draw a solid line) or an even number of items. So we add a zero length
+% term if the size is $0$ or odd and bigger than $1$.
+%
+% \DescribeRoutine{mkdasharrays}
+% The dashing code in \gbc{gendashed} is written so the the beginning and
+% ending patterns can be different from the repeating patterns. If so,
+% they must be named \gbc{pat.start}, \gbc{pat.rep} and \gbc{pat.finish}.
+% If one of these three is not a known array but \gbc{pat} is, this macro
+% creates the array in a generic way. When created this way, \gbc{pat.rep}
+% is a copy of \gbc{pat}. So is \gbc{pat.start}, except only a fraction of
+% the first dash is used, while \gbc{pat.finish} is just the first dash of
+% \gbc{pat} reduced by the factor \gbc{dash_finish}.
+% \begin{macrocode}
+def dashpat (suffix pat) (text t) =
+ list (pat) (t);
+ if (pat = 0) or (odd (pat) and (pat > 1)):
+ pat[incr pat] := 0;
+ fi
+enddef;
+
+vardef mkdasharrays (suffix src, dest) =
+ save _bad; boolean _bad; _bad := false;
+ forsuffixes _s = start, rep, finish:
+ numeric dest._s, dest._s[];
+ boolean _bad._s;
+ if knownnumericarray src._s:
+ copyarray (src._s) (dest._s);
+ _bad._s := false;
+ else:
+ _bad := _bad._s := true;
+ fi
+ endfor
+ % _bad = one of the three arrays not copied.
+ if _bad:
+ if knownnumericarray src: _bad := false;
+ if _bad.rep: % make dest.rep = src
+ copyarray (src) (dest.rep);
+ fi
+ if _bad.start: % shrink first dash to get dest.start
+ copyarray (src) (dest.start);
+ dest.start1 := dash_start*src1;
+ fi
+ if _bad.finish: % use partial first dash for dest.finish
+ dest.finish := 1;
+ dest.finish1 := dash_finish*src1;
+ fi
+ fi
+ fi
+ not _bad
+enddef;
+
+% \end{macrocode}
+%
+% The \mfpic{} command \cs{dashed} is now implemented by making a
+% dashpattern from the two arguments and calling gendashed. That is the
+% definition of \gbc{DASHED}.
+%
+% \gbc{dashed} takes parameters which are the length and the space (device
+% coordinates) and a path (graph coordinates). It returns the path.
+% \begin{macrocode}
+vardef Dashed (expr dlen, dgap) expr f =
+ save dashes; dashpat (dashes) (dlen, dgap);
+ gendashed (dashes) f
+enddef;
+
+def DASHED = Dashed enddef;
+%<MF> def dashed = Dashed enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{doplot}
+% \gbc{doplot} places symbols at positions along a path determined by
+% \gbc{dgap} (space between symbols), they are scaled by \gbc{sc} and the
+% actual symbol is \gbc{spath}. Currently this may be one of three things:
+% \begin{enumerate}
+% \item A path, giving the shape of the dot, which should be defined in
+% units so that the desired size is obtained under scaling by
+% \gbc{sc}. Normally this means one unit across.
+% \item A picture. This is used unscaled, it being presumed that it has
+% been prepared by a user to the correct size.
+% \item (\MP{} only) a string.
+% \end{enumerate}
+% All these are converted to a picture by the \gbc{makesymbol} command and
+% it is assigned to \gbc{plot_pic}, which \gbc{gendashed} has been
+% trained to use when dots are needed.
+%
+% After this \gbc{gendashed} is called with a pattern where the dashes are
+% 0 length, the signal that dots are to be used.
+% \DescribeRoutine{dotted}
+% The macro \gbc{dotted} is implemented by calling \gbc{doplot} with
+% \gbc{dotpath} as the the symbol.
+% \begin{macrocode}
+vardef doplot (expr spath, sc, dgap) expr f =
+ save dots; dashpat (dots) (0, dgap);
+ setpicture (plot_pic) makesymbol (spath, sc);
+ plot_pic.size := sc;
+ gendashed (dots) f
+enddef;
+
+path dotpath; dotpath := fullcircle;
+def dotted = doplot (dotpath) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{plotnodes}
+% These are useful little utilities to draw the points on top of the
+% curve through them. \gbc{plotnodes} differs from \gbc{plotsymbol}
+% (defined later) in that it takes a path parameter (rather than a list of
+% points) and returns that path (so it works with \mfpic{} as a prefix
+% macro). It also uses \gbc{drawcolor}. Otherwise it calls the same code.
+%
+% \DescribeRoutine{showcontrols}
+% \gbc{showcontrols} was mainly for debugging; it draws a line segment
+% connecting the control points of each node. It optionally draws a symbol
+% at each control point. We use \mfc{0} for a `symbol' to indicate we
+% don't wish to draw a symbol there. The default color for both the
+% symbols and the segment is \gbc{pointcolor}.
+% \begin{macrocode}
+vardef plotnodes (expr symbol, size) expr f =
+ if size > 0:
+ save pln; pair pln[];
+ pln := 0;
+ for _a = 0 upto (length f) if cycle f: - 1 fi:
+ pln[incr pln] := pnt[_a] (f);
+ endfor
+ dosymbols (drawcolor, symbol, size) (pln);
+ fi
+ f
+enddef;
+
+def showcontrols = colorshowcontrols (pointcolor) enddef;
+vardef colorshowcontrols (expr clr, syma, symb, size) expr f =
+ save shpre, shpost;
+ pair shpre[], shpost[];
+ shpre := 0; shpost := 0;
+ for a = 0 upto (length f) if cycle f: - 1 fi:
+ shpre [incr shpre] := pre [a] (f);
+ shpost[incr shpost] := post[a] (f);
+ colorsafedraw (clr)
+ (zconv (shpre[shpre]--pnt[a](f)--shpost[shpost]));
+ endfor
+ if size > 0:
+ if not numeric syma: dosymbols (clr, syma, size) (shpre) ; fi
+ if not numeric symb: dosymbols (clr, symb, size) (shpost); fi
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Double-line drawing}\label{doubleline}
+%
+% \DescribeRoutine{doubledraw}
+% This invokes \gbc{parapath}, which has issues with smooth but wiggly
+% paths. An easier approach would be to draw a wide line and erase a
+% narrow one in the middle. However, that would not be transparent in
+% \MP{}.
+% \begin{macrocode}
+def doubledraw = colordoubledraw (drawcolor) enddef;
+vardef colordoubledraw (expr clr, sep) expr f =
+ convertpath (g) f;
+ colorsafedraw (clr) (parapath ( sep/2) g);
+ colorsafedraw (clr) (parapath (-sep/2) g);
+ f
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Points Symbols and Other Pictures}\label{symbols}
+%
+% \DescribeRoutine{centerit}
+% This accepts a picture and returns the same picture centered. This
+% is close to impossible in \MF, so we only do it in \MP. Actually, we
+% no longer use it, because in the one case where we did
+% (\gbc{makesymbol}), it seemed to restrict the user's choices too much.
+% \begin{macrocode}
+%<*MP>
+vardef centerit (expr pic) =
+ pic shifted -(0.5[urcorner pic, llcorner pic])
+enddef;
+
+%</MP>
+% \end{macrocode}
+%
+% \DescribeRoutine{makesymbol}
+% This utility takes \emph{any} expression and scale and returns a picture.
+% If the expression \gbc{spath} is a cycle it returns the interior, for
+% other paths, a drawing of the path, in either case scaled by \gbc{sc}.
+% If already a picture, it returns it. In \MP, if it is a string, it
+% returns a picture containing that string drawn in the \mfc{defaultfont}.
+% In any other case, the default dot is returned.
+% \begin{macrocode}
+vardef makesymbol (expr spath, sc) =
+ if picture spath :
+%<MF> setpicture (v) spath; mono (v); v
+%<MP> spath
+ elseif path spath: setdot (spath, sc)
+%<MP> elseif string spath:
+%<MP> spath infont defaultfont scaled defaultscale
+ else:
+ GBwarn "Undefined symbol for plotting, "
+ & "dotpath will be used instead.";
+ setdot (dotpath, sc)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% Points are filled or unfilled circles. They are implemented with
+% \gbc{plotsymbol}, but the code differs in that filled or unfilled
+% circles are determined by a parameter rather than the type of curve.
+% In addition, for unfilled circles, it clears the pixels inside the circle.
+%
+% \DescribeRoutine{bpoint}
+% \gbc{bpoint} is basicly a shorthand for a scaled circle shifted to a
+% point. The scale and the point are in device coordinates. We don't use
+% it anywhere in \grafbase{} anymore.
+% \begin{macrocode}
+vardef bpoint (expr ptwd, b) =
+ fullcircle scaled ptwd shifted b
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{pointd}
+% This draws disks with diameter \gbc{ptwd}, filled or unfilled based on
+% the boolean \gbc{filled}, at the graph coordinate coordinates in the
+% list \gbc{t}. In case \gbc{filled} is true, \gbc{pointd} calls
+% \gbc{plotsymbol (SolidCircle)} otherwise we make \gbc{clearsymbols} true
+% (so that the area where each point is drawn will be cleared before
+% drawing it) and call \gbc{plotsymbol (Circle)}.
+% \begin{macrocode}
+def pointd (expr ptwd, filled) (text t) =
+ if filled:
+ plotsymbol (SolidCircle, ptwd) (t);
+ else:
+ begingroup;
+ setboolean (clearsymbols) true;
+ plotsymbol (Circle, ptwd) (t);
+ endgroup
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{plotsymbol}
+% \RoutineIndex{colorplotsymbol}
+% The \gbc{plotsymbol} command places a symbol centered at each of the
+% graph coordinate points in the list. The symbol placed is the first
+% parameter, which would normally be a path, but can be a picture or, in
+% \MP, a string. Like the \gbc{doplot} command, it calls \gbc{makesymbol}.
+% If \gbc{spath} is of type path, and is cyclic, it is drawn filled. This
+% is because we call \gbc{makesymbol} on it, and that subjects it to
+% \gbc{setdot}, which has that behavior. For other types of symbols, we
+% simply convert them to pictures with \gbc{makesymbol} and then place
+% them. Unlike \gbc{pointd} above, the interior of the path is not erased
+% by default. However, in the special case where the symbol is an open
+% path, if its first point is equal to its last point, and
+% \gbc{clearsymbols} is true, then the interior of the path obtained by
+% \gbc{\& cycle} is cleared before the path itself is drawn. We copy the
+% text list to an array and call \gbc{dosymbols} so that \gbc{plotnodes},
+% \gbc{plotsymbol} and \gbc{showcontrols} can share the code.
+%
+% \DescribeRoutine{dosymbols}
+% Since \gbc{dosymbols} uses identical code twice (once to clear, once to
+% draw), we put that code in \gbc{addsymbols}.
+% \DescribeRoutine{addsymbols}
+% And finally, \gbc{addsymbols} draws copies of a symbol at a given array
+% of points with a given color.
+% \begin{macrocode}
+boolean clearsymbols; clearsymbols := false;
+vardef clearable (expr pth) =
+ if path pth:
+ ( pnt0 (pth) = pnt[length pth] (pth) ) and (not cycle pth)
+ and (length pth > 0)
+ else: false
+ fi
+enddef;
+
+def clearopenpath expr f =
+ if clearable (f): safeunfill f & cycle; fi
+enddef;
+
+def plotsymbol = colorplotsymbol (pointcolor) enddef;
+def colorplotsymbol (expr clr, spath, sc) (text t) =
+ if sc > 0:
+ begingroup
+ setpairs (_cpls) (t);
+ if _cpls > 0: dosymbols (clr, spath, sc) (_cpls); fi
+ endgroup
+ fi
+enddef;
+
+def dosymbols (expr clr, spath, sc) (suffix arr) =
+ if clearsymbols and clearable (spath):
+ addsymbols (background, makesymbol (spath&cycle, sc)) (arr);
+ fi
+ addsymbols (clr, makesymbol (spath, sc)) (arr);
+enddef;
+
+def addsymbols (expr clr, symb) (suffix arr) =
+ newpicture (_pls);
+ for _idx = 1 upto arr:
+ picdot (_pls, symb, zconv (arr[_idx]));
+ endfor
+ DoClip (_pls); coloraddon (clr, _pls);
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{putimage}
+% This is designed to allow \mfpic{} users to make a picture (created with
+% \cs{mfpimage} or \cs{tile} perhaps), and put a copy at several
+% locations. This allows more complex things than \cs{plotsymbol} and
+% more flexibility than \cs{tess}. As the picture is should be completely
+% prepared in advance, there is no color or size parameter. Moreover,
+% \gbc{pic} might be quite complex, so we don't use \gbc{picdot} which
+% takes the added picture as an expression, but rather repeat its code.
+% The indirection of adding to \gbc{_pti} is normal when we want to
+% respect clipping without clipping what is already drawn. Saving memory
+% at some sacrifice of speed, we clip and reset with each addition. (It is
+% uncertain whether adding multiple clipped pictures includes the clipping
+% path for each addition. I'll have to test the memory use of this code
+% versus adding all the copies to \gbc{_pti} and clipping once.)
+% \begin{macrocode}
+def putimage (suffix pic) (text t) =
+ newpicture (_pti);
+ for _itm = t:
+ addto _pti also
+%<MF> (pic shifted goodpair (zconv (_itm)));
+%<MP> (pic shifted zconv (_itm));
+ DoClip (_pti); addto active_plane also _pti;
+ _pti := nullpicture;
+ endfor
+%<MF> mono active_plane
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Axes, Tic Marks, and Grids}\label{axes}
+%
+% \DescribeRoutine{arrowdraw}
+% This is used in \gbc{vectorfield} and to draw axes. It returns nothing.
+% This doesn't follow the usual pattern of drawing a path and returning
+% it. This approach makes the old \cs{axes}, \cs{xaxis} and \cs{yaxis}
+% commands in \mfpic{} impossible to dash or dot. The newer axis drawing
+% commands permit this and so use other code.
+%
+% We simply call \gbc{headpath} with default values, but add \gbc{drawn}
+% to make sure the path is drawn, and precede it with \gbc{store} so
+% \MF{} won't complain of an isolated expression. The new \mfpic{}
+% method of drawing an axis is to apply \cs{arrow} to the path
+% \gbc{axisline}. Thus it can also be \gbc{dashed}, \gbc{dotted},
+% etc.
+%
+% The order is significant if axis and head are different colors. This
+% order puts the head on top of the shaft.
+% \begin{macrocode}
+def arrowdraw (expr hlen) (expr f) =
+ store (curpath) headpath (hlen, 0, 0) drawn f;
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{xaxis}
+% The macro \gbc{xaxis} draws the $x$-axis through the point $(0,0)$ in
+% graph coordinates. The only parameter is the length of the arrowhead in
+% device coordinates.
+% \DescribeRoutine{yaxis}
+% The Macro \gbc{yaxis} draws the $y$-axis.
+%
+% \DescribeRoutine{axes}
+% \gbc{axes} draws both axes with the same length of head.
+% \begin{macrocode}
+def xaxis (expr hlen) = arrowdraw (hlen) ((xneg, 0)--(xpos, 0));
+enddef;
+def yaxis (expr hlen) = arrowdraw (hlen) ((0, yneg)--(0, ypos));
+enddef;
+def axes (expr hlen) = xaxis (hlen); yaxis (hlen); enddef;
+
+% \end{macrocode}
+%
+% For axes at the borders of the graph coordinates, we allow for them to
+% be shifted inwards. The amount of the shift is given by \gbc{laxis} for
+% the left side axis, \gbc{baxis} for the bottom axis, etc. They are in
+% graph coordinates.
+%
+% \DescribeRoutine{axisline}
+% The commands \gbc{axisline.x}, etc., return the appropriate straight
+% line at the appropriate location. These are vardefs rather than
+% variables so they can be affected by changing shift values.
+%
+% \DescribeRoutine{axis}
+% Finally, the commands \gbc{axis.x}, etc. examine their suffix and
+% apply \gbc{headpath} to the corresponding axis line. With a recent
+% change in \mfpic{} code, it is no longer used there. Instead, code
+% is written that allows the head to be drawn after the line is.
+% Note it is a vardef, and so returns the line as a path..
+% \begin{macrocode}
+laxis := baxis := raxis := taxis := 0;
+
+vardef xlow = xneg + laxis enddef;
+vardef xhigh = xpos - raxis enddef;
+vardef ylow = yneg + baxis enddef;
+vardef yhigh = ypos - taxis enddef;
+
+vardef axisline.x = (xlow, 0)--(xhigh, 0) enddef;
+vardef axisline.y = (0, ylow)--(0, yhigh) enddef;
+vardef axisline.l = axisline.y shifted (xlow, 0) enddef;
+vardef axisline.b = axisline.x shifted (0, ylow) enddef;
+vardef axisline.r = axisline.y shifted (xhigh, 0) enddef;
+vardef axisline.t = axisline.x shifted (0, yhigh) enddef;
+
+vardef axis@# (expr len) = headpath (len, 0, 0) axisline@# enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{borderrect}
+% These are mostly for the simplification of \mfpic{} and readability of
+% code. The command \gbc{borderrect} produces the border of the picture
+% in graph coordinates, taking into account the four margins.
+%
+% \DescribeRoutine{between}
+% The boolean \gbc{between} checks if the last argument is strictly
+% between the first two (which must be in order).
+%
+% \DescribeRoutine{inrange}
+% The boolean \gbc{inrange} checks if the last argument is in the closed
+% interval determined by the first two (which must be in order).
+%
+% \DescribeRoutine{inbounds}
+% The boolean \gbc{inbounds} checks if the argument (a pair) is in
+% the closed border rectangle (\gbc{borderrect}). It is not yet used in
+% \grafbase{}, though it would seem it ought to be useful.
+% \begin{macrocode}
+vardef borderrect =
+ rect((xlow,ylow),(xhigh,yhigh))
+enddef;
+
+vardef between (expr A, B, X) = (A < X) and (X < B) enddef;
+vardef inrange (expr A, B, X) = (A <= X) and (X <= B) enddef;
+
+vardef inbounds (expr Z) =
+ inrange (xlow, xhigh) (xpart Z) and inrange (ylow, yhigh) (ypart Z)
+enddef;
+
+% \end{macrocode}
+%
+% Possible binary relation versions. The last is just a reversal of the
+% order of the first. These are not yet used in \grafbase{}.
+% \begin{macrocode}
+tertiarydef X isbetween P = between (xpart P, ypart P, X) enddef;
+tertiarydef X isinrange P = inrange (xpart P, ypart P, X) enddef;
+tertiarydef P contains X = between (xpart P, ypart P, X) enddef;
+
+% \end{macrocode}
+%
+% Tick marks can be on the inside or outside of a border axis,
+% above or below any horizontal axes, left or right of any vertical axis
+% or centered on any axis. The following numerics are merely used to
+% convert the names to numeric code that the drawing routine will examine.
+%
+% However, it is no accident that \gbc{onbottom = onright} and that
+% \gbc{centered} is halfway between \gbc{onright} and \gbc{onleft}. The
+% code uses the numeric values to compute a shift, and one can supply an
+% expression like \gbc{.33ontop+.67onbottom]} and then 1/3 of each mark
+% will be above (and 2/3 will be below) the axis.
+%
+% The negative value of \gbc{inside} and \gbc{outside} is a flag that they
+% are to be treated differently. The others have the property that the
+% direction is the direction of the axis rotated a certain way (e.g.,
+% $90$ degrees from \mfc{up} points \mfc{left}, $-90$ points \mfc{right}).
+% But \gbc{inside} is right of the left axis and left of the right axis.
+% \begin{macrocode}
+numeric inside, outside, centered, onleft, onright, ontop, onbottom;
+inside := -2;
+outside := -1;
+onright := 1;
+onleft := 2;
+centered := .5[onright, onleft];
+onbottom := onright;
+ontop := onleft;
+% \end{macrocode}
+%
+% We interact with \mfpic{} by allowing the user to change the value of
+% \gbc{ltick}, for example, with a command like
+% \cs{setaxismarks l}\marg{outside}. Here we set the defaults.
+% \begin{macrocode}
+ltick := rtick := ttick := btick := inside;
+xtick := ytick := centered;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{axismarks}
+% This utility macro draws the tick marks on an arbitrary axis. The
+% different commands \gbc{xmarks}, etc., call this command with particular
+% values of these parameters.
+% \begin{itemize}
+% \item \gbc{inang} is the direction one must rotate the axis to point
+% inside. This is always $\pm90$ degrees. The $x$-axis and $y$-axis
+% are treated just like bottom and left axis in this respect.
+% \item \gbc{tp} is the tick position (e.g., \gbc{inside} or
+% \gbc{ontop}).
+% \item \gbc{loc} is the location of the 0-point of the axis (graph
+% coordinates).
+% \item \gbc{pdir} is \mfc{right} or \mfc{up}, indicating the positive
+% direction on the axis.
+% \item \gbc{len} is the length of a tick mark, supplied as an argument
+% to the individual axis mark commands.
+% \item \gbc{t} is the list of positions, also supplied.
+% \end{itemize}
+% \begin{macrocode}
+vardef axismarks (expr inang, tp, loc, pdir) (expr len) (text t) =
+ save _tp, _U, _P, _tic, _ticang;
+ pair _U, _P; path _tic;
+% \end{macrocode}
+% For \gbc{onleft}, \gbc{onright}, \gbc{ontop} or \gbc{onbottom}, which
+% are positive, don't examine \gbc{inang} but for \gbc{inside/outside}
+% use it to determine what inside means. \gbc{_ticang} will be the angle
+% to rotate \gbc{pdir} to set the direction of the tic mark.
+%
+% Then we shift the numeric value of \gbc{tp} by one, so \gbc{centered}
+% corresponds to $.5$ and the rest to either $0$ or $1$.
+% \begin{macrocode}
+ _ticang := if tp < 0: inang else: 90 fi;
+ _tp := abs(tp) - 1;
+% \end{macrocode}
+% Except, we go through the following shenanigans so that the marks are
+% always perpendicular to the axis, even if a coordinate transform will
+% slant the axis. After this \gbc{_U} should point in direction of inside,
+% onleft or ontop.
+% \begin{macrocode}
+ _U := unitvector (vconv (pdir)) rotated _ticang;
+% \end{macrocode}
+% Next, we use \gbc{_tp} to calculate the mark. For example, if
+% \gbc{tp = inside}, then \gbc{_tp = 1}. Since \gbc{_U} points toward
+% inside, \gbc{_tic} will go from \mfc{(0,0)} to a point a distance
+% \gbc{len} in the direction of \gbc{_U}.
+% \begin{macrocode}
+ _tic := (-_U--(0,0)) shifted (_tp*_U) scaled len;
+% \end{macrocode}
+% Finally, for each numeric value in the list \gbc{t}, draw the tic
+% shifted to the corresponding point on the axis.
+% \begin{macrocode}
+ for _a = t:
+ safedraw (_tic shifted zconv (loc + _a*pdir));
+ endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{xmarks}
+% And now the specialized command for each axis. Inside and outside
+% really make no sense for the $x$- and
+% \DescribeRoutine{ymarks}
+% \RoutineIndex{lmarks}
+% \RoutineIndex{bmarks}
+% \RoutineIndex{rmarks}
+% \RoutineIndex{tmarks}
+% $y$-axis, but since a bottom axis is usually used for $x$ and a left
+% axis for $y$, we give \gbc{xmarks} the same first parameter as
+% \gbc{bmarks} and \gbc{ymarks} the same as \gbc{lmarks}.
+% \begin{macrocode}
+def xmarks = axismarks ( 90, xtick, origin, right) enddef;
+def ymarks = axismarks (-90, ytick, origin, up) enddef;
+def lmarks = axismarks (-90, ltick, (xlow, 0), up) enddef;
+def bmarks = axismarks ( 90, btick, (0, ylow), right) enddef;
+def rmarks = axismarks ( 90, rtick, (xhigh, 0), up) enddef;
+def tmarks = axismarks (-90, ttick, (0, yhigh), right) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{vargrid}
+% \RoutineIndex{vgrid}
+% Mainly for the purpose of visualising coordinates, \gbc{vargrid}
+% draws a dot of size \gbc{dsize} at every point whose coordinates
+% are are \gbc{(n*xsp, m*ysp)}, \gbc{n} and \gbc{m} being integers.
+% \gbc{dsize} is in device coordinates, the spacings are in graph
+% coordinates.
+% \DescribeRoutine{grid}
+% The macro \gbc{grid} is for backward compatibility, calling
+% \gbc{vargrid} with a default \gbc{dsize} of \mfc{.5bp}. The old name
+% \gbc{vgrid} incorrectly suggests a connection to \gbc{vgridlines}.
+% \begin{macrocode}
+path griddotpath; griddotpath := fullcircle;
+def grid = vargrid (0.5bp) enddef;
+vardef vargrid (expr dsize, xsp, ysp) =
+ save gdot, gridpic; picture gdot, gridpic;
+ gdot := setdot (griddotpath, dsize);
+ gridpic := nullpicture;
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ for m = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ picdot (gridpic, gdot, zconv ((n*xsp, m*ysp)));
+ endfor
+ endfor
+ coloraddon (pointcolor, gridpic);
+enddef;
+def vgrid = vargrid enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{gridlines}
+% This is more what I think of when I hear `grid', but the name was
+% already taken. The macro \gbc{gridlines} draws horizontal and vertical
+% lines through all the points that \gbc{grid} would draw.
+% \DescribeRoutine{hgridlines}
+% The macro \gbc{hgridlines} draws only the horizontal lines through the
+% same points, while
+% \DescribeRoutine{vgridlines}
+% \gbc{vgridlines} draws only vertical lines.
+% \begin{macrocode}
+def hgridlines (expr ysp) =
+ for n = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ safedraw zconv ((xlow, n*ysp)--(xhigh, n*ysp));
+ endfor
+enddef;
+def vgridlines (expr xsp) =
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ safedraw zconv ((n*xsp, ylow)--(n*xsp, yhigh));
+ endfor
+enddef;
+def gridlines (expr xsp, ysp) =
+ vgridlines (xsp); hgridlines (ysp);
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{vectorfield}
+% This command produces a field of arrows from a pair-valued formula (text
+% parameter \gbc{fcn}) in a region described by a boolean-valued
+% expression (text parameter \gbc{cond}). This routine simply makes
+% functions (\mfc{vardef}\,s) out of the expressions and calls
+% \DescribeRoutine{mkvectorfield}
+% \gbc{mkvectorfield}, which steps through the points described by
+% \gbc{xsp} and \gbc{ysp} and places an arrow (actually, any path) at
+% each. The arrow path is given by the function \gbc{vf}. The arrow is
+% placed at the point only if the function \gbc{isOK} returns true. It
+% also omits points that lie in the axis margins.
+%
+% \DescribeRoutine{plrvectorfield}
+% The polar version differs only in the distribution of the arrows. They
+% are placed at regular intervals of $r$ an $\theta$. The text parameters
+% should be expressions in \gbc{r} and \gbc{t}, but are otherwise the
+% same. In particular, \gbc{fcn} should return \MF{} pairs, not polar
+% coordinate pairs. The function \gbc{polar} can be used to convert if
+% necessary. Its code is very similar, except for the boolean code needed
+% to keep the vectors within the bounds of the graph.
+% \DescribeRoutine{mkplrvectorfield}
+% It calls \gbc{mkplrvectorfield}, which is a lot like the non-polar
+% version, except it first calculates the extremes of the polar variables
+% with \gbc{getpolarbounds} and relies on the boolean to keep it out of
+% the axis margins.
+% \begin{macrocode}
+def vectorfield (expr len, xsp, ysp) (text fcn) (text cond) =
+ save _vf, _is_OK;
+ vardef _vf (expr x,y) = ((0,0)--(fcn)) shifted (x,y) enddef;
+ vardef _is_OK (expr x,y) = cond enddef;
+ mkvectorfield (len, xsp, ysp) (_vf, _is_OK);
+enddef;
+
+vardef mkvectorfield (expr len, xsp, ysp) (suffix vf, isOK) =
+ for n = ceiling ((xlow)/xsp) upto floor ((xhigh)/xsp):
+ for m = ceiling ((ylow)/ysp) upto floor ((yhigh)/ysp):
+ if isOK (n*xsp,m*ysp): arrowdraw (len) (vf(n*xsp,m*ysp)); fi
+ endfor
+ endfor
+enddef;
+
+def plrvectorfield (expr len, rsp, tsp) (text fcn) (text cond) =
+ save _vf, _is_OK, _A, _B, _C, _D;
+ _A := xlow; _B := xhigh;
+ _C := ylow; _D := yhigh;
+ vardef _vf (expr r,t) = ((0,0)--(fcn)) shifted (r*dir t) enddef;
+ vardef _is_OK (expr r,t) =
+ save _X, _Y; _X := r*cosd t; _Y := r*sind t;
+ (cond) and between (_A, _B) (_X) and between (_C, _D) (_Y)
+ enddef;
+ mkplrvectorfield (len, rsp, tsp) (_vf, _is_OK);
+enddef;
+
+vardef mkplrvectorfield (expr len, rsp, tsp) (suffix vf, isOK) =
+ save rmin, rmax, tmin, tmax;
+ getpolarbounds;
+ if rmin = 0:
+ if isOK (0,tmin): arrowdraw (len) (vf (0,tmin)); fi
+ rmin := rsp;
+ fi
+ for n = ceiling (rmin/rsp) upto floor (rmax/rsp):
+ for m = ceiling (tmin/tsp) upto floor (tmax/tsp):
+ if isOK (n*rsp,m*tsp): arrowdraw (len) (vf (n*rsp,m*tsp)); fi
+ endfor
+ endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{patcharcs}
+% The macro \gbc{patcharcs} draws on a picture \gbc{X} the arcs
+% \gbc{tstart}${}\le \theta \le{}$\gbc{tstop} with radii starting at
+% \gbc{rstart}, stepping by \gbc{rstep} until \gbc{rstop}.
+% \DescribeRoutine{patchrays}
+% The macro \gbc{patchrays} draws the radial lines with $r$ coordinate
+% varying between \gbc{rstart} and \gbc{rstop} at angles from \gbc{tstart}
+% to \gbc{tstop} stepping by \gbc{tstep}.
+% \DescribeRoutine{plrpatch}
+% And \gbc{plrpatch} simply calls them both, and adds the resulting
+% pictures to \gbc{active_plane}.
+% \begin{macrocode}
+def patcharcs (suffix X) (expr rstart, rstop, rstep, tstart, tstop) =
+ for rad = (if rstart = 0: rstep else: rstart fi)
+ step rstep until rstop:
+ orto (X, picpath zconv (arcplr (origin, tstart, tstop, rad)) );
+ endfor
+enddef;
+def patchrays (suffix X) (expr tstart, tstop, tstep, rstart, rstop) =
+ for _ang = tstart step tstep until tstop:
+ orto (X) (picpath zconv ((rstart*dir _ang)--(rstop*dir _ang)));
+ endfor
+enddef;
+
+def plrpatch (expr rstart, rstop, rstep, tstart, tstop, tstep) =
+begingroup
+ newpicture (v);
+ patcharcs (v) (rstart, rstop, rstep, tstart, tstop);
+ coloraddon (drawcolor, v);
+ v := nullpicture;
+ patchrays (v) (tstart, tstop, tstep, rstart, rstop);
+ coloraddon (drawcolor, v);
+endgroup
+enddef;
+
+% \end{macrocode}
+%
+% Polar coordinate grids are analogous to \gbc{gridlines} and \gbc{grid}.
+% They first draw a grid large enough to cover the whole graph, then clip
+% it to the graph boundaries. Since three of the four require
+% calculating the dimensions of a polar coordinate patch that completely
+% covers the graph rectangle, we isolate that code in
+% \gbc{beginpolargrid}, defined later.
+%
+%
+% \DescribeRoutine{gridarcs}
+% \gbc{gridarcs} creates arcs having radii that are integer multiples of
+% \gbc{rstep} and
+% \DescribeRoutine{gridrays}
+% \gbc{gridrays} draws radial lines at angles that are multiples of
+% \gbc{tstep}.
+% \DescribeRoutine{polargrid}
+% The command \gbc{polargrid}simply calls the first two.
+%
+% \DescribeRoutine{polargridpoints}
+% On the other hand, \gbc{polargridpoints} draws dots at the points where
+% the lines and arcs in \gbc{poloargrid} would intersect. The `step'
+% parameters are in graph coordinates. \gbc{beginpolargrid} also
+% declares the picture variable \gbc{gridpic}, while \gbc{endpolargrid}
+% clips the resulting picture and adds it to \gbc{active_plane}.
+%
+% The \gbc{rmin}, etc., returned by \gbc{beginpolargrid} are modified to
+% fit the grid established by the step sizes. A ray could happen to be one
+% of the graph's sides, so we use \mfc{ceiling} and \mfc{floor} which
+% doesn't change integer values. However, the arc with radius \gbc{rmin}
+% or \gbc{rmax} could touch the graph rectangle in at most 4 points, so we
+% use \mfc{floor (x + 1)} and \mfc{ceiling (x - 1)} to start and stop
+% before the edge of the graph.
+% \begin{macrocode}
+def gridarcs (expr rstep) =
+ beginpolargrid;
+ if rmin = 0:
+ picdot (gridpic, setdot (griddotpath, penwd), zconv (origin));
+ fi
+ rmin := rstep * floor (rmin/rstep + 1);
+ rmax := rstep * ceiling (rmax/rstep - 1);
+ patcharcs (gridpic) (rmin, rmax, rstep, tmin, tmax);
+ endpolargrid (drawcolor, .5penwd);
+enddef;
+
+def gridrays (expr tstep) =
+ beginpolargrid;
+ tmin := tstep * ceiling (tmin/tstep);
+ tmax := tstep * floor (tmax/tstep);
+ patchrays (gridpic) (tmin, tmax, tstep, rmin, rmax);
+ endpolargrid (drawcolor, .5penwd);
+enddef;
+
+def polargrid (expr rstep, tstep) =
+ gridarcs (rstep); gridrays (tstep);
+enddef;
+
+def polargridpoints (expr dsize, rstep, tstep) =
+ beginpolargrid;
+ setpicture (gdot) setdot (griddotpath, dsize);
+ if rmin = 0:
+ picdot (gridpic, gdot, zconv (origin));
+ rmin := rstep;
+ fi
+ for n = ceiling (rmin/rstep) upto floor (rmax/rstep):
+ for m = ceiling (tmin/tstep) upto floor (tmax/tstep):
+ picdot ( gridpic, gdot, zconv ( polar ((n*rstep, m*tstep)) ) );
+ endfor
+ endfor
+ endpolargrid (pointcolor, .5dsize);
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{beginpolargrid}
+% The macro \gbc{beginpolargrid} calls \gbc{getpolarbounds} to compute the
+% bounds (on $r$ and $\theta$) of the smallest polar coordinate patch that
+% covers the graph rectangle.
+% \DescribeRoutine{getpolarbounds}
+% That command leaves the values in \gbc{rmin}, \gbc{rmax}, \gbc{tmin} and
+% \gbc{tmax}. Then \gbc{beginpolargrid} initializes \gbc{gridpic} whereon
+% the grids are drawn.
+% \begin{macrocode}
+def beginpolargrid =
+begingroup;
+ save rmax, rmin, tmax, tmin;
+ getpolarbounds;
+ newpicture (gridpic);
+enddef;
+
+def getpolarbounds =
+ save p, r, t;
+ pair p[];
+ p0 := (xneg, yneg); p1 := (xneg, ypos);
+ p2 := (xpos, ypos); p3 := (xpos, yneg);
+% \end{macrocode}
+% This loop finds the radial coordinate of each corner of the graph and
+% finds the maximum while doing so.
+% \begin{macrocode}
+ r0 := abs(p0); rmax := r0;
+ for j = 1 upto 3:
+ r[j] := abs(p[j]);
+ if rmax < r[j]: rmax := r[j]; fi
+ endfor
+% \end{macrocode}
+% When the origin is inside the graph rectangle we need the full range
+% of $r$ and $\theta$. When the origin is one of the corners, the angles
+% can just be read off. Otherwise, to find the range of $\theta$ we
+% essentially rotate one corner to have angle zero, get the angles to all
+% corners and rotate back. This guarantees that the wedge with
+% \gbc{tmin}${} < \theta < {}$\gbc{tmax} includes the graph.
+% \begin{macrocode}
+ rmin := 0;
+ if between (xneg, xpos) (0) and between (yneg, ypos) (0):
+ tmin := 0; tmax := 360;
+ elseif (p0 = origin): tmin := 0; tmax := 90;
+ elseif (p1 = origin): tmin := -90; tmax := 0;
+ elseif (p2 = origin): tmin := -180; tmax := -90;
+ elseif (p3 = origin): tmin := 90; tmax := 180;
+ else:
+ tmax := tmin := t0 := angle p0;
+ for j = 1 upto 3:
+ t := t0 + anglefromto (p0, p[j]);
+ if tmax < t: tmax := t; fi
+ if tmin > t: tmin := t; fi
+ endfor
+% \end{macrocode}
+% The minimum value of $r$ can be one of 9 possibilities: if the four
+% sides of the graph are extended infinitely far in both directions, the
+% origin can be in any one of the 9 regions formed. We've already disposed
+% of the inside of the graph. This code considers the remaining regions in
+% the following order: (1)~above or below, (2)~left or right, and (3)~one
+% of the four corner regions.
+% \begin{macrocode}
+ if between (xneg, xpos) (0):
+ rmin := emin (abs(yneg), abs(ypos));
+ elseif between (yneg, ypos) (0):
+ rmin := emin (abs(xneg), abs(xpos));
+ else:
+ rmin := min (r0, r1, r2, r3);
+ fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{endpolargrid}
+% The \gbc{clr} is \gbc{drawcolor} for line grids, \gbc{pointcolor} for
+% dot grids. The \gbc{size} is half the width of the grid's lines or half
+% the width of the grid's dots. The purpose is to make sure dots and lines
+% on the graph's edge aren't cut off. For dots I should probably put this
+% decision in the code that draws them on \gbc{gridpic}.
+% \begin{macrocode}
+
+def endpolargrid (expr clr, size)=
+ clipto (gridpic) rect ( zconv ((xneg, yneg)) - size*(1,1),
+ zconv ((xpos, ypos)) + size*(1,1) );
+ coloraddon (clr, gridpic);
+ endgroup
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{polarpatch}
+% Finally, this just does \gbc{plrpatch}, but also draws the ending
+% boundaries, in case they are not an integer number of steps from the
+% start.
+% \begin{macrocode}
+vardef polarpatch (expr rstart, rstop, rstep, tstart, tstop, tstep) =
+ plrpatch (rstart, rstop, rstep, tstart, tstop, tstep);
+ safedraw zconv ( arcplr (origin, tstart, tstop, rstop) );
+ safedraw zconv ( ((rstart, 0)--(rstop, 0)) rotated tstop );
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Path Construction}\label{pathconstruction}
+%
+% This section is devoted to commands that accept a list or array of
+% points and produce a path, usually (but not necessarily) through those
+% points. In addition there are a few commands that find some of the key
+% points, lines and circles associated with a triangle. No \mfpic{}
+% interface is yet available for the triangle commands.
+%
+%
+% \subsection{Piecewise linear paths}\label{linear}
+%
+% \DescribeRoutine{rect}
+% Most of the macros that only define paths are coordinate independent.
+% The simplest is \gbc{rect}. It accepts two pair expressions and produces
+% the upright rectangle with those points at opposite corners. It might be
+% noted that if the corners really are lower left and upper right, then
+% the path is anticlockwise, If they are on the other diagonal, the
+% path is clockwise. The path is a cycle (closed). The starting/ending
+% point (needed for arrows and the like) is the first point of the two.
+%
+% \DescribeRoutine{triangle}
+% Produces a closed path joining three points with straight lines; first
+% named point \gbc{A} is \mfc{point 0 of triangle (A, B, C)}, etc.
+% \begin{macrocode}
+vardef rect (expr ll, ur) =
+ ll--(xpart ur, ypart ll)--ur--(xpart ll, ypart ur)--cycle
+enddef;
+vardef triangle (expr A, B, C) = A--B--C--cycle enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{regularpolygon}
+% The first argument is the number of sides, the second is an array name
+% to hold the list of vertices. The third argument contains two
+% equations separated by a semicolon, preferably the location of two of
+% the vertices, or the location of the center and one vertex. That plus
+% the equations in the \mfc{for}-loop give \gbc{n+1} equations to
+% determine the \gbc{n} vertices and the center. Note that the vertices
+% are numbered anticlockwise.
+%
+% The equations must \emph{not} be equations that are satisfied by all
+% $n$-gons regardless of size and position. For example:\\
+% \indent \gbc{regulapolygon(4)(Ted)(Ted0 := (0,0);Ted1 + Ted3 = (0,0))}\\
+% The second of these says the middle lies halfway between the extremes,
+% and is already a consequence of the code. It goes without saying that
+% equations that cannot be satisfied by any regular polygon are also out.
+% \begin{macrocode}
+vardef regularpolygon (expr n) (suffix Bob) (text eqns) =
+ pair Bob[]; Bob := emax (round (abs (n)), 2);
+ eqns;
+ for _uncle = 1 upto Bob - 1:
+ (Bob1 - Bob0) rotated (360/Bob*_uncle) = Bob[_uncle+1] - Bob0;
+ endfor
+ mkpoly (true) (Bob)
+enddef;
+
+% \end{macrocode}
+%
+% The following set of commands take a path as argument, but it is
+% intended that it be a triangle. Even then, they work correctly only if
+% it is a cycle.
+%
+% These produce the perpendicular from \,\gbc{point n of t}\, to the
+% (extension of) the opposite side (i.e., the altitude).
+% \DescribeRoutine{altitudept}
+% The first one determines where the altitude meets the opposite side, and
+% the
+% \DescribeRoutine{altitude}
+% second just connects the two points. Since \gbc{altitudept} is always
+% \gbc{point 1 of altitude}, it is actually redundant. However, the
+% command \gbc{medianpt} (defined below) is used outside of the
+% construction of \gbc{median}, so it seemed possible the \gbc{altitudept}
+% might be useful also.
+%
+% We need a cycle so that points $n+1$ and $n+2$ will wrap around to the
+% start of the path when necessary.
+% \begin{macrocode}
+vardef altitudept expr n of t =
+ save A, B, C, zz; pair A, B, C, zz;
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ zz = whatever[B,C];
+ zz = pnt[n](t) + whatever*((C-B) rotated 90);
+ zz
+enddef;
+
+vardef altitude expr n of t =
+ (pnt[n](t))--(altitudept n of t)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{medianpt}
+% These next two produce the midpoint of the side opposite
+% \,\gbc{point n of t}\, and the
+% \DescribeRoutine{median}
+% line connecting those two points.
+% \begin{macrocode}
+vardef medianpt expr n of t =
+ 0.5[pnt[n + 1] (t), pnt[n + 2] (t)]
+enddef;
+
+vardef median expr n of t =
+ (pnt[n](t))--(medianpt n of t)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{anglebisectorpt}
+% The first produces the point on the side opposite \,\gbc{point n of t}\,
+% where the angle bisector at that corner crosses it and the second
+% produces
+% \DescribeRoutine{anglebisector}
+% the line that bisects that angle.
+% \begin{macrocode}
+vardef anglebisectorpt expr n of t =
+ save A, B, C; pair A, B, C;
+ A := pnt[n ] (t);
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ save zz; pair zz;
+ zz = whatever[B,C];
+ zz = A + whatever*((B-A) rotated (.5*cornerangle (A,B,C)));
+ zz
+enddef;
+
+vardef anglebisector expr n of t =
+ (pnt[n](t))--(anglebisectorpt n of t)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{cornerangle}
+% This calculates the angle at the corner of a triangle. Specifically,
+% the angle (between $-180$ and $180$) required to rotate the vector
+% \gbc{B-A} into \gbc{C-A}. For degenerate triangles the seemingly
+% arbitrary values 60 and 90 are designed to match the assumptions used
+% in the arc commands. But also to guarantee that the three
+% \gbc{cornerangle}\,s add up to $\pm180$. \gbc{cornerangle (A,B,C)} gives
+% the angle at \gbc{A}, positive if \gbc{A--B--C--cycle} is
+% anticlockwise.
+% \begin{macrocode}
+vardef anglefromto (expr u, v) =
+ if (u = origin) or (v = origin): 0
+ else: angle (v rotated (-angle u))
+ fi
+enddef;
+
+vardef cornerangle (expr A, B, C) =
+ if (A = B) or (A = C) :
+ if (B = C) : 60
+ else: 90
+ fi
+ else: anglefromto (B - A, C - A)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mkpath}
+% This accepts the name of an array of pairs and produces a path
+% that connects them. The first and third parameters are booleans. If
+% \gbc{smooth} is \mfc{true} a smooth path is produced, otherwise a
+% polyline. If \gbc{cyclic} is \mfc{true} the path is closed. The work is
+% actually done by \gbc{mksmooth} or \gbc{mkpoly}.
+% \begin{macrocode}
+vardef mkpath (expr smooth, tens, cyclic) (suffix pts) =
+ if smooth: mksmooth (tens)
+ else: mkpoly
+ fi (cyclic, pts)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mkpoly}
+% This produces the path of line segments connecting \gbc{pts1},
+% \gbc{pts2}, etc., closing it up if the boolean \gbc{cyclic} is true.
+% It can also be used with an array of paths instead of points, connecting
+% the end of each with the beginning of the next. We do this in \mfpic{}'s
+% \cs{connect} \dots\ \cs{endconnect} construct.
+% \begin{macrocode}
+vardef mkpoly (expr cyclic) (suffix pts) =
+ for _i = 1 upto pts-1: pts[_i]-- endfor
+ pts[pts] if cyclic: -- cycle else: {0,0} fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{polyline}
+% This is the \mfpic{} interface. Instead of an array name, it accepts a
+% list of pair expressions, forms an array from them and calls
+% \gbc{mkpoly}.
+% \DescribeRoutine{NoPoints}
+% \mfc{NoPoints} is called when an array of points is defined (using
+% setpairs) that returns $0$ for the number of pairs. It prints a warning
+% and sets the array to a single point, the origin.
+% \begin{macrocode}
+vardef polyline (expr cyclic) (text t) =
+ setpairs (_pl) (t);
+ if _pl=0: NoPoints ("polyline", _pl); fi
+ mkpoly (cyclic, _pl)
+enddef;
+
+def NoPoints (expr s) (suffix pts) =
+ GBwarn s & " attempted with empty list."; pts[incr pts] := origin;
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{turtle}
+% \emph{Turtle graphics} was a teaching tool to get youngsters used to the
+% concept of programming while also teaching geometry. The students fed an
+% Apple II computer a sequence of angles and distances, and a small
+% triangle on the screen (the `turtle') would turn the indicated angle
+% and travel the indicated distance, tracing a polyline on the screen.
+%
+% The argument of \gbc{turtle} is a list of pairs. The first is the
+% starting point, the rest are vector displacements (moves). The
+% distance and incremental angles of the original turtle graphics would
+% require keeping track of the current angle and using the \gbc{polar}
+% command.
+% \begin{macrocode}
+vardef turtle (text t) =
+ setnumeric (_tu) 0;
+ setpair (_tmp) origin;
+ pair _tu[];
+ for _a = t:
+ _tmp := _tmp + _a;
+ _tu[incr _tu] := _tmp;
+ endfor
+ if _tu = 0: NoPoints("turtle", _tu); fi
+ mkpoly (false, _tu)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{brownianpath}
+% I needed the following to illustrate Brownian motion. It takes a given
+% starting point, a given number of steps and a scaling factor. It
+% generates a sequence of random points, each one being chosen randomly
+% using a Gaussian distribution centered at the previous point. The
+% standard deviation of the random distance is the scale factor. Strictly
+% speaking this is a Gaussian random walk, not Brownian motion. A true
+% Brownian motion would be a limit of these, with \gbc{num} tending to
+% $\infty$ and \gbc{sc} tending to 0.
+%
+% \DescribeRoutine{randomwalk}
+% This is like \gbc{brownianpath}, but the distance from one point to
+% the next is always the same, only the direction is random. It takes
+% the same arguments as \gbc{brownianpath}
+%
+% \DescribeRoutine{browniangraph}
+% This command takes a given number of steps \gbc{num} and a scaling
+% factor/step size \gbc{scst}. It generates a sequence of points, each one
+% being chosen right of the previous one by the step size \gbc{scst} and
+% randomly up or down using a Gaussian distribution centered at the
+% previous $y-value$. The Gaussian distribution has standard deviation
+% equal to \gbc{scst}. The path starts at $(0,0)$. One needs to transform
+% the path to get a different start or a scale factor different from the
+% step size.
+%
+% In \MF{} we run into capacity problems when \gbc{num} is greater than
+% 500 or so. This is the \mfc{autorounding} problem again (see the
+% discussion at \gbc{sinewave}. We can't use the same technique we used
+% there since it is the drawing that invokes \mfc{autorounding} and these
+% macros only construct paths; they don't draw them.
+% \begin{macrocode}
+vardef brownianpath (expr start, num, sc) =
+ setnumeric (_brp) 1;
+ setpair (_tmp) start;
+ pair _brp[]; _brp1 := _tmp;
+ for _idx := 1 upto num:
+ _tmp := _tmp + sc/(sqrt 2)*(normaldeviate,normaldeviate);
+ _brp[incr _brp] := _tmp;
+ endfor
+ mkpoly (false, _brp)
+enddef;
+vardef randomwalk (expr start, num, dst) =
+ setnumeric (_rdw) 1;
+ setpair (_tmp) start;
+ pair _rdw[]; _rdw1 := _tmp;
+ for _idx := 1 upto num:
+ _tmp := _tmp + dst*dir(uniformdeviate(360));
+ _rdw[incr _rdw] := _tmp;
+ endfor
+ mkpoly (false, _rdw)
+enddef;
+vardef browniangraph (expr num, scst) =
+ setnumeric (_brg) 1;
+ pair _tmp, _brg[]; _tmp := _brg1 := (0,0);
+ for _idx := 1 upto num:
+ _tmp := _tmp + scst*(1,normaldeviate);
+ _brg[incr _brg] := _tmp;
+ endfor
+ mkpoly (false, _brg)
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Smooth paths}\label{smooth}
+%
+% We added an optional parameter for the tension of smooth curves to
+% \mfpic. It used to be implemented this way: functions that implement a
+% tension parameter set \gbc{cur_tension} and called \gbc{mksmooth}, which
+% used that tension in its formation of a path. Since \gbc{mksmooth} was
+% only ever used in this way, I decided to change its syntax to include a
+% tension parameter. Only the functions \gbc{tcurve} and \gbc{mkpath}
+% actually call \gbc{mksmooth} directly, most other path building commands
+% with tension parameters call \gbc{mkpath} or \gbc{mkfcn} (which calls
+% \gbc{mkpath}).
+%
+% \DescribeRoutine{mksmooth}
+% This takes a tension value, a boolean, and the name of an array of
+% points, draws the curve connecting them and closes it up if the boolean
+% is true. It draws the curve forcing it to have the same direction at a
+% point as the line segment connecting the preceding and following points.
+% This is normally best if the curve direction changes relatively modestly
+% from point to point. For example, if the polyline would be convex, then
+% this smooth version would be pretty close to being convex. If the convex
+% polygon has several consecutive sides that are in the same direction,
+% all but the first and last of these segments in the smooth version would
+% be straight.
+% \begin{macrocode}
+vardef mksmooth (expr tens, cyclic) (suffix pts) =
+ if pts = 1: onepointpath (cyclic, pts1)
+ else:
+ settension (_tn) tens; fixtension (_tn);
+ pts1 if cyclic: {pts[2]-pts[pts]} fi
+ for _i = 2 upto pts-1:
+ ..tension _tn..pts[_i]{pts[_i+1]-pts[_i-1]}
+ endfor
+ ..tension _tn..pts[pts]
+ if cyclic: {pts[1]-pts[pts-1]}..tension _tn..cycle fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mktenser}
+% This is just like \gbc{mksmooth}, except the tension value is preceded
+% by \mfc{atleast}. At this writing only \gbc{mkconvex} uses it (as a
+% fallback when there are three or fewer points to connect).
+% \begin{macrocode}
+vardef mktenser (expr tens, cyclic) (suffix pts) =
+ if pts = 1: onepointpath (cyclic, pts1)
+ else:
+ settension (_tn) tens; fixtension (_tn);
+ pts1 if cyclic: {pts[2]-pts[pts]} fi
+ for _i = 2 upto pts-1:
+ ..tension atleast _tn..pts[_i]{pts[_i+1]-pts[_i-1]}
+ endfor
+ ..tension atleast _tn..pts[pts]
+ if cyclic: {pts[1]-pts[pts-1]}..tension atleast _tn..cycle fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mkconvex}
+% This could have been very much like \gbc{mksmooth}, using
+% \mfc{tension atleast} instead of \mfc{tension} (i.e., exactly
+% \gbc{mktenser} above). Unfortunately This destroys smoothness at the
+% beginning and end of any sequence of three or more points that lie on a
+% straight line. Some geometric situations absolutely prevent smoothness,
+% but this certainly isn't one of them. Two consecutive points
+% identical isn't either, but it does. We let the user or calling command
+% arrange for it not to happen (for example, using \gbc{setuniquepairs}
+% instead of \gbc{setpairs}.
+%
+% What we do is weight the direction to be used at each point by how flat
+% the polygon is on the two sides of each point, the flatter side
+% getting the most weight. If a point is collinear with the next two,
+% the flatness is infinite and the curve is forced in that direction. We
+% measure the flatness using the square root of the area of the triangle
+% made by the given point and the the next two points. Those three points
+% lie on a line just when the area is $0$. Using this measure of flatness
+% can be disputed (two triangles can be equally flat in terms of angles
+% but different in terms of areas), but it has the advantage that if the
+% points are subjected to an affine transformation, the weighting is
+% unchanged and the constructed direction vectors transform the same way.
+% Of course, this is also true of other measures. I've tested only
+% the square root of area and it works well for simple cases.
+%
+% The only way to ensure that the whole path transforms the same as the
+% points is to explicitly calculate the controls (in a manner that
+% transforms the same way as the points). I will do this if I can figure
+% out how it \emph{should} be done. It appears to be a convex programing
+% problem.
+%
+% The end segments of a noncycle are problematic. One could argue that
+% this command doesn't apply to noncycles and just truncate the cyclic
+% path. I decided to treat them specially and hope the result is useful.
+% \begin{macrocode}
+vardef mkconvex (expr tens, cyclic) (suffix pts) =
+ save _B, _d, _tmp; pair _d[];
+ settension (_tn) tens; fixtension (_tn);
+ if pts < 4: mktenser (_tn, cyclic) (pts)
+ else:
+ for _j = 2 upto pts - 1:
+ _B[_j] := sqrt(abs((pts[_j]-pts[_j-1])xprod(pts[_j+1]-pts[_j])));
+ endfor
+ if cyclic:
+ _B1 := sqrt(abs((pts1 - pts[pts])xprod(pts2 - pts1)));
+ _B[pts] := sqrt(abs((pts[pts]-pts[pts-1])xprod(pts1 - pts[pts])));
+ else:
+ _B1 := _B2;
+ _B[pts] := _B[pts-1];
+ fi
+ for _j = 2 upto pts - 1:
+ _tmp := _B[_j-1] + _B[_j+1];
+ _d[_j] :=
+ if _tmp = 0: origin % signal to use curl1
+ else:
+ ( _B[_j+1]*(pts[_j] - pts[_j-1]) +
+ _B[_j-1]*(pts[_j+1] - pts[_j]) )/_tmp
+ fi;
+ endfor
+ if cyclic:
+ _tmp := _B[pts] + _B2;
+ _d1 :=
+ if _tmp = 0: origin
+ else:
+ (_B2*(pts1 - pts[pts]) + _B[pts]*(pts2 - pts1))/_tmp
+ fi;
+ _tmp := _B[pts-1] + _B1;
+ _d[pts] :=
+ if _tmp = 0: origin
+ else:
+ ( _B1*(pts[pts] - pts[pts-1]) +
+ _B[pts-1]*(pts1 - pts[pts]) )/_tmp
+ fi;
+ else:
+ _d1 := origin; _d[pts] := origin;
+ fi
+ pts1
+ for _j = 1 upto pts-1:
+ {if _d[_j] = origin: curl1 else: _d[_j] fi}
+ ..tension atleast _tn..pts[_j+1]
+ endfor
+ {if _d[pts] = origin: curl1 else: _d[pts] fi}
+ if cyclic: ..tension atleast _tn..cycle fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% The old \cs{curve} command in \mfpic{} permitted no tension parameter
+% and wrote a \grafbase{} \gbc{curve} command.
+% \DescribeRoutine{curve}
+% For backward compatibility we keep that name, but simply call the
+% \gbc{tcurve} command with the default value for tension.
+% \DescribeRoutine{tcurve}
+% \gbc{tcurve} converts a list of pairs to an array, then calls
+% \gbc{mksmooth} on the array.
+%
+% The next pair call \gbc{mkconvex}, which tries to produce a convex curve
+% when the points form a convex polygon.
+% \DescribeRoutine{ccurve}
+% The first, \gbc{ccurve}, merely calls the second with a default texnsion,
+% while
+% \DescribeRoutine{tccurve}
+% creates an array from the list of pairs and calls \gbc{mkconvex} on it.
+% \begin{macrocode}
+numeric default_tension; default_tension := 1;
+def curve = tcurve (default_tension) enddef;
+vardef tcurve (expr tens, cyclic) (text t) =
+ setpairs (_tc) (t);
+ if _tc=0: NoPoints("curve", _tc); fi
+ mksmooth (tens, cyclic, _tc)
+enddef;
+
+def ccurve = tccurve (default_tension) enddef;
+vardef tccurve (expr tens, cyclic) (text t) =
+ setuniquepairs (_tcc) (t);
+ if _tcc=0: NoPoints("ccurve", _tcc); fi
+ mkconvex (tens, cyclic, _tcc)
+enddef;
+
+% \end{macrocode}
+%
+% It seemed odd that we had no way for an \MF-savvy user to easily get
+% the standard \mfc{p..q..r} kind of path. For such a simple one,
+% \cs{mfobj} with the explicit path expression would work, but when one
+% has to add a tension to it, it is nice to have an abbreviation. That's
+% what these are for.
+%
+% \DescribeRoutine{mkbezier}
+% The command \gbc{mkbezier} takes an array argument and produces either
+% an open or cyclic path with a given tension.
+% \DescribeRoutine{bezier}
+% The macro \gbc{bezier} does nothing more than call \gbc{tbezier} with
+% the default tension,
+% \DescribeRoutine{tbezier}
+% which takes a list of points and creates an array for \gbc{mkbezier} to
+% act on.
+% \begin{macrocode}
+vardef mkbezier (expr tens, cyclic) (suffix pts) =
+ settension (_tn) tens; fixtension (_tn);
+ pts1
+ for _i = 2 upto pts: ..tension _tn..pts[_i] endfor
+ if cyclic: ..tension _tn..cycle else: {0,0} fi
+enddef;
+
+def bezier = tbezier (default_tension) enddef;
+vardef tbezier (expr tens, cyclic) (text t) =
+ setpairs (_tbs) (t);
+ if _tbs=0: NoPoints ("bezier", _tbs); fi
+ mkbezier (tens, cyclic) (_tbs)
+enddef;
+
+% \end{macrocode}
+%
+% It also seemed we ought to allow \mfpic{} users to easily reproduce the
+% effect of a sequence of \LaTeX's \cs{qbezier} commands. That's what
+% these next are for.
+%
+% These commands and the various splines below don't use tension as they
+% have their control points explicitly given, not computed from the
+% tension value by \MF. The \gbc{qbezier} command does not produce a
+% smooth path unless the controls are explicitely chosen for that. The
+% spline commands will almost always produce a smooth path.
+%
+% \DescribeRoutine{mkqbezier}
+% \gbc{mkqbezier} requires an even number of points for a cyclic path,
+% an odd number for a noncyclic path. It does not check for this, but
+% the calling macro \gbc{qbezier} does. If the parity is incorrect, it
+% repeats the last point in the list. This has the effect of making
+% the last link a straight line.
+%
+% \DescribeRoutine{qbezier}
+% The \gbc{qbezier} command takes a list of points and creates an array
+% from then before calling \gbc{mkqbezier}.
+%
+% \DescribeRoutine{mkcbezier}
+% This is like \gbc{mkqbezier}, but needs a multiple of 3 for a closed
+% cubic bezier, one more (the endpoint) for an open cubic bezier.
+%
+% \DescribeRoutine{cbezier}
+% Like \gbc{qbezier}, but calls \gbc{mkcbezier}.
+% \begin{macrocode}
+vardef mkqbezier (expr cyclic) (suffix pts) =
+ pts1
+ if pts=1: {0,0}
+ else:
+ for _i = 2 step 2 until pts - 1:
+ ..controls 1/3[pts[_i], pts[_i-1]]
+ and 1/3[pts[_i], pts[_i+1]].. pts[_i+1]
+ endfor
+ if cyclic:
+ ..controls 1/3[ pts[pts], pts[pts - 1] ]
+ and 1/3[ pts[pts], pts1 ]..cycle
+ fi
+ fi
+enddef;
+
+vardef qbezier (expr cyclic) (text t) =
+ setpairs (_qbz) (t);
+ if _qbz=0: NoPoints ("qbezier", _qbz);
+ else:
+ if (cyclic and odd _qbz) or (not cyclic and even _qbz):
+ _qbz[incr _qbz] := _qbz[_qbz-1];
+ fi
+ mkqbezier (cyclic) (_qbz)
+ fi
+enddef;
+
+vardef mkcbezier (expr cyclic) (suffix pts) =
+ pts1
+ if pts=1: {0,0}
+ else:
+ for _i = 1 step 3 until pts - 3:
+ ..controls pts[_i+1] and pts[_i+2] .. pts[_i+3]
+ endfor
+ if cyclic:
+ ..controls pts[pts - 1] and pts[pts]..cycle
+ fi
+ fi
+enddef;
+
+vardef cbezier (expr cyclic) (text t) =
+ setpairs (_cbz) (t);
+ if _cbz=0: NoPoints ("qbezier", _cbz);
+ else:
+ % Need 0 mod 3 for cyclic, otherwise 1 mod 3
+ setnumeric (_mdt) _cbz mod 3;
+ if cyclic:
+ if _mdt <> 0: _cbz[incr _cbz] := _cbz[_cbz-1]; fi
+ if _mdt = 1 : _cbz[incr _cbz] := _cbz1; fi
+ else: % need 1 more, duplicate next to last
+ if _mdt = 0:
+ _cbz := _cbz + 1;
+ _cbz[_cbz] := _cbz[_cbz-1];
+ _cbz[_cbz-1] := _cbz[_cbz-2];
+ fi
+ if _mdt = 2: % need 2 more, duplicate last 2.
+ _cbz := _cbz + 2; % add 2 slots
+ _cbz[_cbz] := _cbz[_cbz-2]; % fill them
+ _cbz[_cbz-1] := _cbz[_cbz-2]; % with last node
+ _cbz[_cbz-2] := _cbz[_cbz-3]; % orig last slot = orig previous.
+ fi
+ fi
+ mkcbezier (cyclic) (_cbz)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% When calling \gbc{curve} or \gbc{tcurve} there can be a problem
+% with the resulting path: even with high tension one is not guaranteed
+% that a sequence of points with increasing $x$-coordinate will produce a
+% path with increasing $x$-coordinate. The \gbc{fcnspline} command will do
+% what we want, but we have no control over the path, apart from the
+% equations at the ends.
+%
+% The requirement to guarantee that a path have increasing $x$-coordinates
+% is that the control points of the segment connecting
+% $(x\sb{j}, y\sb{j})$ to the next $(x\sb{j+1}, y\sb{j+1})$ have their
+% $x$-part in the interval $x\sb{j} < x < x\sb{j+1}$.
+%
+% Therefore, if we wish to plot a curve connecting points with increasing
+% $x$-coordinates and believe that the resulting path should be the graph
+% of a function, we pretty much have to select the control points
+% ourselves. By default we choose the two controls so the \mfc{xpart}s
+% divide the $x$-interval into three equal parts. This makes the B\'ezier
+% $f(t)$ linear in the $x$-part and so has the added `advantage' that in
+% each segment, $y$ is a cubic function of $x$. It is not a spline, as
+% the computation of the controls uses only the two nearest points, plus
+% we allow them to be modified by an additional parameter.
+%
+% Another concern is what direction to place the controls. In
+% \gbc{mksmooth} we ask the direction at a given point to be the average
+% of the straight line directions to adjacent points. We do the same
+% here, though it is not clear if this is best.
+%
+% Finally, we permit a tension of sorts by dividing the distance to the
+% controls by a parameter normally equal to \gbc{default_tension}.
+%
+% \DescribeRoutine{fcncontrol}
+% This computes the control point for the points on the path, following
+% the above description. If by chance some $x$ interval is zero, we
+% make the controls equal to the nodes, which gives a straight vertical
+% (the $y$ values differ because we use \gbc{setuniquepairs}. This also
+% abandons smoothness there.
+%
+% The method selecting the controls is new with \mfpic{} version 0.8.
+% Following discussions with Stephan Hennig in \texttt{comp.text.tex} I
+% came to the conclusion that the method used ought to satisfy the
+% following: if the data are xscaled or yscaled, the control vectors ought
+% to scale the same way. The current version does that, the previous one
+% did not.
+%
+% \DescribeRoutine{mkfcnpath}
+% This produces the path, calling \gbc{fcncontrol} to produce the controls.
+%
+% \DescribeRoutine{fcncurve}
+% This is the \mfpic{} interface; \gbc{fcncurve} calls \gbc{functioncurve}
+% with the default tension, and
+% \DescribeRoutine{functioncurve}
+% then takes a list of points, converts it to an array, and calls
+% \gbc{mkfcnpath} to build the path.
+% \begin{macrocode}
+vardef fcncontrol (expr ftens, X, Y, Z) =
+ Y if (xpart(Z-Y) <> 0) and (xpart(Y-X) <> 0):
+ + xpart(Z-Y)/3/xpart(Z-X)*(Z - X)/ftens fi
+enddef;
+
+vardef mkfcnpath (expr ftens) (suffix q) =
+ settension (_tn) ftens;
+ if _tn <= 0: _tn := 1; fi
+ for _i = 1 upto q - 1:
+ q[_i]..controls fcncontrol (_tn) (q[_i-1], q[_i], q[_i+1])
+ and fcncontrol (_tn) (q[_i+2], q[_i+1], q[_i])..
+ endfor
+ q[q]{0,0}
+enddef;
+
+def fcncurve = functioncurve (default_tension) enddef;
+def tfcncurve = functioncurve enddef;
+vardef functioncurve (expr ftens) (text t) =
+ settension (_ftens) ftens; if _ftens < 1/3: _ftens := 1/3; fi
+ setuniquepairs (_fc) (t);
+ if _fc=0: NoPoints ("functioncurve", _fc); fi
+ if _fc > 1: _fc0 := _fc1; _fc[_fc+1] := _fc[_fc]; fi
+ mkfcnpath (_ftens) (_fc)
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Splines with explicit controls}\label{splines}
+%
+% For these quadratic B-splines, a list of pairs representing the control
+% points must be given. The nodes of the path and the cubic Bezi\'er
+% controls required to produce a quadratic B-spline are computed. The
+% nodes are just half way between the one control point and the next.
+%
+% \DescribeRoutine{openqbs}
+% For simplicity, the list is converted to an array \gbc{_oq} first. In
+% the closed version
+% \DescribeRoutine{closedqbs}
+% additional array elements are created at the end, repeating two of the
+% beginning elements. Finally,
+% \DescribeRoutine{mkqbs}
+% \gbc{mkqbs} is called. This draws an open spline based on the points in
+% an array \gbc{b}. The additional array elements defined by
+% \gbc{closedqbs} cause the resulting path to end where it began and a
+% simple \mfc{\&cycle} closes it.
+%
+% \DescribeRoutine{qspline}
+% The \mfpic{} commands \cs{qspline} and \cs{closedqspline} now call
+% \gbc{qspline} with appropriate boolean, for consistency with other
+% commands that have the same argument structure. The commands
+% \gbc{openqbs}, and \gbc{closedqbs} are no longer needed, but are kept
+% for backward compatability. The most efficient setup would be to give
+% \gbc{mkqbs} a boolean argument, but that could break old files.
+% \begin{macrocode}
+def openqbs = qspline (false) enddef;
+def closedqbs = qspline (true) enddef;
+
+vardef mkqbs (suffix b) =
+ 0.5[ b1, b2]
+ if b<3: {0,0}
+ else:
+ for _i = 2 upto b-1:
+ ..controls 1/6[ b[_i], b[_i-1] ] and 1/6[ b[_i], b[_i+1] ]..
+ 0.5[ b[_i], b[_i+1] ]
+ endfor
+ fi
+enddef;
+
+vardef qspline (expr cyclic) (text t) =
+ setpairs (_qs) (t);
+ if _qs=0: NoPoints ("qspline", _qs); fi
+ if _qs=1: _qs[incr _qs] := _qs1; fi
+ if cyclic:
+ _qs[incr _qs] := _qs1; _qs[incr _qs] := _qs2;
+ fi
+ mkqbs (_qs) if cyclic: & cycle fi
+enddef;
+
+% \end{macrocode}
+%
+% These cubic B-splines also require a list of `control' points. Each of
+% the points $Q$, combined with the next one $Q'$, determine two more
+% points that divide the segment from $Q$ to $Q'$ into thirds. These new
+% points become the two control points of a \MF{} B\'ezier segment. The
+% nodes of these segments are half way between the second control of one
+% segment and the first control of the next.
+%
+% \DescribeRoutine{mkcbs}
+% The main code is in \gbc{mkcbs}, which results in an open curve. For
+% backward compatibility, the alias
+% \DescribeRoutine{mkopencbs}
+% \gbc{mkopencbs} is supplied.
+%
+% \DescribeRoutine{mkclosedcbs}
+% Earlier versions of \gbc{mkclosedcbs} would partly redefine its suffix
+% parameter (for example, using \gbc{b[incr b]:=b1}. I decided this
+% shouldn't change the array variable (imagine using two such functions on
+% the same array). Now the code has been rearranged so the cubic case is
+% handled just like the quadratic. We retain \gbc{mkclosedcbs} only for
+% backward compatibility.
+%
+% \DescribeRoutine{opencbs}
+% These are the versions taking a list of points instead of an array name.
+% They create a temporary array and call \gbc{mkcbs}, with
+% \DescribeRoutine{closedcbs}
+% \gbc{closedcbs} extending the array, just like the quadratic versions.
+%
+% \DescribeRoutine{cspline}
+% The \mfpic{} commands \cs{cspline} and \cs{closedcspline} now call
+% \gbc{cspline} with appropriate boolean, for consistency with other
+% commands that have the same argument structure. The commands
+% \gbc{mkopencbs}, \gbc{opencbs}, and \gbc{closedcbs} are no longer
+% needed, but are kept for backward compatability. The most efficient
+% setup would be to give \gbc{mkcbs} a boolean argument, but that could
+% break old files.
+% \begin{macrocode}
+vardef mkcbs (suffix b) =
+ (b[1]+4b[2]+b[3])/6
+ if b < 4: {0,0}
+ else:
+ for _i = 3 upto b-1:
+ ..controls 1/3[ b[_i-1], b[_i] ] and 1/3[ b[_i], b[_i-1] ]
+ .. (b[_i-1] + 4b[_i] + b[_i+1])/6
+ endfor
+ fi
+enddef;
+
+def mkopencbs = mkcbs enddef;
+vardef mkclosedcbs (suffix b) =
+ mkcbs (b) & opencbs (b[b-2],b[b-1],b[b], b1, b2, b3) & cycle
+enddef;
+
+def opencbs = cspline (false) enddef;
+def closedcbs = cspline (true) enddef;
+
+vardef cspline (expr cyclic) (text t) =
+ setpairs (_cs) (t);
+ if _cs=0: NoPoints ("cspline", _cs); fi
+ for _idx = _cs upto 2: _cs[incr _cs] := _cs[_idx]; endfor
+ if cyclic:
+ for _idx = 1 upto 3: _cs[incr _cs] := _cs[_idx]; endfor
+ fi
+ mkcbs (_cs) if cyclic: & cycle fi
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Splines with computed controls}\label{computedsplines}
+%
+% A cubic spline through a set of points is a curve obtained by joining
+% each point to the next with a cubic parametrized curve, where adjoining
+% cubics must have matching first and second derivative at their common
+% point. In the previous section's \gbc{mkcbs}, the control points must be
+% supplied, it being up to the user to arrange (if necessary) that the
+% spline produced passes through given points. If, instead, these points
+% are given, it is possible to compute the necessary controls.
+% Unfortunately, the controls are not uniquely determined unless the curve
+% is required to be closed. For open curves, there is need for two
+% additional conditions at the end points. A `relaxed spline' is produced
+% if we require that the second derivative is $0$ at those points.
+%
+% For a closed curve, the equality of the first and second derivatives at
+% the common beginning/ending point gives the needed additional equations.
+%
+% Note that this equates \emph{time} derivatives, so this works best when
+% points are relatively evenly spaced and so the speed is relatively
+% uniform. If points are differently spaced then the relatively slower
+% speed between closely spaced points allows sharper turns without large
+% second derivatives. Curves produced tend to have a more natural look,
+% and relaxed splines are most suitable for smoothing data that is
+% obtained by taking observations at evenly space times. Still, the
+% technique is somewhat unstable when points are closely spaced, for
+% example when a small change in the position of one point can produce a
+% large change in its direction when viewed from another point.
+%
+% \DescribeRoutine{init_spline_eqns}
+% In this command we generate the equations common to all cubic
+% splines: the equality of derivatives at all interior points.
+% This command accepts a suffix \gbc{pts}, which is the array of points
+% to be connected. It initializes the variables \gbc{_spl_pre[\,]} and
+% \gbc{_spl_post[\,]} to unknown arrays of pairs. These will hold the
+% control points.
+%
+% \DescribeRoutine{closed_spline_eqns}
+% The next two macros contain the additional equations: for a closed
+% spline these are the same as the interior equation, but at the first and
+% last point in the array.
+% \DescribeRoutine{relaxed_spline_eqns}
+% For relaxed splines they force the second derivative to be 0 at the
+% first and last point.
+%
+% The macro \gbc{mksplinepath} simply assembles the previously computed
+% points and controls into a path.
+%
+% \DescribeRoutine{mkspline}
+% The macro \gbc{mkspline} issues the common equations and then either the
+% closed equations (\gbc{closed = true}) or the relaxed equations
+% (\gbc{closed = false}), before calling \gbc{mksplinepath}.
+%
+% The knowledgeable user can call \gbc{init_spline_eqns}, append any
+% choice of equations for the end segments, and then call
+% \gbc{mksplinepath~(false)} to produce any sort of open spline.
+%
+% \DescribeRoutine{dospline}
+% This version accepts a list of pairs and produces a spline through
+% them. It simply stores the list in an array and calls the appropriate
+% version that operates on an array. This is the command passed by \mfpic{}.
+% \begin{macrocode}
+def init_spline_eqns (suffix pts) =
+ save _spl_pre, _spl_post;
+ pair _spl_pre[], _spl_post[];
+ for j= 2 upto pts - 1:
+ _spl_post[j] + _spl_pre[j] = 2pts[j];
+ _spl_pre[j+1]+2_spl_pre[j] = 2_spl_post[j]+_spl_post[j-1];
+ endfor
+enddef;
+
+def closed_spline_eqns (suffix pts) =
+ _spl_post1 + _spl_pre1 = 2pts1;
+ _spl_post[pts] + _spl_pre[pts] = 2pts[pts];
+ _spl_pre2 + 2_spl_pre1 = 2_spl_post1 + _spl_post[pts];
+ _spl_pre1+2_spl_pre[pts] = 2_spl_post[pts]+_spl_post[pts-1];
+enddef;
+
+def relaxed_spline_eqns (suffix pts) =
+ _spl_pre2 + pts1 = 2_spl_post1;
+ pts[pts] + _spl_post[pts-1] = 2_spl_pre[pts];
+enddef;
+
+vardef mksplinepath (expr closed) (suffix pts) =
+ pts1..controls _spl_post1 and
+ for j = 2 upto pts if not closed: -1 fi:
+ _spl_pre[j]..pts[j]..controls _spl_post[j] and
+ endfor
+ if closed: _spl_pre1..cycle else: _spl_pre[pts]..pts[pts] fi
+enddef;
+
+def mkspline (expr closed) (suffix pts) =
+ init_spline_eqns (pts);
+ if closed: closed_spline_eqns (pts);
+ else: relaxed_spline_eqns (pts);
+ fi
+ mksplinepath (closed) (pts)
+enddef;
+
+vardef dospline (expr closed) (text the_list) =
+ setpairs (_sp) (the_list);
+ if _sp=0: NoPoints ("dospline", _sp); fi
+ if _sp=1: _sp[incr _sp] := _sp1; fi
+ mkspline (closed) (_sp)
+enddef;
+
+% \end{macrocode}
+%
+% The above computations produce a $2$-dimensional spline. A $1$-dimensional
+% cubic spline would be a function $f(t)$ with numeric values rather
+% than pair values. Such are often used to interpolate functions. That is,
+% given pairs $(x\sb j,y\sb{j})$, and assuming they lie on the graph of
+% some function (generally unknown), fill in the graph with $y = f(x)$
+% where $f$ is a cubic function of $x$ in each interval $x\sb j \le x
+% \le x\sb {j+1}$, making sure that the resulting graph is as smooth as
+% possible at the points $(x\sb j, y\sb j)$.
+%
+% The requirements on our $2$-dimensional path are the following:
+% \begin{enumerate}
+% \item The $j$th link should connect $(x\sb{j},y\sb{j})$ to $(x\sb{j+1},
+% y\sb{j+1})$.
+% \item The $x$-part of that link should increase linearly from $x\sb{j}$ to
+% $x\sb{j+1}$ as $t$ goes from $0$ to $1$.
+% \item The $y$-part should be a cubic $y = f(x)$.
+% \item The $x$-derivatives $df/dx$ and $d^2f/dx^2$ should match at the
+% connecting points.
+% \end{enumerate}
+%
+% Two necessary equations for converting between $x$ and $t$ coordinates
+% are:
+% \begin{equation}\label{first}
+% x = x\sb{j} + t \Delta x\sb{j}
+% \end{equation}
+% (where $\Delta x\sb{j} = x\sb{j+1} - x\sb{j}$) and
+% \begin{equation}\label{second}
+% \frac{df}{dt} = \frac{dx}{dt}\frac{df}{dx} =
+% \Delta x\sb{j} \frac{df}{dx}.
+% \end{equation}
+% Thus we want to choose controls so that (\ref{first}) is maintained and
+% so that $x$-derivatives match. It turns out that this requires controls
+% at
+% \begin{equation}
+% \begin{array}{c}
+% (x\sb{j}, y\sb{j}) - (\Delta x\sb{j-1}, s\sb{j} \Delta x\sb{j-1})/3\\
+% (x\sb{j}, y\sb{j}) + (\Delta x\sb{j} , s\sb{j} \Delta x\sb{j} )/3
+% \end{array}
+% \end{equation}
+% where $s\sb{j}$ is the slope (derivative) at $x\sb{j}$. This provides
+% matching first derivatives automatically (equation (\ref{second})) and
+% also (\ref{first}). To get matching second derivatives we need the same
+% conditions as in parametric splines. We use these equations simplified to
+% the form:
+% \begin{displaymath}
+% s\sb{j+1} \Delta x\sb{j} - 2s\sb{j} (\Delta x\sb{j} +
+% \Delta x\sb{j-1}) + s\sb{j-1}\Delta x\sb{j-1}
+% = 3y\sb{j+1} - 3y\sb{j-1}.
+% \end{displaymath}
+% There can be almost any equations at the end points. For a relaxed
+% spline we equate the second derivatives to 0. To get a periodic
+% function, we equate the slope and second derivative at beginning to
+% those at the end. This makes it possible to put a shifted copy of the
+% graph with starting point at the end of the original and have the same
+% smoothness at that connection as at the other points.
+%
+% \DescribeRoutine{init_fcnspl_eqns}
+% This declares the temporary arrays \gbc{_dx[\,]} (the set of $dx\sb j$)
+% and \gbc{_sl[\,]} (the desired slopes) and issues the common equations.
+% The parameter \gbc{pts} is the array of $(x,y)$ values.
+%
+% \DescribeRoutine{periodic_fcnspl_eqns}
+% For the periodic case we use \gbc{periodic_fcnspl_eqns} to generate the
+% additional equations and for the
+% \DescribeRoutine{relaxed_fcnspl_eqns}
+% relaxed case we use \gbc{relaxed_fcnspl_eqns}. As before, one can
+% produce custom splines by issuing the common equations and then ones own
+% equations.
+%
+% \DescribeRoutine{mkfcnsplpath}
+% Then we assemble the path from the computed information by calling the
+% command \gbc{mkfcnsplpath}.
+%
+% \DescribeRoutine{mkfcnspline}
+% These commands emits the appropriate equations then assemble the path.
+% The if the first parameter is true it uses the periodic equations,
+% otherwise the relaxed equations.
+%
+% \DescribeRoutine{fcnspline}
+% Finally, this command is the one written by \mfpic{}. It copies a list
+% of pairs into an array and calls the appropriate command to process
+% them.
+% \begin{macrocode}
+def init_fcnspl_eqns (suffix pts) =
+ save _dx, _sl; numeric _dx[], _sl[];
+ _dx1 := xpart (pts2 - pts1);
+ for j = 2 upto pts - 1:
+ _dx[j] := xpart (pts[j+1] - pts[j]);
+ _sl[j + 1]*_dx[j] + _sl[j-1]*_dx[j-1] + 2_sl[j]*(_dx[j] + _dx[j-1])
+ = 3*ypart(pts[j+1] - pts[j-1]);
+ endfor
+enddef;
+
+def periodic_fcnspl_eqns (suffix pts) =
+ _sl1 = _sl[pts];
+ _sl2*_dx1 + 2_sl1*_dx1 + 2_sl[pts]*_dx[pts-1] + _sl[pts-1]*_dx[pts-1]
+ = 3 * ypart (pts[2] - pts[pts-1]);
+enddef;
+
+def relaxed_fcnspl_eqns (suffix pts) =
+ _sl2*_dx1 + 2_sl1*_dx1 = 3 * ypart(pts2 - pts1);
+ _sl[pts-1]*_dx[pts-1] + 2_sl[pts]*_dx[pts-1]
+ = 3 * ypart(pts[pts] - pts[pts-1]);
+enddef;
+
+vardef mkfcnsplpath (suffix pts) =
+ pts1..controls (pts1 + (1, _sl1)/3*_dx1) and
+ for j = 2 upto pts - 1:
+ (pts[j] - (1, _sl[j])/3*_dx[j-1]) ..pts[j]..
+ controls (pts[j] + (1,_sl[j])/3*_dx[j]) and
+ endfor
+ (pts[pts] - (1,_sl[pts])*_dx[pts-1]/3)..pts[pts]
+enddef;
+
+vardef mkfcnspline (expr periodic) (suffix pts) =
+ init_fcnspl_eqns (pts);
+ if periodic: periodic_fcnspl_eqns (pts);
+ else: relaxed_fcnspl_eqns (pts);
+ fi
+ mkfcnsplpath (pts)
+enddef;
+
+vardef fcnspline (expr periodic) (text the_list) =
+ setpairs (_fs) (the_list);
+ if _fs<2:
+ if _fs=0: NoPoints ("fcnspline", _fs); fi
+ onepointpath (false, _fs1)
+ else:
+ mkfcnspline (periodic) (_fs)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Arcs, circles and ellipses}\label{arcs}
+%
+% We have multiple commands that generate circular arcs, differing in
+% how the arc is specified. All are (in part) based on the following
+% \gbc{mkarc}. However, perfectly reasonable arcs can have centers so far
+% away that requiring the center among the parameters can cause numeric
+% overflow.
+%
+% I'd like to use some scheme that avoids this. It is possible, given
+% three reasonably spaced points on an arc with angle less than 90
+% degrees between each, to draw the arc without finding the center.
+% However, I am not sure how to reduce any given format to this
+% information
+%
+% Another problem is that of accuracy. If the angle is small, accuracy is
+% not usually a problem, but if an angle is close to 360, and the
+% endpoints are known, then finding the center (or finding other points on
+% the arc without knowing the center) is unstable.
+%
+% There is really no problem with \gbc{mkarc} itself: if you can express
+% both \gbc{center} and \gbc{begpt} in \MF, then the other values on the
+% arc should normally be no problem. (Of course, if the radius is near
+% \mfc{infinity}, there could be points on the arc with coordinates near
+% \mfc{2infinity}, causing overflow in \MF{}. One hopes this is rare.)
+%
+% Care has been taken that changing the sign of various parameters
+% produces reasonable results. And there should be no more problem for
+% arcs with sweep larger than 360 degrees than with less.
+%
+% \DescribeRoutine{mkarc}
+% This takes the center, starting and ending point (pair expressions) and
+% the angle, and returns the arc defined pretty much the way \file{plain.mf}
+% defines \mfc{quartercircle}.
+%
+% It would be easier to do something like we frequently do with
+% \mfc{fullcircle}: make an arc of unit radius, and then rotate, scale
+% and shift it into place. However, I would like to accomplish at least
+% the following: if an endpoint of the arc is among the parameters, or is
+% straightforwardly implied by them, then the corresponding endpoint of
+% the path created should test equal to that point. Shifting works OK, but
+% scaling and rotating cause roundoff differences.
+%
+% Note that \gbc{mkarc} has parameters that may over-determine the arc.
+% It is only called by arc-making commands that have calculated these
+% parameters and, I hope, ensured they are compatible. \gbc{mkarc}'s job
+% is mainly to ensure that the arc begins at \gbc{begpt} and ends at
+% \gbc{endpt} (exactly). A \gbc{sweep} of $0$ is actually incompatible
+% with any case where \gbc{begpt<>endpt} unless \gbc{center} is
+% literally at $\infty$, but we allow it even though I am pretty sure
+% the other arc commands all filter out that case.
+% \begin{macrocode}
+vardef mkarc (expr center, begpt, endpt, sweep) =
+ if (sweep = 0): begpt--endpt
+ else:
+ setnumeric (n) ceiling (abs(sweep)/45);
+ setpair (d) (begpt - center) rotated (signof (sweep) 90);
+ begpt{d}
+ for j = 1 upto n-1:
+ ..(begpt rotatedabout (center, j/n*sweep)){d rotated (j/n*sweep)}
+ endfor ..endpt{d rotated sweep}
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{arc}
+% The most basic: center of circle, starting point of arc, and angle
+% subtended. Another name for \gbc{arc} is \gbc{arccps}, (``\gbc{cps}'' is
+% for ``center, point, sweep'').
+% \begin{macrocode}
+vardef arc (expr center, begpt, sweep) =
+ if (center = begpt) or (sweep = 0): begpt--begpt
+ else:
+ mkarc (center, begpt, begpt rotatedabout (center, sweep), sweep)
+ fi
+enddef;
+def arccps = arc enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{arcpps}
+% In this form we are given two points and the angle of the arc between
+% them. If the points are equal or the sweep makes the arc undefined, we
+% return a line segment. If the sweep is less than 90 degrees we use the
+% idea from the code of \mfc{quartercircle}, except, when the sweep is
+% greater than 45 degrees we let \MF{} find the midpoint \gbc{m} of the
+% arc. Otherwise, we get the center \gbc{c} of the circle and call
+% \gbc{mkarc}.
+%
+% The code for finding \gbc{c} and \gbc{m} used to be separate commands,
+% \gbc{arccenter} and \gbc{midarc}. However, this is the only place we
+% used them and the several cases that they had to consider are reduced
+% because the \mfc{if} in this command takes care of some of them.
+%
+% The code for finding \gbc{m} uses the fact that the chord and the line
+% from one of its endpoints to the midpoint subtend a circular arc of
+% \gbc{sweep/2} and so the angle between them is half that, \gbc{sweep/4}.
+% The code gets the intersection between the line in that direction and
+% the perpendicular bisector of the chord.
+%
+% We find the center by intersecting two lines. One is the radius from
+% one end of the chord. Then we branch on two cases: if the chord is close
+% to a diameter, use its perpendicular bisector as the other line,
+% otherwise use the radius from the opposite end of the chord. Here
+% \gbc{cd} is a vector in the direction of the chord from \gbc{begpt} to
+% \gbc{endpt}. The angle \gbc{ang} is the amount we have to rotate
+% \gbc{cd} about \gbc{begpt} to make it point toward the center of the
+% circle. This gives the radius mentioned above.
+% \begin{macrocode}
+vardef arcpps (expr begpt, endpt, sweep) =
+ if (begpt = endpt) or (sweep = 0): begpt--endpt
+ else:
+ setpair (cd) unitvector (endpt-begpt);
+ if abs(sweep) <= 45:
+ begpt{cd rotated (-sweep/2)}..endpt{cd rotated (sweep/2)}
+ elseif abs(sweep) <= 90:
+ save m; pair m;
+ m = begpt + whatever*( cd rotated (-sweep/4));
+ m = 0.5[begpt, endpt] + whatever*(cd rotated 90);
+ begpt{cd rotated (-sweep/2)}..m{cd}..endpt{cd rotated (sweep/2)}
+ else:
+ setnumeric (ang) 90 - ((sweep/2) mod 180);
+ if abs(ang) = 90:
+ GBwarn "undefined arc. A line segment will be used instead.";
+ begpt--endpt
+ else:
+ save c; pair c;
+ c = begpt + whatever*(cd rotated ang);
+ c = if abs(ang) < 30:
+ (0.5)[begpt, endpt] + whatever*(cd rotated 90)
+ else:
+ endpt + whatever*(-cd rotated -ang)
+ fi;
+ mkarc (c, begpt, endpt, sweep)
+ fi
+ fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{arcpp}
+% In the macro \gbc{arcpp}, two points and the radius of the circle are
+% given. Alone, this would determine two circles and therefore 4 arcs. We
+% reduce the possibilities to two by assuming the arc is anticlockwise
+% from the first point to the second if \gbc{rad} is positive, clockwise
+% if negative. Then \gbc{arcpp} produces the one that has absolute value
+% no more than 180 degrees if \gbc{small} is true, otherwise the other
+% one.
+% \DescribeRoutine{arcppr}
+% The macro \gbc{arcppr} is just \gbc{arcpp} with the boolean argument
+% \gbc{small} last (for compatibility with previous \mfpic{} versions).
+%
+% The code computes the angle of the arc and calls \gbc{arcpps}. If the
+% radius is not larger than half the distance between the points, we make
+% the angle $\pm 180$, which produces a half circle.
+% \begin{macrocode}
+vardef arcpp (expr small, begpt, endpt, rad) =
+ save full, diam, chord, ang;
+ full := signof (rad) 360;
+ diam := 2rad;
+ chord := abs(endpt-begpt);
+ if chord < abs(diam):
+ ang := if not small: full - fi 2*asin (chord/diam);
+ else: ang := signof (rad) 180;
+ fi
+ arcpps (begpt, endpt, ang)
+enddef;
+def arcppr (expr begpt, endpt, rad, small) =
+ arcpp (small, begpt, endpt, rad)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{arcplr}
+% This one takes the center and polar coordinates of the ends relative to
+% the center. We just call \gbc{mkarc} with the obviously computed
+% endpoints and sweep.
+% \begin{macrocode}
+vardef arcplr (expr center, frtheta, totheta, rad) =
+ if rad = 0: center--center
+ else:
+ mkarc (center, center + rad*dir frtheta,
+ center + rad*dir totheta, totheta - frtheta)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{arcalt}
+% This one is the same as above, but with the same argument order as
+% \gbc{sector}.
+% \begin{macrocode}
+vardef arcalt (expr center, radius, frtheta, totheta) =
+ arcplr (center, frtheta, totheta, radius)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{arcppp}
+% This last one finds the arc connecting three points in the order given.
+% It works by calling \gbc{arcpps} twice, using first the sweep from
+% \gbc{first} to \gbc{second}, and then the sweep from \gbc{second} to
+% \gbc{third}. Each of these is twice the opposite angle of the triangle
+% formed from these points, and calculated by \gbc{cornerangle}.
+% \begin{macrocode}
+vardef arcppp (expr first, second, third) =
+ arcpps (first, second, 2*cornerangle (third, first, second)) &
+ arcpps (second, third, 2*cornerangle (first, second, third))
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{ellipse}
+% We get an ellipse by xscaling and yscaling a unit circle, rotating it
+% and then shifting it into position. All parameters are coordinate
+% independent expressions, with obvious meaning (\gbc{center} is a pair, the
+% rest numeric). \gbc{circle} is similar, but we only scale and shift.
+%
+% If either radius is negative, the sense of the ellipse is reversed and
+% the starting point changes. If both are negative, only the starting
+% point changes.
+% \DescribeRoutine{circle}
+% \gbc{circle} acts like \gbc{ellipse} with both radii the same.
+% \begin{macrocode}
+vardef ellipse (expr center, radx, rady, angle) =
+ fullcircle xscaled (2*radx) yscaled (2*rady) rotated angle
+ shifted center
+enddef;
+
+vardef circle (expr center, rad) =
+ fullcircle scaled (2*rad) shifted center
+enddef;
+
+% \end{macrocode}
+%
+% The next four implement different ways of specifying a circle.
+% \DescribeRoutine{circlecp}
+% The first, \gbc{circlecp}, produces the circle with a given center
+% passing through a given point.
+% \DescribeRoutine{circleppp}
+% The second, \gbc{circleppp}, produces the circle passing through three
+% given points.
+% \DescribeRoutine{circlepps}
+% The third, \gbc{circlepps}, produces the circle passing through two
+% given points in such a way that the arc from the first to the second has
+% a given angle.
+% \DescribeRoutine{circleppr}
+% The fourth, \gbc{circleppr}, produces the circle with the given radius
+% passing through the two points in such a way that the angle from the
+% first point to the second is between $0$ and $180$ degrees if the switch
+% \gbc{small} is true. If \gbc{small} is false, then the clockwise arc
+% from first to second is between $180$ and $360$. If \gbc{rad} is
+% negative, the circles switch and their orientation is reversed.
+% \DescribeRoutine{circlepp}
+% The last, \gbc{circlepp}, is just \gbc{circleppr} with a different order
+% of arguments (for previous \mfpic{} versions).
+%
+% These could be implemented by finding the center and radius and calling
+% \gbc{circle}. However, we call the arc commands so that those points
+% specified in the parameters that lie on the circle will be nodes of the
+% path produced, in the given order.
+% \begin{macrocode}
+vardef circlecp (expr center, point) =
+ mkarc (center, point, point, 360) & cycle
+enddef;
+
+vardef circleppp (expr one, two, three) =
+ arcpps (one, two, 2*cornerangle (three, one, two))
+ & arcpps (two, three, 2*cornerangle (one, two, three))
+ & arcpps (three, one, 2*cornerangle (two, three, one))
+ & cycle
+enddef;
+
+vardef circlepps (expr one, two, sweep) =
+ save ang, full;
+ full := signof (sweep) 360;
+ ang := sweep mod full;
+ arcpps (one, two, ang) & arcpps (two, one, full - ang) & cycle
+enddef;
+
+vardef circlepp (expr small, one, two, rad) =
+ arcpp (small, one, two, rad) & arcpp (not small, two, one, rad)
+ & cycle
+enddef;
+
+def circleppr (expr one, two, rad, small) =
+ circleppr (one, two, rad, small)
+enddef;
+
+% \end{macrocode}
+%
+% Now we implement a different way to specify an ellipse, essentially
+% specifying it by a parallelogram in which it is to be inscribed.
+%
+% \DescribeRoutine{quarterellipse}
+% If an ellipse is inscribed in a parallelogram, tangent to all four
+% sides at the midpoints, this command produces one ``corner'' of that
+% ellipse. The arguments \mfc{A} and \mfc{C} are the midpoints of two
+% adjacent sides and \mfc{B} is the corner between those two sides. This
+% quarter-ellipse starts at \mfc{A} in the direction \mfc{B-A} and ends at
+% \mfc{C} in the direction \mfc{C-B}. As a path \mfc{p} it has two segments, where
+% \mfc{point 0 of p} is \mfc{A}, \mfc{point 2 of p} is \mfc{C}, while
+% \mfc{point 1 of p} lies on the diagonal of the parallelogram through
+% \mfc{B} and has direction there the same as \mfc{C-A}.
+%
+% This was created for the purpose of rounding off corners of a polygonal
+% path.
+% \begin{macrocode}
+vardef quarterellipse(expr A,B,C) =
+ save T_;
+ transform T_;
+ (1,0) transformed T_ = A;
+ (1,1) transformed T_ = B;
+ (0,1) transformed T_ = C;
+ quartercircle scaled 2 transformed T_
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{halfellipse}
+% While \gbc{quarterellipse} is for corners, I don't have much use for
+% \gbc{halfellipse}. Nevertheless, it seems wise (and easy) to provide a
+% definition.
+%
+% The pairs \mfc{A}, \mfc{B}, and \mfc{C} are three midpoints of a
+% parallelogram with \mfc{A} and \mfc{C} on opposite sides and \mfc{B} on
+% a third side. This determines a unique parallelogram, and
+% \gbc{halfellipse} starts at \mfc{A}, passing through \mfc{B} then
+% \mfc{C}, tangent to the respective sides. It makes a point of building
+% it out of two \gbc{quarterellipse}\,s as \mfc{halfcircle} does with
+% \mfc{quartercircle} (at least in \MF{}). We just have to compute their
+% corners.
+% \begin{macrocode}
+vardef halfellipse (expr A,B,C) =
+ save P_; pair P_;
+ P_ = (C - A)/2;
+ quarterellipse (A, B - P_, B) & quarterellipse (B, B + P_, C)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{fullellipse}
+% For \gbc{fullellipse} we specify the center \mfc{C} of the parallelogram
+% and the midpoints \mfc{A} and \mfc{B} of two adjacent sides. We compute
+% the midpoints of the other two sides and draw two \gbc{halfellipse}\,s.
+%
+% Note that the points \gbc{A} and \gbc{B} do not correspond to the
+% usual radii of an ellipse unless the corresponding parallelogram is
+% actually a rectangle (i.e., only if $\angle ACB$ is a right angle).
+% \begin{macrocode}
+vardef fullellipse (expr C, A, B) =
+ save P_; pair P_;
+ P_ := 2[A,C];
+ halfellipse (A,B,P_) & halfellipse (P_,2[B,C],A) & cycle
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{pathcenter}
+% This finds the center of a circle. For other paths, the point found
+% may be meaningless (but it will also obtain the center of an arc or a
+% rectangle). It takes three or four supposedly distinct points on the
+% path and finds the intersection of the perpendicular bisectors of two
+% chords.
+%
+% This code is rather non-robust if applied to an arc that has angular
+% measure very close to either 0 or 360.
+% \begin{macrocode}
+vardef pathcenter expr p =
+ save a, cntr, n; pair cntr, a[];
+ n := length p;
+ a1 = pnt 0 (p);
+ a3 = pnt [n/2] (p);
+ if cycle p:
+ a2 = pnt [ n/4] (p);
+ a4 = pnt [3n/4] (p);
+ else:
+ a2 := a3;
+ a4 := pnt[n] (p);
+ fi
+ cntr = .5[a1, a3] + whatever*((a3 - a1) rotated 90);
+ cntr = .5[a2, a4] + whatever*((a4 - a2) rotated 90);
+ cntr
+enddef;
+
+% \end{macrocode}
+%
+% The next four commands create certain circles associated to
+% triangles. The triangle is specified as a path expression, so they
+% produce results for any path, but make sense only for a cyclic
+% triangular path.
+%
+% \DescribeRoutine{circumcircle}
+% This is just the circle through the three corners.
+%
+% \DescribeRoutine{incircle}
+% The command \gbc{incircle} produces the circle that is tangent to all
+% three sides of the triangle. It makes use of the fact that the two
+% tangent points on the sides adjacent to corner \gbc{A} (for example) are
+% equidistant from \gbc{A}. The three equations then express the fact that
+% the sum of the two distances from the tangent point to the corners on
+% the same side add up to the length of the side.
+%
+% \DescribeRoutine{excircle}
+% In \gbc{excircle}, a corner is given (by number from $0$ to $2$) and the
+% circle is produced that is \emph{outside} the triangle and is tangent to
+% the side opposite the point and tangent to the extensions of the other
+% two sides.
+%
+% \DescribeRoutine{ninepointcircle}
+% The ``nine-point circle'' passes through the following nine points: the
+% midpoint of each side, the point on each side (extended, if necessary)
+% where the altitude from the opposite corner meets it, and the midpoint
+% of the segments connecting each corner to the intersection of the
+% altitudes.
+% \begin{macrocode}
+vardef circumcircle expr t =
+ circleppp (pnt0 (t), pnt1 (t), pnt2 (t))
+enddef;
+
+vardef incircle expr t =
+ save A, B, C; pair A, B, C;
+ A := pnt0 (t);
+ B := pnt1 (t);
+ C := pnt2 (t);
+ save a, b, c, D, E, F;
+ D := abs (B-A) = a + b;
+ E := abs (C-B) = b + c;
+ F := abs (A-C) = a + c;
+ circleppp ((a/D)[A,B], (b/E)[B,C], (c/F)[C,A])
+enddef;
+
+vardef excircle expr n of t =
+ save A, B, C; pair A, B, C;
+ A := pnt[n] (t);
+ B := pnt[n + 1] (t);
+ C := pnt[n + 2] (t);
+ save a, b, c, D, E, F;
+ D := abs (B-A) = a - b;
+ E := abs (C-B) = b + c;
+ F := abs (C-A) = a - c;
+ circleppp ((a/D)[A,B], (b/E)[B,C], (c/F)[A,C])
+enddef;
+
+vardef ninepointcircle expr t =
+ circleppp (medianpt 0 of t, medianpt 1 of t, medianpt 2 of t)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{pshcircle}
+% Here are a couple of circles maybe only I need. They are the
+% pseudohyperbolic circles in the unit disk and upper half-plane.
+% One supplies a point that must be inside the unit circle or above
+% the $x$-axis, and a radius that must be less than $1$. Some degenerate
+% cases will not generate an error. We code this with a boolean that
+% determines whether the disk or the half-plane is to be assumed.
+%
+% If $\alpha=(a,b)$ is the hyperbolic center (the \mfc{ctr} parameter)
+% and $\rho$ is the pseudohyperbolic radius (the \mfc{rad parameter}),
+% the formula for the (Euclidean) center $C$ and radius $R$ of the circle
+% is, for the unit disk:
+% $$
+% C = \frac{ (1 - \rho^2)a }{1 - \rho^2|a|^2},\quad
+% R = \frac{\rho(1 - |a|^2)}{1 - \rho^2|a|^2}
+% $$
+% and for the half-plane:
+% $$
+% C = a + \frac{(1 + \rho^2}{1 - \rho^2}b,\quad
+% R = \frac{2\rho b}{1 - \rho^2}
+% $$
+% \begin{macrocode}
+vardef pshcircle (expr disk, ctr, rad) =
+ if disk:
+ if rad >= 1 :
+ if rad > 1:
+ GBerrmsg ("Impossible radius of pseudohyperbolic circle.")
+ "The radius of a pseudohyperbolic circle can be at most 1.";
+ fi
+ circle ((0,0),1)
+ elseif abs(ctr) >= 1 :
+ if abs(ctr) > 1:
+ GBerrmsg ("Impossible center of pseudohyperbolic circle.")
+ "The center of this pseudohyperbolic circle must be in "
+ & "the unit disk.";
+ fi
+ onepointpath (true,ctr)
+ else:
+ save _r, _dnm;
+ _r := abs(ctr);
+ _dnm := 1 - _r*_r*rad*rad;
+ circle ((1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm)
+ fi
+ else:
+ if rad >= 1 :
+ GBerrmsg ("Impossible radius of pseudohyperbolic circle.")
+ "The radius of a pseudohyperbolic circle must be less than 1.";
+ onepointpath (true,ctr)
+ elseif ypart ctr <= 0:
+ if ypart ctr < 0:
+ GBerrmsg ("Impossible center of pseudohyperbolic circle.")
+ "The center of this pseudohyperbolic circle must be in "
+ & "the upper half-plane.";
+ fi
+ onepointpath (true,ctr)
+ else:
+ save _y, _dnm;
+ _y := ypart ctr;
+ _dnm := 1 - rad*rad;
+ circle ((xpart ctr, (1 + rad*rad)/_dnm * _y), 2rad/_dnm*_y)
+ fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{UHPgeodesic}
+% Here is another arc-producing command. What it produces is the
+% hyperbolic geodesic from one point to another in the \emph{upper
+% half-plane} (UHP). While, theoretically, the points should both be in
+% the UHP, where the hyperbolic geometry is defined, the computations make
+% sense for any pair of points. This could be useful, so I do not enforce
+% this theoretical requirement.
+%
+% Unless two points have the same xpart, there is a unique circle passing
+% through them that meets the $x$-axis at a right angle. The hyperbolic
+% geodesic is an arc of that circle. The path starts at the first listed
+% point and ends at the second. Of the two possible arcs that connect
+% these points, it is the one that doesn't cross the $x$-axis (if there
+% is one). Our computations simply determine the angle of the arc and call
+% \gbc{arcpps}.
+%
+% When the points have the same xpart, the hyperbolic geodesic is the
+% line segment connecting them. When the points have yparts with opposite
+% signs, both arcs cross the $x$-axis. Our code produces the shorter one.
+% If both are $180$ degrees, the one that lies all on the same side of the
+% vertical line through $A$ is produced ($A$ being the first argument).
+%
+% Our method is based on the fact that the reflection $C$ of $A$ (to the
+% other side of the $x$-axis) lies on the circle on which the arc lies.
+% The angle between $A$ and $B$ when viewed from this point is therefore
+% half the angle of the arc. We actually reflect the point farthest from
+% the $x$-axis, as this produces better results.
+%
+% If $A$ and $B$ are on opposite sides of the $x$-axis, then $C$ might
+% coincide with one of the points. In this case $A$ and $B$ would
+% necessarily have equal xparts, a case we will already have processed.
+%
+% If both points lie on the $x$-axis, the computations produce the
+% semicircle from the first to the second in the upper half-plane.
+% \begin{macrocode}
+vardef UHPgeodesic (expr A, B) =
+ if xpart A = xpart B:
+ A--B
+ else:
+ save ang_, C_; pair C_;
+ if abs(ypart A) < abs(ypart B):
+ C_ := conj B;
+ else:
+ C_ := conj A;
+ fi
+ if ypart C_ = 0: % both on x-axis
+ ang_ := anglefromto(up, B - A);
+ else:
+ ang_ := anglefromto(A - C_, B - C_);
+ fi
+ arcpps(A, B, 2ang_)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{UDgeodesic}
+% There is a hyperbolic geometry defined for any simply connected open
+% set. The standard examples of such are the UHP and the unit disk (UD).
+% This next macro produces the geodesic in the UD. Once again it is the
+% arc of a circle and, if the two points do not lie on the same diameter,
+% that circle is the unique one through the two points that meets the
+% boundary of $UD$ at a right angle. When the two points do lie on the
+% same then the geodesic is the straight line connecting the points.
+%
+% The method we use is also based on reflection, where the `reflection' of
+% a point $A$ is given by $C = A/|A|^2$. Computing this can cause overflow
+% if $|A|$ too near $0$. Unfortunately, overflow can also occur if either
+% point lies are outside the UD. That is because, even for modest sizes of
+% $A$ and $B$, the part of the mentioned circle that lies outside the UD
+% can approach \gbc{infinity} in size, making the arc itself impossible to
+% draw. While it is feasible to compute when this will occur, we try to
+% keep it simple by using an approach that is only guaranteed to work when
+% the points lie in the unit disk. A minor modification allows it to to
+% always work when only one of the points is outside. This is because the
+% geodesic is not unique and we can easily choose one that doesn't
+% overflow.
+%
+% We isolate several special cases: if either point is the origin or if
+% the points have the same angle, a straight line is produced. If either
+% point is on the boundary, the computation is based on the fact that the
+% arc is tangent to the direction of that point. In the remaining cases,
+% we compute two angles based on reflecting both points. In the case where
+% both points lie inside or both lie outside, these angles are
+% theoretically equal, but when one point lies inside and the other
+% outside, these angles have opposite signs and their absolute values sum
+% to 360. They correspond to going opposite ways around the circle. We
+% choose the shorter arc as being more ``geodesic-like''.
+%
+% If $C$ is the point being reflected, but it is close enough to the
+% origin to make overflow a significant problem, we rescale the triangle
+% used to find the angle: we compute the angle between $|C|A$ and $|C|B$
+% as viewed from $C/|C|$.
+% \begin{macrocode}
+vardef UDgeodesic (expr A, B) =
+ save a_, b_;
+ a_ := abs(A); b_ = abs(B);
+ if (a_ = 0) or (b_ = 0):
+ A--B
+ elseif angle A = angle B:
+ A--B
+ else: % note: A, B and B-A are all nonzero from this point
+ save ang_;
+ if a_ = 1:
+ ang_ := anglefromto (if b_>1: A else: -A fi, B-A)
+ elseif b_ = 1:
+ ang_ := anglefromto (A-B, if a_>1: B else: -B fi)
+ else:
+ save C_; pair C_;
+ % reflecting A
+ if a_ < eps:
+ C_ := unitvector A;
+ ang_1 := anglefromto(a_*A - C_, a_*B - C_);
+ else:
+ C_ := (1/a_)*unitvector A;
+ ang_1 := anglefromto(A - C_, B - C_);
+ fi
+ % reflecting B
+ if b_ < eps:
+ C_ := unitvector B;
+ ang_2 := anglefromto(b_*A - C_, b_*B - C_);
+ else:
+ C_ := (1/b_)*unitvector B;
+ ang_2 := anglefromto(A - C_, B - C_);
+ fi
+ ang_ := if abs(ang_1) < abs(ang_2): ang_1 else: ang_2 fi;
+ fi
+ arcpps(A, B, 2ang_)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{barycenter}
+% This is the average of the three corners of the triangle, or of all the
+% nodes of any path. If \gbc{t} is an open path with length $n$ and the
+% nodes are $x\sb0$ through $x\sb n$, the barycenter is
+% $$ \frac{1}{n+1}\sum\sb{j=0}\sp{n} x\sb j. $$
+% If \gbc{t} is a cycle with $x\sb n = x\sb0$, then it is
+% $$ \frac{1}{n}\sum\sb{j=0}\sp{n-1} x\sb j. $$
+%
+% For a triangle the barycenter is the intersection of the medians. I
+% don't recall if this is the center of any important circle.
+%
+% The centers of the various circles associated with triangles can be
+% found with \gbc{pathcenter}. Or by intersecting various lines: the
+% \emph{incenter} (center of the inscribed circle)is the intersection of
+% the angle bisectors; the \emph{circumcenter} is the intersection of the
+% prependicular bisectors.
+% \begin{macrocode}
+vardef barycenter expr t =
+ save m; m := length t if not cycle t: + 1 fi;
+ pnt0(t)/m for k = 1 upto m - 1: + pnt[k](t)/m endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{sector}
+% \gbc{sector} produces the closed path consisting of a straight line
+% of length \gbc{rad} from \gbc{center} in the direction \gbc{frtheta},
+% thence along an arc of the circle centered at \gbc{center} to angle
+% \gbc{totheta}, and then along the straight line back to \gbc{center}.
+% \begin{macrocode}
+vardef sector (expr center, rad, frtheta, totheta) =
+ center -- arcalt (center, rad, frtheta, totheta) -- cycle
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mkbrace}
+% Because it doesn't really fit anywhere else, and because it is not
+% really enough to waste a whole subsection on, we put \gbc{mkbrace} here.
+% It is a command to draw a brace (i.e., a ``$\lbrace$'' shape) with its
+% ends and its cusp at given points. The start is at \gbc{S}, the end at
+% \gbc{E} and the cusp at \gbc{C}. \gbc{C} should be close to, but not
+% on, the line from \gbc{S} to \gbc{E}. It should also not be too close to
+% \gbc{S} or \gbc{E}, as we need room to draw two quarter circles on
+% either side of \gbc{C} and one at each of \gbc{S} and \gbc{E}.
+% \begin{macrocode}
+vardef mkbrace (expr S, C, E) =
+ save R_, U_, V_, Z_;
+ pair U_, V_, Z_[];
+ U_ := unitvector (E-S);
+ V_ := U_ rotated 90;
+
+ R_ := 0.5*(C-S) dotprod V_;
+ if R_ = 0:
+ S--C
+ else:
+ if R_ < 0 : V_ := -V_; R_ := -R_; fi
+ V_ := R_*V_; U_ := R_*U_;
+ Z_1 := S + V_ + U_;
+ Z_2 := C - V_ - U_;
+ Z_3 := C - V_ + U_;
+ Z_4 := E + V_ - U_;
+ S{V_}..{U_}Z_1--Z_2{U_}..{V_}C{-V_}..{U_}Z_3--Z_4{U_}..{-V_}E
+ fi
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Plotting of functions}\label{functionplots}
+%
+% In these macros, if the boolean argument \gbc{sm} is true then the
+% path returned will be a B\'ezier, otherwise it will be a polyline. If a
+% \gbc{tens} parameter exists, then the smooth version will have that
+% value of tension, otherwise the value of \gbc{default_tension} is used.
+% These two parameters are simply passed to \gbc{mkpath} by \gbc{mkfcn},
+% and all these macros call \gbc{mkfcn}.
+%
+% \DescribeRoutine{mkfcn}
+% In this command the text parameter \gbc{pf} should be the name of a
+% function of some sort that can take a numeric value in parentheses and
+% return a pair expression. The parameters \gbc{bmin}, \gbc{bmax} and
+% \gbc{bst} determine a sequence of numeric values starting at \gbc{bmin},
+% stepping by \gbc{bst} and ending with \gbc{bmax}. These are fed to
+% \gbc{pf} and the resulting pairs stored in an array. Then either
+% \gbc{mkpoly} or \gbc{mksmooth} is called with the tension \gbc{tens} and
+% the name of the array.
+%
+% For stability, we don't actually step by \gbc{bst}, but round
+% \gbc{(bmax-bmin)/bst} and step that many equal steps. We first adjust
+% the step size upward so the number of steps doesn't exceed
+% \gbc{infinity}. The path is forced to begin at \gbc{pf(bmin)} and
+% end at \gbc{pf(bmax)} even if that is not an integer multiple of
+% \gbc{bst}.
+%
+% \DescribeRoutine{tfcn}
+% The macro \gbc{tfcn} is included for backward compatibility.
+% \begin{macrocode}
+vardef mkfcn (expr sm, tens) (expr bmin, bmax, bst) (text pf) =
+ save _p; pair _p[]; _p := 0;
+ save _dx, _n, _r; numeric _dx, _n, _r;
+ if bmax = bmin: _n := 1;
+ else:
+ _r := bmax - bmin;
+ _dx := max (abs(bst), nottoosmall*abs(_r), epsilon);
+ _n := emax (round(abs(_r)/_dx), 1);
+ fi
+ for _i = 0 upto _n: _p[incr _p] := pf(bmin + _i/_n*_r); endfor
+ mkpath (sm, tens, false, _p)
+enddef;
+
+def tfcn (expr sm) = mkfcn (sm, default_tension) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{parafcn}
+% This is like \gbc{mkfcn}, but the text argument is not a pair
+% valued function, but rather a text parameter containing code that, when
+% copied literally into a vardef, defines a function in which \gbc{t} is
+% the argument, and which returns a pair.
+%
+% Older files are supported with a definition of \gbc{parafcn} that calls
+% \gbc{tparafcn} with \gbc{default_tension}. I should have made this easier
+% by reversing the smoothness and tension arguments, but for backward
+% compatibility I have to leave it thus. Other commands implement \mfpic's
+% tension options: \gbc{function} and \gbc{plrfcn}. They also have forms
+% that accept a tension argument (\gbc{tfunction} and \gbc{tplrfcn}) and
+% call them with the default tension.
+% \begin{macrocode}
+def parafcn (expr sm) = tparafcn (sm, default_tension) enddef;
+vardef tparafcn (expr sm, tn) (expr bmin, bmax, bst) (text pf) =
+ save _fp; vardef _fp (expr t) = pf enddef;
+ mkfcn (sm, tn) (bmin, bmax, bst) (_fp)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{xfcn}
+% This first converts its final argument, which should be a numeric
+% valued function \gbc{f}, to a pair valued function \gbc{(x, f(x))}, then
+% calls \gbc{mkfcn} to return the path that should be the graph of $f(x)$.
+% \begin{macrocode}
+vardef xfcn (expr sm) (expr xmin, xmax, st) (text _fx) =
+ save _fp; vardef _fp (expr _x) = (_x, _fx(_x)) enddef;
+ mkfcn (sm, default_tension) (xmin, xmax, st) (_fp)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{function}
+% This is like \gbc{xfcn} but its last argument, instead of a function,
+% is a text argument that can be copied literally it into a vardef so as
+% to define a pair valued function with a literal \gbc{x} as the argument.
+%
+% \DescribeRoutine{btwnfcn}
+% This is mainly for the sake of simpler \mfpic{} output, implementing
+% the \cs{btwnfcn} macro. One could code it in \mfpic{} macros with two
+% calls to \gbc{function}.
+%
+% \DescribeRoutine{belowfcn}
+% This is essentially \gbc{btwnfcn} with the first function identically
+% 0, but it more efficiently graphs $0$ with one straight line
+% rather than several end-to-end.
+% \begin{macrocode}
+def function (expr sm) = tfunction (sm, default_tension) enddef;
+vardef tfunction (expr sm, tens, xmin, xmax, st) (text _fx) =
+ save _fp; vardef _fp (expr x) = (x, _fx) enddef;
+ mkfcn (sm, tens) (xmin, xmax, st) (_fp)
+enddef;
+
+def btwnfcn (expr sm) = tbtwnfcn (sm, default_tension) enddef;
+vardef tbtwnfcn (expr sm, tn, xlo, xhi, st)(text _fx)(text _gx) =
+ tfunction (sm, tn) (xlo, xhi, st) (_fx) --
+ ( reverse tfunction (sm, tn) (xlo, xhi, st) (_gx) ) -- cycle
+enddef;
+
+def belowfcn (expr sm) = tbelowfcn (sm, default_tension) enddef;
+vardef tbelowfcn (expr sm, tn, xlo, xhi, st)(text _fx) =
+ (xlo,0)--(xhi,0)--
+ (reverse tfunction (sm, tn, xlo, xhi, st)(_fx))--cycle
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{rfcn}
+% This takes the name of a function \gbc{f} which is a numeric
+% valued function of a numeric parameter. It interprets it as a polar
+% curve $(\theta, f(\theta))$, converts that to a curve in rectangular
+% coordinates and calls \gbc{mkfcn} on it.
+% \begin{macrocode}
+vardef rfcn (expr sm, tmin, tmax, st) (text ft) =
+ save _fq; vardef _fq (expr t) = (ft(t)) * (dir t) enddef;
+ mkfcn (sm, default_tension) (tmin, tmax, st) (_fq)
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{plrfcn}
+% This is like \gbc{rfcn}, but with a text argument containing code that
+% can be copied literally into a \mfc{vardef} creating a numeric function
+% with a literal \gbc{t} as the parameter (representing $\theta$).
+%
+% \DescribeRoutine{btwnplrfcn}
+% The macro \gbc{btwnplrfcn} is the polar version of \gbc{btwnfcn}.
+% \begin{macrocode}
+def plrfcn (expr sm) = tplrfcn (sm, default_tension) enddef;
+vardef tplrfcn (expr sm, tens, tmin, tmax, st) (text ft) =
+ save _fq; vardef _fq (expr t) = (ft) * (dir t) enddef;
+ mkfcn (sm, tens) (tmin, tmax, st) (_fq)
+enddef;
+
+def btwnplrfcn (expr sm) = tbtwnplrfcn (sm, default_tension) enddef;
+vardef tbtwnplrfcn (expr sm, tn, tlo, thi, st)(text _ft)(text _gt)=
+ tplrfcn (sm, tn, tlo, thi, st) (_ft) --
+ ( reverse tplrfcn (sm, tn, tlo, thi, st) (_gt) ) -- cycle
+enddef;
+
+def plrregion (expr sm) = tplrregion (sm, default_tension) enddef;
+vardef tplrregion (expr sm, tn, tlo, thi, st) (text _ft) =
+ (0,0)--tplrfcn (sm, tn, tlo, thi, st ) (_ft)--cycle
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mklevelset}
+% This command assumes \gbc{inside_levelset} has been defined, which
+% should be a boolean-valued function of two variables. It tries to create
+% a path such that the expression is true inside the path and false
+% outside it. The intended application is to obtain a path surrounding a
+% region like $\lbrace (x,y) \mid F(x,y) > 0 \rbrace$.
+%
+% The parameters are
+% \begin{itemize}
+% \item \gbc{sm}: Boolean, smooth path (true) or polyline.
+% \item \gbc{tens}: Numeric, the tension (if \gbc{sm} is true).
+% \item \gbc{X} and \gbc{Y}: A starting point where \gbc{_inside_}
+% should return true.
+% \item \gbc{t}: Numeric, a step size.
+% \item \gbc{a}, \gbc{b}, \gbc{c}, and \gbc{d}: Numeric, the limits
+% beyond which the search routine will not go. This is needed to
+% get a starting range for the binary chop method of \mfc{solve}.
+% In practice, the extent of the \mfpic{} figure will be used.
+% \end{itemize}
+%
+% We use \mfc{solve} to find the first point $z\sb1$ to the right of the
+% given point that is on the edge of the region. Then we find the first
+% point of intersection between the circle at $z\sb1$ with radius \gbc{t}
+% and the edge of the region. Continue from this new point to the next
+% until (one hopes) we are within a distance \gbc{t} of the first point.
+% The radius \gbc{t} should be in coordinates appropriate for the use:
+% graph coordinates when used in \mfpic{} figures.
+%
+% The tolerance used in the first \mfc{solve} is \gbc{t/50}. In later uses
+% it is an angle parameter and is set to a number of degrees sufficient to
+% give a distance tolerance at least that.
+%
+% If the starting point \gbc{(X,Y)} does not actually satisfy the
+% condition, a one point path is returned.
+% \begin{macrocode}
+numeric tolerancefactor;
+tolerancefactor := .02;
+
+vardef mklevelset (expr sm, tens, X, Y, t, a, b, c, d) =
+ save _inside_;
+ vardef _inside_ (expr U, V) =
+ inside_levelset(U, V) and between(a, b)(U) and between(c, d)(V)
+ enddef;
+ if not _inside_ (X, Y):
+ GBwarn "Invalid seed point for levelset.";
+ pairmax((a,c), pairmin((X,Y), (b,d)))&cycle
+ else:
+ save ls, W, A, B, prev, curr, seed;
+ pair ls[], prev, curr, seed;
+ seed := (X,Y);
+ ls := 0; W := 0;
+
+ save _first_, _next_, get_next;
+ vardef _first_ (expr U) = _inside_ (U, Y) enddef;
+ vardef _next_ (expr ang) =
+ _inside_ (X_curr + t * cosd ang, Y_curr + t * sind ang)
+ enddef;
+ def get_next (expr angA, angB) =
+ X_curr := xpart curr; Y_curr := ypart curr;
+ ls[incr ls] := curr + t * dir (solve _next_ (angA, angB));
+ prev := curr; curr := ls[ls];
+ W := W + anglefromto (prev - seed, curr - seed);
+ enddef;
+
+ interim tolerance := t*tolerancefactor;
+ ls[incr ls] := (solve _first_ (X, b), Y);
+ curr := ls[ls];
+ interim tolerance := radian*tolerancefactor;
+ get_next (180, 0);
+ for n = 3 upto max_points:
+ A := angle (curr - prev);
+ get_next (A + 120, A - 120);
+ exitif ((abs(W) > 180) or (ls > 10))
+ and (abs(ls[ls] - ls1) < 1.2t);
+ endfor
+ mkpath (sm, tens, true) (ls)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{levelset}
+% This is the \mfpic{} interface. It checks the \gbc{t} parameter before
+% passing it to \gbc{mklevelset}, making sure it is not zero, it passes
+% appropriate limits, and defines boolean function \gbc{mklevelset}
+% expects with literal \mfc{x} and \mfc{y} as parameters, using the text
+% parameter \gbc{cond}.
+% \begin{macrocode}
+numeric max_points;
+max_points := 2000;
+
+def levelset (expr s) = tlevelset (s, default_tension) enddef;
+vardef tlevelset (expr smth, tens, seed, seg) (text cond) =
+ save inside_levelset, _t;
+ vardef inside_levelset (expr x, y) = cond enddef;
+ _t := if seg <= 0: emax (xpos-xneg, ypos-yneg)/max_points * 20
+ else: seg fi;
+ mklevelset (smth, tens, xpart seed, ypart seed, _t)
+ (xneg, xpos, yneg, ypos)
+enddef;
+
+% \end{macrocode}
+%
+% Our next set of macros produce approximations to the solutions of
+% differential equations. While we could have several different macros
+% each using a different method (Euler, two-step Runge-Kutta, four-step
+% Runge-Kutta, etc.), our point of view is that we just want to draw a
+% reasonably accurate solution, so we only utilize one method: four-step
+% Runge-Kutta. The variations we allow are the following:
+% \begin{enumerate}
+% \item Drawing the graph of a one-dimensional differential
+% equation,
+% \[ \frac{dy}{dx} = g(x,y)\,.\]
+%
+% \item Drawing the trajectory of a two-dimensional differential
+% equation,
+% \[ \left( \frac{dx}{dt},\frac{dy}{dt} \right) =
+% (f(x,y,t), g(x,y,t))\,.\]
+% \end{enumerate}
+% The first of these is implemented using the second with $f(x,y,t) \equiv
+% 1$ and $g(x,y,t)$ not depending on $t$. The parameters passed include
+% the starting point, the step size, the number of steps and an expression
+% representing the right side of the equation.
+%
+% We do not use exactly the traditional Runge-Kutta method: we use the
+% Runge-Kutta algorithm, but with a variable step size. The time step
+% $\Delta t$ is chosen so that $|\mathbf{F}(x,y,t)|\Delta t$ equals the
+% given step size parameter, and thus the parameter passed is actually a
+% distance step. This makes drawing more stable, especially if the DE is
+% one that produces an infinite path in finite time.
+%
+% This modification is itself unstable if $|\mathbf{F}|$ is very
+% small (and impossible if it is zero), so we never use a $\Delta t$
+% larger than the given step size parameter $\Delta s$. That is, we
+% actually use $\Delta t = \Delta s/\max(1,|\mathbf{F}|)$.
+%
+% As with our other function-like paths, we offer two variants. The basic
+% version has a final text parameter which is the name of a pair-valued
+% function of a numeric (representing $t$) and a pair variable
+% (representing $x$ and $y$). The other version takes a text
+% parameter, which must be a pair-valued expression in \mfc{x}, \mfc{y}
+% and \mfc{t}. This parameter is copied into the definition text of a
+% function and then the first form is called with that function's name.
+%
+% Also like other function-like paths, we offer polygonal or smooth
+% versions controlled by a boolean argument, and the smooth versions make
+% use of a tension parameter.
+% \begin{macrocode}
+def RKIV (expr sm) = tRKIV (sm, default_tension)
+enddef;
+vardef tRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) =
+ save _trj, _ztr, _dz, _ztmp, _ctm;
+ pair _trj[], % The trajectory
+ _ztr, % current point
+ _dz[], % array[4] of displacements
+ _ztmp; % current point for calculating velocity
+%
+ _trj := N+1; % ultimate size of _trj array
+ _trj1 := _ztr := zstart;
+ save _tt, % current time
+ _dt, % current time step
+ _th; % current time plus half a step
+ _tt := 0;
+ for _idx := 2 upto _trj:
+ _dt := ds/emax(1,abs(_RHS_(_tt,_ztr)));
+ _th := _tt + .5_dt;
+ _dz1 := _dt*_RHS_(_tt, _ztr); % displacement for current point
+ _ztmp := _ztr + .5_dz1; % 1st midpoint
+ % use _th instead of twice calculating (_tt + .5_dt)
+ _dz2 := _dt*_RHS_(_th, _ztmp); % displacement for 1st midpoint
+ _ztmp := _ztr + .5_dz2; % 2nd midpoint
+ _dz3 := _dt*_RHS_(_th, _ztmp); % displacement for 2nd midpoint
+ _ztmp := _ztr + _dz3; % temporary end point
+ % get time for next loop now since we need it in the next line:
+ _tt := _tt + _dt;
+ _dz4 := _dt*_RHS_(_tt, _ztmp); % displacement for end point
+ % get next point
+ _ztr := _ztr + (_dz1 + 2_dz2 + 2_dz3 + _dz4)/6;
+ _trj[_idx] := _ztr;
+ endfor
+ mkpath (sm, tens, false, _trj)
+enddef;
+
+def xyRKIV (expr sm) = txyRKIV (sm, default_tension)
+enddef;
+vardef txyRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) =
+ save _fgxy, __fgxy;
+ vardef __fgxy (expr t, x, y) = _RHS_ enddef;
+ vardef _fgxy (expr t, Z) = __fgxy(t, xpart Z, ypart Z) enddef;
+ tRKIV (sm, tens, zstart, ds, N) (_fgxy)
+enddef;
+
+def odeRKIV (expr sm) = todeRKIV (sm, default_tension)
+enddef;
+vardef todeRKIV (expr sm, tens, xstart, ystart, ds, N)
+(text _fxy) =
+ txyRKIV (sm, tens, (xstart, ystart), ds, N) ((1, _fxy))
+enddef;
+
+% \end{macrocode}
+%
+%
+%
+% \section{Modification of Paths}\label{modification}
+%
+%
+% \subsection{Closing a path}\label{closing}
+%
+% In \MF{} one closes a path with any legal path connection between the
+% last point and the keyword \mfc{cycle}. Connecting the last point to the
+% first point is not enough. \Grafbase{} commands provide a few different
+% ways. All the commads take an undelimited path expression as the last
+% parameter and return a cycle (closed path). If the path is already
+% closed, it is returned unchanged.
+%
+% All the closure commands have a version with a tension parameter when
+% that makes sense. Those versions create the join with the supplied
+% tension. The ones where it doesn't make sense are \gbc{lclosed},
+% \gbc{cbclosed} and \gbc{qbclosed}. The first always uses a straight line
+% and the other two require explicit controls.
+%
+% \DescribeRoutine{lclosed}
+% This closes with a line segment. If the first and last point are
+% already equal, we just use the \mfc{\&} path join.
+% \begin{macrocode}
+vardef lclosed expr f =
+ f
+ if not cycle f:
+ if pnt0(f) = pnt[infinity](f): & else: -- fi cycle
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{sclosed}
+% This closes the path in the manner that \gbc{mksmooth} creates a path.
+% This will change the first and last segment of the original path. In
+% particular, if there are fewer than three segments, the whole path can
+% be different.
+% \DescribeRoutine{sclosedt}
+% It has a variant \gbc{sclosedt} that takes a tension argument.
+% \begin{macrocode}
+def sclosed = sclosedt (default_tension) enddef;
+vardef sclosedt (expr t) expr f =
+ if cycle f: f
+ else: save n; n := length f;
+ if n = 0: f&cycle
+ elseif n = 1: pnt0(f)..tension t..pnt1(f)..tension t..cycle
+ else:
+ (pnt0 (f)) { (pnt1(f)) - (pnt[n] (f)) }..tension t
+ ..(subpath (1, n-1) of f)..tension t
+ ..(pnt[n](f)) { pnt0(f) - pnt[n-1](f) }
+ ..tension t..cycle
+ fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{bclosed}
+% This closes with the basic default \MF{} Bezi\'er. It is a smooth
+% closure, but it does not have the same direction at the endpoints
+% that \gbc{mksmooth (true)} would have produced. It has a tense variant
+% \DescribeRoutine{bclosedt}
+% \gbc{bclosedt}
+% \begin{macrocode}
+def bclosed = bclosedt (default_tension) enddef;
+vardef bclosedt (expr t) expr f =
+ f
+ if not cycle f:
+ if pnt0(f) = pnt[infinity](f): & else: ..tension t.. fi cycle
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{uclosed}
+% Same as \gbc{bclosed}. Retained for backward compatibility. There is
+% a tense variant only for
+% \DescribeRoutine{uclosedt}
+% consistency.
+% \begin{macrocode}
+def uclosed = bclosed enddef;
+def uclosedt = bclosedt enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{cbcontrols}
+% This utility is for use in \gbc{cbclosed}. It converts Bezier segment
+% key points of a path \gbc{f}, to cubic B-spline control points stored
+% in an array \gbc{b}. The data needed are the first point and first two
+% control points of a path. It is used twice in \gbc{cbclosed} on a path
+% and on its reverse. The appropriate three points are passed in the array
+% \gbc{t}.
+% The B-spline points needed are \gbc{b1} and \gbc{b4}. The extra two
+% points \gbc{b2} and \gbc{b3} divide the line from \gbc{b1} to \gbc{b4}
+% into thirds and will be turned into Bezier control points of a new path
+% segment.
+% \begin{macrocode}
+def cbcontrols (suffix b, t) =
+ b1 := 2[t3, t2];
+ b2 := 2[t2, t1];
+ b3 := 2[b1, b2];
+ b4 := 2[b2, b3];
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{cbclosed}
+% This closes a path with a cubic B-spline. If the path \gbc{f} had been
+% produced by \gbc{opencbs}, then \gbc{q1} and \gbc{q4} would have been the
+% last two points in the argument list, and \gbc{p4} and \gbc{p1} would
+% have been the first two. We just use them and mimic the effect of
+% \gbc{closedcbs}.
+% \begin{macrocode}
+vardef cbclosed expr f =
+ save n; n := length f;
+ if cycle f: f
+ elseif n = 0: f&cycle
+ else:
+ save p, q, t; pair p[], q[], t[];
+ t1 := pnt0(f); t2 := post0(f); t3 := pre1(f);
+ cbcontrols (p, t); % defines p1 to p4
+ t1 := pnt[n](f); t2 := pre[n](f); t3 := post[n-1](f);
+ cbcontrols (q, t); % defines q1 to q4
+ f..controls q2 and q3..opencbs (q1,q4,p4,p1)
+ ..controls p3 and p2..cycle
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{qbclosed}
+% It seemed wrong to be able to close with a cubic B-spline but not a
+% quadratic B-spline; therefore I have add such a possibility. We
+% calculate B-spline controls \gbc{p[n]} that will agree with those of
+% \gbc{f}, if \gbc{f} had been created as a quadratic B-spline. Note
+% that \gbc{cbclosed} required three \MF{} links to close the curve;
+% \gbc{qbclosed} only requires two (\gbc{mkqbs} on an array of $n$
+% points makes $n-2$ links).
+% \begin{macrocode}
+vardef qbclosed expr f =
+ if cycle f: f
+ else: save n; n := length f;
+ if n = 0: f&cycle
+ else:
+ save p; pair p[]; p := 4;
+ p1 := (3/2)[pnt[n](f), pre[n](f)];
+ p2 := 2[p1, pnt[n](f)];
+ p4 := (3/2)[pnt 0 (f), post0 (f)];
+ p3 := 2[p4, pnt 0 (f)];
+ f & mkqbs (p) & cycle
+ fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{makesector}
+% This makes sense only if the path being modified is an arc. It closes
+% the arc by connecting its ends to the center of the circle, as
+% computed by \gbc{pathcenter}.
+% \begin{macrocode}
+vardef makesector expr p = (pathcenter p)--p--cycle enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{arccomplement}
+% Getting the complement of an arc is easy if the arc is specified by
+% three points. So we just select three points on the arc and do that.
+% The \gbc{setpairs} statement makes \gbc{pp1}, \gbc{pp2} and \gbc{pp3}
+% three points on the arc \gbc{p} in order. The arc we want goes from
+% \gbc{pp3} to \gbc{pp1} with angle twice that of the corner angle at
+% \gbc{pp2}. This function can be applied to an arbitrary path, and its
+% result will be an arc, but not necessarily a meaningful one.
+% \begin{macrocode}
+vardef arccomplement expr p =
+ if cycle p: onepointpath (false, pnt0(p))
+ else:
+ setnumeric (nn) length p;
+ setpairs (pp) (pnt0(p), pnt[.5nn](p), pnt[nn](p));
+ arcpps (pp3,pp1,2*cornerangle(pp2,pp3,pp1))
+ fi
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Trimming a path}\label{trimming}
+%
+% \DescribeRoutine{cutoffbefore}
+% This is a useful utility operation present in \file{plain.mp} (as
+% \mfc{cutbefore}) but missing from \file{plain.mf}. We write a different
+% version for our purposes: it has the syntax of most of our path
+% modification commands, plus the first loop tries to avoid a bug (or
+% perhaps inaccuracy) in \mfc{intersectiontimes} which can return an
+% intersection time in a later segment of \gbc{f} than the first
+% intersection point.
+%
+% \DescribeRoutine{cutoffafter}
+% What it and \gbc{cutoffafter} do is return the second path with the
+% part before\slash after the first path removed.
+% \begin{macrocode}
+%<MF>path cuttings;
+vardef cutoffbefore (expr b) expr f =
+ save t, n; n := length f;
+ if n > 0:
+ for k = 1 upto n:
+ exitif (subpath (0,k) of f) intersects b;
+ endfor
+ if _Xtime < 0:
+ cuttings := pnt0 (f){0,0};
+ f
+ else:
+ cuttings := subpath (0,_Xtime) of f;
+ subpath (_Xtime, n) of f
+ fi
+ else: f
+ fi
+enddef;
+
+vardef cutoffafter (expr b) expr f =
+ setpath (g) cutoffbefore (b) reverse f;
+ cuttings := reverse cuttings;
+ reverse g
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{trimmedpath}
+% This takes two lengths and a path and trims off the ends of the path
+% that lie within the given lengths of the endpoints. The lengths are in
+% device coordinates, the path in graph coordinates.
+% \begin{macrocode}
+vardef trimmedpath (expr btrim, etrim) expr f =
+ save g, h; path g, h;
+ g := invvconv (fullcircle scaled 2btrim) shifted pnt0(f);
+ h := invvconv (fullcircle scaled 2etrim) shifted pnt[length f] (f);
+ cutoffafter (h) cutoffbefore (g) f
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Creating arrows}\label{arrows}
+%
+% First, some better \mfc{direction} commands. They makes use of the fact
+% (easily proved) that a cubic B\'ezier
+% \[
+% z\sb0(1 - t)^3 + 3z\sb1(1-t)^2t + 3z\sb2(1-t)t^2 + z\sb3t^3
+% \]
+% has a tangent at $z\sb0$ equal to the first one of $z\sb{j} -z\sb0$
+% that is nonzero.
+%
+% \gbc{__dir} gets the direction at point 0 for an arbitrary path.
+% \gbc{postdirection}
+% \DescribeRoutine{postdirection}
+% reduces to this case using \mfc{subpath}. If the postdirection is
+% $(0,0)$, that means the path is trivial from that point to the end so we
+% are effectively at an endpoint (noncyclic path) and we use the incoming
+% direction. If that is $(0,0)$, the path is trivial.
+% \DescribeRoutine{predirection}
+% \gbc{predirection} just runs \gbc{postdirection} on the reversed path.
+%
+% \DescribeRoutine{trivial}
+% This returns \mfc{true} if a path has direction vector $(0,0)$ (as
+% determined by \gbc{__dir}).
+% \begin{macrocode}
+vardef predirection@# (expr p) =
+ - postdirection[length p - @#] (reverse p)
+enddef;
+
+vardef postdirection@# (expr p) =
+ save _n; _n := length (p);
+ setpair (v) __dir (subpath (@#, @# + _n) of p);
+ if v = origin:
+ v := - __dir (subpath (@#, @# - _n) of p);
+ fi
+ v
+enddef;
+
+vardef __dir (expr p) =
+ save v, w; pair v, w; w := pnt0 (p);
+ v := origin;
+ for n = 1 upto length (p):
+ v := post[n-1] (p) - w; exitif v <> origin;
+ v := pre [ n ] (p) - w; exitif v <> origin;
+ v := pnt [ n ] (p) - w; exitif v <> origin;
+ endfor
+ sgn v
+enddef;
+
+vardef trivial expr p = (__dir (p) = origin) enddef;
+
+% \end{macrocode}
+%
+% Arrowheads can be just two straight lines at an angle placed on the end
+% of a curve, or it can be a filled triangle. \grafbase{} permits both,
+% but it also allows the two lines (or the corresponding sides of the
+% triangle) to be gracefully concave and tangent to the path at the
+% endpoint of the path. The parameters controlling the shape of the arrowhead
+% are the two numerics \gbc{hdwdr}, the ratio of the length to width of the
+% arrowhead, and \gbc{hdten}, the tension in the two angled curves. By
+% default, one side of an arrowhead is just the \MF{} path
+% \mfc{a..b\marg{\meta{tangent}}}, where \mfc{a} is the base of the
+% arrowhead (calculated from \gbc{hdwdr}) and \gbc{b} is the end of the
+% path and \meta{tangent} is the direction of the path at that
+% point. The curve can be straightened by increasing \gbc{hdten}, the
+% head widened by increasing \gbc{hdwdr}
+%
+% The arrowhead is drawn by drawing two of the curves described above. If
+% \gbc{hfilled} is \mfc{true}, the two base points (\gbc{a} above) are
+% connected and the three sided region filled.
+% \begin{macrocode}
+newinternal hdwdr, hdten;
+boolean hfilled;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{headshape}
+% The following utility not only adjusts the above parameters, but
+% creates the arrowhead paths as it does so. Call it with two pure numbers
+% \gbc{wr} and \gbc{tens} for the \gbc{hdwdr} and \gbc{hdten}, and a
+% boolean \gbc{fil} for \gbc{hfilled}. The paths include two harpoon
+% tips, an arrowhead, and the paths that give regions that will be erased
+% when requested.
+% \begin{macrocode}
+def headshape (expr wr, tens, fil) =
+ interim hdwdr := wr;
+ interim hdten := if tens>0: tens else: default_tension fi;
+ if hdten < .75: hdten := .75; fi
+ setboolean (hfilled) fil;
+ mkheadpaths;
+enddef;
+def mkheadpaths =
+ save Arrowhead, Leftharpoon, Rightharpoon;
+ path Arrowhead, Leftharpoon, Rightharpoon,
+ Arrowhead.clear, Leftharpoon.clear, Rightharpoon.clear;
+ Rightharpoon := (0,0){down}..tension hdten..(.5hdwdr,-1);
+ Rightharpoon.clear := Rightharpoon--(.5hdwdr,0)--cycle;
+ Leftharpoon := (reverse Rightharpoon) xscaled -1;
+ Leftharpoon.clear := (reverse Rightharpoon.clear) xscaled -1;
+ Arrowhead := Leftharpoon & Rightharpoon;
+ Arrowhead.clear := Leftharpoon.clear & Rightharpoon.clear & cycle;
+ if hfilled:
+ Arrowhead := Arrowhead--cycle;
+ Rightharpoon := Rightharpoon--(0,-1)--cycle;
+ Leftharpoon := Leftharpoon--(0,-1)--cycle;
+ fi
+enddef;
+headshape (1,1,false);
+
+% \end{macrocode}
+%
+% \DescribeRoutine{ahead}
+% This command draws an arrowhead. Current code for arrows no longer uses
+% it. \gbc{front} and \gbc{back} are in device coordinates. They are the
+% point of the arrowhead (\gbc{front}) and the point such that \gbc{front
+% - back} is as long as the arrowhead and points in the direction of the
+% arrow. We use the ratio \gbc{hwr} to compute the other two corners. So
+% \gbc{side} is the vector from \gbc{back} to one of the corners \gbc{p1},
+% and the other corner is on the other side. \gbc{f} is the path of the
+% arrowhead.
+%
+% If \gbc{filled} is true we close the curve draw it and fill it,
+% otherwise we just draw it. (To only fill it, make the pen width $0$.)
+% \gbc{clr} is the color used to draw or fill it.
+%
+% For backward compatibility we define \gbc{head}. In \MF{} \gbc{head}
+% didn't have a color parameter, while in \MP{} it has always had one,
+% in retrospect, this was not a good idea, and I should have followed
+% the pattern of other macros. However, \gbc{head} was never a user-level
+% macro and it didn't seem to mattered at the time.
+% \begin{macrocode}
+%<MF>def head = ahead (headcolor) enddef;
+%<MP>def head = ahead enddef;
+
+vardef ahead (expr clr, front, back, hwr, tens, filled) =
+ settension (_tn) tens; fixtension (_tn);
+ if front <> back:
+ setpair (side) (hwr/2) * ((front-back) rotated 90);
+ setpath (f) (back + side)..tension _tn..
+ {front-back}front{back-front}..tension _tn..(back - side);
+ if clearhead:
+ safeunfill (back - side)--(front-side)--(front+side)--
+ (back+side) & f & cycle;
+ colorsafedraw (background) (back - side)--(front-side)--
+ (front+side)--(back+side) & f & cycle;
+ fi
+ if filled:
+ f := f--cycle;
+ colorsafefill (clr) f;
+ fi
+ colorsafedraw (clr) f;
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% It is a fact of life that, unless the path to which the head is added is
+% a straight line, the arrowhead may appear to point in the wrong
+% direction. But I know of no automatic way of making it always look
+% correct. Therefore \grafbase{} and \mfpic{} have provided a means to
+% micro-adjust the head.
+%
+% The various arrow creation commands take a path expression \gbc{f} in
+% graph coordinates, puts a head/tail/decoration on it and returns
+% \gbc{f}. There are also four parameters determining (i)~the color,
+% (ii)~the size, (iii)~a rotation adjustment, and (iv)~a position
+% adjustment.
+%
+% \DescribeRoutine{headpath}
+% \RoutineIndex{colorheadpath}
+% \RoutineIndex{headpathx}
+% \RoutineIndex{colorheadpathx}
+% \gbc{headpath} calls \gbc{Gheadpath}, a more general command that takes
+% a boolean expression and a shape (path) suffix as arguments. It
+% supplies \mfc{false} for the boolean and \gbc{Arrowhead} for the shape.
+% The \gbc{headpathx} version differs only in that the boolean is
+% \mfc{true}. The \gbc{color...} versions call \gbc{colorGheadpath} in the
+% same way, but require that a color parameter follow.
+% \begin{macrocode}
+def headpath = Gheadpath (false) (Arrowhead) enddef;
+def headpathx = Gheadpath (true) (Arrowhead) enddef;
+
+def colorheadpath = colorGheadpath (false) (Arrowhead) enddef;
+def colorheadpathx = colorGheadpath (true) (Arrowhead) enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{Gheadpath}
+% \RoutineIndex{colorGheadpath}
+% \RoutineIndex{Gheadpathx}
+% \RoutineIndex{colorGheadpathx}
+% For general arrowhead shapes we require two paths; one giving the shape
+% of the head and the other the shape that is cleared when the boolean
+% parameter \gbc{trim} is true. We pass this information by name with a
+% suffix parameter \gbc{ah} that names the head shape. Then \gbc{ah.clear}
+% names the cleared region. If \gbc{ah} is a cycle, the head is filled,
+% otherwise it is drawn with the current \gbc{drawpen}.
+% If one wants it drawn and center erased, one could place first the
+% solid (filled) version with color \mfc{background}, then the outline
+% (drawn only) version.
+%
+% We also need to know which point on the path is the tip, and
+% \gbc{ah.tip} provides that. If \gbc{ah.clear} is undefined, the clearing
+% is silently skipped. If \gbc{ah.tip} is unknown, it is taken to be
+% \mfc{(0,0)}. The head shape is assumed to be initially defined
+% pointing \mfc{up} (to match predefined shapes like \gbc{Triangle} and
+% \gbc{Diamond}).
+%
+% The standard symbols for \gbc{plot} have both the clearing path and
+% the tip defined. Thus one can produce \gbc{Diamond}-tipped arrows. The
+% old arrow heads are given by \gbc{Arrowhead}, which is redefined with
+% every call to \gbc{headshape}.
+%
+% If the \gbc{rot} and \gbc{pos} parameters are zero, the head is placed
+% with its tip at the end of the path, pointing in the direction of the
+% path at that point. Otherwise, the head is rotated around the tip by the
+% amount \gbc{rot} and \emph{then} shifted backward along its new
+% direction by the amount \gbc{pos}.
+%
+% We have a version that takes a color parameter. The simpler version
+% simply calls it with \gbc{clr} equal to \gbc{headcolor}.
+% \begin{macrocode}
+def Gheadpath (expr trim) (suffix ah) =
+ colorGheadpath (trim) (ah) (headcolor)
+enddef;
+vardef colorGheadpath
+(expr trim) (suffix ah) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known ah) and (path ah):
+ convertpath (_g) f;
+ setpair (_P) predirection[length _g] (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ setnumeric (_ang) anglefromto (up, _P);
+ _P := pnt[length _g] (_g) - pos * _P;
+ setpair (_tip) if known ah.tip: ah.tip else: origin fi;
+
+ if trim:
+ if known ah.clear:
+ safeunfill (ah.clear shifted - _tip)
+ scaled sc
+ rotated _ang
+ shifted _P;
+ fi
+ setnumeric (_ys) max(bp, penwd, last_dot_size);
+ safeunfill cut_path
+%<MP> xscaled sc yscaled _ys
+%<MF> xscaled ceiling sc yscaled ceiling _ys
+ rotated _ang shifted _P;
+ fi
+ if cycle ah: colorsafefill else: colorsafedraw fi (clr)
+ (ah shifted -_tip)
+ scaled sc
+ rotated _ang
+ shifted _P;
+ fi
+ fi
+ f
+enddef;
+
+
+% \end{macrocode}
+%
+% \DescribeVariable{cut_path}
+% Additional clearing path, almost the same as plain.mf's \gbc{cut_} (no
+% \gbc{cut_} in plain.mp) but rotated, and scaled differently. The odd
+% scaling is so that if yscaled by the diameter of a dot, and the dot
+% happens to be digitized to a square shape, then the \gbc{cut_path},
+% centered at the center of the dot and rotated 45 degrees, will encompass
+% the whole square (theoretically).
+% \begin{macrocode}
+path cut_path;
+cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{tailpath}
+% \RoutineIndex{colortailpath}
+% The macro \gbc{tailpath} places a tail at the start of a path. It is
+% almost like \gbc{Gheadpath} except there is no clearing done and the tip
+% is at the start (point 0) of the path. Also, the position parameter
+% \gbc{pos} is a forward shift.
+%
+% \DescribeRoutine{midpath}
+% \RoutineIndex{colormidpath}
+% The macro \gbc{midpath} is just like \gbc{tailpath} except it puts the
+% given shape somewhere in the middle of the path. Its position parameter
+% indicates the fraction of the length of the path where the shape is to
+% be placed. This works best in two cases: the shape has a definite
+% direction (like the \gbc{Arrowhead}) and the tip is placed at the given
+% position, or the shape has a center of symmetry and that is placed at
+% the given position. We obtain this in most cases by shifting $(0,0)$ to
+% that position. The standard arrowhead has its tip at this point, and the
+% standard symbols (with the exception of \gbc{Circle}) have their center
+% of symmetry there.
+% \begin{macrocode}
+def tailpath (suffix sh) = colortailpath (sh) (headcolor) enddef;
+vardef colortailpath (suffix sh) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known sh) and (path sh):
+ convertpath (_g) f;
+ setpair(_P) postdirection0 (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ if cycle sh: colorsafefill else: colorsafedraw fi (clr)
+ (sh if known sh.tip: shifted -sh.tip fi)
+ scaled sc
+ rotated anglefromto (up, _P)
+ shifted (pnt0 (_g) + pos * _P);
+ fi
+ fi
+ f
+enddef;
+
+def midpath (suffix sh) = colormidpath (sh) (headcolor) enddef;
+vardef colormidpath (suffix sh) (expr clr, sc, rot, pos) expr f =
+ if (sc <> 0) and (known sh) and (path sh):
+ convertpath (_g) f;
+ setnumeric (_t) pathtime[pos] (_g);
+ setpair (_P) postdirection[_t] (_g);
+ if _P <> origin:
+ _P := _P rotated rot;
+ if cycle sh: colorsafefill else: colorsafedraw fi (clr)
+ sh scaled sc
+ rotated anglefromto (up, _P)
+ shifted (pnt[_t] (_g));
+ fi
+ fi
+ f
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Randomizing a path}
+%
+% In order to randomly change a path, we need to randomly change its
+% points and its controls. If we just apply independent random shifts to
+% every point and control point, it could happen that the direction from a
+% point to a control changes dramatically, introducing a wild change even
+% with a small shift (if point and control were very close to begin with).
+% Also, this method would almost guarantee that a smooth path would
+% randomize into one with all corners. Our solution to these problems is
+% in the following paragraph.
+%
+% If $z\sb0$ and $z\sb3$ are the start and end points, with controls
+% $z\sb1$ and $z\sb2$, then we randomize $z\sb0$ and $z\sb3$ using a
+% random shift with size supplied as a parameter. If there was a
+% preceeding segment, its ending angle and the angle of $z\sb1-z\sb0$
+% determine an angle difference which we multiply by a random factor.
+% This determines the direction to the new control point. If there was no
+% preceeding segment we rotate $z\sb1-z\sb0$ a random amount. Finally we
+% randomly scale $|z\sb1-z\sb0|$.
+%
+% The following `\gbc{deviate}s' are analogous to \MF{}'s
+% \mfc{uniformdeviate}.
+% \DescribeRoutine{signeddeviate}
+% The first, \gbc{signeddeviate X}, produces a random number uniformly
+% distributed in $(-X, X)$. The second,
+% \DescribeRoutine{scaledeviate}
+% \gbc{scaledeviate (W, A)}, produces a pair in a particular direction
+% with length distributed in $(2^{-w}, 2^w)$.
+% \DescribeRoutine{polardeviate}
+% The third, \gbc{polardeviate R} produces a pair whose polar coordinates
+% are separately uniformly distributed, the radius over the interval $(0,
+% R)$ the angle over $(0,360)$.
+% \DescribeRoutine{xydeviate}
+% The last, \gbc{xydeviate (X,Y)}, produces a pair uniformly distributed
+% over the rectangle with corners at $(-X,-Y)$ and $(X,Y)$.
+%
+% \DescribeRoutine{randompair}
+% Finally, \gbc{randompair} runs \gbc{polardeviate} if \gbc{X} is
+% numeric and \gbc{pairdeviate} if it is a pair.
+% \begin{macrocode}
+vardef signeddeviate primary X =
+ (uniformdeviate 1)[-X,X]
+enddef;
+vardef scaledeviate (expr W, A) =
+ 2 ** (signeddeviate W) * dir A
+enddef;
+vardef polardeviate primary R =
+ (uniformdeviate abs(R)) * dir uniformdeviate 360
+enddef;
+vardef xydeviate primary Z =
+ (signeddeviate (xpart Z), signeddeviate (ypart Z))
+enddef;
+
+vardef randompair (expr maxshift) =
+ if numeric maxshift: polardeviate (maxshift)
+ elseif pair maxshift: xydeviate (maxshift)
+ else: (0,0)
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{randompath}
+% The \gbc{randompath} macro returns a path formed from \gbc{f} by
+% shifting each of its point with independent instances of
+% \gbc{randompair (maxshift)}. Its control points are also modified, but
+% the algorithm is not as simple.
+%
+% Let $X$ be one of the points of \gbc{f}, with precontrol $X-U$ and
+% postcontrol $X+V$. We create random $X'$, $U'$ and $V'$ as follows.
+%
+% Let $S$ be the pair that results from \gbc{randompair(maxshift)}, let
+% $w$ be the value of \gbc{weirdness}, let $\eta\sb j(w)$ be the value of
+% the $j$th instance of \gbc{signeddeviate ($w$)}.
+% Then $X' = X + S$, $U'$ is $U$ rotated $\beta=30\eta\sb1(w)$ and scaled
+% $\sigma = 2^{\eta\sb2(w)}$. Let $\alpha$ be the angle between the two
+% vectors $U$ and $V$. Then $V'$ is $\sigma V$ rotated to make the angle
+% between $U'$ and $V'$ equal to $\alpha 2^{\eta\sb3(w)}$.
+% In the new path, the point is $X'$ with precontrol $X'-U'$ and
+% postcontrol $X' + V'$. Note that if the path is smooth at $X$, then
+% $\alpha = 0$ and the new angle is also $0$.
+%
+% \DescribeRoutine{randomlines}
+% This is a simpler version that simply shifts the nodes and connects
+% the results with straight lines. It is intended to be applied to
+% polyline paths.
+%
+% \DescribeRoutine{detrivialized}
+% We start with a routine that strips out trivial segments from a path.
+% This makes some loops a lot easier. It would be weird to differently
+% shift the two (equal) endpoints of a trivial segment.
+% \begin{macrocode}
+vardef detrivialized expr f =
+ save g; path p, g[]; g := 0;
+ for k = 1 upto length f:
+ p := subpath (k-1,k) of f;
+ if not trivial p: g[incr g] := p; fi
+ endfor
+ if g = 0: onepointpath (cycle f, pnt0(f))
+ else: g1 for k = 2 upto g: &g[k] endfor if cycle f: &cycle fi
+ fi
+enddef;
+
+vardef randompath (expr maxshift, weirdness) expr f =
+ save g, n; path g;
+ g := detrivialized f;
+ n := length g;
+ if n = 0:
+ f shifted randompair (maxshift)
+ else:
+ save X, U, V;
+ pair X[], U[], V[];
+ if cycle g: n := n - 1; fi
+ for k = 0 upto n:
+ X[k] := pnt[k](g);
+ U[k] := X[k] - pre[k](g);
+ V[k] := post[k](g) - X[k];
+ endfor
+ save A, B;
+ for k := 0 upto n:
+ X[k] := X[k] shifted randompair (maxshift);
+ A := anglefromto (U[k],V[k]);
+ B := signeddeviate (30weirdness);
+ U[k] := X[k] - (U[k] zscaled scaledeviate (weirdness,B));
+ B := B - A + A * (2 ** signeddeviate weirdness);
+ V[k] := X[k] + (V[k] zscaled scaledeviate (weirdness,B));
+ endfor
+ X0 for k = 1 upto n:
+ .. controls V[k-1] and U[k] .. X[k]
+ endfor
+ if cycle g:
+ .. controls V[n] and U0 .. cycle
+ fi
+ fi
+enddef;
+
+vardef randomlines (expr maxshift) expr f =
+ save g, n; path g;
+ g := detrivialized f;
+ n := length g;
+ if n = 0:
+ f shifted randompair (maxshift)
+ else:
+ if cycle g: n := n - 1; fi
+ (pnt0(g) shifted randompair (maxshift))
+ for k = 1 upto n:
+ -- (pnt[k](g) shifted randompair (maxshift))
+ endfor
+ if cycle g:
+ -- cycle
+ fi
+ fi
+enddef;
+
+% \end{macrocode}
+%
+%
+% \subsection{Interpolating paths}
+%
+% Given two cubic B\'eziers, it is straightforward to create a path that
+% is ``half-way between'' them: just take its control points to be
+% at the midpoint between corresponding control points of the two
+% B\'eziers. Two paths made up of an equal number of B\'ezier are also
+% easily interpolated. However, two paths with different numbers of
+% B\'ezier segments need to be subdivided until they have an equal
+% number.
+%
+% \DescribeRoutine{interpolatedpath}
+% This command accepts a number \gbc{num}, a path or pair \gbc{P} and a
+% path \gbc{Q}. It returns a path which is somewhere ``between'' \gbc{P}
+% and \gbc{Q} if the number is between $0$ and $1$. The case where \gbc{P}
+% or \gbc{Q} is trivial is passed on to another command which is
+% considerably more efficient for that case. In the more general case, the
+% paths are rewritten so that they have equal length. For example, if
+% \gbc{P} has length 2 and \gbc{Q} has length 1, then \gbc{Q} is rewritten
+% as\\
+% \indent \gbc{subpath (0,1/2) of Q \& subpath (1/2,1) of Q}\\
+% which follows the same course as \gbc{Q} but has the same number of
+% B\'ezier parts as \gbc{P}.
+%
+% The splitting of \gbc{Q} shown above can, for reasons unknown to me,
+% produce adjacent subpaths that do not always share an endpoint. One
+% would think that \gbc{subpath (s,t) of Q} and
+% \gbc{subpath (t,u) of Q} would obviously end and start, respectively,
+% at \gbc{point t of Q}. Alas, they don't always. Hence, we employ
+% \gbc{force_equal_ends} to to make them equal, shifting their endpoints a
+% microscopic amount.
+%
+% If \gbc{Q} is a cycle we want the returned path to also be a cycle
+% (but not otherwise). This is possible whenever the ends of \gbc{P} are
+% equal.
+% \begin{macrocode}
+vardef interpolatedpath (expr t, P) expr Q =
+ if not path Q:
+ GBerrmsg ("Improper argument to interpolatedpath.")
+ "The last argument to interpolatedpath must be a path.";
+ if pair P: onepointpath(false, P)
+ else:
+ if path P:
+ P
+ else:
+ onepointpath (false, origin)
+ fi
+ fi
+ elseif pair P:
+ interpolated_pair_path (t, cycle Q, P, Q)
+ elseif not path P:
+ GBerrmsg ("Improper argument to interpolatedpath.")
+ "The second argument to interpolatedpath must be a pair "
+ & "or a path.";
+ Q
+ else:
+ if t=0: Q
+ elseif t=1: P
+ else:
+ save P_, Q_; path P_, Q_;
+ P_ := detrivialized P;
+ Q_ := detrivialized Q;
+ if length P_ = 0:
+ interpolated_pair_path (t, cycle Q, pnt0(P_), Q)
+ elseif length Q_ = 0:
+ interpolated_pair_path (t, cycle Q, pnt0(Q_), P)
+ else:
+ save G, H, n, m, k, r;
+ path G[], H[];
+ G := H := 0;
+ n := length P_; m := length Q_;
+ k := gcd(n, m);
+ r := m/k;
+ for I=0 upto n-1:
+ for J=0 upto r-1:
+ G[incr G] := subpath (I+J/r, I+(J+1)/r) of P_;
+ endfor
+ endfor
+ r := n/k;
+ for I=0 upto m-1:
+ for J=0 upto r-1:
+ H[incr H] := subpath (I+J/r, I+(J+1)/r) of Q_;
+ endfor
+ endfor
+ for N = 1 upto G-1:
+ force_equal_ends(G[N], G[N+1]);
+ force_equal_ends(H[N], H[N+1]);
+ endfor
+ interpolated_segment (t, G1, H1)
+ for N = 2 upto G: & interpolated_segment (t, G[N], H[N])
+ endfor if (pnt0(G1)=pnt1(G[G])) and (cycle Q): & cycle fi
+ fi
+ fi
+ fi
+enddef;
+
+% \end{macrocode}
+% \DescribeRoutine{interpolated_pair_path}
+% Since we cannot rely on the cyclicity of \gbc{Q}, we pass a boolean
+% parameter . That is because the second argument here might actually
+% have been the first argument of \gbc{interpolatedpath}.
+% \begin{macrocode}
+vardef interpolated_pair_path (expr t, cyclic, P, Q) =
+ save N; N := length Q;
+ if N=0: onepointpath (cyclic, (t)[pnt0(Q),P])
+ else:
+ (t)[pnt0(Q),P]..controls (t)[post0(Q),P] and
+ for n=1 upto N - 1:
+ (t)[pre[n](Q),P]..(t)[pnt[n](Q),P]..controls (t)[post[n](Q),P]
+ and
+ endfor
+ (t)[pre[N](Q),P].. if cyclic: cycle else: (t)[pnt[N](Q),P] fi
+ fi
+enddef;
+
+vardef interpolated_segment (expr t, S, T) =
+ (t)[ pnt0(S), pnt0(T)]..controls
+ (t)[ post0(S), post0(T)] and (t)[ pre1(S), pre1(T)]..
+ (t)[ pnt1(S), pnt1(T)]
+enddef;
+
+% \end{macrocode}
+%
+% \subsection{Parallelling a path}
+%
+% \DescribeRoutine{parasegment}
+% This creates a path parallel to a given cubic B\'ezier segment \gbc{f}.
+% It should be called by a command (such as \gbc{parapath}) that makes
+% sure \gbc{f} is nontrivial (meaning the directions are non-zero). It
+% splits the segment into subsegments for accuracy. Its arguments are the
+% distance the original path is shifted, the number of subsegments to
+% split into, and the path.
+% \begin{macrocode}
+vardef parasegment (expr d, segs, f) =
+ if d = 0: f
+ else:
+ save u, v, t; pair u[], v[];
+ for n = 0 upto segs:
+ t := n/segs;
+ u[n] := postdirection [t] (f);
+ v[n] := pnt[t] (f) + (u[n] zscaled (0,d));
+ endfor
+ v0{u0}
+ for n = 1 upto segs: ...v[n]{u[n]} endfor
+ fi
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{parapath}
+% Attempt to parallel one path with another at a distance \gbc{d}. The
+% algorithm is as follows:
+% \begin{enumerate}
+% \item Create an array of paths that parallel each segment of \gbc{f}.
+% \item Redo the array by adding a half circle at each end. The purpose
+% of the half circle is to force consecutive elements of the array
+% to intersect (I hope).
+% \item Do something like \mfc{buildcycle}: where consecutive array
+% elements intersect, strip the the elements to the subpaths between
+% intersection points, and join them directly.
+% \item If \gbc{f} is a cycle, process the joining at the endpoints in
+% the same way.
+% \end{enumerate}
+% We use \gbc{force_equal_ends} to force exact equality of endpoints so
+% we can join segments with \mfc{\&}. The reason for prefering the
+% \mfc{\&} join is to permit better performance of macros (such as this
+% one) that take a path apart into segments. If we used `\mfc{..}' instead
+% then the returned path would have a great many added segments, nearly
+% all of which are nearly trivial. For similar reasons we drop trivial
+% segments of \gbc{f}.
+% \begin{macrocode}
+vardef parapath (expr d) expr f =
+ if d = 0:
+ f
+ else:
+ save a, g, h, p, q, s, t, u, v, w;
+ path g[], h, p[], q[];
+ numeric a, s, t;
+ pair u, v, w, w[];
+ s := emax(3, emin(segment_split, ceiling(max_points/5/length f)));
+ p := 0;
+ for i = 1 upto length f:
+ h := subpath (i-1, i) of f;
+ if not trivial h:
+ q[incr p] := h;
+ p[p] := parasegment (d, s, h);
+ fi
+ endfor
+ if p = 0:
+ f
+ else:
+ a := if d>0: - fi 180;
+ h := p1;
+ for i = 1 upto p-1:
+ u := predirection 1 (q[i]);
+ v := postdirection 0 (q[i+1]);
+ w1 := pnt 1 (q[i]) - (u zscaled (0,d));
+ w2 := pnt 0 (q[i+1]) - (v zscaled (0,d));
+ w3 := pnt [infinity] (h);
+ w4 := pnt 0 (p[i+1]);
+ g0 := arcpps(w3, w1, a);
+ g1 := h & g0;
+ g2 := arcpps(w2, w4, a) & p[i+1];
+ if (p[i] & g0) intersects reverse g2:
+ s := length g2 - _Ytime;
+ t := length h - length p[i] + _Xtime;
+ g1 := subpath (0, t) of g1;
+ g2 := subpath (s, length g2) of g2;
+ force_equal_ends (g1, g2);
+ h := g1 & g2;
+ else:
+ h := h .. p[i+1];
+ fi
+ endfor
+
+ if cycle f:
+ u := predirection 1 (q[p]);
+ v := postdirection 0 (q[1]);
+ w1 := pnt 1 (q[p]) - (u zscaled (0,d));
+ w2 := pnt 0 (q[1]) - (v zscaled (0,d));
+ w3 := pnt [infinity] (h);
+ w4 := pnt 0 (p[1]);
+ g3 := arcpps(w3, w1, a);
+ g0 := arcpps(w2, w4, a);
+ g1 := g0 & h & g3;
+ g2 := g0 & p[1];
+ if (p[p] & g3) intersects reverse g2:
+ s := length g2 - _Ytime;
+ t := length g0 + length h - length p[p] + _Xtime;
+ g1 := subpath (s, t) of g1;
+ force_equal_ends (g1, g1);
+ h := g1 & cycle;
+ else:
+ h := h..cycle;
+ fi
+ fi
+ h
+ fi
+ fi
+enddef;
+
+vardef turnangle@# (expr f) =
+ anglefromto(predirection@# (f), postdirection@#(f))
+enddef;
+
+% \end{macrocode}
+%
+%
+% \section{Miscellaneous}\label{misc}
+%
+% \subsection{Implementation of \mfpic{}'s \cs{plotdata} command}%
+% \label{plotdata}
+%
+% In \mfpic, the \cs{plotdata} command draws several curves with one
+% command. The curves are drawn with changeable methods of rendering.
+% There are three schemes. The first draws the curves with different dash
+% patterns. Another scheme is to plot the curves with different symbols.
+% Still another is to use different colors (\MP{} only).
+%
+% We implement the changing of patterns (symbols, colors) by defining
+% arrays of such things and changing the index into the array. For
+% example, when the user has selected dashes, the first curve is
+% \gbc{gendashed} with the pattern \gbc{dashtype0}, the next with
+% \gbc{dashtype1}, etc.
+%
+% \DescribeRoutine{setdatadashes}
+% We have this method for users to select their own dash patterns. The
+% \gbc{setdatadashes} command requires a list of suffixes previously
+% defined by the \gbc{dashpat} command. Since a dash pattern need only
+% be an array, we check if it is one and, if it is, we copy it to the
+% next \gbc{dashtype[n]}. We actually copy it to a temporary array and
+% make sure there are at least two patterns before we overwrite
+% \gbc{dashtype}.
+%
+% \DescribeRoutine{getdashpat}
+% We have removed this mod-ing operation from \TeX, where it is
+% cumbersome, to \MF, where it is trivial.
+% \begin{macrocode}
+def setdatadashes (text lst) =
+ save __type; __type := 0;
+ forsuffixes _itm = lst:
+ if knownnumericarray _itm :
+ copyarray (_itm) (__type[__type]);
+ next __type;
+ else: GBwarn "Improper dash pattern in setdatadashes.";
+ fi
+ endfor
+ if __type > 1:
+ save dashtype; dashtype := __type;
+ for _j = 0 upto dashtype - 1:
+ copyarray (__type[_j]) (dashtype[_j]);
+ endfor
+ else:
+ SetdataWarn "dashes";
+ fi
+enddef;
+def getdashpat expr n = dashtype[n mod dashtype] enddef;
+
+def SetdataWarn expr s =
+ GBwarn "command setdata"& s &"() failed. Previous values retained.";
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{defaultdashes}
+% These are the default dash patterns. Their setting is done by a macro
+% so the user may easily restore them. The spaces are apparently larger
+% than the dashes, but taking the thickness of the pen into account
+% (\mfc{.5bp}) the dashes will appear about \mfc{.5bp} larger than stated
+% and the spaces about \mfc{.5bp} smaller (unless the user inexplicably
+% sets \mfc{linecap} to \mfc{butt}).
+% \begin{macrocode}
+numeric Solid, Simpledash, Simpledot, Dotdash, Dotdashdot, Dotdashdash;
+dashpat (Solid) (0);
+dashpat (Simple_dash) (3bp, 4bp);
+dashpat (Simple_dot) (0, 4bp);
+dashpat (Dot_dash) (0, 4bp, 3bp, 4bp);
+dashpat (Dot_dash_dot) (0, 4bp, 3bp, 4bp, 0, 4bp);
+dashpat (Dot_dash_dash) (0, 4bp, 3bp, 4bp, 3bp, 4bp);
+
+numeric dashtype, dashtype[], dashtype[][];
+def defaultdashes =
+ setdatadashes (Solid, Simple_dash, Simple_dot,
+ Dot_dash, Dot_dash_dot, Dot_dash_dash);
+enddef;
+defaultdashes;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{setdatasymbols}
+% This can be used to define the sequence of point plotting styles for
+% \mfpic's \cs{plotdata} command. It is quite similar to
+% \gbc{setdatadashes} above and \gbc{setdatacolors} below.
+%
+% \DescribeRoutine{getsymbol}
+% This is similar to \gbc{getdashpat}. In fact we could write a
+% single macro to do both, but I think we get a more readable \mfpic{}
+% output file if we have separate commands.
+% \begin{macrocode}
+def setdatasymbols (text lst) =
+ save __type; path __type[];
+ __type := 0;
+ for _itm = lst:
+ if (known _itm) and (path _itm):
+ __type[__type] := _itm;
+ next __type;
+ else:
+ GBwarn "Improper symbol in setdatasymbols().";
+ fi
+ endfor
+ if __type > 1:
+ save pointtype; pointtype := __type;
+ path pointtype[];
+ for _j = 0 upto pointtype - 1:
+ pointtype[_j] := __type[_j];
+ endfor
+ else:
+ SetdataWarn "symbols";
+ fi
+enddef;
+def getsymbol expr n := pointtype[n mod pointtype] enddef;
+
+% \end{macrocode}
+%
+% Before we can set the default symbols we need to define some. They need
+% to be paths. The ones below named with `\gbc{Solid}' are closed paths.
+% Since the drawing commands that use them feed the path to \gbc{setdot},
+% they end up filled if they are cyclic, merely drawn if not.
+%
+% All are intended to have roughly the area (when area makes sense) of a
+% circle with diameter 1. The scaling factors are the square root of the
+% ratios of the areas.
+%
+% Associated with each is a another path with the same basename and the
+% suffix \gbc{clear} and a pair with the suffix \gbc{tip}. Moreover,
+% they are (mostly) symmetric about the $y$-axis pointing (where that
+% makes sense) in the direction \mfc{up}. The purpose of all this is so
+% that they can be plugged into code for adding arrowheads/tails of
+% different shapes.\VariableIndex{Triangle}\VariableIndex{Square}
+% \VariableIndex{Circle}\VariableIndex{Diamond}\VariableIndex{Star}
+% \VariableIndex{Plus}\VariableIndex{Cross}\VariableIndex{Asterisk}
+% \VariableIndex{Crossbar}\VariableIndex{Leftbar}\VariableIndex{Rightbar}
+% \VariableIndex{Righthook}\VariableIndex{Lefthook}
+% \VariableIndex{SolidTriangle}\VariableIndex{SolidSquare}
+% \VariableIndex{SolidCircle}\VariableIndex{SolidDiamond}
+% \VariableIndex{SolidStar}
+% \begin{macrocode}
+def DeclareGBSymbols (text S) =
+ forsuffixes _itm = S:
+ path _itm;
+ path _itm.clear;
+ pair _itm.tip;
+ endfor
+enddef;
+DeclareGBSymbols(
+ Triangle, Square, Circle, Diamond, Star, Plus, Cross,
+ Asterisk, Crossbar, Leftbar, Rightbar, Righthook,
+ Lefthook, SolidTriangle, SolidSquare, SolidCircle,
+ SolidDiamond, SolidStar
+);
+
+vardef undo_cycle expr f = subpath (0, length f) of f enddef;
+
+SolidTriangle := (up--(dir 210)--(dir -30)--cycle) scaled .78;
+Triangle := undo_cycle SolidTriangle;
+
+Triangle.clear := SolidTriangle.clear :=
+ ((dir -30)--(cosd 30,1)--(cosd 210,1)--(dir 210)--up--cycle)
+ scaled .78;
+
+SolidSquare := (up--(-1,1)--(-1,-1)--(1,-1)--(1,1)--cycle) scaled .443;
+Square := undo_cycle SolidSquare;
+
+SolidCircle := fullcircle rotated 90;
+Circle := undo_cycle SolidCircle;
+Circle.clear := SolidCircle.clear :=
+ halfcircle--(-.5,.5)--(.5,.5)--cycle;
+
+SolidDiamond := (up--left--down--right--cycle)
+ scaled .522 yscaled 1.44;
+Diamond := undo_cycle SolidDiamond;
+Diamond.clear := SolidDiamond.clear :=
+ (right--(1,1)--(-1,1)--left--up--cycle) scaled .522 yscaled 1.44;
+
+Plus := ((0,0)--up--down--(0,0)--left--right) scaled .65;
+Plus.clear := (right--(1,1)--(-1,1)--(left)--cycle) scaled .65;
+
+Cross := ((0,0)--(dir 45)--(dir -135)--(0,0)--(dir -45)--(dir 135))
+ scaled .65;
+Cross.clear :=
+ ((0,0)--(dir -45)--dir(45)--(dir 135)--(dir -135)--cycle) scaled .65;
+
+Asterisk := ((0,0)--up--down--(0,0)--(dir 30)--(dir -150)
+ --(0,0)--(dir -30)--(dir 150)) scaled .6;
+Asterisk.clear := ((0,0)--(dir -30)--(cosd 30,1)--(cosd 150,1)
+ --(dir -150)--cycle) scaled .6;
+
+Crossbar := ((0,0)--left--right) scaled .65;
+Crossbar.clear := rect (right,(-1,.5)) scaled .65;
+
+Leftbar := ((0,0)--left);
+Rightbar := ((0,0)--right);
+Leftbar.clear := rect((0,0),(-1,.5));
+Rightbar.clear := rect((0,0),(1,.5));
+
+Righthook := arcpps((0,0),(1,0),180);
+Lefthook := Righthook xscaled -1;
+Righthook.clear := Righthook--cycle;
+Lefthook.clear := Lefthook--cycle;
+
+% \end{macrocode}
+%
+% We do some computations to find the vertices of an n-pointed
+% star. We assume that \mfc{A1} is \mfc{up} and the line from there
+% to \mfc{A[1 + m]} determines one side of the top point of the star.
+% We must have $2 \le {}$\gbc{m}${}\le{}$\gbc{n}${}-2$. The rest of the
+% vertices are determined by symmetry. \gbc{Star} is made with \gbc{n=5}
+% and \gbc{m=2}. We store the points in an array so we can use them for
+% the \gbc{Star.clear} path.
+% \begin{macrocode}
+vardef mkstar (expr n, m) (suffix A) =
+ save ang; ang := 360/n;
+ A1 := up; A3 := up rotated ang;
+ A2 = (whatever)[A1, A1 rotated ( ang*m)];
+ A2 = (whatever)[A3, A3 rotated (-ang*m)];
+ for i = 4 upto 2n:
+ A[i] := A[i-2] rotated ang;
+ endfor
+ A := 2n;
+ mkpoly (true, A)
+enddef;
+
+save _A; pair _A[];
+SolidStar := mkstar (5, 2, _A) scaled .84;
+Star := undo_cycle SolidStar;
+Star.clear := polyline (true)
+ (_A9, _A10, _A1, _A2, _A3, (xpart _A3, 1), (xpart _A9, 1))
+ scaled .84;
+SolidStar.clear := Star.clear;
+
+forsuffixes S =
+ Triangle, Square, Circle, Diamond, Star, Plus, Cross,
+ Asterisk, Crossbar, Leftbar, Rightbar, Righthook,
+ Lefthook, SolidTriangle, SolidSquare, SolidCircle,
+ SolidDiamond, SolidStar :
+ S.tip := point 0 of S;
+endfor
+
+% \end{macrocode}
+%
+% \DescribeRoutine{gcd}
+% I thought I was going to use \gbc{gcd} for the \gbc{mkstar} routine
+% above, but went another way. Still, it might have a future use. Once we
+% have it,
+% \DescribeRoutine{lcm}
+% \gbc{lcm} is a snap. Since \gbc{gcd} always returns a positive result,
+% \gbc{lcm} satisfies the rule for signs of products. Note that these both
+% silently accept noninteger arguments, though the results may not be very
+% meaningful.
+% \begin{macrocode}
+vardef gcd (expr n, m) =
+ save a, b, r;
+ a := emax (abs(m), abs(n));
+ b := emin (abs(m), abs(n));
+ if b > 0:
+ forever:
+ r := a mod b;
+ exitif r < 1;
+ a := b; b := r;
+ endfor
+ b
+ else:
+ a
+ fi
+enddef;
+
+vardef lcm (expr n, m) =
+ n/gcd(n, m)*m
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{defaultsymbols}
+% The command for restoring the default symbols.
+% \begin{macrocode}
+numeric pointtype; path pointtype[];
+def defaultsymbols =
+ setdatasymbols( Circle, Cross, SolidDiamond, Square, Plus,
+ Triangle, SolidCircle, Star, SolidTriangle);
+enddef;
+defaultsymbols;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{setdatacolors}
+% Finally, for \MP, we do a similar pair of commands for setting
+% the colors for the \cs{plotdata} command, and for
+% \DescribeRoutine{getcolor}
+% getting the next one. The odd indirection (\gbc{colortype[]} is an array
+% of strings, the names of variables having color values) is because \MP{}
+% now has three different data types for colors. Arrays must be all one
+% type.
+%
+% \DescribeRoutine{defaultcolors}
+% These default colors were tested on screen and on an inkjet printer.
+% The adjustments away from pure colors is based on a compromise between
+% those experiments.
+% \begin{macrocode}
+%<*MP>
+def setdatacolors (text lst) =
+ setnumeric (__type) 0;
+ % First, just count and store the known colors in the list
+ for _itm = lst:
+ if knowncolor _itm :
+ if __type = 0 : def _datacolors = _itm enddef;
+ else:
+ expandafter def
+ expandafter _datacolors
+ expandafter = _datacolors, _itm enddef;
+ fi
+ next __type;
+ else: GBwarn "Improper color in setdatacolors().";
+ fi
+ endfor
+ if __type > 1:
+ save colortype, _tmpstr;
+ colortype := 0;
+ % colortype[] is an array of strings:
+ string colortype[], _tmpstr;
+ for _itm = _datacolors: %
+ % Each string is the name of some color variable
+ _tmpstr := "colortype_" & GBromannumeral(colortype);
+ setcolor (scantokens(_tmpstr)) _itm;
+ colortype[colortype] := _tmpstr;
+ next colortype;
+ endfor
+ else:
+ SetdataWarn "colors";
+ fi
+enddef;
+def getcolor expr n = (scantokens (colortype[n mod colortype])) enddef;
+
+numeric colortype; string colortype[];
+
+setcolor (dRed) (1, 0, 0);
+setcolor (dBlue) (.2,.2,1);
+setcolor (dOrange) (1,.34,0);
+setcolor (dGreen) (0,.80,0);
+setcolor (dBlack) cmykblack;
+if has_cmyk :
+ setcolor (dCyan) cyan;
+ setcolor (dMagenta) magenta;
+ setcolor (dYellow) yellow;
+else: % rgb colors seem to be lighter than the cmyk equivalents.
+ setcolor (dCyan) cmyk(.85,0,0,.15);
+ setcolor (dMagenta) cmyk(0,.85,0,.15);
+ setcolor (dYellow) cmyk(0,0,.85,.15);
+fi
+def defaultcolors =
+ setdatacolors(dBlack, dRed, dBlue, dOrange,
+ dGreen, dMagenta, dCyan, dYellow);
+enddef;
+defaultcolors;
+
+%</MP>
+% \end{macrocode}
+%
+%
+% \subsection{Pie Charts and Bar Charts}\label{charts}
+%
+% \DescribeRoutine{computepie}
+% The \gbc{computepie} command calculates the wedges of a pie from the text
+% parameter \gbc{data}. It should be a list of positive numerics, and the
+% result will be one wedge for each datum, the area of the wedge being
+% proportional to the corresponding datum. The wedge for each datum has
+% its point at \gbc{cent} and the wedge for the first datum begins at
+% angle \gbc{ang}. Each wedge is clockwise from the preceding one if
+% \gbc{sign = -1}, otherwise anticlockwise. The radius of the pie is
+% \gbc{rad}.
+%
+% \DescribeRoutine{piechart}
+% This calls \gbc{computepie} to calculate the angles and store that in
+% the array \gbc{_dat}, then \gbc{mkpiewedges} creates the actual user
+% level arrays. This separation allows us (in a future enhancement) to
+% easily handle named piecharts, so there can be more than one defined at
+% a time.
+% \begin{macrocode}
+def computepie (suffix dat) (expr sign, ang, cent, rad) (text data) =
+begingroup
+ save _tot, _max, _toobig;
+ _max := 0; dat := 0;
+ for _val = data:
+ dat[incr dat] := _val;
+ _max := emax (_max, _val);
+ endfor
+ if dat=0: GBwarn "piechart attempted with empty list.";
+ _toobig := 1;
+ else:
+ _toobig := infinity/dat;
+ fi
+ if _max > _toobig:
+ for _idx = 1 upto dat:
+ dat[_idx] := dat[_idx]/_toobig;
+ endfor
+ fi
+ for _idx = 2 upto dat:
+ dat[_idx] := dat[_idx - 1] + dat[_idx];
+ endfor
+ _tot := dat[dat];
+ for _idx = dat downto 2:
+ dat[_idx] := ang + sign*dat[_idx-1]/_tot*360;
+ endfor
+ dat1 := ang; dat[dat + 1] := ang + 360sign;
+endgroup
+enddef;
+
+def piechart (expr sign, ang, cent, rad) (text data) =
+ save _dat;
+ computepie (_dat) (sign, ang, cent, rad) (data);
+ mkpiewedges (_dat, cent, rad);
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{mkpiewedges}
+% The wedges (closed sectors) are stored in the array \gbc{piewedge[\,]}
+% with the numeric \gbc{piewedge} holding the number of wedges. The center
+% is saved in \gbc{piecenter}, the directions of the wedges (the bisecting
+% rays) are stored in \gbc{piedirection[\,]}, the starting angles of the
+% wedges in \gbc{pieangle[\,]}
+% \begin{macrocode}
+def mkpiewedges (suffix dat) (expr cent, rad) =
+ numeric piewedge, piedirection, pieangle, pieangle[];
+ pair piecenter, piedirection[];
+ path piewedge[];
+ piecenter := cent;
+ piedirection := pieangle := piewedge := dat;
+ for _idx = 1 upto dat:
+ pieangle[_idx] := dat[_idx];
+ piewedge[_idx] := sector (piecenter, rad, dat[_idx], dat[_idx+1]);
+ piedirection[_idx] := dir(0.5[ dat[_idx], dat[_idx+1] ]);
+ endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{namedpiechart}
+% This is a future enhancement. It takes a suffix, the name of the chart
+% which will be the base name of the various arrays and key values, and
+% will be a numeric equal to the number of wedges. The first part is
+% identical to that of \gbc{piechart} above. Note that some elements
+% of the chart are not (yet) directly accessible. Those needed by mfpic
+% are: the paths, the directions and the center. The rest would be easy
+% to add.
+% \begin{macrocode}
+def namedpiechart (suffix nm) (expr sign, ang, cent, rad) (text data) =
+ save _dat;
+ computepie (_dat) (sign, ang, cent, rad) (data);
+ setnumeric (nm) _dat;
+ pair nm.center, nm.direction[];
+ path nm.wedge[];
+ nm.center := cent;
+ for _idx = 1 upto _dat:
+ nm.wedge[_idx] := sector (cent, rad, _dat[_idx], _dat[_idx+1]);
+ nm.direction[_idx] := dir(0.5[ _dat[_idx], _dat[_idx+1] ]);
+ endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{barchart}
+% I was told that there are better ways (than piecharts) to represent
+% quantitative data. Perhaps bar charts are better. \gbc{barchart}
+% calculates the bars from the text parameter, \gbc{data}. These bars are
+% vertical if \gbc{vert} is true, otherwise horizontal.
+%
+% \gbc{firstbar} is the location (on the appropriate axis) of the start of
+% the first bar. \gbc{sep} is the separation between bar centers. \gbc{r}
+% is the ratio of the width of the bars to their separation.
+%
+% After the calculations, the array of paths \gbc{chartbar[\,]} holds the
+% rectangles, \gbc{barend[\,]} holds their rightmost or topmost
+% coordinates (which is just the items in \gbc{data} or their yparts),
+% \gbc{barbegin[\,]} holds their leftmost or bottommost coordinates (either
+% 0 or the xparts of the data), \gbc{barstart[\,]} holds the appropriate
+% coordinate of the leading edge of the bar, and \gbc{barwd = r*sep}.
+%
+% If the data are pair data, this command uses the xpart as the beginning
+% of the bar and the ypart as the end. Thus Gantt diagrams can be
+% created. We keep \gbc{barlength} for backward compatibility (formerly
+% all data had to be numeric and bars went from 0 to \gbc{barlength[\,]}).
+% \gbc{barlength[\,]} was made available to help place some label or symbol
+% at the end of a bar and existing code might break if we omit it.
+% \begin{macrocode}
+def barchart (expr firstbar, sep, r, vert)(text data) =
+ numeric barbegin, barbegin[],
+ barend, barend[],
+ barlength, barlength[],
+ barstart, barstart[],
+ chartbar, barwd;
+ path chartbar[];
+ chartbar := 0; barwd := r*sep;
+ for _itm = data:
+ barend[incr chartbar]
+ := if pair _itm: ypart _itm else: _itm fi;
+ barbegin[chartbar] := if pair _itm: xpart _itm else: 0 fi;
+ endfor
+ barbegin := barend := barlength := barstart := chartbar;
+ for _nn = 1 upto chartbar:
+ barstart[_nn] := firstbar + sep*(_nn-1);
+ barlength[_nn] := barend[_nn];
+ chartbar[_nn] := rect ((barbegin[_nn], 0), ( barend[_nn], barwd))
+ shifted (0, barstart[_nn]) if vert: xyswap fi;
+ endfor
+enddef;
+
+% \end{macrocode}
+%
+% \DescribeRoutine{namedbarchart}
+% This is a future enhancement. It takes a suffix, the name of the chart,
+% which will be the base name of the path array. Note that the various key
+% elements (ends of the bar, etc.) are not (yet) directly accessible as in
+% the above version, but they would be easy to add.
+% \begin{macrocode}
+def namedbarchart (suffix nm) (expr first, sep, r, vert) (text data) =
+ save nm;
+begingroup
+ save _bb, _ee, _ww;
+ path nm.bar[];
+ nm := 0; _ww := r*sep;
+ for _itm = data:
+ _ee := if pair _itm: ypart _itm else: _itm fi;
+ _bb := if pair _itm: xpart _itm else: 0 fi;
+ nm.bar[incr nm] := rect ((_bb, 0), ( _ee, _ww) )
+ shifted (0, first + sep*(nm-1)) if vert: xyswap fi;
+ endfor
+endgroup
+enddef;
+
+% \end{macrocode}
+%
+%
+%^^A Overlays - taken from MFbook, p 295. (Bruce Leban)
+%
+%
+% \subsection{Overlays}\label{overlays}
+%
+% This final code predates me. When I inherited \mfpic{} it contained no
+% use of \gbc{keepit}. For the \MP{} version I just tried to make sure
+% everything was defined in \MP{} or \file{plain.mp} and otherwise left it
+% alone. One might presumably issue \gbc{keepit} periodically, clearing
+% \mfc{currentpicture} after adding it onto \gbc{totalpicture}. This would
+% save some memory because manipulating \mfc{currentpicture} often
+% requires a couple of copies to be around simultaneously. Right now we
+% treat currentpicture as the place to save things and manipulate local
+% picture variables.
+% \begin{macrocode}
+picture totalpicture;
+boolean totalnull, currentnull;
+def clearit =
+ currentpicture := totalpicture := nullpicture;
+ currentnull := totalnull := true;
+enddef;
+
+def keepit =
+ addto totalpicture also currentpicture;
+%<MF> mono (totalpicture);
+ currentpicture := nullpicture;
+ totalnull := totalnull or currentnull;
+ currentnull := true;
+enddef;
+
+def addto_currentpicture =
+ currentnull := false;
+ addto currentpicture
+enddef;
+
+def mergeit (text do) =
+ if totalnull:
+ do currentpicture
+ elseif currentnull:
+ do totalpicture
+ else:
+ begingroup
+ save _v_; picture _v_;
+ _v_ := currentpicture;
+ addto _v_ also totalpicture;
+ do _v_
+ endgroup
+ fi
+enddef;
+
+% \end{macrocode}
+% This implements \mfpic{}'s \cs{stopshipping} and \cs{resumeshipping}
+% commands. It used to be that those commands wrote a redefinition of
+% \gbc{shipit}, now we write a boolean assignment and the \cs{shipit}
+% command tests it.
+% \begin{macrocode}
+boolean noship; noship := false;
+def shipit = if noship: else: mergeit (shipout) fi enddef;
+
+%<*MF>
+def showit_ = mergeit (show_) enddef;
+def show_ suffix v = display v inwindow currentwindow enddef;
+
+%</MF>
+% \end{macrocode}
+%
+% Here we initialize \gbc{gcode} (which current versions of mfpic do not
+% use) for hacked \mfpic{} files that require it. In \MP{} we load the
+% color definitions. And thats all.
+% \begin{macrocode}
+numeric gcode; gcode := 0;
+
+%<MF>% end grafbase.mf
+%<MP>input dvipsnam.mp;
+%<MP>% end grafbase.mp
+%</MF|MP>
+% \end{macrocode}
+%
+%
+% \subsection{Dvips names for colors}\label{dvipsnam}
+%
+% In order to make \file{dvipsnam.mp} useful outside grafbase, we give
+% here a definition for \gbc{cmyk} when \gbc{grafbaseversion} is unknown.
+% \begin{macrocode}
+%<*dvips>
+if unknown grafbaseversion:
+ if unknown mpversion:
+ let cmykcolor=color;
+ vardef cmyk (expr c, m, y, k) =
+ (max(1-c-k,0), max(1-m-k,0), max(1-y-k,0))
+ enddef;
+ else:
+ vardef cmyk (expr c, m, y, k) = (c, m, y, k) enddef;
+ fi
+fi
+
+% \end{macrocode}
+%
+% The following code was borrowed from the the standard \LaTeX{} graphics
+% package (\file{dvipsname.def} by David Carlisle and Sebastian Rahtz). In
+% fact it was mostly generated automatically by some editor macros that
+% replaced \prog{graphics} package code with the \grafbase{} code.
+%
+%^^A This file may be distributed under the terms of the LaTeX Project Public
+%^^A License, as described in \file{lppl.txt} in the base LaTeX
+%^^A distribution, either version 1.0 or, at your option, any later version.
+%
+% Declare all the dvips color names to be color variables, and define
+% them as in \file{dvipsnam.def}:
+% \begin{macrocode}
+cmykcolor Apricot, Aquamarine, Bittersweet, Black, Blue, BlueGreen,
+BlueViolet, BrickRed, Brown, BurntOrange, CadetBlue, CarnationPink,
+Cerulean, CornflowerBlue, Cyan, Dandelion, DarkOrchid, Emerald,
+ForestGreen, Fuchsia, Goldenrod, Gray, Green, GreenYellow, JungleGreen,
+Lavender, LimeGreen, Magenta, Mahogany, Maroon, Melon, MidnightBlue,
+Mulberry, NavyBlue, OliveGreen, Orange, OrangeRed, Orchid, Peach,
+Periwinkle, PineGreen, Plum, ProcessBlue, Purple, RawSienna, Red,
+RedOrange, RedViolet, Rhodamine, RoyalBlue, RoyalPurple, RubineRed,
+Salmon, SeaGreen, Sepia, SkyBlue, SpringGreen, Tan, TealBlue, Thistle,
+Turquoise, Violet, VioletRed, White, WildStrawberry, Yellow,
+YellowGreen, YellowOrange;
+
+Apricot := cmyk(0,0.32,0.52,0);
+Aquamarine := cmyk(0.82,0,0.30,0);
+Bittersweet := cmyk(0,0.75,1,0.24);
+Black := cmyk(0,0,0,1);
+Blue := cmyk(1,1,0,0);
+BlueGreen := cmyk(0.85,0,0.33,0);
+BlueViolet := cmyk(0.86,0.91,0,0.04);
+BrickRed := cmyk(0,0.89,0.94,0.28);
+Brown := cmyk(0,0.81,1,0.60);
+BurntOrange := cmyk(0,0.51,1,0);
+CadetBlue := cmyk(0.62,0.57,0.23,0);
+CarnationPink := cmyk(0,0.63,0,0);
+Cerulean := cmyk(0.94,0.11,0,0);
+CornflowerBlue := cmyk(0.65,0.13,0,0);
+Cyan := cmyk(1,0,0,0);
+Dandelion := cmyk(0,0.29,0.84,0);
+DarkOrchid := cmyk(0.40,0.80,0.20,0);
+Emerald := cmyk(1,0,0.50,0);
+ForestGreen := cmyk(0.91,0,0.88,0.12);
+Fuchsia := cmyk(0.47,0.91,0,0.08);
+Goldenrod := cmyk(0,0.10,0.84,0);
+Gray := cmyk(0,0,0,0.50);
+Green := cmyk(1,0,1,0);
+GreenYellow := cmyk(0.15,0,0.69,0);
+JungleGreen := cmyk(0.99,0,0.52,0);
+Lavender := cmyk(0,0.48,0,0);
+LimeGreen := cmyk(0.50,0,1,0);
+Magenta := cmyk(0,1,0,0);
+Mahogany := cmyk(0,0.85,0.87,0.35);
+Maroon := cmyk(0,0.87,0.68,0.32);
+Melon := cmyk(0,0.46,0.50,0);
+MidnightBlue := cmyk(0.98,0.13,0,0.43);
+Mulberry := cmyk(0.34,0.90,0,0.02);
+NavyBlue := cmyk(0.94,0.54,0,0);
+OliveGreen := cmyk(0.64,0,0.95,0.40);
+Orange := cmyk(0,0.61,0.87,0);
+OrangeRed := cmyk(0,1,0.50,0);
+Orchid := cmyk(0.32,0.64,0,0);
+Peach := cmyk(0,0.50,0.70,0);
+Periwinkle := cmyk(0.57,0.55,0,0);
+PineGreen := cmyk(0.92,0,0.59,0.25);
+Plum := cmyk(0.50,1,0,0);
+ProcessBlue := cmyk(0.96,0,0,0);
+Purple := cmyk(0.45,0.86,0,0);
+RawSienna := cmyk(0,0.72,1,0.45);
+Red := cmyk(0,1,1,0);
+RedOrange := cmyk(0,0.77,0.87,0);
+RedViolet := cmyk(0.07,0.90,0,0.34);
+Rhodamine := cmyk(0,0.82,0,0);
+RoyalBlue := cmyk(1,0.50,0,0);
+RoyalPurple := cmyk(0.75,0.90,0,0);
+RubineRed := cmyk(0,1,0.13,0);
+Salmon := cmyk(0,0.53,0.38,0);
+SeaGreen := cmyk(0.69,0,0.50,0);
+Sepia := cmyk(0,0.83,1,0.70);
+SkyBlue := cmyk(0.62,0,0.12,0);
+SpringGreen := cmyk(0.26,0,0.76,0);
+Tan := cmyk(0.14,0.42,0.56,0);
+TealBlue := cmyk(0.86,0,0.34,0.02);
+Thistle := cmyk(0.12,0.59,0,0);
+Turquoise := cmyk(0.85,0,0.20,0);
+Violet := cmyk(0.79,0.88,0,0);
+VioletRed := cmyk(0,0.81,0,0);
+White := cmyk(0,0,0,0);
+WildStrawberry := cmyk(0,0.96,0.39,0);
+Yellow := cmyk(0,0,1,0);
+YellowGreen := cmyk(0.44,0,0.74,0);
+YellowOrange := cmyk(0,0.42,1,0);
+
+% End of file `dvipsnam.mp'.
+%</dvips>
+% \end{macrocode}
+% \clearpage
+%\Finale
diff --git a/graphics/mfpic/source/mfpic.dtx b/graphics/mfpic/source/mfpic.dtx
new file mode 100644
index 0000000000..586d051e18
--- /dev/null
+++ b/graphics/mfpic/source/mfpic.dtx
@@ -0,0 +1,6735 @@
+% \iffalse
+% File: mfpic.dtx
+% A part of mfpic 1.10 2012/12/03
+%
+% -------------------------------------------------------------------
+%
+% Copyright 2002--2012, Daniel H. Luecking
+%
+% Mfpic may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License, either version 1.3c of this license or (at
+% your option) any later version. The latest version of this license is in
+% <http://www.latex-project.org/lppl.txt>
+% and version 1.3c or later is part of all distributions of LaTeX version
+% 2008/12/01 or later.
+%
+% Mfpic has maintenance status "author-maintained". The Current Maintainer
+% is Daniel H. Luecking. There are several Base Interpreters: plain TeX, LaTeX,
+% plain Metafont and plain MetaPost.
+%
+%<*driver>
+\ProvidesFile{mfpic.dtx}
+%</driver>
+%<sty>\ProvidesPackage{mfpic}
+%<*sty>
+ [2012/12/03 v1.10. Macros for drawing with Metafont/MetaPost.]%
+%</sty>
+%<*driver>
+\documentclass{ltxdoc}
+
+\addtolength{\textwidth}{.5878pt}
+
+\def\mytt{\upshape\mdseries\ttfamily}
+\renewcommand\marg[1]{{\mytt\{#1\}}}
+\renewcommand\oarg[1]{{\mytt [#1]}}
+\renewcommand\parg[1]{{\mytt (#1)}}
+\renewcommand \arg[1]{{\mytt \##1}}
+\renewcommand\#{\char`\#\relax}
+\renewcommand{\meta}[1]{{$\langle$\rmfamily\itshape#1\/$\rangle$}}
+\newcommand{\mmarg}[1]{\marg{\meta{#1}}}
+\DeclareRobustCommand\cs[1]{{\mytt\char`\\#1}}
+\def\prog#1{{\mdseries\scshape #1}}
+\def\grafbase{\prog{grafbase}}
+\def\Grafbase{\prog{Grafbase}}
+\def\mfpic{\prog{mfpic}}
+\def\Mfpic{\prog{Mfpic}}
+\def\MF{\prog{meta\-font}}
+\def\MP{\prog{meta\-post}}
+\def\CMF{\prog{Meta\-font}}
+\def\CMP{\prog{Meta\-post}}
+\def\opt#1{{\sffamily\upshape#1}}
+\def\mfc#1{{\mytt#1}}
+\let\env\mfc
+\let\file\mfc
+\let\gbc \mfc
+\catcode`\_=12
+\renewcommand\{{\char`\{}
+\renewcommand\}{\char`\}}
+\renewcommand\|{${}\mathrel{|}{}$}
+
+\makeatletter
+\let\HD@SetMacroIndent\@gobble
+\newcommand\bsl{{\mytt\@backslashchar}}
+% Stupid lists!
+\def\@listi{\leftmargin\leftmargini
+ \parsep \z@ \@plus\p@ \@minus\z@
+ \topsep 4\p@ \@plus\p@ \@minus2\p@
+ \itemsep\parsep}
+\let\@listI\@listi \@listi
+\renewcommand\labelitemi{\normalfont\bfseries \textendash}
+\renewcommand\labelitemii{\textasteriskcentered}
+\renewcommand\labelitemiii{\textperiodcentered}
+\leftmargini\parindent
+% Stupid index!
+\def\usage#1{\textrm{#1}}
+\def\index@prologue{\section*{Index}\markboth{Index}{Index}%
+ Numbers refer to the page where the corresponding entry is described.
+}
+\def\IndexParms{%
+ \parindent \z@ \columnsep 15pt
+ \parskip 0pt plus 1pt
+ \rightskip 5pt plus2em \mathsurround \z@
+ \parfillskip-5pt \small
+ % less hanging:
+ \def\@idxitem{\par\hangindent 20pt}%
+ \def\subitem{\@idxitem\hspace*{15pt}}%
+ \def\subsubitem{\@idxitem\hspace*{25pt}}%
+ \def\indexspace{\par\vspace{10pt plus 2pt minus 3pt}}}
+\makeatother
+
+\def\pdfTeX{\textrm{pdf\kern.04em\TeX}}
+\def\pdfLaTeX{\textrm{pdf\kern.06em\LaTeX}}
+\def\ConTeXt{\textrm{Con\kern-.16em\TeX\kern-0.06em t}}
+\def\PiCTeX{\textrm{P\kern-.13em\lower.3ex\hbox{I}C\TeX}}
+
+\title{The \mfpic{} package\thanks{This file has version number
+ \fileversion, last revised \filedate. The code described here
+ was developed by several people, notably Thomas Leathrum,
+ Geoffrey Tobin and Dan Luecking. Dan wrote this documentation.}}
+\author{Dan Luecking}
+\date{\filedate}
+\DisableCrossrefs
+\CodelineIndex
+\AlsoImplementation
+
+\begin{document}
+ \DeleteShortVerb{\|}
+ \DocInput{mfpic.dtx}
+\end{document}
+%</driver>
+%\fi
+% \CheckSum{5188}
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+% \GetFileInfo{mfpic.dtx}
+% \maketitle
+%
+% \begin{abstract}
+% An environment, \env{mfpic}, is defined, within which commands can be
+% used for drawing pictures, especially of mathematical objects and
+% functions. These commands actually write code to an external file to be
+% processed through \MF{} or \MP{} (depending on package options) to
+% produce the picture. The picture is then included on a second pass
+% through \TeX.
+%
+% This file documents the \mfpic{} source code. The user manual for
+% \mfpic{} is distributed as \file{mfpic-doc.pdf}, produced from
+% \file{mfpic-doc.tex}. An introductory guide to \mfpic{} is available
+% in \file{mfpguide.pdf}, produced from \file{mfpguide.tex}
+% \end{abstract}
+%
+% \StopEventually{\PrintIndex}
+% \tableofcontents
+%
+%
+%
+% \section{Introductory setup}\label{intro}
+%
+% \Mfpic{} is designed to work with plain \TeX, \LaTeX, \pdfTeX, and
+% \pdfLaTeX. I consistently use it with eplain and AMS\LaTeX{}
+% without problems. Users have reported succesfully using it with \AmSTeX.
+% It has \emph{not} been successfully used with \ConTeXt.
+%
+% \subsection{Versions numbers, category codes, etc.}\label{category}
+%
+% Almost all the various category code settings we do were prompted by
+% an \mfpic{} user who had sent a bug report and had to send along his
+% modified version of \file{mfpic.tex}. It had been modified so that
+% \cs{message}\,s and \cs{write}\,s would do the right thing in latex
+% files where various punctuation were made active (e.g., with
+% \file{french.sty}).
+%
+% We keep track of version numbers here. We store the version and date
+% in macros and later we write this version information to the
+% output file, The \cs{mfpicversion} is 100 times the numeric part of the
+% version. The output file can compare this number with the corresponding
+% value in \file{grafbase} and detect installations where there is a
+% mismatch.
+% \begin{macrocode}
+%<*tex>
+\ifx\mfpfileversion\UndEfInEd\else\expandafter\endinput\fi%
+{%
+ \catcode\lq\.12 \catcode\lq\/12%
+ \gdef\mfpfileversion{1.10}%
+ \gdef\mfpfiledate{2012/12/03}%
+ \gdef\mfpicversion{110}%
+}%
+% \end{macrocode}
+%
+% A bug in older versions of some support files is triggered by the macro
+% \cs{+}, which is an \cs{outer} macro in plain \TeX. Here we save the
+% current definition and then give it a nonouter meaning.
+% \begin{macrocode}
+\let\mfpsaveplus\+%
+\let\+\tabalign%
+% \end{macrocode}
+%
+% We now get rid of unusually catcoded punctuation, space and EOL.
+% We assume that letters, numbers, `\texttt\bsl', `\texttt\{', `\texttt\}',
+% `\texttt\#' and `\texttt\%' have the usual categories. However, styles
+% (e.g., \prog{french}) that make punctuation active foul up \cs{write}\,s
+% of MF/MP code. This can still occur in user-generated \cs{write}\,s, so
+% maybe some of this code should be added in \cs{mfpic} or \cs{mfsrc}
+% command, too.
+% \begin{macrocode}
+{%
+ \catcode61\space12\relax% 61=equal sign
+ \catcode32=10\relax% 32=space
+ \catcode13=5 % 13=EOL
+ \catcode96=12 % 96=left quote
+ \catcode`\@=11
+ \gdef\MFPsavecodes{%
+ \edef\mfp@restoreNLC{\newlinechar\number\newlinechar\relax}%
+ \edef\mfp@restoreELC{\endlinechar\number\endlinechar\relax}%
+ \edef\mfp@restoreSPA{\catcode32=\number\catcode32\relax}%
+ \edef\mfp@restoreEOL{\catcode13=\number\catcode13\relax}%
+ \edef\mfp@restoreALL{\mfp@restorecode{=}\mfp@restorecode{@}%
+ \mfp@restorecode{$}\mfp@restorecode{:}\mfp@restorecode{;}%
+ \mfp@restorecode{.}\mfp@restorecode{,}\mfp@restorecode{!}%
+ \mfp@restorecode{?}\mfp@restorecode{(}\mfp@restorecode{)}%
+ \mfp@restorecode{[}\mfp@restorecode{]}\mfp@restorecode{<}%
+ \mfp@restorecode{>}\mfp@restorecode{*}\mfp@restorecode{/}%
+ \mfp@restorecode{+}\mfp@restorecode{-}\mfp@restorecode{"}%
+ \mfp@restorecode{'}\mfp@restorecode{_}\mfp@restorecode{`}%
+ \mfp@restoreEOL\mfp@restoreSPA\catcode10=\number\catcode10
+ \mfp@restoreNLC\mfp@restoreELC}}%
+ \gdef\mfp@restorecode#1{\catcode`\string#1=\number\catcode`#1\relax}%
+ \ifx\@makeother\UndEfInEd \gdef\@makeother#1{\catcode`#1=12\relax}\fi
+ \gdef\MFPsanitize{\endlinechar13 \newlinechar10
+ \catcode10=12 \catcode13=5 \catcode`\$=3 \catcode`\ =10
+ \@makeother\:\@makeother\;\@makeother\.\@makeother\,%
+ \@makeother\!\@makeother\?\@makeother\(\@makeother\)%
+ \@makeother\[\@makeother\]\@makeother\>\@makeother\<%
+ \@makeother\/\@makeother\*\@makeother\+\@makeother\-%
+ \@makeother\'\@makeother\"\@makeother\_\@makeother\`%
+ \@makeother\=\@makeother\@}%
+}%
+\MFPsavecodes\MFPsanitize
+\catcode`@11
+\chardef\mfp@ctrlJ 10 \chardef\mfp@ctrlM 13
+% \end{macrocode}
+%
+% \cs{MFPsavecodes} saves a bunch of things that must have (mostly)
+% normal settings. \cs{mfp@restoreALL} will be invoked at the end of the
+% file to restore all the values.
+%
+% \cs{MFPsanitize} sets (almost) everything to normal. It can be used to
+% redo these settings inside some other macro, should that ever become
+% necessary. Characters 10 and 13 are \verb|^^J| and \verb|^^M|,
+% control-J and control-M.
+%
+%
+% \subsection{Debugging and messages}\label{debug}
+%
+% \DescribeMacro{\mfpicdebug}
+% To turn on debugging before option processing, the user must make sure
+% \cs{mfpicdebug} is defined. \cs{mfp@DBlog} writes it contents to the
+% log file only if debugging is on.
+% \DescribeMacro{\ifmfpicdebug}
+% The switch \cs {ifmfpicdebug} is normally set to true if the user loads
+% \mfpic{} with the \opt{debug} option, or sets it directly with
+% \cs{mfpicdebugtrue} after loading.
+% \begin{macrocode}
+\newif\ifmfpicdebug
+\ifx\mfpicdebug\UndEfInEd \mfpicdebugfalse
+\else \mfpicdebugtrue
+\fi
+\def\mfp@DBlog#1{%
+ \ifmfpicdebug{\let\@msgbreak\mfp@errbrk\wlog{Mfpic debug: #1}}\fi}%
+% \end{macrocode}
+%
+% We need to write various kinds of messages to the screen and log file.
+% \cs{mfp@msg} is only used in the definition of the others and to write a
+% blank line. We always use the second, which identifies the source of the
+% message, or the third, which adds the word `warning'. The fourth is for
+% errors and provides for help if a user presses `\texttt h' in response
+% to the message. The bit with the spaces is to get a hanging indentation
+% with text properly aligned on screen. The basic \cs{mfp@msg} defines
+% \cs{@nl} to place the \cs{newlinechar}, for multiline messages. We
+% also define \cs{@nl} in \cs{mfp@write} for new lines in writing to a
+% file. We do not define it at all at the outer level.
+% \begin{macrocode}
+\def\mfp@msg#1{%
+ {\newlinechar\mfp@ctrlJ\def\@nl{^^J}\immediate\write16{#1}}}%
+\def\mfp@spaces{\space\space\space\space\space\space}%
+\def\mfp@msgbrk{^^J\mfp@spaces\space}%
+\def\mfp@errbrk{\mfp@msgbrk\mfp@spaces}%
+\def\mfp@warnbrk{\mfp@errbrk\space\space}%
+\def\Mfpic@msg#1{{\let\@msgbreak\mfp@msgbrk\mfp@msg{Mfpic: #1}}}%
+\def\Mfpic@warn#1{%
+ {\let\@msgbreak\mfp@warnbrk\mfp@msg{\@nl Mfpic warning: #1}}}%
+\def\mfp@errmsg#1#2{{\newlinechar\mfp@ctrlJ\let\@msgbreak\mfp@errbrk
+ \errhelp{#2}\errmessage{Mfpic error: #1}}}%
+% \end{macrocode}
+%
+% In \TeX{} 3.x we can identify the line being processed when a message is
+% issued. We do not support \TeX{} 2.x. The command \cs{mfp@lineno} is
+% for information written into the output file.
+% \begin{macrocode}
+\def\mfp@lineno{line \number\inputlineno\space in the TeX source}%
+% \end{macrocode}
+%
+%
+% \subsection{Detecting the format}\label{format}
+%
+% To detect its environment, \mfpic{} needs to test whether certain
+% commands are defined. We usually use the positive version
+% \cs{mfp@ifdefined}. The \cs{@xp} in it is used to `expand away' the rest
+% of a conditional. \cs{@XP} does this from two levels deep in a
+% conditional. Since our check uses \cs{@firstoftwo} and
+% \cs{@secondoftwo}, we cannot use it to check \emph{their} existence (but
+% we could use other means).
+%
+% \cs{mfp@ifundefined} checks its argument to see if it is defined.
+% If so, it gobbles all code up to \cs{mfp@enddef}. Otherwise that code is
+% executed. This avoids reading code prematurely (category code changes).
+%
+% We also copy \LaTeX's \cs{@ifundefined} since we have at least five
+% places where we need to supply the name without a backslash.
+% \begin{macrocode}
+\let\@xp\expandafter
+\def\@XP{\@xp\@xp\@xp}%
+\long\def\@firstoftwo#1#2{#1}%
+\long\def\@secondoftwo#1#2{#2}%
+\def\mfp@ifdefined#1{%
+ \ifx#1\UndEfInEd \@xp\@secondoftwo
+ \else\ifx#1\relax \@XP\@secondoftwo
+ \else \@XP\@firstoftwo
+ \fi\fi}%
+\mfp@ifdefined\@empty{}{\def\@empty{}}%
+\mfp@ifdefined\@gobble{}{\def\@gobble#1{}}%
+\mfp@ifdefined\@firstofone{}{\long\def\@firstofone#1{#1}}%
+\mfp@ifdefined\on@line{}%
+ {\def\on@line{ on input line \number\inputlineno}}%
+\let\mfp@enddef\@empty
+\long\def\mfp@gobbledef#1\mfp@enddef{}%
+\def\mfp@ifundefined#1{\mfp@ifdefined#1\mfp@gobbledef\@empty}%
+\mfp@ifundefined\@ifundefined
+ \def\@ifundefined#1{%
+ \@xp\ifx\csname #1\endcsname\relax \@xp\@firstoftwo
+ \else \@xp\@secondoftwo
+ \fi}%
+\mfp@enddef
+% \end{macrocode}
+%
+% The following might be useful in patching things or adding to
+% \cs{mfp@additions}.
+% \begin{macrocode}
+\mfp@ifundefined\g@addto@macro
+ \long\def\g@addto@macro#1#2{%
+ \begingroup
+ \toks@\@xp{#1#2}%
+ \xdef#1{\the\toks@}%
+ \endgroup}%
+\mfp@enddef
+\mfp@ifundefined\g@prependto@macro
+ \long\def\g@prependto@macro#1#2{%
+ \begingroup
+ \toks@{#2}\toks2\@xp{#1}%
+ \xdef#1{\the\toks@\the\toks2}%
+ \endgroup}%
+\mfp@enddef
+% \end{macrocode}
+%
+% We test for LaTeX. We assume plain\TeX{}, or something compatible,
+% except in a few places where LaTeX{} does thing differently. \Mfpic{}
+% didn't work in \ConTeXt{} the last few times I tried.
+%
+% Here we see if \cs{documentstyle} is defined, and then make sure
+% we are not in \AmSTeX{}. We used to detect \AmSTeX{} by checking
+% \cs{fmtname}. This leads to problems if some other format inputs
+% \file{amstex.tex} and redefined \cs{fmtname}. Thus we will now check
+% \cs{amstexloaded@}. Unfortunately, \file{amstex.tex} sets it equal to
+% \cs{relax}, which is much too easy to be the result of some other
+% attempt to check it. Thus, we add an additional check for
+% \cs{NoBlackBoxes}.
+% \begin{macrocode}
+\newif\ifmfp@latex \mfp@latexfalse
+\mfp@ifdefined\documentstyle
+ {\ifx \amstexloaded@\relax % amstex loaded, or a bad check for it
+ \ifx\NoBlackBoxes\UndEfInEd % amstex not loaded
+ \mfp@DBlog{LaTeX detected.}\mfp@latextrue
+ \else % most likely amstex loaded
+ \mfp@DBlog{AmS-TeX detected.}%
+ \fi
+ \else % amstex not loaded
+ \mfp@DBlog{LaTeX detected.}\mfp@latextrue
+ \fi}%
+ {\mfp@DBlog{Neither LaTeX nor AmS-TeX detected.}}%
+% \end{macrocode}
+%
+% We are in \LaTeXe{}, as opposed to \LaTeX2.09, if \cs{documentclass}
+% is defined. The \file{mfpic.sty} now assumes \LaTeXe{}. It might still
+% be possible to use \LaTeX{}2.09 with \cs{input mfpic}, but I don't
+% care enough to test it.
+% \begin{macrocode}
+\newif\ifmfp@latexe \mfp@latexefalse
+\mfp@ifdefined\documentclass
+ {\mfp@latexetrue \mfp@DBlog{LaTeX2e detected.}}%
+ {\mfp@DBlog{Not LaTeX2e.}}%
+% \end{macrocode}
+%
+% We now test \cs{pdfoutput} to see if pdf support is needed.
+% \begin{macrocode}
+\newif\ifmfp@pdf \mfp@pdffalse
+\mfp@ifdefined\pdfoutput
+ {\mfp@DBlog{PdfTeX detected...}%
+ \ifnum\pdfoutput<1 \mfp@DBlog{...with dvi output.}%
+ \else \mfp@pdftrue \mfp@DBlog{...with PDF output.}%
+ \fi}%
+ {\mfp@DBlog{Not pdfTeX.}}%
+% \end{macrocode}
+%
+%
+% \subsection{Blank line and spacing hacks}\label{spacing}
+%
+% In order for commands to always read their arguments correctly,
+% we need EOLs to have their normal category codes, but then a
+% blank line will end a paragraph, and we would like blank lines to be
+% ignored inside an \env{mfpic} environment. Therefore we turn off
+% \cs{par} inside that environment, and then need(?) to turn it back on
+% inside \cs{tlabel} and \cs{tcaption}. \cs{@@par} (in \LaTeX) and
+% \cs{endgraf} (in plain \TeX) should equal the primitive \cs{par}.
+% \begin{macrocode}
+\ifmfp@latex \else \let\@@par\endgraf \fi
+\def\mfp@restorepar{\let\par\@@par}%
+% \end{macrocode}
+%
+% Some \mfpic{} commands end with \cs{ignorespaces}. For some others a
+% better choice is the \LaTeX{} strategy of conditionally ignoring spaces.
+% \begin{macrocode}
+\mfp@ifdefined\@namedef{}%
+ {\def\@namedef#1{\@xp\def\csname #1\endcsname}}%
+\mfp@ifdefined\@namelet{}%
+ {\def\@namelet#1{\@xp\let\csname #1\endcsname}}%
+\mfp@ifdefined\@nameuse{}%
+ {\def\@nameuse#1{\csname #1\endcsname}}%
+\mfp@ifundefined\@bsphack
+ \@nameuse{newskip}\@savsk
+ \@nameuse{newcount}\@savsf
+ \def\@bsphack{\relax
+ \ifhmode \@savsk\lastskip \@savsf\spacefactor \fi}%
+ \def\@esphack{\relax
+ \ifhmode \spacefactor\@savsf
+ \ifdim\@savsk>\z@ \ignorespaces
+ \fi\fi}%
+\mfp@enddef
+% \end{macrocode}
+%
+%
+% \subsection{Warning if commands are already defined}
+%
+% We sometimes (either by accident or by choice) redefine things defined
+% in some formats. For the accidental redefinitions we want to be told,
+% and since we cannot assume \LaTeX{} with its \cs{newcommand}, we define
+% a simple check and print a warning when it happens.
+% \begin{macrocode}
+\mfp@DBlog{Defining test for previous definitions of macros.}%
+\def\mfp@testdef#1{%
+ \ifx#1\UndEfInEd
+ \else\ifx#1\relax
+ \Mfpic@warn{\string#1 was previouly defined to be \string\relax.}%
+ \else
+ \Mfpic@warn{\string#1 is already defined.}%
+ \fi\fi}%
+% \end{macrocode}
+%
+% Is the proposed definer of new definitions itself not new? Well,
+% we'd like a warning, but go ahead and define it anyway. All
+% \cs{newdef} does is check whether the macro being defined is already
+% defined, raise a warning (but \emph{not} an error) and define it
+% anyway. We do something similar with \cs{let}.
+% \begin{macrocode}
+\mfp@testdef\newdef
+\def\newdef#1{\mfp@testdef#1\def#1}%
+\newdef\newlet#1{\mfp@testdef#1\let#1}%
+% \end{macrocode}
+%
+%
+% \subsection{Error messages and warnings}
+%
+% If one tries to switch on \MP{} support after the output file has been
+% set up, we issue this error message.
+% \begin{macrocode}
+\newdef\mfp@useMP@error{%
+ \mfp@errmsg {Command \mfp@b usemetapost too late}%
+ {It is too late to select the metapost option.^^J%
+ It must be selected before the \opengraphsfile command.^^J%
+ If you proceed, the metafont option will be assumed.}}%
+% \end{macrocode}
+%
+% This one is for macros that need an output file to write to, but are
+% called before one has been opened.
+% \begin{macrocode}
+\def\mfp@nooutput@error#1{%
+ \mfp@errmsg {No output file has been opened}%
+ {You have tried to used a command, #1, that requires an output^^J%
+ file to be opened with the \opengraphsfile command, which^^J%
+ was either not issued or was not successful.}}%
+% \end{macrocode}
+%
+% Some options and commands require the \opt{metapost} option be in
+% effect. We define an error message for the case where it is not in
+% effect. Rarely, we need a similar warning for the \opt{metafont}
+% option.
+% \begin{macrocode}
+\newdef\mfp@noMP@error#1{%
+ \mfp@errmsg {Metafont does not support #1, use MetaPost}%
+ {Metafont doesn't support #1. Perhaps you forgot to turn on^^J%
+ MetaPost support by using the metapost option or issuing the^^J%
+ command \usemetapost. For now, I will ignore it.}}%
+\newdef\mfp@noMF@warn#1{%
+ \Mfpic@warn
+ {Metapost does not support \string#1, it will be ignored.}}%
+% \end{macrocode}
+%
+% This next is like \cs{mfp@useMP@error}, but it is not so specific.
+% It is for other options that also need to be issued before
+% \cs{opengraphsfile}.
+% \begin{macrocode}
+\def\mfp@afteropen@error#1{%
+ \mfp@errmsg{Improper use of command \string#1\on@line}%
+ {You must issue the command #1 prior to \opengraphsfile.
+ It will be ignored now.}}%
+% \end{macrocode}
+%
+% \cs{mfp@end} is defined to be an error message, but that is for
+% debugging purposes. It's actual use is to mark the end when we need to
+% process a list of tokens. The code should simply detect and remove it,
+% and it should never be expanded, so seeing the error message indicates
+% a coding error by me, or incorrect syntax by a user.
+% \begin{macrocode}
+\newdef\mfp@end{%
+ \mfp@errmsg {Unexpected token \string\mfp@end}%
+ {If you get this message but did not misuse the command^^J%
+ \mfp@end, it could mean you have unbalanced braces.}}%
+% \end{macrocode}
+%
+% The next two are error messages for missing or empty data files.
+% \begin{macrocode}
+\newdef\mfp@nofile@error#1{%
+ \mfp@errmsg{No data file: #1}%
+ {The data file you tried to plot was not found.}}%
+\newdef\mfp@nodata@error#1{%
+ \mfp@errmsg{Empty data file: #1}%
+ {The data file contained only empty lines and comments.}}%
+% \end{macrocode}
+%
+% This message is issued when the \cs{tlabeljustify} command (see
+% subsection~\ref{labelsettings}) is issued with an invalid parameter.
+% \begin{macrocode}
+\newdef\mfp@justify@error{%
+ \mfp@errmsg{Invalid justification parameter for text label}%
+ {The optional argument for an mfpic text label must be^^J%
+ one of B, b, c or t, followed by^^J%
+ one of l, r or c, optionally followed by an angle.}}%
+% \end{macrocode}
+%
+% This is the default meaning assigned to \cs{@nountil} at the
+% beginning of \cs{mfploop}. Use of \cs{mfpuntil} cancels the
+% warning, which is otherwise issued by \cs{mfpendloop}.
+% \begin{macrocode}
+\newdef\mfp@untilwarn{%
+ \Mfpic@warn{\mfp@b mfploop without \string\mfpuntil!\@nl}}%
+% \end{macrocode}
+%
+%
+%
+% \section{Configuring \mfpic{} behavior}\label{configuring}
+%
+%
+% \subsection{Options}\label{options}
+%
+% \DescribeMacro{\ifmfpmpost}
+% I have decided to make this a user-level macro so that a user can
+% write code that behaves one way for \MP{} and another for \MF. However
+% the commands to change the setting are private.
+%
+% Our switch to turn \MP{} support on or off needs to be global, so it
+% can't be a normal \cs{newif}.
+% \begin{macrocode}
+\newlet\ifmfpmpost\iffalse
+\newdef\mfp@mposttrue {\global\let\ifmfpmpost\iftrue}%
+\newdef\mfp@mpostfalse{\global\let\ifmfpmpost\iffalse}%
+\newdef\mfp@ifmpost{%
+ \ifmfpmpost\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+% \end{macrocode}
+%
+% \DescribeMacro{\usemetafont}
+% We make user-level commands for switching to the appropriate drawing
+% program. This is necessary for plain\TeX, but also used internally by
+% \mfpic. \CMF{} is the default. This command needs to not only clear the
+% boolean \cs{ifmfpmpost}, but also restore the default graphics inclusion
+% commands. Actually, it doesn't \emph{need} to unless \cs{usemetapost}
+% was previously issued to change the default. This would normally not
+% happen unless the user wanted to close the current graph file and open a
+% new one for \MF. For similar reasons, we clear the \opt{mplabels}
+% option.
+%
+% \MP{} support requires macros for including EPS graphics. What works
+% best depends on the format, so we delay the definition of
+% \cs{usemetapost} until the \LaTeX{} options section.
+%
+% Since \cs{mfpicllx} and \cs{mfpiclly} are globally defined by graphic
+% inclusion, we reset then to 0, in case \opt{metafont} and \opt{metapost}
+% options are mixed in one file.
+% \begin{macrocode}
+\newdef\usemetafont{\mfp@mpostfalse
+ \nomplabels
+ \def\preparemfpicgraphic##1{}%
+ \def\setmfpicgraphic##1{\mfp@graphfont\char\mfp@count}%
+ \def\getmfpicoffset##1{\gdef\mfpicllx{0}\gdef\mfpiclly{0}}}%
+% \end{macrocode}
+%
+% Some options need an open \file{.mf} or \file{.mp} file before they
+% can do anything. This means the \cs{opengraphsfile} command must have
+% been issued but not \cs{closegraphsfile}. Since those commands define and
+% undefine \cs{mfp@filename}, we use that as our test.
+% \begin{macrocode}
+\newdef\mfp@ifopengraphsfile{\mfp@ifdefined\mfp@filename}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfmode}
+% For use with the \opt{metafont} option, we allow the user to set the
+% \MF{} mode. Example: \verb$\mfmode{ljfour}$
+%
+% \DescribeMacro{\mfresolution}
+% If modes are too esoteric, the user can at least set the resolution.
+% This should be a pure number representing dots per inch. Example:
+% \verb$\mfresolution{600}$
+% \begin{macrocode}
+\newdef\mfmode#1{\edef\mfp@mode{#1}%
+ \mfp@ifopengraphsfile%
+ {\mfp@afteropen@error\mfmode}%
+ {\mfp@ifmpost{\mfp@noMF@warn\mfmode}{}}}%
+\newdef\mfresolution#1{\edef\mfp@resolution{#1}%
+ \mfp@ifopengraphsfile%
+ {\mfp@afteropen@error\mfresolution}%
+ {\mfp@ifmpost{\mfp@noMF@warn\mfresolution}{}}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\setmfvariable}
+% A useful abbreviation for a common requirement: declaring and setting
+% a \MF{} variable. I have decided to change it to a user-level macro for
+% power users.
+% \DescribeMacro{\setmpvariable}
+% For consistency, \cs{setmpvariable} is an alternative name for it. It
+% takes three arguments: the type of variable, the variable itself, and
+% its value. Example:\\
+% \indent \cs{setmfvariable}\marg{numeric}\marg{shadewd}\marg{.7pt}.\\
+% Since the \MF{} code \mfc{save}\,s the variable, there must be no
+% suffix. This is not a big problem since mostly it is for internal use.
+% We document that fact for power users and advise ordinary users on the
+% naming of \MF{} variables.
+%
+% Since \MP{} has three (or four) data types for color, we have to write
+% the command `\gbc{setcolor}' to the output file instead of
+% `\gbc{setvariable (color)}' so that the datatype can be determined
+% before declaring the variable. (Unlike the other data types the
+% \grafbase{} command \gbc{setcolor} is more complicated than
+% \gbc{setvariable(color)}.) For simplicity, we do this with all data
+% types. For example \cs{setmfvariable}\marg{numeric} writes
+% `\gbc{setnumeric}'. This makes spaces significant in the first argument,
+% so we strip them off the ends with \cs{mfp@sp@def} (defined in
+% section~\ref{optional}).
+%
+% We have abbreviations for the most common internal uses. For example
+% \SpecialUsageIndex{\setmfboolean}\cs{setmfboolean} is the equivalent of
+% \cs{setmfvariable} with type \mfc{boolean}. A similar statement is true
+% For \SpecialUsageIndex{\setmfnumeric}\cs{setmfnumeric},
+% \SpecialUsageIndex{\setmfpair}\cs{setmfpair}, and
+% \SpecialUsageIndex{\setmfcolor}\cs{setmfcolor}.
+%
+% \DescribeMacro{\globalsetmfvariable}
+% This is like \cs{setmfvariable}, except it doesn't perform a
+% \mfc{save} and so the variable is globally defined. Also,
+% suffixed variables are permitted (but not numeric suffixes).
+% Here, too, we have to write a different command for setting color.
+% Thus, me need to test whether the first argument is `color'. Here again,
+% spaces are significant.
+% \begin{macrocode}
+\newdef\setmfvariable#1{%
+ \mfp@sp@def\mfp@tempa{#1}\@setmfvariable\mfp@tempa}%
+\newdef\@setmfvariable#1#2#3{%
+ \mfp@ifopengraphsfile%
+ {\mfcmd{set#1 (#2) #3}}%
+ {\mfp@nooutput@error\setmfvariable}}%
+\newdef\setmfboolean{\@setmfvariable{boolean}}%
+\newdef\setmfnumeric{\@setmfvariable{numeric}}%
+\newdef\setmfpair {\@setmfvariable{pair}}%
+\newdef\setmfcolor {\@setmfvariable{color}}%
+\newdef\globalsetmfvariable#1#2#3{%
+ \mfp@sp@def\mfp@tempa{#1}%
+ \mfp@ifopengraphsfile
+ {\mfcmd{\ifx\mfp@tempa\mfp@C gsetcolor \else gsetvariable (#1) \fi
+ (#2) #3}}%
+ {\mfp@nooutput@error\globalsetmfvariable}}%
+\newlet\setmpvariable\setmfvariable
+\newlet\globalsetmpvariable\globalsetmfvariable
+% \end{macrocode}
+%
+% The command \cs{setmfvariable} arranges for the value of
+% that variable to be localized to each figure if set inside one, but
+% it is global otherwise. We have to be careful that \TeX{} and \MF{}
+% stay in synchrony, as they have different understandings as to what is
+% global and what is not. So we define a switch that will be set at the
+% start of an \env{mfpic} environment to test if a command is issued
+% inside one. The command \cs{mfp@local} tests this switch and makes the
+% following assignment global if it fails. Then we have two shortcuts for
+% the more commonly occuring cases.
+%
+% We also define here \texttt{true}, \texttt{false} and \texttt{color} as
+% macros. These are strings we need to write to the output frequently.
+% \begin{macrocode}
+\newlet\ifin@mfpicenv\iffalse
+\newdef\mfp@local{\relax\ifin@mfpicenv\else\global\fi}%
+\newdef\mfp@let{\mfp@local\let}%
+\newdef\mfp@def{\mfp@local\def}%
+\newdef\mfp@T{true}%
+\newdef\mfp@F{false}%
+\newdef\mfp@C{color}%
+% \end{macrocode}
+%
+% \DescribeMacro{\usecenteredcaptions}
+% This (\opt{centeredcaptions}) is the simplest option. Other options
+% follow a similar pattern: a user-level command \cs{usecenteredcaptions}
+% is defined for turning it on and another,
+% \DescribeMacro{\nocenteredcaptions}
+% \cs{nocenteredcaptions}, is defined for turning it off. Selection of
+% centered captions can be turned on or off at will throughout a document.
+% \begin{macrocode}
+\newdef\usecenteredcaptions{\mfp@let\ifmfp@centcapt\iftrue}%
+\newdef\nocenteredcaptions {\mfp@let\ifmfp@centcapt\iffalse}%
+\nocenteredcaptions
+% \end{macrocode}
+%
+% \DescribeMacro{\useraggedcaptions}
+% Here we define the settings for justified and ragged captions.
+% Justified captions are the default. Ragged captions are normally
+% raggedright, but are ragged on both sides if \opt{centeredcaptions} is
+% in effect.
+% \DescribeMacro{\noraggedcaptions}
+% For justified captions, lines are justified on both sides, except the
+% last is centered under \opt{centeredcaptions}.
+% \begin{macrocode}
+\newdef\useraggedcaptions{\mfp@let\mfp@capsettings\mfp@raggedcap}%
+\newdef\noraggedcaptions{\mfp@let\mfp@capsettings\mfp@justifiedcap}%
+\newdef\mfp@raggedcap{%
+ \ifmfp@latex
+ \ifmfp@centcapt \centering \else \raggedright \fi
+ \else
+ \rightskip 0pt plus 1fil\relax
+ \ifmfp@centcapt
+ \leftskip 0pt plus 1fil
+ \parfillskip 0pt plus 1fil\relax
+ \fi
+ \def\\{\unskip\hbox{}\penalty-\@M\ignorespaces}%
+ \fi}%
+\def\mfp@justifiedcap{%
+ \ifmfp@centcapt
+ \leftskip 0pt plus 0.5fil
+ \rightskip 0pt plus -0.5fil
+ \parfillskip 0pt plus 1fil\relax
+ \fi
+ \def\\{\unskip\hbox{}\hfil\penalty-\@M\ignorespaces}}%
+\noraggedcaptions
+% \end{macrocode}
+%
+% This common code is repeated almost verbatim four times, so we define
+% the following abbreviation. The first two arguments are the commands
+% to turn the option on and off. The third and fourth are the \MF{} and
+% \TeX{} booleans to switch. In all cases, the default for the option is
+% \emph{off}, so we issue the second command after it is defined.
+%
+% Since the output file has not been opened while \mfpic{} is loading, the
+% \MF{} boolean is not set, but the \cs{opengraphsfile} code will check
+% the \TeX{} boolean and write the appropriate \MF{} code.
+% \begin{macrocode}
+\newdef\mfp@makeoption#1#2#3#4{%
+ \newdef#1{\mfp@let#4\iftrue
+ \mfp@ifopengraphsfile{\setmfboolean{#3}\mfp@T}{}}%
+ \newdef#2{\mfp@let#4\iffalse
+ \mfp@ifopengraphsfile{\setmfboolean{#3}\mfp@F}{}}%
+ #2}%
+% \end{macrocode}
+%
+% \DescribeMacro{\clipmfpic}
+% The \opt{clip} option shows only what's inside the rectangle given in
+% the \cs{mfpic} command. It can be turned on or off for each figure
+% independently.
+% \DescribeMacro{\noclipmfpic}
+% The default is the old behavior: no clipping.
+% \begin{macrocode}
+\mfp@makeoption\clipmfpic\noclipmfpic{clipall}\ifmfp@clip
+% \end{macrocode}
+%
+% \DescribeMacro{\usetruebbox}
+% The \opt{truebbox} option lets \MP{} set the true bounding box (which
+% may differ from the numbers defined through \cs{mfpic}).
+% \DescribeMacro{\notruebbox}
+% The default is the old behavior, \cs{notruebbox}.
+%
+% We don't need to be too careful with the scope of these option
+% commands. As currently written, \TeX{} never needs to know the setting
+% except to pass the information on to \cs{opengraphsfile} if the option
+% is set before then. However, we treat it like most other settings,
+% turning on or off an appropriate \TeX{} boolean, in case it ever becomes
+% necessary to know the setting. It is local to any \env{mfpic}, global
+% otherwise. The default is to have \opt{truebbox} turned off.
+% \begin{macrocode}
+\mfp@makeoption\usetruebbox\notruebbox{truebbox}\ifmfp@truebbox
+% \end{macrocode}
+%
+% \DescribeMacro{\usemplabels}
+% An option to let \MP{} create labels, \opt{mplabels} mostly just
+% switches between two versions of \cs{tlabel} so no \MP{} booleans
+% are set and so synchronization of scope is not an issue.
+% \DescribeMacro{\nomplabels}
+% The default is the old behavior: labels are placed by \TeX. The actual
+% setting is delayed until \cs{opengraphsfile} so the order of these
+% commands and \cs{usemetapost} is not significant (before
+% \cs{opengraphsfile}).
+%
+% Because of the frequent need to check this setting, we define
+% \cs{@ifmplabels} to execute one of two alternatives based on it.
+% When writing \TeX{} code to the file we need to make sure \texttt\#
+% is not doubled. We do this by issuing \cs{mp@mksharpother} before
+% reading the argument that will be written.
+% \begin{macrocode}
+\newdef\usemplabels{\mfp@let\ifmfp@mplabels\iftrue
+ \mfp@ifopengraphsfile
+ {\mfp@ifmpost{}%
+ {\mfp@noMP@error{mplabels}\global\let\ifmfp@mplabels\iffalse}}{}}%
+\newdef\nomplabels{\mfp@let\ifmfp@mplabels\iffalse}%
+\newdef\@ifmplabels{%
+ \ifmfp@mplabels\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\nomplabels
+\newdef\mp@mksharpother{\@ifmplabels{\@makeother\#}{}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\overlaylabels}
+% The option \opt{overlaylabels} instructs \MP{} to defer adding labels
+% until the end of the picture. That means they don't get clipped or
+% covered up by any drawing elements.
+% \DescribeMacro{\nooverlaylabels}
+% The default is the old behavior, \cs{nooverlaylabels}. Neither of these
+% commands affect \MF, but they write to the output file anyway if issued
+% after \cs{opengraphsfile}.
+% \begin{macrocode}
+\mfp@makeoption%
+ \overlaylabels\nooverlaylabels{overlaylabels}\ifmfp@overlabels
+% \end{macrocode}
+%
+% \DescribeMacro{\clearsymbols}
+% The option \opt{clearsymbols} causes the symbols drawn by
+% \cs{plotsymbol} and \cs{plotnodes} to have their interiors erased before
+% being drawn.
+% \DescribeMacro{\noclearsymbols}
+% The default is the old behavior: \cs{noclearsymbols}.
+% \begin{macrocode}
+\mfp@makeoption%
+ \clearsymbols\noclearsymbols{clearsymbols}\ifmfp@clearsym
+% \end{macrocode}
+%
+% \DescribeMacro{\stopshipping}
+% This is to turn off character shipping for duration of innermost
+% enclosing \MF{} group (eg, \env{mfpic} environment). As far as I know
+% it has never been tested with \MP. (It hasn't been tested recently even
+% in \MF.) The \MF{} code prevents the figure from being added to the font,
+% the \TeX{} switch \cs{ifmfp@noship} is checked before \cs{endmfpic}
+% attempts to add the (nonexistent) figure to the document.
+% \DescribeMacro{\resumeshipping}
+% The macro \cs{resumeshipping} restores character shipping.
+%
+% \DescribeMacro{\noship}
+% The macro \cs{noship} is the older name for \cs{stopshipping}. Its name
+% indicated that it was intended for use in one picture. This is not
+% actually an option (that is, there is no corresponding
+% \cs{DeclareOption} in \LaTeX), but it is coded the same.
+% \begin{macrocode}
+\mfp@makeoption\stopshipping\resumeshipping{noship}\ifmfp@noship
+\newlet\noship\stopshipping
+% \end{macrocode}
+%
+% \DescribeMacro{\mfpreadlog}
+% This sets the boolean governing the option to examine the \MF{} or
+% \MP{} log file for certain information.
+% \begin{macrocode}
+\newlet\ifmfp@readlog\iffalse
+\newdef\mfpreadlog{%
+ \mfp@ifopengraphsfile
+ {\mfp@afteropen@error\mfpreadlog}{\global\let\ifmfp@readlog\iftrue}}%
+% \end{macrocode}
+%
+%
+% \subsection{Graphic inclusion}\label{graphic}
+%
+% \DescribeMacro{\mfpicllx}
+% The code to include a figure has been divided into three parts. Under
+% \opt{metapost} we need to both include the figure and save the
+% \DescribeMacro{\mfpiclly}
+% bounding box coordinates of the lower left corner. Here we initialize
+% the macros that hold these coordinates.
+% \begin{macrocode}
+\newdef\mfpicllx{0}%
+\newdef\mfpiclly{0}%
+% \end{macrocode}
+%
+% \DescribeMacro{\preparemfpicgraphic}
+% Most EPS inclusion macros make the bounding box information available,
+% and so after the inclusion command we just save it in the above two
+% macros. However, \LaTeX's \cs{includegraphics} does not, so we have to
+% issue a command before the inclusion to force it to become available.
+% That command is \cs{preparemfpicgraphic}. Usually it does nothing,
+% but in the \LaTeXe{} case it locally redefines one of the graphics
+% packages internal macros.
+%
+% \DescribeMacro{\setmfpicgraphic}
+% This command includes the graphic. The \mfpic{} default (for the
+% \opt{metafont} option) is set by running \cs{usemetafont}.
+%
+% \DescribeMacro{\getmfpicoffset}
+% This one saves the lower left corner in the macros \cs{mfpicllx} and
+% \cs{mfpiclly}. In the case described above, that is accomplished by
+% the redefined internal command, so this command does nothing.
+%
+% The command \cs{@setmfpicgraphic} is a wrapper around the inclusion
+% code. It takes the name of the graphic file and passes it along to the
+% above three commands. Those three commands can be redefined by the
+% user for special circumstances. The user is then responsible to make
+% sure \cs{mfpicllx} and \cs{mfpiclly} are properly set when necessary.
+% Redefining one may necessitate redefining one or both of the others.
+%
+% The definition of these three is delayed to the option processing
+% section, except under the \MF{} default: \cs{usemetafont} defines them.
+%
+% We actually define two alternative versions of \cs{@setmfpicgraphic}.
+% The normal one is as described above, and a `nofile' alternative for
+% when the graphic file somehow doesn't exist. Then we just print the
+% filename.
+% \begin{macrocode}
+\newdef\normal@setmfpgraphic#1{%
+ \preparemfpicgraphic{#1}\setmfpicgraphic{#1}\getmfpicoffset{#1}}%
+\newdef\nofile@setmfpgraphic#1{%
+ {\edef\mfp@tempa{#1}%
+ \vbox to 0pt{\vss
+ \rlap{\kern2pt \mfpdraftfont \mfp@sanitized\mfp@tempa}\kern 2pt}}}%
+\mfp@ifdefined\strip@prefix{}{\def\strip@prefix#1>{}}%
+\newdef\mfp@sanitized{\@xp\strip@prefix\meaning}%
+\newlet\@setmfpicgraphic\normal@setmfpgraphic
+\usemetafont
+% \end{macrocode}
+%
+% \DescribeMacro{\setfilename}
+% The user can also change \cs{setfilename} to modify the assumed
+% filenames of the graphics output by \MP. The default is the output
+% file's basename (\arg1) with the picture number as the extension.
+%
+% \DescribeMacro{\setfilenametemplate}
+% The user can also tell \MP{} what kind of filename he wishes it to
+% produce. one uses \verb$\_$ in the template as a placeholder for the
+% \file{.mp} filename (the name used in \cs{opengraphsfile}) and \verb$\#$
+% for the figure number.
+% \begin{macrocode}
+\newdef\setfilename#1#2{#1.#2}%
+\newdef\setfilenametemplate#1{%
+ \begingroup
+ \def\_{\mfp@p j}%
+ \def\#{\mfp@p c}%
+ \let\@nl\relax
+ \xdef\mfp@settemplate{\@nl setoutputtemplate "#1";\@nl}%
+ \let\number\relax
+ \let\mfp@count\relax
+ \let\mfp@filename\relax
+ \def\_{\mfp@filename}%
+ \def\#{\number\mfp@count}%
+ \xdef\setfilename##1##2{#1}%
+ \endgroup
+}%
+% \end{macrocode}
+%
+% The \opt{draft}, \opt{final} and \opt{nowrite} options override
+% \mfpic's attempts to automatically detect whether the pictures should
+% be included. They also work under the \opt{metafont} option, but are
+% less important then (even unnecessary).
+%
+% \DescribeMacro{\mfpicdraft}
+% The \opt{draft} option (\cs{mfpicdraft} command) causes the pictures
+% created by \mfpic{} to be omitted.
+%
+% \DescribeMacro{\mfpicnowrite}
+% The \opt{nowrite} option (\cs{mfpicnowrite} command) turns off creation
+% of the output \file{.mp} file. It is intended to help speed things up
+% after all figures are completed, so it permits the insertion of pictures.
+%
+% \DescribeMacro{\mfpicfinal}
+% The \opt{final} option (\cs{mfpicfinal} command) can be used to
+% override a global draft option. It forces \mfpic{} to attempt to
+% insert the pictures. Under the \opt{metapost} option, missing figures
+% may cause serious slow-downs as a large number of directories may be
+% searched.
+%
+% Each of these sets the user level if-command
+% \SpecialUsageIndex{\ifmfpicdraft}\cs{ifmfpicdraft}, which is retained
+% for backward compatibility. These settings are global since they are
+% intended to be set for the whole document. The four commands
+% \cs{mfp@\{draft\|final\}\{true\|false\}} are used to communicate with
+% the \cs{opengraphsfile} command, in case the user-level commands occur
+% before then.
+% \begin{macrocode}
+\newif\ifmfpicdraft
+\newlet\ifmfp@draft\iffalse
+\newlet\ifmfp@final\iffalse
+\newlet\ifmfp@nowrite\iffalse
+\newdef\mfpicdraft{%
+ \mfp@ifopengraphsfile{\global\mfpicdrafttrue}%
+ {\global\let\ifmfp@draft\iftrue}}%
+\newdef\mfpicfinal{%
+ \mfp@ifopengraphsfile{\global\mfpicdraftfalse}%
+ {\global\let\ifmfp@final\iftrue}}%
+\newdef\mfpicnowrite{%
+ \mfp@ifopengraphsfile{\mfp@afteropen@error\mfpicnowrite}%
+ {\global\let\ifmfp@nowrite\iftrue}}%
+%</tex>
+% \end{macrocode}
+%
+%
+% \subsection{\LaTeX{} options and \MP{} graphics inclusion}\label{latex}
+%
+% Code dependent on \LaTeXe. Mostly this is the option processing
+% facilities. The declaration of options is in the file
+% \file{mfpic.sty}, which will input \file{mfpic.tex}.
+% \begin{macrocode}
+%<*sty>
+\DeclareOption{draft}{\mfpicdraft}%
+\DeclareOption{final}{%
+ \mfpicfinal\PassOptionsToPackage{final}{graphics}}%
+\DeclareOption{nowrite}{\mfpicnowrite}%
+\DeclareOption{metapost}{\mfp@mposttrue}%
+\DeclareOption{metafont}{\usemetafont}%
+\DeclareOption{centeredcaptions}{\usecenteredcaptions}%
+\DeclareOption{justifiedcaptions}{\noraggedcaptions}%
+\DeclareOption{raggedcaptions}{\useraggedcaptions}%
+\DeclareOption{clip}{\clipmfpic}%
+\DeclareOption{truebbox}{\usetruebbox}%
+\DeclareOption{mplabels}{\usemplabels}%
+\DeclareOption{overlaylabels}{\overlaylabels}%
+\DeclareOption{clearsymbols}{\clearsymbols}%
+\DeclareOption{debug}{\mfpicdebugtrue}%
+\DeclareOption{mfpreadlog}{\mfp@readlogtrue}%
+\DeclareOption*{%
+ \@ifpackageloaded{graphics}%
+ {\Mfpic@warn{Unrecognized option \CurrentOption.}}%
+ {\Mfpic@msg{Passing option \CurrentOption\space to %
+ graphics package.}%
+ \PassOptionsToPackage{\CurrentOption}{graphics}}}%
+\newcommand*\mfpdraftfont{\normalfont\ttfamily}%
+% \end{macrocode}
+%
+% Now we define one of three versions of \cs{@usemetapost}. This command
+% will be issued by the user level command \cs{usemetapost}, and consists
+% of the format dependent code. The one here is, of course, for \LaTeX{}
+% and will be in \file{mfpic.sty}.
+%
+% Unlike all the other EPS inclusion macros, \cs{includegraphics} does
+% not make the bounding box coordinates available: \cs{Gin@llx} and the
+% others are defined, but are local to a group surrounding the internals
+% of \cs{includegraphics}. We locally modify one graphics package internal
+% macro to globally save the information we need. Here we save the
+% original definition and define our replacement. For this, we definitely
+% need to make sure the \prog{graphics} package is loaded.
+% \begin{macrocode}
+\def\@usemetapost{%
+ \mfp@ifdefined\includegraphics{}{\RequirePackage{graphics}}%
+ \let\mfp@save@parse@bb\Gread@parse@bb
+ \newdef\mfp@parse@bb##1 ##2 ##3 ##4 ##5\\{%
+ \mfp@save@parse@bb##1 ##2 ##3 ##4 ##5\\%
+ \xdef\mfpicllx{\Gin@llx}\xdef\mfpiclly{\Gin@lly}}%
+% \end{macrocode}
+% The \prog{graphics} package makes decisions about graphic files based on
+% the files' extensions. Since we don't want to force our users to rename
+% all the graphics output by \MP, we add code to \cs{preparemfpicgraphic}
+% to force \cs{includegraphics} to treat the current extension (some
+% number) as if it were `{\tt eps}' or `{\tt mps}' according to the
+% context. We also use this command to substitute the above BoundingBox
+% parsing code for the \prog{graphics} package version.
+% \begin{macrocode}
+ \ifmfp@pdf \gdef\mfp@Gtype{mps}%
+ \else \gdef\mfp@Gtype{eps}%
+ \fi
+ \gdef\preparemfpicgraphic##1{%
+ \@namedef{Gin@rule@.\number\mfp@count}####1{{\mfp@Gtype}%
+ {.\number\mfp@count}{####1}}%
+ \let\Gread@parse@bb\mfp@parse@bb}%
+ \global\let\setmfpicgraphic\includegraphics
+ \gdef\getmfpicoffset##1{}}%
+% \end{macrocode}
+%
+% The \LaTeX{} wrapper ends by inputing \file{mfpic.tex}.
+% \begin{macrocode}
+\input mfpic.tex\relax
+%</sty>
+% \end{macrocode}
+%
+% \DescribeMacro{\usemetapost}
+% The user level command \cs{usemetapost} starts with a few actions common
+% to all formats, then calls \cs{@usemetapost} which is defined
+% differently for different formats.
+% \begin{macrocode}
+%<*tex>
+\newdef\usemetapost{%
+ \mfp@ifopengraphsfile{\mfp@mpostfalse\mfp@useMP@error}%
+ {\mfp@mposttrue \@usemetapost}}%
+% \end{macrocode}
+%
+% Under \LaTeX, if \file{mfpic.cfg} exists, it will be input at this
+% point. Then, we \cs{ProcessOptions}, using the star-form because it allows
+% package options to take precedence over global options. Thus \mfpic's
+% \opt{final} option can counteract the \mfpic-specific side effects of a
+% global \opt{draft} option.
+% \begin{macrocode}
+\ifmfp@latexe
+ \InputIfFileExists{mfpic.cfg}{}{}%
+ \ProcessOptions*\relax
+% \end{macrocode}
+%
+% \cs{ProcessOptions} doesn't allow \cs{RequirePackage}\marg{graphics},
+% so the above and the following were not simply put inside
+% \cs{DeclareOption}\marg{metapost}. The \cs{AtEndDocument} command will
+% close the output file if the user forgot.
+% \begin{macrocode}
+ \mfp@ifmpost{\usemetapost}{}%
+ \AtEndDocument{\mfp@closegraphsfile}%
+% \end{macrocode}
+%
+% Now those cases outside \LaTeXe{} that we try to support.
+% \begin{macrocode}
+\else
+ \mfp@msg{}\Mfpic@msg{\mfpfiledate\space v\mfpfileversion.\@nl}%
+% \end{macrocode}
+%
+% The definition of \cs{@usemetapost} in plain \TeX{} depends on the
+% setting of \cs{ifmfp@pdf}. However both cases are so similar that we
+% define a helper macro \cs{mfp@useMP} that just needs to have the names
+% of three commands and two files fed to it.
+% \begin{macrocode}
+ \newdef\mfp@useMP#1#2#3#4#5{%
+ \mfp@ifdefined#1{}{%
+ \InputIfFileExists{#2}{}{%
+ \InputIfFileExists{#3}{}{%
+ \mfp@errmsg{Files not found: #1, #2}%
+ {One of the two named files is necessary
+ for mfpic, but neither was found.}}}}%
+ \global\let\setmfpicgraphic\mfp@includeMPS
+ \gdef\getmfpicoffset##1{\xdef\mfpicllx{#4}\xdef\mfpiclly{#5}}}%
+% \end{macrocode}
+%
+% Under \pdfTeX{}, the graphics inclusion command is \cs{convertMPtoPDF},
+% defined in \file{supp-pdf.tex}. This command parses the file's PS
+% contents to PDF code, and leaves the bounding box info in macros
+% \cs{MPllx} and \cs{MPlly}.
+% \begin{macrocode}
+ \ifmfp@pdf
+ \newdef\mfp@includeMPS#1{\convertMPtoPDF{#1}{1}{1}}%
+ \newdef\@usemetapost{%
+ \mfp@useMP\convertMPtoPDF{supp-pdf.mkii}{supp-pdf.tex}%
+ \MPllx\MPlly}%
+% \end{macrocode}
+%
+% Under plain\TeX, eplain (still need to test this after recent eplain
+% changes), \AmSTeX, or \LaTeX2.09, the graphics inclusion command is
+% \cs{epsfbox}, defined in \file{epsf.tex}. This command writes a
+% \cs{special} for \prog{dvips} (and other DVI driver programs), and
+% leaves the bounding box info in macros \cs{epsfllx} and \cs{epsflly}.
+% \begin{macrocode}
+ \else
+ \newdef\mfp@includeMPS#1{\epsfbox{#1}}%
+ \newdef\@usemetapost{%
+ \mfp@useMP\epsfbox{epsf.tex}{epsf.sty}\epsfllx\epsflly}%
+ \fi
+\fi
+% \end{macrocode}
+%
+%
+%
+% \section{Optional parameter handling}\label{optional}
+%
+% We borrow \LaTeX's \cs{@ifnextchar}. The first argument is the token
+% being checked. It doesn't have to be a character and we sometimes use
+% \cs{@ifnextchar} to check whether a certain command follows.
+% The next argument is the code to run if that character is present, the
+% last is code to use if the character is not present.
+% \begin{macrocode}
+\mfp@DBlog{Handlers for optional parameters.}%
+\mfp@ifundefined\@ifnextchar
+ \long\def\@ifnextchar#1#2#3{%
+ \let\reserved@d#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch}%
+ \def\@ifnch{%
+ \ifx\@let@token\@sptoken
+ \let\reserved@c\@xifnch
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \reserved@c}%
+ {%
+ \def\:{\global\let\@sptoken= }\: % makes \@sptoken a space token
+ \def\:{\@xifnch}\@xp\gdef\: {\futurelet\@let@token\@ifnch}%
+ }%
+\mfp@enddef
+% \end{macrocode}
+%
+% Here we borrow from \file{keyval.sty}. We need a command that strips
+% spaces off ends of an argument and stores the result in a macro. In
+% \file{keyval}, that is \cs{KV@@sp@def}; we copy it here with name
+% changes. Defining \cs{mfp@tempa}, and then calling it with a space as
+% argument, ensures there will be an actual space token where needed in
+% the definition of \cs{mfp@sp@def}. The first argument is the control
+% sequence to define and the second is its definition text, with possible
+% spaces to be stripped. (I'm wondering now why I didn't just use
+% \cs{zap@space} since there shouldn't be \emph{any} significant spaces.
+% Well, at least I have the code in place for a future key-value
+% interface.)
+% \begin{macrocode}
+\def\mfp@tempa#1{%
+ \def\mfp@sp@def##1##2{%
+ \futurelet\mfp@next\mfp@sp@d##2\@nil\@nil#1\@nil\relax##1}%
+ \def\mfp@sp@d{%
+ \ifx\mfp@next\@sptoken \@xp\mfp@sp@b
+ \else \@xp\mfp@sp@b\@xp#1%
+ \fi}%
+ \def\mfp@sp@b#1##1 \@nil{\mfp@sp@c##1}}%
+\mfp@tempa{ }%
+\def\mfp@sp@c#1\@nil#2\relax#3{\mfp@toks{#1}\edef#3{\the\mfp@toks}}%
+% \end{macrocode}
+%
+% The following save us some typing whenever we need to check if some
+% token follows, and then remove it if it does. That's what
+% \cs{mfp@iftoken} does, being just a generalized form of \LaTeX{}'s
+% \cs{@ifstar}. Almost all our star-form commands differ only in what
+% parameter is passed to some other command. Thus \cs{mfp@ifstar} passes
+% either \arg{2} or \arg{3} to command \arg{1}.
+%
+% The \cs{mfp@ifend} is for use in processing lists, which all end with
+% the token \cs{mfp@end}. \cs{mfp@ifendorcomma} is useful for processing
+% comma-separated lists. If \cs{mfp@end} follows, it is removed and \arg1
+% is executed. Otherwise, if a comma follows, it is removed and \arg2 is
+% executed. When neither follows, nothing is removed and \arg3 is
+% executed. Normally, this last is the main command being applied to each
+% element of the list.
+%
+% We also define \LaTeX's \cs{@ifstar} for the few cases that require it.
+% \begin{macrocode}
+\def\mfp@iftoken#1#2{\@ifnextchar#1{\@firstoftwo{#2}}}%
+\def\mfp@ifstar#1#2#3{\mfp@iftoken*{#1{#2}}{#1{#3}}}%
+\def\mfp@ifend{\mfp@iftoken\mfp@end}%
+\def\mfp@ifendorcomma#1#2#3{\mfp@ifend{#1}{\mfp@iftoken,{#2}{#3}}}%
+\mfp@ifundefined\@ifstar
+ \def\@ifstar#1{\@ifnextchar*{\@firstoftwo{#1}}}%
+\mfp@enddef
+% \end{macrocode}
+%
+% I've taken to making an empty optional argument the default for a lot
+% of commands. I wanted to make it possible to have the same result for
+% empty brackets (i.e., \texttt{[\,]}) as for omitted brackets.
+% \cs{mfp@ifempty} helps check for emptyness. It uses a simple \cs{if} so
+% that \arg{1} will be expanded. I use a non-active \texttt\textasciitilde
+% (so it won't expand) to test for emptiness because, even if
+% a tilde should accidentally occur in a user's \arg1, it will most
+% likely be the usual active version which expands to something else.
+%
+% The shorthand \cs{mfp@ifexist} executes some code if \arg1 is not
+% empty, otherwise it does nothing. And \cs{mfp@emptysub} expands to
+% \arg1 if it isn't empty, otherwise \arg2.
+%
+% The \cs{@ifmtarg} macro is borrowed from \file{ifmtarg.sty}.
+% It is used when a space should count as empty, but expansion isn't
+% needed. It would be nice to have one that counts both as empty, but
+% that seems impossible (or impossibly hard).
+% \begin{macrocode}
+{%
+\catcode`Q3 \catcode`\~12
+\gdef\mfp@ifempty#1{\if~#1~\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\gdef\mfp@ifexist#1{\if~#1~\@xp\@gobble\else\@xp\@firstofone\fi}%
+\gdef\mfp@emptysub#1#2{\if~#1~#2\else#1\fi}%
+\long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil}%
+\long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4}%
+}%
+% \end{macrocode}
+%
+% These are the two most common methods to parse optional arguments. In
+% \cs{mfp@defaultopt}, if an optional argument is present, we use
+% \cs{mfp@ifemptyopt} to see if it is empty and substitute a default
+% (\arg{2}) if it is. Argument \arg{1} is the command to run
+% on the resulting argument after this check. It needn't be a single
+% command token, but can (and often will) be a series of commands, or a
+% command with additional arguments.
+%
+% \cs{mfp@nullopt} is a convenient abbreviation for a common case: the
+% default option is empty. We could define it in terms of
+% \cs{mfp@defaultopt}, but then we'd have the redundant step of checking
+% for an empty optional argument, only to replace it by an empty argument.
+% That might not make a significant difference, but it just feels wrong.
+%
+% Both commands turn the delimited argument, if present, into an ordinary
+% one. This extra step permits us to avoid many bracket pairs in later
+% code.
+% \begin{macrocode}
+\newdef\mfp@defaultopt#1#2{%
+ \@ifnextchar[{\mfp@ifemptyopt{#1}{#2}}{#1{#2}}}%]
+\newdef\mfp@ifemptyopt#1#2[#3]{\mfp@ifempty{#3}{#1{#2}}{#1{#3}}}%
+\newdef\mfp@nullopt#1{\@ifnextchar[{\mfp@getopt{#1}}{#1{}}}%
+\newdef\mfp@getopt#1[#2]{#1{#2}}%
+% \end{macrocode}
+%
+% Why do we bother to check for an empty optional argument? Because
+% quite a few \mfpic{} commands stuff several parameters into a
+% single optional argument. All but the last are processed as undelimited
+% arguments and the last one as delimited by the right bracket. If only
+% the last parameter is missing, TeX{} takes that as an empty argument and
+% we can proceed gracefully (substituting a default). However, if more
+% than that are missing, \TeX{} takes the closing bracket as the
+% \emph{undelimited} argument and produces pretty inscrutable error
+% mesages. This decision to add extra information in one optional argument
+% was, in retrospect, a bad one. It was made for backward compatibility
+% and (originally) to minimize the changes in existing commands.
+% Unfortunately we are stuck with it for at least the near future.
+%
+% Another reason is that multiple optional arguments generally mean that
+% the to specify a later one, all the previous ones need to be specified.
+% But with the above code, the user can always use an empty bracket pair
+% to indicate the default, minimizing the extra typing.
+%
+%
+%
+% \section{Writing to the \file{.mf} or \file{.mp} file}\label{writing}
+%
+%
+% \subsection{Preserving linebreaks}\label{linebreaks}
+%
+% Some macros (the ones we call list macros) can take quite long
+% arguments, especially if they are automatically generated by some
+% program. While the output file need not ever be looked at, there can be
+% a problem with lines too long for the \MF{} executable's line buffer.
+% Plus, for debugging, we might want to examine the file \mfpic{} writes.
+% We therefore try to get at least the list macros to preserve linebreaks
+% on output.
+%
+% We make use of the \TeX{} property that expandable commands are expanded
+% inside \cs{write} commands, but unexpandable commands and characters are
+% written verbatim (almost). If this were the only consideration, nothing
+% would need to be done. But characters with catagory code 5 (end-of-line)
+% are converted to spaces upon reading, so we have to change the category
+% of the \cs{endlinechar}, or we have change the \cs{endlinechar} to a
+% character of a different category. We do the former, because the line a
+% macro starts on will already have the end-of-line character added, but
+% it will not yet have been tokenized, so its category can be changed. We
+% need a category that \TeX{} will not \emph{ignore}, but that
+% nevertheless has no (or minimal) side effects if encountered in a \TeX{}
+% file. We therefore make it active, but \cs{let} it equal to \cs{relax}.
+% This makes the end-line-character unexpandable since \cs{relax} is not
+% expandable.
+% \begin{macrocode}
+\mfp@DBlog{Direct output to Metafont/Post file.}%
+{%
+ \catcode\mfp@ctrlM\active%
+ \gdef\@activectrlM{^^M}%
+ \gdef\mfp@obeylines{\catcode\mfp@ctrlM\active\let^^M\relax}%
+}%
+% \end{macrocode}
+%
+% The choice \cs{relax} seems to be actually a slightly better choice
+% than \cs{endgraf} (which we used to use, and which equals the
+% unexpandable primative \cs{par}) because \cs{relax} is permitted before
+% the opening brace in the syntax of \meta{general text} (for token
+% variable assignments, \cs{write}, \cs{message}, and the like).
+%
+% The character assigned to \cs{endlinechar} is added to the end of all
+% lines read in by \TeX. The character assigned to \cs{newlinechar}
+% will produce a newline when it occurs in a \cs{write}. Our
+% \cs{mfp@keeplines} ensures these are the same and makes the above
+% changes in category. This will fail in the following case:
+% \cs{endlinechar} is not \verb$^^M$ and the data starts on the same line
+% as the command that issued \cs{mfp@keeplines}. But then the output will
+% lack only that first linebreak.
+% \begin{macrocode}
+\newdef\mfp@keeplines{\newlinechar\mfp@ctrlM
+ \endlinechar\newlinechar \mfp@obeylines}%
+% \end{macrocode}
+%
+% We want our file writes to issue \cs{mfp@keeplines} before the text is
+% read (and category codes assigned). Also we often want to add a few
+% items to the argument (figure macros append a semi-colon, list macros
+% surround with parentheses), so we isolate the common starting code in
+% \cs{mfp@write}, and then invoke the appropriate continuation command.
+%
+% \DescribeMacro{\mfsrc}
+% The macro \cs{mfsrc} is the most basic, merely writing its contents. For
+% figure macros, we ultimately call
+% \DescribeMacro{\mfcmd}
+% \cs{mfcmd}, which appends a semicolon, terminating any pending \MF{}
+% command. For macros which take a comma separated list of values as their
+% arguments, we call
+% \DescribeMacro{\mflist}
+% \cs{mflist} which surrounds the list in parentheses and appends a
+% semicolon
+%
+% The ending code is in \cs{mfp@src}. The \cs{begingroup} in
+% \cs{mfp@write} matches the \cs{endgroup} in \cs{mfp@src}. The group
+% isolates the changes to EOLs. We also define \cs{@nl} to expand to an
+% active control-M so that it can be used for line breaks in cases where
+% it is inconvenient to make EOLs active (in the replacement text of
+% \cs{opengraphsfile} and \cs{@mfpic}, for example).
+% \begin{macrocode}
+\newdef\mfsrc {\mfp@write\mfp@src\mfsrc}%
+\newdef\mfcmd {\mfp@write\mfp@cmd}%
+\newdef\mflist{\mfp@write\mfp@wlist}%
+\newdef\mfp@write{\begingroup\mfp@keeplines \let\@nl\@activectrlM}%
+% \end{macrocode}
+%
+% The macro \cs{mfp@src} does the job of writing to files. The output
+% stream \cs{mfp@out} is declared later. The other two commands invoke
+% \cs{mfp@src} on a slightly modified argument. The first argument to
+% \cs{mfp@src} is the command that called it (for the error message), the
+% second is the code to write.
+% \begin{macrocode}
+\newdef\mfp@src#1#2{%
+ \mfp@ifopengraphsfile{\immediate\write\mfp@out{#2}}%
+ {\mfp@nooutput@error{#1}}\endgroup}%
+\newdef\mfp@cmd#1{\mfp@src\mfcmd{#1;}}%
+\newdef\mfp@wlist#1{\mfp@src\mflist{(#1);}}%
+% \end{macrocode}
+%
+% If \prog{babel} is loaded with some options, certain punctuation will
+% be made active. These will then be expanded when written to the graph
+% file. \prog{Babel} provides a way to turn this off, but it would be an
+% error to run those commands if \prog{babel} is not loaded. Rather than
+% try to detect \prog{babel}, we run these commands only if they are
+% defined.
+% \begin{macrocode}
+\def\mfp@safe@activestrue{%
+ \mfp@ifdefined\@safe@activestrue\@safe@activestrue{}}%
+\def\mfp@safe@activesfalse{%
+ \mfp@ifdefined\@safe@activesfalse\@safe@activesfalse{}}%
+% \end{macrocode}
+%
+%
+% \subsection{Initializing the output file}\label{output}
+%
+% Category 12 characters percent, sharp and backslash signs for the
+% \file{.mf} file. The command \cs{mfp@d} is used to write a line of
+% dashes above and below each figure to make them stand out when debugging
+% the file.
+% \begin{macrocode}
+\edef\mfp@p{\@xp\@gobble\string\%}% percent (%)
+\edef\mfp@s{\@xp\@gobble\string\#}% sharp (#)
+\edef\mfp@b{\@xp\@gobble\string\\}% backslash (\)
+\newdef\mfp@d{--------------}%
+% \end{macrocode}
+%
+% The current date and time stamp will be written to the \file{.mf} file.
+% We calculate it here and store the result in these macros. The commands
+% \cs{normalyear} and \cs{normalmonth} are part of \ConTeXt, where they
+% have been equated to the primitive commands \cs{year} and \cs{month}
+% (which are then redefined).
+% \begin{macrocode}
+\mfp@ifdefined\two@digits{}%
+ {\def\two@digits#1{\ifnum#1<10 0\fi\number#1}}%
+{%
+ \mfp@ifdefined\normalmonth
+ {\let\month\normalmonth\let\year\normalyear}{}%
+ \count@\time \divide\count@ by 60
+ \xdef\mfp@now{\number\year/\two@digits\month/\two@digits\day
+ \space at \two@digits\count@:}%
+ \multiply\count@ by -60 \advance\count@\time
+ \xdef\mfp@now{\mfp@now\two@digits\count@}%
+}%
+% \end{macrocode}
+%
+% These registers are allocated:
+% \begin{itemize}
+% \item \cs{mfp@out} Write stream for the \file{.mf} or \file{.mp} file.
+% \item \cs{mfp@graph} Read stream used to test existence of files and
+% for reading datafiles.
+% \item \cs{mfp@count} Number for next \env{mfpic} environment.
+% \item \cs{mfp@linetype} Number indexing current line style in
+% multi-curve data plots.
+% \item \cs{mfp@sequence} Counter incremented with every datapoint written
+% from a file to implement the feature that a list of numeric data
+% can be plotted against its sequence position.
+% \item \cs{mfp@toks} Temporary token register.
+% \item \cs{mfp@verbtex} A temporary token list used by \cs{mfpverbtex}.
+% \item \cs{ifmfp@switch} Not exactly a register, but a temporary
+% switch for passing information from one macro to another.
+% \end{itemize}
+% \begin{macrocode}
+\mfp@DBlog{Declarations used with data and graphs files.}%
+\newwrite\mfp@out
+\newread\mfp@graph
+\newlet\mfp@data\mfp@graph
+\newcount\mfp@count
+\newcount\mfp@linetype
+\newcount\mfp@sequence
+\newtoks\mfp@toks
+\newtoks\mfp@verbtex
+\newif\ifmfp@switch
+%</tex>
+% \end{macrocode}
+%
+% We store most of the \mfc{verbatimtex} block that \mfpic{} relies on in
+% the file \file{mfpicdef.tex}. This is the code that goes into that
+% file
+%
+% The \cs{mpxshipout} is to cover all three cases of the output of
+% `\texttt{mpto -tex}'. In public versions of \MP{} prior to 0.9 there was
+% no such command in that output file. In 0.9 and 0.901 that command is
+% defined at the start of the file, prior to any verbatimtex, but it is
+% buggy. This code overwrites it and fixes the bugs. In later versions a
+% good definition is used, but it appears only just before the first
+% \mfc{btex} and so will overwrite my definition. Thus all cases are
+% served.
+% \begin{macrocode}
+%<*defs>
+\gdef\mpxshipout{\afterassignment\middlempxshipout\setbox0=\hbox}%
+\gdef\middlempxshipout{\aftergroup\finishmpxshipout}%
+\gdef\finishmpxshipout{\dimen1=\ht0 \dimen2=\dp0
+ \dimen0=\dimen1 \advance\dimen0\dimen2
+ \setbox0=\hbox{\hbox{\box0
+ \ifnum\dimen0>0 \vrule width1sp height\dimen1 depth\dimen2
+ \else \vrule width1sp height1sp depth0sp\relax
+ \fi}}%
+ \ht0=0pt \dp0=0pt \shipout\hbox{\box0}}%
+\def\MFPtext#1{\vbox{\def\\{\cr}\MFPcfont\MFPeverylabel
+ \halign{##\hfil\cr#1\crcr}}}%
+% \end{macrocode}
+%
+% There are vague plans to make the output file equally usable by \MF{}
+% and \MP{}. For this to work, \file{grafbase.mf} defines
+% \mfc{verbatimtex} to gobble everything to the next colon (which we place
+% after each \mfc{etex} we write). This fails if there is a
+% \verb$\begingroup$ without matching \verb$\endgroup$ because \MF{} sees
+% this as the command \verb$\$ (meaning \mfc{relax}) followed by the \MF{}
+% primitive \mfc{begingroup}. But \MF{} doesn't allow gobbled text
+% parameters to contain unbalanced groups. Thus, we use the replacements
+% defined here, hidden from \MF{} in a \TeX{} input file.
+% \begin{macrocode}
+\let\MFPbegingroup\begingroup
+\let\MFPendgroup\endgroup
+%</defs>
+% \end{macrocode}
+%
+% Within \file{mfpic.tex} these commands can be anything unexpandable,
+% since we just want them to be written verbatim. It makes sense to give
+% them the obvious meanings.
+% \begin{macrocode}
+%<*tex>
+\let\MFPbegingroup\begingroup
+\let\MFPendgroup\endgroup
+% \end{macrocode}
+%
+% We store the first several lines that will be written to the output
+% file in a few internal macros, so that changing them will be easier.
+%
+% The first two lines of the output file are comments identifying the
+% file, the \mfpic{} version, the tex source file, and the timestamp.
+% These are stored in \cs{mfp@versioninfo}. We also let \grafbase{} know
+% the \mfpic{} version creating the file. This could catch version
+% mismatches. But since older \grafbase{} didn't test this, some
+% mismatches will be missed.
+%
+% After that (\cs{mfp@init@outfile}) we set the \mfc{mode} and the
+% \mfc{mag} if not known (both ignored by \MP), and arrange for
+% \grafbase{} macros to be loaded.
+% \begin{macrocode}
+\newdef\mfp@versioninfo{%
+ \mfp@p\space\mfp@filename.m\mfp@ifmpost{p}{f}, %
+ generated by Mfpic, v\mfpfileversion\space\mfpfiledate,\@nl
+ \mfp@p\space from TeX source "\jobname" on \mfp@now\@nl
+ numeric mfpicversion; mfpicversion := \mfpicversion;\@nl}%
+\newdef\mfp@init@outfile{%
+ if unknown mode: mode := localfont; fi\@nl
+ if unknown mag: mag := \number\mag/1000; fi\@nl
+ if unknown grafbase: input grafbase; fi\@nl\@nl}%
+% \end{macrocode}
+% Then a comparison of the version of this file, stored in
+% \cs{mfpicversion} with the version stored in the \grafbase{} variable
+% \mfc{grafbaseversion}. This should catch a mismatch caused by an old
+% \grafbase{} with a current \mfpic.
+% \begin{macrocode}
+\newdef\mfp@versioncheck{%
+ if unknown grafbaseversion: grafbaseversion := 0; fi\@nl
+ if grafbaseversion <> mfpicversion :\@nl
+ GBmsg "Bad mfpic installation: mfpic and grafbase %
+ versions do not match.";\@nl
+ fi\@nl}%
+% \end{macrocode}
+%
+% This opens the output file and prints a reminder to the user to run
+% \MF{} or \MP{}.
+% \begin{macrocode}
+\newdef\mfp@openfile{%
+ \ifmfp@nowrite \else \mfp@msg{}%
+ \Mfpic@msg{Initializing \mfp@filename\mfp@ext.}%
+ \immediate\openout\mfp@out=\mfp@filename\mfp@ext\relax
+ \Mfpic@msg{Don't forget to process \mfp@filename\mfp@ext!}%
+ \Mfpic@msg{Apply \mfp@progname\space to \mfp@filename\mfp@ext%
+ \mfp@ifmpost{}{, then gftopk to the resulting gf file}.}%
+ \Mfpic@msg{Then reprocess this file "\jobname".\@nl}%
+ \fi}%
+% \end{macrocode}
+%
+% A little bit of \LaTeX{} for checking file existence.
+% \begin{macrocode}
+\mfp@ifundefined\IfFileExists
+ \def\IfFileExists#1{\openin\mfp@graph=#1\relax
+ \ifeof\mfp@graph \@xp\@secondoftwo
+ \else \immediate\closein\mfp@graph \@xp\@firstoftwo
+ \fi}%
+ \def\InputIfFileExists#1#2{\IfFileExists{#1}{#2\input #1\relax}}%
+\mfp@enddef
+% \end{macrocode}
+%
+% The following is the code involved in opening the output file and
+% checking for the existence of already created figures.
+% \cs{mfp@checkoutput} checks if the output file of \MP{} or \MF{} exists.
+% The first argument is the extension of that output file (\file{tfm} for
+% \MF{}, the starting value of the figure counter for \MP{}). We use the
+% existence of that output as a signal that there are graphics to be
+% included.
+%
+% Based on the file existence, we set the values of the draft switch, and
+% issue a message. Any other actions needed are passed as \arg2 (it
+% exists) and \arg3 (it doesn't). These are nonempty only under the
+% \opt{metafont} option: we load the font only if the \file{.tfm} exists,
+% otherwise we use a the \texttt{dummy} font.
+%
+% We do not try to load a nonexistent font because that might trigger some
+% \prog{maketfm} script which could be disastrous at this point, when the
+% \file{.mf} file is in an uncertain state.
+% \begin{macrocode}
+\newdef\mfp@checkoutput#1#2#3{%
+ \IfFileExists{\setfilename\mfp@filename{#1}}%
+ {\global\mfpicdraftfalse #2}%
+ {\global\mfpicdrafttrue #3\mfp@msg{}%
+ \Mfpic@msg{No file \setfilename\mfp@filename{#1}.}%
+ }}%
+\newdef\mfp@checkMPoutput{\mfp@checkoutput{\number\mfp@count}{}{}}%
+\newdef\mfp@checkMFoutput{\mfp@checkoutput{tfm}%
+ {\global\font\mfp@graphfont\mfp@filename\relax}%
+ {\global\let\mfp@graphfont\mfp@dummy}}%
+% \end{macrocode}
+%
+% For \opt{metapost} the output file needs to load some color macros, and
+% write some setup for text labels (even if \cs{nomplabels}, because
+% \cs{usemplabels could be turned on later}). \MF{} now can also handle
+% the definitions in \file{dvipsnam.mp} but it seems a waste to load all
+% those definitions just to get more names for grayscales (even given
+% that \MF{} can find that file).
+% \begin{macrocode}
+\newdef\mfp@MPextras{\mfp@toks\@xp{\every@tlabel}%
+ \mfsrc{%
+ if unknown Apricot: input dvipsnam.mp; fi\@nl
+ verbatimtex\@nl
+ \ifmfp@verbtex \the\mfp@verbtex\@nl \fi
+ \relax\@nl
+ \noexpand\input mfpicdef.tex\relax\@nl
+ \def\noexpand\MFPeverylabel{\the\mfp@toks}\@nl
+ etex;\@nl
+ \mfp@ifdefined\mfp@settemplate\mfp@settemplate{}%
+ }%
+ \global\mfp@verbtexfalse \global\mfp@verbtex{}%
+% \end{macrocode}
+% Finally, we process the \MP{}-specific options as they are currently
+% known. The \cs{usemplabels} was delayed until now so that the order of
+% it and \cs{usemetapost} before now would not matter.
+% \begin{macrocode}
+ \@ifmplabels\usemplabels{}%
+ \ifmfp@truebbox \usetruebbox \fi
+ \ifmfp@overlabels \overlaylabels \fi}%
+% \end{macrocode}
+%
+% There are a couple of extras that are only needed by \MF{}, the mode
+% and resolution. Unlike the `MPextras' this does not write code, but
+% rather \emph{is} code to write. It will occur inside a \cs{write}
+% command.
+% \begin{macrocode}
+\def\mfp@MFextras{%
+ \mfp@ifdefined\mfp@resolution%
+ {GBresolution := \mfp@resolution;\@nl}{}%
+ \mfp@ifdefined\mfp@mode{mode := \mfp@mode;\@nl}{}}%
+% \end{macrocode}
+%
+% All the characters likely to cause problems in a filename are rendered
+% harmless with this command. We want to allow macros so backslashes,
+% braces and spaces aren't touched.
+% \begin{macrocode}
+\def\mfp@dospecials{\do\$\do\&\do\#\do\^\do\_\do\%\do\~}%
+% \end{macrocode}
+% \DescribeMacro{\opengraphsfile}
+% This is the main command to set up the output file.
+% The name of the output file is its only parameter, and it appends
+% the extension \file{.mf} or \file{.mp} depending on the whether option
+% \opt{metafont} or \opt{metapost} was chosen. We first nullify \TeX{}
+% special characters, then read the graphfile name, then store an
+% expanded version.
+% \begin{macrocode}
+\mfp@DBlog{Macros to open and close graphs files.}%
+\newdef\opengraphsfile{\@bsphack
+ \begingroup
+ \let\do\@makeother
+ \mfp@dospecials\@opengraphsfile}%
+\newdef\@opengraphsfile#1{%
+ \xdef\mfp@tempa{#1}%
+ \endgroup
+% \end{macrocode}
+%
+% With the graphfile name safely stored, we check if a previous one had
+% been opened and close it if so. Then we store in \cs{mfp@filename}
+% a sanitized version of the name.
+%
+% A command can determine if it occurs after \cs{opengraphsfile} but
+% before \cs{closegraphsfile} by testing whether \cs{mfp@filename} is
+% defined. We also save the name of the processing program (\MF{} or \MP)
+% and the file extension (\file{.mf} of \file{.mp}) in macros for use in
+% messages.
+% \begin{macrocode}
+ \mfp@ifopengraphsfile%
+ {\Mfpic@warn
+ {\@nl An attempt has been made to open a graph file, %
+ \mfp@sanitized\mfp@tempa\@msgbreak
+ while another, \mfp@filename, is still open. \@msgbreak
+ Closing \mfp@filename.}\mfp@closegraphsfile}%
+ {}%
+ \xdef\mfp@filename{\mfp@sanitized\mfp@tempa}%
+ \xdef\mfp@progname{meta\mfp@ifmpost{pos}{fon}t}%
+ \xdef\mfp@ext{.m\mfp@ifmpost{p}{f}}%
+% \end{macrocode}
+%
+% These commands test for the existence of the graphics (\file{.tfm} file
+% or first EPS file) and provisionally set \cs{ifmfpicdraft} based on the
+% result. Then the \file{.mf} or \file{.mp} file is opened, and the
+% automatic settings of \cs{ifmfpicdraft}, etc., are overridden if the
+% user has explicitly chosen the \opt{draft} or \opt{final} option. The
+% \opt{nowrite} option merely disables the \cs{mfp@src} command, called
+% by all the commands that write to the file.
+% \begin{macrocode}
+ \mfp@ifmpost\mfp@checkMPoutput\mfp@checkMFoutput
+ \mfp@openfile
+ \ifmfp@draft \global\mfpicdrafttrue \fi
+ \ifmfp@final \global\mfpicdraftfalse \fi
+ \ifmfp@nowrite \gdef\mfp@src##1##2{\endgroup}\fi
+% \end{macrocode}
+%
+% Now we set up the header and preamble of the output file, writing
+% version info, initializations, version checking code and extra code
+% for \MP{}, if required.
+%
+% Finally, we process options as they are currently known. These were
+% delayed until now because they might require a write to the output file.
+% Finally, we read the \prog{meta*o*t} log file, if the option to do that
+% is in effect.
+% \begin{macrocode}
+ \mfsrc{\mfp@versioninfo \mfp@ifmpost{}\mfp@MFextras
+ \mfp@init@outfile \mfp@versioncheck}%
+ \mfp@ifmpost\mfp@MPextras{}%
+ \ifmfp@clip \clipmfpic \fi
+ \ifmfp@clearsym \clearsymbols \fi
+ \ifmfp@noship \stopshipping \fi
+ \ifmfp@readlog \mfp@readlogfile \fi
+ \@esphack}%
+% \end{macrocode}
+%
+% \DescribeMacro{\closegraphsfile}
+% This command finishes off the output file and undefines \cs{mfp@filename}.
+% We define an error message free version \cs{mfp@closegraphsfile} for
+% internal use. We unconditionally undefine \cs{mfp@filename} just in
+% case.
+% \begin{macrocode}
+\newdef\closegraphsfile{%
+ \mfp@ifopengraphsfile{}{\mfp@nooutput@error\closegraphsfile}%
+ \mfp@closegraphsfile}%
+\newdef\mfp@closegraphsfile{%
+ \mfp@ifopengraphsfile
+ {\ifmfp@nowrite \else
+ \mfsrc{\@nl end.}\immediate\closeout\mfp@out
+ \fi \global\let\mfp@filename\UndEfInEd}{}}%
+% \end{macrocode}
+%
+%
+% \subsection{Information from \MF: reading its log file}
+%
+% \DescribeMacro{\assignmfvalue}\SpecialUsageIndex{\globalassignmfvalue}
+% This macro was suggested by Werner Lemberg, who also supplied working
+% code. I have made modifications, so I am to blame if it has bugs. It
+% writes code to the \file{.mf} file that causes \MF{} to write
+% information to its \file{.log} file. If the option \opt{mfpreadlog} has
+% been set, that log file will be examined for that information. The
+% result, for example, of
+% \begin{verbatim}
+% \setmfvariable{numeric}{s}{10}
+% \assignmfvalue\foo{s+2}
+% \end{verbatim}
+% is that \cs{foo} will be a macro that expands to `\texttt{12}' (during
+% the \TeX{} run following the \MF{} pass). Under \opt{mplabels} a label
+% containing \cs{foo} will only be correct in the \file{.mp} file after
+% the second \MP{} pass, and so a third \TeX{} run may be required to
+% insert the correct figure. To implement localization, the code causes
+% the internal command \cs{mfpic-\meta{N}-foo} to be defined to the value,
+% where \meta{N} is the number of the current figure. The \cs{foo} is then
+% defined to the value of that internal command. Outside any \env{mfpic}
+% environment, the internal command is \cs{mfpic--foo}. If the \file{.log}
+% file doesn't exist or doesn't yet contain the information, \cs{foo} is
+% defined to `???'.
+%
+% While \cs{mfpicvalue} is merely a signal and doesn't need a
+% definition, we give it a useful definition for debugging: its own name.
+% It could be accidentally redefined by a user, but that will be harmless;
+% the debugging is mainly for me.
+%
+% It is possible to put \cs{global} in front of \cs{assignmfvalue} and
+% its macro will be defined globally in the \TeX{} run, but I could find
+% no way to make it global in the \file{.mp} file under \opt{mplabels}.
+% Thus, I've created a \cs{globalassignmfvalue}.
+% \begin{macrocode}
+\edef\mfpicvalue{\string\mfpicvalue}%
+\newdef\mfp@cmdname{%
+ mfpic-\ifin@mfpicenv\number\mfp@count\fi-\@xp\@gobble\string}%
+\newdef\assignmfvalue{\mfp@assign\@empty}%
+\newdef\globalassignmfvalue{\mfp@assign\global}%
+\newdef\mfp@assign#1#2#3{%
+ #1\edef#2{%
+ \@ifundefined{\mfp@cmdname#2}{???}{\@nameuse{\mfp@cmdname#2}}}%
+ \@ifundefined{\mfp@cmdname#2}%
+ {\mfp@msg{}\Mfpic@msg{No value for \string#2\ifin@mfpicenv\space
+ in mfpic figure \number\mfp@count\fi.\@nl}}%
+ {}%
+ \mfsrc{%
+ \@ifmplabels{\@nl verbatimtex #1\def\string#2{#2} etex;\@nl}{}%
+ message "\string\mfpicvalue";\@nl
+ message "\mfp@cmdname#2";\@nl
+ show #3;\@nl
+ message "";}}%
+\newlet\assignmpvalue\assignmfvalue
+\newlet\globalassignmpvalue\globalassignmfvalue
+% \end{macrocode}
+%
+% The following code is what really makes \cs{assignmfvalue} work. It is
+% similar to code in the \prog{metatex} package, adapted by Werner Lemberg
+% and then modified by me. It steps through the \mfpic{} output file looking
+% for this signal: a line containing only `\verb$\mfpicvalue$'. It then
+% reads the next line, creates a macro name from it, and assigns to that
+% macro the value it reads on the next line. This is repeated to the end
+% of the file.
+% \begin{macrocode}
+\newdef\strip@gtgt>> #1\mfp@end{#1}%
+\newdef\mfp@readlogfile{%
+ \openin\mfp@data=\mfp@filename.log\relax
+ \ifeof\mfp@data \Mfpic@msg{No file \mfp@filename.log.}%
+ \else
+ {%
+ \mfp@resetwhitespace \endlinechar -1
+ \catcode`\>12
+ \def\@mfpicvalue{\mfpicvalue}%
+ \message{< Mfpic: Reading \mfp@filename.log}%
+ \mfp@readloglines
+ \message{>}%
+ }%
+ \fi \closein\mfp@data}%
+\newdef\mfp@readloglines{%
+ \read\mfp@data to \mfp@tempa
+ \ifeof\mfp@data
+ \else
+ \ifx\mfp@tempa\@mfpicvalue
+ \read\mfp@data to \mfp@tempa
+ \read\mfp@data to \mfp@tempb
+ \@XP\xdef\@nameuse\mfp@tempa{\@xp\strip@gtgt\mfp@tempb\mfp@end}%
+ \fi
+ \@xp\mfp@readloglines
+ \fi}%
+% \end{macrocode}
+%
+%
+%
+% \section{\Mfpic{} dimensions}\label{dimensions}
+%
+% A number of packages, especially figure drawing packages, allocate a
+% great many dimension registers. The most familiar example is \PiCTeX{}
+% which is at least partially responsible for most ``No room for a new
+% \cs{dimen}'' error messages. \Mfpic{} also needs many dimension
+% values, but some are set by macros that simply write the value to the
+% \file{.mf} file and do not use any registers. A few are stored in
+% \TeX{} registers, but most are stored using a trick with font
+% dimensions.
+% \begin{macrocode}
+\mfp@DBlog{Using dummy font's dimensions, to spare TeX registers.}%
+% \end{macrocode}
+%
+% While most fonts have relatively few font dimensions (twenty-two is a
+% common number), it turns out that if one loads a font and immediately
+% assigns a value to \cs{fontdimen}~$n$, Then \TeX{} acts as if the font
+% has \cs{fontdimen}\,s 0 through $n$ available. They can be assigned
+% dimension values just like \TeX{} dimension registers.
+%
+% Virtually all \TeX{} systems have a \file{dummy.tfm}, which contains
+% no characters (it is used for syntax checking by some packages and
+% classes). Since this trick will only work if we are the first to
+% load the font (the \AmSTeX{} document style \file{amsppt.sty} loads
+% the dummy font), we use another trick, which is to load it scaled to
+% some unlikely value, which \TeX{} treats as a new font.
+% \begin{macrocode}
+\font\mfp@dummy=dummy scaled 1042
+\fontdimen100\mfp@dummy0pt
+% \end{macrocode}
+%
+% Some versions of \file{dummy.tfm} have values already assigned to font
+% dimensions 0 through 22. It would probably not hurt to use those, but
+% we'll be cautious and use only font dimensions 23 and up, making 78
+% available.
+%
+% We use an auxiliary count register to keep track of new font dimens.
+% \begin{macrocode}
+\newcount\mfp@fdc
+\mfp@fdc22
+% \end{macrocode}
+%
+% We define a macros that mimics the behavior of \cs{newdimen}, for
+% allocating font dimension numbers. It increments \cs{mfp@fdc} and
+% defines its argument \arg{1} to expand to a reference to the
+% \cs{fontdimen} with that number. The syntax it produces is valid as
+% the left side of a dimension assignment and also as a dimension
+% that may follow a real factor and \cs{the}. For example, later we say
+% \cs{newfdim}\cs{pointsize} and give it the value \texttt{2pt}. Then
+% \verb$\the\pointsize$ prints this value and
+% \verb$\pointsize = 0.5\pointsize$ is a valid assignment.
+% \begin{macrocode}
+\newdef\newfdim#1{%
+ \global\advance\mfp@fdc1
+ \xdef#1{\fontdimen\number\mfp@fdc\mfp@dummy}%
+ \wlog{\string#1=\fontdimen\number\mfp@fdc\mfp@dummy}}%
+% \end{macrocode}
+% \TeX{} will not accept font dimensions in its syntax for the dimension
+% arithmetic commands \cs{advance}, \cs{multiply} and \cs{divide}. In the
+% rare cases where we need to do this we assign the value to a temporary
+% register and calculate with it.
+%
+% We allocate a couple of boxes. At the end of an \mfpic{}
+% environment, \cs{@wholegraph} is loaded with the picture (possibly
+% null) as it exists then. Inside the environment, when text labels are
+% processed, \cs{@textbox} holds this text temporarily so it can be
+% measured, moved about, etc. We also define abbreviations for the
+% frequent commands that specify the dimensions of \cs{@textbox}
+% \begin{macrocode}
+\mfp@DBlog{A box register for whole labeled graph, %
+ and a temporary one.}%
+\newbox\@wholegraph
+\newbox\@textbox
+\newdef\tb@ht{\ht\@textbox}%
+\newdef\tb@dp{\dp\@textbox}%
+\newdef\tb@wd{\wd\@textbox}%
+% \end{macrocode}
+%
+% When labels are processed, they are accumulated in the box
+% \cs{@alltlabels}. We allocate it, and four \cs{newfdim}\,s for the
+% location of three of the sides (We don't need the fourth). The box
+% \cs{@backtext} holds `background text', that is, text accumulated
+% between \cs{startbacktext} and \cs{stopbacktext}.
+% \begin{macrocode}
+\newbox\@alltlabels
+\newbox\@backtext
+\newfdim\@tlabelstop
+\newfdim\@tlabelsbot
+\newfdim\@tlabelsleft
+% \end{macrocode}
+%
+% The following fontdims record the dimensions of the box containing the
+% picture. We need to adjust them when the text labels are added to the
+% picture, because \TeX{} doesn't do it automatically. For example,
+% kerning left outside the picture will not change the picture box's
+% reference point.
+% \begin{macrocode}
+\mfp@DBlog{Internal dimension parameters for graph dimensions...}%
+\newfdim\@graphright
+\newfdim\@graphleft
+\newfdim\@graphtop
+\newfdim\@graphbot
+\mfp@DBlog{...and dimension parameters for tlabel positioning.}%
+\newfdim\tb@raise
+\newfdim\tb@moveright
+\newfdim\tb@totalht
+% \end{macrocode}
+%
+% The following are for label adjustments. The first two are used to
+% implement the feature that all labels can be simultaneously shifted an
+% equal amount. The third is for the feature that the label can be a
+% certain distance separated from the point where it is placed. And the
+% last establishes the distance between a label and a path surrounding it.
+% \begin{macrocode}
+\newfdim\tlabel@hadj
+\newfdim\tlabel@vadj
+\newfdim\tlabel@sep
+\newfdim\tlpath@sep
+\tlabel@hadj0pt
+\tlabel@vadj0pt
+\tlabel@sep0pt
+\tlpath@sep0pt
+% \end{macrocode}
+%
+% It can be argued that dimensions not needed by \TeX{} should be stored
+% in the output file rather than allocating (font) dimensions. These are
+% everything below from \cs{pointsize} through \cs{symbolspace},
+% inclusive. This would make synchrony between \TeX{} and \MF{} easier
+% to maintain. Those that are needed by \TeX{} are then few enough to be
+% regular \cs{dimen} registers, making them automatically local to each
+% \env{mfpic} environment. Unfortunately, changing to such a scheme could
+% break some past \mfpic{} files. It would also require recoding every
+% command that now writes one of these dimensions to the output.
+%
+% The following are default parameters for various graphics commands that
+% take an optional argument for the size of something.
+% \begin{itemize}
+% \item\cs{mfpicunit}\SpecialUsageIndex{mfpicunit}, the unit of length in
+% a picture. \cs{@mfpicunit} is used internally.
+% \item\cs{pointsize}\SpecialUsageIndex{pointsize}, the diameter of a
+% \cs{point}.
+% \item\cs{shadespace}\SpecialUsageIndex{shadespace}, the spacing of dots
+% in \cs{shade}.
+% \item\cs{polkadotspace}\SpecialUsageIndex{polkadotspace}, the spacing of
+% polkadots.
+% \item\cs{hatchspace}\SpecialUsageIndex{hatchspace}, the spacing of hatch
+% lines.
+% \item\cs{headlen}\SpecialUsageIndex{headlen}, the size of arrowheads
+% (except on axes).
+% \item\cs{axisheadlen}\SpecialUsageIndex{axisheadlen}, the size of the
+% arrowhead for $x$- and $y$-axes.
+% \item\cs{sideheadlen}\SpecialUsageIndex{sideheadlen}, the size of the
+% arrowhead for border axes.
+% \item\cs{hashlen}\SpecialUsageIndex{hashlen}, the length of tic marks on
+% axes.
+% \item\cs{dashlen}\SpecialUsageIndex{dashlen}, the length of dashes in
+% \cs{dashed}.
+% \item\cs{dashspace}\SpecialUsageIndex{dashspace}, the space between such
+% dashes.
+% \item\cs{dotsize}\SpecialUsageIndex{dotsize}, the size of dots for
+% \cs{dotted}.
+% \item\cs{griddotsize}\SpecialUsageIndex{griddotsize}, the size of dots
+% for \cs{grid} and \cs{plrgridpoints}.
+% \item\cs{dotspace}\SpecialUsageIndex{dotspace}, the space between such
+% dots.
+% \item\cs{symbolspace}\SpecialUsageIndex{symbolspace}, the space between
+% symbols used in a \cs{plot} command.
+% \end{itemize}
+% We allocate them, and then initialize them.
+% \begin{macrocode}
+\mfp@DBlog{User level dimension parameters, with default settings.}%
+\newfdim\mfpicunit
+\newfdim\@mfpicunit % internal version
+\newfdim\pointsize
+\newfdim\shadespace
+\newfdim\polkadotspace
+\newfdim\hatchspace
+\newfdim\headlen
+\newfdim\axisheadlen
+\newfdim\sideheadlen
+\newfdim\hashlen
+\newfdim\dashlen
+\newfdim\dashspace
+\newfdim\dotsize
+\newfdim\griddotsize
+\newfdim\dotspace
+\newfdim\symbolspace
+\mfpicunit1pt
+\pointsize2pt
+\shadespace1pt
+\polkadotspace10pt
+\hatchspace3pt
+\headlen3pt
+\axisheadlen5pt
+\sideheadlen0pt
+\hashlen4pt
+\dashlen4pt
+\dashspace4pt
+\dotsize0.5pt
+\griddotsize0.5pt
+\dotspace3pt
+\symbolspace5pt
+% \end{macrocode}
+%
+% Font dimensions are global, and so not restricted to an \env{mfpic}
+% environment even when assigned inside one. This would require the
+% user to restore a value every time one picture needed a different
+% value from the rest. To avoid requiring this, the following macro is
+% used to save all values of these dimensions at the start of a picture,
+% and to restore the saved values at the end. Some internal dimensions
+% (all the \cs{@graph...}, \cs{@tlabels...} and \cs{tb@...}) don't need
+% saving since they are reset with each picture.
+% \begin{macrocode}
+\newdef\save@mfpicdimens{%
+ \edef\restore@mfpicdimens{%
+ \mfpicunit \the\mfpicunit
+ \pointsize \the\pointsize
+ \shadespace \the\shadespace
+ \polkadotspace \the\polkadotspace
+ \hatchspace \the\hatchspace
+ \headlen \the\headlen
+ \axisheadlen \the\axisheadlen
+ \sideheadlen \the\sideheadlen
+ \hashlen \the\hashlen
+ \dashlen \the\dashlen
+ \dashspace \the\dashspace
+ \dotsize \the\dotsize
+ \griddotsize \the\griddotsize
+ \dotspace \the\dotspace
+ \symbolspace \the\symbolspace
+ \tlabel@hadj \the\tlabel@hadj
+ \tlabel@vadj \the\tlabel@vadj
+ \tlabel@sep \the\tlabel@sep
+ \tlpath@sep \the\tlpath@sep}}%
+% \end{macrocode}
+%
+% Here are the few dimension registers we do allocate:
+% \SpecialUsageIndex{\mfpframesep}\cs{mfpframesep}, and
+% \SpecialUsageIndex{\mfpframethickness}\cs{mfpframethickness}
+% govern frames.
+% \SpecialUsageIndex{\mfpicheight}\cs{mfpicheight} and
+% \SpecialUsageIndex{\mfpicwidth}\cs{mfpicwidth} are set
+% after each picture to that picture's size. A \cs{vskip} of
+% \SpecialUsageIndex{\mfpiccaptionskip}\cs{mfpiccaptionskip} is placed
+% between figure and caption by \cs{tcaption}. We also allocate a
+% frequently used scratch register
+% \begin{macrocode}
+\newdimen\mfp@scratch
+\newdimen\mfpframesep
+\newdimen\mfpframethickness
+\newdimen\mfpicheight
+\newdimen\mfpicwidth
+\newskip\mfpiccaptionskip
+\mfpframethickness0.4pt
+\mfpframesep2pt
+\mfpiccaptionskip\medskipamount
+% \end{macrocode}
+%
+%
+%
+% \section{Helper macros}\label{helper}
+%
+% \DescribeMacro{\mfpicnumber}
+% We make a user-level macro for setting the number of the next graph.
+% The original purpose of this is so that the font file could have
+% characters in the positions of printable characters. Then creating a
+% composite figure is as easy as changing fonts: \marg{\cs{pic} ABABAAB}.
+% The motivation came from a discussion on \texttt{comp.text.tex} started
+% by someone who wanted to input a sequence of 0's and 1's and get a
+% sequence of black and white squares. For \MP{} users it is not very
+% important.
+% \begin{macrocode}
+\def\mfpicnumber#1{\global\mfp@count#1\relax}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfpaddto}
+% When placing text at intervals on an axis, we need to automatically
+% calculate coordinates to feed to the \cs{tlabel} command. The
+% following is a utility macro to add two real numbers. It is currently
+% used only in the \cs{axislabels} command, so it needn't be globally
+% defined, but it might be handy in the future.
+% \begin{itemize}
+% \item[] \arg{1} is a \emph{macro} that expands to some number.
+% \item[] \arg{2} is a number to add to it.
+% \end{itemize}
+% The result is stored again in \arg{1}, overwriting the old value.
+%
+% \DescribeMacro{\mfpmultiply}
+% This is the multiplicative version, with the same syntax and behavior.
+% It is not used anywhere yet.
+% \begin{macrocode}
+\newdef\mfpaddto#1#2{\mfp@scratch#1pt \advance\mfp@scratch#2pt
+ \edef#1{\strip@pt\mfp@scratch}}%
+\newdef\mfpmultiply#1#2{\mfp@scratch#1pt \mfp@scratch#2\mfp@scratch
+ \edef#1{\strip@pt\mfp@scratch}}%
+\mfp@ifundefined\strip@pt
+ \begingroup
+ \lccode`\/`\p
+ \lccode`\?`\t
+ \lowercase{%
+ \endgroup
+ \def\rem@pt#1.#2/?}{#1\ifnum#2>\z@.#2\fi}%
+ \def\strip@pt{\@xp\rem@pt\the}%
+\mfp@enddef
+% \end{macrocode}
+%
+% \DescribeMacro{\pointdef}
+% A point defining macro, suggested by a user.
+% \begin{itemize}
+% \item[] \arg{1} is a symbolic name for a point, only letters.
+% \item[] \arg{2} and \arg{3} are the coordinates.
+% \item[] Usage: \cs{pointdef}\marg{A}\parg{2,5} makes \cs{A} expand
+% to \texttt{(2,5)}, \cs{Ax} to \texttt{2}, and \cs{Ay} to
+% \texttt{5}.
+% \end{itemize}
+% \begin{macrocode}
+\newdef\pointdef#1(#2,#3){%
+ \@ifundefined{#1} {}{\Mfpic@warn{\mfp@b#1 already defined.}}%
+ \@ifundefined{#1x}{}{\Mfpic@warn{\mfp@b#1x already defined.}}%
+ \@ifundefined{#1y}{}{\Mfpic@warn{\mfp@b#1y already defined.}}%
+ \@namedef{#1}{(#2,#3)}\@namedef{#1x}{#2}\@namedef{#1y}{#3}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\setmfarray}
+% This enables the simultaneous definition of \MF{} (or \MP) variables
+% such as \mfc{A1}, \mfc{A2}, etc., by writing
+% \cs{setmfarray}\marg{\meta{type}}\marg{\meta{name}}\marg{\meta{list}},
+% the \meta{name} being any \MF{} variable without a suffix, the list being
+% a comma separated list of items of the appropriate \meta{type}.
+% For example, \cs{setmfarray}\marg{pair} would require a list of
+% pairs.
+%
+% \SpecialUsageIndex{\numericarray}
+% As with \cs{setmfvariable}, we provide a few abbreviations.
+% \cs{numericarray} is for arrays of numeric variables,
+% \SpecialUsageIndex{\pairarray} \cs{pairarray} for arrays of pair
+% variables and \SpecialUsageIndex{\colorarray}\cs{colorarray} is for
+% arrays of color variables. Finally, to set arrays globally, there is
+% \SpecialUsageIndex{\globalsetmfarray}\cs{globalsetmfarray}.
+% \begin{macrocode}
+\newdef\setmfarray#1#2{\mfsrc{setarray (#1) (#2)}\mfp@writedata}%
+\newlet\setmparray\setmfarray
+\newdef\pairarray{\setmfarray{pair}}%
+\newdef\numericarray{\setmfarray{numeric}}%
+\newdef\colorarray{\setmfarray{color}}%
+\newdef\rgbcolorarray{\setmfarray{rgbcolor}}%
+\newdef\cmykcolorarray{\setmfarray{cmykcolor}}%
+\newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1)(#2)}\mfp@writedata}%
+\newlet\globalsetmparray\globalsetmfarray
+% \end{macrocode}
+%
+% \DescribeMacro{\lightershade}
+% Shade adjustment macros. \cs{lightershade} just multiplies
+% \cs{shadespace} by $1.2$.
+% \DescribeMacro{\darkershade}
+% While \cs{darkershade} divides by $1.2$ (actually, multiplies by
+% $1/1.2$)
+% \begin{macrocode}
+\newdef\lightershade{\shadespace1.2\shadespace}%
+\newdef\darkershade{\shadespace.83333\shadespace}%
+% \end{macrocode}
+%
+% \DescribeMacro{\dashlineset}
+% The following arrange for contrastive dashed lines. \cs{dashlineset}
+% just resets the default parameters that the \cs{dashed} macro uses,
+% \DescribeMacro{\dotlineset}
+% \cs{dotlineset} sets these parameters so that \cs{dashed} produces
+% something almost dotted.
+% \begin{macrocode}
+\newdef\dashlineset{\dashlen4pt \dashspace4pt }%
+\newdef\dotlineset{\dashlen1pt \dashspace2pt }%
+% \end{macrocode}
+%
+% \DescribeMacro{\pointfilltrue}
+% With the commands \cs{pointfilltrue} or \cs{pointfillfalse} the user
+% can specify points drawn with the \cs{point} command to be either
+% filled in or
+% \DescribeMacro{\pointfillfalse}
+% not.
+% \begin{macrocode}
+\let\ifpointfill\iftrue
+\newdef\pointfilltrue{\mfp@let\ifpointfill\iftrue}%
+\newdef\pointfillfalse{\mfp@let\ifpointfill\iffalse}%
+% \end{macrocode}
+%
+% \CMF{} has very flexible looping capabilities. Before version 0.8 there
+% was no \mfpic{} interface because it seemed that \cs{mfsrc} was the
+% simplest way to access this capability. Anything else would have to
+% be either a clone of \cs{mfsrc} or limit the possibilities. However, I
+% now believe it might be a good thing to have a structured way to perform
+% repetitive actions at the \MF{} level.
+%
+% As of version 0.9, \mfpic{} will allow loops outside \env{mfpic}
+% environments. It seems like a reasonable thing to be allowed to do.
+% Fortunately, the macro names are already unique.
+%
+% \DescribeMacro{\mfpfor}
+% This is the simplest: it writes the word \mfc{for} plus the contents of
+% its only mandatory argument, followed by a colon. The loop is ended by
+% \DescribeMacro{\endmfpfor}
+% \cs{endmfpfor} which merely writes the text \mfc{endfor}.
+% \begin{macrocode}
+\newdef\mfpfor#1{\begingroup\mfsrc{for #1:}}%
+\newdef\endmfpfor{\mfsrc{endfor}\endgroup}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfploop}
+% The macro \cs{mfploop} starts a loop with \mfc{forever}. The user is
+% expected to provide an escape condition with
+% \DescribeMacro{\mfpuntil}
+% \cs{mfpuntil}, which can be placed anywhere among the commands contained
+% in the \env{mfploop} environment.
+% \DescribeMacro{\endmfploop}
+% The macro \cs{endmfploop} is a clone of \cs{endmfpfor} except for the
+% warning. Grouping keeps the warning from being turned off if
+% \cs{mfpuntil} occurs in a nested loop.
+% \begin{macrocode}
+\newdef\mfploop{%
+ \begingroup\mfsrc{forever:}\let\@nountil\mfp@untilwarn}%
+\newdef\mfpuntil#1{\mfcmd{exitif #1}\let\@nountil\@empty}%
+\newdef\endmfploop{\@nountil\endmfpfor}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfpwhile}
+% This emulates a while-loop, the condition being given in the mandatory
+% argument. It has the same behavior, and writes almost the same code as
+% \cs{mfploop} with an immediate \cs{mfpuntil} using the negative of the
+% condition.
+% \DescribeMacro{\endmfpwhile}
+% The closing, \cs{endmfpwhile}, is again the same as \cs{endmfpfor}.
+% \begin{macrocode}
+\newdef\mfpwhile#1{\begingroup\mfcmd{forever: exitif not(#1)}}%
+\newlet\endmfpwhile\endmfpfor
+% \end{macrocode}
+%
+% \DescribeMacro{\plr}
+% A little utility to convert a list of pairs into another list of
+% pairs, where the given list are assumed to be polar coordinates and the
+% results are their Cartesian counterparts. This is guaranteed to work as
+% expected only in macros with a list argument, or for a single pair.
+% \DescribeMacro{\midpoint}
+% And one to calculate the midpoint, given two points separated by a comma.
+% Can be used in graphics macros where a point is required.
+% \begin{macrocode}
+\newdef\plr#1{map (polar) (#1)}%
+\newdef\midpoint#1{(0.5[#1])}%
+% \end{macrocode}
+%
+%
+%
+% \section{Macros to implement prefix commands}\label{prefix}
+%
+% Some \mfpic{} macros, like \cs{circle} create a path. When used without
+% a prefix, they also draw the path. At the \MF{} level, every figure
+% macro is syntactically a path expression. Other macros are prefix macros
+% and operate on a figure macro that follows. Every prefix accepts a path
+% expression as input and has a path as its return value, so a combination
+% prefix + path expression is again a path expression.
+%
+% Prefixes may also have side effects, such as adding some ink to the
+% current picture. Such prefixes are called \emph{rendering} macros.
+%
+% Rendering macros normally return the same path as their argument, but
+% there are macros that modify the path. Some apply a linear transform,
+% some close an open path, some return a subpath. These we call
+% \emph{modification} macros.
+%
+% This scheme is quite simple, but unfortunately too simple. To avoid
+% having to explicitly type a rendering prefix every time, a figure
+% macro needs to know if a rendering prefix has occured, so prefix macros
+% need to pass information to the figure macro (and to later prefixes).
+%
+% Moreover, \MF{} abhors an `isolated expression', so the first prefix
+% has to write something with a different syntax, and pass the info that
+% it has already done so on to later prefixes, who need to test that
+% info. Thus, every prefix macro needs to know if it is the first or a
+% later one. They test this \cs{if} command and also set it to false. The
+% figure macros, which are last in the chain, close by resetting it true.
+% \begin{macrocode}
+\mfp@DBlog{Tests to control multiple prefix commands.}%
+\newif\if@mfpstart\@mfpstarttrue
+% \end{macrocode}
+%
+% If a prefix is a rendering prefix, it writes its rendering code and sets
+% the following switch to false, letting the figure macro know it needn't
+% invoke the default rendering. Figure macros close by resetting it true.
+% Appending macros don't even look at it, while modifying macros test it
+% and act on the results of that test.
+% \begin{macrocode}
+\newif\if@mfprend\@mfprendtrue
+% \end{macrocode}
+%
+% The following macro is always (and only) invoked by the first prefix
+% macro (or the figure macro, if there are no prefixes). It writes the
+% code that prevents an isolated expression. It stores the following path
+% expression in the variable \gbc{curpath}. Thus every combination of
+% prefixes followed by a figure macro is syntactically a \MF{} variable
+% assignment command.
+% \begin{macrocode}
+\newdef\mfp@storepath{\mfsrc{\@nl store (curpath)}}%
+% \end{macrocode}
+%
+% Every prefix and figure macro has to invoke \cs{mfp@first}, since each
+% is potentially the first in the sequence. If \cs{@mfpstart} is true, it
+% writes the storing command, sets \cs{@mfpstartfalse}, and says that
+% rendering is needed. (The rendering macros immediately cancel that
+% switch.)
+% \begin{macrocode}
+\newdef\mfp@first{\relax
+ \if@mfpstart \mfp@storepath \@mfprendtrue \@mfpstartfalse\fi}%
+% \end{macrocode}
+%
+% Every rendering macro invokes this next command. After the first-stage
+% code it writes its rendering command (via \cs{mfsrc}) and passes on the
+% info that rendering is no longer required of the figure macro.
+% \begin{macrocode}
+\newdef\mfp@rendmac{\mfp@first \@mfprendfalse \mfsrc}%
+% \end{macrocode}
+%
+% The \emph{figure} macros proceed as follows: (i)~they invoke the
+% \cs{mfp@first} code, then (ii)~write a rendering macro if necessary
+% (\cs{mfp@autorend}), (iii)~then make \cs{@mfpstarttrue} (for the next
+% figure) and write \MF{} code that defines the path. The \cs{mfp@modmac}
+% macros do only the first two, then write their modification code,
+% counting on the following figure macro to do (iii). The idea is that
+% [modifier + figure] should act the same as if the path it defines were
+% encoded as a single figure command.
+% \begin{macrocode}
+\newdef\mfp@modmac{\mfp@first\mfp@autorend\mfsrc}%
+\newdef\mfp@autorend{\if@mfprend\@xp\mfp@render\fi}%
+% \end{macrocode}
+%
+% Only axis and arrow commands (plus \cs{reverse}) use \cs{mfp@addmac}.
+% As the name suggests, something is added onto an existing figure. That
+% is, it is designed to ignore the rendering state and not invoke implicit
+% rendering. If no explicit rendering occurs, the figure macro that
+% follows invokes a rendering. For arrows, this causes the arrowhead to be
+% drawn on top of the drawing of the shaft.
+%
+% It would seem \cs{reverse} doesn't fit this name, but it also needs to
+% be transparent to the rendering state so that it will work in
+% combination with arrows.
+%
+% \cs{mfp@addmac} simply invokes the common first-stage code and writes
+% its \MF{} code.
+% \begin{macrocode}
+\newdef\mfp@addmac{\mfp@first \mfsrc}%
+% \end{macrocode}
+%
+% The \cs{mfp@addmac} and \cs{mfp@modmac} macros differ when there are no
+% preceeding rendering macros. In that case it is as if \cs{draw} (or
+% more generally \cs{mfp@render}) precedes the \cs{mfp@modmac} macro. That
+% drawing happens \emph{in addition to} any rendering macros that follow.
+% This implicitly added \cs{draw} is not present for \cs{mfp@addmac}
+% macros; it is added by the following figure macro. The effect of this is
+% the \cs{mfp@addmac} macros perform their additions on top of an already
+% rendered figure.
+%
+% \DescribeMacro{\setrender}
+% As mentioned above, when a figure macro is invoked without a rendering
+% prefix, it will invoke some default. That default is stored in a macro
+% and can be changed for special effects. Initially we define it as
+% \cs{draw} (with empty optional argument) to draw solid paths in the
+% default color, but we provide a command for the user to change it.
+% \begin{macrocode}
+\newdef\mfp@render{\draw[]}%
+\newdef\setrender{\mfp@def\mfp@render}%
+% \end{macrocode}
+%
+% A figure macro will invoke the common first-stage code and the rendering
+% check. It also resets the \cs{@mfpstart} switch. Because a figure macro
+% completes an assignment command in \MF, it writes its code with
+% \cs{mfcmd}, which places a semicolon at the end. We define the first
+% part (all but the writing) as a separate command because there are a few
+% cases where we need to delay that writing.
+% \begin{macrocode}
+\newdef\mfp@figmacbase{\mfp@first \mfp@autorend \@mfpstarttrue}%
+\newdef\mfp@figmac{\mfp@figmacbase\mfcmd}%
+% \end{macrocode}
+%
+% The list macros take as their last argument a list of $(x,y)$ pairs (or
+% occasionally a list of numbers). That list can either be typed directly
+% into the \TeX{} source file (inside braces, separated by commas) or be
+% present in an external datafile. Either way, the data is written as a
+% list within an enclosing pair of parentheses. Since these are all
+% figure macros, \cs{mfp@listmac} starts out just like \cs{mfp@figmac},
+% but it writes only part of its arguments, the last one (the data list)
+% being handled by \cs{mfp@writedata}.
+%
+% \cs{mfp@writedata} looks ahead to see if the token \cs{datafile}
+% follows, if it does \cs{mfp@writefile} is invoked, which gobbles
+% the \cs{datafile} token and processes the filename that should follow it.
+% Otherwise, \cs{mflist} is invoked to write the list in braces
+% that should follow.
+%
+% \cs{mfp@writedata} is also used by non-figure macros such as the axis
+% marks macros, plus \cs{piechart} and \cs{barchart}.
+% \begin{macrocode}
+\newdef\mfp@listmac#1{\mfp@figmacbase\mfsrc{#1}\mfp@writedata}%
+\newdef\mfp@writedata{\mfp@iftoken\datafile{\mfp@writefile}{\mflist}}%
+\newdef\mfp@writefile{%
+ \mfp@ifopengraphsfile
+ {\mfp@processfile{\mfp@rwdata}}{\mfp@nooutput@error\datafile}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mftitle}
+% This is mainly for debugging the example files. \cs{mfp@title} takes
+% two arguments: the command that called it (for the error message of
+% \cs{mfp@src}), and some \TeX{} code. That code is written into the string
+% argument of the \grafbase{} command \gbc{mftitle} and ends up in the
+% \MF{} \file{.log} file and as a comment in the GF file. \cs{mftitle}
+% merely calls \cs{mfp@title}, while
+% \DescribeMacro{\tmtitle}
+% \cs{tmtitle} also writes the argument to the \TeX{} \file{.log} file and
+% typesets it in the document.
+%
+% We write the argument as a token list because that is the the easiest
+% verbatim-like way to do it.
+% \begin{macrocode}
+\newdef\mftitle#1{\@bsphack\mfp@title\mftitle{#1}\@esphack}%
+\newdef\tmtitle#1{\mfp@title\tmtitle{#1}\wlog{\the\mfp@toks}{#1}}%
+\newdef\mfp@title#1#2{\mfp@toks{#2}%
+ \mfp@write\mfp@src#1{mftitle "\the\mfp@toks";}}%
+% \end{macrocode}
+%
+%
+%
+% \section{Macros for getting data from files}\label{rwdata}
+%
+% The following command contains the common code to open a data file for
+% reading. The second parameter is the filename, the first is what to do
+% if it exists and is nonempty. We first try to \cs{openin} the file and
+% issue an error message if that fails. Then we skip any initial blank
+% lines and comments and complain if that takes us to the end of the
+% file. Otherwise we execute the command specified. Afterwards, since
+% each \cs{plotdata} command in a given \env{mfpic} environment
+% starts with the linetype at which the previous one ended, we allow the
+% value of \cs{mfp@linetype} to survive this group but not any enclosing
+% group.
+% \begin{macrocode}
+\newdef\mfp@processfile#1#2{%
+ \openin\mfp@data=#2\relax
+ \ifeof\mfp@data \mfp@nofile@error{#2}%
+ \else
+ \mfp@DBlog{Opening file #2 for data.}%
+ {%
+ \mfp@resetwhitespace \mfp@setcomment
+ \mfp@skipblanklines
+ \ifeof\mfp@data
+ \mfp@nodata@error{#2}%
+ \else
+ \message{< Mfpic: Reading #2}%
+ #1%
+ \message{>}%
+ \fi
+ \@xp
+ }\@xp\mfp@linetype\number\mfp@linetype\relax
+ \mfp@DBlog{Closing file #2.}%
+ \fi
+ \closein\mfp@data}%
+% \end{macrocode}
+%
+% When reading files it is important that white space in the files
+% always have the same meaning for \TeX{}. This utility resets spaces,
+% tabs and EOLs to the standard categories.
+% \begin{macrocode}
+\newdef\mfp@resetwhitespace{\mfp@restorepar
+ \endlinechar`\^^M \catcode`\^^M5 \catcode`\ 10 \catcode`\^^I10 }%
+% \end{macrocode}
+%
+% \cs{mfp@skipcomments}
+% does what it says, skipping comments in a data file. It reads a
+% line from a previously opened file (input stream \cs{mfp@data}) and
+% compares it to \cs{@empty}. It calls itself when they are equal (a
+% comment line, a blank line would put a \cs{par} token in \cs{mfp@data}).
+% When this macro finishes, \cs{mfp@temp} contains either \cs{par} (blank
+% line or EOF) or real data.
+% \begin{macrocode}
+\newdef\mfp@skipcomments{\read\mfp@data to \mfp@temp
+ \ifx\mfp@temp\@empty \@xp\mfp@skipcomments\fi}%
+% \end{macrocode}
+%
+% \cs{mfp@skipblanklines}
+% first skips comments. After that \cs{mfp@temp} can contain \cs{par},
+% indicating either EOF or a blank line, or something else. In the first
+% case (EOF) the macro terminates, in the second case (blank) it calls
+% itself again, in the other case (something else) it also terminates,
+% having presumably found real data.
+%
+% When this is called, a file should already be open using the handle
+% \cs{mfp@data}.
+% \begin{macrocode}
+\newdef\mfp@skipblanklines{\mfp@skipcomments
+ \ifeof\mfp@data
+ \else\ifx\mfp@temp\mfp@par \@XP\mfp@skipblanklines
+ \fi\fi}%
+% \end{macrocode}
+%
+% The following two commands, \cs{mfp@rwdata} and \cs{mfp@rwdataloop}
+% perform the work of writing the file (read stream \cs{mfp@data} opened
+% by \cs{mfp@processfile}).
+%
+% The figure counter \cs{mfp@count} is reused (this should all be inside
+% a group) to keep track of how many lines of the data file have been
+% written to one line of the output. The token \cs{sequence} in a
+% \cs{using} specification will expand to the value of the counter
+% \cs{mfp@sequence}.
+%
+% When \cs{mfp@rwdata} is called, a non-blank line has been read to the
+% macro \cs{mfp@temp}, to which we now add a space. The macro
+% \cs{mfp@buffer} is what will be written to the output file as soon as it
+% is long enough. We initialize it by defining it to be an open
+% parenthesis followed by the result of applying \cs{parse@data} to the
+% contents of \cs{mfp@temp}. Then we call \cs{mfp@rwdataloop}, which does
+% the remaining reading and all the writing.
+% \begin{macrocode}
+\newdef\mfp@nextdatum{\@xp\parse@data\mfp@temp\mfp@end}%
+\newdef\mfp@rwdata{\mfp@count1 \mfp@sequence1
+ \def\sequence{\number\mfp@sequence}%
+ \edef\mfp@temp{\mfp@temp\space}%
+ \edef\mfp@buffer{(\mfp@nextdatum}\mfp@rwdataloop}%
+% \end{macrocode}
+%
+% At this point, the buffer has been started with the first datum, so we
+% read another line. If that is blank, we write the buffer (and the closing
+% parenthesis and a semicolon) and terminate the loop. Otherwise we have
+% read another datum and then we:
+% \begin{enumerate}
+% \item increment the sequence counter,
+% \item add a comma to the buffer,
+% \item test whether the buffer is `full', and if so, write the buffer
+% to the output and clear it, then
+% \item add the datum to the buffer.
+% \end{enumerate}
+% The buffer is `full' when \cs{mfp@count} (the number of data in the
+% buffer) exceeds \cs{mfp@dataperline}.
+%
+% \cs{mfp@rwdataloop} loops by calling itself at the end. Whenever
+% \cs{mfp@temp} is empty (comment line read), (1)--(4) are skipped and
+% another line read.
+% \begin{macrocode}
+\newdef\mfp@rwdataloop{%
+ \read\mfp@data to \mfp@temp
+ \ifx\mfp@temp\mfp@par
+ \mfcmd{\mfp@buffer)}%
+ \else
+ \ifx\mfp@temp\@empty
+ \else
+ \edef\mfp@temp{\mfp@temp\space}%
+ \advance\mfp@sequence1
+ \edef\mfp@buffer{\mfp@buffer\mfp@join}%
+ \ifnum\mfp@count<\mfpdataperline\relax \advance\mfp@count1
+ \else \mfsrc{\mfp@buffer}\mfp@count1 \def\mfp@buffer{}%
+ \fi
+ \edef\mfp@buffer{\mfp@buffer\mfp@nextdatum}%
+ \fi
+ \@xp\mfp@rwdataloop
+ \fi}%
+% \end{macrocode}
+%
+% \section{Various \mfpic{} Settings.}\label{mfpsettings}
+%
+% \subsection {\CMF{} settings}\label{MFsettings}
+%
+% \DescribeMacro{\penwd}
+% Macros that write changes in default \grafbase{} variables now use the
+% construct ``\gbc{save x; <type> x; x := <value>;}'' (via a call to
+% \cs{setmfvariable}). This makes changes local if inside a given \env{mfpic}
+% environment, global if outside. An exception is \gbc{penwd} which, as an
+% internal variable uses `\gbc{interim}' instead (via the \grafbase{}
+% command \gbc{resizedrawpen}).
+%
+% \SpecialUsageIndex{\drawpen}
+% \cs{drawpen} was the original command used to set the pen diameter
+% (prior to version 0.2.13). At some point it was replaced by
+% \SpecialUsageIndex{\pen}\cs{pen}. However \cs{penwd} seems to be more
+% consistent with other commands (e.g., \cs{shadewd}), and we keep all three.
+% \begin{macrocode}
+\newdef\pen#1{\mfcmd{\@nl resizedrawpen (#1)}}%
+\newlet\penwd\pen \newlet\drawpen\pen
+% \end{macrocode}
+%
+% \DescribeMacro{\shadewd}
+% The \cs{shade} macro works in \MF{} by adding many copies of the small
+% picture \gbc{shadedot} to the figure, in \MP{} the parameters
+% \gbc{shadewd} and \cs{shadespace} are simply used to calculate a level
+% of gray and a color fill is used.
+%
+% \DescribeMacro{\polkadotwd}
+% However, both \MF{} and \MP{} handle polkadots the same. The only
+% difference is \MF's need for fitting to a pixel grid. But that is
+% handled in \grafbase.
+% \begin{macrocode}
+\newdef\shadewd#1{\setmfnumeric{shadewd}{#1}}%
+\newdef\polkadotwd#1{\setmfnumeric{polkadotwd}{#1}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\hatchwd}
+% The thickness of lines in the hatching fill is set by \cs{hatchwd}.
+% \begin{macrocode}
+\newdef\hatchwd#1{\setmfnumeric{hatchwd}{#1}%
+ \setmfvariable{pen}{hatchpen}{pencircle scaled hatchwd}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\dashpattern}
+% A dash pattern consists (internal to \MF) of an array of lengths. The
+% \grafbase{} command \gbc{dashpat} accepts a name, and a sequence of
+% numbers representing the sizes of dashes and spaces, and builds this
+% array. It differs from \cs{numericarray} in that a little additional
+% checking is done (at the \grafbase{} level).
+% \begin{macrocode}
+\newdef\dashpattern#1{\mfsrc{save #1; dashpat (#1)}\mfp@writedata}%
+% \end{macrocode}
+%
+% \DescribeMacro{\settension}
+% This sets the default tension for any command (for example, \cs{curve})
+% that takes an optional argument that contains a tension value. This
+% includes also \cs{function}, \cs{plrfcn}, \cs{fcncurve}, \cs{datafile},
+% \cs{plotdata}. It also sets the default tension for \cs{sclosed} and
+% \cs{bclosed}. The value should be at least $3/4$.
+% \begin{macrocode}
+\newdef\settension#1{\setmfnumeric{default_tension}{#1}}%
+% \end{macrocode}
+%
+% \subsection{Settings for text label placement in figures}
+% \label{labelsettings}
+%
+% \cs{tlabel}\,s are `justified' by placing a particular point of the
+% text at the location specified. The \cs{tlabel} command accepts an
+% optional argument containing two letters. There are 4 possibilities
+% for the first and three for the second. It turns out to be easier to
+% process these if we have a command that converts these to numbers, and
+% then \cs{ifcase} can be used. There is a third part of the optional
+% argument usable only in \MP{}: a number indicating degrees of rotation.
+%
+% \DescribeMacro{\tlabeljustify}
+% The multi-part definition of \cs{tlabeljustify} is to guard
+% against confusing error messages if some part of this optional argument
+% is empty. The code assumes that if there are only 2, 1 or no parts, then
+% later parts should be left unchanged. The rotation part is empty by
+% default (rather than 0), because some commands will emit a warning if
+% a nonempty rotation exists without \opt{mplabels}.
+%
+% The result of \cs{tlabeljustify} is that \cs{tl@vpos} is set equal to
+% $-1$ if the first letter is (default) \texttt{B} (for Baseline), and
+% 0--2 if it is \texttt{b} (bottom), \texttt{c} (center) or \texttt{t}
+% (top). Similarly, \cs{tl@hpos} is set equal to $-1$ if the second
+% letter is (default) \texttt{l} (for left), and 0 or 1 if it is
+% \texttt{c} (center) or \texttt{r} (right). Making the defaults
+% negative means they must be handled by the \cs{else} portion of any
+% \cs{ifcase}.
+%
+% The rotation part is just saved in \cs{tl@rot}. This is true even
+% without \opt{mplabels}, in case it is turned on later. It is ignored by
+% \cs{tlabel} without \opt{mplabels}, but a warning is issued here anyway.
+% \begin{macrocode}
+\newcount\tl@vpos \newcount\tl@hpos
+\newdef\mfp@tlh@l{-1}%
+\newdef\mfp@tlh@c{0}%
+\newdef\mfp@tlh@r{1}%
+\newdef\mfp@tlv@B{-1}%
+\newdef\mfp@tlv@b{0}%
+\newdef\mfp@tlv@c{1}%
+\newdef\mfp@tlv@t{2}%
+\newdef\tl@rot{}\tl@vpos-1 \tl@hpos-1
+\newdef\tlabeljustify#1{\mfp@ifexist{#1}{\mfp@justify#1\mfp@end}}%
+\newdef\mfp@justify#1#2\mfp@end{\mfp@local\mfp@vconv{#1}%
+ \mfp@ifexist{#2}{\mfp@@justify#2\mfp@end}}%
+\newdef\mfp@@justify#1#2\mfp@end{\mfp@local\mfp@hconv{#1}%
+ \mfp@local\edef\tl@rot{#2}%
+ \@ifmplabels{}%
+ {\mfp@ifexist{#2}%
+ {\Mfpic@warn{Rotation of labels is not supported without the %
+ mplabels\@msgbreak option. Rotation setting\on@line\space
+ may be ignored.}}%
+ }}%
+\newdef\mfp@vconv#1{%
+ \@ifundefined{mfp@tlv@#1}%
+ {\tl@vpos-1 \mfp@justify@error}%
+ {\tl@vpos\@nameuse{mfp@tlv@#1}\relax}}%
+\newdef\mfp@hconv#1{%
+ \@ifundefined{mfp@tlh@#1}%
+ {\tl@hpos-1 \mfp@justify@error}%
+ {\tl@hpos\@nameuse{mfp@tlh@#1}\relax}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\tlpathjustify}
+% This acts just like \cs{tlabeljustify} from the user's point of view.
+% Since it is only for users, and not used internally, it merely defines
+% three macros that are passed to \cs{tlabeljustify} when no justification
+% parameter is present for a \cs{tlabel}-path command.
+% \begin{macrocode}
+\newdef\tlpathjustify#1{%
+ \mfp@ifexist{#1}{\tlp@justify#1\mfp@end}}%
+\newdef\tlp@justify#1#2\mfp@end{\mfp@def\tlpath@v{#1}%
+ \mfp@ifexist{#2}{\tlp@@justify#2\mfp@end}}%
+\newdef\tlp@@justify#1#2\mfp@end{%
+ \mfp@def\tlpath@h{#1}\mfp@def\tlpath@r{#2}}%
+\tlpathjustify{cc}%
+% \end{macrocode}
+%
+% \DescribeMacro{\tlpointsep}
+% This takes an absolute length as its argument and sets parameters that
+% determine by how much a tlabel is separated from the point it is placed
+% at. This is in case something is drawn at that point, such as a dot or
+% a hash mark on an axis.
+%
+% \DescribeMacro{\tlpathsep}
+% This takes an absolute length and sets parameters that determine by how
+% much a path created by one of the \cs{tlabel\meta{path}} macros is
+% separated from the label it surrounds.
+%
+% \DescribeMacro{\tlabelsep}
+% This simply issues both the above commands. This is for compatibility
+% with \mfpic{} versions 0.7 or earlier, where both these separations were
+% determined by the same parameters.
+%
+% \DescribeMacro{\tlabeloffset}
+% \cs{tlabeloffset}, on the other hand, takes two arguments: dimensions,
+% representing offsets of labels from their point of placement. This is
+% mainly so that, if labels seem to be off, they can all be shifted with
+% one command.
+%
+% Both these values are written to the \MF{} file for the sake of the
+% commands that draw rectangles or ovals around labels.
+% \begin{macrocode}
+\newdef\tlpointsep#1{\mfp@local\tlabel@sep#1\relax
+ \setmfnumeric{label_sep}{\the\tlabel@sep}}%
+\newdef\tlpathsep#1{\mfp@local\tlpath@sep#1\relax
+ \setmfnumeric{labelpath_sep}{\the\tlpath@sep}}%
+\newdef\tlabelsep#1{\tlpointsep{#1}\tlpathsep{#1}}%
+\newdef\tlabeloffset#1#2{%
+ \mfp@local\tlabel@hadj#1\relax \mfp@local\tlabel@vadj#2\relax
+ \setmfpair{label_adjust}%
+ {(\the\tlabel@hadj,\the\tlabel@vadj)}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\everytlabel}
+% Every line of a multiline label is written inside a group, so
+% adjustments to baselineskip and other things are difficult or
+% impossible. Therefore, \cs{everytlabel} is provided to define code to be
+% inserted before the label code, outside these groups. The messing around
+% with the token register \cs{mfp@toks} is so one can put definitions in
+% the code without having to double \arg{} characters.
+%
+% The command \cs{extra@endtlabel} is called at the end of every
+% \cs{tlabel}. Normally it does nothing, but the \cs{tlabels} command
+% defines it to repeat the start of a loop.
+% \begin{macrocode}
+\newdef\everytlabel{\afterassignment\mfp@everytlabel\mfp@toks}%
+\newdef\mfp@everytlabel{\mfp@local\edef\every@tlabel{\the\mfp@toks}%
+ \mfp@ifmpost
+ {\mfp@ifopengraphsfile
+ {\mfcmd{verbatimtex\@nl
+ \def\noexpand\MFPeverylabel{\the\mfp@toks} etex}}%
+ {}}%
+ {}}%
+\newdef\every@tlabel{}%
+\newdef\extra@endtlabel{}%
+% \end{macrocode}
+%
+% Without \opt{mplabels} it is impossible to use \MP{} variables in
+% a text label placement parameter. I have occasionally found it useful
+% to have a \TeX{} version of the numeric variable \gbc{pi}.
+% \begin{macrocode}
+\newdef\pinumber{3.14159}%
+% \end{macrocode}
+%
+% \subsection{Other settings}\label{othersettings}
+%
+% \DescribeMacro{\headshape}
+% This sets the arrowhead shape. The parameters are: the ratio of width
+% to length, the tension (see \file{grafbase.dtx}) and a boolean
+% (\gbc{true} or \gbc{false}) to say whether the the head is filled, or
+% only the barbs are drawn. It would be more consistent with other
+% commands to have one \TeX{} parameter with commas separating the
+% components, but this is legacy code.
+% \begin{macrocode}
+\newdef\headshape#1#2#3{\mfcmd{\@nl headshape (#1, #2, #3)}}%
+% \end{macrocode}
+%
+% There are up to 4 optional arguments to any given \cs{arrow} command,
+% and these can take any one of 6 special indicators ({\mytt b}, {\mytt c},
+% {\mytt f}, {\mytt l}, {\mytt r} or {\mytt s}). Here we define macros
+% to handle these options. Each macro is fed a \emph{value}. For example,
+% the indicator {\mytt b} must be followed by a length, and that length is
+% the argument of \cs{mfp@arr@b}.
+% \begin{macrocode}
+\newdef\mfp@arr@b#1{\edef\mfp@hlocate{#1}}%
+\newdef\mfp@arr@c#1{\edef\mfp@hcolour{#1}}%
+\newdef\mfp@arr@l#1{\edef\mfp@hlength{#1}}%
+\newdef\mfp@arr@r#1{\edef\mfp@hrotate{#1}}%
+\newlet\mfp@arr@f\mfp@arr@b
+\newlet\mfp@arr@s\mfp@arr@l
+% \end{macrocode}
+%
+% The \cs{arc} and \cs{circle} commands take an optional argument that
+% indicates how the arc or circle is defined (and therefore the format of
+% the non-optional argument). These are passed to different \grafbase{}
+% commands whose names start with \gbc{arc} or \gbc{circle}. The commands
+% below store the rest of that name. The switch is set true by the
+% \cs{arc} command and false by \cs{circle}.
+% \begin{macrocode}
+\newdef\mfp@arc@s{pps}%
+\newdef\mfp@arc@t{ppp}%
+\newdef\mfp@arc@p{\ifmfp@switch plr\fi}%
+\newdef\mfp@arc@a{\ifmfp@switch alt\fi}%
+\newdef\mfp@arc@c{cp\ifmfp@switch s\fi}%
+\newdef\mfp@arc@r{pp (\mfp@T)}%
+\newdef\mfp@arc@q{pp (\mfp@F)}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfpdefinecolor}
+% \prog{Mfpic} supports color under \MP{} by writing all color
+% definitions to the output \file{.mp} file. In order to support a
+% \LaTeX-like color syntax, all the color models allowed by the color
+% package correspond to a \grafbase{} function that returns a \MP{}
+% color value. For example, \gbc{cmyk(.3,.3,0,.7)} returns \gbc{(0,0,.3)},
+% a very dark blue. This can be set by
+% \cs{mfpdefinecolor}\marg{vdblue}\marg{cmyk}\marg{.3,.3,0,.7}.
+%
+% Several commands are provided to set certain special colors. Currently
+% we have the following commands, setting the color of the same name as
+% the command (except \cs{backgroundcolor} which sets a color named
+% \gbc{background}):
+% \cs{drawcolor}\SpecialUsageIndex{\drawcolor},\\
+% \cs{fillcolor}\SpecialUsageIndex{\fillcolor},
+% \cs{hatchcolor}\SpecialUsageIndex{\hatchcolor},
+% \cs{headcolor}\SpecialUsageIndex{\headcolor},
+% \cs{pointcolor}\SpecialUsageIndex{\pointcolor},
+% \cs{tlabelcolor}\SpecialUsageIndex{\tlabelcolor}, and\\
+% \cs{backgroundcolor}\SpecialUsageIndex{\backgroundcolor}.
+%
+% These commands support the \LaTeX-like syntax:\\
+% \indent\cs{fillcolor}\oarg{\meta{model}}\marg{\meta{parameters}}.\\
+% The code for \cs{backgroundcolor} has to be spelled out since the
+% command name has the string `\texttt{color}', but the color does not.
+% \begin{macrocode}
+\newdef\mfpdefinecolor#1#2#3{\setmfcolor{#1}{#2(#3)}}%
+\newdef\mfp@defclr#1#2#3{%
+ \setmfcolor{#1}{\mfp@ifempty{#2}{#3}{#2(#3)}}}%
+\newdef\mfp@newcolorcmd#1{%
+ \@namedef{#1\mfp@C}{\mfp@nullopt{\mfp@defclr{#1\mfp@C}}}}%
+\mfp@newcolorcmd{draw}\mfp@newcolorcmd{fill}\mfp@newcolorcmd{tlabel}%
+\mfp@newcolorcmd{hatch}\mfp@newcolorcmd{head}\mfp@newcolorcmd{point}%
+\def\backgroundcolor{\mfp@nullopt{\mfp@defclr{background}}}%
+% \end{macrocode}
+%
+% When \cs{plotdata} is used to draw several graphs from one file, each
+% sequence of non-blank lines corresponds to a different curve with a
+% different style of rendering. The user has the option to cycle through
+% different dashing patterns, different colors, or different symbols.
+%
+% Internally, \cs{plotdata} issues the command \cs{mfp@setstyle} (which
+% can be defined to be any rendering macro), followed by a path defining
+% command such as \cs{curve} or \cs{polyline}, followed by a command
+% that reads the data and writes it in a suitable format. The following
+% commands essentially allow the user to select the rendering macro.
+% They start by resetting \cs{mfp@linetype}, the count register that keeps
+% track of how many curves have been drawn, then they define
+% \cs{mfp@setstyle}.
+%
+% \DescribeMacro{\dashedlines}
+% \cs{dashedlines} uses the rendering prefix \cs{gendashed} with 6
+% different dashing patterns \gbc{dashtype0} through \gbc{dashtype5}.
+% These are actually selected in \MF{} through the command
+% \gbc{getdashpat}. This takes care of cycling back to
+% \gbc{dashtype0} when the number of available dash patterns is exceeded.
+% Dashed lines is the default.
+% \begin{macrocode}
+\newdef\dashedlines{\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\gendashed{getdashpat \number\mfp@linetype}}}%
+\dashedlines
+% \end{macrocode}
+%
+% \DescribeMacro{\coloredlines}
+% This uses \cs{draw} with an optional color parameter set to
+% \gbc{colortype0} through (by default) \gbc{colortype7}. These are color
+% variables defined by \grafbase{}. It also issues a warning if \MF{} is
+% being used. As with \cs{dashedlines}, a \MP{} command \gbc{getcolor}
+% selects these colors.
+% \begin{macrocode}
+\newdef\coloredlines{%
+ \mfp@ifmpost
+ {\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\draw[getcolor \number\mfp@linetype]}}%
+ {\Mfpic@warn{You can't use \mfp@b coloredlines in %
+ Metafont.\@msgbreak Using \dashedlines instead}%
+ \dashedlines}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\pointedlines}
+% This makes a sort of dotted line, except the dots are actually different
+% symbols. It uses the rendering macro \cs{plot} with a parameter cycling
+% through 9 different symbols.
+% \begin{macrocode}
+\newdef\pointedlines{\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\plot{getsymbol \number\mfp@linetype}}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\datapointsonly}
+% \cs{datapointsonly} uses symbols like \cs{pointedlines}, but places
+% them only at the data points from the file. It uses the rendering macro
+% \cs{plotnodes} with a parameter cycling through the same 9 symbols.
+% \begin{macrocode}
+\newdef\datapointsonly{\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\relax
+ \plotnodes{getsymbol \number\mfp@linetype}}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\reconfigureplot}
+% This command allows the user to set the dashes, colors and symbols used
+% by the \cs{plotdata} command. The first argument is the plotting method
+% to be changed (\texttt{dashes}, \texttt{colors}, or \texttt{symbols})
+% and the second argument is a comma separated list of appropriate type
+% variables for \cs{plotdata} to cycle through. For example,
+% \cs{reconfigureplot}\marg{dashes} takes a list of dashing patterns
+% (previously defined by the \cs{dashpattern} command) separated by
+% commas. It writes a command instructing \MF{} to redefine the arrays
+% \mfc{dashtype0}, \mfc{dashtype1}, etc., used with \cs{gendashed} when
+% \cs{dashedlines} is in effect. The number of patterns is counted by \MF,
+% which also handles the mod-ing operation now.
+%
+% \cs{reconfigureplot}\marg{colors} takes a list of colors (expressions or
+% color names previously defined) separated by commas. It redefines
+% \gbc{colortype0}, etc., used with \cs{plotdata} when \cs{coloredlines}
+% is in effect.
+%
+% \cs{reconfigureplot}\marg{symbols} takes a list of symbols (\MF{} path
+% expressions, one of the symbols available to \cs{plotsymbol}, or path
+% names defined by \cs{store}) separated by commas. It redefines
+% \gbc{pointtype0}, etc., used by \cs{plotdata} when \cs{pointedlines} or
+% \cs{datapointsonly} is in effect.
+%
+% \DescribeMacro{\defaultplot}
+% This restores \mfpic's predefined defaults for dash patterns, colors and
+% symbols in \cs{plotdata}. The one argument is one of the words
+% \texttt{dashes}, \texttt{colors}, or \texttt{symbols}, indicating which
+% plotting method is to be restored.
+% \begin{macrocode}
+\newdef\reconfigureplot#1{\mfsrc{setdata#1}\mfp@writedata}%
+\newdef\defaultplot#1{\mfcmd{default#1}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfplinetype}
+% The user-level command \cs{mfplinetype} allows the user to set the
+% starting value of \cs{mfp@linetype}. The default is to start at $0$.
+% \DescribeMacro{\mfplinestyle}
+% The macro \cs{mfplinestyle} is an alias for this same command. The names
+% `linestyle' and `linetype' come from an analogous system of changing
+% rendering in \prog{gnuplot}. (The reason for two names is that
+% \prog{gnuplot} documentation was not consistent in its terminology.)
+% \begin{macrocode}
+\newdef\mfplinetype#1{\mfp@local\mfp@linetype#1\relax}%
+\newlet\mfplinestyle\mfplinetype
+\mfplinetype{0}%
+% \end{macrocode}
+%
+% \prog{Mfpic} has 6 possible axes, the $x$- and $y$-axes pass through the
+% origin, $(0,0)$, the four border axes are at the edges of the graph
+% space, possibly offset from it by some amount. These four commands hold
+% the amount of that offset in graph units, the default being 0.
+% \begin{macrocode}
+\newdef\mfp@lshift{0}\newdef\mfp@bshift{0}%
+\newdef\mfp@rshift{0}\newdef\mfp@tshift{0}%
+% \end{macrocode}
+%
+% \DescribeMacro{\axismargin}
+% The main user-level command for setting the above offsets is
+% \cs{axismargin}. Its first argument is one of the letters l, b, r, or t
+% to select the axis and the second is the offset in graph units. A
+% positive offset represents an inward shift, which is why we call them
+% \emph{margins}.
+% \DescribeMacro{\setaxismargins}
+% The arguments of \cs{setaxismargins} are four offsets for the axes (in
+% the above order, which is anticlockwise, starting with the left).
+% \DescribeMacro{\setallaxismargins}
+% \cs{setallaxismargins} takes one offset and applies it to all axes.
+%
+% The values are passed on to \MF{} in the variables \gbc{laxis},
+% \gbc{baxis}, \gbc{raxis}, and \gbc{taxis}. They are also needed by the
+% \cs{axislabels} command so they are saved in macros.
+% \begin{macrocode}
+\newdef\axismargin#1#2{\setmfnumeric{#1axis}{#2}%
+ \mfp@local\@namedef{mfp@#1shift}{#2}}%
+\newdef\setaxismargins#1#2#3#4{\axismargin l{#1}\axismargin b{#2}%
+ \axismargin r{#3}\axismargin t{#4}}%
+\newdef\setallaxismargins#1{\setaxismargins{#1}{#1}{#1}{#1}}%
+% \end{macrocode}
+%
+% The following converts axis letters to a numeric, making conditionals for
+% axes simpler to code (\cs{ifcase} versus six nested \cs{if}\,s).
+% Plus we get to define the error message only once. The first argument
+% of \cs{mfp@getaxis} is the letter and the third argument is the calling
+% command (for the error message). We allow the letter to be instead a word,
+% using only the first letter and discarding the rest (\arg2).
+% \begin{macrocode}
+\def\mfp@axis@x{0}%
+\def\mfp@axis@y{1}%
+\def\mfp@axis@l{2}%
+\def\mfp@axis@b{3}%
+\def\mfp@axis@r{4}%
+\def\mfp@axis@t{5}%
+\def\mfp@getaxis#1#2\mfp@end#3{%
+ \@ifundefined{mfp@axis@#1}%
+ {\mfp@errmsg {Invalid axis letter "#1"}%
+ {The command #3 requires an axis to be designated by one of^^J%
+ the following letters: x, y, l, b, r, or t. If you proceed, ^^J%
+ x will be assumed.}\def\mfp@axisnum{0}\def\mfp@axisletter{x}}%
+ {\edef\mfp@axisnum{\@nameuse{mfp@axis@#1}}\def\mfp@axisletter{#1}}%
+ \edef\mfp@defaultheadlen{%
+ \the\ifnum\mfp@axisnum>1 \sideheadlen\else \axisheadlen\fi}}%
+% \end{macrocode}
+%
+% The tick marks (or hash marks) on the axes can be in three possible
+% positions: centered on the axes, on one side, or on the other side.
+% The default for the $x$- and $y$-axes is centered, for the border axes it
+% is inside.
+% \DescribeMacro{\setaxismarks}
+% For changing this we provide the \cs{setaxismarks} command, whose first
+% argument is the axis letter, and whose second argument is one of the
+% words \texttt{inside}, \texttt{outside}, \texttt{centered},
+% \texttt{ontop}, \texttt{onbottom}, \texttt{onleft}, or \texttt{onright}.
+%
+% \DescribeMacro{\setxmarks}
+% \cs{setxmarks} takes one argument and sets the position for the $x$ axis
+% only, while
+% \DescribeMacro{\setymarks}
+% \cs{setymarks} does the same for the $y$ axis. For the border axes we
+% provide
+% \DescribeMacro{\setbordermarks}
+% \cs{setbordermarks}, which takes four arguments: the positions for the
+% left, bottom, right and top axis (in that order).
+% \DescribeMacro{\setallbordermarks}
+% The abbreviation \cs{setallbordermarks} takes one argument and sets the
+% position for all border axis marks to that.
+% \begin{macrocode}
+\newdef\setaxismarks#1#2{\setmfnumeric{#1tick}{#2}}%
+\newdef\setxmarks#1{\setaxismarks x{#1}}%
+\newdef\setymarks#1{\setaxismarks y{#1}}%
+\newdef\setbordermarks#1#2#3#4{\setaxismarks l{#1}\setaxismarks b{#2}%
+ \setaxismarks r{#3}\setaxismarks t{#4}}%
+\newdef\setallbordermarks#1{\setbordermarks{#1}{#1}{#1}{#1}}%
+% \end{macrocode}
+%
+% The \cs{datafile} and \cs{plotdata} commands originally just created
+% polygonal paths, but users requested the ability to draw smooth ones.
+% Originally only the commands below (\cs{smoothdata} and
+% \cs{unsmoothdata}) were written to do this. Later, these file
+% manipulation commands were given optional arguments to achieve the same
+% effect, so now the commands below just set the defaults for the optional
+% parameter, storing them in the macros \cs{mfp@smoothness} and
+% \cs{mfp@tension}. The latter can be used to adjust the tension of the
+% \MF{} path if smoothness is `\texttt{s}'.
+%
+% \DescribeMacro{\smoothdata}
+% This takes an option tension argument. It defines \cs{mfp@smoothness} to
+% be `\texttt{s}' and \cs{mfp@tension} to be the optional argument.
+% Default tension is empty rather than 1 so we can implement a scheme to
+% change the actual default used.
+% \DescribeMacro{\unsmoothdata}
+% The macro \cs{unsmoothdata} defines \cs{mfp@smoothness} to be
+% `\texttt{p}' and \cs{mfp@tension} to be empty. The latter might not be
+% necessary.
+% \begin{macrocode}
+\newdef\mfp@smdata#1{\mfp@def\mfp@smoothness{#1}%
+ \mfp@nullopt{\mfp@def\mfp@tension}}%
+\newdef\smoothdata{\mfp@smdata{s}}%
+\newdef\unsmoothdata{\mfp@smdata{p}\@empty}%
+\unsmoothdata% default
+% \end{macrocode}
+%
+% \DescribeMacro{\using}
+% The command \cs{using} is named after a keyword in \prog{gnuplot}. It
+% controls which datum is plotted against which by \cs{plotdata} and
+% \cs{datafile}.
+%
+% \DescribeMacro{\usingpairdefault}
+% The macro \cs{usingpairdefault} sets the default, which is to read the
+% first two space separated words on a line as the $x$ and $y$ coordinate
+% of a point. To allow that there might be more data on a line, it is also
+% assumed that the second word is followed by a space and the rest of the
+% line is read as a third parameter that is not used. In case there are
+% only two words, \mfpic{} will always add a space on the end and then the
+% third parameter will be empty.
+%
+% \DescribeMacro{\usingnumericdefault}
+% For the occasional command that needs numeric data,
+% \cs{usingnumericdefault} sets \cs{using} so that the first
+% space-separated word on a line is selected and the remainder of the line
+% discarded.
+%
+% The \cs{parse@data} command reads its argument as delimited
+% parameters, and the \cs{using} command tells what those delimiters are.
+% For example, in the first part of
+% \cs{using}\marg{\#1 \#2 \#3}\marg{(\#1,\#2)}, we are telling
+% \cs{parse@data} that everything on a line up to the first space is the
+% first parameter, and everything up to the second space is the second
+% parameter and the rest of the line is the third parameter. In the second
+% part we are telling it that what we write to the output is a pair in
+% parentheses with the first two parameters separated by a comma. This
+% example is the default as we see here in \cs{usingpairdefault}. This
+% command can be issued by a user to return to that default. The user can
+% also issue \cs{usingnumericdefault} to write the first word as a single
+% numeric for commands like \cs{piechart}.
+%
+% \DescribeMacro{\mfpdataperline}
+% \cs{mfpdataperline} is a user level macro that controls the maximum
+% number of points that will be written to a single line in the output.
+% \begin{macrocode}
+\newdef\using#1#2{\mfp@def\parse@data#1\mfp@end{#2}}%
+\newdef\usingpairdefault{\using{##1 ##2 ##3}{(##1,##2)}}%
+\newdef\usingnumericdefault{\using{##1 ##2}{##1}}%
+\usingpairdefault
+\newdef\mfpdataperline{5}%
+% \end{macrocode}
+%
+% The following macros are used internally by \cs{datafile} and
+% \cs{plotdata}. A blank line is read as \cs{par} (not the primitive
+% \cs{par}, but the literal token \cs{par}, so it tests as equal to
+% \cs{mfp@par}. Early versions of \cs{plotdata} wrote a literal \MF{} path
+% expression to the output file and \cs{mfp@join} created the \mfc{--}
+% between points. Now we write one of the \grafbase{} list-to-path
+% commands followed by a comma separated list of points, so \cs{mfp@join}
+% has morphed into a comma.
+% \begin{macrocode}
+\newdef\mfp@par{\par}\newdef\mfp@join{,}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfpdatacomment}
+% The user can change the comment character for data files with
+% something like \cs{mfpdatacomment}\marg{\cs{\#}}. This also changes the
+% percent character to category `other'. We can also use the percent sign
+% as part of the numeric data by placing
+% \DescribeMacro{\makepercentother}
+% \cs{makepercentother} before the \cs{using} command to turn `\texttt\%'
+% into an ordinary character.
+% \DescribeMacro{\makepercentcomment}
+% \cs{makepercentcomment} returns it to its usual role as a comment. Every
+% file reading command issues \cs{mfp@setcomment} before reading. The
+% count register \cs{mfp@commentchar} holds the ASCII code of the current
+% comment character, the default being the percent sign.
+% \begin{macrocode}
+\newcount\mfp@commentchar \mfp@commentchar`\%%
+\newdef\makepercentother{\@makeother\%}%
+\newdef\makepercentcomment{\catcode`\%14 }%
+\newdef\mfpdatacomment#1{\mfp@local\mfp@commentchar`#1}%
+\newdef\mfp@setcomment{\makepercentother\catcode\mfp@commentchar14 }%
+% \end{macrocode}
+%
+% \DescribeMacro{\fdef}
+% The following is for defining functions to be used in \cs{function}
+% through \cs{plrregion}. The first argument is the name of the function,
+% the second is its variable, the last is the \MF{} code. Obviously its
+% use requires a knowledge of the \MF{} language. The function produced is
+% a \mfc{vardef}, and can contain almost arbitrary \MF{} code, but must
+% end with an expression. Normally it must be a numerical expression, to
+% be use in \cs{function}, or a pair expression so it can be used alone in
+% the last argument of \cs{parafcn}.
+%
+% We apply \cs{@makeother} to \arg{} so it doesn't get doubled. The
+% \arg{} is frequent in vardefs among the \MF{} gurus.
+% \begin{macrocode}
+\newdef\fdef{\begingroup\@makeother\#\mfp@keeplines\mfp@fdef}%
+\newdef\mfp@fdef#1#2#3{\mfcmd{\@nl save #1;\@nl
+ vardef #1 (expr #2) = \@nl #3\@nl enddef}\endgroup}%
+% \end{macrocode}
+%
+% The following is executed right after \cs{mfp@grafmacs}. It is a hook
+% for adding new definitions inside and \env{mfpic} environment. It is
+% initialized to empty, and add-on packages can add to it.
+% \begin{macrocode}
+\newdef\mfp@additions{}%
+% \end{macrocode}
+%
+%
+%
+% \section{The user level graphics macros}
+%
+% This is the start of the definition of \cs{mfp@grafmacs}. It contains
+% the definition of every user command that has no purpose outside an
+% \env{mfpic} environment. It will be expanded inside every \env{mfpic}
+% environment, localizing all these definitions. We do this so we can
+% avoid name clashes without giving them all names beginning with \cs{mfp}.
+% \begin{macrocode}
+\newdef\mfp@grafmacs{%
+% \end{macrocode}
+%
+%
+% \subsection{Figure macros}\label{figure}
+%
+% These are the figure macros. These are implemented as \MF{} paths that
+% can be variously rendered, transformed, etc., by the prefix macros of
+% subsection~\ref{prefixcommands}.
+%
+% Most of the \mfpic{} graphic commands take optional arguments. Most of
+% them follow the scheme \cs{mfp@command} takes mandatory arguments
+% enclosed in braces, and does the work. \cs{command} is simply defined to
+% test for an optional argument (with \cs{mfp@defaultopt}) and pass it or a
+% default to \cs{mfp@command}. A typical example is \cs{ellipse} defined
+% to be \verb$\mfp@defaultopt\mfp@ellipse0$. In some cases, the default
+% option is signaled by passing an empty argument via \cs{mfp@nullopt}.
+%
+% Of the commands that have no optional argument, most simply write
+% the appropriate commands to the output file, and require no
+% \cs{mfp@} version.
+%
+% This section contains a description of the behavior of each command and
+% its syntax in use. For those that call an \cs{mfp@} version, the
+% implementation is in the next section.
+%
+%
+% \subsubsection{Common geometric objects}\label{geometric}
+%
+% The first few (\cs{rect} through \cs{sector}) are closed paths and
+% need not be prefixed with a closing macro before filling, etc.
+%
+% \DescribeMacro{\rect}
+% This takes one mandatory argument, the two diagonally opposite
+% corners of the rectangle separated by a comma, and draws the rectangle
+% with horizontal and vertical sides having these as two corners. The
+% direction of the path (which seldom makes a difference) is such that it
+% starts at the first specified point and moves horizontally first.
+%
+% This is an example of a command that requires no further processing.
+% The \cs{mfp@figmac} command sets the appropriate switches and writes its
+% argument to the output file, followed by a semicolon.
+% \begin{macrocode}
+ \newdef\rect##1{\mfp@figmac{rect (##1)}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\regpolygon}
+% There are four arguments. The first is the number of sides. The second
+% is the name of a variable to represent the vertices. The other
+% two should be equations locating two vertices or the center and one
+% vertex. If the name used is \gbc{Ver}, then the vertices will be
+% \gbc{Ver1}, \gbc{Ver2}, etc., numbering anticlockwise. The center is
+% \gbc{Ver0}. Case is significant. After the command, the points can be
+% referred to in other \mfpic{} commands (except text label commands
+% when \opt{mplabels} is not in effect).
+% \begin{macrocode}
+ \newdef\regpolygon##1##2##3##4{%
+ \mfp@figmac{regularpolygon (##1) (##2) (##3; ##4;)}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\circle}
+% This has one optional argument containing one of the letters
+% \texttt{t}, \texttt{p} (the default), \texttt{c}, \texttt{s},
+% \texttt{r}, or \texttt{q}. Its purpose is to specify what kind of data
+% is in the single mandatory argument. These are a subset of the optional
+% arguments that the \cs{arc} commad (below) takes, and have almost the
+% same meaning:
+% \begin{itemize}
+% \item \oarg{t}, the three point form needs three points (of course).
+% \item \oarg{p}, the polar form needs the center point and the radius.
+% This is the default when the optional argument is absent.
+% \item \oarg{c}, the center/point form needs the center and one point on
+% the circle.
+% \item \oarg{s}, the point-sweep form requires two points and the angle of
+% arc between them. The angle may be positive or negative. A
+% positive angle indicates the number of degrees anticlockwise from
+% the first point to the second. Negative means clockwise.
+% \item \oarg{r}, the point-radius form requires two points and the
+% radius of the circle. Of the two possible circles, it produces the
+% one where the anticlockwise arc from the first point to the second
+% is not more than 180 degrees.
+% \item \oarg{q}, an alternative point-radius with the same parameters.
+% It produces the circle
+% where the anticlockwise arc from the first point to the second
+% is not less than 180 degrees.
+% \end{itemize}
+%
+% Supplying \cs{arc} with the same parameters, or the appropriate superset
+% in the case of \oarg{p} and \oarg{c}, would produce a sub-arc of the
+% circle that \cs{circle} produces. This is the reason for giving
+% \cs{circle} these options: to make diagrams which show a circle and an
+% arc on it.
+%
+% We use \cs{def} instead of \cs{newdef} because we know \LaTeX{} has
+% already defined a \cs{circle} command. We now use the same command,
+% \cs{mfp@arccircle}, for arcs and circles, setting a switch to tell it
+% which to produce.
+% \begin{macrocode}
+ \def\circle{\mfp@switchfalse\mfp@defaultopt\mfp@arccircle{p}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\ellipse}
+% \cs{ellipse} has one optional argument, an angle of rotation and one
+% mandatory argument, containing the center, the horizontal and vertical
+% radii (before rotation), separated by commas.
+% \begin{macrocode}
+ \newdef\ellipse{\mfp@defaultopt\mfp@ellipse{0}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\quarterellipse}
+% \DescribeMacro{\halfellipse}
+% \DescribeMacro{\fullellipse}
+% The next three commands simply call \grafbase{} commands of the same
+% name. They draw part or all of an ellipse inscribed in a parallelogram.
+% Each requires for its argument three points, separated by commas. For
+% \cs{quarterellipse} these points are, respectively, the midpoint of one
+% side of a parallelogram, a corner point on that side, and the midpoint
+% of the side adjacent to the first at that corner. For \cs{halfellipse}
+% they are the midpoints of three successive sides. For \cs{fullellipse}
+% they are the center and the midpoints of two adjacent sides. They are
+% all simple figmacs with no optional arguments and no star forms.
+%
+% It would be possible to give all of them the same three arguments,
+% for example those of \cs{fullellipse}, but I wanted to put the
+% endpoints of the paths into the argument list. The reason
+% \cs{quarterellipse} is passed the corner point instead of the center is
+% because of the intended use: rounding off an asymmetric corner without
+% having to compute the center of the parallelogram.
+% \begin{macrocode}
+ \newdef\quarterellipse##1{\mfp@figmac{quarterellipse (##1)}}%
+ \newdef\halfellipse##1{\mfp@figmac{halfellipse (##1)}}%
+ \newdef\fullellipse##1{\mfp@figmac{fullellipse (##1)}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\sector}
+% This is the closed curve starting at the center of a circle, out
+% along a radius to the circumference of the circle, along an arc of the
+% circle, then back to the center. It has one mandatory argument
+% containing the center, the radius, and the two angles, separated by
+% commas.
+% \begin{macrocode}
+ \newdef\sector##1{\mfp@figmac{sector (##1)}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\arc}
+% We have seven (actually 14) ways to specify a circular arc. \cs{arc}
+% takes an optional argument: a letter to indicate which of the 7
+% specifications. It has one mandatory argument containing the data for
+% that specification, separated by commas. It also has a star-form,
+% which produces the complementary arc. That is, instead of the arc that
+% is specified (as described below) it produces the rest of the circle
+% from the end of the specified arc to its start.
+%
+% The available letters and the corresponding required data are listed
+% below. The default optional argument is \oarg{s}.
+% \begin{itemize}
+% \item \oarg{t}, the three point form needs three ordered pairs.
+% \item \oarg{p}, the polar form needs the center point, two angles and
+% the radius (in that order).
+% \item \oarg{a}, the alternative polar form needs the center, the radius
+% and two angles (in that order).
+% \item \oarg{c}, the center-point-sweep form needs the center, the
+% starting point, and the angle.
+% \item \oarg{s}, the points-sweep form requires the starting point, the
+% ending point and the angle.
+% \item \oarg{r}, the points-radius form requires the starting point, the
+% ending point and the radius of the arc. There are two circles with
+% the given radius that pass through the given points, and hence
+% four possible arcs. One arc on each circle is anticlockwise from
+% the first point to the second. Of those two arcs, only one is
+% less than $180$ degrees. That one is produced.
+% \item \oarg{q} Same as \oarg{r}, except the arc is the larger of two
+% anticlockwise arcs.
+% \end{itemize}
+% \begin{macrocode}
+ \newdef\arc{\mfp@iftoken*{\arccomplement\mfp@arc}{\mfp@arc}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\pshcircle}
+% This final circle is for us complex function theorists. It makes a
+% `pseudohyperbolic circle'. This requires a point $z$ inside the circle
+% with center $(0,0)$ and radius $1$, and a radius $R < 1$. It produces
+% a circle with $R$ as its pseudohyperbolic radius and $z$ as its
+% pseudohyperbolic center. The star form switches contexts to the upper
+% half-plane.
+% \begin{macrocode}
+ \newdef\pshcircle{\mfp@ifstar\mfp@pshcircle\mfp@F\mfp@T}%
+% \end{macrocode}
+%
+% \DescribeMacro{\hypergeodesic}
+% And this final arc is also for we complex function theorists. It makes a
+% `hyperbolic geodesic'. This requires two points $z$ and $w$ inside the
+% circle $T$ with center $(0,0)$ and radius $1$. It produces a circular arc
+% from the first point to the second on the unique circle that passes
+% through these two points and meets $T$ at right angles. The star form
+% switches contexts to the upper half-plane.
+% \begin{macrocode}
+ \newdef\hypergeodesic{\mfp@ifstar\mfp@hypergeodesic{UHP}{UD}}%
+% \end{macrocode}
+%
+%
+% \subsubsection{List macros}\label{list}
+%
+% The figure macros of this section are all list macros. They produce a
+% path from a list of ordered pairs. The list can be explicitly given as a
+% mandatory argument containing a comma-separated list of pair
+% expressions, or it can be taken from an external datafile. This is true
+% for \cs{polyline} through \cs{turtle}. These macros differ only in how
+% the data determine the path. (Some of the splines don't connect given
+% points, but rather use the points in a different way to determine a
+% curve.) The list of pairs is not an argument of any of these. It should
+% follow, and is ultimately written to output by the ending code of
+% \cs{mfp@listmac}. This is basic to list macros, and will not be repeated
+% for each one.
+%
+% Commands in this section are grouped by the argument structure of the
+% command written to the output file. The first twelve come in pairs
+% that are distinguished by a boolean parameter, which usually determines
+% whether the path produced is closed, followed by the list.
+%
+% \DescribeMacro{\polyline}
+% The most basic, a polyline or polygonal path, \cs{polyline} draws line
+% segments from each point to the next.
+% \DescribeMacro{\lines}
+% \cs{lines} is an alias.
+%
+% \DescribeMacro{\closedpolyline}
+% The macro \cs{closedpolyline} does the same, except it produces a closed
+% path, connecting the last point to the first.
+% \DescribeMacro{polygon}
+% \cs{polygon} is an alias.
+%
+% \DescribeMacro{\computedspline}
+% The \cs{computedspline} command takes a list of points and computes the
+% controls of a cubic spline that connects the points. Adjacent segments
+% have matching first and second derivatives at the common endpoint. It is
+% limited to what is called a \emph{relaxed} spline, which has zero
+% curvature at the beginning and ending points.
+%
+% \DescribeMacro{\closedcomputedspline}
+% This is similar, but computes the unique \emph{closed} cubic spline that
+% connects a list of points.
+%
+% The next four commands also produce types of splines. The list of pairs
+% is not, however, the points passed through but rather are control points,
+% of a sort.
+%
+% \DescribeMacro{\qspline}
+% This produces quadratic splines. The points create the path as follows:
+% for successive points $p\sb i, p\sb {i+1}$ in the list, the path passes
+% through the midpoint of the line segment connecting $p\sb i$ and
+% $p\sb {i+1}$, tangent to that line segment. This causes adjacent
+% B\'ezier segments to have matching derivatives at their common
+% endpoint. Each three successive data points determines one segment of
+% the path.
+%
+% \DescribeMacro{\closedqspline}
+% The closed variant works by creating two additional segments, viewing
+% the triples $p\sb{n-1}, p\sb{n}, p\sb1$ and $p\sb{n}, p\sb1, p\sb2$ as
+% being `successive'.
+%
+% \DescribeMacro{\cspline}
+% The macro \cs{cspline} produces cubic splines. The points determine the
+% curve as follows: for successive points $p\sb i, p\sb {i+1}$ in the
+% list, the line segment connecting them is divided into thirds with two
+% points $q\sb i$ and $q\sb i'$. The curve then passes through the
+% midpoint of the segment from $q\sb {i-1}'$ to $q\sb i$ and tangent to
+% that segment. This causes adjacent B\'ezier segments to have matching
+% first and second derivatives at their common endpoint. Each four
+% successive data points determines one segment of the path.
+%
+% \DescribeMacro{\closedcspline}
+% The closed variant works by viewing the first point as a succesor of the
+% last point, creating three additional path segments.
+%
+% \DescribeMacro{\qbeziers}
+% This produces the equivalent of a sequence of \LaTeX{} \cs{qbezier}
+% commands. The mandatory argument will be a list of points alternating
+% between nodes and control points, ending with the last node.
+% \DescribeMacro{\closedqbeziers}
+% The closed version ends with the control point between the last node and
+% the first. Therefore, the \cs{qbeziers} command needs an odd number of
+% points in the list, while \cs{closedqbeziers} needs an even number. If
+% this is not the case, the last point in the list is repeated, causing
+% the final segment to be a straight line (closed case) or trivial.
+%
+% Note that quadratic B\'eziers need not be smooth at the nodes unless
+% the control points line up. Our plural name distinguishes it from the
+% \LaTeX{} command.
+%
+% \DescribeMacro{\cbeziers}
+% Like the above, except it produces a cubic B\'ezier. It requires a
+% list of $3n+1$ points in the pattern node-control-control, ending with
+% an extra node.
+% \DescribeMacro{closedcbeziers}
+% The closed version requires only $3n$ points, taking the first for the
+% final node.
+%
+% \DescribeMacro{\fcnspline}
+% The above splines are two dimensional splines, that is, functions of
+% $t$ with pair values $(x,y)$. One dimensional splines are functions of
+% $x$ with numeric values $y$. This command produces the \emph{graph} of
+% such a function computed from a supplied list of points. It is required
+% that the $x$-values of the points are in increasing order, although it
+% will produce some sort of curve as long as adjacet $x$-values are
+% distinct. It produces the graph of a \emph{relaxed} spline, in the sense
+% that the second derivative $d^2y/dx^2$ is zero at the beginning and end.
+%
+% \DescribeMacro{\periodicfcnspline}
+% This is the same, but instead of requiring the second derivative to be
+% zero at both ends, it produces a graph such that the first and second
+% derivatives at the end match the ones at the beginning. If a copy of the
+% graph is placed with its starting point at the original graph's ending
+% point, then there is a smooth join. If the $y$-values of the
+% beginning and ending points match, a periodic graph is obtained. For
+% these last two commands the paths cannot be closed, and the boolean
+% determines the behavior at the endpoints.
+%
+% The command \cs{mfp@listi} that implements these writes the command
+% name and the argument and ends with code to write the list of pairs.
+% \begin{macrocode}
+ \newdef\lines{\mfp@listi{polyline}\mfp@F}%
+ \newdef\polygon{\mfp@listi{polyline}\mfp@T}%
+ \newdef\computedspline{\mfp@listi{dospline}\mfp@F}%
+ \newdef\closedcomputedspline{\mfp@listi{dospline}\mfp@T}%
+ \newdef\qspline{\mfp@listi{qspline}\mfp@F}%
+ \newdef\closedqspline{\mfp@listi{qspline}\mfp@T}%
+ \newdef\cspline{\mfp@listi{cspline}\mfp@F}%
+ \newdef\closedcspline{\mfp@listi{cspline}\mfp@T}%
+ \newdef\qbeziers{\mfp@listi{qbezier}\mfp@F}%
+ \newdef\closedqbeziers{\mfp@listi{qbezier}\mfp@T}%
+ \newdef\cbeziers{\mfp@listi{cbezier}\mfp@F}%
+ \newdef\closedcbeziers{\mfp@listi{cbezier}\mfp@T}%
+ \newdef\fcnspline{\mfp@listi{fcnspline}\mfp@F}%
+ \newdef\periodicfcnspline{\mfp@listi{fcnspline}\mfp@T}%
+ \newlet\closedpolyline\polygon
+ \newlet\polyline\lines
+% \end{macrocode}
+%
+% The next six macros have an optional argument called `tension', a
+% numerical value that controls how tightly the path turns at each point
+% in the list. If the optional argument is absent (or empty), the
+% \grafbase{} command that is written takes only a boolean argument
+% (closed or not closed) followed by the list of points. If the tension
+% argument is present, a different command is written that also has a tension
+% argument. The command name is almost the same, but has a `\gbc{t}'
+% prepended. The default tension is the \cs{grafbase}{} variable
+% \gbc{default_tension}, set with \cs{settension}, initialized to 1.
+% Tension of 0 is ignored (ultimately tension is divided by) and may
+% produce error messages from \MF{}.
+%
+% \DescribeMacro{\curve}
+% \cs{curve} draws a smooth curve connecting a list of points. it arranges
+% for the curve, at point $p\sb n$ to be traveling parallel to the direction
+% from $p\sb {n-1}$ to $p\sb {n+1}$ (except at the first and last point).
+%
+% \DescribeMacro{\closedcurve}
+% The closed version \cs{closedcurve} treats the
+% first point and last point the same as the rest. It has the alias
+% \DescribeMacro{\cyclic}
+% \cs{cyclic}.
+%
+% \DescribeMacro{\convexcurve}
+% This convex version produces a smooth curve that is convex in those
+% places where \cs{polyline} (with the same list of points) would produce
+% a convex shape.
+% \DescribeMacro{\closedconvexcurve}
+% It also comes in a closed version, with the alias
+% \DescribeMacro{\convexcyclic}
+% \cs{convexcyclic}.
+%
+% \DescribeMacro{\mfbezier}
+% This produces the standard \MF{} cubic B\'ezier using the \MF{} path
+% join operator (\mfc{..}) with tension given by an optional argument.
+% \DescribeMacro{\closedmfbezier}
+% The closed version connects the last point to the first in the same way.
+%
+% The command \cs{mfp@curve} examines the optional argument and writes
+% the command name (first argument, possibly modified) with the
+% appropriate arguments (the boolean or tension plus boolean).
+% \begin{macrocode}
+ \newdef\curve{\mfp@curve{curve}\mfp@F}%
+ \newdef\cyclic{\mfp@curve{curve}\mfp@T}%
+ \newdef\convexcurve{\mfp@curve{ccurve}\mfp@F}%
+ \newdef\convexcyclic{\mfp@curve{ccurve}\mfp@T}%
+ \newdef\mfbezier{\mfp@curve{bezier}\mfp@F}%
+ \newdef\closedmfbezier{\mfp@curve{bezier}\mfp@T}%
+ \newlet\closedcurve\cyclic
+ \newlet\closedconvexcurve\convexcyclic
+% \end{macrocode}
+%
+% \DescribeMacro{\fcncurve}
+% A `function curve' is the graph of a function of $x$. It should always
+% travel left to right. This is not guaranteed by the \cs{curve} macro,
+% above, even if the $x$ coordinates are listed in order. \cs{fcncurve} is
+% guaranteed to do this if the list of points has the $x$ coordinates so
+% ordered.
+%
+% While the optional argument is called tension, it is not quite the
+% same as the tension argument to \cs{curve}, but it has a similar effect.
+% The default value is the sane as for \cs{curve}. The above guarantee is
+% voided if the value used is ${}\le1/3$.
+% \begin{macrocode}
+ \newdef\fcncurve{\mfp@nullopt\mfp@fcncurve}%
+% \end{macrocode}
+%
+% \DescribeMacro{\turtle}
+% Many years ago there was a tool for teaching programming concepts to
+% young children. They could draw a figure on a screen by programming a
+% `turtle' with a sequence of turns and distances. The following is
+% similar. It has a mandatory argument containing a list of ordered pairs.
+% The first is the coordinates of the starting point, and each of the rest
+% is interpreted as a displacement from the current position, along which
+% a line segment is to be drawn. The terminal point of that segment is the
+% new current position
+% \begin{macrocode}
+ \newdef\turtle{\mfp@listmac{turtle}}%
+% \end{macrocode}
+%
+%
+% \subsubsection{Graphing functions}\label{functions}
+%
+% \DescribeMacro{\function}
+% \prog{Mfpic} provides the ability to plot the graph of any function that
+% can be defined in \MF. This is done with the \cs{function} command, a
+% figure macro which takes one optional parameter that selects
+% the smoothness of the \MF{} path produced. It can be \oarg{p}, which
+% draws a polyline path through selected points (much like \cs{polyline}),
+% or \oarg{s\meta{tension}} which selects a smooth path (much like
+% \cs{curve}\oarg{\meta{tension}}). The tension may be omitted and then
+% will be 1 (or the value set by \cs{settension}). The default optional
+% argument is \oarg{s}, a smooth curve with the default tension.
+%
+% There are two mandatory arguments. The second is the function, which
+% must be written as a formula (strictly speaking, a \MF{} numerical
+% expression) containing only one variable, \texttt{x}. The first
+% mandatory argument contains three numbers separated by commas. They are,
+% in order, the starting value of \texttt{x}, the ending value, and the
+% step size.
+%
+% \DescribeMacro{\parafcn}
+% \cs{parafcn} is similar, except its formula must be an ordered pair of
+% formulas (strictly speaking, a \MF{} pair expression) in which
+% \texttt{t} is the only variable.
+%
+% \DescribeMacro{\plrfcn}
+% \cs{plrfcn} is similar, except its argument is a formula (a \MF{}
+% numeric expression) representing the radius, in which \texttt{t} is the
+% only variable, interpreted as the angle coordinate, $\theta$, in degrees.
+%
+% These three commands are so alike that they call the same macro
+% with the name to be written as the first argument and the default
+% optional argument as the second. The latter is so that we can reuse it
+% for two other commands where the default is different.
+% \begin{macrocode}
+ \newdef\function{\mfp@fcn{function}s}%
+ \newdef\parafcn{\mfp@fcn{parafcn}s}%
+ \newdef\plrfcn{\mfp@fcn{plrfcn}s}%
+% \end{macrocode}
+%
+% \DescribeMacro{\btwnfcn}
+% The region between two functions \cs{btwnfcn} is a figure macro. It is
+% mostly intended for shading or other filling operations so it is already
+% closed and, by default, it is not `smooth'. Its parameters are the
+% same as those of \cs{function} (above), with two exceptions: the default
+% optional argument is \oarg{p} and it has an additional mandatory
+% argument, the other function. The resulting \MF{} path travels along the
+% graph of the first function from the starting $x$ to the ending $x$,
+% thence vertically to the graph of the second function, along it (in
+% reverse) to the starting $x$ and finally, vertically to the start of the
+% first function's graph.
+%
+% \DescribeMacro{\btwnplrfcn}
+% We also have the polar function version, where the two function
+% arguments are as in \cs{plrfcn}. The default option is also \oarg{p}.
+% As with \cs{function}, these are implemented by calling a common
+% command with the basename of the \grafbase{} command as argument.
+%
+% \DescribeMacro{\plrregion}
+% This is like \cs{btwnplrfcn} with 0 as the first function, but it
+% is more efficient. It takes only the other function as an argument.
+% Again, the default option is \oarg{p}.
+%
+% \DescribeMacro{\belowfcn}
+% This is like \cs{btwnfcn} with 0 as the first function, but it
+% is more efficient. It takes only the other function as an argument.
+% The default option is \oarg{p}.
+% \begin{macrocode}
+ \newdef\btwnfcn{\mfp@btwn{btwnfcn}}%
+ \newdef\btwnplrfcn{\mfp@btwn{btwnplrfcn}}%
+ \newdef\belowfcn{\mfp@fcn{belowfcn}p}%
+ \newdef\plrregion{\mfp@fcn{plrregion}p}%
+% \end{macrocode}
+%
+% \DescribeMacro{\levelcurve}
+% One way to graph a function of two variables is to draw level curves.
+% The figure macro \cs{levelcurve} takes an optional smoothness
+% argument (\texttt{[s\meta{tension}]} or \texttt{[p]} with \texttt{p}
+% being the default), and two mandatory arguments. The first
+% mandatory argument is a `seed' point which is known to lie inside the
+% level curve, followed by a comma and a step size. The second is an
+% inequality between the function and the level value that is true inside
+% the level curve. Strictly speaking, the last argument can be any \MF{}
+% boolean valued expression with variables \mfc{x} and \mfc{y}. The simple
+% example,\\
+% \indent\verb$\levelcurve[p]{(0,0),0.1}{x*x + y*y < 3}$\\
+% will draw approximately the circle with radius $\sqrt3$ as a sequence of
+% line segments with length $0.1$. That will require about 109 segments.
+% Its parameters are similar enough to those of \cs{function} that we
+% can use the same interface.
+% \begin{macrocode}
+ \def\levelcurve{\mfp@fcn{levelset}p}%
+% \end{macrocode}
+%
+% We now define two macros for depicting the solution of an
+% ordinary differential equation. The first of these, \cs{DEgraph},
+% produces the graph of the solution for equations of the form
+% $$
+% \frac{dy}{dx} = f(x,y),\quad y(x\sb0) = y\sb0.
+% $$
+% The data required are the \emph{initial values} (the two numbers $x\sb0$
+% and $y\sb0$), the formula $f(x,y)$ (an explicit \MF{} numerical
+% expression with literal variables \mfc{x} and \mfc{y} as the only
+% unknowns. Since \MF{} can only handle paths connecting discrete points,
+% also required is a step size which, roughly speaking, is the distance
+% between points in graph coordinates, and the number of steps $N$ to use.
+% The \MF{} macros then calculate $N$ additional points (the first is
+% $(x\sb0,y\sb0)$) and join them together to produce the graph.
+%
+% The second macro, \cs{DEtrajectory}, draws the trajectory of a
+% two-dimentional differential equation of the form
+% $$
+% \left( \frac{dx}{dt}, \frac{dy}{dt}\right) = (f(x,y,t),g(x,y,t)\,,
+% \quad (x(0),y(0)) = (x\sb0,y\sb0)
+% $$
+% This is not, strictly speaking, a \emph{graph} since that would
+% require three dimensions to indicate the relation between $x$, $y$, and
+% $t$. Mathematicians call it a trajectory, and it only shows the
+% two-dimensional path followed by the moving object. The required data
+% are an initial point $(x\sb0,y\sb0)$, the formula for the right-hand side
+% (an explicit \MF{} pair-valued expression or a pair of numerical
+% expressions in parentheses, with literal variables \mfc{x}, \mfc{y} and
+% \mfc{t} as the only unknowns. Also required are a step size and the
+% number of steps, as in \cs{DEgraph}.
+%
+% The method used to calculate the points to connect is a modified version
+% of the four-step Runge-Kutta method. The modifications are intended to
+% avoid numerical overflow. That is, infinite blow-up in finite time. An
+% example is the simple equation
+% $$
+% \frac{dy}{dx} = y^2 \quad y(0) = 1,
+% $$
+% whose solution is $y = 1/(1-x)$. The usual definition of
+% Runge-Kutta-IV would have one process equally spaced $x$-values. If a
+% user had no idea of the character of the solution, and asked for $N$
+% $x$-values with separation $h$ to get a graph on $0\le x \le Nh$, and if
+% $Nh > 1$, then the result would be either quite different from the actual
+% solution (especially around $x=1$), or would reach a point of numerical
+% overflow.
+%
+% Thus our macros require the user to supply a parameter that will be
+% interpreted as a distance step: if $h$ is this parameter, instead of
+% finding values of $y$ at $x\sb0$, $x\sb{0+h}$, $x\sb{0+2h}$, etc., it
+% finds points $(x\sb{n},y\sb{n})$ on the graph so that the
+% two-dimensional distance from $(x\sb0,y\sb0)$ to $(x\sb1,y\sb1)$ is $h$,
+% then the distance from $(x\sb1,y\sb1)$ to $(x\sb2,y\sb2)$ is also $h$,
+% etc. The resulting graph therefore simply follow the graph of $y =
+% 1/(1-x)$ a distance roughly $Nh$ and numerical overflow is impossible
+% unless the value of $Nh$ exceeds \MF{}'s size limits. There is an
+% optional smoothness parameter as in \cs{function}.
+% \begin{macrocode}
+ \newdef\DEgraph{\mfp@fcn{odeRKIV}s}%
+ \newdef\DEtrajectory{\mfp@fcn{xyRKIV}s}%
+% \end{macrocode}
+%
+% \DescribeMacro{\brownianmotion}
+% Used by me once to ilustrate Brownian motion. The argument consists of
+% a starting point, the number of steps, and a scale factor, separated
+% by commas. It draws a polyline starting with the starting point moving
+% in a random direction a random distance, then repeating that from the
+% new point, etc., for the number of steps given. The size of each step is
+% random, but the scale factor gives the average size.
+%
+% \DescribeMacro{\browniangraph}
+% This approximates the graph of one-dimensional Brownian motion. The
+% argument consists of the number of steps and a scale factor/step size,
+% separated by commas. It draws a polyline starting at $(0,0)$, moving
+% right by the step size and up or down (randomly chosen) by a random
+% amount, then repeating that from the new point, etc., for the number of
+% steps given.
+%
+% \DescribeMacro{\randomwalk}
+% This is a two dimensional random walk. The argument consists of a
+% starting point, the number of steps, and a distance, separated by
+% commas. Like \cs{brownianmotion}, it draws a polyline starting at the
+% starting point, moving in a random direction, but for this command it
+% always moves a fixed distance.
+% \begin{macrocode}
+ \newdef\brownianmotion##1{\mfp@figmac{brownianpath (##1)}}%
+ \newdef\browniangraph##1{\mfp@figmac{browniangraph (##1)}}%
+ \newdef\randomwalk##1{\mfp@figmac{randomwalk(##1)}}%
+% \end{macrocode}
+%
+%
+% \subsection{Plotting data from files}\label{datafiles}
+%
+% \DescribeMacro{\plotdata}
+% The optional parameter is the smoothness, which may be
+% \oarg{s\meta{tension}} for a smooth path or \oarg{p} for a polygonal
+% path, or empty to select the default. The default is \oarg{p} when
+% \mfpic{} is loaded, but can be changed with \cs{smoothdata} and restored
+% with \cs{unsmoothdata}.
+% \begin{macrocode}
+ \newdef\plotdata{\mfp@nullopt\mfp@plotdata}%
+% \end{macrocode}
+%
+% \DescribeMacro{\datafile}
+% \cs{datafile} defines a path connecting the points in a datafile. It has
+% an optional parameter for the smoothness, as in \cs{plotdata}.
+% \begin{macrocode}
+ \newdef\datafile{\mfp@nullopt\mfp@datafile}%
+% \end{macrocode}
+%
+%
+% \subsection{The prefix commands}\label{prefixcommands}
+%
+%
+% \subsubsection{Storing and reusing a figure}\label{storing}
+%
+% \DescribeMacro{\store}
+% This stores an \mfpic{} path in a \MF{} path variable. The argument is
+% the variable name. It should be followed by an \mfpic{} figure macro
+% (such as \cs{rect}\marg{...}). The stored path can be reused via the
+% \cs{mfobj} command. This command is written as a \cs{mfp@rendmac} even
+% though it does no rendering. This is so (1)~it will turn off implicit
+% rendering (any rendering must be explicitly written) and (2) it can be
+% placed anywhere within the prefix area. This is new behavior with
+% version 0.7. Prior to this it was required to place the path to be
+% stored as a second argument. Though that argument could contain other
+% prefixes in addition to the path, it was required that no other prefixes
+% precede \cs{store}. Note that \cs{store} takes a second argument but
+% it merely puts it back. This is so that the old syntax (with the figure
+% macro in braces) will continue to work.
+%
+% \DescribeMacro{\norender}
+% Occasionally it is useful to turn off rendering (say we want to add an
+% arrowhead to a subpath of a path that is already rendered). One could
+% put \cs{store} at the start with an unused name, but as every path is
+% already stored in \gbc{curpath}, that seems redundant. So here is a
+% prefix macro with null rendering and no side effects. It is exactly
+% like \cs{mfp@rendmac}, except it does not end with \cs{mfsrc}.
+% \begin{macrocode}
+ \newdef\store##1##2{\mfp@rendmac{stored (##1)}##2}%
+ \newdef\norender{\mfp@first\@mfprendfalse}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfobj}
+% This is the interface to use a \cs{store}-d object.
+% \cs{mfobj}\marg{\meta{name}} is a figure macro, and should act exactly
+% the same as if the figure macro that had been stored in the variable
+% were typed in its place. Its one argument is the variable name.
+%
+% Instead of the variable name, the argument can contain any reasonable
+% \MF{} path expression. In this context ``reasonable'' means it should
+% contain no special \TeX{} characters that might expand upon being
+% written to the output file. In particular, the backslash and `\verb$~$'
+% should especially be avoided.
+%
+% \DescribeMacro{\mpobj}
+% The macro \cs{mpobj} is just another name for the same command.
+% \begin{macrocode}
+ \newlet\mfobj\mfp@figmac \newlet\mpobj\mfobj
+% \end{macrocode}
+%
+% \DescribeMacro{\mfpimage}
+% The command \cs{mfpimage} starts a group in which drawing commands
+% work just as usual, except they draw in a picture variable, whose name
+% is the only mandatory argument to \cs{mfpimage}.
+% \DescribeMacro{\endmfpimage}
+% The command \cs{endmfpimage} ends that group. There is an optional
+% argument to set the reference point of the created picture, the default
+% being \gbc{(0,0)}. The resulting picture can then be placed using
+% \cs{putmfpimage}.
+% \begin{macrocode}
+ \newdef\mfpimage{\mfp@defaultopt\mfp@image{(0,0)}}%
+ \newdef\endmfpimage{\mfcmd{\@nl concludeimage}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\putmfpimage}
+% This takes the name of a picture variable created with the
+% \cs{mfpimage} environment (or even with the \cs{tile} environment), and
+% places it with its reference point at the points in a list.
+% \begin{macrocode}
+ \newdef\putmfpimage##1{\mfsrc{\@nl putimage (##1)}\mfp@writedata}%
+% \end{macrocode}
+%
+%
+% \subsubsection{Subpaths}
+%
+% \DescribeMacro{\cutoffbefore}
+% This macro take one mandatory argument which is an object stored with
+% \cs{store}. It modifies the path it is prefixed to so that it starts
+% at its first point of intersection with the object, cutting off any
+% earlier part of the path.
+%
+% \DescribeMacro{\cutoffafter}
+% This is similar, except the modified path ends at the last point of
+% intersection between the following path and the object, cutting off
+% any later part of the path. It is internally the same as applying
+% \cs{cutoffbefore} to the reversed path and reversing the result.
+%
+% \DescribeMacro{\trimpath}
+% This trims off the specified absolute amounts from the start and end of
+% the path. The amounts can be specified as two absolute dimensions
+% separated by a comma, or a single dimension. In the second case, that
+% dimension is used at both the start and end.
+%
+% The implementation uses \cs{mfp@modi} which simply reads the argument
+% and writes it (via \cs{mfp@modmac}) as a set of parameters to the
+% appropriate \grafbase{} command. With \cs{trimpath}, however, we have to
+% parse that argument with \cs{mfp@getdimens}.
+% \begin{macrocode}
+ \newdef\cutoffafter {\mfp@modi{cutoffafter}}%
+ \newdef\cutoffbefore{\mfp@modi{cutoffbefore}}%
+ \newdef\trimpath##1{\mfp@getdimens##1,,\mfp@end
+ \mfp@modi{trimmedpath}\mfp@thedimens}%
+% \end{macrocode}
+%
+% \DescribeMacro{\partpath}
+% This produces a subpath of the following path. Its mandatory argument
+% contains two numbers separated by a comma. The numbers should be between
+% 0 and 1 and produce a fraction of the following path.
+% \DescribeMacro{\subpath}
+% The macro \cs{subpath} has a similar argument, but the numbers are
+% between $0$ and the number of segments in the path, and it produces the
+% equivalent of \MF's \mfc{subpath} primitive.
+% \begin{macrocode}
+ \newdef\partpath{\mfp@modi{partialpath}}%
+ \newdef\subpath{\mfp@modi{gsubpath}}%
+% \end{macrocode}
+%
+% \subsubsection{Drawing a curve}\label{drawing}
+%
+% These are rendering macros that draw the curve in some fashion: solid,
+% dashed, colored, etc.
+%
+% \DescribeMacro{\draw}
+% \cs{draw} takes one optional argument, a color. In \MF{}, where the
+% color commands return a numeric, if it is ${}\ge 1$ (representing white)
+% the path is subtracted from the picture, otherwise it is drawn in black
+% (the default). The default in \MP{} is \gbc{drawcolor}.
+%
+% We signal the use of the default color by passing a null optional
+% argument. Because several commands handle color the same way, and all
+% are rendering macros, we have a common macro that only needs the name of
+% the \grafbase{} command.
+% \begin{macrocode}
+ \newdef\draw{\mfp@nullopt{\mfp@clroptrend{drawn}}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\doubledraw}
+% Behaves something like \cs{draw}, except it draws a double line. It
+% takes two optional arguments; the first is the distance between the
+% centers of the two lines (default \gbc{2penwd}) and the second is a
+% color.
+% \begin{macrocode}
+ \newdef\doubledraw{\mfp@defaultopt\mfp@doubledraw{2penwd}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\dashed}
+% \cs{dashed} and \cs{dotted} take one optional argument, which should
+% contain the length of the dashes (diameter of
+% \DescribeMacro{\dotted}
+% dots) and the length of the spaces between, separated by a comma.
+%
+% Several rendering macros take an optional argument which is written as
+% the first parameter of a \grafbase{} command. Thus all are handled with
+% a single macro whose arguments are the name of the command and the
+% default for the optional argument.
+% \begin{macrocode}
+ \newdef\dashed{\mfp@optrendi{DASHED}{\the\dashlen,\the\dashspace}}%
+ \newdef\dotted{\mfp@optrendi{dotted}{\the\dotsize,\the\dotspace}}%
+% \end{macrocode}
+%
+% \cs{gendashed} takes one mandatory argument, the name of a dash pattern
+% previously defined by \cs{dashpattern}. The implementing macro,
+% \cs{mfp@rendi}, is like the above, except it doesn't need to perform the
+% option processing.
+% \begin{macrocode}
+ \newdef\gendashed{\mfp@rendi{gendashed}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\zigzag}
+% This draws a zigzag, crossing from one side of the following path to
+% the other. It has one required argument containing four dimensions,
+% \meta{dim$\sb1$} through \meta{dim$\sb4$}, separated by commas. What is
+% drawn depends on whether the path is closed or open. For an open path,
+% this draws the start of the path for a distance \meta{dim$\sb1$},
+% followed by zigzags, followed by the end of the path for a distance
+% \meta{dim$\sb2$}. For a closed path the first two dimensions are
+% ignored and the zigzags follow the entire path.
+%
+% The last two dimensions define the size and slant of each `zig'. If we
+% think of the zigzags as representing a periodic wave, \meta{dim$\sb3$}
+% is the wavelength and \meta{dim$\sb4$} is the amplitude (distance from
+% the true path to the sharp points).
+%
+% \DescribeMacro{\sinewave}
+% This is similar, but the result is a smooth sinewave shaped rendering.
+%
+% \DescribeMacro{\coil}
+% This creates a coil, or corkscrew-shaped rendering. In this case
+% \meta{dim$\sb3$} is the distance from one loop to the next and
+% \meta{dim$\sb4$} is the maximum distance to each side of the path.
+% An alias,
+% \DescribeMacro{\corkscrew}
+% \cs{corkscrew}, is provided.
+%
+% Both \cs{sinewave} and \cs{corkscrew} take an optional `tension'
+% argument that affects the smoothness of the result. The default is $1$
+% and the higher the value the closer they become to a zigzag.
+% \begin{macrocode}
+ \newdef\zigzag{\mfp@rendi{zigzag}}%
+ \newdef\sinewave {\mfp@defaultopt{\mfp@wiggle{sinewave}}1}%
+ \newdef\coil{\mfp@defaultopt{\mfp@wiggle{corkscrew}}1}%
+ \newlet\corkscrew\coil
+% \end{macrocode}
+%
+% \cs{plot} is like \cs{dotted}, except the dots are variously shaped
+% symbols. It takes one optional argument containing the size of the
+% symbol and the spacing, separated by a comma, and one mandatory
+% argument, the name of the symbol. This can in principal be any
+% expression of type \mfc{picture} or \mfc{path}. (In \MP, type
+% \mfc{string} is also permitted). For the size parameter to work
+% correctly, the symbol should be a path, and it should have 1
+% as it's natural size. \Mfpic{} provides the predefined paths
+% \texttt{Triangle}, \texttt{Square}, \texttt{Circle}, \texttt{Star},
+% \texttt{Diamond}, \texttt{Plus}, \texttt{Cross} and \texttt{Asterisk}.
+% The first 5 have filled-in versions: \texttt{SolidTriangle}, etc.
+%
+% The utility \cs{mfp@optrendii} is similar \cs{mfp@optrendi} except it
+% takes an additional argument, in this case, the first mandatory argument
+% of \cs{plot}.
+% \begin{macrocode}
+ \newdef\plot{%
+ \mfp@optrendii{doplot}{\the\pointsize,\the\symbolspace}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\plotnodes}
+% Sometimes, rather than equally spaced dots or symbols, we would rather
+% have a symbol at each `node' of the following path. If the path is
+% created by a list macro, then usually each point in the list is a node
+% (but some of the spline paths are exceptions). For other figures, the
+% nodes can seem pretty random. For example, a \cs{circle} command without
+% optional argument produces a curve with 8 equally spaced nodes, but with
+% optional argument the nodes depend on how it is drawn and the size of
+% any angle parameter.
+%
+% \cs{plotnodes} has almost the same syntax as \cs{plot}, but since it
+% places the symbols only at the nodes of the path, there is no spacing
+% parameter in the optional argument.
+% \begin{macrocode}
+ \newdef\plotnodes{\mfp@optrendii{plotnodes}{\the\pointsize}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\showcontrols}
+% Mainly for debugging, this places a symbol at the precontrol and
+% postcontrol of each node, and draws a line segment from each symbol to
+% the node. The names of two symbols are given in a mandatory argument,
+% separated by commas. As a special case, if either symbol is just the
+% number `\mfc{0}', it is not drawn. There is an optional argument for
+% the size of these symbols. If the size is zero, neither symbol is drawn.
+% That is useful if one only wants to see the line segments.
+% \begin{macrocode}
+ \newdef\showcontrols{\mfp@optrendii{showcontrols}{\the\pointsize}}%
+% \end{macrocode}
+%
+%
+% \subsubsection{Closing a curve}\label{closing}
+%
+% There are several commands used to close paths (by prefixing them to
+% figure macros). The \grafbase{} commands that implement closing have a
+% common naming pattern. They all contain the string `\texttt{closed},
+% to which is added a distinguishing prefix. If the command takes a
+% tension argument, the letter `\texttt{t}' is appended. The corresponding
+% command without the `\texttt{t}' calls it with a default tension value.
+%
+% These macros all call \cs{mfp@close}, feeding it the proper prefix and
+% the tension value (empty if there is no tension option).
+%
+% \DescribeMacro{\sclosed}
+% The first, \cs{sclosed}, closes smoothly in the same manner that
+% \cs{curve} creates a smooth path.
+%
+% \DescribeMacro{\bclosed}
+% The second, \cs{bclosed}, uses an ordinary \MF{} B\'ezier. These two
+% have an optional argument: the amount of tension to put in the
+% connecting link. This makes no sense with the rest.
+%
+% \DescribeMacro{\lclosed}
+% The macro \cs{lclosed} always draws a straight line from the end of a
+% path to its start.
+%
+% \DescribeMacro{\cbclosed}
+% The macro \cs{cbclosed} computes a closure by calculating cubic B-spline
+% control points from the path data and then generating a connecting
+% spline (see \cs{cspline}).
+%
+% \DescribeMacro{\qbclosed}
+% The macro \cs{qbclosed} is similar, but quadratic B-splines are used.
+%
+% \DescribeMacro{\uclosed}
+% At one time \cs{uclosed} was defined in a more complicated manner than
+% necessary, but actually produced exactly the same path as \cs{bclosed}.
+% So now they are just made to be equal.
+% \begin{macrocode}
+ \newdef\bclosed{\mfp@nullopt{\mfp@close b}}%
+ \newdef\sclosed{\mfp@nullopt{\mfp@close s}}%
+ \newdef\lclosed{\mfp@close l{}}%
+ \newdef\cbclosed{\mfp@close{cb}{}}%
+ \newdef\qbclosed{\mfp@close{qb}{}}%
+ \newlet\uclosed\bclosed
+% \end{macrocode}
+%
+% \DescribeMacro{\makesector}
+% Takes a following arc and draws the sector (even if the center point
+% is not known). It really only works if prefixed to one of the
+% \cs{arc} commands, but it will attempt to create something even for
+% other paths. It calculates the center of the circle containing the arc
+% and connects that to the endpoints with two straight lines.
+% \begin{macrocode}
+ \newdef\makesector{\mfp@modmac{makesector}}%
+% \end{macrocode}
+%
+%
+% \subsubsection{Filling a closed curve}\label{filling}
+%
+% The next few prefix macros fill the interior of the closed path that
+% follows with some sort of pattern. The path must be closed; if not,
+% the path will simply be drawn with a solid line.
+%
+% \DescribeMacro{\tess}
+% \cs{tess} takes one mandatory argument, the name of a previously defined
+% tile (see subsection~\ref{composite}), and fills with shifted copies of
+% the tile.
+% \begin{macrocode}
+ \newdef\tess{\mfp@rendi{tess}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\shade}
+% \cs{shade} is implemented in \MF{} by filling a region with a pattern
+% of dots, simulating gray. It take one optional parameter, the separation
+% between dots, defaulting to \cs{shadespace}. The size of the dots is
+% set by issuing the command \cs{shadewd}. In \MP{} a gray fill is
+% used but the syntax is the same. It would be better to just use
+% \cs{gfill} instead (described later).
+%
+% \DescribeMacro{\polkadot}
+% This command is actually meant to fill with a pattern of large dots.
+% It also takes the separation between dots (default \cs{polkadotspace})
+% as an optional argument. The command \cs{polkadotwd} sets the size of
+% the dots.
+% \begin{macrocode}
+ \newdef\shade{\mfp@optrendi{shade}{\the\shadespace}}%
+ \newdef\polkadot{\mfp@optrendi{polkadot}{\the\polkadotspace}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\thatch}
+% The hatching macros mostly take two optional parameters, the
+% separation of the hatching lines (default \cs{hatchspace}) and their
+% color. One slight exception is \cs{thatch}, which is called by all the
+% others. Its first optional argument is the separation \emph{and} the
+% angle (default $0$) of the lines, separated by a comma. The other
+% hatching macros have a fixed angle.
+% \DescribeMacro{\lhatch}
+% The macro \cs{lhatch} has lines at a $-45$ degree angle (upper left to
+% lower right),
+% \DescribeMacro{\rhatch}
+% \cs{rhatch} produces the opposite diagonal (angle $45$ degrees), and
+% \DescribeMacro{\xhatch}
+% \cs{xhatch} does both sets of lines (cross hatching).
+% \begin{macrocode}
+ \newdef\thatch{\mfp@defaultopt\mfp@thatch{\the\hatchspace,0}}%
+ \newdef\lhatch{\mfp@defaultopt\mfp@lhatch{\the\hatchspace}}%
+ \newdef\rhatch{\mfp@defaultopt\mfp@rhatch{\the\hatchspace}}%
+ \newdef\xhatch{\mfp@defaultopt\mfp@xhatch{\the\hatchspace}}%
+ \newlet\hatch\xhatch
+% \end{macrocode}
+%
+% \DescribeMacro{\gradient}
+% The \cs{gradient} command approximates a linear gradient fill using
+% adjacent strips of different colors. It takes one mandatory argument
+% containing three items separated by commas. The first is a
+% \mfc{vardef}-ed function that produces the colors, the second is the
+% thickness of the color strips and the third is the angle these strips
+% make with the horizontal.
+%
+% \DescribeMacro{\areagradient}
+% This allows more general shading. It produces a fill consisting of
+% differently colored ``pixels''. It also takes one mandatory argument
+% containing three items separated by commas. The first is a
+% function of two variables that produces the colors, the second is the
+% width of the pixels and the third is their height.
+%
+% \DescribeMacro{\radialgradient}
+% This allows shading in a concentric circular pattern. It produces a fill
+% consisting of differently colored circular strips. It also takes one
+% mandatory argument containing three items separated by commas. The first
+% is a function of one variable that produces the colors, the second is
+% the thickness of the circular strips, and the third is an ordered pair
+% (the center the circles).
+% \begin{macrocode}
+ \newdef\gradient{\mfp@rendi{axialgradient}}%
+ \newdef\areagradient{\mfp@rendi{areagradient}}%
+ \newdef\radialgradient{\mfp@rendi{radialgradient}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\gfill}
+% \cs{gfill} take one optional argument, the color with which to fill.
+% Under \MF{} the color must be a numeric (representing a level of gray)
+% or one of the color functions, which are defined in \file{grafbase.mf}
+% to return numeric values.
+%
+% \DescribeMacro{\gclear}
+% \cs{gclear} will actually fill with the color \texttt{background} in \MP.
+% This merely covers what originally was there.
+%
+% \DescribeMacro{\gclip}
+% \cs{gclip} clears the outside of a region, but it is a true clip
+% operation, completely different from \cs{gclear}.
+% \begin{macrocode}
+ \newdef\gfill{\mfp@nullopt{\mfp@clroptrend{filled}}}%
+ \newdef\gclear{\mfp@rendmac{unfilled}}%
+ \newdef\gclip{\mfp@rendmac{Clip}}%
+% \end{macrocode}
+%
+%
+% \subsubsection{Modifying a curve}\label{transforming}
+%
+% The following are transformation prefixes. They are all (except
+% \cs{reverse}, for reasons covered in section~\ref{prefix}) implemented
+% with \cs{mfp@modmac}. Most have a mandatory argument, the parameters of
+% the transformation. Because of the implementation, one can insert
+% rendering macros between a transformation macro and the path being
+% transformed, and they will apply to the untransformed path.
+%
+% If the \env{mfpic} environment has different $x$ and $y$ scales, the
+% \cs{rotatepath} and \cs{reflectpath} compensates so that the result is
+% congruent to the original. This is what users seem to expect. The rest
+% do not compensate and users don't seem to mind.
+% \begin{itemize}
+% \item \cs{reverse} and \cs{xyswappath} have no argument.
+% \item \cs{reversepath} = \cs{reverse}.
+% \item \cs{rotatepath} takes \marg{\meta{point},\meta{angle}}.
+% \item \cs{shiftpath} takes \marg{\meta{pair}}.
+% \item \cs{scalepath} takes \marg{\meta{center of scaling},\meta{factor}}.
+% \item \cs{xscalepath} takes \marg{\meta{x-center},\meta{factor}}.
+% \item \cs{yscalepath} takes \marg{\meta{y-center},\meta{factor}}.
+% \item \cs{slantpath} takes \marg{\meta{y-pivot},\meta{factor}}.
+% \item \cs{xslantpath} = \cs{slantpath}.
+% \item \cs{yslantpath} takes \marg{\meta{x-pivot},\meta{factor}}.
+% \item \cs{reflectpath} takes \marg{\meta{point1},\meta{point2}}, the
+% endpoints of a `mirror'.
+% \item \cs{transformpath} takes \marg{\meta{transformer}}, a \MF{}
+% `transformer' (see ``The \MF book'', page~212).
+% \end{itemize}
+%
+% All of them simply write the \grafbase{} command of nearly the same
+% name, with the same arguments, via
+% \cs{mfp@modi}.\SpecialUsageIndex{\reversepath}\SpecialUsageIndex{\reverse}
+% \SpecialUsageIndex{\xyswappath}\SpecialUsageIndex{\rotatepath}
+% \SpecialUsageIndex{\shiftpath}\SpecialUsageIndex{\scalepath}
+% \SpecialUsageIndex{\xscalepath}\SpecialUsageIndex{\yscalepath}
+% \SpecialUsageIndex{\slantpath}\SpecialUsageIndex{\xslantpath}
+% \SpecialUsageIndex{\yslantpath}\SpecialUsageIndex{\reflectpath}
+% \SpecialUsageIndex{\transformpath}
+%
+% \begin{macrocode}
+ \newdef\reversepath{\mfp@addmac{reverse}}%
+ \newlet\reverse\reversepath
+ \newdef\xyswappath{\mfp@modmac{xyswappedpath}}%
+ \newdef\rotatepath{\mfp@modi{rotatedpath}}%
+ \newdef\shiftpath{\mfp@modi{shiftedpath}}%
+ \newdef\scalepath{\mfp@modi{scaledpath}}%
+ \newdef\xscalepath{\mfp@modi{xscaledpath}}%
+ \newdef\yscalepath{\mfp@modi{yscaledpath}}%
+ \newdef\xslantpath{\mfp@modi{xslantedpath}}%
+ \newlet\slantpath\xslantpath
+ \newdef\yslantpath{\mfp@modi{yslantedpath}}%
+ \newdef\reflectpath{\mfp@modi{reflectedpath}}%
+ \newdef\transformpath{\mfp@modi{transformedpath}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\parallelpath}
+% This is not an affine transformation, but is a transformation of sorts.
+% It tries to define a curve that parallels the following curve at a fixed
+% distance. The mandatory argument is the separation, in graph units. It
+% is sort of experimental and will probably fail if the path that follows
+% is too wild. Since \cs{doubledraw} shares code with \cs{parallelpath},
+% that too will probably fail in similar circumstances.
+% \begin{macrocode}
+ \newdef\parallelpath{\mfp@modi{parapath}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\randomizepath}
+% This, too, is a nonaffine transformation. It tries to define a curve
+% that remains smooth if the original is, but applies random shifts to the
+% nodes and random changes to the direction at each node.
+%
+% The only argument is mandatory and consists of a maximum shift (in graph
+% units) and a `weirdness' (a pure number) separated by a comma.
+%
+% The maximum shift can be a number, in which case it is the maximum
+% possible distance and there is no preferred direction, or it can be an
+% ordered pair, in which case it gives maximum horizontal and vertical
+% shift amounts.
+%
+% The `weirdness' is applied to path directions. If it is 0, there is no
+% change in directions of the path at nodes. If it is a positive number
+% $w$, a random angle of up to $\pm 30 w$ is added to the directions at
+% each node. Also a random scaling between $2^{-w}$ and $2^w$ is applied
+% to the control vectors. Also, if a path has a corner, the angle between
+% the two sides is randomly adjusted to be between $2^{-w}$ and $2^w$
+% times its original size.
+%
+% \DescribeMacro{\randomlines}
+% This is a simpler version whose mandatory argument contains only the
+% maximum shift parameter. It shifts the nodes and connects the results
+% with straight lines.
+% \begin{macrocode}
+ \newdef\randomizepath{\mfp@modi{randompath}}%
+ \newdef\randomlines{\mfp@modi{randomlines}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\interpolatepath}
+% This prefix macro has one mandatory argument containing a number and a path,
+% separated by a comma. The number can be any \MF{} numeric expression and
+% the path can be any \MF{} path expression. The number should normally be
+% in the range $0$ to $1$ and the path normally a variable (e.g, defined using
+% \cs{store}). It returns a path which is between the one in its argument
+% and the one that follows. If the number is $0$, the following path is
+% returned unchanged, if the number is $1$ the path in the argument is
+% returned.
+% \begin{macrocode}
+ \newdef\interpolatepath{\mfp@modi{interpolatedpath}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\arccomplement}
+% This can precede an arc and then returns its complement. It starts at
+% the last point of the following arc and ends at the beginning of that
+% arc. The sense of the resulting arc (clockwise or anticlockwise) is the
+% same as the arc it is applied to. If the following path is not an arc,
+% the result is an arc that connects the end of the path to the beginning,
+% but may bear no obvious relation to that path.
+% \begin{macrocode}
+ \newdef\arccomplement{\mfp@modmac{arccomplement}}%
+% \end{macrocode}
+%
+%
+% \subsubsection{Adding arrowheads (and tails)}\label{arrows}
+%
+% Paths can now have heads and tails and something placed in the
+% middle. Also the head, tail or the `something' can be any symbol. In
+% addition to the \cs{plotsymbol} possibilities, there is \gbc{Arrowhead},
+% which is the arrowhead of previous \mfpic{} versions, as well as
+% \gbc{Leftharpoon} and \gbc{Rightharpoon}, which are the left and right
+% halves.
+%
+% Intended for middle or tail of an arrow are \gbc{Crossbar}, \gbc{Leftbar}
+% and \gbc{Rightbar}, and for the tail there are \gbc{Lefthook} and
+% \gbc{Righthook}. \gbc{Crossbar} cuts right across the shaft
+% (perpendicular unless a rotation option is present) while \gbc{Leftbar}
+% extends to the left (from the point of view of someone facing in the
+% direction of the path. Similarly \gbc{Lefthook} curls to the left of the
+% arrow's shaft.
+%
+% All the new arrow commands take one mandatory argument, the name of the
+% symbol, followed by up to four optional arguments. Three of the optional
+% arguments are the same for all commands: these set the color, the size
+% and the amount of rotation of the symbol. Normally the symbol is
+% adjusted to `point' in the direction of the path (\gbc{Crossbar} is
+% actually perpendicular to it); with the rotation option it can be
+% adjusted.
+%
+% For example, \oarg{c red} makes the symbol red, \oarg{l 5pt} or \oarg{s
+% 5pt} scales the symbol so its nominal size or length is 5 points,
+% \oarg{r 10} rotates the symbol 10 degrees (anticlockwise) from its
+% default position.
+%
+% The other optional argument depends on the command: for heads it is an
+% amount to shift the head backward, for tails the amount to shift it
+% forward, and for things placed in the middle, it is the fraction of the
+% length of the path along which the symbol is placed.
+%
+% For example, \oarg{b 2pt} shifts a head two points backward, \oarg{f
+% 2pt} shifts a tail 2 points forward and \oarg{f .5} puts the symbol
+% right in the middle.
+%
+% The letters are mnemonics, being the initial letters of the words
+% `color', `length' or `size', `rotate', `back', and `forward' or
+% `fraction'. Actually, the letters \texttt{s} and \texttt{l} have
+% identical effects since I couldn't decide which mnemonic was more
+% natural. Oddly, \texttt{b} and \texttt{f} have identical effects also.
+% So if you accidentally use \oarg{b 2pt} for a tail, it will still be
+% shifted \emph{forward}! The reason for this is that these \mfpic{}
+% commands all correspond to \grafbase{} commands that have the same
+% argument structure. Both \texttt{b} and \texttt{f} simply cause the
+% accompanying value to be written into the fourth argument, while the
+% different commands use that argument differently. (You can shift a
+% tail backwards with a negative argument, if you really need that.)
+%
+% \DescribeMacro{\arrowhead}\SpecialUsageIndex{\arrow}
+% The \cs{arrowhead} command has a star-form which allows part of the
+% path beyond the tip of the arrowhead to be erased. The presence of a
+% star ultimately changes the \MF{} command passed on to later macros.
+% It does so by passing to \cs{mfp@arrowhead} the word `\texttt{true}' for
+% the star-form and `\texttt{false}' otherwise.
+%
+% The old \cs{arrow} command first checks for a star, and passes to
+% \cs{mfp@arrow} either an `\texttt{x}' or an empty parameter. This is
+% used to construct the \grafbase{} command name. We use \cs{def}
+% because \prog{eplain} defines one also.
+% \begin{macrocode}
+ \newdef\arrowhead{\mfp@ifstar\mfp@arrowhead\mfp@T\mfp@F}%
+ \def\arrow{\mfp@ifstar\mfp@arrow{x}{}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\arrowtail}
+% Tails are just like heads except that there is no star-form and the
+% \grafbase{} command name (second parameter of \cs{mfp@arr}) is
+% different.
+% \DescribeMacro{\arrowmid}
+% And \cs{arrowmid} is just like \cs{arrowtail} except for the command
+% name and the different default for the position optional argument.
+% \begin{macrocode}
+ \newdef\arrowtail##1{\mfp@arr 0{tailpath (##1)}}%
+ \newdef\arrowmid##1{\mfp@arr{0.5}{midpath (##1)}}%
+% \end{macrocode}
+%
+% This ends the prefix macros.
+%
+%
+% \subsection{Transforming the coordinate system}\label{coordinate}
+%
+% \DescribeMacro{\coords}
+% The following apply transforms to the \MF{} coordinate system, and
+% these can be localized with the \env{coords} environment. In plain
+% \TeX{} \cs{coords} starts the environment and
+% \DescribeMacro{\endcoords}
+% \cs{endcoords} closes it. The transforms apply when the curve is
+% \emph{rendered} and do not affect what paths are defined. Thus, for
+% example, \cs{store} will store the same path whatever the state of the
+% coordinate system. In terms of \grafbase{} commands, only \gbc{vtr} and
+% \gbc{ztr} are changed, and these are only applied when rendering.
+%
+% \DescribeMacro{\applyT}
+% These are implemented by \cs{applyT} which takes as its argument a \MF{}
+% `transformer'.
+%
+% These commands (except \cs{turn}, kept for backward compatibility) have
+% no optional arguments, only mandatory arguments containing the
+% parameters of the transformation. \cs{rotate} rotates around the origin,
+% \cs{rotatearound} rotates around a given point, \cs{turn} takes the point
+% as an optional argument, defaulting to $(0,0)$.
+%
+% Transformations are applied in reverse of the order they appear in the
+% file (i.e., the most recent first). This applies even if \env{coords}
+% environments are nested, except that at \cs{endcoords} the state at
+% the matching \cs{coords} is restored.
+% \begin{macrocode}
+ \newdef\coords{\mfsrc{\@nl bcoords\@nl}}%
+ \newdef\endcoords{\mfsrc{\@nl ecoords\@nl}}%
+ \newdef\applyT##1{\mfsrc{\@nl hide(apply_t (##1))}}%
+ \def\rotate##1{\applyT{rotated ##1}}%
+ \newdef\rotatearound##1##2{%
+ \applyT{rotatedaround (##1, ##2)}}%
+ \newdef\turn{\mfp@defaultopt\mfp@turn{(0,0)}}%
+ \newdef\reflectabout##1##2{\applyT{reflectedabout (##1, ##2)}}%
+ \let\mirror\reflectabout
+ \newdef\shift##1{\applyT{shifted ##1}}% pair.
+ \def\scale##1{\applyT{scaled ##1}}% same scaling
+ \newdef\xscale##1{\applyT{xscaled ##1}}%
+ \newdef\yscale##1{\applyT{yscaled ##1}}%
+ \newdef\zscale##1{\applyT{zscaled ##1}}%
+ \newdef\xslant##1{\applyT{xslant ##1}}%
+ \newdef\yslant##1{\applyT{yslant ##1}}%
+ \newdef\zslant##1{\applyT{zslant ##1}}%
+ \newdef\boost##1{\applyT{boost ##1}}%
+ \newdef\xyswap{\applyT{xyswap}}%
+% \end{macrocode}
+%
+%
+% \subsection{Axes and grids}\label{axes}
+%
+% An axis would normally not be thought of as a figure macro, because one
+% would not want to position them arbitrarily nor transform them. One
+% would also not want the hassle of having always to specify the origin,
+% etc. However, one would want to occasionally make them dotted or dashed
+% or colored.
+%
+% \DescribeMacro{\axes}
+% The original \cs{axes} was therefore not a figure macro. It always drew
+% both axes with solid lines.
+% \DescribeMacro{\xaxis}
+% Later \cs{xaxis} and \cs{yaxis} were introduced, which mimicked the
+% behavior of \cs{axes}. For backward
+% \DescribeMacro{\yaxis}
+% compatibility, the old behavior is supported with the old commands. The
+% optional argument to \cs{axes}, \cs{xaxis} and \cs{yaxis} is the length
+% of the arrowhead, defaulting to \cs{the}\cs{axisheadlen}.
+% \begin{macrocode}
+ \newdef\xaxis{\mfp@defaultopt{\mfp@simple{xaxis}}{\the\axisheadlen}}%
+ \newdef\yaxis{\mfp@defaultopt{\mfp@simple{yaxis}}{\the\axisheadlen}}%
+ \newdef\axes{\mfp@defaultopt {\mfp@simple{axes}}{\the\axisheadlen}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\axis}
+% When border axes were added, all the code was revamped, and now we
+% create axes as figure macros. It also became clear there was so
+% much common code that it would be better to implement the syntax
+% \cs{axis}\marg{l}, etc., rather than have separate commands \cs{laxis},
+% etc. for all six possible axes. Therefore, only the $x$- and $y$-axes
+% have their own commands. The \cs{axis} command has one optional argument
+% (the arrowhead length) and one mandatory argument, a single letter
+% designating the axis to draw.
+%
+% \DescribeMacro{\axisline}
+% The \cs{axisline} command is provided for users who want more control.
+% It is a figure macro that produces the corresponding line, and the user
+% can use all the flexibility of the \cs{arrowhead} command if necessary.
+% \begin{macrocode}
+ \newdef\axis{\mfp@nullopt\mfp@axis}%
+ \newdef\axisline##1{\mfp@figmac{axisline.##1}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\doaxes}
+% \cs{doaxes} takes one optional argument, the arrowhead length, and one
+% mandatory argument, all the axes to draw. These should be just letters
+% with nothing separating them except optional spaces. \cs{doaxes} is
+% implemented via the self-looping macro \cs{mfp@doaxis}.
+%
+% \DescribeMacro{\border}
+% The \cs{border} command is almost equivalent to \cs{doaxes}\marg{lbrt},
+% except it is a figure macro. With it, the whole picture can be filled
+% with a background color, or outlined in any available rendering.
+% \begin{macrocode}
+ \newdef\doaxes{\mfp@nullopt\mfp@doaxes}%
+ \newdef\border{\mfp@figmac{borderrect}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\axismarks}
+% Hash marks (or tick marks) on the axes are provided by the
+% \cs{axismarks} command (\cs{marks} was the original choice, but that
+% turned out to conflict with one of e\kern-.06em\TeX's primitives).
+% For brevity, therefore, we also have separate commands
+% \DescribeMacro{\xmarks}
+% \cs{xmarks},
+% \cs{ymarks}\SpecialUsageIndex\ymarks,
+% \cs{lmarks}\SpecialUsageIndex\lmarks,
+% \cs{bmarks}\SpecialUsageIndex\bmarks,
+% \cs{rmarks}\SpecialUsageIndex\rmarks, and
+% \cs{tmarks}\SpecialUsageIndex\tmarks.
+%
+% \cs{axismarks} has two mandatory arguments: the letter for the axis, and
+% a comma separated list of numbers giving the positions on the axis. It
+% functions as a list macro (see previous discussion of types of macros)
+% and so the list of numbers can be prescribed by an external file
+% \cs{datafile}\marg{\meta{file}}. One must be sure to issue an
+% appropriate \cs{using} command to produce a numeric list in the output.
+% This is the main reason for the \cs{usingnumericdefault} command.
+%
+% I had a change of heart after the \cs{axis} command, and I made things
+% simpler to code here by putting the optional argument of \cs{axismarks}
+% after the first mandatory argument. I could justify this because I
+% expect most users will use the shorter versions that don't require the
+% first argument (that is, the expectation that optional arguments come
+% first is still satisfied). The optional argument is the length of the
+% marks. The position of the marks is controlled separately by the
+% \cs{setaxismarks} command, described in subsection~\ref{othersettings}.
+% \begin{macrocode}
+ \newdef\axismarks##1{\mfp@defaultopt{\mfp@marks{##1}}{\the\hashlen}}%
+ \newdef\xmarks{\axismarks x}%
+ \newdef\ymarks{\axismarks y}%
+ \newdef\lmarks{\axismarks l}%
+ \newdef\bmarks{\axismarks b}%
+ \newdef\rmarks{\axismarks r}%
+ \newdef\tmarks{\axismarks t}%
+% \end{macrocode}
+%
+% \DescribeMacro{\grid}
+% The command \cs{grid} is, I think, inaccurately named: the word `grid'
+% suggests a set of lines, but this actually produces dots. Its function
+% is to allow a visualization of the coordinates. The dots are located at
+% the points whose coordinates are integer multiples of two numbers, which
+% are given in the single mandatory argument separated by commas. The
+% optional first argument is the diameter of the dots. This defaults to
+% \cs{griddotsize}, initially \texttt{0.5pt}.
+%
+% Because of my concerns about the name, I have provided two aliases:
+% \cs{gridpoints}\SpecialUsageIndex{\gridpoints} (for consistency with
+% \cs{gridlines}, below) and \cs{lattice}\SpecialUsageIndex{\lattice}.
+%
+% \DescribeMacro{\gridlines}
+% Macro \cs{gridlines} has no optional argument and takes the same
+% mandatory argument as \cs{grid}. It draws horizontal and vertical lines
+% intersecting at all the dots that \cs{grid} would draw. Some packages
+% (and \ConTeXt) define a \cs{grid} command so we use \cs{def} here
+% instead of \cs{newdef}.
+%
+% \DescribeMacro{\hgridlines}
+% This draws only the horizontal lines and its argument is the separation
+% (in graph units) between successive lines.
+% \DescribeMacro{\vgridlines}
+% \cs{vgridlines} is the vertical version.
+%
+% No arguments are shown because \cs{mfp@simple} or \cs{mfp@simplei} will
+% read what it needs.
+% \begin{macrocode}
+ \def\grid{\mfp@defaultopt{\mfp@simplei{vargrid}}{\the\griddotsize}}%
+ \newlet\gridpoints\grid \newlet\lattice\grid
+ \newdef\gridlines{\mfp@simple{gridlines}}%
+ \newdef\vgridlines{\mfp@simple{vgridlines}}%
+ \newdef\hgridlines{\mfp@simple{hgridlines}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\plrgrid}
+% The command \cs{plrgrid} takes one mandatory argument which contains two
+% numbers separated by a comma. The first is a radius (in graph
+% coordinates) and the second an angle. It draws circular arcs at integer
+% multiples of the radius, and radial lines at integer multiples of the
+% angle. It fills the picture rectangle and is clipped to that rectangle.
+%
+% \DescribeMacro{\plrgridpoints}
+% \cs{plrgridpoints} is similar but places only dots at the intersections
+% of these arcs and rays. It takes an optional argument for the size of
+% the dots, default \cs{griddotsize}.
+% \DescribeMacro{\gridarcs}
+% The macro \cs{gridarcs} draws only the arcs. Its only parameter is the
+% distance between them (in graph units).
+% \DescribeMacro{\gridrays}
+% The macro \cs{gridrays} draws only the rays and its parameter is the
+% angle separating the rays.
+%
+% \DescribeMacro{\plrpatch}
+% \cs{plrpatch} draws: a circular arc at a starting radius, then
+% increments that radius by a step size and draws another arc, etc., and
+% finally draws an arc at the ending radius. It does a similar thing for
+% radial lines and angles. It takes one mandatory argument, which contains
+% $6$ numbers separated by commas: starting radius, ending radius, radius
+% step, starting angle, ending angle, angle step.
+% \begin{macrocode}
+ \newdef\plrgrid{\mfp@simple{polargrid}}%
+ \newdef\plrgridpoints{%
+ \mfp@defaultopt{\mfp@simplei{polargridpoints}}{\the\griddotsize}}%
+ \newdef\gridarcs{\mfp@simple{gridarcs}}%
+ \newdef\gridrays{\mfp@simple{gridrays}}%
+ \newdef\plrpatch{\mfp@simple{polarpatch}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\vectorfield}The \cs{vectorfield} command draws arrows to
+% represent a vector field. It takes one optional argument, the length of
+% the arrowhead (default \cs{headlen}), and three mandatory arguments. The
+% first is like \cs{grid}: it contains two numbers, separated by commas.
+% The arrows are located at the points whose coordinates are integer
+% multiples of two numbers. The second argument is the formula for the
+% vector field. It should consist of a pair expression in which the only
+% unknowns are the variables \texttt{x} and \texttt{y}. The last argument
+% should contain a boolean expression in which the only unknowns are
+% \texttt{x} and \texttt{y}. The macro steps through the relevant set of
+% points and draws the vector only if the boolean is true at that point.
+% The set of points considered includes only those inside the axis margins
+% (set by \cs{axismargin} and related commands). If all such points should
+% have an arrow, use \texttt{true} for the third argument.
+% \begin{macrocode}
+ \newdef\vectorfield{%
+ \mfp@defaultopt{\mfp@vectorfield{}}{\the\headlen}}%
+ \newdef\plrvectorfield{%
+ \mfp@defaultopt{\mfp@vectorfield{plr}}{\the\headlen}}%
+% \end{macrocode}
+%
+%
+% \subsection{Visualizing points}\label{points}
+%
+% \DescribeMacro{\point}
+% \cs{point} draws a dot or a small circle. It takes one optional
+% argument, the diameter of the dot, and one mandatory argument, the ordered
+% pair (or comma separated list of them) at which to draw a dot. After
+% \cs{pointfillfalse}, the dots will be unfilled (i.e., small circles),
+% after \cs{pointfilltrue} (the default), they will be solid. Like the
+% grid macros, it is not a figure macro, but merely does its drawing and
+% is not subject to any prefix macros.
+%
+% \DescribeMacro{\plotsymbol}
+% In order to mark points with other than circles, we have the
+% \cs{plotsymbol} command, so-called because it uses the same symbols as
+% the \cs{plot} command (previously discussed). There is an optional
+% argument that gives the size of the symbol, a mandatory argument with
+% the name of the symbol, and a second mandatory argument which
+% is a comma separated list of ordered pairs for the locations.
+%
+% For both these commands, the default optional argument is
+% \cs{the}\cs{pointsize}. These are list macros: in place of a list of
+% points in braces, one can use the \cs{datafile} construct.
+% \begin{macrocode}
+ \newdef\point{\mfp@defaultopt\mfp@point{\the\pointsize}}%
+ \newdef\plotsymbol{\mfp@defaultopt\mfp@plotsymbol{\the\pointsize}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\plottext}
+% We keep \cs{plottext} for backward compatability. It is equivalent
+% to a \cs{tlabel} command with a different default for the justification
+% (\oarg{cc}) and the arguments rearranged. The order for \cs{plottext}
+% is: optional justification, then \TeX{} label, then list of points.
+% Because of the complication involved in making it work, in this case we
+% do not allow a datafile to replace the list of points. All this
+% command now does is perform a simplified version of the start of the
+% \cs{tlabel} command and jump to one of its internals, \cs{mfp@thelabel}.
+% \begin{macrocode}
+ \newdef\plottext{\begingroup\mfp@resetwhitespace\mp@mksharpother
+ \mfp@defaultopt\mfp@plottext{cc}}%
+% \end{macrocode}
+%
+%
+% \subsection{Some composite objects}\label{composite}
+%
+% \DescribeMacro{\tile}
+% A tile is syntactically a \MF{} picture variable. The commands between
+% \cs{tile} and \cs{endtile} (or \cs{begin}\marg{tile} and
+% \cs{end}\marg{tile}) should be any sequence of \mfpic{} figure macros
+% with possible prefix macros. They will be drawn not on the main picture
+% (\gbc{currentpicture}), but on the picture given by the name in the
+% \cs{tile} command's argument.
+%
+% The argument has five parts separated by commas, the first is the
+% name, the second is the unit of length (some absolute dimension like
+% \mfc{1pt}), the next two are the width and height (pure numbers, the
+% actual dimensions being these numbers times the unit of length), the
+% last is one of the words \mfc{true} or \mfc{false}, indicating whether
+% tile should be clipped to these dimensions (true) or allowed to extend
+% beyond them (false).
+% \begin{macrocode}
+ \newdef\tile{\mfp@simple{tile}}%
+ \newdef\endtile{\mfcmd{\@nl endtile}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\patharr}
+% A path array is a set of \MF{} path variables each having the same base
+% name followed by a different numeric suffix. This command turns off
+% rendering and simply assigns these variables in order to the path
+% expressions written by the figure macros between \cs{patharr} and
+% \cs{endpatharr}. It works by redefining \cs{mfp@storepath}, issued by all
+% the figure macros. These variables can be accessed in \mfpic{} by using
+% the \cs{mfobj} command. The name of the path array \emph{without} a
+% numeric suffix is a \MF{} numeric variable whose value is the number of
+% array elements.
+%
+% \emph{Explicit} rendering commands will work in the sense that the
+% affected path will be rendered in addition to being assigned to the
+% variable. The only parameter is the common base name of the variables.
+% \begin{macrocode}
+ \newdef\patharr##1{\begingroup
+ \mfsrc{hide(numeric ##1; path ##1[]; ##1 = 0)}%
+ \def\mfp@storepath{\mfsrc{\@nl store (##1[incr ##1])}}%
+ \setrender{}}%
+ \newdef\endpatharr{\endgroup}%
+% \end{macrocode}
+%
+% \DescribeMacro{\connect}
+% This starts an environment that can contain any sequence of figure
+% macros. The environment functions as a single large \cs{mfp@figmac}, the
+% figure being the path obtained by connecting all the paths
+% \DescribeMacro{\endconnect}
+% (up to the following \cs{endconnect} command) by straight lines from the
+% end of one to the beginning of the next. It is implemented via a path
+% array, so the individual figures within the environment have implicit
+% rendering turned off. Explicit rendering commands within the
+% environment will have the expected effect.
+%
+% The \cs{mfp@checklatexenv} at the end allows \cs{connect} to be used as
+% a \LaTeX{} environment.
+% \begin{macrocode}
+ \newdef\connect{\mfp@figmac{begingroup; save mfpicnexus}%
+ \patharr{mfpicnexus}}%
+ \newdef\endconnect{\endpatharr
+ \mfcmd{\@nl mkpoly (\mfp@F, mfpicnexus)\@nl endgroup}%
+ \mfp@checklatexenv{connect}{\aftergroup\@mfpstarttrue}{}}%
+% \end{macrocode}
+%
+%
+% \subsection{Other graphical features}\label{otherfeatures}
+%
+% And now for something completely different.
+%
+% \DescribeMacro{\piechart}
+% Actually, nothing is drawn by the \cs{piechart} command; it only defines
+% a path array and a few other internal variables. Since nothing is
+% drawn by this command, it makes sense to allow it outside the drawing
+% environment, so it has been made available outside \env{mfpic}
+% environments with the command name \cs{mfppiechart}(page
+% \pageref{charts}).
+%
+% The \cs{piechart} command takes one optional argument and two mandatory
+% argument. The first mandatory argument contains the center and radius of
+% the chart separated by a comma; the second is the list of data. The
+% optional argument contains a letter and an optional angle. The letter
+% can be `\texttt{c}' for clockwise or `\texttt{a}' for anticlockwise and
+% determines the direction around the pie the different wedges will be drawn.
+% The angle determines the angle of the first edge (in the given
+% direction) of the first wedge. The default letter is \texttt{c} and the
+% default angle is $90$ degrees, which starts the first wedge at
+% 12~o'clock and proceeds from there either clockwise or anticlockwise..
+%
+% \cs{piechart} acts like a list macro in that the above arguments should
+% be followed by either a list of numbers in braces or a \cs{datafile}
+% command (with numbers in a datafile). If this feature is used, an
+% appropriate \cs{using} command is needed. If the numbers are listed one
+% per line, then \cs{usingnumericdefault} should work.
+%
+% \DescribeMacro{\piewedge}
+% Each individual wedge (elements of the above mentioned path array) may
+% be drawn using the \cs{piewedge} command, which is a figure macro. That
+% command takes one optional argument that determines how the wedge is
+% drawn (described below) and one mandatory argument, the number of the
+% wedge. Without the optional argument, \cs{piewedge}\marg{1} draws the
+% first wedge in the position given by the arguments of the \cs{piechart}
+% command, as described above.
+%
+% The optional arguments can be:
+% \begin{itemize}
+% \item \oarg{x\meta{distance}}, the wedge is `exploded': drawn
+% shifted radially outward from the center of the pie chart by
+% \meta{distance} (in graph units).
+% \item \oarg{s(\meta{dx},\meta{dy})}, the wedge is shifted from its
+% position by \meta{dx} horizontally and \meta{dy} vertically (in
+% graph units).
+% \item \oarg{m(\meta{x},\meta{y})}, the wedge is moved so that its
+% point is at coordinates \parg{\meta{x},\meta{y}}.
+% \end{itemize}
+% \begin{macrocode}
+ \newlet\piechart\mfppiechart
+ \newdef\piewedge{\mfp@defaultopt\mfp@piewedge{d}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\barchart}
+% As with \cs{piechart}, the \cs{barchart} command does not actually draw
+% anything, but defines a path array, so we make available a version for
+% use outside \cs{mfpic} environments: \cs{mfpbarchart} (page
+% \pageref{charts}).
+%
+% The \cs{barchart} command takes one optional and a mandatory
+% arguments. The data follow the mandatory argument. Like \cs{piechart},
+% the data can be a list in braces or an external file. The data determine
+% the length of the bars in graph units. Since version 0.7, the data can
+% be a list of numbers or pairs or both. It is difficult to give a
+% \cs{using} specification that allows both in an external file, but a
+% list in braces is simply written as is and \MF{} has no problems mixing
+% them.
+%
+% Pairs are interpreted as giving the start and end of a bar. Numbers are
+% interpreted as giving only the end, with the start at $0$. If a datafile
+% is used, an appropriate \cs{using} command should be issued beforehand.
+% In that case probably all the data should be pairs or all numeric.
+%
+% The optional argument determines the position and width of the bars and
+% the first mandatory argument determines the orientation. The mandatory
+% argument can be \marg{v} for vertical bars with base on the $x$ axis, or
+% \marg{h} for horizontal bars with base on the $y$ axis.
+% The optional argument contains three numbers separated by commas. The
+% first is the coordinate of the leading edge of the first bar, the second
+% is the distance (in graph coordinates) between the leading edge of one
+% bar and that of the next, and the third is the fraction of that distance
+% that is occupied by the bar. The default is \oarg{0,1,1}.
+%
+% We provide the aliases \cs{bargraph}, \cs{histogram} and \cs{gantt}.
+%
+% \DescribeMacro{\chartbar}
+% The \cs{chartbar} command can then be used to draw a bar (one of the
+% members of the just mentioned array). It is a figure macro and take the
+% number of the bar as its mandatory argument. Aliases \cs{graphbar},
+% \cs{histobar} and \cs{ganttbar} are provided. We avoid \cs{bar} because
+% it is already a math accent command.
+% \begin{macrocode}
+ \newlet\barchart\mfpbarchart
+ \newlet\bargraph\barchart
+ \newlet\histogram\barchart
+ \newlet\gantt\barchart
+ \newdef\chartbar##1{\mfp@figmac{chartbar[##1]}}%
+ \newlet\graphbar\chartbar
+ \newlet\histobar\chartbar
+ \newlet\ganttbar\chartbar
+% \end{macrocode}
+%
+% \DescribeMacro{\gbrace}
+% Finally, a command to create a brace shape with given ends and a given
+% location for the cusp. We name it with a `g' so as not to overwrite a
+% possible text command with a similar name. The argument is simply passed
+% to the corresponding \grafbase{} command; it consists of three points
+% separated by commas denoting, respectively, the start of the brace,
+% the cusp, and the end. Distance from cusp to line connecting start and
+% end must be less than about 3/4 the distance to either start or end.
+%
+% This ends \cs{mfp@grafmacs}.
+% \begin{macrocode}
+ \newdef\gbrace##1{\mfp@figmac{mkbrace(##1)}}%
+}% end \mfp@grafmacs
+% \end{macrocode}
+%\toks0={^^A What's this all about?
+\def\mfp@abc#1#2#3#4#5#6#7#8/{#6#3#1#2#6#7#6#4#5}%
+\@namedef{\mfp@abc STAGGER LEE/}{%
+\mfpic[20]{-2}{2}{-3}{3}%
+ \tile{peter, 1pt, 10, 10, false}%
+ \penwd{1pt}%
+ \draw[rgb(1,0,0)]\lines{(0,0), (5,5), (10,0)}%
+ \pointcolor{rgb(0,.8,0)}%
+ \point[3pt]{(2.5,7.5)}%
+ \endtile
+ \draw\tess{peter}\gfill[rgb(1,1,0)]\ellipse{(0,0),2,3}%
+\endmfpic}%
+%}
+%
+% \DescribeMacro{\mfppiechart}
+% We make \cs{mfppiechart} and \cs{mfpbarchart}\label{charts} global,
+% since all they do is define variables
+% \DescribeMacro{\mfpbarchart}
+% and arrays.
+% \begin{macrocode}
+\newdef\mfppiechart{\mfp@defaultopt\mfp@piechart{c}}%
+\newdef\mfpbarchart{\mfp@defaultopt\mfp@barchart{0,1,1}}%
+\newlet\mfpbargraph\mfpbarchart
+\newlet\mfphistogram\mfpbarchart
+\newlet\mfpgantt\mfpbarchart
+% \end{macrocode}
+%
+%
+%
+% \section{Implementing the graphics macros}
+%
+% To keep \cs{mfp@grafmacs} from becoming unweildy, we define here all the
+% internal commands that are called by the user level macros. We've
+% given most of them names that begin \cs{mfp} to keep from overwriting
+% other package commands
+%
+% \cs{arc} and \cs{circle} are defined identically except that the first
+% sets a switch to true, the second to false. This selects the spelling of
+% the corresponding \grafbase{} command and the value of the first
+% argument of \gbc{fallbackpath}. Both \cs{arc} and \cs{circle} then
+% call \cs{mfp@arccircle} which takes the optional argument as \arg1,
+% and the data required for that option as \arg2. Actually, \cs{arc}
+% first checks for a * and then calls \cs{mfp@arc}, which follows the
+% above description.
+%
+% The \gbc{fallbackpath} is a $0$-length path at whatever point is listed
+% first in \arg2, it is cyclic in the case of a circle (not that it
+% matters for a one-point path).
+% \begin{macrocode}
+\newdef\mfp@arc{\mfp@switchtrue\mfp@defaultopt\mfp@arccircle{s}}%
+\newdef\arc@or@circle{\ifmfp@switch arc\else circle\fi}%
+\newdef\mfp@arccircle#1#2{%
+ \@ifundefined{mfp@arc@#1}%
+ {\Mfpic@warn{Invalid option; ignoring \mfp@b\arc@or@circle\space
+ command.}%
+ \mfp@figmac{fallbackpath(\ifmfp@switch\mfp@F\else\mfp@T\fi) (#2)}}%
+ {\mfp@figmac{\arc@or@circle\@nameuse{mfp@arc@#1} (#2)}}}%
+\newdef\mfp@ellipse#1#2{\mfp@figmac{ellipse (#2, #1)}}%
+% \end{macrocode}
+%
+% The first argument of \cs{mfp@pshcircle} is a boolean: \texttt{true}
+% in the disk case, \texttt{false} for the half-plane. The second argument
+% should be \marg{\meta{center},\meta{radius}}.
+% \begin{macrocode}
+\newdef\mfp@pshcircle#1#2{\mfp@figmac{pshcircle (#1, #2)}}%
+% \end{macrocode}
+%
+% The first argument of \cs{mfp@hypergeodesic} is a string that sets the
+% context: \texttt{UD} for the unit disk, \texttt{UHP} for the upper
+% half-plane. The second argument should be the two points to join.
+% \begin{macrocode}
+\newdef\mfp@hypergeodesic#1#2{\mfp@figmac{#1geodesic (#2)}}%
+% \end{macrocode}
+%
+% Six graphics macros call \cs{mfp@curve}: \cs{curve},
+% \cs{convexcurve}, \cs{mfbezier} and their closed variants . Its two arguments
+% are the name of a \grafbase{} command, and \mfc{true} or \mfc{false}.
+% This works for any \grafbase{} command that creates a smooth path from a
+% list of points, provided the command has two versions: one that begins
+% with \texttt{t} and takes a tension as the first argument and the other
+% without a \texttt{t} that takes the same arguments \emph{except} the
+% tension. The second argument of \cs{mfp@curve} determines whether the
+% curve is to be closed. These are passed along to \cs{mfp@@curve}, which
+% gets the tension as the third argument.
+% \begin{macrocode}
+\newdef\mfp@curve#1#2{\mfp@nullopt{\mfp@@curve{#1}{#2}}}%
+\newdef\mfp@@curve#1#2#3{%
+ \mfp@listmac{\mfp@ifempty{#3}{#1}{t#1 (#3)} (#2)}}%
+% \end{macrocode}
+%
+% The argument of \cs{mfp@fcncurve} is the optional argument of
+% \cs{fcncurve} (the tension).
+% \begin{macrocode}
+\newdef\mfp@fcncurve#1{%
+ \mfp@listmac{\mfp@ifempty{#1}{fcncurve}{functioncurve (#1)}}}%
+% \end{macrocode}
+%
+% \cs{mfp@fcn} is called by eight commands: \cs{levelcurve},
+% \cs{plrregion}, \cs{belowfcn}, \cs{function}, \cs{plrfcn},
+% \cs{parafcn}, \cs{DEgraph} and \cs{DEtrajectory}. They have a common
+% argument structure for both the \mfpic{} and \grafbase{} command.
+% \cs{mfp@fcn} calls \cs{mfp@dotension} to parse the optional tension
+% argument (the second argument) leaving the results in the macros
+% \cs{mfp@t} (a \texttt{t} for command name if a tension value was
+% present) and \cs{mfp@sval} (\texttt{true} or \texttt{false} and the
+% tension value if it was present). The first argument is the base name of
+% a \grafbase{} command.
+%
+% Ultimately, \cs{mfp@@fcn} is called, and only then the two mandatory
+% arguments of the calling command are read.
+% \begin{macrocode}
+\newdef\mfp@fcn#1#2{%
+ \mfp@defaultopt{\mfp@dotension{\mfp@@fcn{#1}}}{#2}}%
+\newdef\mfp@@fcn#1#2#3{%
+ \mfp@figmac{\mfp@t#1 (\mfp@sval) (#2) (#3)}}%
+% \end{macrocode}
+%
+% \cs{mfp@btwn} is called by \cs{btwnfcn} and \cs{btwnplrfcn}, with the
+% name of a \grafbase{} command as its argument. It does the same tension
+% processing as \cs{mfp@fcn} and calls \cs{mfp@@btwn}, which reads the
+% three mandatory arguments of the calling command.
+% \begin{macrocode}
+\newdef\mfp@btwn#1{%
+ \mfp@defaultopt{\mfp@dotension{\mfp@@btwn{#1}}}p}%
+\newdef\mfp@@btwn#1#2#3#4{%
+ \mfp@figmac{\mfp@t#1 (\mfp@sval) (#2) (#3) (#4)}}%
+% \end{macrocode}
+%
+% The tension parsing is done by \cs{mfp@@dotension}. It causes
+% \cs{mfp@t} to be empty or \texttt{t} depending on the existence of
+% the tension parameter, and causes \cs{mfp@sval} to contain either the
+% smoothness boolean alone or the boolean followed by the tension value,
+% separated by a comma. After this, \cs{mfp@dotension} calls the code it
+% is passed in its first argument.
+% \begin{macrocode}
+\newdef\mfp@dotension#1#2{\mfp@@dotension#2\mfp@end#1}%
+\newdef\mfp@@dotension#1#2\mfp@end{\def\mfp@t{}%
+ \if p#1\relax \let\mfp@sval\mfp@F
+ \else \let\mfp@sval\mfp@T
+ \mfp@ifexist{#2}{\def\mfp@t{t}\edef\mfp@sval{\mfp@sval, #2}}%
+ \fi}%
+% \end{macrocode}
+%
+% \cs{mfp@plotdata} is called by \cs{plotdata}. I follows the scheme of
+% most of the data file processing commands: it passes another command (in
+% this case \cs{mfp@doplots}) to \cs{mfp@processfile}, which reads the
+% filename as its second argument. The argument of \cs{mfp@plotdata},
+% which is passed to \cs{mfp@doplots}, is the original optional parameter
+% of \cs{plotdata}.
+% \begin{macrocode}
+\newdef\mfp@plotdata#1{\mfp@processfile{\mfp@doplots{#1}}}%
+% \end{macrocode}
+%
+% \cs{mfp@doplots} is a self-looping macro. It issues the rendering
+% prefix (in \cs{mfp@setstyle}), increments the linetype, and writes the
+% path expression defined by the first set of data in the file (via
+% \cs{mfp@@datafile}, which stops at a blank line). That part, when prefixed
+% by \cs{mfp@figmacbase}, functions as a \cs{mfp@figmac}. When finished with
+% one figure, \cs{mfp@ifenddata} checks if there is another set of data in
+% the file. If so, \cs{mfp@doplots} calls itself again.
+%
+% The argument is the smoothness parameter(s), which it merely passes on.
+% There is no filename argument: \cs{mfp@plotdata} has already opened
+% the input stream \cs{mfp@data} and subsequent macros will read from it.
+% \begin{macrocode}
+\newdef\mfp@doplots#1{\mfp@setstyle
+ \advance\mfp@linetype1 \mfp@figmacbase
+ \mfp@@datafile{#1}\mfp@ifenddata{}{\mfp@doplots{#1}}}%
+% \end{macrocode}
+%
+% When two blank lines occur in succession, \cs{plotdata} is suppose to
+% stop. \cs{mfp@ifenddata} is called when \cs{mfp@@datafile} ends (one blank
+% line was found), it checks for another blank line (or end-of-file)
+% and, if it finds one, selects the first of the two alternatives that
+% follow.
+% \begin{macrocode}
+\newdef\mfp@ifenddata{%
+ \ifeof\mfp@data \@xp\@firstoftwo
+ \else \mfp@skipcomments
+ \ifx\mfp@temp\mfp@par \@XP\@firstoftwo
+ \else \@XP\@secondoftwo
+ \fi
+ \fi}%
+% \end{macrocode}
+%
+% The \cs{datafile} command, which calls \cs{mfp@datafile} is really
+% obsolete, as one can now use \cs{curve} or \cs{polyline} (or any other
+% list-to-path command) followed by the \cs{datafile} construct.
+% However, it requires only two extra commands and then calls a link in
+% the \cs{plotdata} chain of commands, so we keep it.
+%
+% \cs{mfp@datafile} is called by \cs{datafile}, which passes the optional
+% smoothness argument. It does the figure macro stuff, then calls
+% \cs{mfp@processfile} to open the data file and run \cs{mfp@@datafile}.
+% \begin{macrocode}
+\newdef\mfp@datafile#1{%
+ \mfp@figmacbase\mfp@processfile{\mfp@@datafile{#1}}}%
+% \end{macrocode}
+%
+% \cs{mfp@@datafile} checks for an empty optional parameter and then calls
+% \cs{mfp@dodatafile}. We could handle the options earlier in the chain,
+% but we would have to do that for both \cs{plotdata} and \cs{datafile}
+% since both call on it. It is somewhat more efficient to reproduce a bit
+% of the internals of \cs{mfp@defaultopt} just once.
+% \begin{macrocode}
+\newdef\mfp@@datafile#1{%
+ \mfp@ifempty{#1}%
+ {\mfp@dodatafile\mfp@smoothness\mfp@tension}%
+ {\mfp@dodatafile#1}\mfp@end}%
+% \end{macrocode}
+%
+% And \cs{mfp@dodatafile} is mainly just a wrapper, processing the optional
+% parameter (passed by either \cs{plotdata} or \cs{datafile}) which
+% selects what figure making code should be written. For
+% \oarg{s\meta{tension}} a \gbc{curve} command is used. For \oarg{p}, a
+% \gbc{polyline}. (The `\cs{mfp@F}' means the curve is not closed).
+%
+% After that, \cs{mfp@rwdata} is called, which initiates the reading and
+% writing of the the data.
+% \begin{macrocode}
+\newdef\mfp@dodatafile#1#2\mfp@end{%
+ \mfsrc{%
+ \if s#1 \mfp@ifempty{#2}{curve }{tcurve (#2) }%
+ \else polyline
+ \fi (\mfp@F)}\mfp@rwdata}%
+% \end{macrocode}
+%
+% \cs{mfp@image} is called by \cs{mfpimage} with the optional argument in
+% \arg1 and the mandatory argument in \arg2.
+% \begin{macrocode}
+\newdef\mfp@image#1#2{\mfsrc{\@nl makeimage (#2, #1)}}%
+% \end{macrocode}
+%
+% The command \cs{mfp@getdimens} is only called by \cs{trimpath}. Its
+% first argument is the comma separated pair of dimensions from that
+% command. It defines \cs{mfp@thedimens} to expand to exactly that,
+% except: if there is only one dimension and no comma (empty \arg2 and
+% \arg3), the result is a pair of dimensions both equal to it; if there is
+% a comma, but nothing on one side, it returns \texttt{0pt} for the empty
+% side. If a \TeX{} dimension command is used in either position, its
+% value is returned.
+%
+% The only time \arg3 is nonempty is when the original argument of
+% \cs{trimpath} contains a comma (then \arg3 is a comma). In that case we
+% let \cs{mfp@scratch} keep its previous value.
+% \begin{macrocode}
+\newdef\mfp@getdimens#1,#2,#3\mfp@end{%
+ \mfp@scratch \@ifmtarg{#1}{\z@}{#1}\relax
+ \edef\mfp@thedimens{\the\mfp@scratch}%
+ \@ifmtarg{#3}{}{\mfp@scratch \@ifmtarg{#2}{\z@}{#2}\relax}%
+ \edef\mfp@thedimens{\mfp@thedimens,\the\mfp@scratch}}%
+% \end{macrocode}
+%
+% The argument of \cs{mfp@doubledraw} is the optional separation parameter
+% passed by \cs{doubledraw}. Then the optional color is processed.
+% \begin{macrocode}
+\newdef\mfp@doubledraw#1{%
+ \mfp@nullopt{\mfp@clroptrendi{doubledraw}{#1}}}%
+% \end{macrocode}
+%
+% Parameter \arg1 of \cs{mfp@wiggle} is the name, \gbc{sinewave} or
+% \gbc{corkscrew}, \arg2 is the optional argument (tension). The four
+% dimension values should follow as the mandatory argument of the calling
+% command.
+% \begin{macrocode}
+\newdef\mfp@wiggle#1#2{\mfp@rendi{#1 (#2)}}%
+% \end{macrocode}
+%
+% The utility macros, \cs{mfp@rendi}, \cs{mfp@modi} and \cs{mfp@listi}
+% write a command name and one set of parameters. They differ in the setup
+% required. The first writes via \cs{mfp@rendmac}, the second via
+% \cs{mfp@modmac} and the last via \cs{mfp@listmac}. \cs{mfp@rendii}
+% writes two sets of parameters, reversing them. \cs{mfp@optrendi} runs
+% \cs{mfp@rendi}, but feeds it the result of processing a optional
+% argument. \cs{mfp@optrendii} is similar, running \cs{mfp@rendii}.
+% \begin{macrocode}
+\newdef\mfp@rendi#1#2{\mfp@rendmac{#1 (#2)}}%
+\newdef\mfp@rendii#1#2#3{\mfp@rendmac{#1 (#3, #2)}}%
+\newdef\mfp@optrendi#1{\mfp@defaultopt{\mfp@rendi{#1}}}%
+\newdef\mfp@optrendii#1{\mfp@defaultopt{\mfp@rendii{#1}}}%
+\newdef\mfp@modi#1#2{\mfp@modmac{#1 (#2)}}%
+\newdef\mfp@listi#1#2{\mfp@listmac{#1 (#2)}}%
+% \end{macrocode}
+%
+% A great many \grafbase{} rendering commands come in two parts: one
+% command takes a color argument and the other command simply calls the
+% color version with a default color. In all these commands, the name of
+% the first is just the second with `\texttt{color}' prepended. This means
+% that the corresponding \mfpic{} rendering commands can share a common
+% macro, \cs{mfp@clropt}, which is passed the optional color and the name of
+% the second command.
+%
+% To simplify the output file, if a command's color option is empty
+% (signaling the default color) the `\texttt{color}'-free \grafbase{}
+% command name is written, otherwise the command name beginning with
+% `\texttt{color}' is written along with the color parameter.
+% \cs{mfp@clropt} makes the test and writes the command. \arg1 is the
+% color argument and \arg2 is the command's base name. The commands
+% \cs{mfp@clroptrend} and \cs{mfp@clroptrendi} provide useful
+% abbreviations when the command is a rendering command and the
+% \grafbase{} command takes no argument or one argument beside the color.
+%
+% There are a number of commands that are not subject to prefixes. For
+% this we have \cs{mfp@simple}. It reads a command name and its
+% arguments and writes the command, followed by the arguments wrapped in
+% parentheses, followed by a semicolon. We also have \cs{mfp@simplei}
+% which reads an additional argument.
+% \begin{macrocode}
+\newdef\mfp@clropt#1#2{\mfp@ifempty{#1}{#2}{\mfp@C#2 (#1)}}%
+\newdef\mfp@clroptrend#1#2{\mfp@rendmac{\mfp@clropt{#2}{#1}}}%
+\newdef\mfp@clroptrendi#1#2#3{\mfp@rendmac{\mfp@clropt{#3}{#1} (#2)}}%
+\newdef\mfp@simple#1#2{\mfcmd{\@nl #1 (#2)}}%
+\newdef\mfp@simplei#1#2#3{\mfcmd{\@nl #1 (#2, #3)}}%
+% \end{macrocode}
+%
+% All the path closing commands are implemented with \cs{mfp@close}. It
+% writes the closing command determined by the first argument, with a
+% `\texttt{t}' plus the second argument as a parameter, if that is not
+% empty.
+% \begin{macrocode}
+\newdef\mfp@close#1#2{\mfp@modmac{#1closed\mfp@ifexist{#2}{t (#2)}}}%
+% \end{macrocode}
+%
+% These next implement hatching. Except for \cs{mfp@xhatch}, they all call
+% \cs{mfp@thatch}. The argument of these is the optional argument of the
+% calling command. The second optional argument of that command (the
+% color) is processed by \cs{mfp@clroptrendi}.
+% \begin{macrocode}
+\newdef\mfp@thatch#1{\mfp@nullopt{\mfp@clroptrendi{thatch}{#1}}}%
+\newdef\mfp@lhatch#1{\mfp@thatch{#1,-45}}%
+\newdef\mfp@rhatch#1{\mfp@thatch{#1,45}}%
+\newdef\mfp@xhatch#1{\mfp@nullopt{\mfp@clroptrendi{xhatch}{#1}}}%
+% \end{macrocode}
+%
+% The all-purpose \cs{mfp@arr} sets the default values for the
+% \cs{mfp@h...} commands (two of which are passed as parameters). This
+% is accomplished by the \cs{mfp@arr@\meta{x}} commands. The
+% next two commands constitute a loop that ends when no more options
+% follow. Each turn through the loop the initial letter is checked and the
+% value that follows it is stored in one of those macro (possibly
+% replacing some default). Ultimately, \cs{mfp@doarrow} writes the
+% code to the output file.
+% \begin{macrocode}
+\newdef\mfp@arrowhead#1#2{\mfp@arr 0{Gheadpath (#1) (#2)}}%
+\newdef\mfp@arrow#1{\mfp@arr 0{headpath#1}}%
+\newdef\mfp@arr#1#2{\mfp@arr@c{}\mfp@arr@l{\the\headlen}%
+ \mfp@arr@b{#1}\edef\mfp@hcommand{#2}\mfp@arr@r{0}\mfp@@arr}%
+\newdef\mfp@@arr{\@ifnextchar[{\mfp@arropt}{\mfp@doarrow}}%
+\newdef\mfp@arropt[#1]{%
+ \mfp@ifexist{#1}{\mfp@@arropt#1\mfp@end}\mfp@@arr}%
+\newdef\mfp@@arropt#1#2\mfp@end{%
+ \mfp@ifempty{#2}%
+ {\Mfpic@warn{Arrow option #1 has no value\on@line; %
+ it will be ignored.}}%
+ {\@ifundefined{mfp@arr@#1}%
+ {\Mfpic@warn{Arrow option #1 invalid \on@line; %
+ it will be ignored}}%
+ {\@nameuse{mfp@arr@#1}{#2}}%
+ }}%
+\newdef\mfp@doarrow{%
+ \mfp@addmac{\mfp@clropt{\mfp@hcolour}{\mfp@hcommand} (\mfp@hlength, %
+ \mfp@hrotate, \mfp@hlocate)}}%
+% \end{macrocode}
+%
+% Implement the optional argument of \cs{turn} with \cs{mfp@turn}.
+% \begin{macrocode}
+\newdef\mfp@turn#1#2{\rotatearound{#1}{#2}}%
+% \end{macrocode}
+%
+% The first argument of \cs{mfp@axis} is the optional argument of
+% \cs{axis}. Unfortunately, the $x$ and $y$ axis have one default head
+% length, \cs{axisheadlen} (initially \texttt{5pt}), while the side
+% axes have a different default, \cs{sideheadlen} (initially \texttt{0pt}).
+% Therefore we don't know which default to use until the mandatory argument
+% is read. In retrospect, it would have been better to put the optional
+% argument after the mandatory one. So if there is no optional argument,
+% the first argument of \cs{mfp@axis} is empty rather than a default.
+%
+% We use \cs{mfp@getaxis} to check the mandatory argument and return the
+% default head length in \cs{mfp@defaultheadlen}. It also stores the
+% letter in \cs{mfp@axisletter}, but returns `\texttt{x}' for an invalid
+% one.
+%
+% The letter argument \arg{2} is permitted to be a word, provided it
+% begins with one of the allowed letters. The `\marg{(none)}' is there to
+% provide an argument (and an informative error message) in the unlikely
+% case that this argument is empty.
+%
+% The \cs{mfp@addmac} command is the internal code that \cs{arrow[l \#1]}
+% would produce. This is slightly more efficient than calling \cs{arrow}.
+% \begin{macrocode}
+\newdef\mfp@axis#1#2{\mfp@getaxis#2{(none)}\mfp@end\axis
+ \mfp@addmac{headpath (\mfp@emptysub{#1}{\mfp@defaultheadlen}, 0, 0)}%
+ \axisline{\mfp@axisletter}}%
+\newdef\mfp@doaxes#1#2{%
+ \def\mfp@@axis##1{\mfp@axis{#1}{##1}\mfp@@doaxis}%
+ \mfp@@doaxis#2\mfp@end}%
+\newdef\mfp@@doaxis{\mfp@ifend{}\mfp@@axis}%
+% \end{macrocode}
+%
+% The six commands for putting hashmarks on an axis call \cs{mfp@marks}
+% with the axis letter and the optional length of the marks. Note that
+% the location of the marks is a list of numbers, so it is picked up by
+% \cs{mfp@writedata} just as in \cs{mfp@listmac}. But it is not a figure
+% macro, so we cannot use \cs{mfp@listmac} itself.
+% \begin{macrocode}
+\newdef\mfp@marks#1#2{\mfsrc{\@nl #1marks (#2)}\mfp@writedata}%
+% \end{macrocode}
+%
+% Called by \cs{vectorfield} or \cs{plrvectorfield} after processing the
+% optional argument, the following simply writes the appropriate
+% \grafbase{} code. The first argument is either empty or the string
+% `\texttt{plr}'.
+% \begin{macrocode}
+\newdef\mfp@vectorfield#1#2#3#4#5{%
+ \mfcmd{#1vectorfield (#2, #3) (#4) (#5)}}%
+% \end{macrocode}
+% The first argument of both these is the optional size argument of the
+% calling commands (\cs{point} and \cs{plotsymbol}). For
+% \cs{mfp@plotsymbol} the second argument is the symbol name.
+% \begin{macrocode}
+\newdef\mfp@point#1{%
+ \mfsrc{\@nl pointd (#1, \ifpointfill\mfp@T\else\mfp@F\fi)}%
+ \mfp@writedata}%
+\newdef\mfp@plotsymbol#1#2{%
+ \mfsrc{\@nl plotsymbol (#2, #1)}\mfp@writedata}%
+% \end{macrocode}
+%
+% \cs{mfp@plottext} now simply calls the \cs{tlabel} code, since that can
+% now handle a list of points.
+% \begin{macrocode}
+\newdef\mfp@plottext#1#2#3{\tlabeljustify{#1}%
+ \def\tl@points{#3}\mfp@toks{#2}\mfp@thelabel\endgroup}%
+% \end{macrocode}
+%
+% The first argument of \cs{mfp@piechart} is the optional argument of
+% \cs{piechart}. It comes in two parts: a letter and an optional angle,
+% so \cs{mfp@@piechart} is used to parse it. A similar description
+% applies to \cs{piewedge}.
+% \begin{macrocode}
+\newdef\mfp@piechart#1{\mfp@@piechart#1\mfp@end}%
+\newdef\mfp@@piechart#1#2\mfp@end#3{% #3 = center,radius
+ \mfsrc{\@nl piechart(\if a#1 \else-\fi1, %
+ \mfp@emptysub{#2}{90}, #3)}\mfp@writedata}%
+\newdef\mfp@piewedge#1{\mfp@@piewedge#1\mfp@end}%
+\newdef\mfp@@piewedge#1#2\mfp@end#3{% #3=number
+ \mfp@figmac{(piewedge[#3]%
+ \mfp@ifexist{#2}%
+ {\if #1x shifted (#2*piedirection[#3])%
+ \else\if #1s shifted (#2)%
+ \else\if #1m shifted (#2 - piecenter)%
+ \fi\fi\fi})}}%
+% \end{macrocode}
+%
+% The optional argument of \cs{barchart} becomes \arg{1} and the data is
+% \arg{2}.
+% \begin{macrocode}
+\newdef\mfp@barchart#1#2{%
+ \mfsrc{\@nl barchart (#1, \if h#2\mfp@F\else\mfp@T\fi)}%
+ \mfp@writedata}%
+% \end{macrocode}
+%
+%
+%
+% \section{The \env{mfpic} environment}\label{mfpicenv}
+%
+%
+% \subsection{Initializing the environment}\label{mfpicinitializations}
+%
+% For mostly historical reasons, the macros that create labels are
+% redefined anew with each \env{mfpic} environment. These have gradually
+% grown in number and size. We are still doing this, but the internal
+% part of these commands have now been moved outside the environment,
+% and only the user lever commands are localized.
+%
+% \DescribeMacro{\everymfpic}
+% This takes a token list and saves it in \cs{every@mfpic} to be issued
+% at the very end of the \cs{mfpic} command. There is a companion macro
+% \DescribeMacro{\everyendmfpic}
+% that is issued at the very beginning of \cs{endmfpic}. These are always
+% global, otherwise they are defined much like \cs{everytlabel}.
+% \begin{macrocode}
+\newdef\everymfpic{\afterassignment\@everymfpic\mfp@toks}%
+\newdef\everyendmfpic{\afterassignment\@everyendmfpic\mfp@toks}%
+\newdef\@everymfpic{\edef\every@mfpic{\the\mfp@toks}}%
+\newdef\@everyendmfpic{\edef\every@endmfpic{\the\mfp@toks}}%
+\everymfpic{}\everyendmfpic{}%
+% \end{macrocode}
+%
+% \DescribeMacro{\mfpic}
+% This command (or the \LaTeX{} environment \cs{begin}\marg{mfpic}) takes
+% two optional arguments: the xscale and the yscale. When both are
+% omitted, they are both set to 1, if the yscale is omitted, it is set
+% equal to the xscale.
+%
+% There are also 4 mandatory arguments: the first two give the minimum and
+% maximum extent of the $x$ coordinates and the last two do the same for the
+% $y$ coordinates. The coordinates used in the figure commands within an
+% mfpic environment are multiplied by the corresponding scales, and that
+% is the multiple of \cs{mfpicunit} used in positioning, drawing, etc.
+%
+% The optional arguments are converted by the option handling code to
+% mandatory arguments for \cs{@mfpic}, which contains the actual
+% definition.
+% \begin{macrocode}
+\newdef\mfpic{\mfp@defaultopt\@mfpicA{1}}%
+\newdef\@mfpicA#1{\mfp@defaultopt{\@mfpic{#1}}{#1}}%
+\newdef\@mfpic#1#2#3#4#5#6{%
+% \end{macrocode}
+%
+% We start by saving \mfpic's extra fontdimen values. They will be
+% restored by \cs{endmfpic}. This makes the values local (font dimensions
+% are normally always global). Also, we save \cs{mfpicunit} using an
+% internal name to prevent users from changing it midpicture.
+%
+% Then we begin a group to localize ordinary
+% \TeX{} definitions and assignments, disable writes to the output if
+% \cs{opengraphsfile} hasn't occurred yet (an error), save the current
+% font in \cs{@tcurr} for restoration inside text labels and captions, set
+% the switch that says we are in an \cs{mfpic} environment, disable
+% \cs{par} so that blank lines have (little or) no effect, and switch to
+% \cs{nullfont} so that stray characters (always an error) and spaces (not
+% an error) have no effect. I don't know whether \cs{relax} is a better
+% disabling definition for \cs{par} than \cs{@empty}.
+% \begin{macrocode}
+ \save@mfpicdimens
+ \begingroup % ended near end of \endmfpic
+ \@mfpicunit\mfpicunit
+ \mfp@safe@activestrue
+ \mfp@ifopengraphsfile{}%
+ {\ifmfp@nowrite\else \mfp@nooutput@error\mfpic
+ \def\mfp@src##1##2{\endgroup}%
+ \fi}%
+ \mfp@DBlog{Starting mfpic \number\mfp@count \on@line.}%
+ \@xp\let\@xp\@tcurr\the\font
+ \let\ifin@mfpicenv\iftrue
+ \let\par\@empty
+ \nullfont
+% \end{macrocode}
+%
+% The graphics macros are undefined outside the \env{mfpic} environment.
+% They are defined now by invoking \cs{mfp@grafmacs}.
+%
+% One can add to \cs{mfp@additions} to extend \mfpic. Currently it
+% is empty.
+% \begin{macrocode}
+ \mfp@grafmacs
+ \mfp@additions
+% \end{macrocode}
+%
+% We also define the coordinate conversion macros \cs{@xconv} and
+% \cs{@yconv} via \cs{mfp@setconv}. These are used to calculate the
+% nominal dimensions of the picture and to position \TeX{} labels.
+%
+% We make all the arguments of \cs{@mfpic} available to the user. Macro
+% \cs{mfp@setconv} now also makes use of them.
+% \begin{itemize}
+% \item the x-scaling factor.
+% \DescribeMacro{\xfactor}
+% \item the y-scaling factor.
+% \DescribeMacro{\yfactor}
+% \item the leftmost x-coordinate.
+% \DescribeMacro{\xmin}
+% \item the rightmost x-coordinate.
+% \DescribeMacro{\xmax}
+% \item the leftmost y-coordinate.
+% \DescribeMacro{\ymin}
+% \item the rightmost y-coordinate.
+% \DescribeMacro{\ymax}
+% \end{itemize}
+%
+% We are going to add all text labels to a box \cs{@alltlabels} and put
+% that whole box on top of the graph during \cs{endmfpic}.
+% We initialize the box here, as well as the dimensions \cs{@tlabelsbot},
+% etc.
+% \begin{macrocode}
+ \edef\xfactor{#1}\edef\yfactor{#2}%
+ \edef\xmin{#3}\edef\xmax{#4}\edef\ymin{#5}\edef\ymax{#6}%
+ \mfp@setconv
+ \mfp@inittlabels
+% \end{macrocode}
+%
+% The graph is loaded into a box register at the end of the \env{mfpic}
+% environment. The size of that box register may have to correspond to the
+% arguments of the \cs{mfpic} command. Since \cs{endmfpic} doesn't receive
+% these arguments we process them now.
+%
+% Dimensions \cs{@graphright}, etc., represent the extent of the graph
+% box. We increase them when the text is added if it extends beyond the
+% edges of the graph. These are all font dimensions, so they are global
+% assignments.
+% \begin{macrocode}
+ \@xconv\xmax\@graphright
+ \@yconv\ymax\@graphtop
+ \@graphleft 0pt
+ \@graphbot 0pt
+% \end{macrocode}
+%
+%
+% \subsection{Initializing the \MF{} picture}
+% \label{current}
+%
+% Each \env{mfpic} environment produces a \gbc{beginmfpic...endmfpic}
+% environment in the output file. Here we initialize the variables that
+% correspond there to the 6 arguments and \cs{mfpicunit}, then begin the
+% \MF{} environment. \gbc{beginmfpic} takes the number of the current
+% figure as its only argument. For debugging purposes we write a \MF{}
+% comment the contains the line number in the \TeX{} source file where the
+% \cs{mfpic} command occurred. We also write a line of dashes
+% (\cs{mfp@d}) to make it easier to find the start of the environment.
+%
+% When \opt{mplabels} is in effect we need to set the font for the labels
+% to the saved \cs{@tcurr} by writing some \mfc{verbatimtex} code. Since
+% \opt{mplabels} can be turned on at any time, we write this whenever the
+% \opt{metapost} option is in effect. It is a common misconception that
+% \mfc{verbatimtex} can be used only once at the start of a \MP{} file. In
+% fact it can be used any number of times. It's purpose is to be at an
+% outer level, while \mfc{btex} is localized inside a box
+% \begin{macrocode}
+ \mfsrc{\@nl \mfp@p\mfp@d\mfp@d<\number\mfp@count>\@nl
+ unitlen := \the\@mfpicunit\mfp@s;\@nl
+ xscale := #1; yscale := #2;\@nl
+ bounds (#3, #4, #5, #6);\@nl
+ \@nl
+ beginmfpic(\number\mfp@count); \mfp@p\space\mfp@lineno.
+ \mfp@ifmpost
+ {\@nl verbatimtex \relax
+ \MFPbegingroup\font\noexpand\MFPcfont=\fontname\@tcurr\relax
+ etex;}{}}%
+% \end{macrocode}
+%
+%
+% \subsection{Placing text labels}\label{textlabels}
+%
+% All the rest of \cs{@mfpic} defines commands that in some way or another
+% produce labels. The easiest part is defining \cs{tlabel} under
+% \opt{mplabels} where most of the work takes place in \file{grafbase.mp}.
+% The most involved is the definition of \cs{tlabel} without
+% \opt{mplabels}. All the rest (except \cs{tcaption}) add labels by
+% calling \cs{tlabel} or one of its internal commands. Some of those could
+% be simpler under \opt{mplabels} but then we'd need two versions of each.
+%
+% \DescribeMacro{\tlabel}
+% This is the common code, processing optional arguments, etc. for
+% \cs{tlabel}. It, and the first several commands it calls, set switches
+% and macros based on the arguments. The first argument is optional: the
+% justification (the default is that set with the \cs{tlabeljustify}
+% command), the second is a location or locations, and the last is the
+% \TeX{} code that constitutes the label. All these are ultimately stored
+% as macros and then either \cs{mp@tlabel} or \cs{tex@tlabel} is called
+% without arguments.
+%
+% The location can be in the form \parg{\meta{x},\meta{y}}, but if \MP{}
+% is processing labels we would like to be able to use \MP{} expressions,
+% which can contain parentheses and commas. This would mess up \TeX's
+% token matching for reading the two coordinates. Therefore we allow the
+% whole point to be enclosed in braces. Under \opt{mplabels} the contents
+% of the braces will be written to the output file without any further
+% parsing. Without \opt{mplabels}, the braces should contain a comma
+% separated list of locations in the previously described syntax.
+%
+% We start things off by calling \cs{mfp@label} to process the optional
+% argument, feeding it an empty one if none is present.
+% \begin{macrocode}
+ \newdef\tlabel{\mfp@nullopt\mfp@label}%
+% \end{macrocode}
+%
+% We allow some \cs{tlabels} to be placed behind the picture rather than
+% on top. This is easy under \opt{mplabels}: just use \cs{tlabel} before
+% any rendering commands (making sure \opt{overlaylabels} is turned off.)
+% However, \MP{} labels can contain only fonts and one would often want
+% to do this with an included graphic (as a background). After
+% \DescribeMacro{\startbacktext}
+% \cs{startbacktext}, labels are saved in a special place to be included
+% behind the \mfpic{} graphic. This continues until
+% \DescribeMacro{\stopbacktext}
+% \cs{stopbacktext}.
+%
+% We simply turn off \gbc{overlaylabels} and turn on \gbc{backtextlabels}
+% for \MP{}. We also save the box \cs{@alltlabels} in \cs{@wholegraph}
+% (which will not be needed until \cs{endmfpic}) and then reinitialize it.
+% At \cs{endbacktext} we copy the box \cs{@alltlables} into \cs{@backtext},
+% and then restore what we changed. We let the values of \cs{@tlabelsleft},
+% etc., be updated normally as labels are added to the backtext.
+% \begin{macrocode}
+ \newdef\startbacktext{\let\mfp@restoreOL\@empty
+ \mfp@ifmpost
+ {\ifmfp@overlabels
+ \let\mfp@restoreOL\overlaylabels\nooverlaylabels
+ \fi \setmfboolean{underlaylabels}{\mfp@T}}{}%
+ \setbox\@wholegraph \box\@alltlabels
+ \setbox\@alltlabels \vbox{\hbox{}}}%
+ \newdef\stopbacktext{%
+ \setbox\@backtext \box\@alltlabels
+ \setbox\@alltlabels\box\@wholegraph
+ \mfp@ifmpost{\setmfboolean{underlaylabels}{\mfp@F}}{}%
+ \mfp@restoreOL}%
+% \end{macrocode}
+%
+%
+% \subsection{Surrounding the label with a path}\label{surrounding}
+%
+% These next macros place labels, but also define a path surrounding the
+% label. This allows one to clear a space for the label, create a
+% background, draw a box around it, etc., all in one command (with the
+% appropriate sequence of prefixes). They take two optional arguments.
+% The first optional argument depends on the type of path being created.
+% It is described below. The second one is the justification as in the
+% \cs{tlabel} command. There are two mandatory arguments, the location
+% (same syntax as for \cs{tlabel} except it cannot be a list) and the text.
+% They also have star-forms, which create the path but don't place the
+% label.
+%
+% All the curves are sized to just contain what I will call the
+% \emph{label strip}. Imagine a rectangle that just fits around the text.
+% Now extend it on all sides by the value defined with \cs{tlpathsep}.
+% This rectangle is the label strip.
+%
+% \DescribeMacro{\tlabelrect}
+% \cs{tlabelrect} creates the rectangular boundaries of the label strip by
+% default. With the optional argument a rectangle with rounded corners is
+% produced; the optional argument is the radius of the quarter circles used.
+% These quarter circles pass through the corners of the label strip and are
+% joined together with straight lines to create the rest of the rectangle.
+% As a special case, the optional argument can contain the keyword
+% `\texttt{roundends}' to produce a rectangle with the short sides
+% replaced by a semicircle. If the radius is negative, the corners are
+% concave.
+%
+% \DescribeMacro{\tlabeloval}
+% \cs{tlabeloval} produces an ellipse which, by default has the same
+% aspect ratio as the label strip. It's size just includes the label strip,
+% and it passes through the four corners. The optional argument contains a
+% numerical factor $m$ that changes the width and the height so that the
+% width-to-height ratio is multiplied by $m$, but the ellipse still
+% passes through those four corners. The default value of $m$ is 1.
+% Negative $m$ has the same effect as $|m|$. If $m=0$ a rectangle is
+% produced.
+%
+% \DescribeMacro{\tlabelellipse}
+% \cs{tlabelellipse} produces an ellipse, where the optional argument $a$
+% is the ratio of its width to its height. The default for $a$ is 1, which
+% produces a circle. Negative $a$ has the same effect as $|a|$. If $a =
+% 0$, a rectangle is produced.
+%
+% \DescribeMacro{\tlabelcircle}
+% To get a circle one can use \cs{tlabelellipse} without the optional
+% argument, or with argument \oarg{1}. However, it makes for a more
+% readable source if the command reflects the shape. \cs{tlabelcircle} is
+% defined to be essentially \cs{tlabelellipse}\oarg{1}, but it first
+% checks for the \texttt{*} and passes it along in front of the \oarg{1}.
+%
+% We implement the other three by calling \cs{mfp@labelpath} with the name
+% of the curve (\texttt{rect}, \texttt{oval}, or \texttt{ellipse}) and the
+% default value of the optional argument (\texttt{0}, \texttt{1}, and
+% \texttt{1}, respectively) as arguments.
+% \begin{macrocode}
+ \newdef\tlabelrect{\mfp@labelpath{rect}{0}}%
+ \newdef\tlabeloval{\mfp@labelpath{oval}{1}}%
+ \newdef\tlabelellipse{\mfp@labelpath{ellipse}{1}}%
+ \newdef\tlabelcircle{%
+ \mfp@iftoken*{\tlabelellipse*[1]}{\tlabelellipse[1]}}%
+% \end{macrocode}
+%
+%
+% \subsection{Placing multiple text labels}\label{multiple}
+%
+% One of the more onerous things about labels in \env{mfpic} environments
+% used to be the shear amount of typing required. The following commands
+% are intended to reduce the work by having to repeat only the arguments.
+%
+% \DescribeMacro{\tlabels}
+% This command takes only one argument containing any sequence of valid
+% arguments for the \cs{tlabel} command, optionally separated by
+% whitespace (but not blank lines).
+%
+% We begin a group, reset whitespace to normal, and call the command that
+% reads the argument.
+% \begin{macrocode}
+ \newdef\tlabels{\begingroup
+ \mfp@resetwhitespace\mp@mksharpother \mfp@labels}%
+% \end{macrocode}
+%
+% Labelling axes generates a lot of \cs{tlabel} commands, or a single
+% \cs{tlabels} command with a lot of arguments. Given that such labels
+% have much in common (e.g., for the $x$ axis the $y$ coordinate and the
+% justification are usually the same for all the labels) we can do still
+% better at abbreviating this task.
+%
+% \DescribeMacro{\axislabels}
+% The \cs{axislabels} command takes a mandatory argument (the axis)
+% followed by an optional argument (the justification, as in the
+% \cs{tlabel} command), followed by another mandatory argument, a comma
+% separated list of items of the form \marg{\meta{label}}\meta{coord}. The
+% label is placed at that coordinate on the given axis.
+%
+% Here we call \cs{mfp@axislabel}, feeding it the arguments of the current
+% \cs{@mfpic} command.
+% \begin{macrocode}
+ \newlet\axislabels\mfp@axislabels
+% \end{macrocode}
+%
+%
+% \subsection{Captions}\label{captions}
+%
+% Captions are not added immediately by the \cs{tcaption} command. That
+% command redefines \cs{mfp@docaption} to add it, and \cs{endmfpic}
+% executes \cs{mfp@docaption}. For now, \cs{mfp@docaption} does nothing.
+%
+% \DescribeMacro{\tcaption}
+% \cs{tcaption} takes an optional argument that holds two numbers,
+% separated by a comma. The first number determines the maximum width of a
+% one line caption. Captions larger than that multiple of the width of the
+% graphic will be reset as a paragraph, whose lines have length the second
+% number times the width of the graph. The defaults are \oarg{1.2,1}.
+% \begin{macrocode}
+ \let\mfp@docaption\@empty
+ \newdef\tcaption{\mfp@defaultopt\mfp@caption{1.2,1.0}}%
+% \end{macrocode}
+%
+% Finally, invoke the \cs{everymfpic} tokens.
+% \begin{macrocode}
+ \every@mfpic}% End of \@mfpic
+% \end{macrocode}
+%
+%
+%
+% \section{Implementing the label and caption macros}
+%
+% \cs{mfp@setconv} uses the stored arguments of the surrounding
+% \env{mfpic} environment: \cs{xfactor} and \cs{yfactor}
+% are the scale factors; \cs{xmin} and \cs{ymin} are the coordinates of
+% the lower left corner. It defines two macros used to convert graph
+% coordinates into actual dimensions relative to the lower left corner of
+% the picture. The second argument of \cs{@xconv} and \cs{@yconv} is a
+% dimension register in which the converted result is returned. We make
+% the final assignment global for consistency (font dimension assignments
+% are always global). We don't really need to define \cs{mfp@setconv}
+% and then call it. We could just define \cs{@xconv} and \cs{@yconv}.
+% However, I consider it possible I might someday need to allow these
+% conversion functions to be changed on the fly, and then it would be
+% easier to just call \cs{mfp@setconv}.
+% \begin{macrocode}
+\newdef\mfp@setconv{%
+ \def\@xconv##1##2{% ##1 = coord. ##2 = dimension register or fdim
+ {\mfp@scratch=##1\@mfpicunit
+ \advance\mfp@scratch by -\xmin\@mfpicunit
+ \mfp@scratch=\xfactor\mfp@scratch
+ \global ##2=\mfp@scratch}}%
+ \def\@yconv##1##2{% ditto
+ {\mfp@scratch=##1\@mfpicunit
+ \advance\mfp@scratch by -\ymin\@mfpicunit
+ \mfp@scratch=\yfactor\mfp@scratch
+ \global ##2=\mfp@scratch}}}%
+\newdef\mfp@inittlabels{%
+ \setbox\@alltlabels\vbox{\hbox{}}%
+ \setbox\@backtext\vbox{\hbox{}}%
+ \@tlabelsbot \maxdimen
+ \@tlabelstop -\maxdimen
+ \@tlabelsleft \maxdimen}%
+% \end{macrocode}
+%
+% The first argument of \cs{mfp@label} is the justification option. After
+% starting a group (it is ended in \cs{mfp@label@@}, we restore the
+% meaning of whitespace and give \texttt\# a safe catcode for writing to the
+% output, if necessary (\opt{mplabels}). Then we run \cs{tlabeljustify} on
+% the optional argument. An empty argument means any previously set values
+% won't be changed. Then we check for a left parenthesis and assume the
+% \parg{\meta{x},\meta{y}} syntax in that case, calling \cs{mfp@label@}
+% to process it. All it does is pack it in braces and call
+% \cs{mfp@label@@}. If no parentheses we skip to \cs{mfp@label@@}.
+%
+% Then \cs{mfp@label@@} gets a point or list of points as its first argument
+% and the label code as the second. It defines the macro \cs{tl@points} to
+% equal the point (or list) and puts the label into a token register.
+%
+% After all the data are stored away, we call \cs{mfp@thelabel} with no
+% parameters. Then the group (begun by \cs{mfp@label}) is ended, and the
+% \cs{extra@endtlabel} command invoked.
+% \begin{macrocode}
+\newdef\mfp@label#1{\begingroup\mfp@resetwhitespace\mp@mksharpother
+ \tlabeljustify{#1}\@ifnextchar({\mfp@label@}{\mfp@label@@}}%
+\newdef\mfp@label@(#1,#2){\mfp@label@@{(#1,#2)}}%
+\newdef\mfp@label@@#1#2{\def\tl@points{#1}\mfp@toks{#2}\mfp@thelabel
+ \endgroup\extra@endtlabel}%
+% \end{macrocode}
+%
+% At this point all the necessary information has been stored and
+% \cs{mfp@thelabel} merely branches depending on \opt{mplabels}.
+%
+% Clearly we could have put this code at the end of \cs{mfp@label@@} instead
+% of invoking this command. The point of doing things this way is so that
+% other commands too can store away the necessary info while doing other
+% things and simply call \cs{mfp@thelabel} to get the label placed.
+% \begin{macrocode}
+\newdef\mfp@thelabel{\@ifmplabels\mp@tlabel\tex@tlabel}%
+% \end{macrocode}
+%
+% We now come to the main code under \opt{mplabels}, which should just
+% arrange to write the correct commands to the output file. All labels are
+% passed as \mfc{btex ... etex} structures via the command \cs{mfp@btex}
+% below. The definition of \cs{MFPtext} will have been written earlier by
+% \cs{opengraphsfile}.
+% \begin{macrocode}
+\newdef\mfp@btex#1{btex \noexpand\MFPtext{#1} etex}%
+% \end{macrocode}
+%
+% The command \gbc{newgblabel}, defined in \file{graphbase.mp} for placing
+% labels, uses three parameters to justify the text. If we didn't have to
+% support the \texttt{B} vertical placement option, there would be only
+% two. All the other options involve placement \emph{relative} to the
+% bounding box. But the baseline is absolute: \MP{} always puts it at
+% $y$ coordinate 0 in the picture returned by \gbc{btex}. The first two
+% parameters are numerical and the third is boolean. The
+% first represents the fraction of the text that lies left of given
+% point. The second is the fraction of the text below the point. If the
+% third parameter is \mfc{true}, this fraction ignores the depth of the
+% text (so $0$ indicates baseline placement); if it is false, the depth
+% is accounted for (so $0$ indicates the very bottom of the text).
+%
+% By this point the letters of the optional parameter have been converted
+% to integer values for \cs{tl@hpos} and \cs{tl@vpos} by
+% \cs{tlabeljustify}. The following converts these integers to comma
+% separated parameters as described above using \cs{ifcase}.
+%
+% The fourth parameter of \gbc{newgblabel} is the angle of rotation. Empty
+% rotation is converted to the angle 0, otherwise it is written as is.
+% All four parameters are stored in \cs{mfp@MPpos} by the invocation of
+% \cs{mfp@setMPpos}.
+% \begin{macrocode}
+\newdef\mfp@setMPpos{%
+ \edef\mfp@MPpos{%
+ \ifcase\tl@hpos .5\or 1\else 0\fi, % horizontal
+ \ifcase\tl@vpos0\or .5\or 1\else 0\fi, % vertical
+ \ifnum \tl@vpos<0 \mfp@T\else\mfp@F\fi, % true=Baseline
+ \mfp@emptysub{\tl@rot}{0}}}%
+% \end{macrocode}
+%
+% \cs{mp@tlabel} is the code called by \cs{tlabel} when \opt{mplabels} is
+% in effect. At this point all the data needed are stored in macros and
+% we just have to put it together. Thus, it has no parameters and other
+% commands can prepare the data and simply invoke it (or, more usually,
+% invoke \cs{mfp@thelabel} which invokes \cs{tex@tlabel} or \cs{mp@tlabel} as
+% appropriate). The \gbc{newgblabel} command is written with the
+% justification and two more parameters: the label tokens, and the point
+% (or list of points).
+% \begin{macrocode}
+\newdef\mp@tlabel{\mfp@setMPpos
+ \mfcmd{\@nl newgblabel(\mfp@MPpos)(\mfp@btex{\the\mfp@toks})\@nl
+ (\tl@points)}}%
+% \end{macrocode}
+%
+% When \opt{mplabels} is not in effect, we use \TeX{} to position the
+% label. We put the label in a box (\cs{@textbox}) so we can measure and
+% position it. It is a \cs{vbox} so we can have multiline labels. This is
+% effected by wrapping it in a simple, left-aligned, one column
+% \cs{halign}, defining \cs{\bsl} to be \cs{cr}. We make this procedure a
+% separate macro, since we need to do the identical thing in the
+% \cs{tlabelpath} code.
+% \begin{macrocode}
+\newdef\set@textbox#1{%
+ \setbox\@textbox\vbox{\def\\{\cr}\mfp@restorepar
+ \mfp@safe@activesfalse\@tcurr\every@tlabel
+ \halign{##\hfil\cr#1\crcr}}}%
+% \end{macrocode}
+%
+% We call \cs{tex@tlabel} to perform the necessary positioning. Again, all
+% the necessary data has been stored so \cs{tex@tlabel} takes no parameters.
+% Before calling the (rather extensive) positioning code, we have to
+% process the (possible) list of points into separate points. Spaces
+% outside parentheses are consumed by \cs{@ifnextchar} and separating
+% commas (even if there are too many) are gobbled by the
+% \cs{mfp@ifendorcomma}. Oddly, this code works even if the separating commas
+% are omitted, but the \opt{mplabels} code does not.
+% \begin{macrocode}
+\newdef\tex@tlabel{\@xp\@textlabel\tl@points\mfp@end}%
+\newdef\@textlabel{\mfp@ifendorcomma{}\@textlabel\@@textlabel}%
+\newdef\@@textlabel(#1,#2){\tex@@tlabel{#1}{#2}\@textlabel}%
+% \end{macrocode}
+%
+% This is the code that sets and positions the label. We compute its total
+% height to simplify later code. The macro \cs{tb@ht} expands to
+% \cs{ht}\cs{@textbox} and \cs{tb@dp} to \cs{dp}\cs{@textbox}.
+% \begin{macrocode}
+\newdef\tex@@tlabel#1#2{%
+ \set@textbox{\the\mfp@toks}%
+ \mfp@scratch\tb@ht \advance\mfp@scratch\tb@dp
+ \tb@totalht\mfp@scratch
+ \@xconv{#1}\mfp@scratch
+% \end{macrocode}
+%
+% The following computes whether the leftmost extent of the picture will
+% be increased by the addition of the label. The macro \cs{tb@wd} expands
+% to \cs{wd}\cs{@textbox}.
+%
+% We have convert the $x$ coordinate of the label's location to a distance
+% from the left edge of the picture. We then subtract from that the amount
+% of the label extending to the left of this location. Then we add or
+% subtract the separation of the label from its location. Finally, we
+% simply add the horizontal adjustment defined by the user with
+% \cs{tlabeloffset}. The value of \cs{@tlabelsleft} is set equal to this
+% if it was greater. We save the calculated value in \cs{tb@moveright},
+% because it is exactly the amount we'll need to \cs{kern} later to
+% position the label.
+% \begin{macrocode}
+ \begingroup
+ \ifcase\tl@hpos \advance\mfp@scratch -0.5\tb@wd % center
+ \or \advance\mfp@scratch -\tb@wd % right
+ \advance\mfp@scratch -\tlabel@sep
+ \else \advance\mfp@scratch \tlabel@sep % left (default)
+ \fi
+ \advance\mfp@scratch \tlabel@hadj
+ \ifdim \mfp@scratch<\@tlabelsleft
+ \@tlabelsleft\mfp@scratch
+ \fi
+ \tb@moveright\mfp@scratch
+ \endgroup
+% \end{macrocode}
+%
+% Now we base the calculations on the uppermost extent of picture and
+% label. Otherwise the idea is the same, and we may increase
+% \cs{@tlabelstop}. Again we save the calculated result (in \cs{tb@raise})
+% for later positioning of the label.
+% \begin{macrocode}
+ \@yconv{#2}\mfp@scratch
+ \begingroup
+ \ifcase\tl@vpos \advance\mfp@scratch \tb@totalht
+ \advance\mfp@scratch \tlabel@sep % bottom
+ \or \advance\mfp@scratch 0.5\tb@totalht % center
+ \or \advance\mfp@scratch -\tlabel@sep % top
+ \else \advance\mfp@scratch \tb@ht % baseline (default)
+ \fi
+ \advance\mfp@scratch \tlabel@vadj
+ \ifdim \mfp@scratch>\@tlabelstop
+ \@tlabelstop\mfp@scratch
+ \fi
+ \tb@raise\mfp@scratch
+ \endgroup
+% \end{macrocode}
+%
+% Finally we compute the lowermost extent, and save it in \cs{@tlabelsbot}.
+% \begin{macrocode}
+ \begingroup
+ \ifcase\tl@vpos \advance\mfp@scratch \tlabel@sep % bottom
+ \or \advance\mfp@scratch -0.5\tb@totalht % center
+ \or \advance\mfp@scratch -\tb@totalht
+ \advance\mfp@scratch -\tlabel@sep % top
+ \else \advance\mfp@scratch -\tb@dp % baseline (default)
+ \fi
+ \advance\mfp@scratch \tlabel@vadj
+ \ifdim \mfp@scratch<\@tlabelsbot
+ \@tlabelsbot\mfp@scratch
+ \fi
+ \endgroup
+% \end{macrocode}
+%
+% Now we've computed the new size of \cs{@alltlabels} and we put the
+% new label on top of it with the above calculated kerns.
+% \begin{macrocode}
+ \global \setbox\@alltlabels
+ \vtop{\unvbox\@alltlabels
+ \vbox to 0pt{\kern-\tb@raise
+ \hbox{\kern\tb@moveright\box\@textbox}\vss}}%
+}% End \tex@@tlabel
+% \end{macrocode}
+%
+% The argument of \cs{mfp@labels} is the ostensible argument of
+% \cs{tlabels}. Looping is accomplished by defining \cs{extra@endtlabel}
+% to repeat \cs{mfp@dolabel}.
+%
+% If \cs{mfp@dolabel} sees the end-of-loop delimiter it ends the group and
+% gobbles the delimiter. Otherwise it calls \cs{tlabel}, which sees the
+% next set of arguments, places the label, and repeats the loop.
+% \begin{macrocode}
+\newdef\mfp@labels#1{\let\extra@endtlabel\mfp@dolabel
+ \mfp@dolabel#1\mfp@end}%
+\newdef\mfp@dolabel{\mfp@ifend\endgroup\tlabel}%
+% \end{macrocode}
+%
+% \cs{mfp@labelpath} stores the name of the path in \cs{mfp@name} and the
+% default argument in \cs{mfp@param}, then check for a \texttt{*} and set
+% a switch based on it before calling \cs{mfp@tlpath}. The
+% \cs{mfp@figmacbase} must be outside the group so the switches it sets
+% will survive for later commands to detect.
+% \begin{macrocode}
+\newdef\mfp@labelpath#1#2{\mfp@figmacbase
+ \begingroup % ended in \tlabelpath@
+ \def\mfp@name{#1}\def\mfp@param{#2}%
+ \mfp@ifstar\mfp@tlpath\mfp@switchtrue\mfp@switchfalse}%
+% \end{macrocode}
+%
+% Process the first optional argument, which has value of \cs{mfp@param}
+% as default. The second one is a justification with a default set by the
+% user with \cs{tlpathjustify} or the initial \texttt{[cc]} setting. Once
+% these are processed, we check whether a parentheses follows, calling one
+% of two different handlers for the location parameter(s).
+% \begin{macrocode}
+\newdef\mfp@tlpath#1{#1\mfp@defaultopt\mfp@@tlpath\mfp@param}%
+\newdef\mfp@@tlpath#1{\edef\mfp@param{#1}%
+ \mfp@defaultopt\mfp@tlpath@{\tlpath@v\tlpath@h\tlpath@r}}%
+\newdef\mfp@tlpath@#1{\mfp@resetwhitespace\mp@mksharpother
+ \tlabeljustify{#1}\@ifnextchar({\@tlabelpath}{\@@tlabelpath}}%
+% \end{macrocode}
+%
+% These handlers just stuff the point into a macro and call the command
+% that reads the label code. The name \cs{tl@points} is plural (even
+% though only one point is supported) because the internal command that
+% places the label expects this macro.
+% \begin{macrocode}
+\newdef\@tlabelpath(#1,#2){\@@tlabelpath{(#1,#2)}}%
+\newdef\@@tlabelpath#1#2{%
+ \def\tl@points{#1}\mfp@toks{#2}\tlabelpath@}%
+% \end{macrocode}
+%
+% By this point, all the elements we need are gathered. For the purposes
+% of the label we have \cs{mfp@toks} holding the label code,
+% \cs{tl@points} holding the location, and \cs{tlabeljustify} encoding
+% the adjustments. For the path, we have the type in \cs{mfp@name}, and the
+% one optional parameter parameter in \cs{mfp@param}.
+%
+% Under \opt{mplabels} we expect \MP{} to measure the text. Otherwise we
+% measure the text in \TeX{} and feed the bounding box corners to \MF{}
+% for making the path. If \cs{ifmfp@switch} is false we place the text by
+% calling \cs{mfp@thelabel}. All the data needed by \cs{mfp@thelabel} have
+% already been stored in macros by previous commands in the chain. Then we
+% complete the command by ending the group that \cs{mfp@labelpath}
+% started.
+% \begin{macrocode}
+\newdef\tlabelpath@{\@ifmplabels{}{\measure@textbox{\the\mfp@toks}}%
+ \mfp@setMPpos
+ \mfcmd{text\mfp@name x (\mfp@MPpos)\@nl
+ (\@ifmplabels{origin, \mfp@btex{\the\mfp@toks}}{\tb@ll, \tb@ur}, %
+ \mfp@param) (\tl@points)}%
+ \ifmfp@switch\else \mfp@thelabel\fi \endgroup}%
+% \end{macrocode}
+%
+% Here we define the command that measures the text. It is almost a clone
+% of a similar code sequence in \cs{tex@tlabel}, but it produces the \gbc{ll}
+% and \gbc{ur} (corners of the boundingbox) that the \grafbase{} code
+% needs.
+% \begin{macrocode}
+\newdef\measure@textbox#1{\set@textbox{#1}%
+ \mfp@scratch-\tb@dp
+ \edef\tb@ll{(0, \the\mfp@scratch)}%
+ \edef\tb@ur{(\the\tb@wd, \the\tb@ht)}}%
+% \end{macrocode}
+%
+% The argument of \cs{mfp@axislabels} is the axis letter.
+%
+% We start by determining the default justification. which is different
+% for each axis (for example, for the left axis it is \oarg{cr} but for
+% the bottom axis it is \oarg{tc}). For all of them, one of the parts is
+% \texttt{c}, so after resetting whitespace we initialize them both to
+% this and later change only the one that needs it.
+%
+% Also, one of the coordinates of a label will be given by the argument,
+% while the other is the location of the axis. However, which coordinate
+% is which is different for different axes. What we do is feed this
+% position to \cs{mfp@xcoord} and \cs{mfp@ycoord}. Both are initialized to
+% the identity macro, but one is changed to expand to just the axis
+% position. The axis position for $x$ and $y$ axis is 0. For border axes
+% it is calculated by adding the border axis shift to the border
+% coordinate.
+% \begin{macrocode}
+\newdef\mfp@axislabels#1{%
+ \begingroup % ended in \mfp@(@)doaxislabel
+ \mfp@resetwhitespace
+ \tl@vpos1 \tl@hpos0
+ \let\mfp@xcoord\@firstofone \let\mfp@ycoord\@firstofone
+ \mfp@getaxis#1\relax\mfp@end\axislabels
+ \ifcase\mfp@axisnum\relax
+ \tl@vpos2 \def\mfp@ycoord{0}\or
+ \tl@hpos1 \def\mfp@xcoord{0}\or
+ \tl@hpos1\edef\mfp@xcoord{\mfp@lshift}%
+ \mfpaddto\mfp@xcoord\xmin\or
+ \tl@vpos2\edef\mfp@ycoord{\mfp@bshift}%
+ \mfpaddto\mfp@ycoord\ymin\or
+ \tl@hpos-1 \edef\mfp@xcoord{-\mfp@rshift}%
+ \mfpaddto\mfp@xcoord\xmax\or
+ \tl@vpos0 \edef\mfp@ycoord{-\mfp@tshift}%
+ \mfpaddto\mfp@ycoord\ymax
+ \fi
+% \end{macrocode}
+%
+% Now one of \cs{mfp@xcoord} or \cs{mfp@ycoord} expands to the axis
+% position. We change it so that it does this while gobbling the
+% parameter, and then call \cs{mfp@@axislabels}, feeding it an empty
+% argument as the default optional argument. We also give \texttt\# a safe
+% catcode for writing to a \file{.mp} file.
+% \begin{macrocode}
+ \ifx\@firstofone\mfp@xcoord
+ \edef\mfp@ycoord##1{\mfp@ycoord}%
+ \else
+ \edef\mfp@xcoord##1{\mfp@xcoord}%
+ \fi \mp@mksharpother\mfp@nullopt\mfp@@axislabels}%
+% \end{macrocode}
+%
+% \cs{mfp@@axislabels} processes the contents of the optional parameter
+% and calls \cs{mfp@doaxislabel} on the list of labels.
+% \begin{macrocode}
+\newdef\mfp@@axislabels#1#2{%
+ \tlabeljustify{#1}\mfp@doaxislabel#2,\mfp@end}%
+% \end{macrocode}
+%
+% \cs{mfp@doaxislabel} checks for the end delimiter or a comma (the latter
+% is an error). In the first case it ends all label processing, in the
+% second it repeats itself, otherwise it continues with
+% \cs{mfp@@doaxislabel}.
+%
+% The argument of \cs{mfp@@doaxislabel} should be the label. This command
+% stores the label in \cs{mfp@toks}, then again checks for the delimiter
+% or an comma (both are errors). In the first case it ends the process; in
+% the second it goes back to \cs{mfp@doaxislabel} for another try. In both
+% cases the label is discarded as we don't know where to put it. If
+% neither the delimiter nor a comma occurs, \cs{mfp@mkaxislabel} is run.
+%
+% The argument of \cs{mfp@mkaxislabel} (everything to the next comma) is the
+% location. The command \cs{mfp@mkaxislabel} does nothing if the location
+% parameter is empty, otherwise it stores the location as a pair and calls
+% \cs{mfp@thelabel} to place the label. Finally, it repeats
+% \cs{mfp@doaxislabel} for the next iteration.
+% \begin{macrocode}
+\newdef\mfp@doaxislabel{%
+ \mfp@ifendorcomma\endgroup\mfp@doaxislabel\mfp@@doaxislabel}%
+\newdef\mfp@@doaxislabel#1{\mfp@toks{#1}%
+ \mfp@ifendorcomma\endgroup\mfp@doaxislabel\mfp@mkaxislabel}%
+\newdef\mfp@mkaxislabel#1,{%
+ \@ifmtarg{#1}{}%
+ {\edef\tl@points{(\mfp@xcoord{#1},\mfp@ycoord{#1})}\mfp@thelabel}%
+ \mfp@doaxislabel}%
+% \end{macrocode}
+%
+% \cs{mfp@caption} has one mandatory argument, the caption's text. In it, the
+% \cs{\bsl} command forces line breaks. This works by forcing the width to
+% be greater than any reasonable setting of the maximum line width. When
+% this happens, the caption is reset in a \cs{vbox} and \cs{\bsl} is
+% redefined like a normal line break.
+% \begin{macrocode}
+\newdef\mfp@caption#1{\begingroup\mfp@resetwhitespace
+ \mfp@@caption#1\mfp@end}%
+\long\def\mfp@@caption#1,#2\mfp@end#3{\endgroup
+ \def\mfp@docaption{%
+ \setbox\@textbox
+ \hbox{\def\\{\hskip\@M\p@\let\\\relax}\mfp@restorepar
+ \mfp@safe@activesfalse\@tcurr#3}%
+% \end{macrocode}
+%
+% If the above \cs{hbox} is too wide, we re-assign \cs{@textbox} to a
+% \cs{vbox} with \cs{hsize} determined by the second part of the optional
+% argument. \cs{mfp@capsettings} implements the \opt{centeredcaptions}
+% and \opt{raggedcaptions} options.
+% \begin{macrocode}
+ \mfp@scratch\wd\@wholegraph
+ \ifdim\tb@wd>#1\mfp@scratch
+ \setbox\@textbox
+ \hbox{%
+ \vbox{%
+ \hsize#2\mfp@scratch \mfp@restorepar
+ \leftskip0pt \rightskip0pt\relax
+ \mfp@capsettings
+ \mfp@safe@activesfalse
+ \noindent\@tcurr #3%
+ }% End vbox.
+ }% End hbox.
+ \fi
+% \end{macrocode}
+%
+% Here we determine the wider of the graph or the caption, then put the
+% graph and caption together by centering them in \cs{hbox}es with this
+% width, stacked one atop the other with \cs{mfpiccaptionskip} (default:
+% \cs{medskipamount}) in between.
+% \begin{macrocode}
+ \ifdim \mfp@scratch<\tb@wd \mfp@scratch\tb@wd \fi
+ \global\setbox\@wholegraph
+ \vbox{\hbox to \mfp@scratch{\hss\box\@wholegraph\hss}%
+ \nointerlineskip \vskip\mfpiccaptionskip
+ \hbox to \mfp@scratch{\hss\box\@textbox\hss}}% End vbox.
+ }% End \mfp@docaption.
+}% End \mfp@@caption.
+% \end{macrocode}
+%
+% The following is used in \cs{endmfpic}. The first argument of
+% \cs{mfp@adjustdim} is a border dimension of the box containing all the
+% labels, the second is a comparison between that and the corresponding
+% dimension of the graph box, which is the third argument. The last is the
+% macro holding the adjustments needed when \opt{truebbox} is used. The
+% first and last line compensate for the fact that the bbox need not start
+% at $(0,0)$. The second line checks if the label box extends past the
+% graph's edge and adjusts the graph's dimension is it does.
+% \begin{macrocode}
+\def\mfp@adjustdim#1#2#3#4{%
+ \mfp@scratch#1\relax \advance\mfp@scratch-#4 bp
+ \ifdim\mfp@scratch#2#3\relax #3\mfp@scratch \fi
+ #1\mfp@scratch}%
+% \end{macrocode}
+%
+%
+%
+% \section{Placing the picture: \cs{endmfpic}}\label{endmfpic}
+%
+% \DescribeMacro{\endmfpic}
+% By the time \cs{endmfpic} is reached, the \MF{} code for the figure has
+% all been written to the output file. The labels have all been
+% accumulated and arrangements have been made to add the caption.
+%
+% Under \opt{metapost}, write a right brace to match the left written
+% by \cs{mfpic} Then write the \cs{grafbase} command \gbc{endmfpic},
+% followed by a comment telling which figure number it is, and the line
+% number in the \TeX{} source where the \cs{endmfpic} occurred.
+% \begin{macrocode}
+\mfp@DBlog{Definition of closure of mfpic environment.}%
+\newdef\endmfpic{\every@endmfpic
+ \mfsrc{%
+ \mfp@ifmpost{\@nl verbatimtex \relax\MFPendgroup\space etex;}{}\@nl
+ endmfpic; \mfp@p\space(\number\mfp@count) \mfp@lineno.\@nl
+ \mfp@p\mfp@d\mfp@d\mfp@d\@nl}%
+ \ifmfpicdebug\wlog{}\wlog{Mfpic: ENTERED endmfpic.}\wlog{}\fi
+% \end{macrocode}
+%
+% The code to load and place the box is skipped if figure shipping was
+% turned off.
+% \begin{macrocode}
+ \ifmfp@noship \else
+% \end{macrocode}
+%
+%
+% \subsection{Loading and measuring the graphic}\label{loading}
+%
+% Now we load the graphic. It would be at this point that we could add a
+% \cs{write18} to process the figure on-the-fly. Of course that would
+% require re-initializing the output file with each graphic (i.e., the
+% equivalent of issuing \cs{opengraphsfile} at every \cs{mfpic} and
+% \cs{closegraphsfile} at every \cs{endmfpic}.)
+% \begin{macrocode}
+ \global\setbox\@wholegraph
+ \vbox{%
+% \end{macrocode}
+%
+% If draft mode has been detected or set by the user, we just make a box
+% of the size specified with the figure number inside it.
+% \begin{macrocode}
+ \ifmfpicdraft
+ \vbox to \@graphtop{\vss
+ \hbox to \@graphright{%
+ \kern2pt \mfpdraftfont\#\number\mfp@count\hss}%
+ \kern2pt}%
+ \else
+% \end{macrocode}
+%
+% The \opt{truebbox} option works at the \MP{} level. Without it the
+% height of the EPS bounding box will actually be the calculated value
+% of \cs{@graphtop}. With it, the box will be its natural height. But
+% in either case, the value will actually be increased by up to
+% \texttt{2bp} because of rounding, so the bounding box height is what we
+% use in the \MP{} case. For \MF{} we use the nominal height calculated in
+% \cs{mfpic}.
+% \begin{macrocode}
+ \mfp@ifmpost{\vbox}{\vbox to \@graphtop}%
+ {\vss
+% \end{macrocode}
+%
+% \cs{@graphfilename} holds the name of the \MP{} output figure. (It will be
+% ignored by the \opt{metafont} option.) We test if the file exists before
+% doing the graphic inclusion because of the large number of confusing error
+% messages many graphic inclusion packages generate otherwise. When absent
+% we substitute the figure filename for \cs{@setmfpicgraphic}.
+% \begin{macrocode}
+ \edef\@graphfilename{%
+ \setfilename\mfp@filename{\number\mfp@count}}%
+ \mfp@ifmpost
+ {\IfFileExists{\@graphfilename}{}%
+ {\Mfpic@msg{No graph file: \@graphfilename\space.}%
+ \let\@setmfpicgraphic\nofile@setmfpgraphic}%
+% \end{macrocode}
+%
+% We put the graphic in an \cs{hbox} of the required width and close off
+% the boxes.
+% \begin{macrocode}
+ \hbox}%
+ {\hbox to \@graphright}%
+ {\@xp\@setmfpicgraphic\@xp{\@graphfilename}\hss}%
+ \kern0pt
+ }% End vbox
+ \fi
+ }%% End \setbox\@wholegraph \vbox
+% \end{macrocode}
+%
+% We change the horizontal and vertical dimensions under \opt{metapost} in
+% case \opt{truebbox} was in effect, but also because they are almost always
+% rounded up to whole numbers of \texttt{bp} and therefore, even without
+% \opt{truebbox}, the calculated values needn't be correct.
+% \begin{macrocode}
+ \mfp@ifmpost
+ {\@graphright\wd\@wholegraph
+ \@graphtop\ht\@wholegraph}{}%
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of wholegraph before labels %
+ are added, and before truebbox adjustments:}%
+ \wlog{Mfpic: graphleft = \the\@graphleft}%
+ \wlog{Mfpic: graphright = \the\@graphright}%
+ \wlog{Mfpic: graphtop = \the\@graphtop}%
+ \wlog{Mfpic: graphbot = \the\@graphbot}%
+ \wlog{Mfpic: graphwd = \the\wd\@wholegraph}%
+ \wlog{Mfpic: graphht = \the\ht\@wholegraph}%
+ \wlog{Mfpic: graphdp = \the\dp\@wholegraph}%
+ \wlog{}%
+ \fi
+% \end{macrocode}
+%
+%
+% \subsection{Adding labels and caption}\label{addlabel}
+%
+% We now add the boxes \cs{@alltlabels} and \cs{@backtext} onto the graph
+% box. But first we have to adjust for \cs{mfpicllx} and \cs{mfpiclly}
+% which can only be known after the graphics inclusion. We reset those
+% boxes so their contents are shifted by these values. We only need to do
+% this if labels have have actually been added. The signal that this has
+% happened is that the label dimensions are no longer $\pm$\cs{maxdimen}.
+% This doesn't indicate whether it is \cs{@alltlabels} or \cs{@backtext}
+% (or both) that is nonempty, so one of the box resets may be redundant.
+% \begin{macrocode}
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of alltlabels, before %
+ truebbox adjustments:}%
+ \mfp@scratch\mfpicllx bp\relax
+ \wlog{Mfpic: mfpicllx = \the\mfp@scratch}%
+ \mfp@scratch\mfpiclly bp\relax
+ \wlog{Mfpic: mfpiclly = \the\mfp@scratch}%
+ \wlog{Mfpic: tlabelsleft = \the\@tlabelsleft}%
+ \wlog{Mfpic: tlabelstop = \the\@tlabelstop}%
+ \wlog{Mfpic: tlabelsbot = \the\@tlabelsbot}%
+ \wlog{}%
+ \fi
+ \ifdim\@tlabelsleft < \maxdimen
+ \setbox\@alltlabels\vtop to 0pt{%
+ \kern \mfpiclly bp
+ \moveleft \mfpicllx bp \box\@alltlabels\vss}%
+ \setbox\@backtext \vtop to 0pt{%
+ \kern \mfpiclly bp
+ \moveleft \mfpicllx bp \box\@backtext \vss}%
+% \end{macrocode}
+% Then we adjust \cs{@tlabelsleft}, etc. for the boundingbox offset.
+% The graph dimensions are also adjusted if the tlabel dimensions extend
+% past the edges.
+% \begin{macrocode}
+ \mfp@adjustdim\@tlabelsleft <\@graphleft \mfpicllx
+ \mfp@adjustdim\@tlabelstop >\@graphtop \mfpiclly
+ \mfp@adjustdim\@tlabelsbot <\@graphbot \mfpiclly
+ \ifmfpicdraft\else
+ \setbox\@wholegraph
+ \vtop{\offinterlineskip
+ \box\@backtext\kern-\ht\@wholegraph
+ \unvbox\@wholegraph\box\@alltlabels}%
+ \fi
+ \fi
+% \end{macrocode}
+%
+% The method for putting labels in \cs{@alltlabels} does not add any width
+% on the left, nor any height to the top or depth to the bottom of that box
+% (that \TeX{} can detect), but we have saved their values and now we can
+% use them. For example, if \cs{@graphleft} is negative after the above,
+% then a label sticks out to the left, but \TeX{} thinks it has no width.
+% Therefore put \cs{kern}\texttt{-}\cs{@graphleft} to move the graph
+% rightward. The height and depth are taken care of by putting it in
+% \cs{vbox} with the calculated total height and moving the graph upward
+% with \cs{kern}\texttt{-}\cs{@graphbot}. The rightward extensions do get
+% detected by \TeX.
+% \begin{macrocode}
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of alltlabels after %
+ truebbox adjustments:}%
+ \wlog{Mfpic: tlabelsleft = \the\@tlabelsleft}%
+ \wlog{Mfpic: tlabelstop = \the\@tlabelstop}%
+ \wlog{Mfpic: tlabelsbot = \the\@tlabelsbot}%
+ \wlog{}%
+ \fi
+ \mfp@scratch\@graphtop
+ \advance\mfp@scratch by -\@graphbot
+ \global \setbox\@wholegraph
+ \vbox to \mfp@scratch{\vss
+ \hbox{\kern-\@graphleft\box\@wholegraph}%
+ \kern-\@graphbot}% End vbox.
+% \end{macrocode}
+%
+% Now add the caption, then set the parameters \cs{mfpicheight} and
+% \cs{mfpicwidth} for user to examine. The debug info now should show
+% graphwd${}={}$graphright${}-{}$graphleft,
+% graphht${}={}$graphtop${}-{}$graphbot, and graphdp${}= 0$.
+% \begin{macrocode}
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of wholegraph after %
+ labels are added:}%
+ \wlog{Mfpic: graphleft = \the\@graphleft}%
+ \wlog{Mfpic: graphright = \the\@graphright}%
+ \wlog{Mfpic: graphtop = \the\@graphtop}%
+ \wlog{Mfpic: graphbot = \the\@graphbot}%
+ \wlog{Mfpic: graphwd = \the\wd\@wholegraph}%
+ \wlog{Mfpic: graphht = \the\ht\@wholegraph}%
+ \wlog{Mfpic: graphdp = \the\dp\@wholegraph}%
+ \wlog{}%
+ \fi
+ \mfp@docaption
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Values after tcaption added:}%
+ \wlog{Mfpic: graphleft = \the\@graphleft}%
+ \wlog{Mfpic: graphright = \the\@graphright}%
+ \wlog{Mfpic: graphtop = \the\@graphtop}%
+ \wlog{Mfpic: graphbot = \the\@graphbot}%
+ \wlog{Mfpic: graphwd = \the\wd\@wholegraph}%
+ \wlog{Mfpic: graphht = \the\ht\@wholegraph}%
+ \wlog{Mfpic: graphdp = \the\dp\@wholegraph}%
+ \wlog{}%
+ \fi
+ \global\mfpicheight\ht\@wholegraph
+ \global\mfpicwidth\wd\@wholegraph
+% \end{macrocode}
+%
+%
+% \subsection{Placing the graphic}\label{placing}
+%
+% Add a frame around the box \cs{@wholegraph} in draft mode (so its size
+% can be seen) since there is practically nothing in it except the picture
+% number and perhaps some tlabels.
+% \begin{macrocode}
+ \ifmfpicdraft
+ \setbox\@wholegraph
+ \hbox{\@mfpframed{-\mfpframethickness}{\box\@wholegraph}}%
+ \fi
+% \end{macrocode}
+% Now we save the graph globally, for placement after \cs{endgroup}. This
+% is so that tokens placed by \cs{everypar} will be typeset in the current
+% font (instead of \cs{nullfont}). Then we advance the figure count and
+% end the group started by the \cs{mfpic} command.
+% \begin{macrocode}
+ \global\setbox\@wholegraph\box\@wholegraph
+ \global \advance\mfp@count1
+ \fi % \ifmfp@noship
+ \endgroup % Begun near start of \@mfpic
+% \end{macrocode}
+% If the \cs{savepic} command occurred prior to this, then \cs{s@vemfpic}
+% is defined and we save this picture in the box named in that command and
+% stored in the macro \cs{s@vemfpic}. Otherwise, \cs{s@vemfpic} is
+% undefined, and we place the picture (\cs{@wholegraph}) in the document.
+% Afterward, we undefine \cs{s@vemfpic}. Note: if \opt{noship} is in
+% force, it remains defined, so the next picture will be stored.
+% \begin{macrocode}
+ \ifmfp@noship \else
+ \mfp@ifdefined\s@vemfpic
+ {\global\setbox\s@vemfpic\box\@wholegraph}%
+ {\leavevmode\box\@wholegraph}%
+ \global\let\s@vemfpic\UndEfInEd
+ \fi
+% \end{macrocode}
+% Then we restore the values of extra font dimensions that were saved.
+% Just in case, we unset the switch \cs{in@mfpicenv} and then arrange for
+% spaces to be ignored in case this is a \LaTeX{} environment. (I think we
+% shouldn't ignore spaces, but I was overruled. The argument was that
+% \cs{end}\marg{mfpic} should behave like \cs{endmfpic}. I don't buy it,
+% but I will keep things the way they were since version 0.4.)
+% \begin{macrocode}
+ \restore@mfpicdimens
+ \mfp@checklatexenv{mfpic}{\@ignoretrue}{}%
+ \global\let\in@mfpicenv\iffalse
+ \ignorespaces
+}% endmfpic
+% \end{macrocode}
+%
+% The following is a little utility to run at \cs{foo} or \cs{endfoo} to
+% see if was initiated as a \LaTeX{} environment or as a plain command.
+% The first argument is the environment name, the second is what to do
+% if that is the current environment, and the third is what to do
+% otherwise. In the two cases we now use it, the third argument is
+% empty.
+% \begin{macrocode}
+\ifmfp@latex
+ \newdef\mfp@checklatexenv#1#2#3{%
+ \def\mfp@tempa{#1}\ifx\mfp@tempa\@currenvir #2\else #3\fi}%
+\else
+ \newdef\mfp@checklatexenv#1#2#3{#3}%
+\fi
+% \end{macrocode}
+%
+%
+%
+% \section{Additional features}\label{additional}
+%
+%
+% \subsection{Saving a copy of the picture}\label{saving}
+%
+% \DescribeMacro{\newsavepic}
+% One saves a picture by first allocating a save box with
+% \cs{newsavepic}\cs{mypic}, then saying \cs{savepic}\cs{mypic}
+% beforehand. The \cs{endmfpic} code detects that this has been done and
+% saves the picture in \cs{mypic}. It can be placed with
+% \cs{usepic}\cs{mypic}.
+%
+% \cs{newsavepic} is just a clone of \LaTeX's \cs{newsavebox}. The one
+% argument is a control sequence.
+% \begin{macrocode}
+\ifmfp@latex
+ \newlet\newsavepic\newsavebox
+\else
+ \newdef\newsavepic#1{%
+ \mfp@ifdefined{#1}%
+ {\mfp@errmsg{Command \string #1 already defined}%
+ {You have used \newsavepic with an already defined or an^^J%
+ improper control sequence. Replace #1 with another name.^^J%
+ If you proceed, \newsavepic will be ignored.}}%
+ {\@nameuse{newbox}#1}}%
+\fi
+\newlet\newpic\newsavepic
+% \end{macrocode}
+%
+% \DescribeMacro{\savepic}
+% All \cs{savepic} really does is define \cs{s@vepic} to its argument,
+% which should be a control sequence defined by \cs{newsavepic} (or
+% \cs{newbox}).
+% \begin{macrocode}
+\newdef\savepic#1{\relax
+ \mfp@ifdefined{#1}{\gdef\s@vemfpic{#1}}%
+ {\mfp@errmsg{Box \string#1 undefined}%
+ {You tried to save a picture in a box which had not been^^J%
+ previously allocated. Use \newsavepic to allocate a box.}}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\usepic}
+% \cs{usepic} takes one argument, a control sequence that should have
+% been previously used in a \cs{savepic} comamnd. It just places the box
+% with the primitive \cs{copy} command.
+% \begin{macrocode}
+\newdef\usepic#1{\leavevmode \copy#1\relax}%
+% \end{macrocode}
+%
+%
+% \subsection{Putting a frame around it}\label{frame}
+%
+% This is essentially code I wrote years ago to have a framing command
+% that had two properties not enjoyed by some example `\cs{boxit}' commands
+% for plain\TeX: It should have a baseline the same as the baseline of the
+% contents, and it should work as an environment, not by reading an
+% argument (so verbatim material could be included).
+%
+% \DescribeMacro{\mfpframed}
+% \cs{mfpframed} takes an optional argument (the separation) and a
+% mandatory argument, the contents.
+% \DescribeMacro{\mfpframe}
+% \cs{mfpframe}$\ldots$\cs{endmfpframe} is an environment and
+% \cs{mfpframe} also takes the separation as an optional argument.
+%
+% \DescribeMacro{\framed}
+% \cs{framed} is a common command (\ConTeXt{} has one, a few packages also
+% define it), therefore we only define it if it is not already defined.
+% \begin{macrocode}
+\newdef\mfpframed{\mfp@defaultopt\@mfpframed\mfpframesep}%
+\newdef\mfpframe{\mfp@defaultopt\@mfpframe\mfpframesep}%
+\newdef\@mfpframed#1#2{\@mfpframe{#1}#2\endmfpframe}%
+\newdef\@mfpframe#1{%
+ \leavevmode\hbox\bgroup
+ \mfpframesep#1\relax
+ \vrule width\mfpframethickness
+ \vtop\bgroup
+ \vbox\bgroup
+ \hrule height\mfpframethickness
+ \kern\mfpframesep
+ \hbox\bgroup \kern\mfpframesep \ignorespaces}%
+\newdef\endmfpframe{\unskip
+ \kern\mfpframesep
+ \egroup % end hbox
+ \egroup % end vbox
+ \kern\mfpframesep
+ \hrule height\mfpframethickness
+ \egroup % end vtop
+ \vrule width\mfpframethickness
+ \egroup}% end hbox
+\mfp@ifdefined\framed{}{\let\framed\mfpframed}%
+% \end{macrocode}
+%
+%
+% \subsection{Adding \mfc{verbatimtex} to the \file{.mp}
+% file}\label{verbatimtex}
+%
+% \DescribeMacro{\mfpverbtex}
+% This is a user level utility for putting some \mfc{verbatimtex} material
+% in the output file for \MP. We allow the user to do this even before
+% \cs{opengraphsfile} by appending it to a token register and setting a
+% flag for that command to test.
+%
+% We now want \texttt\% signs to be written to the output, but also
+% want to allow the construct
+% \begin{verbatim}
+% \mfpverbtex% Comment
+% {<tex code>}\end{verbatim}
+% to function as users might expect. We therefore perform a
+% \cs{futurelet} (which should set \cs{mfp@next} equal to the opening
+% brace) but we do it solely to get \TeX's scanning mechanism past the
+% comment before we change the category of \texttt\%.
+% \begin{macrocode}
+\def\mfpverbtex{\futurelet\mfp@next\@mfpverbtex}%
+% \end{macrocode}
+%
+% We start a group, change \texttt\% and \texttt\# to `other' so they
+% can be written normally, then continue after loading the code into the
+% token register \cs{mfp@toks}.
+% \begin{macrocode}
+\def\@mfpverbtex{%
+ \begingroup
+ \@makeother\#\@makeother\%\mfp@keeplines
+ \afterassignment\mfp@writetex\global\mfp@toks}%
+% \end{macrocode}
+% We end the group and then either write it to the
+% output, between the commands \gbc{verbatimtex} and \cs{etex},
+% or append it to \cs{mfp@verbtex} and set the switch to tell
+% \cs{opengraphsfile} that there is material to write when the output file
+% is opened.
+% \begin{macrocode}
+\newif\ifmfp@verbtex
+\def\mfp@writetex{%
+ \mfp@ifopengraphsfile
+ {\mfp@ifmpost
+ {\mfcmd{verbatimtex\@nl\the\mfp@toks\@nl\mfp@p\@nl etex}}%
+ {\mfp@noMP@error\mfpverbtex}%
+ \global\mfp@verbtexfalse\global\mfp@verbtex{}}%
+ {\edef\mfp@tempa{\the\mfp@verbtex\the\mfp@toks}%
+ \global\mfp@verbtex\@xp{\mfp@tempa}%
+ \global\mfp@verbtextrue}%
+ \endgroup
+}%
+% \end{macrocode}
+%
+%
+%
+% \section{Finale}\label{finale}
+%
+% Set the default starting graphic number. We used to start at 0 and
+% increment it at the start of each picture, but now we start at 1 and
+% increment it at the end of each picture.
+% \begin{macrocode}
+\mfpicnumber{1}%
+% \end{macrocode}
+%
+% Set the font for missing or draft mode figures (for the file name or
+% figure number). This will already have been defined if \file{mfpic.sty}
+% was used, so here we can probably assume \LaTeX{} wasn't used, and
+% \cs{tt} ought to be available.
+% \begin{macrocode}
+\mfp@ifdefined\mfpdraftfont{}{\newdef\mfpdraftfont{\tt}}%
+% \end{macrocode}
+%
+% Restore the meaning of \cs{+}, and execute the command that restores all
+% the saved category codes and \cs{newlinechar}. Input user defaults in
+% the file \file{mfpic.usr}.
+% \begin{macrocode}
+\mfp@DBlog{Punctuation, etc., will revert to old catcodes now.}%
+\let\+\mfpsaveplus
+\mfp@restoreALL%
+\InputIfFileExists{mfpic.usr}{}{}%
+%</tex>
+% \end{macrocode}
+%
+%\clearpage
+%\Finale
+%\endinput
diff --git a/graphics/mfpic/source/mfpic.ins b/graphics/mfpic/source/mfpic.ins
new file mode 100644
index 0000000000..a66d283223
--- /dev/null
+++ b/graphics/mfpic/source/mfpic.ins
@@ -0,0 +1,59 @@
+% File: mfpic.ins
+% A part of mfpic 1.10 2012/12/03
+%
+\input docstrip
+\keepsilent
+\preamble
+
+-------------------------------------------------------------------
+
+Copyright 2002--2012, Daniel H. Luecking
+
+Mfpic may be distributed and/or modified under the conditions of the
+LaTeX Project Public License, either version 1.3c of this license or (at
+your option) any later version. The latest version of this license is in
+ <http://www.latex-project.org/lppl.txt>
+and version 1.3c or later is part of all distributions of LaTeX version
+2008/12/01 or later.
+
+Mfpic has maintenance status "author-maintained". The Current Maintainer
+is Daniel H. Luecking. There are several Base Interpreters associated
+with mfpic: plain TeX, LaTeX, plain Metafont and plain MetaPost.
+
+\endpreamble
+\edef\zyx{%
+endinput.^^J%
+\DoubleperCent^^J%
+\DoubleperCent\space End of file `\outFileName'.}
+
+\askforoverwritefalse
+
+\generate{\file{mfpic.tex}{\from{mfpic.dtx}{tex}}
+ \file{mfpic.sty}{\from{mfpic.dtx}{sty}}
+ \file{mfpicdef.tex}{\from{mfpic.dtx}{defs}}
+ \usepostamble\zyx
+ \file{grafbase.mf}{\from{grafbase.dtx}{MF}}
+ \file{grafbase.mp}{\from{grafbase.dtx}{MP}}
+ \file{dvipsnam.mp}{\from{grafbase.dtx}{dvips}}}
+
+\def\sJ{^^J \space\space\space}
+\immediate\write16{%
+^^J*******************************************************************
+^^J
+^^J To finish the installation:
+^^J
+^^J -- Copy the files mfpic.tex, mfpic.sty and mfppatch.tex to a
+\sJ location where TeX and LaTeX will find them. For example, in a
+\sJ TDS compliant system, the directory TEXMF/tex/generic/mfpic/ .
+^^J
+^^J -- Copy the file grafbase.mf to a location where Metafont
+\sJ will find it, for example TEXMF/metafont/mfpic/ .
+^^J
+^^J -- Copy the files grafbase.mp and dvipsnam.mp to a location where
+\sJ MetaPost will find them, for example TEXMF/metapost/mfpic/ .
+^^J
+^^J -- Refresh the filename database if your TeX system requires it.
+^^J
+^^J*******************************************************************}
+
+\endbatchfile
diff --git a/graphics/mfpic/tex/mfpic.sty b/graphics/mfpic/tex/mfpic.sty
new file mode 100644
index 0000000000..bddbccf9b9
--- /dev/null
+++ b/graphics/mfpic/tex/mfpic.sty
@@ -0,0 +1,67 @@
+%%
+%% This is file `mfpic.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% mfpic.dtx (with options: `sty')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2002--2012, Daniel H. Luecking
+%%
+%% Mfpic may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3c of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Mfpic has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. There are several Base Interpreters associated
+%% with mfpic: plain TeX, LaTeX, plain Metafont and plain MetaPost.
+%%
+\ProvidesPackage{mfpic}
+ [2012/12/03 v1.10. Macros for drawing with Metafont/MetaPost.]%
+\DeclareOption{draft}{\mfpicdraft}%
+\DeclareOption{final}{%
+ \mfpicfinal\PassOptionsToPackage{final}{graphics}}%
+\DeclareOption{nowrite}{\mfpicnowrite}%
+\DeclareOption{metapost}{\mfp@mposttrue}%
+\DeclareOption{metafont}{\usemetafont}%
+\DeclareOption{centeredcaptions}{\usecenteredcaptions}%
+\DeclareOption{justifiedcaptions}{\noraggedcaptions}%
+\DeclareOption{raggedcaptions}{\useraggedcaptions}%
+\DeclareOption{clip}{\clipmfpic}%
+\DeclareOption{truebbox}{\usetruebbox}%
+\DeclareOption{mplabels}{\usemplabels}%
+\DeclareOption{overlaylabels}{\overlaylabels}%
+\DeclareOption{clearsymbols}{\clearsymbols}%
+\DeclareOption{debug}{\mfpicdebugtrue}%
+\DeclareOption{mfpreadlog}{\mfp@readlogtrue}%
+\DeclareOption*{%
+ \@ifpackageloaded{graphics}%
+ {\Mfpic@warn{Unrecognized option \CurrentOption.}}%
+ {\Mfpic@msg{Passing option \CurrentOption\space to %
+ graphics package.}%
+ \PassOptionsToPackage{\CurrentOption}{graphics}}}%
+\newcommand*\mfpdraftfont{\normalfont\ttfamily}%
+\def\@usemetapost{%
+ \mfp@ifdefined\includegraphics{}{\RequirePackage{graphics}}%
+ \let\mfp@save@parse@bb\Gread@parse@bb
+ \newdef\mfp@parse@bb##1 ##2 ##3 ##4 ##5\\{%
+ \mfp@save@parse@bb##1 ##2 ##3 ##4 ##5\\%
+ \xdef\mfpicllx{\Gin@llx}\xdef\mfpiclly{\Gin@lly}}%
+ \ifmfp@pdf \gdef\mfp@Gtype{mps}%
+ \else \gdef\mfp@Gtype{eps}%
+ \fi
+ \gdef\preparemfpicgraphic##1{%
+ \@namedef{Gin@rule@.\number\mfp@count}####1{{\mfp@Gtype}%
+ {.\number\mfp@count}{####1}}%
+ \let\Gread@parse@bb\mfp@parse@bb}%
+ \global\let\setmfpicgraphic\includegraphics
+ \gdef\getmfpicoffset##1{}}%
+\input mfpic.tex\relax
+\endinput
+%%
+%% End of file `mfpic.sty'.
diff --git a/graphics/mfpic/tex/mfpic.tex b/graphics/mfpic/tex/mfpic.tex
new file mode 100644
index 0000000000..11f1795307
--- /dev/null
+++ b/graphics/mfpic/tex/mfpic.tex
@@ -0,0 +1,1786 @@
+%%
+%% This is file `mfpic.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% mfpic.dtx (with options: `tex')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2002--2012, Daniel H. Luecking
+%%
+%% Mfpic may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3c of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Mfpic has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. There are several Base Interpreters associated
+%% with mfpic: plain TeX, LaTeX, plain Metafont and plain MetaPost.
+%%
+\ifx\mfpfileversion\UndEfInEd\else\expandafter\endinput\fi%
+{%
+ \catcode\lq\.12 \catcode\lq\/12%
+ \gdef\mfpfileversion{1.10}%
+ \gdef\mfpfiledate{2012/12/03}%
+ \gdef\mfpicversion{110}%
+}%
+\let\mfpsaveplus\+%
+\let\+\tabalign%
+{%
+ \catcode61\space12\relax% 61=equal sign
+ \catcode32=10\relax% 32=space
+ \catcode13=5 % 13=EOL
+ \catcode96=12 % 96=left quote
+ \catcode`\@=11
+ \gdef\MFPsavecodes{%
+ \edef\mfp@restoreNLC{\newlinechar\number\newlinechar\relax}%
+ \edef\mfp@restoreELC{\endlinechar\number\endlinechar\relax}%
+ \edef\mfp@restoreSPA{\catcode32=\number\catcode32\relax}%
+ \edef\mfp@restoreEOL{\catcode13=\number\catcode13\relax}%
+ \edef\mfp@restoreALL{\mfp@restorecode{=}\mfp@restorecode{@}%
+ \mfp@restorecode{$}\mfp@restorecode{:}\mfp@restorecode{;}%
+ \mfp@restorecode{.}\mfp@restorecode{,}\mfp@restorecode{!}%
+ \mfp@restorecode{?}\mfp@restorecode{(}\mfp@restorecode{)}%
+ \mfp@restorecode{[}\mfp@restorecode{]}\mfp@restorecode{<}%
+ \mfp@restorecode{>}\mfp@restorecode{*}\mfp@restorecode{/}%
+ \mfp@restorecode{+}\mfp@restorecode{-}\mfp@restorecode{"}%
+ \mfp@restorecode{'}\mfp@restorecode{_}\mfp@restorecode{`}%
+ \mfp@restoreEOL\mfp@restoreSPA\catcode10=\number\catcode10
+ \mfp@restoreNLC\mfp@restoreELC}}%
+ \gdef\mfp@restorecode#1{\catcode`\string#1=\number\catcode`#1\relax}%
+ \ifx\@makeother\UndEfInEd \gdef\@makeother#1{\catcode`#1=12\relax}\fi
+ \gdef\MFPsanitize{\endlinechar13 \newlinechar10
+ \catcode10=12 \catcode13=5 \catcode`\$=3 \catcode`\ =10
+ \@makeother\:\@makeother\;\@makeother\.\@makeother\,%
+ \@makeother\!\@makeother\?\@makeother\(\@makeother\)%
+ \@makeother\[\@makeother\]\@makeother\>\@makeother\<%
+ \@makeother\/\@makeother\*\@makeother\+\@makeother\-%
+ \@makeother\'\@makeother\"\@makeother\_\@makeother\`%
+ \@makeother\=\@makeother\@}%
+}%
+\MFPsavecodes\MFPsanitize
+\catcode`@11
+\chardef\mfp@ctrlJ 10 \chardef\mfp@ctrlM 13
+\newif\ifmfpicdebug
+\ifx\mfpicdebug\UndEfInEd \mfpicdebugfalse
+\else \mfpicdebugtrue
+\fi
+\def\mfp@DBlog#1{%
+ \ifmfpicdebug{\let\@msgbreak\mfp@errbrk\wlog{Mfpic debug: #1}}\fi}%
+\def\mfp@msg#1{%
+ {\newlinechar\mfp@ctrlJ\def\@nl{^^J}\immediate\write16{#1}}}%
+\def\mfp@spaces{\space\space\space\space\space\space}%
+\def\mfp@msgbrk{^^J\mfp@spaces\space}%
+\def\mfp@errbrk{\mfp@msgbrk\mfp@spaces}%
+\def\mfp@warnbrk{\mfp@errbrk\space\space}%
+\def\Mfpic@msg#1{{\let\@msgbreak\mfp@msgbrk\mfp@msg{Mfpic: #1}}}%
+\def\Mfpic@warn#1{%
+ {\let\@msgbreak\mfp@warnbrk\mfp@msg{\@nl Mfpic warning: #1}}}%
+\def\mfp@errmsg#1#2{{\newlinechar\mfp@ctrlJ\let\@msgbreak\mfp@errbrk
+ \errhelp{#2}\errmessage{Mfpic error: #1}}}%
+\def\mfp@lineno{line \number\inputlineno\space in the TeX source}%
+\let\@xp\expandafter
+\def\@XP{\@xp\@xp\@xp}%
+\long\def\@firstoftwo#1#2{#1}%
+\long\def\@secondoftwo#1#2{#2}%
+\def\mfp@ifdefined#1{%
+ \ifx#1\UndEfInEd \@xp\@secondoftwo
+ \else\ifx#1\relax \@XP\@secondoftwo
+ \else \@XP\@firstoftwo
+ \fi\fi}%
+\mfp@ifdefined\@empty{}{\def\@empty{}}%
+\mfp@ifdefined\@gobble{}{\def\@gobble#1{}}%
+\mfp@ifdefined\@firstofone{}{\long\def\@firstofone#1{#1}}%
+\mfp@ifdefined\on@line{}%
+ {\def\on@line{ on input line \number\inputlineno}}%
+\let\mfp@enddef\@empty
+\long\def\mfp@gobbledef#1\mfp@enddef{}%
+\def\mfp@ifundefined#1{\mfp@ifdefined#1\mfp@gobbledef\@empty}%
+\mfp@ifundefined\@ifundefined
+ \def\@ifundefined#1{%
+ \@xp\ifx\csname #1\endcsname\relax \@xp\@firstoftwo
+ \else \@xp\@secondoftwo
+ \fi}%
+\mfp@enddef
+\mfp@ifundefined\g@addto@macro
+ \long\def\g@addto@macro#1#2{%
+ \begingroup
+ \toks@\@xp{#1#2}%
+ \xdef#1{\the\toks@}%
+ \endgroup}%
+\mfp@enddef
+\mfp@ifundefined\g@prependto@macro
+ \long\def\g@prependto@macro#1#2{%
+ \begingroup
+ \toks@{#2}\toks2\@xp{#1}%
+ \xdef#1{\the\toks@\the\toks2}%
+ \endgroup}%
+\mfp@enddef
+\newif\ifmfp@latex \mfp@latexfalse
+\mfp@ifdefined\documentstyle
+ {\ifx \amstexloaded@\relax % amstex loaded, or a bad check for it
+ \ifx\NoBlackBoxes\UndEfInEd % amstex not loaded
+ \mfp@DBlog{LaTeX detected.}\mfp@latextrue
+ \else % most likely amstex loaded
+ \mfp@DBlog{AmS-TeX detected.}%
+ \fi
+ \else % amstex not loaded
+ \mfp@DBlog{LaTeX detected.}\mfp@latextrue
+ \fi}%
+ {\mfp@DBlog{Neither LaTeX nor AmS-TeX detected.}}%
+\newif\ifmfp@latexe \mfp@latexefalse
+\mfp@ifdefined\documentclass
+ {\mfp@latexetrue \mfp@DBlog{LaTeX2e detected.}}%
+ {\mfp@DBlog{Not LaTeX2e.}}%
+\newif\ifmfp@pdf \mfp@pdffalse
+\mfp@ifdefined\pdfoutput
+ {\mfp@DBlog{PdfTeX detected...}%
+ \ifnum\pdfoutput<1 \mfp@DBlog{...with dvi output.}%
+ \else \mfp@pdftrue \mfp@DBlog{...with PDF output.}%
+ \fi}%
+ {\mfp@DBlog{Not pdfTeX.}}%
+\ifmfp@latex \else \let\@@par\endgraf \fi
+\def\mfp@restorepar{\let\par\@@par}%
+\mfp@ifdefined\@namedef{}%
+ {\def\@namedef#1{\@xp\def\csname #1\endcsname}}%
+\mfp@ifdefined\@namelet{}%
+ {\def\@namelet#1{\@xp\let\csname #1\endcsname}}%
+\mfp@ifdefined\@nameuse{}%
+ {\def\@nameuse#1{\csname #1\endcsname}}%
+\mfp@ifundefined\@bsphack
+ \@nameuse{newskip}\@savsk
+ \@nameuse{newcount}\@savsf
+ \def\@bsphack{\relax
+ \ifhmode \@savsk\lastskip \@savsf\spacefactor \fi}%
+ \def\@esphack{\relax
+ \ifhmode \spacefactor\@savsf
+ \ifdim\@savsk>\z@ \ignorespaces
+ \fi\fi}%
+\mfp@enddef
+\mfp@DBlog{Defining test for previous definitions of macros.}%
+\def\mfp@testdef#1{%
+ \ifx#1\UndEfInEd
+ \else\ifx#1\relax
+ \Mfpic@warn{\string#1 was previouly defined to be \string\relax.}%
+ \else
+ \Mfpic@warn{\string#1 is already defined.}%
+ \fi\fi}%
+\mfp@testdef\newdef
+\def\newdef#1{\mfp@testdef#1\def#1}%
+\newdef\newlet#1{\mfp@testdef#1\let#1}%
+\newdef\mfp@useMP@error{%
+ \mfp@errmsg {Command \mfp@b usemetapost too late}%
+ {It is too late to select the metapost option.^^J%
+ It must be selected before the \opengraphsfile command.^^J%
+ If you proceed, the metafont option will be assumed.}}%
+\def\mfp@nooutput@error#1{%
+ \mfp@errmsg {No output file has been opened}%
+ {You have tried to used a command, #1, that requires an output^^J%
+ file to be opened with the \opengraphsfile command, which^^J%
+ was either not issued or was not successful.}}%
+\newdef\mfp@noMP@error#1{%
+ \mfp@errmsg {Metafont does not support #1, use MetaPost}%
+ {Metafont doesn't support #1. Perhaps you forgot to turn on^^J%
+ MetaPost support by using the metapost option or issuing the^^J%
+ command \usemetapost. For now, I will ignore it.}}%
+\newdef\mfp@noMF@warn#1{%
+ \Mfpic@warn
+ {Metapost does not support \string#1, it will be ignored.}}%
+\def\mfp@afteropen@error#1{%
+ \mfp@errmsg{Improper use of command \string#1\on@line}%
+ {You must issue the command #1 prior to \opengraphsfile.
+ It will be ignored now.}}%
+\newdef\mfp@end{%
+ \mfp@errmsg {Unexpected token \string\mfp@end}%
+ {If you get this message but did not misuse the command^^J%
+ \mfp@end, it could mean you have unbalanced braces.}}%
+\newdef\mfp@nofile@error#1{%
+ \mfp@errmsg{No data file: #1}%
+ {The data file you tried to plot was not found.}}%
+\newdef\mfp@nodata@error#1{%
+ \mfp@errmsg{Empty data file: #1}%
+ {The data file contained only empty lines and comments.}}%
+\newdef\mfp@justify@error{%
+ \mfp@errmsg{Invalid justification parameter for text label}%
+ {The optional argument for an mfpic text label must be^^J%
+ one of B, b, c or t, followed by^^J%
+ one of l, r or c, optionally followed by an angle.}}%
+\newdef\mfp@untilwarn{%
+ \Mfpic@warn{\mfp@b mfploop without \string\mfpuntil!\@nl}}%
+\newlet\ifmfpmpost\iffalse
+\newdef\mfp@mposttrue {\global\let\ifmfpmpost\iftrue}%
+\newdef\mfp@mpostfalse{\global\let\ifmfpmpost\iffalse}%
+\newdef\mfp@ifmpost{%
+ \ifmfpmpost\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\newdef\usemetafont{\mfp@mpostfalse
+ \nomplabels
+ \def\preparemfpicgraphic##1{}%
+ \def\setmfpicgraphic##1{\mfp@graphfont\char\mfp@count}%
+ \def\getmfpicoffset##1{\gdef\mfpicllx{0}\gdef\mfpiclly{0}}}%
+\newdef\mfp@ifopengraphsfile{\mfp@ifdefined\mfp@filename}%
+\newdef\mfmode#1{\edef\mfp@mode{#1}%
+ \mfp@ifopengraphsfile%
+ {\mfp@afteropen@error\mfmode}%
+ {\mfp@ifmpost{\mfp@noMF@warn\mfmode}{}}}%
+\newdef\mfresolution#1{\edef\mfp@resolution{#1}%
+ \mfp@ifopengraphsfile%
+ {\mfp@afteropen@error\mfresolution}%
+ {\mfp@ifmpost{\mfp@noMF@warn\mfresolution}{}}}%
+\newdef\setmfvariable#1{%
+ \mfp@sp@def\mfp@tempa{#1}\@setmfvariable\mfp@tempa}%
+\newdef\@setmfvariable#1#2#3{%
+ \mfp@ifopengraphsfile%
+ {\mfcmd{set#1 (#2) #3}}%
+ {\mfp@nooutput@error\setmfvariable}}%
+\newdef\setmfboolean{\@setmfvariable{boolean}}%
+\newdef\setmfnumeric{\@setmfvariable{numeric}}%
+\newdef\setmfpair {\@setmfvariable{pair}}%
+\newdef\setmfcolor {\@setmfvariable{color}}%
+\newdef\globalsetmfvariable#1#2#3{%
+ \mfp@sp@def\mfp@tempa{#1}%
+ \mfp@ifopengraphsfile
+ {\mfcmd{\ifx\mfp@tempa\mfp@C gsetcolor \else gsetvariable (#1) \fi
+ (#2) #3}}%
+ {\mfp@nooutput@error\globalsetmfvariable}}%
+\newlet\setmpvariable\setmfvariable
+\newlet\globalsetmpvariable\globalsetmfvariable
+\newlet\ifin@mfpicenv\iffalse
+\newdef\mfp@local{\relax\ifin@mfpicenv\else\global\fi}%
+\newdef\mfp@let{\mfp@local\let}%
+\newdef\mfp@def{\mfp@local\def}%
+\newdef\mfp@T{true}%
+\newdef\mfp@F{false}%
+\newdef\mfp@C{color}%
+\newdef\usecenteredcaptions{\mfp@let\ifmfp@centcapt\iftrue}%
+\newdef\nocenteredcaptions {\mfp@let\ifmfp@centcapt\iffalse}%
+\nocenteredcaptions
+\newdef\useraggedcaptions{\mfp@let\mfp@capsettings\mfp@raggedcap}%
+\newdef\noraggedcaptions{\mfp@let\mfp@capsettings\mfp@justifiedcap}%
+\newdef\mfp@raggedcap{%
+ \ifmfp@latex
+ \ifmfp@centcapt \centering \else \raggedright \fi
+ \else
+ \rightskip 0pt plus 1fil\relax
+ \ifmfp@centcapt
+ \leftskip 0pt plus 1fil
+ \parfillskip 0pt plus 1fil\relax
+ \fi
+ \def\\{\unskip\hbox{}\penalty-\@M\ignorespaces}%
+ \fi}%
+\def\mfp@justifiedcap{%
+ \ifmfp@centcapt
+ \leftskip 0pt plus 0.5fil
+ \rightskip 0pt plus -0.5fil
+ \parfillskip 0pt plus 1fil\relax
+ \fi
+ \def\\{\unskip\hbox{}\hfil\penalty-\@M\ignorespaces}}%
+\noraggedcaptions
+\newdef\mfp@makeoption#1#2#3#4{%
+ \newdef#1{\mfp@let#4\iftrue
+ \mfp@ifopengraphsfile{\setmfboolean{#3}\mfp@T}{}}%
+ \newdef#2{\mfp@let#4\iffalse
+ \mfp@ifopengraphsfile{\setmfboolean{#3}\mfp@F}{}}%
+ #2}%
+\mfp@makeoption\clipmfpic\noclipmfpic{clipall}\ifmfp@clip
+\mfp@makeoption\usetruebbox\notruebbox{truebbox}\ifmfp@truebbox
+\newdef\usemplabels{\mfp@let\ifmfp@mplabels\iftrue
+ \mfp@ifopengraphsfile
+ {\mfp@ifmpost{}%
+ {\mfp@noMP@error{mplabels}\global\let\ifmfp@mplabels\iffalse}}{}}%
+\newdef\nomplabels{\mfp@let\ifmfp@mplabels\iffalse}%
+\newdef\@ifmplabels{%
+ \ifmfp@mplabels\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\nomplabels
+\newdef\mp@mksharpother{\@ifmplabels{\@makeother\#}{}}%
+\mfp@makeoption%
+ \overlaylabels\nooverlaylabels{overlaylabels}\ifmfp@overlabels
+\mfp@makeoption%
+ \clearsymbols\noclearsymbols{clearsymbols}\ifmfp@clearsym
+\mfp@makeoption\stopshipping\resumeshipping{noship}\ifmfp@noship
+\newlet\noship\stopshipping
+\newlet\ifmfp@readlog\iffalse
+\newdef\mfpreadlog{%
+ \mfp@ifopengraphsfile
+ {\mfp@afteropen@error\mfpreadlog}{\global\let\ifmfp@readlog\iftrue}}%
+\newdef\mfpicllx{0}%
+\newdef\mfpiclly{0}%
+\newdef\normal@setmfpgraphic#1{%
+ \preparemfpicgraphic{#1}\setmfpicgraphic{#1}\getmfpicoffset{#1}}%
+\newdef\nofile@setmfpgraphic#1{%
+ {\edef\mfp@tempa{#1}%
+ \vbox to 0pt{\vss
+ \rlap{\kern2pt \mfpdraftfont \mfp@sanitized\mfp@tempa}\kern 2pt}}}%
+\mfp@ifdefined\strip@prefix{}{\def\strip@prefix#1>{}}%
+\newdef\mfp@sanitized{\@xp\strip@prefix\meaning}%
+\newlet\@setmfpicgraphic\normal@setmfpgraphic
+\usemetafont
+\newdef\setfilename#1#2{#1.#2}%
+\newdef\setfilenametemplate#1{%
+ \begingroup
+ \def\_{\mfp@p j}%
+ \def\#{\mfp@p c}%
+ \let\@nl\relax
+ \xdef\mfp@settemplate{\@nl setoutputtemplate "#1";\@nl}%
+ \let\number\relax
+ \let\mfp@count\relax
+ \let\mfp@filename\relax
+ \def\_{\mfp@filename}%
+ \def\#{\number\mfp@count}%
+ \xdef\setfilename##1##2{#1}%
+ \endgroup
+}%
+\newif\ifmfpicdraft
+\newlet\ifmfp@draft\iffalse
+\newlet\ifmfp@final\iffalse
+\newlet\ifmfp@nowrite\iffalse
+\newdef\mfpicdraft{%
+ \mfp@ifopengraphsfile{\global\mfpicdrafttrue}%
+ {\global\let\ifmfp@draft\iftrue}}%
+\newdef\mfpicfinal{%
+ \mfp@ifopengraphsfile{\global\mfpicdraftfalse}%
+ {\global\let\ifmfp@final\iftrue}}%
+\newdef\mfpicnowrite{%
+ \mfp@ifopengraphsfile{\mfp@afteropen@error\mfpicnowrite}%
+ {\global\let\ifmfp@nowrite\iftrue}}%
+\newdef\usemetapost{%
+ \mfp@ifopengraphsfile{\mfp@mpostfalse\mfp@useMP@error}%
+ {\mfp@mposttrue \@usemetapost}}%
+\ifmfp@latexe
+ \InputIfFileExists{mfpic.cfg}{}{}%
+ \ProcessOptions*\relax
+ \mfp@ifmpost{\usemetapost}{}%
+ \AtEndDocument{\mfp@closegraphsfile}%
+\else
+ \mfp@msg{}\Mfpic@msg{\mfpfiledate\space v\mfpfileversion.\@nl}%
+ \newdef\mfp@useMP#1#2#3#4#5{%
+ \mfp@ifdefined#1{}{%
+ \InputIfFileExists{#2}{}{%
+ \InputIfFileExists{#3}{}{%
+ \mfp@errmsg{Files not found: #1, #2}%
+ {One of the two named files is necessary
+ for mfpic, but neither was found.}}}}%
+ \global\let\setmfpicgraphic\mfp@includeMPS
+ \gdef\getmfpicoffset##1{\xdef\mfpicllx{#4}\xdef\mfpiclly{#5}}}%
+ \ifmfp@pdf
+ \newdef\mfp@includeMPS#1{\convertMPtoPDF{#1}{1}{1}}%
+ \newdef\@usemetapost{%
+ \mfp@useMP\convertMPtoPDF{supp-pdf.mkii}{supp-pdf.tex}%
+ \MPllx\MPlly}%
+ \else
+ \newdef\mfp@includeMPS#1{\epsfbox{#1}}%
+ \newdef\@usemetapost{%
+ \mfp@useMP\epsfbox{epsf.tex}{epsf.sty}\epsfllx\epsflly}%
+ \fi
+\fi
+\mfp@DBlog{Handlers for optional parameters.}%
+\mfp@ifundefined\@ifnextchar
+ \long\def\@ifnextchar#1#2#3{%
+ \let\reserved@d#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch}%
+ \def\@ifnch{%
+ \ifx\@let@token\@sptoken
+ \let\reserved@c\@xifnch
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \reserved@c}%
+ {%
+ \def\:{\global\let\@sptoken= }\: % makes \@sptoken a space token
+ \def\:{\@xifnch}\@xp\gdef\: {\futurelet\@let@token\@ifnch}%
+ }%
+\mfp@enddef
+\def\mfp@tempa#1{%
+ \def\mfp@sp@def##1##2{%
+ \futurelet\mfp@next\mfp@sp@d##2\@nil\@nil#1\@nil\relax##1}%
+ \def\mfp@sp@d{%
+ \ifx\mfp@next\@sptoken \@xp\mfp@sp@b
+ \else \@xp\mfp@sp@b\@xp#1%
+ \fi}%
+ \def\mfp@sp@b#1##1 \@nil{\mfp@sp@c##1}}%
+\mfp@tempa{ }%
+\def\mfp@sp@c#1\@nil#2\relax#3{\mfp@toks{#1}\edef#3{\the\mfp@toks}}%
+\def\mfp@iftoken#1#2{\@ifnextchar#1{\@firstoftwo{#2}}}%
+\def\mfp@ifstar#1#2#3{\mfp@iftoken*{#1{#2}}{#1{#3}}}%
+\def\mfp@ifend{\mfp@iftoken\mfp@end}%
+\def\mfp@ifendorcomma#1#2#3{\mfp@ifend{#1}{\mfp@iftoken,{#2}{#3}}}%
+\mfp@ifundefined\@ifstar
+ \def\@ifstar#1{\@ifnextchar*{\@firstoftwo{#1}}}%
+\mfp@enddef
+{%
+\catcode`Q3 \catcode`\~12
+\gdef\mfp@ifempty#1{\if~#1~\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\gdef\mfp@ifexist#1{\if~#1~\@xp\@gobble\else\@xp\@firstofone\fi}%
+\gdef\mfp@emptysub#1#2{\if~#1~#2\else#1\fi}%
+\long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil}%
+\long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4}%
+}%
+\newdef\mfp@defaultopt#1#2{%
+ \@ifnextchar[{\mfp@ifemptyopt{#1}{#2}}{#1{#2}}}%]
+\newdef\mfp@ifemptyopt#1#2[#3]{\mfp@ifempty{#3}{#1{#2}}{#1{#3}}}%
+\newdef\mfp@nullopt#1{\@ifnextchar[{\mfp@getopt{#1}}{#1{}}}%
+\newdef\mfp@getopt#1[#2]{#1{#2}}%
+\mfp@DBlog{Direct output to Metafont/Post file.}%
+{%
+ \catcode\mfp@ctrlM\active%
+ \gdef\@activectrlM{^^M}%
+ \gdef\mfp@obeylines{\catcode\mfp@ctrlM\active\let^^M\relax}%
+}%
+\newdef\mfp@keeplines{\newlinechar\mfp@ctrlM
+ \endlinechar\newlinechar \mfp@obeylines}%
+\newdef\mfsrc {\mfp@write\mfp@src\mfsrc}%
+\newdef\mfcmd {\mfp@write\mfp@cmd}%
+\newdef\mflist{\mfp@write\mfp@wlist}%
+\newdef\mfp@write{\begingroup\mfp@keeplines \let\@nl\@activectrlM}%
+\newdef\mfp@src#1#2{%
+ \mfp@ifopengraphsfile{\immediate\write\mfp@out{#2}}%
+ {\mfp@nooutput@error{#1}}\endgroup}%
+\newdef\mfp@cmd#1{\mfp@src\mfcmd{#1;}}%
+\newdef\mfp@wlist#1{\mfp@src\mflist{(#1);}}%
+\def\mfp@safe@activestrue{%
+ \mfp@ifdefined\@safe@activestrue\@safe@activestrue{}}%
+\def\mfp@safe@activesfalse{%
+ \mfp@ifdefined\@safe@activesfalse\@safe@activesfalse{}}%
+\edef\mfp@p{\@xp\@gobble\string\%}% percent (%)
+\edef\mfp@s{\@xp\@gobble\string\#}% sharp (#)
+\edef\mfp@b{\@xp\@gobble\string\\}% backslash (\)
+\newdef\mfp@d{--------------}%
+\mfp@ifdefined\two@digits{}%
+ {\def\two@digits#1{\ifnum#1<10 0\fi\number#1}}%
+{%
+ \mfp@ifdefined\normalmonth
+ {\let\month\normalmonth\let\year\normalyear}{}%
+ \count@\time \divide\count@ by 60
+ \xdef\mfp@now{\number\year/\two@digits\month/\two@digits\day
+ \space at \two@digits\count@:}%
+ \multiply\count@ by -60 \advance\count@\time
+ \xdef\mfp@now{\mfp@now\two@digits\count@}%
+}%
+\mfp@DBlog{Declarations used with data and graphs files.}%
+\newwrite\mfp@out
+\newread\mfp@graph
+\newlet\mfp@data\mfp@graph
+\newcount\mfp@count
+\newcount\mfp@linetype
+\newcount\mfp@sequence
+\newtoks\mfp@toks
+\newtoks\mfp@verbtex
+\newif\ifmfp@switch
+\let\MFPbegingroup\begingroup
+\let\MFPendgroup\endgroup
+\newdef\mfp@versioninfo{%
+ \mfp@p\space\mfp@filename.m\mfp@ifmpost{p}{f}, %
+ generated by Mfpic, v\mfpfileversion\space\mfpfiledate,\@nl
+ \mfp@p\space from TeX source "\jobname" on \mfp@now\@nl
+ numeric mfpicversion; mfpicversion := \mfpicversion;\@nl}%
+\newdef\mfp@init@outfile{%
+ if unknown mode: mode := localfont; fi\@nl
+ if unknown mag: mag := \number\mag/1000; fi\@nl
+ if unknown grafbase: input grafbase; fi\@nl\@nl}%
+\newdef\mfp@versioncheck{%
+ if unknown grafbaseversion: grafbaseversion := 0; fi\@nl
+ if grafbaseversion <> mfpicversion :\@nl
+ GBmsg "Bad mfpic installation: mfpic and grafbase %
+ versions do not match.";\@nl
+ fi\@nl}%
+\newdef\mfp@openfile{%
+ \ifmfp@nowrite \else \mfp@msg{}%
+ \Mfpic@msg{Initializing \mfp@filename\mfp@ext.}%
+ \immediate\openout\mfp@out=\mfp@filename\mfp@ext\relax
+ \Mfpic@msg{Don't forget to process \mfp@filename\mfp@ext!}%
+ \Mfpic@msg{Apply \mfp@progname\space to \mfp@filename\mfp@ext%
+ \mfp@ifmpost{}{, then gftopk to the resulting gf file}.}%
+ \Mfpic@msg{Then reprocess this file "\jobname".\@nl}%
+ \fi}%
+\mfp@ifundefined\IfFileExists
+ \def\IfFileExists#1{\openin\mfp@graph=#1\relax
+ \ifeof\mfp@graph \@xp\@secondoftwo
+ \else \immediate\closein\mfp@graph \@xp\@firstoftwo
+ \fi}%
+ \def\InputIfFileExists#1#2{\IfFileExists{#1}{#2\input #1\relax}}%
+\mfp@enddef
+\newdef\mfp@checkoutput#1#2#3{%
+ \IfFileExists{\setfilename\mfp@filename{#1}}%
+ {\global\mfpicdraftfalse #2}%
+ {\global\mfpicdrafttrue #3\mfp@msg{}%
+ \Mfpic@msg{No file \setfilename\mfp@filename{#1}.}%
+ }}%
+\newdef\mfp@checkMPoutput{\mfp@checkoutput{\number\mfp@count}{}{}}%
+\newdef\mfp@checkMFoutput{\mfp@checkoutput{tfm}%
+ {\global\font\mfp@graphfont\mfp@filename\relax}%
+ {\global\let\mfp@graphfont\mfp@dummy}}%
+\newdef\mfp@MPextras{\mfp@toks\@xp{\every@tlabel}%
+ \mfsrc{%
+ if unknown Apricot: input dvipsnam.mp; fi\@nl
+ verbatimtex\@nl
+ \ifmfp@verbtex \the\mfp@verbtex\@nl \fi
+ \relax\@nl
+ \noexpand\input mfpicdef.tex\relax\@nl
+ \def\noexpand\MFPeverylabel{\the\mfp@toks}\@nl
+ etex;\@nl
+ \mfp@ifdefined\mfp@settemplate\mfp@settemplate{}%
+ }%
+ \global\mfp@verbtexfalse \global\mfp@verbtex{}%
+ \@ifmplabels\usemplabels{}%
+ \ifmfp@truebbox \usetruebbox \fi
+ \ifmfp@overlabels \overlaylabels \fi}%
+\def\mfp@MFextras{%
+ \mfp@ifdefined\mfp@resolution%
+ {GBresolution := \mfp@resolution;\@nl}{}%
+ \mfp@ifdefined\mfp@mode{mode := \mfp@mode;\@nl}{}}%
+\def\mfp@dospecials{\do\$\do\&\do\#\do\^\do\_\do\%\do\~}%
+\mfp@DBlog{Macros to open and close graphs files.}%
+\newdef\opengraphsfile{\@bsphack
+ \begingroup
+ \let\do\@makeother
+ \mfp@dospecials\@opengraphsfile}%
+\newdef\@opengraphsfile#1{%
+ \xdef\mfp@tempa{#1}%
+ \endgroup
+ \mfp@ifopengraphsfile%
+ {\Mfpic@warn
+ {\@nl An attempt has been made to open a graph file, %
+ \mfp@sanitized\mfp@tempa\@msgbreak
+ while another, \mfp@filename, is still open. \@msgbreak
+ Closing \mfp@filename.}\mfp@closegraphsfile}%
+ {}%
+ \xdef\mfp@filename{\mfp@sanitized\mfp@tempa}%
+ \xdef\mfp@progname{meta\mfp@ifmpost{pos}{fon}t}%
+ \xdef\mfp@ext{.m\mfp@ifmpost{p}{f}}%
+ \mfp@ifmpost\mfp@checkMPoutput\mfp@checkMFoutput
+ \mfp@openfile
+ \ifmfp@draft \global\mfpicdrafttrue \fi
+ \ifmfp@final \global\mfpicdraftfalse \fi
+ \ifmfp@nowrite \gdef\mfp@src##1##2{\endgroup}\fi
+ \mfsrc{\mfp@versioninfo \mfp@ifmpost{}\mfp@MFextras
+ \mfp@init@outfile \mfp@versioncheck}%
+ \mfp@ifmpost\mfp@MPextras{}%
+ \ifmfp@clip \clipmfpic \fi
+ \ifmfp@clearsym \clearsymbols \fi
+ \ifmfp@noship \stopshipping \fi
+ \ifmfp@readlog \mfp@readlogfile \fi
+ \@esphack}%
+\newdef\closegraphsfile{%
+ \mfp@ifopengraphsfile{}{\mfp@nooutput@error\closegraphsfile}%
+ \mfp@closegraphsfile}%
+\newdef\mfp@closegraphsfile{%
+ \mfp@ifopengraphsfile
+ {\ifmfp@nowrite \else
+ \mfsrc{\@nl end.}\immediate\closeout\mfp@out
+ \fi \global\let\mfp@filename\UndEfInEd}{}}%
+\edef\mfpicvalue{\string\mfpicvalue}%
+\newdef\mfp@cmdname{%
+ mfpic-\ifin@mfpicenv\number\mfp@count\fi-\@xp\@gobble\string}%
+\newdef\assignmfvalue{\mfp@assign\@empty}%
+\newdef\globalassignmfvalue{\mfp@assign\global}%
+\newdef\mfp@assign#1#2#3{%
+ #1\edef#2{%
+ \@ifundefined{\mfp@cmdname#2}{???}{\@nameuse{\mfp@cmdname#2}}}%
+ \@ifundefined{\mfp@cmdname#2}%
+ {\mfp@msg{}\Mfpic@msg{No value for \string#2\ifin@mfpicenv\space
+ in mfpic figure \number\mfp@count\fi.\@nl}}%
+ {}%
+ \mfsrc{%
+ \@ifmplabels{\@nl verbatimtex #1\def\string#2{#2} etex;\@nl}{}%
+ message "\string\mfpicvalue";\@nl
+ message "\mfp@cmdname#2";\@nl
+ show #3;\@nl
+ message "";}}%
+\newlet\assignmpvalue\assignmfvalue
+\newlet\globalassignmpvalue\globalassignmfvalue
+\newdef\strip@gtgt>> #1\mfp@end{#1}%
+\newdef\mfp@readlogfile{%
+ \openin\mfp@data=\mfp@filename.log\relax
+ \ifeof\mfp@data \Mfpic@msg{No file \mfp@filename.log.}%
+ \else
+ {%
+ \mfp@resetwhitespace \endlinechar -1
+ \catcode`\>12
+ \def\@mfpicvalue{\mfpicvalue}%
+ \message{< Mfpic: Reading \mfp@filename.log}%
+ \mfp@readloglines
+ \message{>}%
+ }%
+ \fi \closein\mfp@data}%
+\newdef\mfp@readloglines{%
+ \read\mfp@data to \mfp@tempa
+ \ifeof\mfp@data
+ \else
+ \ifx\mfp@tempa\@mfpicvalue
+ \read\mfp@data to \mfp@tempa
+ \read\mfp@data to \mfp@tempb
+ \@XP\xdef\@nameuse\mfp@tempa{\@xp\strip@gtgt\mfp@tempb\mfp@end}%
+ \fi
+ \@xp\mfp@readloglines
+ \fi}%
+\mfp@DBlog{Using dummy font's dimensions, to spare TeX registers.}%
+\font\mfp@dummy=dummy scaled 1042
+\fontdimen100\mfp@dummy0pt
+\newcount\mfp@fdc
+\mfp@fdc22
+\newdef\newfdim#1{%
+ \global\advance\mfp@fdc1
+ \xdef#1{\fontdimen\number\mfp@fdc\mfp@dummy}%
+ \wlog{\string#1=\fontdimen\number\mfp@fdc\mfp@dummy}}%
+\mfp@DBlog{A box register for whole labeled graph, %
+ and a temporary one.}%
+\newbox\@wholegraph
+\newbox\@textbox
+\newdef\tb@ht{\ht\@textbox}%
+\newdef\tb@dp{\dp\@textbox}%
+\newdef\tb@wd{\wd\@textbox}%
+\newbox\@alltlabels
+\newbox\@backtext
+\newfdim\@tlabelstop
+\newfdim\@tlabelsbot
+\newfdim\@tlabelsleft
+\mfp@DBlog{Internal dimension parameters for graph dimensions...}%
+\newfdim\@graphright
+\newfdim\@graphleft
+\newfdim\@graphtop
+\newfdim\@graphbot
+\mfp@DBlog{...and dimension parameters for tlabel positioning.}%
+\newfdim\tb@raise
+\newfdim\tb@moveright
+\newfdim\tb@totalht
+\newfdim\tlabel@hadj
+\newfdim\tlabel@vadj
+\newfdim\tlabel@sep
+\newfdim\tlpath@sep
+\tlabel@hadj0pt
+\tlabel@vadj0pt
+\tlabel@sep0pt
+\tlpath@sep0pt
+\mfp@DBlog{User level dimension parameters, with default settings.}%
+\newfdim\mfpicunit
+\newfdim\@mfpicunit % internal version
+\newfdim\pointsize
+\newfdim\shadespace
+\newfdim\polkadotspace
+\newfdim\hatchspace
+\newfdim\headlen
+\newfdim\axisheadlen
+\newfdim\sideheadlen
+\newfdim\hashlen
+\newfdim\dashlen
+\newfdim\dashspace
+\newfdim\dotsize
+\newfdim\griddotsize
+\newfdim\dotspace
+\newfdim\symbolspace
+\mfpicunit1pt
+\pointsize2pt
+\shadespace1pt
+\polkadotspace10pt
+\hatchspace3pt
+\headlen3pt
+\axisheadlen5pt
+\sideheadlen0pt
+\hashlen4pt
+\dashlen4pt
+\dashspace4pt
+\dotsize0.5pt
+\griddotsize0.5pt
+\dotspace3pt
+\symbolspace5pt
+\newdef\save@mfpicdimens{%
+ \edef\restore@mfpicdimens{%
+ \mfpicunit \the\mfpicunit
+ \pointsize \the\pointsize
+ \shadespace \the\shadespace
+ \polkadotspace \the\polkadotspace
+ \hatchspace \the\hatchspace
+ \headlen \the\headlen
+ \axisheadlen \the\axisheadlen
+ \sideheadlen \the\sideheadlen
+ \hashlen \the\hashlen
+ \dashlen \the\dashlen
+ \dashspace \the\dashspace
+ \dotsize \the\dotsize
+ \griddotsize \the\griddotsize
+ \dotspace \the\dotspace
+ \symbolspace \the\symbolspace
+ \tlabel@hadj \the\tlabel@hadj
+ \tlabel@vadj \the\tlabel@vadj
+ \tlabel@sep \the\tlabel@sep
+ \tlpath@sep \the\tlpath@sep}}%
+\newdimen\mfp@scratch
+\newdimen\mfpframesep
+\newdimen\mfpframethickness
+\newdimen\mfpicheight
+\newdimen\mfpicwidth
+\newskip\mfpiccaptionskip
+\mfpframethickness0.4pt
+\mfpframesep2pt
+\mfpiccaptionskip\medskipamount
+\def\mfpicnumber#1{\global\mfp@count#1\relax}%
+\newdef\mfpaddto#1#2{\mfp@scratch#1pt \advance\mfp@scratch#2pt
+ \edef#1{\strip@pt\mfp@scratch}}%
+\newdef\mfpmultiply#1#2{\mfp@scratch#1pt \mfp@scratch#2\mfp@scratch
+ \edef#1{\strip@pt\mfp@scratch}}%
+\mfp@ifundefined\strip@pt
+ \begingroup
+ \lccode`\/`\p
+ \lccode`\?`\t
+ \lowercase{%
+ \endgroup
+ \def\rem@pt#1.#2/?}{#1\ifnum#2>\z@.#2\fi}%
+ \def\strip@pt{\@xp\rem@pt\the}%
+\mfp@enddef
+\newdef\pointdef#1(#2,#3){%
+ \@ifundefined{#1} {}{\Mfpic@warn{\mfp@b#1 already defined.}}%
+ \@ifundefined{#1x}{}{\Mfpic@warn{\mfp@b#1x already defined.}}%
+ \@ifundefined{#1y}{}{\Mfpic@warn{\mfp@b#1y already defined.}}%
+ \@namedef{#1}{(#2,#3)}\@namedef{#1x}{#2}\@namedef{#1y}{#3}}%
+\newdef\setmfarray#1#2{\mfsrc{setarray (#1) (#2)}\mfp@writedata}%
+\newlet\setmparray\setmfarray
+\newdef\pairarray{\setmfarray{pair}}%
+\newdef\numericarray{\setmfarray{numeric}}%
+\newdef\colorarray{\setmfarray{color}}%
+\newdef\rgbcolorarray{\setmfarray{rgbcolor}}%
+\newdef\cmykcolorarray{\setmfarray{cmykcolor}}%
+\newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1)(#2)}\mfp@writedata}%
+\newlet\globalsetmparray\globalsetmfarray
+\newdef\lightershade{\shadespace1.2\shadespace}%
+\newdef\darkershade{\shadespace.83333\shadespace}%
+\newdef\dashlineset{\dashlen4pt \dashspace4pt }%
+\newdef\dotlineset{\dashlen1pt \dashspace2pt }%
+\let\ifpointfill\iftrue
+\newdef\pointfilltrue{\mfp@let\ifpointfill\iftrue}%
+\newdef\pointfillfalse{\mfp@let\ifpointfill\iffalse}%
+\newdef\mfpfor#1{\begingroup\mfsrc{for #1:}}%
+\newdef\endmfpfor{\mfsrc{endfor}\endgroup}%
+\newdef\mfploop{%
+ \begingroup\mfsrc{forever:}\let\@nountil\mfp@untilwarn}%
+\newdef\mfpuntil#1{\mfcmd{exitif #1}\let\@nountil\@empty}%
+\newdef\endmfploop{\@nountil\endmfpfor}%
+\newdef\mfpwhile#1{\begingroup\mfcmd{forever: exitif not(#1)}}%
+\newlet\endmfpwhile\endmfpfor
+\newdef\plr#1{map (polar) (#1)}%
+\newdef\midpoint#1{(0.5[#1])}%
+\mfp@DBlog{Tests to control multiple prefix commands.}%
+\newif\if@mfpstart\@mfpstarttrue
+\newif\if@mfprend\@mfprendtrue
+\newdef\mfp@storepath{\mfsrc{\@nl store (curpath)}}%
+\newdef\mfp@first{\relax
+ \if@mfpstart \mfp@storepath \@mfprendtrue \@mfpstartfalse\fi}%
+\newdef\mfp@rendmac{\mfp@first \@mfprendfalse \mfsrc}%
+\newdef\mfp@modmac{\mfp@first\mfp@autorend\mfsrc}%
+\newdef\mfp@autorend{\if@mfprend\@xp\mfp@render\fi}%
+\newdef\mfp@addmac{\mfp@first \mfsrc}%
+\newdef\mfp@render{\draw[]}%
+\newdef\setrender{\mfp@def\mfp@render}%
+\newdef\mfp@figmacbase{\mfp@first \mfp@autorend \@mfpstarttrue}%
+\newdef\mfp@figmac{\mfp@figmacbase\mfcmd}%
+\newdef\mfp@listmac#1{\mfp@figmacbase\mfsrc{#1}\mfp@writedata}%
+\newdef\mfp@writedata{\mfp@iftoken\datafile{\mfp@writefile}{\mflist}}%
+\newdef\mfp@writefile{%
+ \mfp@ifopengraphsfile
+ {\mfp@processfile{\mfp@rwdata}}{\mfp@nooutput@error\datafile}}%
+\newdef\mftitle#1{\@bsphack\mfp@title\mftitle{#1}\@esphack}%
+\newdef\tmtitle#1{\mfp@title\tmtitle{#1}\wlog{\the\mfp@toks}{#1}}%
+\newdef\mfp@title#1#2{\mfp@toks{#2}%
+ \mfp@write\mfp@src#1{mftitle "\the\mfp@toks";}}%
+\newdef\mfp@processfile#1#2{%
+ \openin\mfp@data=#2\relax
+ \ifeof\mfp@data \mfp@nofile@error{#2}%
+ \else
+ \mfp@DBlog{Opening file #2 for data.}%
+ {%
+ \mfp@resetwhitespace \mfp@setcomment
+ \mfp@skipblanklines
+ \ifeof\mfp@data
+ \mfp@nodata@error{#2}%
+ \else
+ \message{< Mfpic: Reading #2}%
+ #1%
+ \message{>}%
+ \fi
+ \@xp
+ }\@xp\mfp@linetype\number\mfp@linetype\relax
+ \mfp@DBlog{Closing file #2.}%
+ \fi
+ \closein\mfp@data}%
+\newdef\mfp@resetwhitespace{\mfp@restorepar
+ \endlinechar`\^^M \catcode`\^^M5 \catcode`\ 10 \catcode`\^^I10 }%
+\newdef\mfp@skipcomments{\read\mfp@data to \mfp@temp
+ \ifx\mfp@temp\@empty \@xp\mfp@skipcomments\fi}%
+\newdef\mfp@skipblanklines{\mfp@skipcomments
+ \ifeof\mfp@data
+ \else\ifx\mfp@temp\mfp@par \@XP\mfp@skipblanklines
+ \fi\fi}%
+\newdef\mfp@nextdatum{\@xp\parse@data\mfp@temp\mfp@end}%
+\newdef\mfp@rwdata{\mfp@count1 \mfp@sequence1
+ \def\sequence{\number\mfp@sequence}%
+ \edef\mfp@temp{\mfp@temp\space}%
+ \edef\mfp@buffer{(\mfp@nextdatum}\mfp@rwdataloop}%
+\newdef\mfp@rwdataloop{%
+ \read\mfp@data to \mfp@temp
+ \ifx\mfp@temp\mfp@par
+ \mfcmd{\mfp@buffer)}%
+ \else
+ \ifx\mfp@temp\@empty
+ \else
+ \edef\mfp@temp{\mfp@temp\space}%
+ \advance\mfp@sequence1
+ \edef\mfp@buffer{\mfp@buffer\mfp@join}%
+ \ifnum\mfp@count<\mfpdataperline\relax \advance\mfp@count1
+ \else \mfsrc{\mfp@buffer}\mfp@count1 \def\mfp@buffer{}%
+ \fi
+ \edef\mfp@buffer{\mfp@buffer\mfp@nextdatum}%
+ \fi
+ \@xp\mfp@rwdataloop
+ \fi}%
+\newdef\pen#1{\mfcmd{\@nl resizedrawpen (#1)}}%
+\newlet\penwd\pen \newlet\drawpen\pen
+\newdef\shadewd#1{\setmfnumeric{shadewd}{#1}}%
+\newdef\polkadotwd#1{\setmfnumeric{polkadotwd}{#1}}%
+\newdef\hatchwd#1{\setmfnumeric{hatchwd}{#1}%
+ \setmfvariable{pen}{hatchpen}{pencircle scaled hatchwd}}%
+\newdef\dashpattern#1{\mfsrc{save #1; dashpat (#1)}\mfp@writedata}%
+\newdef\settension#1{\setmfnumeric{default_tension}{#1}}%
+\newcount\tl@vpos \newcount\tl@hpos
+\newdef\mfp@tlh@l{-1}%
+\newdef\mfp@tlh@c{0}%
+\newdef\mfp@tlh@r{1}%
+\newdef\mfp@tlv@B{-1}%
+\newdef\mfp@tlv@b{0}%
+\newdef\mfp@tlv@c{1}%
+\newdef\mfp@tlv@t{2}%
+\newdef\tl@rot{}\tl@vpos-1 \tl@hpos-1
+\newdef\tlabeljustify#1{\mfp@ifexist{#1}{\mfp@justify#1\mfp@end}}%
+\newdef\mfp@justify#1#2\mfp@end{\mfp@local\mfp@vconv{#1}%
+ \mfp@ifexist{#2}{\mfp@@justify#2\mfp@end}}%
+\newdef\mfp@@justify#1#2\mfp@end{\mfp@local\mfp@hconv{#1}%
+ \mfp@local\edef\tl@rot{#2}%
+ \@ifmplabels{}%
+ {\mfp@ifexist{#2}%
+ {\Mfpic@warn{Rotation of labels is not supported without the %
+ mplabels\@msgbreak option. Rotation setting\on@line\space
+ may be ignored.}}%
+ }}%
+\newdef\mfp@vconv#1{%
+ \@ifundefined{mfp@tlv@#1}%
+ {\tl@vpos-1 \mfp@justify@error}%
+ {\tl@vpos\@nameuse{mfp@tlv@#1}\relax}}%
+\newdef\mfp@hconv#1{%
+ \@ifundefined{mfp@tlh@#1}%
+ {\tl@hpos-1 \mfp@justify@error}%
+ {\tl@hpos\@nameuse{mfp@tlh@#1}\relax}}%
+\newdef\tlpathjustify#1{%
+ \mfp@ifexist{#1}{\tlp@justify#1\mfp@end}}%
+\newdef\tlp@justify#1#2\mfp@end{\mfp@def\tlpath@v{#1}%
+ \mfp@ifexist{#2}{\tlp@@justify#2\mfp@end}}%
+\newdef\tlp@@justify#1#2\mfp@end{%
+ \mfp@def\tlpath@h{#1}\mfp@def\tlpath@r{#2}}%
+\tlpathjustify{cc}%
+\newdef\tlpointsep#1{\mfp@local\tlabel@sep#1\relax
+ \setmfnumeric{label_sep}{\the\tlabel@sep}}%
+\newdef\tlpathsep#1{\mfp@local\tlpath@sep#1\relax
+ \setmfnumeric{labelpath_sep}{\the\tlpath@sep}}%
+\newdef\tlabelsep#1{\tlpointsep{#1}\tlpathsep{#1}}%
+\newdef\tlabeloffset#1#2{%
+ \mfp@local\tlabel@hadj#1\relax \mfp@local\tlabel@vadj#2\relax
+ \setmfpair{label_adjust}%
+ {(\the\tlabel@hadj,\the\tlabel@vadj)}}%
+\newdef\everytlabel{\afterassignment\mfp@everytlabel\mfp@toks}%
+\newdef\mfp@everytlabel{\mfp@local\edef\every@tlabel{\the\mfp@toks}%
+ \mfp@ifmpost
+ {\mfp@ifopengraphsfile
+ {\mfcmd{verbatimtex\@nl
+ \def\noexpand\MFPeverylabel{\the\mfp@toks} etex}}%
+ {}}%
+ {}}%
+\newdef\every@tlabel{}%
+\newdef\extra@endtlabel{}%
+\newdef\pinumber{3.14159}%
+\newdef\headshape#1#2#3{\mfcmd{\@nl headshape (#1, #2, #3)}}%
+\newdef\mfp@arr@b#1{\edef\mfp@hlocate{#1}}%
+\newdef\mfp@arr@c#1{\edef\mfp@hcolour{#1}}%
+\newdef\mfp@arr@l#1{\edef\mfp@hlength{#1}}%
+\newdef\mfp@arr@r#1{\edef\mfp@hrotate{#1}}%
+\newlet\mfp@arr@f\mfp@arr@b
+\newlet\mfp@arr@s\mfp@arr@l
+\newdef\mfp@arc@s{pps}%
+\newdef\mfp@arc@t{ppp}%
+\newdef\mfp@arc@p{\ifmfp@switch plr\fi}%
+\newdef\mfp@arc@a{\ifmfp@switch alt\fi}%
+\newdef\mfp@arc@c{cp\ifmfp@switch s\fi}%
+\newdef\mfp@arc@r{pp (\mfp@T)}%
+\newdef\mfp@arc@q{pp (\mfp@F)}%
+\newdef\mfpdefinecolor#1#2#3{\setmfcolor{#1}{#2(#3)}}%
+\newdef\mfp@defclr#1#2#3{%
+ \setmfcolor{#1}{\mfp@ifempty{#2}{#3}{#2(#3)}}}%
+\newdef\mfp@newcolorcmd#1{%
+ \@namedef{#1\mfp@C}{\mfp@nullopt{\mfp@defclr{#1\mfp@C}}}}%
+\mfp@newcolorcmd{draw}\mfp@newcolorcmd{fill}\mfp@newcolorcmd{tlabel}%
+\mfp@newcolorcmd{hatch}\mfp@newcolorcmd{head}\mfp@newcolorcmd{point}%
+\def\backgroundcolor{\mfp@nullopt{\mfp@defclr{background}}}%
+\newdef\dashedlines{\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\gendashed{getdashpat \number\mfp@linetype}}}%
+\dashedlines
+\newdef\coloredlines{%
+ \mfp@ifmpost
+ {\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\draw[getcolor \number\mfp@linetype]}}%
+ {\Mfpic@warn{You can't use \mfp@b coloredlines in %
+ Metafont.\@msgbreak Using \dashedlines instead}%
+ \dashedlines}}%
+\newdef\pointedlines{\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\plot{getsymbol \number\mfp@linetype}}}%
+\newdef\datapointsonly{\mfp@local\mfp@linetype0
+ \mfp@def\mfp@setstyle{\relax
+ \plotnodes{getsymbol \number\mfp@linetype}}}%
+\newdef\reconfigureplot#1{\mfsrc{setdata#1}\mfp@writedata}%
+\newdef\defaultplot#1{\mfcmd{default#1}}%
+\newdef\mfplinetype#1{\mfp@local\mfp@linetype#1\relax}%
+\newlet\mfplinestyle\mfplinetype
+\mfplinetype{0}%
+\newdef\mfp@lshift{0}\newdef\mfp@bshift{0}%
+\newdef\mfp@rshift{0}\newdef\mfp@tshift{0}%
+\newdef\axismargin#1#2{\setmfnumeric{#1axis}{#2}%
+ \mfp@local\@namedef{mfp@#1shift}{#2}}%
+\newdef\setaxismargins#1#2#3#4{\axismargin l{#1}\axismargin b{#2}%
+ \axismargin r{#3}\axismargin t{#4}}%
+\newdef\setallaxismargins#1{\setaxismargins{#1}{#1}{#1}{#1}}%
+\def\mfp@axis@x{0}%
+\def\mfp@axis@y{1}%
+\def\mfp@axis@l{2}%
+\def\mfp@axis@b{3}%
+\def\mfp@axis@r{4}%
+\def\mfp@axis@t{5}%
+\def\mfp@getaxis#1#2\mfp@end#3{%
+ \@ifundefined{mfp@axis@#1}%
+ {\mfp@errmsg {Invalid axis letter "#1"}%
+ {The command #3 requires an axis to be designated by one of^^J%
+ the following letters: x, y, l, b, r, or t. If you proceed, ^^J%
+ x will be assumed.}\def\mfp@axisnum{0}\def\mfp@axisletter{x}}%
+ {\edef\mfp@axisnum{\@nameuse{mfp@axis@#1}}\def\mfp@axisletter{#1}}%
+ \edef\mfp@defaultheadlen{%
+ \the\ifnum\mfp@axisnum>1 \sideheadlen\else \axisheadlen\fi}}%
+\newdef\setaxismarks#1#2{\setmfnumeric{#1tick}{#2}}%
+\newdef\setxmarks#1{\setaxismarks x{#1}}%
+\newdef\setymarks#1{\setaxismarks y{#1}}%
+\newdef\setbordermarks#1#2#3#4{\setaxismarks l{#1}\setaxismarks b{#2}%
+ \setaxismarks r{#3}\setaxismarks t{#4}}%
+\newdef\setallbordermarks#1{\setbordermarks{#1}{#1}{#1}{#1}}%
+\newdef\mfp@smdata#1{\mfp@def\mfp@smoothness{#1}%
+ \mfp@nullopt{\mfp@def\mfp@tension}}%
+\newdef\smoothdata{\mfp@smdata{s}}%
+\newdef\unsmoothdata{\mfp@smdata{p}\@empty}%
+\unsmoothdata% default
+\newdef\using#1#2{\mfp@def\parse@data#1\mfp@end{#2}}%
+\newdef\usingpairdefault{\using{##1 ##2 ##3}{(##1,##2)}}%
+\newdef\usingnumericdefault{\using{##1 ##2}{##1}}%
+\usingpairdefault
+\newdef\mfpdataperline{5}%
+\newdef\mfp@par{\par}\newdef\mfp@join{,}%
+\newcount\mfp@commentchar \mfp@commentchar`\%%
+\newdef\makepercentother{\@makeother\%}%
+\newdef\makepercentcomment{\catcode`\%14 }%
+\newdef\mfpdatacomment#1{\mfp@local\mfp@commentchar`#1}%
+\newdef\mfp@setcomment{\makepercentother\catcode\mfp@commentchar14 }%
+\newdef\fdef{\begingroup\@makeother\#\mfp@keeplines\mfp@fdef}%
+\newdef\mfp@fdef#1#2#3{\mfcmd{\@nl save #1;\@nl
+ vardef #1 (expr #2) = \@nl #3\@nl enddef}\endgroup}%
+\newdef\mfp@additions{}%
+\newdef\mfp@grafmacs{%
+ \newdef\rect##1{\mfp@figmac{rect (##1)}}%
+ \newdef\regpolygon##1##2##3##4{%
+ \mfp@figmac{regularpolygon (##1) (##2) (##3; ##4;)}}%
+ \def\circle{\mfp@switchfalse\mfp@defaultopt\mfp@arccircle{p}}%
+ \newdef\ellipse{\mfp@defaultopt\mfp@ellipse{0}}%
+ \newdef\quarterellipse##1{\mfp@figmac{quarterellipse (##1)}}%
+ \newdef\halfellipse##1{\mfp@figmac{halfellipse (##1)}}%
+ \newdef\fullellipse##1{\mfp@figmac{fullellipse (##1)}}%
+ \newdef\sector##1{\mfp@figmac{sector (##1)}}%
+ \newdef\arc{\mfp@iftoken*{\arccomplement\mfp@arc}{\mfp@arc}}%
+ \newdef\pshcircle{\mfp@ifstar\mfp@pshcircle\mfp@F\mfp@T}%
+ \newdef\hypergeodesic{\mfp@ifstar\mfp@hypergeodesic{UHP}{UD}}%
+ \newdef\lines{\mfp@listi{polyline}\mfp@F}%
+ \newdef\polygon{\mfp@listi{polyline}\mfp@T}%
+ \newdef\computedspline{\mfp@listi{dospline}\mfp@F}%
+ \newdef\closedcomputedspline{\mfp@listi{dospline}\mfp@T}%
+ \newdef\qspline{\mfp@listi{qspline}\mfp@F}%
+ \newdef\closedqspline{\mfp@listi{qspline}\mfp@T}%
+ \newdef\cspline{\mfp@listi{cspline}\mfp@F}%
+ \newdef\closedcspline{\mfp@listi{cspline}\mfp@T}%
+ \newdef\qbeziers{\mfp@listi{qbezier}\mfp@F}%
+ \newdef\closedqbeziers{\mfp@listi{qbezier}\mfp@T}%
+ \newdef\cbeziers{\mfp@listi{cbezier}\mfp@F}%
+ \newdef\closedcbeziers{\mfp@listi{cbezier}\mfp@T}%
+ \newdef\fcnspline{\mfp@listi{fcnspline}\mfp@F}%
+ \newdef\periodicfcnspline{\mfp@listi{fcnspline}\mfp@T}%
+ \newlet\closedpolyline\polygon
+ \newlet\polyline\lines
+ \newdef\curve{\mfp@curve{curve}\mfp@F}%
+ \newdef\cyclic{\mfp@curve{curve}\mfp@T}%
+ \newdef\convexcurve{\mfp@curve{ccurve}\mfp@F}%
+ \newdef\convexcyclic{\mfp@curve{ccurve}\mfp@T}%
+ \newdef\mfbezier{\mfp@curve{bezier}\mfp@F}%
+ \newdef\closedmfbezier{\mfp@curve{bezier}\mfp@T}%
+ \newlet\closedcurve\cyclic
+ \newlet\closedconvexcurve\convexcyclic
+ \newdef\fcncurve{\mfp@nullopt\mfp@fcncurve}%
+ \newdef\turtle{\mfp@listmac{turtle}}%
+ \newdef\function{\mfp@fcn{function}s}%
+ \newdef\parafcn{\mfp@fcn{parafcn}s}%
+ \newdef\plrfcn{\mfp@fcn{plrfcn}s}%
+ \newdef\btwnfcn{\mfp@btwn{btwnfcn}}%
+ \newdef\btwnplrfcn{\mfp@btwn{btwnplrfcn}}%
+ \newdef\belowfcn{\mfp@fcn{belowfcn}p}%
+ \newdef\plrregion{\mfp@fcn{plrregion}p}%
+ \def\levelcurve{\mfp@fcn{levelset}p}%
+ \newdef\DEgraph{\mfp@fcn{odeRKIV}s}%
+ \newdef\DEtrajectory{\mfp@fcn{xyRKIV}s}%
+ \newdef\brownianmotion##1{\mfp@figmac{brownianpath (##1)}}%
+ \newdef\browniangraph##1{\mfp@figmac{browniangraph (##1)}}%
+ \newdef\randomwalk##1{\mfp@figmac{randomwalk(##1)}}%
+ \newdef\plotdata{\mfp@nullopt\mfp@plotdata}%
+ \newdef\datafile{\mfp@nullopt\mfp@datafile}%
+ \newdef\store##1##2{\mfp@rendmac{stored (##1)}##2}%
+ \newdef\norender{\mfp@first\@mfprendfalse}%
+ \newlet\mfobj\mfp@figmac \newlet\mpobj\mfobj
+ \newdef\mfpimage{\mfp@defaultopt\mfp@image{(0,0)}}%
+ \newdef\endmfpimage{\mfcmd{\@nl concludeimage}}%
+ \newdef\putmfpimage##1{\mfsrc{\@nl putimage (##1)}\mfp@writedata}%
+ \newdef\cutoffafter {\mfp@modi{cutoffafter}}%
+ \newdef\cutoffbefore{\mfp@modi{cutoffbefore}}%
+ \newdef\trimpath##1{\mfp@getdimens##1,,\mfp@end
+ \mfp@modi{trimmedpath}\mfp@thedimens}%
+ \newdef\partpath{\mfp@modi{partialpath}}%
+ \newdef\subpath{\mfp@modi{gsubpath}}%
+ \newdef\draw{\mfp@nullopt{\mfp@clroptrend{drawn}}}%
+ \newdef\doubledraw{\mfp@defaultopt\mfp@doubledraw{2penwd}}%
+ \newdef\dashed{\mfp@optrendi{DASHED}{\the\dashlen,\the\dashspace}}%
+ \newdef\dotted{\mfp@optrendi{dotted}{\the\dotsize,\the\dotspace}}%
+ \newdef\gendashed{\mfp@rendi{gendashed}}%
+ \newdef\zigzag{\mfp@rendi{zigzag}}%
+ \newdef\sinewave {\mfp@defaultopt{\mfp@wiggle{sinewave}}1}%
+ \newdef\coil{\mfp@defaultopt{\mfp@wiggle{corkscrew}}1}%
+ \newlet\corkscrew\coil
+ \newdef\plot{%
+ \mfp@optrendii{doplot}{\the\pointsize,\the\symbolspace}}%
+ \newdef\plotnodes{\mfp@optrendii{plotnodes}{\the\pointsize}}%
+ \newdef\showcontrols{\mfp@optrendii{showcontrols}{\the\pointsize}}%
+ \newdef\bclosed{\mfp@nullopt{\mfp@close b}}%
+ \newdef\sclosed{\mfp@nullopt{\mfp@close s}}%
+ \newdef\lclosed{\mfp@close l{}}%
+ \newdef\cbclosed{\mfp@close{cb}{}}%
+ \newdef\qbclosed{\mfp@close{qb}{}}%
+ \newlet\uclosed\bclosed
+ \newdef\makesector{\mfp@modmac{makesector}}%
+ \newdef\tess{\mfp@rendi{tess}}%
+ \newdef\shade{\mfp@optrendi{shade}{\the\shadespace}}%
+ \newdef\polkadot{\mfp@optrendi{polkadot}{\the\polkadotspace}}%
+ \newdef\thatch{\mfp@defaultopt\mfp@thatch{\the\hatchspace,0}}%
+ \newdef\lhatch{\mfp@defaultopt\mfp@lhatch{\the\hatchspace}}%
+ \newdef\rhatch{\mfp@defaultopt\mfp@rhatch{\the\hatchspace}}%
+ \newdef\xhatch{\mfp@defaultopt\mfp@xhatch{\the\hatchspace}}%
+ \newlet\hatch\xhatch
+ \newdef\gradient{\mfp@rendi{axialgradient}}%
+ \newdef\areagradient{\mfp@rendi{areagradient}}%
+ \newdef\radialgradient{\mfp@rendi{radialgradient}}%
+ \newdef\gfill{\mfp@nullopt{\mfp@clroptrend{filled}}}%
+ \newdef\gclear{\mfp@rendmac{unfilled}}%
+ \newdef\gclip{\mfp@rendmac{Clip}}%
+ \newdef\reversepath{\mfp@addmac{reverse}}%
+ \newlet\reverse\reversepath
+ \newdef\xyswappath{\mfp@modmac{xyswappedpath}}%
+ \newdef\rotatepath{\mfp@modi{rotatedpath}}%
+ \newdef\shiftpath{\mfp@modi{shiftedpath}}%
+ \newdef\scalepath{\mfp@modi{scaledpath}}%
+ \newdef\xscalepath{\mfp@modi{xscaledpath}}%
+ \newdef\yscalepath{\mfp@modi{yscaledpath}}%
+ \newdef\xslantpath{\mfp@modi{xslantedpath}}%
+ \newlet\slantpath\xslantpath
+ \newdef\yslantpath{\mfp@modi{yslantedpath}}%
+ \newdef\reflectpath{\mfp@modi{reflectedpath}}%
+ \newdef\transformpath{\mfp@modi{transformedpath}}%
+ \newdef\parallelpath{\mfp@modi{parapath}}%
+ \newdef\randomizepath{\mfp@modi{randompath}}%
+ \newdef\randomlines{\mfp@modi{randomlines}}%
+ \newdef\interpolatepath{\mfp@modi{interpolatedpath}}%
+ \newdef\arccomplement{\mfp@modmac{arccomplement}}%
+ \newdef\arrowhead{\mfp@ifstar\mfp@arrowhead\mfp@T\mfp@F}%
+ \def\arrow{\mfp@ifstar\mfp@arrow{x}{}}%
+ \newdef\arrowtail##1{\mfp@arr 0{tailpath (##1)}}%
+ \newdef\arrowmid##1{\mfp@arr{0.5}{midpath (##1)}}%
+ \newdef\coords{\mfsrc{\@nl bcoords\@nl}}%
+ \newdef\endcoords{\mfsrc{\@nl ecoords\@nl}}%
+ \newdef\applyT##1{\mfsrc{\@nl hide(apply_t (##1))}}%
+ \def\rotate##1{\applyT{rotated ##1}}%
+ \newdef\rotatearound##1##2{%
+ \applyT{rotatedaround (##1, ##2)}}%
+ \newdef\turn{\mfp@defaultopt\mfp@turn{(0,0)}}%
+ \newdef\reflectabout##1##2{\applyT{reflectedabout (##1, ##2)}}%
+ \let\mirror\reflectabout
+ \newdef\shift##1{\applyT{shifted ##1}}% pair.
+ \def\scale##1{\applyT{scaled ##1}}% same scaling
+ \newdef\xscale##1{\applyT{xscaled ##1}}%
+ \newdef\yscale##1{\applyT{yscaled ##1}}%
+ \newdef\zscale##1{\applyT{zscaled ##1}}%
+ \newdef\xslant##1{\applyT{xslant ##1}}%
+ \newdef\yslant##1{\applyT{yslant ##1}}%
+ \newdef\zslant##1{\applyT{zslant ##1}}%
+ \newdef\boost##1{\applyT{boost ##1}}%
+ \newdef\xyswap{\applyT{xyswap}}%
+ \newdef\xaxis{\mfp@defaultopt{\mfp@simple{xaxis}}{\the\axisheadlen}}%
+ \newdef\yaxis{\mfp@defaultopt{\mfp@simple{yaxis}}{\the\axisheadlen}}%
+ \newdef\axes{\mfp@defaultopt {\mfp@simple{axes}}{\the\axisheadlen}}%
+ \newdef\axis{\mfp@nullopt\mfp@axis}%
+ \newdef\axisline##1{\mfp@figmac{axisline.##1}}%
+ \newdef\doaxes{\mfp@nullopt\mfp@doaxes}%
+ \newdef\border{\mfp@figmac{borderrect}}%
+ \newdef\axismarks##1{\mfp@defaultopt{\mfp@marks{##1}}{\the\hashlen}}%
+ \newdef\xmarks{\axismarks x}%
+ \newdef\ymarks{\axismarks y}%
+ \newdef\lmarks{\axismarks l}%
+ \newdef\bmarks{\axismarks b}%
+ \newdef\rmarks{\axismarks r}%
+ \newdef\tmarks{\axismarks t}%
+ \def\grid{\mfp@defaultopt{\mfp@simplei{vargrid}}{\the\griddotsize}}%
+ \newlet\gridpoints\grid \newlet\lattice\grid
+ \newdef\gridlines{\mfp@simple{gridlines}}%
+ \newdef\vgridlines{\mfp@simple{vgridlines}}%
+ \newdef\hgridlines{\mfp@simple{hgridlines}}%
+ \newdef\plrgrid{\mfp@simple{polargrid}}%
+ \newdef\plrgridpoints{%
+ \mfp@defaultopt{\mfp@simplei{polargridpoints}}{\the\griddotsize}}%
+ \newdef\gridarcs{\mfp@simple{gridarcs}}%
+ \newdef\gridrays{\mfp@simple{gridrays}}%
+ \newdef\plrpatch{\mfp@simple{polarpatch}}%
+ \newdef\vectorfield{%
+ \mfp@defaultopt{\mfp@vectorfield{}}{\the\headlen}}%
+ \newdef\plrvectorfield{%
+ \mfp@defaultopt{\mfp@vectorfield{plr}}{\the\headlen}}%
+ \newdef\point{\mfp@defaultopt\mfp@point{\the\pointsize}}%
+ \newdef\plotsymbol{\mfp@defaultopt\mfp@plotsymbol{\the\pointsize}}%
+ \newdef\plottext{\begingroup\mfp@resetwhitespace\mp@mksharpother
+ \mfp@defaultopt\mfp@plottext{cc}}%
+ \newdef\tile{\mfp@simple{tile}}%
+ \newdef\endtile{\mfcmd{\@nl endtile}}%
+ \newdef\patharr##1{\begingroup
+ \mfsrc{hide(numeric ##1; path ##1[]; ##1 = 0)}%
+ \def\mfp@storepath{\mfsrc{\@nl store (##1[incr ##1])}}%
+ \setrender{}}%
+ \newdef\endpatharr{\endgroup}%
+ \newdef\connect{\mfp@figmac{begingroup; save mfpicnexus}%
+ \patharr{mfpicnexus}}%
+ \newdef\endconnect{\endpatharr
+ \mfcmd{\@nl mkpoly (\mfp@F, mfpicnexus)\@nl endgroup}%
+ \mfp@checklatexenv{connect}{\aftergroup\@mfpstarttrue}{}}%
+ \newlet\piechart\mfppiechart
+ \newdef\piewedge{\mfp@defaultopt\mfp@piewedge{d}}%
+ \newlet\barchart\mfpbarchart
+ \newlet\bargraph\barchart
+ \newlet\histogram\barchart
+ \newlet\gantt\barchart
+ \newdef\chartbar##1{\mfp@figmac{chartbar[##1]}}%
+ \newlet\graphbar\chartbar
+ \newlet\histobar\chartbar
+ \newlet\ganttbar\chartbar
+ \newdef\gbrace##1{\mfp@figmac{mkbrace(##1)}}%
+}% end \mfp@grafmacs
+\def\mfp@abc#1#2#3#4#5#6#7#8/{#6#3#1#2#6#7#6#4#5}%
+\@namedef{\mfp@abc STAGGER LEE/}{%
+\mfpic[20]{-2}{2}{-3}{3}%
+ \tile{peter, 1pt, 10, 10, false}%
+ \penwd{1pt}%
+ \draw[rgb(1,0,0)]\lines{(0,0), (5,5), (10,0)}%
+ \pointcolor{rgb(0,.8,0)}%
+ \point[3pt]{(2.5,7.5)}%
+ \endtile
+ \draw\tess{peter}\gfill[rgb(1,1,0)]\ellipse{(0,0),2,3}%
+\endmfpic}%
+\newdef\mfppiechart{\mfp@defaultopt\mfp@piechart{c}}%
+\newdef\mfpbarchart{\mfp@defaultopt\mfp@barchart{0,1,1}}%
+\newlet\mfpbargraph\mfpbarchart
+\newlet\mfphistogram\mfpbarchart
+\newlet\mfpgantt\mfpbarchart
+\newdef\mfp@arc{\mfp@switchtrue\mfp@defaultopt\mfp@arccircle{s}}%
+\newdef\arc@or@circle{\ifmfp@switch arc\else circle\fi}%
+\newdef\mfp@arccircle#1#2{%
+ \@ifundefined{mfp@arc@#1}%
+ {\Mfpic@warn{Invalid option; ignoring \mfp@b\arc@or@circle\space
+ command.}%
+ \mfp@figmac{fallbackpath(\ifmfp@switch\mfp@F\else\mfp@T\fi) (#2)}}%
+ {\mfp@figmac{\arc@or@circle\@nameuse{mfp@arc@#1} (#2)}}}%
+\newdef\mfp@ellipse#1#2{\mfp@figmac{ellipse (#2, #1)}}%
+\newdef\mfp@pshcircle#1#2{\mfp@figmac{pshcircle (#1, #2)}}%
+\newdef\mfp@hypergeodesic#1#2{\mfp@figmac{#1geodesic (#2)}}%
+\newdef\mfp@curve#1#2{\mfp@nullopt{\mfp@@curve{#1}{#2}}}%
+\newdef\mfp@@curve#1#2#3{%
+ \mfp@listmac{\mfp@ifempty{#3}{#1}{t#1 (#3)} (#2)}}%
+\newdef\mfp@fcncurve#1{%
+ \mfp@listmac{\mfp@ifempty{#1}{fcncurve}{functioncurve (#1)}}}%
+\newdef\mfp@fcn#1#2{%
+ \mfp@defaultopt{\mfp@dotension{\mfp@@fcn{#1}}}{#2}}%
+\newdef\mfp@@fcn#1#2#3{%
+ \mfp@figmac{\mfp@t#1 (\mfp@sval) (#2) (#3)}}%
+\newdef\mfp@btwn#1{%
+ \mfp@defaultopt{\mfp@dotension{\mfp@@btwn{#1}}}p}%
+\newdef\mfp@@btwn#1#2#3#4{%
+ \mfp@figmac{\mfp@t#1 (\mfp@sval) (#2) (#3) (#4)}}%
+\newdef\mfp@dotension#1#2{\mfp@@dotension#2\mfp@end#1}%
+\newdef\mfp@@dotension#1#2\mfp@end{\def\mfp@t{}%
+ \if p#1\relax \let\mfp@sval\mfp@F
+ \else \let\mfp@sval\mfp@T
+ \mfp@ifexist{#2}{\def\mfp@t{t}\edef\mfp@sval{\mfp@sval, #2}}%
+ \fi}%
+\newdef\mfp@plotdata#1{\mfp@processfile{\mfp@doplots{#1}}}%
+\newdef\mfp@doplots#1{\mfp@setstyle
+ \advance\mfp@linetype1 \mfp@figmacbase
+ \mfp@@datafile{#1}\mfp@ifenddata{}{\mfp@doplots{#1}}}%
+\newdef\mfp@ifenddata{%
+ \ifeof\mfp@data \@xp\@firstoftwo
+ \else \mfp@skipcomments
+ \ifx\mfp@temp\mfp@par \@XP\@firstoftwo
+ \else \@XP\@secondoftwo
+ \fi
+ \fi}%
+\newdef\mfp@datafile#1{%
+ \mfp@figmacbase\mfp@processfile{\mfp@@datafile{#1}}}%
+\newdef\mfp@@datafile#1{%
+ \mfp@ifempty{#1}%
+ {\mfp@dodatafile\mfp@smoothness\mfp@tension}%
+ {\mfp@dodatafile#1}\mfp@end}%
+\newdef\mfp@dodatafile#1#2\mfp@end{%
+ \mfsrc{%
+ \if s#1 \mfp@ifempty{#2}{curve }{tcurve (#2) }%
+ \else polyline
+ \fi (\mfp@F)}\mfp@rwdata}%
+\newdef\mfp@image#1#2{\mfsrc{\@nl makeimage (#2, #1)}}%
+\newdef\mfp@getdimens#1,#2,#3\mfp@end{%
+ \mfp@scratch \@ifmtarg{#1}{\z@}{#1}\relax
+ \edef\mfp@thedimens{\the\mfp@scratch}%
+ \@ifmtarg{#3}{}{\mfp@scratch \@ifmtarg{#2}{\z@}{#2}\relax}%
+ \edef\mfp@thedimens{\mfp@thedimens,\the\mfp@scratch}}%
+\newdef\mfp@doubledraw#1{%
+ \mfp@nullopt{\mfp@clroptrendi{doubledraw}{#1}}}%
+\newdef\mfp@wiggle#1#2{\mfp@rendi{#1 (#2)}}%
+\newdef\mfp@rendi#1#2{\mfp@rendmac{#1 (#2)}}%
+\newdef\mfp@rendii#1#2#3{\mfp@rendmac{#1 (#3, #2)}}%
+\newdef\mfp@optrendi#1{\mfp@defaultopt{\mfp@rendi{#1}}}%
+\newdef\mfp@optrendii#1{\mfp@defaultopt{\mfp@rendii{#1}}}%
+\newdef\mfp@modi#1#2{\mfp@modmac{#1 (#2)}}%
+\newdef\mfp@listi#1#2{\mfp@listmac{#1 (#2)}}%
+\newdef\mfp@clropt#1#2{\mfp@ifempty{#1}{#2}{\mfp@C#2 (#1)}}%
+\newdef\mfp@clroptrend#1#2{\mfp@rendmac{\mfp@clropt{#2}{#1}}}%
+\newdef\mfp@clroptrendi#1#2#3{\mfp@rendmac{\mfp@clropt{#3}{#1} (#2)}}%
+\newdef\mfp@simple#1#2{\mfcmd{\@nl #1 (#2)}}%
+\newdef\mfp@simplei#1#2#3{\mfcmd{\@nl #1 (#2, #3)}}%
+\newdef\mfp@close#1#2{\mfp@modmac{#1closed\mfp@ifexist{#2}{t (#2)}}}%
+\newdef\mfp@thatch#1{\mfp@nullopt{\mfp@clroptrendi{thatch}{#1}}}%
+\newdef\mfp@lhatch#1{\mfp@thatch{#1,-45}}%
+\newdef\mfp@rhatch#1{\mfp@thatch{#1,45}}%
+\newdef\mfp@xhatch#1{\mfp@nullopt{\mfp@clroptrendi{xhatch}{#1}}}%
+\newdef\mfp@arrowhead#1#2{\mfp@arr 0{Gheadpath (#1) (#2)}}%
+\newdef\mfp@arrow#1{\mfp@arr 0{headpath#1}}%
+\newdef\mfp@arr#1#2{\mfp@arr@c{}\mfp@arr@l{\the\headlen}%
+ \mfp@arr@b{#1}\edef\mfp@hcommand{#2}\mfp@arr@r{0}\mfp@@arr}%
+\newdef\mfp@@arr{\@ifnextchar[{\mfp@arropt}{\mfp@doarrow}}%
+\newdef\mfp@arropt[#1]{%
+ \mfp@ifexist{#1}{\mfp@@arropt#1\mfp@end}\mfp@@arr}%
+\newdef\mfp@@arropt#1#2\mfp@end{%
+ \mfp@ifempty{#2}%
+ {\Mfpic@warn{Arrow option #1 has no value\on@line; %
+ it will be ignored.}}%
+ {\@ifundefined{mfp@arr@#1}%
+ {\Mfpic@warn{Arrow option #1 invalid \on@line; %
+ it will be ignored}}%
+ {\@nameuse{mfp@arr@#1}{#2}}%
+ }}%
+\newdef\mfp@doarrow{%
+ \mfp@addmac{\mfp@clropt{\mfp@hcolour}{\mfp@hcommand} (\mfp@hlength, %
+ \mfp@hrotate, \mfp@hlocate)}}%
+\newdef\mfp@turn#1#2{\rotatearound{#1}{#2}}%
+\newdef\mfp@axis#1#2{\mfp@getaxis#2{(none)}\mfp@end\axis
+ \mfp@addmac{headpath (\mfp@emptysub{#1}{\mfp@defaultheadlen}, 0, 0)}%
+ \axisline{\mfp@axisletter}}%
+\newdef\mfp@doaxes#1#2{%
+ \def\mfp@@axis##1{\mfp@axis{#1}{##1}\mfp@@doaxis}%
+ \mfp@@doaxis#2\mfp@end}%
+\newdef\mfp@@doaxis{\mfp@ifend{}\mfp@@axis}%
+\newdef\mfp@marks#1#2{\mfsrc{\@nl #1marks (#2)}\mfp@writedata}%
+\newdef\mfp@vectorfield#1#2#3#4#5{%
+ \mfcmd{#1vectorfield (#2, #3) (#4) (#5)}}%
+\newdef\mfp@point#1{%
+ \mfsrc{\@nl pointd (#1, \ifpointfill\mfp@T\else\mfp@F\fi)}%
+ \mfp@writedata}%
+\newdef\mfp@plotsymbol#1#2{%
+ \mfsrc{\@nl plotsymbol (#2, #1)}\mfp@writedata}%
+\newdef\mfp@plottext#1#2#3{\tlabeljustify{#1}%
+ \def\tl@points{#3}\mfp@toks{#2}\mfp@thelabel\endgroup}%
+\newdef\mfp@piechart#1{\mfp@@piechart#1\mfp@end}%
+\newdef\mfp@@piechart#1#2\mfp@end#3{% #3 = center,radius
+ \mfsrc{\@nl piechart(\if a#1 \else-\fi1, %
+ \mfp@emptysub{#2}{90}, #3)}\mfp@writedata}%
+\newdef\mfp@piewedge#1{\mfp@@piewedge#1\mfp@end}%
+\newdef\mfp@@piewedge#1#2\mfp@end#3{% #3=number
+ \mfp@figmac{(piewedge[#3]%
+ \mfp@ifexist{#2}%
+ {\if #1x shifted (#2*piedirection[#3])%
+ \else\if #1s shifted (#2)%
+ \else\if #1m shifted (#2 - piecenter)%
+ \fi\fi\fi})}}%
+\newdef\mfp@barchart#1#2{%
+ \mfsrc{\@nl barchart (#1, \if h#2\mfp@F\else\mfp@T\fi)}%
+ \mfp@writedata}%
+\newdef\everymfpic{\afterassignment\@everymfpic\mfp@toks}%
+\newdef\everyendmfpic{\afterassignment\@everyendmfpic\mfp@toks}%
+\newdef\@everymfpic{\edef\every@mfpic{\the\mfp@toks}}%
+\newdef\@everyendmfpic{\edef\every@endmfpic{\the\mfp@toks}}%
+\everymfpic{}\everyendmfpic{}%
+\newdef\mfpic{\mfp@defaultopt\@mfpicA{1}}%
+\newdef\@mfpicA#1{\mfp@defaultopt{\@mfpic{#1}}{#1}}%
+\newdef\@mfpic#1#2#3#4#5#6{%
+ \save@mfpicdimens
+ \begingroup % ended near end of \endmfpic
+ \@mfpicunit\mfpicunit
+ \mfp@safe@activestrue
+ \mfp@ifopengraphsfile{}%
+ {\ifmfp@nowrite\else \mfp@nooutput@error\mfpic
+ \def\mfp@src##1##2{\endgroup}%
+ \fi}%
+ \mfp@DBlog{Starting mfpic \number\mfp@count \on@line.}%
+ \@xp\let\@xp\@tcurr\the\font
+ \let\ifin@mfpicenv\iftrue
+ \let\par\@empty
+ \nullfont
+ \mfp@grafmacs
+ \mfp@additions
+ \edef\xfactor{#1}\edef\yfactor{#2}%
+ \edef\xmin{#3}\edef\xmax{#4}\edef\ymin{#5}\edef\ymax{#6}%
+ \mfp@setconv
+ \mfp@inittlabels
+ \@xconv\xmax\@graphright
+ \@yconv\ymax\@graphtop
+ \@graphleft 0pt
+ \@graphbot 0pt
+ \mfsrc{\@nl \mfp@p\mfp@d\mfp@d<\number\mfp@count>\@nl
+ unitlen := \the\@mfpicunit\mfp@s;\@nl
+ xscale := #1; yscale := #2;\@nl
+ bounds (#3, #4, #5, #6);\@nl
+ \@nl
+ beginmfpic(\number\mfp@count); \mfp@p\space\mfp@lineno.
+ \mfp@ifmpost
+ {\@nl verbatimtex \relax
+ \MFPbegingroup\font\noexpand\MFPcfont=\fontname\@tcurr\relax
+ etex;}{}}%
+ \newdef\tlabel{\mfp@nullopt\mfp@label}%
+ \newdef\startbacktext{\let\mfp@restoreOL\@empty
+ \mfp@ifmpost
+ {\ifmfp@overlabels
+ \let\mfp@restoreOL\overlaylabels\nooverlaylabels
+ \fi \setmfboolean{underlaylabels}{\mfp@T}}{}%
+ \setbox\@wholegraph \box\@alltlabels
+ \setbox\@alltlabels \vbox{\hbox{}}}%
+ \newdef\stopbacktext{%
+ \setbox\@backtext \box\@alltlabels
+ \setbox\@alltlabels\box\@wholegraph
+ \mfp@ifmpost{\setmfboolean{underlaylabels}{\mfp@F}}{}%
+ \mfp@restoreOL}%
+ \newdef\tlabelrect{\mfp@labelpath{rect}{0}}%
+ \newdef\tlabeloval{\mfp@labelpath{oval}{1}}%
+ \newdef\tlabelellipse{\mfp@labelpath{ellipse}{1}}%
+ \newdef\tlabelcircle{%
+ \mfp@iftoken*{\tlabelellipse*[1]}{\tlabelellipse[1]}}%
+ \newdef\tlabels{\begingroup
+ \mfp@resetwhitespace\mp@mksharpother \mfp@labels}%
+ \newlet\axislabels\mfp@axislabels
+ \let\mfp@docaption\@empty
+ \newdef\tcaption{\mfp@defaultopt\mfp@caption{1.2,1.0}}%
+ \every@mfpic}% End of \@mfpic
+\newdef\mfp@setconv{%
+ \def\@xconv##1##2{% ##1 = coord. ##2 = dimension register or fdim
+ {\mfp@scratch=##1\@mfpicunit
+ \advance\mfp@scratch by -\xmin\@mfpicunit
+ \mfp@scratch=\xfactor\mfp@scratch
+ \global ##2=\mfp@scratch}}%
+ \def\@yconv##1##2{% ditto
+ {\mfp@scratch=##1\@mfpicunit
+ \advance\mfp@scratch by -\ymin\@mfpicunit
+ \mfp@scratch=\yfactor\mfp@scratch
+ \global ##2=\mfp@scratch}}}%
+\newdef\mfp@inittlabels{%
+ \setbox\@alltlabels\vbox{\hbox{}}%
+ \setbox\@backtext\vbox{\hbox{}}%
+ \@tlabelsbot \maxdimen
+ \@tlabelstop -\maxdimen
+ \@tlabelsleft \maxdimen}%
+\newdef\mfp@label#1{\begingroup\mfp@resetwhitespace\mp@mksharpother
+ \tlabeljustify{#1}\@ifnextchar({\mfp@label@}{\mfp@label@@}}%
+\newdef\mfp@label@(#1,#2){\mfp@label@@{(#1,#2)}}%
+\newdef\mfp@label@@#1#2{\def\tl@points{#1}\mfp@toks{#2}\mfp@thelabel
+ \endgroup\extra@endtlabel}%
+\newdef\mfp@thelabel{\@ifmplabels\mp@tlabel\tex@tlabel}%
+\newdef\mfp@btex#1{btex \noexpand\MFPtext{#1} etex}%
+\newdef\mfp@setMPpos{%
+ \edef\mfp@MPpos{%
+ \ifcase\tl@hpos .5\or 1\else 0\fi, % horizontal
+ \ifcase\tl@vpos0\or .5\or 1\else 0\fi, % vertical
+ \ifnum \tl@vpos<0 \mfp@T\else\mfp@F\fi, % true=Baseline
+ \mfp@emptysub{\tl@rot}{0}}}%
+\newdef\mp@tlabel{\mfp@setMPpos
+ \mfcmd{\@nl newgblabel(\mfp@MPpos)(\mfp@btex{\the\mfp@toks})\@nl
+ (\tl@points)}}%
+\newdef\set@textbox#1{%
+ \setbox\@textbox\vbox{\def\\{\cr}\mfp@restorepar
+ \mfp@safe@activesfalse\@tcurr\every@tlabel
+ \halign{##\hfil\cr#1\crcr}}}%
+\newdef\tex@tlabel{\@xp\@textlabel\tl@points\mfp@end}%
+\newdef\@textlabel{\mfp@ifendorcomma{}\@textlabel\@@textlabel}%
+\newdef\@@textlabel(#1,#2){\tex@@tlabel{#1}{#2}\@textlabel}%
+\newdef\tex@@tlabel#1#2{%
+ \set@textbox{\the\mfp@toks}%
+ \mfp@scratch\tb@ht \advance\mfp@scratch\tb@dp
+ \tb@totalht\mfp@scratch
+ \@xconv{#1}\mfp@scratch
+ \begingroup
+ \ifcase\tl@hpos \advance\mfp@scratch -0.5\tb@wd % center
+ \or \advance\mfp@scratch -\tb@wd % right
+ \advance\mfp@scratch -\tlabel@sep
+ \else \advance\mfp@scratch \tlabel@sep % left (default)
+ \fi
+ \advance\mfp@scratch \tlabel@hadj
+ \ifdim \mfp@scratch<\@tlabelsleft
+ \@tlabelsleft\mfp@scratch
+ \fi
+ \tb@moveright\mfp@scratch
+ \endgroup
+ \@yconv{#2}\mfp@scratch
+ \begingroup
+ \ifcase\tl@vpos \advance\mfp@scratch \tb@totalht
+ \advance\mfp@scratch \tlabel@sep % bottom
+ \or \advance\mfp@scratch 0.5\tb@totalht % center
+ \or \advance\mfp@scratch -\tlabel@sep % top
+ \else \advance\mfp@scratch \tb@ht % baseline (default)
+ \fi
+ \advance\mfp@scratch \tlabel@vadj
+ \ifdim \mfp@scratch>\@tlabelstop
+ \@tlabelstop\mfp@scratch
+ \fi
+ \tb@raise\mfp@scratch
+ \endgroup
+ \begingroup
+ \ifcase\tl@vpos \advance\mfp@scratch \tlabel@sep % bottom
+ \or \advance\mfp@scratch -0.5\tb@totalht % center
+ \or \advance\mfp@scratch -\tb@totalht
+ \advance\mfp@scratch -\tlabel@sep % top
+ \else \advance\mfp@scratch -\tb@dp % baseline (default)
+ \fi
+ \advance\mfp@scratch \tlabel@vadj
+ \ifdim \mfp@scratch<\@tlabelsbot
+ \@tlabelsbot\mfp@scratch
+ \fi
+ \endgroup
+ \global \setbox\@alltlabels
+ \vtop{\unvbox\@alltlabels
+ \vbox to 0pt{\kern-\tb@raise
+ \hbox{\kern\tb@moveright\box\@textbox}\vss}}%
+}% End \tex@@tlabel
+\newdef\mfp@labels#1{\let\extra@endtlabel\mfp@dolabel
+ \mfp@dolabel#1\mfp@end}%
+\newdef\mfp@dolabel{\mfp@ifend\endgroup\tlabel}%
+\newdef\mfp@labelpath#1#2{\mfp@figmacbase
+ \begingroup % ended in \tlabelpath@
+ \def\mfp@name{#1}\def\mfp@param{#2}%
+ \mfp@ifstar\mfp@tlpath\mfp@switchtrue\mfp@switchfalse}%
+\newdef\mfp@tlpath#1{#1\mfp@defaultopt\mfp@@tlpath\mfp@param}%
+\newdef\mfp@@tlpath#1{\edef\mfp@param{#1}%
+ \mfp@defaultopt\mfp@tlpath@{\tlpath@v\tlpath@h\tlpath@r}}%
+\newdef\mfp@tlpath@#1{\mfp@resetwhitespace\mp@mksharpother
+ \tlabeljustify{#1}\@ifnextchar({\@tlabelpath}{\@@tlabelpath}}%
+\newdef\@tlabelpath(#1,#2){\@@tlabelpath{(#1,#2)}}%
+\newdef\@@tlabelpath#1#2{%
+ \def\tl@points{#1}\mfp@toks{#2}\tlabelpath@}%
+\newdef\tlabelpath@{\@ifmplabels{}{\measure@textbox{\the\mfp@toks}}%
+ \mfp@setMPpos
+ \mfcmd{text\mfp@name x (\mfp@MPpos)\@nl
+ (\@ifmplabels{origin, \mfp@btex{\the\mfp@toks}}{\tb@ll, \tb@ur}, %
+ \mfp@param) (\tl@points)}%
+ \ifmfp@switch\else \mfp@thelabel\fi \endgroup}%
+\newdef\measure@textbox#1{\set@textbox{#1}%
+ \mfp@scratch-\tb@dp
+ \edef\tb@ll{(0, \the\mfp@scratch)}%
+ \edef\tb@ur{(\the\tb@wd, \the\tb@ht)}}%
+\newdef\mfp@axislabels#1{%
+ \begingroup % ended in \mfp@(@)doaxislabel
+ \mfp@resetwhitespace
+ \tl@vpos1 \tl@hpos0
+ \let\mfp@xcoord\@firstofone \let\mfp@ycoord\@firstofone
+ \mfp@getaxis#1\relax\mfp@end\axislabels
+ \ifcase\mfp@axisnum\relax
+ \tl@vpos2 \def\mfp@ycoord{0}\or
+ \tl@hpos1 \def\mfp@xcoord{0}\or
+ \tl@hpos1\edef\mfp@xcoord{\mfp@lshift}%
+ \mfpaddto\mfp@xcoord\xmin\or
+ \tl@vpos2\edef\mfp@ycoord{\mfp@bshift}%
+ \mfpaddto\mfp@ycoord\ymin\or
+ \tl@hpos-1 \edef\mfp@xcoord{-\mfp@rshift}%
+ \mfpaddto\mfp@xcoord\xmax\or
+ \tl@vpos0 \edef\mfp@ycoord{-\mfp@tshift}%
+ \mfpaddto\mfp@ycoord\ymax
+ \fi
+ \ifx\@firstofone\mfp@xcoord
+ \edef\mfp@ycoord##1{\mfp@ycoord}%
+ \else
+ \edef\mfp@xcoord##1{\mfp@xcoord}%
+ \fi \mp@mksharpother\mfp@nullopt\mfp@@axislabels}%
+\newdef\mfp@@axislabels#1#2{%
+ \tlabeljustify{#1}\mfp@doaxislabel#2,\mfp@end}%
+\newdef\mfp@doaxislabel{%
+ \mfp@ifendorcomma\endgroup\mfp@doaxislabel\mfp@@doaxislabel}%
+\newdef\mfp@@doaxislabel#1{\mfp@toks{#1}%
+ \mfp@ifendorcomma\endgroup\mfp@doaxislabel\mfp@mkaxislabel}%
+\newdef\mfp@mkaxislabel#1,{%
+ \@ifmtarg{#1}{}%
+ {\edef\tl@points{(\mfp@xcoord{#1},\mfp@ycoord{#1})}\mfp@thelabel}%
+ \mfp@doaxislabel}%
+\newdef\mfp@caption#1{\begingroup\mfp@resetwhitespace
+ \mfp@@caption#1\mfp@end}%
+\long\def\mfp@@caption#1,#2\mfp@end#3{\endgroup
+ \def\mfp@docaption{%
+ \setbox\@textbox
+ \hbox{\def\\{\hskip\@M\p@\let\\\relax}\mfp@restorepar
+ \mfp@safe@activesfalse\@tcurr#3}%
+ \mfp@scratch\wd\@wholegraph
+ \ifdim\tb@wd>#1\mfp@scratch
+ \setbox\@textbox
+ \hbox{%
+ \vbox{%
+ \hsize#2\mfp@scratch \mfp@restorepar
+ \leftskip0pt \rightskip0pt\relax
+ \mfp@capsettings
+ \mfp@safe@activesfalse
+ \noindent\@tcurr #3%
+ }% End vbox.
+ }% End hbox.
+ \fi
+ \ifdim \mfp@scratch<\tb@wd \mfp@scratch\tb@wd \fi
+ \global\setbox\@wholegraph
+ \vbox{\hbox to \mfp@scratch{\hss\box\@wholegraph\hss}%
+ \nointerlineskip \vskip\mfpiccaptionskip
+ \hbox to \mfp@scratch{\hss\box\@textbox\hss}}% End vbox.
+ }% End \mfp@docaption.
+}% End \mfp@@caption.
+\def\mfp@adjustdim#1#2#3#4{%
+ \mfp@scratch#1\relax \advance\mfp@scratch-#4 bp
+ \ifdim\mfp@scratch#2#3\relax #3\mfp@scratch \fi
+ #1\mfp@scratch}%
+\mfp@DBlog{Definition of closure of mfpic environment.}%
+\newdef\endmfpic{\every@endmfpic
+ \mfsrc{%
+ \mfp@ifmpost{\@nl verbatimtex \relax\MFPendgroup\space etex;}{}\@nl
+ endmfpic; \mfp@p\space(\number\mfp@count) \mfp@lineno.\@nl
+ \mfp@p\mfp@d\mfp@d\mfp@d\@nl}%
+ \ifmfpicdebug\wlog{}\wlog{Mfpic: ENTERED endmfpic.}\wlog{}\fi
+ \ifmfp@noship \else
+ \global\setbox\@wholegraph
+ \vbox{%
+ \ifmfpicdraft
+ \vbox to \@graphtop{\vss
+ \hbox to \@graphright{%
+ \kern2pt \mfpdraftfont\#\number\mfp@count\hss}%
+ \kern2pt}%
+ \else
+ \mfp@ifmpost{\vbox}{\vbox to \@graphtop}%
+ {\vss
+ \edef\@graphfilename{%
+ \setfilename\mfp@filename{\number\mfp@count}}%
+ \mfp@ifmpost
+ {\IfFileExists{\@graphfilename}{}%
+ {\Mfpic@msg{No graph file: \@graphfilename\space.}%
+ \let\@setmfpicgraphic\nofile@setmfpgraphic}%
+ \hbox}%
+ {\hbox to \@graphright}%
+ {\@xp\@setmfpicgraphic\@xp{\@graphfilename}\hss}%
+ \kern0pt
+ }% End vbox
+ \fi
+ }%% End \setbox\@wholegraph \vbox
+ \mfp@ifmpost
+ {\@graphright\wd\@wholegraph
+ \@graphtop\ht\@wholegraph}{}%
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of wholegraph before labels %
+ are added, and before truebbox adjustments:}%
+ \wlog{Mfpic: graphleft = \the\@graphleft}%
+ \wlog{Mfpic: graphright = \the\@graphright}%
+ \wlog{Mfpic: graphtop = \the\@graphtop}%
+ \wlog{Mfpic: graphbot = \the\@graphbot}%
+ \wlog{Mfpic: graphwd = \the\wd\@wholegraph}%
+ \wlog{Mfpic: graphht = \the\ht\@wholegraph}%
+ \wlog{Mfpic: graphdp = \the\dp\@wholegraph}%
+ \wlog{}%
+ \fi
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of alltlabels, before %
+ truebbox adjustments:}%
+ \mfp@scratch\mfpicllx bp\relax
+ \wlog{Mfpic: mfpicllx = \the\mfp@scratch}%
+ \mfp@scratch\mfpiclly bp\relax
+ \wlog{Mfpic: mfpiclly = \the\mfp@scratch}%
+ \wlog{Mfpic: tlabelsleft = \the\@tlabelsleft}%
+ \wlog{Mfpic: tlabelstop = \the\@tlabelstop}%
+ \wlog{Mfpic: tlabelsbot = \the\@tlabelsbot}%
+ \wlog{}%
+ \fi
+ \ifdim\@tlabelsleft < \maxdimen
+ \setbox\@alltlabels\vtop to 0pt{%
+ \kern \mfpiclly bp
+ \moveleft \mfpicllx bp \box\@alltlabels\vss}%
+ \setbox\@backtext \vtop to 0pt{%
+ \kern \mfpiclly bp
+ \moveleft \mfpicllx bp \box\@backtext \vss}%
+ \mfp@adjustdim\@tlabelsleft <\@graphleft \mfpicllx
+ \mfp@adjustdim\@tlabelstop >\@graphtop \mfpiclly
+ \mfp@adjustdim\@tlabelsbot <\@graphbot \mfpiclly
+ \ifmfpicdraft\else
+ \setbox\@wholegraph
+ \vtop{\offinterlineskip
+ \box\@backtext\kern-\ht\@wholegraph
+ \unvbox\@wholegraph\box\@alltlabels}%
+ \fi
+ \fi
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of alltlabels after %
+ truebbox adjustments:}%
+ \wlog{Mfpic: tlabelsleft = \the\@tlabelsleft}%
+ \wlog{Mfpic: tlabelstop = \the\@tlabelstop}%
+ \wlog{Mfpic: tlabelsbot = \the\@tlabelsbot}%
+ \wlog{}%
+ \fi
+ \mfp@scratch\@graphtop
+ \advance\mfp@scratch by -\@graphbot
+ \global \setbox\@wholegraph
+ \vbox to \mfp@scratch{\vss
+ \hbox{\kern-\@graphleft\box\@wholegraph}%
+ \kern-\@graphbot}% End vbox.
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Dimensions of wholegraph after %
+ labels are added:}%
+ \wlog{Mfpic: graphleft = \the\@graphleft}%
+ \wlog{Mfpic: graphright = \the\@graphright}%
+ \wlog{Mfpic: graphtop = \the\@graphtop}%
+ \wlog{Mfpic: graphbot = \the\@graphbot}%
+ \wlog{Mfpic: graphwd = \the\wd\@wholegraph}%
+ \wlog{Mfpic: graphht = \the\ht\@wholegraph}%
+ \wlog{Mfpic: graphdp = \the\dp\@wholegraph}%
+ \wlog{}%
+ \fi
+ \mfp@docaption
+ \ifmfpicdebug
+ \wlog{Mfpic debug: Values after tcaption added:}%
+ \wlog{Mfpic: graphleft = \the\@graphleft}%
+ \wlog{Mfpic: graphright = \the\@graphright}%
+ \wlog{Mfpic: graphtop = \the\@graphtop}%
+ \wlog{Mfpic: graphbot = \the\@graphbot}%
+ \wlog{Mfpic: graphwd = \the\wd\@wholegraph}%
+ \wlog{Mfpic: graphht = \the\ht\@wholegraph}%
+ \wlog{Mfpic: graphdp = \the\dp\@wholegraph}%
+ \wlog{}%
+ \fi
+ \global\mfpicheight\ht\@wholegraph
+ \global\mfpicwidth\wd\@wholegraph
+ \ifmfpicdraft
+ \setbox\@wholegraph
+ \hbox{\@mfpframed{-\mfpframethickness}{\box\@wholegraph}}%
+ \fi
+ \global\setbox\@wholegraph\box\@wholegraph
+ \global \advance\mfp@count1
+ \fi % \ifmfp@noship
+ \endgroup % Begun near start of \@mfpic
+ \ifmfp@noship \else
+ \mfp@ifdefined\s@vemfpic
+ {\global\setbox\s@vemfpic\box\@wholegraph}%
+ {\leavevmode\box\@wholegraph}%
+ \global\let\s@vemfpic\UndEfInEd
+ \fi
+ \restore@mfpicdimens
+ \mfp@checklatexenv{mfpic}{\@ignoretrue}{}%
+ \global\let\in@mfpicenv\iffalse
+ \ignorespaces
+}% endmfpic
+\ifmfp@latex
+ \newdef\mfp@checklatexenv#1#2#3{%
+ \def\mfp@tempa{#1}\ifx\mfp@tempa\@currenvir #2\else #3\fi}%
+\else
+ \newdef\mfp@checklatexenv#1#2#3{#3}%
+\fi
+\ifmfp@latex
+ \newlet\newsavepic\newsavebox
+\else
+ \newdef\newsavepic#1{%
+ \mfp@ifdefined{#1}%
+ {\mfp@errmsg{Command \string #1 already defined}%
+ {You have used \newsavepic with an already defined or an^^J%
+ improper control sequence. Replace #1 with another name.^^J%
+ If you proceed, \newsavepic will be ignored.}}%
+ {\@nameuse{newbox}#1}}%
+\fi
+\newlet\newpic\newsavepic
+\newdef\savepic#1{\relax
+ \mfp@ifdefined{#1}{\gdef\s@vemfpic{#1}}%
+ {\mfp@errmsg{Box \string#1 undefined}%
+ {You tried to save a picture in a box which had not been^^J%
+ previously allocated. Use \newsavepic to allocate a box.}}}%
+\newdef\usepic#1{\leavevmode \copy#1\relax}%
+\newdef\mfpframed{\mfp@defaultopt\@mfpframed\mfpframesep}%
+\newdef\mfpframe{\mfp@defaultopt\@mfpframe\mfpframesep}%
+\newdef\@mfpframed#1#2{\@mfpframe{#1}#2\endmfpframe}%
+\newdef\@mfpframe#1{%
+ \leavevmode\hbox\bgroup
+ \mfpframesep#1\relax
+ \vrule width\mfpframethickness
+ \vtop\bgroup
+ \vbox\bgroup
+ \hrule height\mfpframethickness
+ \kern\mfpframesep
+ \hbox\bgroup \kern\mfpframesep \ignorespaces}%
+\newdef\endmfpframe{\unskip
+ \kern\mfpframesep
+ \egroup % end hbox
+ \egroup % end vbox
+ \kern\mfpframesep
+ \hrule height\mfpframethickness
+ \egroup % end vtop
+ \vrule width\mfpframethickness
+ \egroup}% end hbox
+\mfp@ifdefined\framed{}{\let\framed\mfpframed}%
+\def\mfpverbtex{\futurelet\mfp@next\@mfpverbtex}%
+\def\@mfpverbtex{%
+ \begingroup
+ \@makeother\#\@makeother\%\mfp@keeplines
+ \afterassignment\mfp@writetex\global\mfp@toks}%
+\newif\ifmfp@verbtex
+\def\mfp@writetex{%
+ \mfp@ifopengraphsfile
+ {\mfp@ifmpost
+ {\mfcmd{verbatimtex\@nl\the\mfp@toks\@nl\mfp@p\@nl etex}}%
+ {\mfp@noMP@error\mfpverbtex}%
+ \global\mfp@verbtexfalse\global\mfp@verbtex{}}%
+ {\edef\mfp@tempa{\the\mfp@verbtex\the\mfp@toks}%
+ \global\mfp@verbtex\@xp{\mfp@tempa}%
+ \global\mfp@verbtextrue}%
+ \endgroup
+}%
+\mfpicnumber{1}%
+\mfp@ifdefined\mfpdraftfont{}{\newdef\mfpdraftfont{\tt}}%
+\mfp@DBlog{Punctuation, etc., will revert to old catcodes now.}%
+\let\+\mfpsaveplus
+\mfp@restoreALL%
+\InputIfFileExists{mfpic.usr}{}{}%
+\endinput
+%%
+%% End of file `mfpic.tex'.
diff --git a/graphics/mfpic/tex/mfpicdef.tex b/graphics/mfpic/tex/mfpicdef.tex
new file mode 100644
index 0000000000..96d7d8d8cc
--- /dev/null
+++ b/graphics/mfpic/tex/mfpicdef.tex
@@ -0,0 +1,39 @@
+%%
+%% This is file `mfpicdef.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% mfpic.dtx (with options: `defs')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2002--2012, Daniel H. Luecking
+%%
+%% Mfpic may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3c of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Mfpic has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. There are several Base Interpreters associated
+%% with mfpic: plain TeX, LaTeX, plain Metafont and plain MetaPost.
+%%
+\gdef\mpxshipout{\afterassignment\middlempxshipout\setbox0=\hbox}%
+\gdef\middlempxshipout{\aftergroup\finishmpxshipout}%
+\gdef\finishmpxshipout{\dimen1=\ht0 \dimen2=\dp0
+ \dimen0=\dimen1 \advance\dimen0\dimen2
+ \setbox0=\hbox{\hbox{\box0
+ \ifnum\dimen0>0 \vrule width1sp height\dimen1 depth\dimen2
+ \else \vrule width1sp height1sp depth0sp\relax
+ \fi}}%
+ \ht0=0pt \dp0=0pt \shipout\hbox{\box0}}%
+\def\MFPtext#1{\vbox{\def\\{\cr}\MFPcfont\MFPeverylabel
+ \halign{##\hfil\cr#1\crcr}}}%
+\let\MFPbegingroup\begingroup
+\let\MFPendgroup\endgroup
+\endinput
+%%
+%% End of file `mfpicdef.tex'.