summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/generic/mfpic
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-12-04 22:14:04 +0000
committerKarl Berry <karl@freefriends.org>2012-12-04 22:14:04 +0000
commitb3e238cd492685a317cf453cbac604541622a450 (patch)
tree5068f6c30c1fdee65991d03d2016ff35ad3bf938 /Master/texmf-dist/source/generic/mfpic
parent8de28ea1b4c5256fafffa4fe6279c20f0752050f (diff)
mfpic (4dec12)
git-svn-id: svn://tug.org/texlive/trunk@28444 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/generic/mfpic')
-rw-r--r--Master/texmf-dist/source/generic/mfpic/grafbase.dtx1211
-rw-r--r--Master/texmf-dist/source/generic/mfpic/mfpic.dtx525
-rw-r--r--Master/texmf-dist/source/generic/mfpic/mfpic.ins11
3 files changed, 1400 insertions, 347 deletions
diff --git a/Master/texmf-dist/source/generic/mfpic/grafbase.dtx b/Master/texmf-dist/source/generic/mfpic/grafbase.dtx
index a309f242f6e..8b7346720dd 100644
--- a/Master/texmf-dist/source/generic/mfpic/grafbase.dtx
+++ b/Master/texmf-dist/source/generic/mfpic/grafbase.dtx
@@ -1,17 +1,17 @@
% \iffalse
% File: grafbase.dtx
-% A part of mfpic 1.06 2011/03/08
+% A part of mfpic 1.10 2012/12/03
%
% -------------------------------------------------------------------
%
-% Copyright 2002--2011, Daniel H. Luecking
+% 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.3b or later is part of all distributions of LaTeX version
-% 2003/12/01 or later.
+% 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,
@@ -19,7 +19,7 @@
%
%<*driver>
\ProvidesFile{grafbase.dtx}
- [2011/03/08 v1.06. Metafont/post macros to interface with mfpic.]%
+ [2012/12/03 v1.10. Metafont/post macros to interface with mfpic.]%
\documentclass{ltxdoc}
\usepackage{docmfp}
@@ -51,6 +51,7 @@
\renewcommand\|{${}\mathrel{|}{}$}
\makeatletter
+\let\HD@SetMacroIndent\@gobble
\newcommand\bsl{{\mytt\@backslashchar}}
% Stupid lists!
\def\@listi{\leftmargin\leftmargini
@@ -113,7 +114,7 @@
%</driver>
%\fi
%
-% \CheckSum{1473}
+% \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
@@ -146,14 +147,17 @@
% 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.pdf}
+% 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
@@ -187,13 +191,14 @@ fi
boolean grafbase; grafbase := true;
string fileversion, filedate;
-fileversion := "1.06"; filedate := "2011/02/25";
+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 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 "";
@@ -236,7 +241,7 @@ def checkversions (expr g)=
fi
enddef;
-checkversions (106);
+checkversions (110);
% \end{macrocode}
%
@@ -298,29 +303,30 @@ enddef;
% In \MF{} `\mfc{color X}' is an identifier (presumably unknown) with the
% base name \mfc{color} and suffix \mfc{X}.
% \begin{macrocode}
-boolean METAPOST;
-METAPOST := known color Geamparalele din Babadag;
+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.";
+ "This file is for Metafont. For Metapost, use grafbase.mp.";
fi
%</MF>
%<*MP>
-if not METAPOST:
+if METAFONT:
GBerrmsg ("wrong compiler.")
- "This file is for Metapost. For Metafont use grafbase.mf.";
+ "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.900 also) have native support for
-% \texttt{CMYK} colors with a \mfc{cmykcolor} data type. It also
-% supports grayscale colors (i.e., \mfc{withcolor} will accept a numeric
-% expression), and has the alias \mfc{rgbcolor} for \mfc{color}.
+% 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
@@ -351,6 +357,7 @@ fi
%</MP>
% \end{macrocode}
%
+%
% \subsection{Setting up the font, \MF{} only}\label{font}
%
% Font-related housekeeping is only for \MF{}. \MF{} only produces
@@ -360,9 +367,10 @@ fi
% \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 it 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).
+% \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
@@ -430,6 +438,7 @@ interim warningcheck := 0;
% \end{macrocode}
%
+%
% \subsection{Initializations}\label{init}
%
% \VariableIndex{unitlen}
@@ -460,15 +469,17 @@ yneg := 0; ypos := 10;
% 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{90} or \gbc{90deg} or \gbc{pi/2*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}
-% for the same effect. Actually, not quite: because of \MF{}'s precision
-% limits, the latter 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} is the maximum possible. If we \emph{define}
-% \gbc{radian} to be \gbc{90/(pi/2)} or \gbc{180/pi} the value of
-% \gbc{pi/2*radian} is even less accurate.
+% 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;
@@ -500,7 +511,7 @@ numeric degree; degree := deg;
%
% \VariableIndex{hatchwd}
% The default \gbc{hatchwd} used to be larger, but it seemed ugly to me.
-% (Backward compatibility? What's that?).
+% (Backward compatibility---what's that?).
% \begin{macrocode}
newinternal penwd; penwd := 0.5pt;
pen drawpen;
@@ -572,6 +583,7 @@ boolean showbbox; showbbox := false;
% \end{macrocode}
%
+%
% \subsubsection{Colors}\label{colors}
%
% Of course colors are only recognized by \MP. The colors \mfc{black},
@@ -595,7 +607,7 @@ 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
+%<MP>if not has_cmyk: let rgbcolor = color; let cmykcolor = color; fi
def _wc_ = withcolor enddef;
% \end{macrocode}
@@ -653,32 +665,61 @@ enddef;
% 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.
-%
-% \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}
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 and write the code for each, rather than load all the functions
-% with three-way booleans (often containing nested booleans).
+% 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 \gbc{makegray(x)}, \gbc{makergb(x)}, and
-% \gbc{makecmyk(x)}, and the boolean \gbc{iscolor clr}. The first three
-% have to return numerics for \MF{}, colors for early \MP{}, and the
-% associated color type for recent \MP{}.
+% 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}
-%<*MP>
if has_cmyk :
vardef grayscalegray (expr g) = snapto g enddef;
vardef gray (expr g) = grayscalegray (g) enddef;
@@ -688,34 +729,13 @@ if has_cmyk :
% \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.
-% \begin{macrocode}
- 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}
-%
% \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, and cmyk or rgb is either retained unchanged or converted to the
-% appropriate model.
+% 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
@@ -729,14 +749,14 @@ if has_cmyk :
enddef;
vardef makergb primary clr =
colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)
- (cmyktorgb(cyanpart clr, magentapart clr, yellowpart clr,
- blackpart 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))
+ (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)
@@ -744,10 +764,13 @@ if has_cmyk :
else:
% \end{macrocode}
%
-% \DescribeRoutine{colorchoice}
-% In early \MP{} \gbc{colorchoice} is a three-way choice, since
-% \mfc{cmykcolor} is not an available data type, but numeric can still be
-% interpreted as a gray.
+% 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}
@@ -762,19 +785,12 @@ 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;
- def colorchoice (expr clr) (text D)(text N)(text R) =
- if unknown clr: D
- elseif numeric clr: N
- elseif rgbcolor clr: R
- else: D
- fi
- enddef;
vardef makergb primary clr =
- colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)
+ colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)()
enddef;
vardef makegray primary clr =
colorchoice (clr)(rgbblack)(rgbgray(clr))
- (rgbtogray (redpart clr, greenpart clr, bluepart clr))
+ (rgbtogray (redpart clr, greenpart clr, bluepart clr))()
enddef;
def makecmyk = makergb enddef;
vardef iscolor expr clr = (color clr) enddef;
@@ -783,7 +799,7 @@ fi
%</MP>
% \end{macrocode}
%
-% \DescribeMacro{knowncolor}
+% \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}
@@ -808,7 +824,7 @@ vardef iscolor expr clr = (color clr) enddef;
%</MF>
% \end{macrocode}
%
-% \DescribeRoutine{forcecolor}
+% \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
@@ -870,6 +886,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Arrays}\label{arrays}
%
% \gbc{ClipPath} is a typical example of an array. Arrays are based on the
@@ -999,6 +1016,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Utilities}\label{utilities}
%
% \DescribeRoutine{chpair}
@@ -1025,13 +1043,14 @@ 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))
+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;
+def hroundpair (expr p) = (hround (xpart p), hround (ypart p))
+enddef;
vardef goodpair (expr p) = hroundpair(p.t_) enddef;
%</MF>
@@ -1090,7 +1109,8 @@ enddef;
% 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;
+primarydef Z xprod W = (xpart Z * ypart W - xpart W * ypart Z)
+enddef;
% \end{macrocode}
%
@@ -1262,7 +1282,7 @@ def endimage =
enddef;
def makeimage (suffix name) (expr refpt) =
- setpair (_image_reference_point) zconv(refpt);
+ setpair (_image_reference_point) zconv (refpt);
setpicture (name) beginimage
enddef;
def concludeimage =
@@ -1481,6 +1501,8 @@ enddef;
% \end{macrocode}
%
+%
+%
% \section{The \grafbase{} Coordinate System}\label{coordinate}
%
% We need to make a distinction between graph units, sharped units, and
@@ -1526,6 +1548,7 @@ enddef;
% want the lower left corner of the graph space to have device coordinates
% $(0,0)$.
%
+%
% \subsection{The main transforms}\label{ztr}
%
% \DescribeVariable{vtr}
@@ -1621,6 +1644,7 @@ vardef invvconv (expr v) = v transformed (inverse vtr) enddef;
% \end{macrocode}
%
+%
% \subsection{The \gbc{mfpic} environment}\label{mfpic}
%
% \DescribeRoutine{active_plane}
@@ -1643,7 +1667,7 @@ def active_plane = currentpicture enddef;
%
% 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.
+% 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
@@ -1695,8 +1719,8 @@ enddef;
% \mfpic.
%
% \DescribeRoutine{bounds}
-% This used to be for compatibility also, but I decided it was a
-% convenient abbreviation, so \mfpic{} uses it now.
+% 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;
@@ -1844,6 +1868,7 @@ enddef;
% \end{macrocode}
%
%
+%
% \section{Text}\label{text}
%
% In the \MP{} version, \gbc{label_adjust}, \gbc{label_sep} and
@@ -1879,6 +1904,7 @@ label_sep := 0; labelpath_sep := 0;
% \end{macrocode}
%
+%
% \subsection{Placement of text, \MP{} only}\label{placement}
%
% \DescribeRoutine{newgblabel}
@@ -1996,6 +2022,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Decorating the text, \MF{} or \MP{}}\label{decorating}
%
% The three macros \gbc{textrect}, \gbc{textoval} and \gbc{textellipse}
@@ -2111,7 +2138,8 @@ vardef textrectx (expr a, b, c, rot, xy, lbl, rad, loc) =
fi
readjustdims (ll, ur) (label_sep - labelpath_sep);
- invvconv (thegblabel (ref_shift(a, b, c, ll, ur), rot, f)) shifted loc
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), rot, f))
+ shifted loc
enddef;
% \end{macrocode}
@@ -2160,7 +2188,8 @@ vardef xellipse (expr aspect, a, b, c, r, xy, lbl, mult, loc) =
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
+ invvconv (thegblabel (ref_shift(a, b, c, ll, ur), r, f))
+ shifted loc
fi
enddef;
@@ -2197,6 +2226,7 @@ enddef;
% \end{macrocode}
%
%
+%
% \section{Additional Functions}\label{functions}
%
% Complex variable functions are provided, which interpret a pair $(x, y)$
@@ -2214,8 +2244,12 @@ enddef;
% in \MF.)
%
% The value \gbc{eps/2 + epsilon} is the smallest value with
-% reciprocal less than \mfc{infinity}. I set \gbc{nottoosmall} a speck
-% bigger to ensure that the same is true of \gbc{2*(nottoosmall/2)}.
+% 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
@@ -2330,9 +2364,9 @@ vardef radians (expr t) = t/radian enddef;
% \RoutineIndex{invcos}\gbc{invcos} and \RoutineIndex{invtan}\gbc{invtan})
% that return angles in radians.
% \begin{macrocode}
-vardef invcos primary X = (acos X)/radian enddef;
-vardef invsin primary X = (asin X)/radian enddef;
-vardef invtan primary X = (atan X)/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;
% \end{macrocode}
%
@@ -2346,10 +2380,10 @@ vardef invtan primary X = (atan X)/radian enddef;
% \begin{macrocode}
vardef exp primary X = mexp (256 * X) enddef;
vardef ln primary X = (mlog X) / 256 enddef;
-def log = ln enddef;
+vardef log primary X = ln (X) enddef;
vardef logbase (expr B) primary X = (mlog X)/(mlog B) enddef;
-def logtwo = logbase( 2) enddef;
-def logten = logbase(10) enddef;
+vardef logtwo primary X = logbase( 2) (X) enddef;
+vardef logten primary X = logbase(10) (X) enddef;
% \end{macrocode}
%
@@ -2437,28 +2471,53 @@ enddef;
% 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}, and \RoutineIndex{conj}\gbc{conj}.
+% \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 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}
+% 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|$.
+% 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;
@@ -2466,6 +2525,17 @@ vardef Moebius (expr A) primary Z =
(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}
%
@@ -2485,6 +2555,13 @@ def id (expr x) = x enddef;
% 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
@@ -2497,6 +2574,7 @@ let ^ = **;
% \end{macrocode}
%
+%
% \section{Coordinate Systems and Transformations}\label{systems}
%
% \DescribeVariable{T_stack}
@@ -2532,6 +2610,7 @@ def ecoords = hide ( T_pop (ztr); vtr := vectorpart ztr ) enddef;
% \end{macrocode}
%
+%
% \subsection{Coordinate changes}\label{changes}
%
% \DescribeRoutine{apply_t}
@@ -2545,7 +2624,8 @@ def ecoords = hide ( T_pop (ztr); vtr := vectorpart ztr ) enddef;
% 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;
+vardef vectorpart primary T = T shifted -(origin transformed T)
+enddef;
def apply_t (text Transformer) =
ztr := identity Transformer transformed ztr;
@@ -2589,6 +2669,7 @@ 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.
@@ -2797,8 +2878,10 @@ 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
@@ -2905,6 +2988,7 @@ enddef;
%</MF>
% \end{macrocode}
%
+%
% \subsection{Producing and modifying pictures}\label{pictures}
%
% Here we define some slightly higher level commands that make use (in \MF)
@@ -2935,12 +3019,10 @@ enddef;
% \gbc{active_plane}, we have eliminated that parameter from
% \gbc{coloraddon}.
%
-% \DescribeRoutine{_orto}
-% This version of \gbc{orto} 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}.
-% \DescribeRoutine{_subto}
+% 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) =
@@ -3020,6 +3102,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Clipping}\label{basicclipping}
%
% \DescribeRoutine{clipto}
@@ -3312,9 +3395,9 @@ enddef;
% calling routine must make sure that picture is initialized (it need
% not be \mfc{nullpicture}).
%
-% One might do this with two nested loops, 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.
+% 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
@@ -3351,6 +3434,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Hatching}\label{basichatching}
%
% \DescribeRoutine{thatchf}
@@ -3374,7 +3458,7 @@ enddef;
% 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 me.)
+% predates my involvement with \mfpic{}.)
% \begin{macrocode}
def thatchf (suffix v) (expr CT, sp, a, b) =
begingroup
@@ -3389,6 +3473,178 @@ 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
@@ -3478,6 +3734,8 @@ enddef;
% \end{macrocode}
%
+%
+%
% \section{Bounding Boxes of Paths}\label{bboxes}
%
% To fill a region with other than a solid fill, we normally fill a
@@ -3522,6 +3780,9 @@ enddef;
% 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}
@@ -3532,6 +3793,7 @@ 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>
@@ -3541,15 +3803,14 @@ def getbbox (suffix ll, ur) expr g =
ll := pairmin (ll, pnt[_j] (g)); ur := pairmax (ur, pnt[_j] (g));
endfor
for _j = 1 upto _s*(length g):
- ctrlsbbox (subpath ((_j-1)/_s, _j/_s) of g) (ll, ur);
+ ctrlsbbox (ll, ur) subpath ((_j-1)/_s, _j/_s) of g;
endfor
%</MF>
if showbbox: noclip ( safedraw rect (ll, ur) ); fi
enddef;
%<*MF>
-numeric bbox_split; bbox_split := 2;
-def ctrlsbbox (expr p) (suffix ll, ur) =
+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;
@@ -3557,6 +3818,31 @@ 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.
@@ -3568,11 +3854,9 @@ enddef;
% \mfc{.5} (accurate enough, assuming pixel units). This is only called by
% \gbc{tbbox}, which is never used.
%
-% \DescribeRoutine{_xlimit}
% \gbc{xlimit(x)} returns a value of true if the path \gbc{g} doesn't
-% cross the vertical line at \gbc{x}.
-% \DescribeRoutine{_ylimit}
-% \gbc{ylimit(y)} is the same for the horizontal line at \gbc{y}.
+% 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) =
@@ -3618,6 +3902,8 @@ enddef;
%</unused>
% \end{macrocode}
%
+%
+%
% \section{Device Coordinate Rendering Commands}\label{basicrendering}
%
% We use the word `rendering' to refer to commands that accept a path
@@ -3625,6 +3911,7 @@ enddef;
% All the commands in this section expect paths, pairs and dimensions in
% device coordinates.
%
+%
% \subsection{Drawing}\label{basicdrawing}
%
% \DescribeRoutine{safedraw}
@@ -3654,6 +3941,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Filling}\label{basicfilling}
%
% \DescribeRoutine{NoCycle}
@@ -3712,6 +4000,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Clipping}\label{clipping}
%
% \DescribeRoutine{safeclip}
@@ -3727,6 +4016,8 @@ enddef;
% \end{macrocode}
%
+%
+%
% \section{Graph Coordinate Rendering}\label{rendering}
%
% \DescribeRoutine{store}
@@ -3764,6 +4055,7 @@ vardef stored (suffix fs) expr f = store (fs) f; f enddef;
% \end{macrocode}
%
+%
% \subsection{Drawing}\label{drawing}
%
% \DescribeRoutine{drawn}
@@ -3797,18 +4089,23 @@ enddef;
%
% 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 autorounding stack. I'd never heard of this stack until I ran
+% 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 =
+vardef colorwiggle (expr smth, clr, tens, blen, elen, len, wid) expr f
+=
convertpath (g) f;
setuplengtharray (cumlen, totlen, ct) g;
save B;
@@ -3919,6 +4216,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Filling, unfilling and clipping}\label{filling}
%
% \DescribeRoutine{filled}
@@ -3943,6 +4241,7 @@ vardef Clip expr c = safeclip zconv (c); c enddef;
% \end{macrocode}
%
+%
% \subsection{Shading}\label{shading}
%
% \DescribeRoutine{shade}
@@ -4117,6 +4416,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Hatching}\label{hatching}
%
% \DescribeRoutine{thatch}
@@ -4183,6 +4483,88 @@ 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}
@@ -4215,6 +4597,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Dots and dashes}\label{dashes}
%
% \MP{} already has commands for drawing a dashed or dotted curve,
@@ -4470,8 +4853,8 @@ vardef makelengtharray (suffix clen) suffix p =
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;
+ clen[_i] := clen[_i-1] + abs (pnt[_i/_s] (p) - pnt[(_i-1)/_s] (p))
+ / _rescale_factor;
endfor
clen[clen]
enddef;
@@ -4725,6 +5108,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Double-line drawing}\label{doubleline}
%
% \DescribeRoutine{doubledraw}
@@ -4743,6 +5127,8 @@ enddef;
% \end{macrocode}
%
+%
+%
% \section{Points Symbols and Other Pictures}\label{symbols}
%
% \DescribeRoutine{centerit}
@@ -4914,6 +5300,8 @@ enddef;
% \end{macrocode}
%
+%
+%
% \section{Axes, Tic Marks, and Grids}\label{axes}
%
% \DescribeRoutine{arrowdraw}
@@ -5482,6 +5870,8 @@ enddef;
% \end{macrocode}
%
+%
+%
% \section{Path Construction}\label{pathconstruction}
%
% This section is devoted to commands that accept a list or array of
@@ -5490,6 +5880,7 @@ enddef;
% 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}
@@ -5658,7 +6049,9 @@ enddef;
% \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 is also used with an array of paths instead of points.
+% 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
@@ -5672,8 +6065,9 @@ enddef;
% list of pair expressions, forms an array from them and calls
% \gbc{mkpoly}.
% \DescribeRoutine{NoPoints}
-% \mfc{NoPoints} prints a warning and sets the array to a single point,
-% the origin.
+% \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);
@@ -5718,10 +6112,32 @@ enddef;
% 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. Strictly
+% 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;
@@ -5733,9 +6149,29 @@ vardef brownianpath (expr start, num, sc) =
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
@@ -5839,8 +6275,8 @@ vardef mkconvex (expr tens, cyclic) (suffix pts) =
_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])));
+ _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];
@@ -5903,12 +6339,16 @@ enddef;
numeric default_tension; default_tension := 1;
def curve = tcurve (default_tension) enddef;
vardef tcurve (expr tens, cyclic) (text t) =
- setpairs (_tc) (t); mksmooth (tens, cyclic, _tc)
+ 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); mkconvex (tens, cyclic, _tcc)
+ setuniquepairs (_tcc) (t);
+ if _tcc=0: NoPoints("ccurve", _tcc); fi
+ mkconvex (tens, cyclic, _tcc)
enddef;
% \end{macrocode}
@@ -5978,8 +6418,8 @@ vardef mkqbezier (expr cyclic) (suffix pts) =
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]
+ ..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] ]
@@ -6114,12 +6554,14 @@ 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
@@ -6240,6 +6682,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Splines with computed controls}\label{computedsplines}
%
% A cubic spline through a set of points is a curve obtained by joining
@@ -6352,9 +6795,9 @@ enddef;
% 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 < x < x\sb
-% {j+1}$, making sure that the resulting graph is as smooth as possible at
-% the points $x\sb j$.
+% 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}
@@ -6481,6 +6924,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Arcs, circles and ellipses}\label{arcs}
%
% We have multiple commands that generate circular arcs, differing in
@@ -6502,7 +6946,9 @@ enddef;
%
% 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 be no problem.
+% 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
@@ -6527,7 +6973,7 @@ enddef;
% 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 infinity, but we allow it even though I am pretty sure
+% 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) =
@@ -6546,7 +6992,7 @@ enddef;
%
% \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
+% subtended. Another name for \gbc{arc} is \gbc{arccps}, (``\gbc{cps}'' is
% for ``center, point, sweep'').
% \begin{macrocode}
vardef arc (expr center, begpt, sweep) =
@@ -6573,7 +7019,7 @@ def arccps = arc enddef;
% 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 chord and the line
+% 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
@@ -6589,7 +7035,7 @@ def arccps = arc enddef;
% circle. This gives the radius mentioned above.
% \begin{macrocode}
vardef arcpps (expr begpt, endpt, sweep) =
- if begpt = endpt: begpt--endpt
+ if (begpt = endpt) or (sweep = 0): begpt--endpt
else:
setpair (cd) unitvector (endpt-begpt);
if abs(sweep) <= 45:
@@ -6761,7 +7207,8 @@ vardef circlepps (expr one, two, sweep) =
enddef;
vardef circlepp (expr small, one, two, rad) =
- arcpp (small, one, two, rad) & arcpp (not small, two, one, rad) & cycle
+ arcpp (small, one, two, rad) & arcpp (not small, two, one, rad)
+ & cycle
enddef;
def circleppr (expr one, two, rad, small) =
@@ -6770,11 +7217,82 @@ 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 supposedly distinct points on the path and
-% finds the intersection of the perpendicular bisectors of two chords.
+% 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[];
@@ -6782,7 +7300,7 @@ vardef pathcenter expr p =
a1 = pnt 0 (p);
a3 = pnt [n/2] (p);
if cycle p:
- a2 = pnt [n/4] (p);
+ a2 = pnt [ n/4] (p);
a4 = pnt [3n/4] (p);
else:
a2 := a3;
@@ -6804,8 +7322,8 @@ enddef;
% This is just the circle through the three corners.
%
% \DescribeRoutine{incircle}
-% The command \gbc{incircle} produces the circle inside the triangle that
-% is tangent to all three sides. It makes use of the fact that the two
+% 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
@@ -6859,12 +7377,26 @@ enddef;
% \end{macrocode}
%
% \DescribeRoutine{pshcircle}
-% Here is a couple of circles maybe only I need. They are the
+% 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:
@@ -6877,49 +7409,176 @@ vardef pshcircle (expr disk, ctr, rad) =
elseif abs(ctr) >= 1 :
if abs(ctr) > 1:
GBerrmsg ("Impossible center of pseudohyperbolic circle.")
- "The center of a pseudohyperbolic circle must be in "
+ "The center of this pseudohyperbolic circle must be in "
& "the unit disk.";
fi
onepointpath (true,ctr)
else:
- % compute Euclidean center and radius (and a denominator used twice
- % in calculations).
save _r, _dnm;
_r := abs(ctr);
_dnm := 1 - _r*_r*rad*rad;
- circle ( (1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm)
+ circle ((1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm)
fi
else:
if rad >= 1 :
- GBerrmsg ("Impossible pseudohyperbolic circle.")
+ 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 pseudohyperbolic circle.")
- "The center of a pseudohyperbolic circle must be in "
+ GBerrmsg ("Impossible center of pseudohyperbolic circle.")
+ "The center of this pseudohyperbolic circle must be in "
& "the upper half-plane.";
fi
onepointpath (true,ctr)
else:
- % compute Euclidean center and radius (and a denominator used twice
- % in calculations).
- % Euclidean center at xpart ctr + (1 + R^2)/(1 - R^2)*ypart ctr
- % Euclidean radius 4R/(1 - R^2)*ypart ctr
save _y, _dnm;
_y := ypart ctr;
_dnm := 1 - rad*rad;
- circle ( (xpart ctr, (1 + rad*rad)/_dnm * _y), 2rad/_dnm*_y)
+ 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 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
+% 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. $$
@@ -6952,6 +7611,39 @@ 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
@@ -7148,7 +7840,7 @@ 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)
+ 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.";
@@ -7273,16 +7965,16 @@ vardef tRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) =
for _idx := 2 upto _trj:
_dt := ds/emax(1,abs(_RHS_(_tt,_ztr)));
_th := _tt + .5_dt;
- _dz1 := _dt*_RHS_(_tt, _ztr); % displacement based on current point
+ _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 based on 1st midpoint
+ _dz2 := _dt*_RHS_(_th, _ztmp); % displacement for 1st midpoint
_ztmp := _ztr + .5_dz2; % 2nd midpoint
- _dz3 := _dt*_RHS_(_th, _ztmp); % displacement based on 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 right away in next line:
+ % get time for next loop now since we need it in the next line:
_tt := _tt + _dt;
- _dz4 := _dt*_RHS_(_tt, _ztmp); % displacement based on end point
+ _dz4 := _dt*_RHS_(_tt, _ztmp); % displacement for end point
% get next point
_ztr := _ztr + (_dz1 + 2_dz2 + 2_dz3 + _dz4)/6;
_trj[_idx] := _ztr;
@@ -7308,8 +8000,11 @@ 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
@@ -7477,7 +8172,8 @@ vardef makesector expr p = (pathcenter p)--p--cycle enddef;
% 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}.
+% \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))
@@ -7490,6 +8186,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Trimming a path}\label{trimming}
%
% \DescribeRoutine{cutoffbefore}
@@ -7545,6 +8242,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Creating arrows}\label{arrows}
%
% First, some better \mfc{direction} commands. They makes use of the fact
@@ -7555,7 +8253,6 @@ enddef;
% has a tangent at $z\sb0$ equal to the first one of $z\sb{j} -z\sb0$
% that is nonzero.
%
-% \DescribeRoutine{__dir}
% \gbc{__dir} gets the direction at point 0 for an arbitrary path.
% \gbc{postdirection}
% \DescribeRoutine{postdirection}
@@ -7815,7 +8512,8 @@ enddef;
% 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;
+path cut_path;
+cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle;
% \end{macrocode}
%
@@ -7875,6 +8573,7 @@ enddef;
% \end{macrocode}
%
+%
% \subsection{Randomizing a path}
%
% In order to randomly change a path, we need to randomly change its
@@ -7964,9 +8663,8 @@ enddef;
%
% \DescribeRoutine{detrivialized}
% We start with a routine that strips out trivial segments from a path.
-% This makes some loops a lot easier. We wouldn't want to differently
-% shift the two (equal) endpoints of a trivial segment, making it
-% nontrivial.
+% 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;
@@ -8032,10 +8730,133 @@ 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 Bezier segment \gbc{f}.
+% 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
@@ -8088,7 +8909,7 @@ vardef parapath (expr d) expr f =
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)));
+ 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;
@@ -8156,6 +8977,7 @@ enddef;
% \end{macrocode}
%
+%
% \section{Miscellaneous}\label{misc}
%
% \subsection{Implementation of \mfpic{}'s \cs{plotdata} command}%
@@ -8337,8 +9159,8 @@ 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;
+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;
@@ -8384,7 +9206,8 @@ 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;
+ (_A9, _A10, _A1, _A2, _A3, (xpart _A3, 1), (xpart _A9, 1))
+ scaled .84;
SolidStar.clear := Star.clear;
forsuffixes S =
@@ -8403,7 +9226,9 @@ endfor
% have it,
% \DescribeRoutine{lcm}
% \gbc{lcm} is a snap. Since \gbc{gcd} always returns a positive result,
-% \gbc{lcm} satisfies the usual rule for signs of products.
+% \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;
@@ -8648,7 +9473,8 @@ def barchart (expr firstbar, sep, r, vert)(text data) =
path chartbar[];
chartbar := 0; barwd := r*sep;
for _itm = data:
- barend[incr chartbar] := if pair _itm: ypart _itm else: _itm fi;
+ 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;
@@ -8685,8 +9511,10 @@ 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
@@ -8762,6 +9590,7 @@ numeric gcode; gcode := 0;
%</MF|MP>
% \end{macrocode}
%
+%
% \subsection{Dvips names for colors}\label{dvipsnam}
%
% In order to make \file{dvipsnam.mp} useful outside grafbase, we give
diff --git a/Master/texmf-dist/source/generic/mfpic/mfpic.dtx b/Master/texmf-dist/source/generic/mfpic/mfpic.dtx
index 5da4b773a74..586d051e18e 100644
--- a/Master/texmf-dist/source/generic/mfpic/mfpic.dtx
+++ b/Master/texmf-dist/source/generic/mfpic/mfpic.dtx
@@ -1,10 +1,10 @@
% \iffalse
% File: mfpic.dtx
-% A part of mfpic 1.06 2011/03/08
+% A part of mfpic 1.10 2012/12/03
%
% -------------------------------------------------------------------
%
-% Copyright 2002--2011, Daniel H. Luecking
+% 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
@@ -22,7 +22,7 @@
%</driver>
%<sty>\ProvidesPackage{mfpic}
%<*sty>
- [2011/03/08 v1.06. Macros for drawing with Metafont/MetaPost.]%
+ [2012/12/03 v1.10. Macros for drawing with Metafont/MetaPost.]%
%</sty>
%<*driver>
\documentclass{ltxdoc}
@@ -36,6 +36,7 @@
\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}}
@@ -57,6 +58,7 @@
\renewcommand\|{${}\mathrel{|}{}$}
\makeatletter
+\let\HD@SetMacroIndent\@gobble
\newcommand\bsl{{\mytt\@backslashchar}}
% Stupid lists!
\def\@listi{\leftmargin\leftmargini
@@ -106,7 +108,7 @@
\end{document}
%</driver>
%\fi
-% \CheckSum{5145}
+% \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
@@ -134,15 +136,17 @@
% produce the picture. The picture is then included on a second pass
% through \TeX.
%
-% This file documents the source code. See \file{mfpic-doc.pdf}/\file{tex}
-% for the user documentation, or \file{mfpguide.pdf}/\file{tex}) for an
-% introductory guide.
+% 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
@@ -170,9 +174,9 @@
\ifx\mfpfileversion\UndEfInEd\else\expandafter\endinput\fi%
{%
\catcode\lq\.12 \catcode\lq\/12%
- \gdef\mfpfileversion{1.06}%
- \gdef\mfpfiledate{2011/02/25}%
- \gdef\mfpicversion{106}%
+ \gdef\mfpfileversion{1.10}%
+ \gdef\mfpfiledate{2012/12/03}%
+ \gdef\mfpicversion{110}%
}%
% \end{macrocode}
%
@@ -185,8 +189,6 @@
% \end{macrocode}
%
% We now get rid of unusually catcoded punctuation, space and EOL.
-% We save all the current category codes in the macro \cs{mfp@restoreALL}
-% and restore them at the end by executing this command.
% 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
@@ -201,9 +203,9 @@
\catcode96=12 % 96=left quote
\catcode`\@=11
\gdef\MFPsavecodes{%
- \edef\mfp@restoreNLchar{\newlinechar\number\newlinechar\relax}%
- \edef\mfp@restoreELchar{\endlinechar\number\endlinechar\relax}%
- \edef\mfp@restoreSP{\catcode32=\number\catcode32\relax}%
+ \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{;}%
@@ -213,8 +215,8 @@
\mfp@restorecode{>}\mfp@restorecode{*}\mfp@restorecode{/}%
\mfp@restorecode{+}\mfp@restorecode{-}\mfp@restorecode{"}%
\mfp@restorecode{'}\mfp@restorecode{_}\mfp@restorecode{`}%
- \mfp@restoreEOL\mfp@restoreSP\catcode10=\number\catcode10
- \mfp@restoreNLchar\mfp@restoreELchar}}%
+ \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
@@ -232,7 +234,7 @@
% \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
+% 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
@@ -240,6 +242,7 @@
% necessary. Characters 10 and 13 are \verb|^^J| and \verb|^^M|,
% control-J and control-M.
%
+%
% \subsection{Debugging and messages}\label{debug}
%
% \DescribeMacro{\mfpicdebug}
@@ -290,6 +293,7 @@
\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
@@ -359,12 +363,21 @@
% 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@}.
+% \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 \mfp@DBlog{AmS-TeX detected.}%
- \else \mfp@DBlog{LaTeX detected.}\mfp@latextrue
+ {\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}
@@ -391,6 +404,7 @@
{\mfp@DBlog{Not pdfTeX.}}%
% \end{macrocode}
%
+%
% \subsection{Blank line and spacing hacks}\label{spacing}
%
% In order for commands to always read their arguments correctly,
@@ -426,6 +440,7 @@
\mfp@enddef
% \end{macrocode}
%
+%
% \subsection{Warning if commands are already defined}
%
% We sometimes (either by accident or by choice) redefine things defined
@@ -454,6 +469,7 @@
\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
@@ -524,7 +540,7 @@
% \end{macrocode}
%
% This message is issued when the \cs{tlabeljustify} command (see
-% section~\ref{labelsettings}) is issued with an invalid parameter.
+% subsection~\ref{labelsettings}) is issued with an invalid parameter.
% \begin{macrocode}
\newdef\mfp@justify@error{%
\mfp@errmsg{Invalid justification parameter for text label}%
@@ -538,12 +554,14 @@
% warning, which is otherwise issued by \cs{mfpendloop}.
% \begin{macrocode}
\newdef\mfp@untilwarn{%
- \Mfpic@warn{\mfp@b mfploop without \string\mfpuntil!}}%
+ \Mfpic@warn{\mfp@b mfploop without \string\mfpuntil!\@nl}}%
% \end{macrocode}
%
%
+%
% \section{Configuring \mfpic{} behavior}\label{configuring}
%
+%
% \subsection{Options}\label{options}
%
% \DescribeMacro{\ifmfpmpost}
@@ -636,7 +654,7 @@
% \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
+% 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
@@ -655,7 +673,7 @@
% spaces are significant.
% \begin{macrocode}
\newdef\setmfvariable#1{%
- \MFP@sp@def\mfp@tempa{#1}\@setmfvariable\mfp@tempa}%
+ \mfp@sp@def\mfp@tempa{#1}\@setmfvariable\mfp@tempa}%
\newdef\@setmfvariable#1#2#3{%
\mfp@ifopengraphsfile%
{\mfcmd{set#1 (#2) #3}}%
@@ -665,7 +683,7 @@
\newdef\setmfpair {\@setmfvariable{pair}}%
\newdef\setmfcolor {\@setmfvariable{color}}%
\newdef\globalsetmfvariable#1#2#3{%
- \MFP@sp@def\mfp@tempa{#1}%
+ \mfp@sp@def\mfp@tempa{#1}%
\mfp@ifopengraphsfile
{\mfcmd{\ifx\mfp@tempa\mfp@C gsetcolor \else gsetvariable (#1) \fi
(#2) #3}}%
@@ -864,9 +882,10 @@
\newlet\ifmfp@readlog\iffalse
\newdef\mfpreadlog{%
\mfp@ifopengraphsfile
- {\mfp@afteropen@error\mfpreadlog}{\global\let\ifmfp@readlog\iftrue}}%
+ {\mfp@afteropen@error\mfpreadlog}{\global\let\ifmfp@readlog\iftrue}}%
% \end{macrocode}
%
+%
% \subsection{Graphic inclusion}\label{graphic}
%
% \DescribeMacro{\mfpicllx}
@@ -918,7 +937,7 @@
\newdef\nofile@setmfpgraphic#1{%
{\edef\mfp@tempa{#1}%
\vbox to 0pt{\vss
- \rlap{\kern2pt \mfpdraftfont \mfp@sanitized\mfp@tempa}\kern 2pt}}}%
+ \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
@@ -998,6 +1017,7 @@
%</tex>
% \end{macrocode}
%
+%
% \subsection{\LaTeX{} options and \MP{} graphics inclusion}\label{latex}
%
% Code dependent on \LaTeXe. Mostly this is the option processing
@@ -1155,6 +1175,7 @@
% \end{macrocode}
%
%
+%
% \section{Optional parameter handling}\label{optional}
%
% We borrow \LaTeX's \cs{@ifnextchar}. The first argument is the token
@@ -1182,7 +1203,7 @@
\fi
\reserved@c}%
{%
- \def\:{\global\let\@sptoken= }\: % this makes \@sptoken a space token
+ \def\:{\global\let\@sptoken= }\: % makes \@sptoken a space token
\def\:{\@xifnch}\@xp\gdef\: {\futurelet\@let@token\@ifnch}%
}%
\mfp@enddef
@@ -1193,18 +1214,23 @@
% \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 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 \expandafter\MFP@sp@b
- \else \expandafter\MFP@sp@b\expandafter#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}}%
+ \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@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
@@ -1252,12 +1278,12 @@
% 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}%
+\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}
%
@@ -1280,7 +1306,7 @@
% code.
% \begin{macrocode}
\newdef\mfp@defaultopt#1#2{%
- \@ifnextchar[{\mfp@ifemptyopt{#1}{#2}}{#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}}%
@@ -1305,8 +1331,10 @@
% 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
@@ -1415,6 +1443,7 @@
\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
@@ -1460,8 +1489,6 @@
% 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{mfp@commonverbatimtex} Tokens written at the start of every
-% output file inside a \mfc{verbatimtex} group.
% \item \cs{ifmfp@switch} Not exactly a register, but a temporary
% switch for passing information from one macro to another.
% \end{itemize}
@@ -1475,15 +1502,13 @@
\newcount\mfp@sequence
\newtoks\mfp@toks
\newtoks\mfp@verbtex
-\newtoks\mfp@commonverbatimtex
\newif\ifmfp@switch
+%</tex>
% \end{macrocode}
%
% We store most of the \mfc{verbatimtex} block that \mfpic{} relies on in
-% the token register \cs{mfp@commonverbatimtex}. We do that because it
-% relies on a couple of catcode changes and we want to be in a situation
-% where we have that under control. Each line will end with an active
-% ctrl-M, which is transformed by \cs{mfsrc} into a newline.
+% 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
@@ -1494,21 +1519,42 @@
% \mfc{btex} and so will overwrite my definition. Thus all cases are
% served.
% \begin{macrocode}
-\begingroup
- \mfp@keeplines\@makeother\#%
- \@makeother\%\global\mfp@commonverbatimtex
- {\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\everylabel
- \halign{##\hfil\cr#1\crcr}}}%
- }\endgroup%
+%<*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
@@ -1616,8 +1662,8 @@
verbatimtex\@nl
\ifmfp@verbtex \the\mfp@verbtex\@nl \fi
\relax\@nl
- \the\mfp@commonverbatimtex
- \def\noexpand\everylabel{\the\mfp@toks}\@nl
+ \noexpand\input mfpicdef.tex\relax\@nl
+ \def\noexpand\MFPeverylabel{\the\mfp@toks}\@nl
etex;\@nl
\mfp@ifdefined\mfp@settemplate\mfp@settemplate{}%
}%
@@ -1648,7 +1694,7 @@
% 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
@@ -1739,6 +1785,7 @@
\fi \global\let\mfp@filename\UndEfInEd}{}}%
% \end{macrocode}
%
+%
% \subsection{Information from \MF: reading its log file}
%
% \DescribeMacro{\assignmfvalue}\SpecialUsageIndex{\globalassignmfvalue}
@@ -1786,7 +1833,8 @@
{\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}{}%
+ \mfsrc{%
+ \@ifmplabels{\@nl verbatimtex #1\def\string#2{#2} etex;\@nl}{}%
message "\string\mfpicvalue";\@nl
message "\mfp@cmdname#2";\@nl
show #3;\@nl
@@ -1831,6 +1879,7 @@
% \end{macrocode}
%
%
+%
% \section{\Mfpic{} dimensions}\label{dimensions}
%
% A number of packages, especially figure drawing packages, allocate a
@@ -2090,6 +2139,7 @@
% \end{macrocode}
%
%
+%
% \section{Helper macros}\label{helper}
%
% \DescribeMacro{\mfpicnumber}
@@ -2177,7 +2227,7 @@
\newdef\colorarray{\setmfarray{color}}%
\newdef\rgbcolorarray{\setmfarray{rgbcolor}}%
\newdef\cmykcolorarray{\setmfarray{cmykcolor}}%
-\newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1) (#2)}\mfp@writedata}%
+\newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1)(#2)}\mfp@writedata}%
\newlet\globalsetmparray\globalsetmfarray
% \end{macrocode}
%
@@ -2279,6 +2329,7 @@
% \end{macrocode}
%
%
+%
% \section{Macros to implement prefix commands}\label{prefix}
%
% Some \mfpic{} macros, like \cs{circle} create a path. When used without
@@ -2395,7 +2446,7 @@
% default color, but we provide a command for the user to change it.
% \begin{macrocode}
\newdef\mfp@render{\draw[]}%
-\newdef\setrender#1{\mfp@def\mfp@render{#1}}%
+\newdef\setrender{\mfp@def\mfp@render}%
% \end{macrocode}
%
% A figure macro will invoke the common first-stage code and the rendering
@@ -2455,6 +2506,7 @@
% \end{macrocode}
%
%
+%
% \section{Macros for getting data from files}\label{rwdata}
%
% The following command contains the common code to open a data file for
@@ -2588,8 +2640,9 @@
\fi}%
% \end{macrocode}
%
+% \section{Various \mfpic{} Settings.}\label{mfpsettings}
%
-% \section{Various \CMF{} Settings.}\label{MFsettings}
+% \subsection {\CMF{} settings}\label{MFsettings}
%
% \DescribeMacro{\penwd}
% Macros that write changes in default \grafbase{} variables now use the
@@ -2651,8 +2704,8 @@
\newdef\settension#1{\setmfnumeric{default_tension}{#1}}%
% \end{macrocode}
%
-%
-% \section{Settings for text label placement in figures}\label{labelsettings}
+% \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
@@ -2781,7 +2834,7 @@
\mfp@ifmpost
{\mfp@ifopengraphsfile
{\mfcmd{verbatimtex\@nl
- \def\noexpand\everylabel{\the\mfp@toks} etex}}%
+ \def\noexpand\MFPeverylabel{\the\mfp@toks} etex}}%
{}}%
{}}%
\newdef\every@tlabel{}%
@@ -2795,8 +2848,7 @@
\newdef\pinumber{3.14159}%
% \end{macrocode}
%
-%
-% \section{Other settings}\label{othersettings}
+% \subsection{Other settings}\label{othersettings}
%
% \DescribeMacro{\headshape}
% This sets the arrowhead shape. The parameters are: the ratio of width
@@ -2867,7 +2919,8 @@
% 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@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}%
@@ -3037,7 +3090,7 @@
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@defheadlen{%
+ \edef\mfp@defaultheadlen{%
\the\ifnum\mfp@axisnum>1 \sideheadlen\else \axisheadlen\fi}}%
% \end{macrocode}
%
@@ -3202,6 +3255,8 @@
\newdef\mfp@additions{}%
% \end{macrocode}
%
+%
+%
% \section{The user level graphics macros}
%
% This is the start of the definition of \cs{mfp@grafmacs}. It contains
@@ -3213,10 +3268,11 @@
\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., with the prefix macros of
+% 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
@@ -3235,6 +3291,7 @@
% 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
@@ -3317,6 +3374,31 @@
\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
@@ -3361,7 +3443,8 @@
\newdef\arc{\mfp@iftoken*{\arccomplement\mfp@arc}{\mfp@arc}}%
% \end{macrocode}
%
-% This final circle is for we complex function theorists. It makes a
+% \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
@@ -3371,6 +3454,18 @@
\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
@@ -3514,7 +3609,7 @@
% 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 comamnd is written that also has a 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.
@@ -3589,16 +3684,6 @@
\newdef\turtle{\mfp@listmac{turtle}}%
% \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.
-% \begin{macrocode}
- \newdef\brownianmotion##1{\mfp@figmac{brownianpath (##1)}}%
-% \end{macrocode}
%
% \subsubsection{Graphing functions}\label{functions}
%
@@ -3687,7 +3772,7 @@
% 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 108 segments.
+% 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}
@@ -3695,19 +3780,19 @@
% \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 solutions of equations of the form
+% 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_0) = y_0.
+% \frac{dy}{dx} = f(x,y),\quad y(x\sb0) = y\sb0.
% $$
-% The data required are the \emph{initial values} (the two numbers $x_0$
-% and $y_0$), the formula $f(x,y)$ (an explicit \MF{} numerical expression
-% with literal variables \mfc{x} and \mfc{y} as the only unknowns. Since
-% the \MF{} and 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_0,y_0)$) and join
-% them together to produce the graph.
+% 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
@@ -3719,7 +3804,7 @@
% 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_0,y_0)$, the formula for the right-hand side
+% 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
@@ -3742,19 +3827,47 @@
%
% 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_0$, $x_0+h$, $x_0+2h$, etc., it finds points
-% $(x_n,y_n)$ on the graph so that the two-dimensional distance from $(x_0,y_0)$
-% to $(x_1,y_1)$ is $h$, then the distance from $(x_1,y_1)$ to $(x_2,y_2)$
-% 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}.
+% 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}
%
@@ -3775,8 +3888,10 @@
\newdef\datafile{\mfp@nullopt\mfp@datafile}%
% \end{macrocode}
%
+%
% \subsection{The prefix commands}\label{prefixcommands}
%
+%
% \subsubsection{Storing and reusing a figure}\label{storing}
%
% \DescribeMacro{\store}
@@ -3811,6 +3926,13 @@
% \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}
@@ -3839,6 +3961,7 @@
\newdef\putmfpimage##1{\mfsrc{\@nl putimage (##1)}\mfp@writedata}%
% \end{macrocode}
%
+%
% \subsubsection{Subpaths}
%
% \DescribeMacro{\cutoffbefore}
@@ -3986,7 +4109,8 @@
% 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}}%
+ \newdef\plot{%
+ \mfp@optrendii{doplot}{\the\pointsize,\the\symbolspace}}%
% \end{macrocode}
%
% \DescribeMacro{\plotnodes}
@@ -4018,6 +4142,7 @@
\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
@@ -4033,6 +4158,7 @@
% \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
@@ -4046,6 +4172,7 @@
% 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.
%
@@ -4072,6 +4199,7 @@
\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
@@ -4126,6 +4254,34 @@
\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)
@@ -4145,6 +4301,7 @@
\newdef\gclip{\mfp@rendmac{Clip}}%
% \end{macrocode}
%
+%
% \subsubsection{Modifying a curve}\label{transforming}
%
% The following are transformation prefixes. They are all (except
@@ -4160,6 +4317,7 @@
% 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}}.
@@ -4176,7 +4334,7 @@
%
% All of them simply write the \grafbase{} command of nearly the same
% name, with the same arguments, via
-% \cs{mfp@modi}.\SpecialUsageIndex{\reverse}
+% \cs{mfp@modi}.\SpecialUsageIndex{\reversepath}\SpecialUsageIndex{\reverse}
% \SpecialUsageIndex{\xyswappath}\SpecialUsageIndex{\rotatepath}
% \SpecialUsageIndex{\shiftpath}\SpecialUsageIndex{\scalepath}
% \SpecialUsageIndex{\xscalepath}\SpecialUsageIndex{\yscalepath}
@@ -4185,15 +4343,16 @@
% \SpecialUsageIndex{\transformpath}
%
% \begin{macrocode}
- \newdef\reverse{\mfp@addmac{reverse}}%
+ \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\slantpath{\mfp@modi{xslantedpath}}%
- \newlet\xslantpath\slantpath
+ \newdef\xslantpath{\mfp@modi{xslantedpath}}%
+ \newlet\slantpath\xslantpath
\newdef\yslantpath{\mfp@modi{yslantedpath}}%
\newdef\reflectpath{\mfp@modi{reflectedpath}}%
\newdef\transformpath{\mfp@modi{transformedpath}}%
@@ -4240,6 +4399,19 @@
\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
@@ -4251,6 +4423,7 @@
\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
@@ -4333,6 +4506,7 @@
%
% This ends the prefix macros.
%
+%
% \subsection{Transforming the coordinate system}\label{coordinate}
%
% \DescribeMacro{\coords}
@@ -4382,6 +4556,7 @@
\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
@@ -4468,7 +4643,7 @@
% 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 section~\ref{othersettings}.
+% \cs{setaxismarks} command, described in subsection~\ref{othersettings}.
% \begin{macrocode}
\newdef\axismarks##1{\mfp@defaultopt{\mfp@marks{##1}}{\the\hashlen}}%
\newdef\xmarks{\axismarks x}%
@@ -4505,7 +4680,7 @@
% \DescribeMacro{\vgridlines}
% \cs{vgridlines} is the vertical version.
%
-% No arguments are shown because \cs{mfp@simple} or \cs{mfp@simpli} will
+% 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}}%
@@ -4570,6 +4745,7 @@
\mfp@defaultopt{\mfp@vectorfield{plr}}{\the\headlen}}%
% \end{macrocode}
%
+%
% \subsection{Visualizing points}\label{points}
%
% \DescribeMacro{\point}
@@ -4611,6 +4787,7 @@
\mfp@defaultopt\mfp@plottext{cc}}%
% \end{macrocode}
%
+%
% \subsection{Some composite objects}\label{composite}
%
% \DescribeMacro{\tile}
@@ -4676,10 +4853,10 @@
\mfp@checklatexenv{connect}{\aftergroup\@mfpstarttrue}{}}%
% \end{macrocode}
%
+%
% \subsection{Other graphical features}\label{otherfeatures}
%
-% And now for something completely different: pie charts and bar charts
-% (or bar graphs, or histograms).
+% And now for something completely different.
%
% \DescribeMacro{\piechart}
% Actually, nothing is drawn by the \cs{piechart} command; it only defines
@@ -4768,7 +4945,7 @@
% 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. This ends \cs{mfp@grafmacs}.
+% it is already a math accent command.
% \begin{macrocode}
\newlet\barchart\mfpbarchart
\newlet\bargraph\barchart
@@ -4778,19 +4955,33 @@
\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?
+%\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[(1,0,0)]\lines{(0,0), (5,5), (10,0)}%
- \pointcolor{(0,.8,0)}%
+ \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[(1,1,0)]\ellipse{(0,0),2,3}%
+ \draw\tess{peter}\gfill[rgb(1,1,0)]\ellipse{(0,0),2,3}%
\endmfpic}%
%}
%
@@ -4807,6 +4998,8 @@
\newlet\mfpgantt\mfpbarchart
% \end{macrocode}
%
+%
+%
% \section{Implementing the graphics macros}
%
% To keep \cs{mfp@grafmacs} from becoming unweildy, we define here all the
@@ -4845,8 +5038,15 @@
\newdef\mfp@pshcircle#1#2{\mfp@figmac{pshcircle (#1, #2)}}%
% \end{macrocode}
%
-% \cs{mfp@curve} is called by six graphics macros: \cs{curve},
-% \cs{ccurve}, \cs{mfbezier} and their closed variants . Its two arguments
+% 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
@@ -5150,7 +5350,7 @@
% 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@defheadlen}. It also stores 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.
%
@@ -5163,9 +5363,10 @@
% 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@defheadlen}, 0, 0)}%
+ \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}%
+\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}
@@ -5187,7 +5388,6 @@
\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.
@@ -5234,8 +5434,10 @@
% \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
@@ -5367,6 +5569,7 @@
\@graphbot 0pt
% \end{macrocode}
%
+%
% \subsection{Initializing the \MF{} picture}
% \label{current}
%
@@ -5377,8 +5580,7 @@
% 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. This
-% may be removed in the public release.
+% (\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
@@ -5396,10 +5598,11 @@
beginmfpic(\number\mfp@count); \mfp@p\space\mfp@lineno.
\mfp@ifmpost
{\@nl verbatimtex \relax
- \bgroup\font\noexpand\MFPcfont=\fontname\@tcurr\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
@@ -5467,6 +5670,7 @@
\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
@@ -5531,6 +5735,7 @@
\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
@@ -5568,6 +5773,7 @@
\newlet\axislabels\mfp@axislabels
% \end{macrocode}
%
+%
% \subsection{Captions}\label{captions}
%
% Captions are not added immediately by the \cs{tcaption} command. That
@@ -5590,6 +5796,8 @@
\every@mfpic}% End of \@mfpic
% \end{macrocode}
%
+%
+%
% \section{Implementing the label and caption macros}
%
% \cs{mfp@setconv} uses the stored arguments of the surrounding
@@ -5608,11 +5816,13 @@
% \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=##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=##1\@mfpicunit
+ \advance\mfp@scratch by -\ymin\@mfpicunit
\mfp@scratch=\yfactor\mfp@scratch
\global ##2=\mfp@scratch}}}%
\newdef\mfp@inittlabels{%
@@ -5787,11 +5997,11 @@
% \begin{macrocode}
\@yconv{#2}\mfp@scratch
\begingroup
- \ifcase\tl@vpos \advance\mfp@scratch \tb@totalht % bottom
- \advance\mfp@scratch \tlabel@sep
- \or \advance\mfp@scratch 0.5\tb@totalht % center
- \or \advance\mfp@scratch -\tlabel@sep % top
- \else \advance\mfp@scratch \tb@ht % baseline (default)
+ \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
@@ -5805,10 +6015,10 @@
% \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 % top
- \advance\mfp@scratch -\tlabel@sep
- \else \advance\mfp@scratch -\tb@dp % baseline (default)
+ \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
@@ -6057,6 +6267,8 @@
#1\mfp@scratch}%
% \end{macrocode}
%
+%
+%
% \section{Placing the picture: \cs{endmfpic}}\label{endmfpic}
%
% \DescribeMacro{\endmfpic}
@@ -6072,7 +6284,7 @@
\mfp@DBlog{Definition of closure of mfpic environment.}%
\newdef\endmfpic{\every@endmfpic
\mfsrc{%
- \mfp@ifmpost{\@nl verbatimtex \relax\egroup\space etex;}{}\@nl
+ \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
@@ -6084,6 +6296,7 @@
\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
@@ -6167,6 +6380,7 @@
\fi
% \end{macrocode}
%
+%
% \subsection{Adding labels and caption}\label{addlabel}
%
% We now add the boxes \cs{@alltlabels} and \cs{@backtext} onto the graph
@@ -6192,9 +6406,11 @@
\fi
\ifdim\@tlabelsleft < \maxdimen
\setbox\@alltlabels\vtop to 0pt{%
- \kern \mfpiclly bp \moveleft \mfpicllx bp \box\@alltlabels\vss}%
+ \kern \mfpiclly bp
+ \moveleft \mfpicllx bp \box\@alltlabels\vss}%
\setbox\@backtext \vtop to 0pt{%
- \kern \mfpiclly bp \moveleft \mfpicllx bp \box\@backtext \vss}%
+ \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
@@ -6272,6 +6488,7 @@
\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
@@ -6337,8 +6554,10 @@
% \end{macrocode}
%
%
+%
% \section{Additional features}\label{additional}
%
+%
% \subsection{Saving a copy of the picture}\label{saving}
%
% \DescribeMacro{\newsavepic}
@@ -6385,6 +6604,7 @@
\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
@@ -6428,6 +6648,7 @@
\mfp@ifdefined\framed{}{\let\framed\mfpframed}%
% \end{macrocode}
%
+%
% \subsection{Adding \mfc{verbatimtex} to the \file{.mp}
% file}\label{verbatimtex}
%
@@ -6480,6 +6701,7 @@
% \end{macrocode}
%
%
+%
% \section{Finale}\label{finale}
%
% Set the default starting graphic number. We used to start at 0 and
@@ -6510,3 +6732,4 @@
%
%\clearpage
%\Finale
+%\endinput
diff --git a/Master/texmf-dist/source/generic/mfpic/mfpic.ins b/Master/texmf-dist/source/generic/mfpic/mfpic.ins
index 4b04ba5007b..a66d2832236 100644
--- a/Master/texmf-dist/source/generic/mfpic/mfpic.ins
+++ b/Master/texmf-dist/source/generic/mfpic/mfpic.ins
@@ -1,5 +1,5 @@
% File: mfpic.ins
-% A part of mfpic 1.06 2011/03/08
+% A part of mfpic 1.10 2012/12/03
%
\input docstrip
\keepsilent
@@ -7,7 +7,7 @@
-------------------------------------------------------------------
-Copyright 2002--2011, Daniel H. Luecking
+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
@@ -30,6 +30,7 @@ endinput.^^J%
\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}}
@@ -41,9 +42,9 @@ endinput.^^J%
^^J
^^J To finish the installation:
^^J
-^^J -- Copy the files mfpic.tex and mfpic.sty to a location where
-\sJ TeX and LaTeX will find them. For example, in a TDS compliant
-\sJ system, the directory TEXMF/tex/generic/mfpic/ .
+^^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/ .