% \iffalse % Copyright 2002--2003, Daniel H. Luecking % % Mfpic consists of the 3 files mfpic.dtx, grafbase.dtx and mfpic.ins % and the 5 files they generate: mfpic.tex, mfpic.sty, grafbase.mf, % grafbase.mp, and dvipsnam.mp. % % Mfpic may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.2 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.2 or later is part of all distributions of LaTeX version % 1999/12/01 or later. % % Documentation, examples, and ancillary files are separate and not % covered by this license. See readme.1st for a complete list. See % individual files for any copyright and license restrictions. % % With respect to the proposed draft LPPL-1.3: mfpic has maintenance % status "maintained". The Current Maintainer is Daniel H. Luecking. There % are several Base Interpreters: TeX, LaTeX, MetaPost and Metafont. % %<*driver> \documentclass[draft]{ltxdoc} \def\fileversion{0.7a beta} \def\filedate{2004/04/16} \addtolength{\textwidth}{.5878pt} \def\mytt{\mdseries\ttfamily} \renewcommand\marg[1]{{\mytt \{#1\}}} \renewcommand\oarg[1]{{\mytt [#1]}} \renewcommand\parg[1]{{\mytt (#1)}} \renewcommand{\meta}[1]{{$\langle$\rmfamily\itshape#1$\rangle$}} \DeclareRobustCommand\cs[1]{{\mytt\char`\\#1}} \def\prog#1{{\mdseries\scshape #1}} \def\grafbase{\prog{grafbase}} \def\mfpic{\prog{mfpic}} \def\Mfpic{\prog{Mfpic}} \def\MF{\prog{meta\-font}} \def\MP{\prog{meta\-post}} \def\CMF{\prog{Meta\-font}} \def\CMP{\prog{Meta\-post}} \def\opt#1{{\sffamily\upshape#1}} \def\mfc#1{{\mytt#1}} \let\env\mfc \let\file\mfc \let\gbc\mfc \renewcommand\{{\char`\{} \renewcommand\}{\char`\}} \renewcommand\|{${}\mathrel{|}{}$} \makeatletter \newcommand\bsl{{\mytt\@backslashchar}} % Stupid lists! \def\@listi{\leftmargin\leftmargini \parsep \z@ \@plus\p@ \@minus\z@ \topsep 4\p@ \@plus\p@ \@minus2\p@ \itemsep\parsep} \let\@listI\@listi \@listi \renewcommand\labelitemi{\normalfont\bfseries \textendash} \renewcommand\labelitemii{\textasteriskcentered} \renewcommand\labelitemiii{\textperiodcentered} \leftmargini\parindent % Stupid index! \def\IndexParms{% \parindent \z@ \columnsep 15pt \parskip 0pt plus 1pt \rightskip 5pt plus2em \mathsurround \z@ \parfillskip=-5pt \small % less hanging: \def\@idxitem{\par\hangindent 20pt}% \def\subitem{\@idxitem\hspace*{15pt}}% \def\subsubitem{\@idxitem\hspace*{25pt}}% \def\indexspace{\par\vspace{10pt plus 2pt minus 3pt}}} \makeatother \def\pdfTeX{\textrm{pdf\kern.04em\TeX}} \def\pdfLaTeX{\textrm{pdf\kern.06em\LaTeX}} \def\ConTeXt{\textrm{Con\kern-.16em\TeX\kern-0.06em t}} \def\PiCTeX{\textrm{P\kern-.13em\lower.3ex\hbox{I}C\TeX}} \title{The \mfpic{} package\thanks{This file has version number \fileversion, last revised \filedate. The code described here was developed by several people, notably Thomas Leathrum, Geoffrey Tobin and Dan Luecking. Dan wrote this documentation.}} \author{Dan Luecking} \date{\filedate} \DisableCrossrefs \CodelineIndex \AlsoImplementation \begin{document} \DeleteShortVerb{\|} \DocInput{mfpic.dtx} \end{document} % %\fi % % \CheckSum{4392} % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \catcode`\_=12 % \maketitle % % \begin{abstract} % An environment, \env{mfpic}, is defined, within which commands can % be used for drawing pictures, especially graphs of mathematical % functions. These commands actually write code to an external file % which can be processed through \MF{} or \MP{} (depending on package % options) to produce the picture. The picture is then included on a % second pass through \TeX. % % This file documents the source code. See \file{mfpicdoc.tex} for the % user documentation. % \end{abstract} % % \StopEventually{\PrintIndex} % \tableofcontents % % % \section{Introductory setup}\label{intro} % % \Mfpic{} is designed to work with plain \TeX, \LaTeX, \pdfTeX, and % \pdfLaTeX. % % \subsection{Versions numbers, category codes, etc.}\label{category} % % Almost all the various category code settings we do were prompted by % an \mfpic{} user who had sent a bug report and had to send along his % modified version of \file{mfpic.tex}. It had been modified so that % \cs{message}\,s and \cs{write}\,s would do the right thing in latex % files where various punctuation were made active (e.g., with % \file{french.sty}). % % \DescribeMacro{\mfpfileversion} % \DescribeMacro{\mfpfiledate} % \DescribeMacro{\mfpicversion} % We keep track of version numbers here. We use \cs{mfpfileversion} % because \cs{fileversion} is used by very many \LaTeX{} packages. % This is important, because later we write the version information to the % output file, The \cs{mfpicversion} is 100 times the numeric part of the % version. The output file can compare this number with the corresponding % value in \file{grafbase} and detect installations where there is a % mismatch. % \begin{macrocode} %<*tex> {\catcode\lq\.12 \catcode\lq\/12% \gdef\mfpfileversion{0.7a beta}% \gdef\mfpfiledate{2004/04/16}% \gdef\mfpicversion{70}}% \ifx\MFPicpackagE\UndEfInEd\else\expandafter\endinput\fi% % \end{macrocode} % % A bug in older versions of some support files is triggered by the macro % \cs{+}, which is an \cs{outer} macro in plain \TeX. Here we save the % current definition and then give it a nonouter meaning. % \begin{macrocode} \let\mfpsaveplus\+% \let\+\tabalign% % \end{macrocode} % % \DescribeMacro{\MFPrestorecode} % We now get rid of unusually catcoded punctuation, space and EOL. % We save all the current category codes in the macro \cs{MFPicpackagE} % and restore them at the end by executing this command. % We try to assume only: that letters, numbers, % `\texttt\bsl', `\texttt\{', `\texttt\}', `\texttt\#' and % `\texttt\%' have the usual categories. Styles (e.g., \prog{french}) % that make punctuation active foul up \cs{write}\,s of MF/MP code. This can % still occur in user-generated \cs{write}\,s, so maybe some code should be % added in \cs{mfpic} or \cs{mfsrc} command too. % \begin{macrocode} \edef\MFPrestoreequal{\catcode61\space\the\catcode61\relax}% \catcode61 12\relax% \edef\MFPrestorespace{\catcode32=\the\catcode32\relax}% \catcode32=10\relax% \edef\MFPrestoreEOL{\catcode13=\the\catcode13\relax}% \catcode13=5\relax \edef\MFPrestorelq{\catcode96=\the\catcode96\relax}% \catcode96=12 \def\MFPrestorecode#1{\catcode`\string#1=\the\catcode`#1\relax}% % \end{macrocode} % % \DescribeMacro{\MFPicpackagE} % This will be invoked at the end of the file to restore all the catcodes. % This will fail if some of these characters have really bad codes % (comment or escape, for example) but that would likely be the case only % if {\tt\bsl} or {\tt\%} have some different codes and then everything % above here would fail. % \begin{macrocode} \edef\MFPicpackagE{% \MFPrestorecode{@}\MFPrestorecode{-}% \MFPrestorecode{:}\MFPrestorecode{;}% \MFPrestorecode{.}\MFPrestorecode{,}% \MFPrestorecode{!}\MFPrestorecode{?}% \MFPrestorecode{(}\MFPrestorecode{)}% \MFPrestorecode{[}\MFPrestorecode{]}% \MFPrestorecode{'}\MFPrestorecode{/}% \MFPrestorecode{"}\MFPrestorecode{*}% \MFPrestorecode{$}\MFPrestorecode{+}% \MFPrestorecode{_}\MFPrestorecode{>}% \MFPrestorecode{<}\MFPrestorecode{~}% \MFPrestorelq\MFPrestoreEOL\MFPrestorespace \MFPrestoreequal\catcode 10=\number\catcode10}% % \end{macrocode} % % Set everything to normal except \texttt @=letter, \mfc{_}=other, and % \texttt \textasciitilde=other. Do this by putting the settings in a % macro and invoking the macro. That makes it possibly to redo the % settings inside some other macro, should that ever become necessary. % Characters 10 and 13 are \verb|^^J| and \verb|^^M|, control-J and % control-M. % % \begin{macrocode} \catcode`\@=11 \ifx\@makeother\UndEfInEd \def\@makeother#1{\catcode`#1=12\relax}\fi \def\mfp@sanitize{% \catcode10=12\catcode13=5\catcode`\$=3\catcode`\ =10 \@makeother\:\@makeother\;\@makeother\.\@makeother\,% \@makeother\!\@makeother\?\@makeother\(\@makeother\)% \@makeother\[\@makeother\]% \@makeother\'\@makeother\/\@makeother\"\@makeother\*% \@makeother\_\@makeother\`\@makeother\+\@makeother\=% \@makeother\>\@makeother\<\@makeother\~\@makeother\-}% \mfp@sanitize \edef\restorenewlinechar{\newlinechar=\number\newlinechar\relax}% \chardef\mfp@ctrlJ10 \chardef\mfp@ctrlM13 \newlinechar\mfp@ctrlJ\def\@nl{^^J}% % \end{macrocode} % % \subsection{Debugging and messages}\label{debug} % % \DescribeMacro{\ifmfpicdebug} % \DescribeMacro{\mfpicdebug} % To turn on debugging before option processing, the user must make sure % \cs{mfpicdebug} is defined. \cs{mfp@DBlog} writes it contents to the % log file only if debugging is on. % \begin{macrocode} \newif\ifmfpicdebug \ifx\mfpicdebug\UndEfInEd \mfpicdebugfalse \else \mfpicdebugtrue \fi \def\mfp@DBlog#1{% \ifmfpicdebug{\let\@msgbreak\mfp@errbrk\wlog{Mfpic debug: #1}}\fi}% % \end{macrocode} % Various kinds of messages to the screen and log file. \cs{mfp@msg} is only % used in the definition of the others and to write a blank line. We % always use the second, which identifies the source of the message, or % the third, which adds the word `warning'. The fourth is for errors % and provides for help if a user presses `\texttt h' in response to the % message. The bit with the spaces is to get a hanging indentation with % text properly aligned on screen. % \begin{macrocode} \def\mfp@msg#1{{\newlinechar\mfp@ctrlJ\immediate\write16{#1}}}% \def\@msgbreak{^^J}% \def\mfp@spaces{\space\space\space\space\space\space}% % \def\mfp@msgbrk{^^J\mfp@spaces\space}% \def\mfp@errbrk{\mfp@msgbrk\mfp@spaces}% \def\mfp@warnbrk{\mfp@errbrk\space\space}% % \def\Mfpic@msg#1{{\let\@msgbreak=\mfp@msgbrk \mfp@msg{Mfpic: #1 }}}% \def\Mfpic@warn#1{{\let\@msgbreak=\mfp@warnbrk \mfp@msg{^^JMfpic warning: #1}}}% \def\mfp@errmsg#1#2{{\newlinechar\mfp@ctrlJ \let\@msgbreak\mfp@errbrk \errhelp{#2}\errmessage{Mfpic error: #1}}}% % \end{macrocode} % % In \TeX{} 3.x we can identify the line being processed when a message is % issued. We do not support \TeX{} 2.x. The command \cs{@mfplineno} is % for information written into the output file. % \begin{macrocode} \def\@online{ on line \number\inputlineno}% \def\@mfplineno{line \number\inputlineno\space in TeX source}% % \end{macrocode} % % \subsection{Detecting the format}\label{format} % % To detect its environment, \mfpic{} needs to test whether certain % commands are defined. The \cs{@xp} is usually used to `expand away' % the rest of a conditional. \cs{@XP} does this from two levels deep in % a conditional. (We use \cs{@xp}\cs{@XP}\cs{@xp} later to expand % away from three levels.) Since it uses \cs{@firstoftwo} and % \cs{@secondoftwo}, we cannot use it to check their existence. % \begin{macrocode} \ifx\@firstoftwo\UndEfInEd \long\def\@firstoftwo#1#2{#1}\fi \ifx\@secondoftwo\UndEfInEd \long\def\@secondoftwo#1#2{#2}\fi \let\@xp\expandafter \def\@XP{\@xp\@xp\@xp}% \def\mfp@ifdefined#1{% \ifx#1\UndEfInEd \@xp\@secondoftwo \else\ifx#1\relax \@XP\@secondoftwo \else \@XP\@firstoftwo \fi\fi}% \mfp@ifdefined\@firstofone{}{\long\def\@firstofone#1{#1}}% % \end{macrocode} % % We test for the format. If all tests fail we assume plain\TeX{} or % something compatible. Mainly this is needed to support \LaTeX. I've done % a few things to work around \ConTeXt, but its been a moving target and % \mfpic{} didn't work in \ConTeXt{} the last time I tried. % % Here we see if \cs{documentstyle} is defined, and then make sure % we are not in \AmSTeX{}. Probably there is a better command to test, % and perhaps we should just test whether the functionality required is % present, but I'm not really sure how best to do either of those. % \begin{macrocode} \newif\if@mfp@latex \@mfp@latexfalse \mfp@ifdefined\documentstyle {{\def\x{AmS-TeX}% \ifx \fmtname\x \mfp@DBlog{AmS-TeX detected.}% \else \global\@mfp@latextrue \mfp@DBlog{LaTeX detected.}% \fi}}% {\mfp@DBlog{Neither LaTeX2e nor LaTeX209 nor AmS-TeX.}}% % \end{macrocode} % % We are in \LaTeXe{}, as opposed to \LaTeX2.09, if \cs{documentclass} % is defined. % \begin{macrocode} \newif\if@mfp@latexe \@mfp@latexefalse \mfp@ifdefined\documentclass {\@mfp@latexetrue \mfp@DBlog{LaTeX2e detected.}}% {\mfp@DBlog{Not LaTeX2e.}}% % \end{macrocode} % % We now test \cs{pdfoutput} to see if pdf support is needed. % \begin{macrocode} \newif\if@mfp@pdf \@mfp@pdffalse \mfp@ifdefined\pdfoutput {\mfp@DBlog{PdfTeX detected...}% \ifcase\pdfoutput \mfp@DBlog{...with dvi output.}% \else \@mfp@pdftrue \mfp@DBlog{...with PDF output.}% \fi}% {\mfp@DBlog{Not pdfTeX.}}% % \end{macrocode} % % \subsection{Blank line and spacing hacks}\label{spacing} % % In order for commands to always read their arguments correctly, % we need EOLs to have their normal category codes, but then a % blank line will end a paragraph, and we would like blank lines to be % ignored inside an \env{mfpic} environment. Therefore we turn off % \cs{par} inside that environment, and then need(?) to turn it back on % inside \cs{tlabel} and \cs{tcaption}. \cs{@@par} (in \LaTeX) and % \cs{endgraf} (in plain \TeX) should equal the primitive \cs{par}. % \begin{macrocode} \if@mfp@latex \else \let\@@par\endgraf \fi \def\mfp@restorepar{\let\par\@@par}% % \end{macrocode} % % Some \mfpic{} commands end with \cs{ignorespaces}. For some others a % better choice is the \LaTeX{} strategy of conditionally ignoring spaces. % \begin{macrocode} \if@mfp@latex\else \def\@namedef#1{\@xp\def\csname #1\endcsname}% \def\@nameuse#1{\csname #1\endcsname}% \fi \mfp@ifdefined\@bsphack{}% {\@nameuse{newskip}\@savsk \@nameuse{newcount}\@savsf \def\@bsphack{\relax \ifhmode \@savsk\lastskip \@savsf\spacefactor \fi}% \def\@esphack{\relax \ifhmode \spacefactor\@savsf \ifdim\@savsk>\z@ \ignorespaces \fi\fi}}% % \end{macrocode} % % We sometimes (either by accident or by choice) redefine things defined % in some formats. For the accidental redefinitions we want to be told, % and since we cannot assume \LaTeX{} with its \cs{newcommand}, we define % a simple check and print a warning when it happens. % \begin{macrocode} \mfp@DBlog{Defining test for previous definitions of macros.}% \mfp@ifdefined\mfp@testdef {\Mfpic@warn{% Hey! How can \string\mfp@testdef\space already be defined? % \@msgbreak I'll redefine it anyway!}}% {}% \def\mfp@testdef#1{% \ifx#1\UndEfInEd \else\ifx#1\relax \Mfpic@warn{\string #1 was previouly defined to be \string\relax.}% \else \Mfpic@warn{\string #1 is already defined!}% \fi\fi}% % \end{macrocode} % % \DescribeMacro{\newdef} % \DescribeMacro{\newlet} % Is the proposed definer of new definitions itself not new? Well, % we'd like a warning, but go ahead and define it anyway. All % \cs{newdef} does is check whether the macro being defined is already % defined, raise a warning (but \emph{not} an error) and define it % anyway. We do something similar with \cs{let}. % \begin{macrocode} \mfp@testdef\newdef \mfp@testdef\newlet \def\newdef#1{\mfp@testdef#1\def#1}% \newdef\newlet#1{\mfp@testdef#1\let#1}% % \end{macrocode} % % % \section{Configuring \mfpic{} behavior}\label{configuring} % % \subsection{Options}\label{options} % % \DescribeMacro{ifmfpmpost} % I have decided to make this a user-level macro so that a user can % write code that behaves one way for \MP{} and another for \MF. However % the commands to change the setting are private. % % Our switch to turn \MP{} support on or off needs to be global, so it % can't be a normal \cs{newif}. % \begin{macrocode} \global\let\ifmfpmpost\iffalse \newdef\mfp@mposttrue {\global\let\ifmfpmpost\iftrue}% \newdef\mfp@mpostfalse{\global\let\ifmfpmpost\iffalse}% \newdef\mfp@ifmpost{% \ifmfpmpost\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% % \end{macrocode} % % \DescribeMacro{\usemetafont} % We make a user-level commands for switching to the appropriate drawing % program. This is necessary for plain\TeX, but also used internally by % \mfpic. \CMF{} is the default. This command needs to not only clear the % boolean \cs{ifmfpmpost}, but also restore the default graphics inclusion % commands. Actually, it doesn't \emph{need} to unless \cs{usemetapost} % was previously issued to change the default. This would normally not % happen unless the user wanted to close the current graph file and open a % new one for \MF. % % \MP{} support requires macros for including EPS graphics. What works % best depends on the format, so we delay the definition of % \cs{usemetapost} until the \LaTeX{} options section, but we define the % error message here. % \begin{macrocode} \newdef\usemetafont{\mfp@mpostfalse \def\preparemfpicgraphic##1{}% \def\setmfpicgraphic##1{\@graphfont\char\mfp@count}% \def\getmfpicoffset##1{}}% \newdef\MPtoolate@error{% \mfp@errmsg {Command \string\usemetapost\space too late.}% {It is too late to select the metapost option.^^J% It must be selected before the \opengraphsfile command.^^J% If you proceed, the metafont option will be assumed.}}% % \end{macrocode} % % Some options need an open \file{.mf} or \file{.mp} file before they % can do anything. This means the \cs{opengraphsfile} command must have % been issued but not \cs{closegraphsfile}. Since those commands define and % undefine \cs{mfp@filename}, we use that as our test. % \begin{macrocode} \newdef\@ifmfpfileisopen{\mfp@ifdefined\mfp@filename}% % \end{macrocode} % % \DescribeMacro{\setmfvariable} % \DescribeMacro{\setmpvariable} % A useful abbreviation for a common requirement: declaring and setting % a \MF{} variable. I have decided to change it to a user level macro for % power users. \cs{setmpvariable} is another name for it. It takes three % arguments: the type of variable, the variable itself, and its value. % Example: \cs{setmfvariable}\marg{numeric}\marg{shadewd}\marg{.7pt}. % Since it \mfc{save}\,s the variable, it must not have a suffix. This is % not a big problem since mostly it is for internal use. We document % that fact for power users and advise ordinary users on the naming of % \MF{} variables. % % \DescribeMacro{\setmfboolean} % \DescribeMacro{\setmfnumeric} % \DescribeMacro{\setmfcolor} % Abbreviations for the most common internal uses. In the case of \MF, % color is the same numeric, but in \MP{} it is a separate variable type. % \begin{macrocode} \newdef\setmfvariable#1#2#3{% \@ifmfpfileisopen{\mfcmd{setvariable (#1) (#2) (#3)}}{}}% \newlet\setmpvariable\setmfvariable \newdef\setmfboolean#1#2{\setmfvariable{boolean}{#1}{#2}}% \newdef\setmfnumeric#1#2{\setmfvariable{numeric}{#1}{#2}}% \newdef\setmfcolor#1#2{\setmfvariable{color}{#1}{#2}}% % \end{macrocode} % % The command \cs{setmfvariable} arranges for the value of % that variable to be localized to each figure if set inside one, but % it is global otherwise. We have to be careful that \TeX{} and \MF{} % stay in sync, as they have different understandings as to what is % global and what is not. So we define a switch that will be set at the % start of an \env{mfpic} environment to test if a command is issued % inside one. % % We also define here \texttt{true} and \texttt{false} as macros. These % are strings we need to write to the output frequently. % \begin{macrocode} \let\ifin@mfpicenv\iffalse \newdef\mfp@local{\relax\ifin@mfpicenv\else\global\fi}% \newdef\mf@T{true}% \newdef\mf@F{false}% \newdef\mfp@let{\mfp@local\let}% \newdef\mfp@def{\mfp@local\def}% % \end{macrocode} % % \DescribeMacro{\usecenteredcaptions} % \DescribeMacro{\nocenteredcaptions} % This (\opt{centeredcaptions}) is the simplest option. Other options % follow a similar pattern: user-level commands are defined for % turning on (and sometimes turning off) the option. Selection of % centered captions can be turned on or off at will throughout a % document. % \begin{macrocode} \newdef\usecenteredcaptions{\mfp@let\if@mfp@centcapt\iftrue}% \newdef\nocenteredcaptions {\mfp@let\if@mfp@centcapt\iffalse}% \nocenteredcaptions % \end{macrocode} % % This common code is repeated almost verbatim four times, so we define % the following abbreviation. The first two arguments are the commands % to turn the option on and off. The third and fourth are the \TeX{} and % \MF{} booleans to switch. In all cases, the default for the option is % \emph{off}, so we run \texttt{\#2} at the end. % \begin{macrocode} \newdef\mfp@makeoption#1#2#3#4{% \newdef#1{\mfp@let#3\iftrue\setmfboolean{#4}\mf@T}% \newdef#2{\mfp@let#3\iffalse\setmfboolean{#4}\mf@F} #2}% % \end{macrocode} % % \DescribeMacro{\clipmfpic} % \DescribeMacro{\noclipmfpic} % The \opt{clip} option shows only what's inside the rectangle % given in the \cs{mfpic} command. It can be turned on or off for % each figure independently. The default is the old behavior: no % clipping. % % If the output file has not been opened, \cs{setmfboolean} does nothing. % But the \cs{opengraphsfile} code checks the boolean and writes the % appropriate code. % \begin{macrocode} \mfp@makeoption\clipmfpic\noclipmfpic\if@mfp@clip{clipall}% % \end{macrocode} % % \DescribeMacro{\usetruebbox} % \DescribeMacro{\notruebbox} % The \opt{truebbox} option lets \MP{} set the true bounding box (which % may differ from the numbers defined through \cs{mfpic}). % % We don't need to be too careful with the scope of truebbox. As % currently written, \TeX{} never needs to know the setting except to pass % the information on to \cs{opengraphsfile} if the option is set before % then. However, we treat it like most other settings, turning on or off % an appropriate \TeX{} boolean, in case it ever becomes necessary to know % the setting. It is local to any \env{mfpic}, global otherwise. The % default is to have \opt{truebbox} turned off. % \begin{macrocode} \mfp@makeoption\usetruebbox\notruebbox\if@mfp@truebbox{truebbox}% % \end{macrocode} % % Some options and commands require the \opt{metapost} option be in % effect. We define a generic error message for such cases. If a command % or option requires \MP, but the \opt{metapost} option is not set, the % option is ignored, or the command aborted. % \begin{macrocode} \newdef\noMP@error#1{% \mfp@errmsg {Metafont does not support #1, use MetaPost.}% {Metafont doesn't support #1. Perhaps you forgot to turn on^^J% MetaPost support by using the metapost option or issuing the^^J% command \usemetapost. For now, I will ignore it.}}% % \end{macrocode} % % \DescribeMacro{\usemplabels} % \DescribeMacro{\nomplabels} % An option to let \MP{} create labels, \opt{mplabels} mostly just % switches between two versions of \cs{tlabel} so no \MP{} booleans % are set and so syncronization of scope is not an issue. The default % is the old behavior: labels are placed by \TeX. The actual setting is % delayed until \cs{opengraphsfile} so the order of these commands and % \cs{usemetapost} is not significant (before \cs{opengraphsfile}). % % Because of the frequent need to check this setting, we define % \cs{@ifmplabels} to execute one of two alternatives based on it. % \begin{macrocode} \newdef\usemplabels{\mfp@let\if@mfp@mplabels\iftrue \@ifmfpfileisopen {\mfp@ifmpost{}% {\noMP@error{mplabels}\global\let\if@mfp@mplabels\iffalse}}{}}% \newdef\nomplabels{\mfp@let\if@mfp@mplabels\iffalse}% \newdef\@ifmplabels{% \if@mfp@mplabels\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% \nomplabels % \end{macrocode} % % \DescribeMacro{\overlaylabels} % \DescribeMacro{\nooverlaylabels} % These control an option to defer adding labels (in \MP) until the end % of the picture. That means they don't get clipped or covered up by any % drawing elements. Neither of these commands affect \MF, but they write % to the output file anyway if issued after \cs{opengraphsfile}. % \begin{macrocode} \mfp@makeoption% \overlaylabels\nooverlaylabels\if@mfp@overlabels{overlaylabels}% % \end{macrocode} % % \DescribeMacro{\clearsymbols} % \DescribeMacro{\noclearsymbols} % These determine whether the symbols drawn by \cs{plotsymbol} and % \cs{plotnodes} should have their interiors erased before being drawn. % \begin{macrocode} \mfp@makeoption% \clearsymbols\noclearsymbols\if@mfp@clearsym{clearsymbols}% % \end{macrocode} % % \subsection{Graphic inclusion}\label{graphic} % % \DescribeMacro{\mfpicllx} % \DescribeMacro{\mfpiclly} % The code to include a figure has been divided into three parts. Under % \opt{metapost} we need to both include the figure and save the % bounding box coordinates of the lower left corner. Here we initialize % the macros that hold these coordinates. % \begin{macrocode} \def\mfpicllx{0}% \def\mfpiclly{0}% % \end{macrocode} % % \DescribeMacro{\preparemfpicgraphic} % Most EPS inclusion macros make the bounding box information available, % and so after the inclusion command we just save it in the above two % macros. However, \LaTeX's \cs{includegraphics} does not, so we have to % issue a command before the inclusion to force it to become available. % That command is \cs{preparemfpicgraphic}. Usually it does nothing, % but in the \LaTeXe{} case it locally redefines one of the graphics % packages internal macros. % % \DescribeMacro{\setmfpicgraphic} % This command includes the graphic. The \mfpic{} default (for the % \opt{metafont} option) is set by running \cs{usemetafont}. % % \DescribeMacro{\getmfpicoffset} % This one saves the lower left corner in the macros \cs{mfpicllx} and % \cs{mfpiclly}. In the case described above, that is accomplished by % the redefined internal command, so this command does nothing. % % The command \cs{@setmfpicgraphic} is a wrapper around the inclusion % code. It takes the name of the graphic file and passes it along to the % above three commands. Those three commands can be redefined by the % user for special circumstances. The user is then responsible to make % sure \cs{mfpicllx} and \cs{mfpiclly} are properly set when necessary. % Redefining one may necessitate redefining one or both of the others. % % The definition of these three is delayed to the option processing % section, except under the \MF{} default: \cs{usemetafont} defines them. % \begin{macrocode} \newdef\@setmfpicgraphic#1{% \preparemfpicgraphic{#1}\setmfpicgraphic{#1}\getmfpicoffset{#1}}% \usemetafont % \end{macrocode} % % \DescribeMacro{\setfilename} % The user can also change \cs{setfilename} to modify the assumed % filenames of the graphics output by \MP. The default is to concatenate % the output file's basename with the picture number. % \begin{macrocode} \newdef\setfilename#1#2{#1.#2}% % \end{macrocode} % % \DescribeMacro{\ifmfpicdraft} % \DescribeMacro{\mfpicdraft} % \DescribeMacro{\mfpicfinal} % \DescribeMacro{\mfpicnowrite} % The \opt{draft}, \opt{final} and \opt{nowrite} options override % \mfpic's attempts to automatically detect whether the eps % files should be included. The \opt{final} option can also be used to % override a global draft option. Each of these sets the user level % if-command \cs{ifmfpicdraft}, which is retained for backward % compatibility. These settings are global since they are intended to % be set for the whole document. The four commands % \cs{@mfp@draft/finaltrue/false} are used to communicate with the % \cs{opengraphsfile} command, in case the user-level commands occur before % then. % \begin{macrocode} \newif\ifmfpicdraft \newif\if@mfp@draft \newif\if@mfp@final \newif\if@mfp@nowrite \newdef\mfpicdraft{% \@ifmfpfileisopen{\global\mfpicdrafttrue}% {\global\@mfp@drafttrue}}% \newdef\mfpicfinal{% \@ifmfpfileisopen{\global\mfpicdraftfalse}% {\global\@mfp@finaltrue}}% \newdef\mfpicnowrite{% \@ifmfpfileisopen {\mfp@errmsg {Improper use of command \string\mfpicnowrite\@online.}% {You must issue the command \mfpicnowrite prior to \opengraphsfile. It will be ignored now.}}% {\global\@mfp@nowritetrue}}% % \end{macrocode} % % \subsection{\CMP{} graphics and \LaTeX{} options}\label{latex} % % Code dependent on \LaTeXe. Mostly this is the option processing % facilities. % \begin{macrocode} \if@mfp@latexe \ProvidesPackage{mfpic}[2004/04/16 v0.7a beta.]% \DeclareOption{draft}{\mfpicdraft}% \DeclareOption{final}{\mfpicfinal}% \DeclareOption{nowrite}{\mfpicnowrite}% \DeclareOption{metapost}{\mfp@mposttrue}% \DeclareOption{metafont}{\usemetafont}% \DeclareOption{centeredcaptions}{\usecenteredcaptions}% \DeclareOption{clip}{\clipmfpic}% \DeclareOption{truebbox}{\usetruebbox}% \DeclareOption{mplabels}{\usemplabels}% \DeclareOption{overlaylabels}{\overlaylabels}% \DeclareOption{clearsymbols}{\clearsymbols}% \DeclareOption{debug}{\mfpicdebugtrue}% \DeclareOption*{% \@ifpackageloaded{graphics}% {\Mfpic@warn{Unrecognized option \CurrentOption.}}% {\Mfpic@msg{Passing option \CurrentOption\space to % graphics package.}% \PassOptionsToPackage{\CurrentOption}{graphics}}}% % \end{macrocode} % If \file{mfpic.cfg} exists, it will be input at this point. Then, % we \cs{ProcessOptions}, using the *-form because it allows package % options to take precedence over global options. Thus \mfpic's % \opt{final} option can counteract the \mfpic-specific side effects of a % global \opt{draft} option. % \begin{macrocode} \InputIfFileExists{mfpic.cfg}{}{}% \ProcessOptions*\relax % \end{macrocode} % % \DescribeMacro{\usemetapost} % Finally, one of the definitions of \cs{usemetapost}. The other is % for use outside \LaTeXe, when the \prog{graphics} package cannot be % assumed to be available. % \begin{macrocode} \def\usemetapost{% \@ifmfpfileisopen{\mfp@mpostfalse\MPtoolate@error}% {\mfp@mposttrue \RequirePackage{graphics}% % \end{macrocode} % % Unlike all the other eps inclusion macros, \cs{includegraphics} does % not make the bounding box coordinates available: \cs{Gin@llx} and the % others are defined, but are local to a group surrounding the internals % of \cs{includegraphics}. We locally modify one graphics package internal % macro to globally save the information we need. Here we save the % original definition and define our replacement. This definitely needs % to come after the above \cs{RequirePackage} command. % \begin{macrocode} \global\let\mfp@save@parse@bb\Gread@parse@bb \gdef\mfp@parse@bb##1 ##2 ##3 ##4 ##5\\{% \mfp@save@parse@bb##1 ##2 ##3 ##4 ##5\\% \xdef\mfpicllx{\Gin@llx}\xdef\mfpiclly{\Gin@lly}}% % \end{macrocode} % % The \prog{graphics} package (as opposed to the \prog{graphicx} package) % is far too dependent on actual extensions. Since we don't want to % force our users to rename all the graphics output by \MP, we have to % force \cs{includegraphics} to treat the current extension (some number) % as if it were `{\tt eps}' or `{\tt mps}' according to the context. We % decide which at this point. % \begin{macrocode} \if@mfp@pdf \gdef\mfp@Gtype{mps}% \else \gdef\mfp@Gtype{eps}% \fi % \end{macrocode} % % The code we add to \cs{setmfpicgraphic} replaces \cs{Gread@parse@bb} with % our own version. % \begin{macrocode} \gdef\preparemfpicgraphic##1{% \let\Gread@parse@bb\mfp@parse@bb}% \gdef\getmfpicoffset##1{}% \gdef\setmfpicgraphic##1{\includegraphics{##1}}}}% % \end{macrocode} % % \cs{ProcessOptions} doesn't allow \cs{RequirePackage}\marg{graphics}, % so the above and the following were not simply put inside % \cs{DeclareOption}\marg{metapost}. The \cs{AtEndDocument} command will % close the output file if the user forgot. % \begin{macrocode} \mfp@ifmpost{\usemetapost}{}% \AtEndDocument{\@closegraphsfile}% % \end{macrocode} % % Now those cases outside \LaTeXe{} that we try to support. % \begin{macrocode} \else \Mfpic@msg{\mfpfiledate\space v\mfpfileversion.}% % \end{macrocode} % % \DescribeMacro{\usemetapost} % The definition of \cs{usemetapost} depends on the setting of % \cs{if@mfp@pdf}: \file{epsf.tex} is used for regular \TeX{} and % \file{supp-pdf.tex} for \pdfTeX. % \begin{macrocode} \if@mfp@pdf \def\usemetapost{% \@ifmfpfileisopen{\mfp@mpostfalse\MPtoolate@error}% {\mfp@mposttrue \mfp@ifdefined\convertMPtoPDF{}{\input supp-pdf\relax}% % \end{macrocode} % The command \cs{convertMPtoPDF} takes the filename and and two % scaling factors. It parses the files PS contents to PDF code. It leaves % the bounding box info in macros \cs{MPllx}, etc. % \begin{macrocode} \gdef\setmfpicgraphic##1{\convertMPtoPDF{##1}{1}{1}}% \gdef\getmfpicoffset##1{% \xdef\mfpicllx{\MPllx}\xdef\mfpiclly{\MPlly}}}}% \else % \end{macrocode} % The final case is the generic plain\TeX, \AmSTeX, or \LaTeX2.09. Our % code uses the macros from \file{epsf.tex}, which should be present in % every installation that includes \prog{dvips}. The command % \cs{epsfbox} takes the filename, writes a \cs{special} for % \prog{dvips} (and other programs) and saves the bounding box % coordinates in \cs{epsfllx}, etc. % \begin{macrocode} \def\usemetapost{% \@ifmfpfileisopen{\mfp@mpostfalse\MPtoolate@error}% {\mfp@mposttrue \mfp@ifdefined\epsfbox {}{\input epsf\relax}% \gdef\setmfpicgraphic##1{\epsfbox{##1}}% \gdef\getmfpicoffset##1{% \xdef\mfpicllx{\epsfllx}\xdef\mfpiclly{\epsflly}}}}% \fi \fi % \end{macrocode} % % % \section{Optional parameter handling}\label{optional} % % We borrow \LaTeX's \cs{@ifnextchar} to have the advantage of % skipping spaces and EOLs, but we skip \cs{relax} as well. The reason for % this last is that an EOL will be set equal to \cs{relax} in certain % contexts and we want option handling to work the same there as % elsewhere. This could be a mistake, since \cs{relax} is a common method % to halt such things. However, there should be no occasion in an % \env{mfpic} environment where one would want a `\texttt[' to follow a % command and \emph{not} be an optional argument. In text label commands % we restore the meaning of blank lines, and EOLs ought to be normal. % % The first argument of \cs{mfp@ifnextchar} is the token being checked. It % doesn't have to be a character and we sometimes use \cs{mfp@ifnextchar} % to check whether a certain command follows. However, it is usually % `\texttt['. The next argument is the code to run if that character is % present, the last is code to use if the character is not present. The % first argument must end with code that handles the character. % % The reason for the \cs{long} in the code when the next token is % \cs{relax} is that it may be \cs{par} which has been \cs{let} equal to % \cs{relax} in \env{mfpic} environments. % \begin{macrocode} \mfp@DBlog{Handlers for optional parameters.}% \long\def\mfp@ifnextchar#1#2#3{% \let\mfptmp@d=#1\def\mfptmp@a{#2}% \def\mfptmp@b{#3}\mfp@checknext}% \def\mfp@checknext{\futurelet\@let@token\mfp@ifnch}% \def\mfp@ifnch{% \ifx\@let@token\@sptoken \let\mfptmp@c\eatspace@checknext \else\ifx\@let@token\relax \long\def\mfptmp@c##1{\mfp@checknext}% \else\ifx\@let@token\mfptmp@d \let\mfptmp@c\mfptmp@a \else \let\mfptmp@c\mfptmp@b \fi\fi\fi\mfptmp@c}% \begingroup \def\:{\global\let\@sptoken= }\: % \def\:{\eatspace@checknext}\@xp\gdef\: {\mfp@checknext}% \endgroup % \end{macrocode} % % I've taken to making an empty optional argument the default for a lot % of commands. I wanted to make it possible to have the same result for % empty brackets (i.e., \texttt{[]}) as for omitted brackets. % The following helps check for emptyness. It uses a simple \cs{if} so % that \texttt{\#1} will be expanded. I use a non-active % \texttt{\textasciitilde} to test for emptyness because, even if a tilde % should accidentally occur in \texttt{\#1}, it will most likely be active % and expand to something else. In fact, in plain \TeX, % \cs{mfp@ifempty}\marg{\textasciitilde} will compare % \texttt{\textasciitilde} to \cs{penalty} and in \LaTeX{} to % \cs{unhbox}. % % The \cs{@ifmtarg} macro is borrowed from \file{ifmtarg.sty}. % It is used when a space should count as empty, but expansion isn't % wanted. % \begin{macrocode} \newdef\mfp@ifempty#1{% \if~#1~\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% \begingroup \catcode`Q=3 \long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil}% \long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4}% \endgroup \newdef\@ifmtsub#1#2{\@ifmtarg{#1}{#2}{#1}}% \newdef\mfp@mtsub#1#2{\mfp@ifempty{#1}{#2}{#1}}% % \end{macrocode} % % The following is a historical holdover. Originally all optional arguments % were handled through \cs{do@ptparam}. Then there arose cases that did not % fit its assumptions and I wrote \cs{alt@ptparam}. Then, it became more % efficient to have \cs{mfp@ifnextchar} (defined above) and now % this command is defined in terms of it. % % The first argument of \cs{do@ptparam} is the command to use and the % second is a default value of the optional argument. The command must be % defined, and it must be a command whose first argument is delimited by % `{\tt[}' and `{\tt]}'. Currently this is no longer used: all commands % use one of the variants below. % \begin{macrocode} \newdef\do@ptparam#1#2{\mfp@ifnextchar[{#1}{#1[#2]}}% % \end{macrocode} % % These are variations on the above. In \cs{simple@opt}, if an optional % argument is present, we check to see if it is empty and substitute the % default if it is. This was so named because I intended that it be used % only if the optional argument required no further parsing (because it % turned the argument into a nondelimited one). But now we use it even % then and the few commands that require further parsing handle it more or % less ad hoc. % % \cs{null@opt} is a convenient abbreviation for a common case: the % default option is null. % \begin{macrocode} \newdef\simple@opt#1#2{% \mfp@ifnextchar[{\process@opt{#1}{#2}}{#1{#2}}}% \newdef\process@opt#1#2[#3]{% \mfp@ifempty{#3}{#1{#2}}{#1{#3}}}% \newdef\null@opt#1{\mfp@ifnextchar[{#1}{#1[]}}% % \end{macrocode} % % Quite a few \mfpic{} commands stuff several parameters into a % single optional argument. Generally, these commands can be coded to % proceed gracefully if the last parameter is missing (substituting a % default). However, if more than that are missing, \TeX{} gobbles the % closing bracket and produces pretty inscrutable error mesages. This % (adding extra information in one optional argument) was, in retrospect, % a bad design decision that was made for backward compatibility and % (originally) to minimize the changes in existing commands. % Unfortunately we are stuck with it for at least the near future. % % We use the following utility to check for empty optional parameters. % \begin{itemize} % \item {\tt\#1} is the parameter to test (passed by some other macro) % \item {\tt\#2} is what to use if {\tt\#1} is empty. % \item {\tt\#3} is the command being passed the optional argument % \end{itemize} % We use a \cs{mfp@ifempty} so \texttt{\#1} will get expanded (often we % pass arguments as macros). After the above revamping of optional % argument handling, we ended up needing this code only once. % \begin{macrocode} \newdef\do@mtparam#1#2#3{\mfp@ifempty{#1}{#3[#2]}{#3[#1]}}% % \end{macrocode} % % % \section{Writing to the \file{.mf} or \file{.mp} file}\label{writing} % % \subsection{Preserving linebreaks}\label{linebreaks} % % Some macros can take quite long arguments (we call them % \cs{@listmac}\,s), especially if they are automatically generated by % some program. While the output file need not ever be looked at, there % can be a problem with lines too long for the \MF{} executable's line % buffer. Plus, for debugging, we might want to examine the file \mfpic{} % writes. We therefore try to get at least the list macros to preserve % linebreaks on output. % % \DescribeMacro{\mfpicobeylines} % We make use of the \TeX{} property that expandable commands are % expanded inside \cs{write} commands, but unexpandable commands and % characters are written verbatim (almost). If this were the only % consideration, nothing would need to be done. But characters with % catagory code 5 (end-of-line) are converted to spaces upon reading, so % we have to change the category of the \cs{endlinechar}, or we have % change the \cs{endlinechar} to a character in a different category. % We do the former, because the line a macro starts on will already have % the end-of-line character added, but its category will not yet be % established. We need a category that \TeX{} will not \emph{ignore}, % but that nevertheless has no (or minimal) side effects if encountered in % a \TeX{} file. We therefore make it active, but \cs{let} it equal to % \cs{relax}. This makes the end-line-character unexpandable. % \begin{macrocode} \mfp@DBlog{Direct output to Metafont/Post file.}% \begingroup \catcode\mfp@ctrlM\active% \gdef\@activectrlM{^^M}% \gdef\mfpicobeylines{\catcode\mfp@ctrlM\active\let^^M\relax}% \endgroup % \end{macrocode} % % The choice \cs{relax} seems to be actually a slightly better choice % than \cs{endgraf} (which we used to use, and which equals the % unexpandable primative \cs{par}) because \cs{relax} is permitted before % the opening brace in the syntax of \meta{general text} (for token % variable assignments, \cs{write}, \cs{message}, and the like) as well as % being skipped in mfpic's version of \cs{@ifnextchar}. % % \DescribeMacro{\preservelines} % The character assigned to \cs{endlinechar} is added to the end of all % lines read in by \TeX. The character assigned to \cs{newlinechar} % will produce a newline when it occurs in a \cs{write}. Our % \cs{preservelines} ensures these are the same and makes the above % changes in category. % \begin{macrocode} \newdef\preservelines{\newlinechar\mfp@ctrlM \endlinechar\newlinechar \mfpicobeylines}% % \end{macrocode} % % \DescribeMacro{\unpreservelines} % This is no longer used and may some day be removed. Grouping is % enough to isolate effects of \cs{preservelines}. The command % \cs{unpreservelines} simply restores the catcode of control-M to the % control-M to the usual in formats consistent with plain \TeX. If we % really wanted to reverse the effects of \cs{preservelines}, we'd have to % save and restore the four items changed: the values of \cs{newlinchar} % and \cs{endlinechar}, the category of control-M, and the definition of % an active control-M. % \begin{macrocode} \newdef\unpreservelines{\catcode\mfp@ctrlM=5 }% % \end{macrocode} % % \DescribeMacro{\mfsrc} % \DescribeMacro{\mfcmd} % \DescribeMacro{\mflist} % We want these to issue \cs{preservelines} before the text is read % (and category codes assigned). Also we often want to add a few items to % the argument (figure macros append a semi-colon, list macros surround % with parentheses), so we isolate the common starting code in % \cs{@mfwrite}, and then invoke the appropriate continuation command. % The ending code is in \cs{@mfsrc}. The \cs{begingroup} in % \cs{@mfwrite} matches the \cs{endgroup} in \cs{@mfsrc}. The group % isolates the changes to EOLs. We also equate \cs{@nl} to an active % control-M so that it can be used for line breaks in cases where it is % inconvenient to make EOLs active (in the replacement text of % \cs{opengraphsfile} and \cs{@mfpic}, for example). % \begin{macrocode} \newdef\mfsrc {\@mfwrite\@mfsrc\mfsrc}% \newdef\mfcmd {\@mfwrite\@mfcmd}% \newdef\mflist{\@mfwrite\@mflist}% \newdef\@mfwrite{\begingroup \preservelines \let\@nl\@activectrlM}% % \end{macrocode} % % The macro \cs{@mfsrc} does the job of writing to files. The output % stream \cs{mfp@out} is declared later. The other two commands invoke % \cs{@mfsrc} on a slightly modified argument. The first argument to % \cs{@mfsrc} is the command that called it (for the error message), the % second is the code to write. % \begin{macrocode} \newdef\@mfsrc#1#2{% \@ifmfpfileisopen{\immediate\write\mfp@out{#2}}% {\nooutputfileerror{#1}}\endgroup}% \newdef\@mfcmd#1{\@mfsrc\mfcmd{#1;}}% \newdef\@mflist#1{\@mfsrc\mflist{(#1);}}% % \end{macrocode} % % \subsection{Initializing the output file}\label{output} % % Category 12 characters percent, sharp and backslash signs for the % \file{.mf} file. The command \cs{mf@d} is used to write a line of % dashes above and below each figure to make them stand out when debugging % the file. This might be removed in the final distribution. % \begin{macrocode} \newdef\mfp@gobble#1{}% \edef\mf@p{\@xp\mfp@gobble\string\%}% percent (%) \edef\mf@s{\@xp\mfp@gobble\string\#}% sharp (#) \edef\mf@b{\@xp\mfp@gobble\string\\}% backslash (\) \newdef\mf@d{--------------}% % \end{macrocode} % % Used to mark ends of things, \cs{mfp@delim} should never be expanded, % but we give it a definition for debugging purposes: % \begin{macrocode} \newdef\mfp@delim{% \mfp@errmsg {Misplaced \string\mfp@delim.}% {If you get this message but did not (mis)use the command^^J% \mfp@delim, please report this to the mfpic maintainer.}}% % \end{macrocode} % % The current date and time stamp will be written to the \file{.mf} file. % We calculate it here and store the result in these macros. The commands % \cs{normalyear} and \cs{normalmonth} are part of \ConTeXt, where they % have been equated to the primitive commands \cs{year} and \cs{month} % (which are then redefined). % \begin{macrocode} {\mfp@ifdefined\normalmonth {\let\month\normalmonth\let\year\normalyear}{}% \xdef\mfp@today{\number\year/\ifnum\month<10 0\fi\number\month/% \ifnum\day<10 0\fi\number\day}% \count2=\time \divide\count2 by 60 \xdef\mfp@now{\ifnum\count2<10 0\fi\number\count2:}% \multiply\count2 by -60 \advance\count2 \time \xdef\mfp@now{\mfp@now\ifnum\count2<10 0\fi\number\count2 }}% % \end{macrocode} % % These registers are allocated: % \begin{itemize} % \item \cs{mfp@out} Write stream for the \file{.mf} or \file{.mp} file. % \item \cs{mfp@graph} Read stream used to test existence of files and % for reading datafiles. % \item \cs{mfp@count} Number for next \env{mfpic} environment. % \item \cs{mfp@linetype} Current line style in multi-curve data plots. % \item \cs{mfp@n} Scratch counter, so far used only in writing data to % the \file{.mf} file. % \item \cs{mfp@sequence} Counter incremented with every datapoint written % from a file to implement the feature that a list of numeric data can be % plotted against its sequence position. % \item \cs{mfp@toks} Temporary token register. % \item \cs{every@tlabel} Tokens inserted at every \cs{tlabel}. % \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. % \end{itemize} % \begin{macrocode} \mfp@DBlog{Declarations used with data and graphs files.}% \newwrite\mfp@out \newread\mfp@graph \newlet\mfp@data\mfp@graph \newcount\mfp@count \newcount\mfp@linetype \newcount\mfp@n \newcount\mfp@sequence \newtoks\mfp@toks \newtoks\every@tlabel \newtoks\mfp@verbtex \newtoks\mfp@commonverbatimtex \every@tlabel{}% % \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. % \begin{macrocode} \begingroup \let\newtoks\relax \@makeother\%\@makeother\#\preservelines \global\mfp@commonverbatimtex= {\def\MFPtext#1{% \vbox{\def\\{\cr}\MFPcfont\everylabel \halign{##\hfil\cr#1\crcr}}}% }\endgroup % \end{macrocode} % % \DescribeMacro{\opengraphsfile} % This is the main command to set up the output file. It also aims to % check whether \MF{} or \MP{} has already been run on the output file, % thereby determining whether the graphics can be included. It does this % by checking for the existence of one of the products of these programs. % In the case of \MF{} it looks for a \file{.tfm} file; in the case of % \MP{} it looks for the first output graphic. % % The name of the output file is its only parameter, and it appends % the extension \file{.mf} or \file{.mp} depending on the whether option % \opt{metafont} or \opt{metapost} was chosen. % \begin{macrocode} \mfp@DBlog{Macros to open and close graphs files.}% \newdef\opengraphsfile#1{\@bsphack % \end{macrocode} % A command can determine if it occurs after \cs{opengraphsfile} but % before \cs{closegraphsfile} by testing whether \cs{mfp@filename} is defined. % \begin{macrocode} \@ifmfpfileisopen% {\Mfpic@warn {An attempt has been made to open a graph file, #1, \@msgbreak while another, \mfp@filename, is still open. \@msgbreak Closing \mfp@filename.}% \@closegraphsfile}% {}% \xdef\mfp@filename{#1}% % \end{macrocode} % The value of \cs{mfp@count} should be the number of the first figure. % We use the existence of that figure as a signal that there are graphics % to be included. % \begin{macrocode} \mfp@ifmpost{% \openin\mfp@graph=\setfilename{\mfp@filename}{\number\mfp@count}% \relax \ifeof\mfp@graph \mfp@msg{}% \Mfpic@msg {No file \setfilename{\mfp@filename}{\number\mfp@count}.^^J}% \global\mfpicdrafttrue \else \global\mfpicdraftfalse \fi % \end{macrocode} % Type out the \MP-specific portion of a reminder to process the % output. Then on to the \MF{} case. % \begin{macrocode} \if@mfp@nowrite \else \immediate\openout\mfp@out=\mfp@filename.mp\relax \Mfpic@msg{Don't forget to process \mfp@filename.mp! % \@msgbreak (Apply metapost to \mfp@filename.mp.)}% \fi }{% metafont % \end{macrocode} % Under the \opt{metafont} option, we check for the \file{.tfm} file. % We do not simply try to load the font because that might trigger % some \prog{maketfm} script which could be disastrous at this point, % when the \file{.mf} file is in an uncertain state. We open the % \file{.tfm} for input, and check \cs{ifeof}, as we did in the % \MP{} graphic case. % \begin{macrocode} \openin\mfp@graph=\mfp@filename.tfm\relax \ifeof\mfp@graph \mfp@msg{}% \Mfpic@msg{No file \mfp@filename.tfm .^^J}% \global\let\@graphfont=\mfp@dummy \global\mfpicdrafttrue % \end{macrocode} % If it does exist, we load the font and in either case type out the % \MF{} specific portion of our reminder. % \begin{macrocode} \else \global\font\@graphfont=\mfp@filename\relax \global\mfpicdraftfalse \fi \if@mfp@nowrite \else \immediate\openout\mfp@out=\mfp@filename.mf\relax \Mfpic@msg{Don't forget to process \mfp@filename.mf! % \@msgbreak (Apply metafont to \mfp@filename.mf, % then gftopk to the resulting gf file.)}% \fi }% % \end{macrocode} % The input stream used for testing is closed and the % unspecific portion of the reminder is typed out, then % the above settings of \cs{ifmfpicdraft} are overridden if the user has % explicitly chosen the \opt{draft} or \opt{final} option. The % \opt{nowrite} option merely disables the \cs{@mfsrc} command. % \begin{macrocode} \closein\mfp@graph \if@mfp@nowrite\else \Mfpic@msg{Then reprocess this file (\jobname).^^J}% \fi \if@mfp@draft\global\mfpicdrafttrue\fi \if@mfp@final\global\mfpicdraftfalse\fi \if@mfp@nowrite\gdef\@mfsrc##1##2{}\fi % \end{macrocode} % The first two lines of the output file are comments identifying the % file, the \mfpic{} version, the tex source file, and the date. % Then we let \grafbase{} know the \mfpic{} version creating the file. % After that we set the \mfc{mode}, the \mfc{mag} (both ignored by \MP), % and arrange for \grafbase{} macros to be loaded. The current % \grafbase{} checks the \gbc{mfpicversion}: if it is unknown, or not % equal to the value of \gbc{grafbaseversion}, a diagnostic message is % printed. % \begin{macrocode} \mfsrc{% \mf@p\space\mfp@filename.m\mfp@ifmpost{p}{f}, % generated by Mfpic, v\mfpfileversion\space\mfpfiledate,\@nl \mf@p\space from TeX source "\jobname" % on \mfp@today\space at \mfp@now\@nl numeric mfpicversion; mfpicversion:=\mfpicversion;\@nl if unknown mode: mode := localfont; fi\@nl if unknown mag: mag := \number\mag/1000; fi\@nl if unknown grafbase: input grafbase; fi\@nl\@nl % \end{macrocode} % Then a comparison of the version of this file, stored in % \cs{mfpicversion} with the version stored in the \grafbase{} variable % \mfc{grafbaseversion}. This should catch mismatches the previous test % would miss. % \begin{macrocode} if unknown grafbaseversion: grafbaseversion := 0; fi\@nl if grafbaseversion <> mfpicversion :\@nl GBmsg "Bad mfpic installation: mfpic and grafbase % versions do not match.";\@nl fi\@nl}% % \end{macrocode} % For \opt{metapost} we need to load some color macros also, and write % some setup for text labels (even if \cs{nomplabels}, because % \cs{usemplabels could be turned on later}). \MF{} now can also handle % the definitions in \file{dvipsnam.mp} but it seems a waste to load all % those definitions just to get a few more grayscales (even given \MF{} % can find that file). % \begin{macrocode} \mfp@ifmpost {\mfsrc{% if unknown Apricot: input dvipsnam.mp; fi\@nl verbatimtex\@nl \the\mfp@commonverbatimtex\@nl \def\noexpand\everylabel{\the\every@tlabel}\@nl \if@mfp@verbtex \the\mfp@verbtex\@nl \fi etex;\@nl}% \global\@mfp@verbtexfalse\mfp@verbtex{}% % \end{macrocode} % Finally, we write information to the output file, and/or set switches % based on the options as they are currently known. The \cs{usemplabels} % was delayed until now so that the order of it and \cs{usemetapost} % before now would not matter. The other five are issued now because they % might require a write to the output file. % \begin{macrocode} \@ifmplabels{\usemplabels}{}% \if@mfp@truebbox \usetruebbox \fi \if@mfp@overlabels \overlaylabels \fi}{}% \if@mfp@clip \clipmfpic \fi \if@mfp@clearsym \clearsymbols \fi \if@shipping\else\stopshipping\fi \@esphack}% % \end{macrocode} % % \DescribeMacro{\closegraphsfile} % This finishes off the output files and undefines \cs{mfp@filename}. % We define an error message free version \cs{@closegraphsfile} for % internal use. We unconditionally undefine \cs{mfp@filename} just in % case. % \begin{macrocode} \newdef\closegraphsfile{% \@ifmfpfileisopen{}{\nooutputfileerror\closegraphsfile}% \@closegraphsfile \global\let\mfp@filename\UndEfInEd}% \newdef\@closegraphsfile{% \@ifmfpfileisopen {\if@mfp@nowrite \else \mfsrc{\@nl end.}\immediate\closeout\mfp@out \fi}{}}% % \end{macrocode} % % \DescribeMacro{\nooutputfileerror} % We define a generic error message for macros that need an output file % to write to. \cs{mfsrc} uses it, as does \cs{closegraphsfile}. % \cs{mfpic} also uses it even though all its writes take place through % \cs{mfsrc}. This avoids potentially hundreds of error messages. % \begin{macrocode} \def\nooutputfileerror#1{% \mfp@errmsg {No output file has been opened.}% {You have tried to used a command, #1, that requires an output^^J% file to be opened with the \opengraphsfile command, which^^J% was either not issued or was not successful.}}% % \end{macrocode} % % % \section{\Mfpic{} dimensions}\label{dimensions} % % A number of packages, especially figure drawing packages, allocate a % great many dimension registers. The most familiar example is \PiCTeX{} % which is at least partially responsible for most ``No room for a new % \cs{dimen}'' error messages. \Mfpic{} also needs many dimension % values, but some are set by macros that simply write the value to the % \file{.mf} file and do not use any registers. A few are stored in % \TeX{} registers, but most are stored using a trick with font % dimensions. % \begin{macrocode} \mfp@DBlog{Using dummy font's dimensions, to spare TeX registers.}% % \end{macrocode} % While most fonts have relatively few font dimensions (twenty-two is a % common number), it turns out that if one loads a font and immediately % assigns a value to \cs{fontdimen}~$n$, Then \TeX{} acts as if the font % has \cs{fontdimen}\,s 0 through $n$ available. They can be assigned % dimension values just like \TeX{} dimension registers. % % Virtually all \TeX{} systems have a \file{dummy.tfm}, which contains % no characters (it is used for syntax checking by some packages and % classes). Since this trick will only work if we are the first to % load the font (the \AmSTeX{} document style \file{amsppt.sty} loads % the dummy font), we use another trick, which is to load it scaled to % some unlikely value, which \TeX{} treats as a new font. % \begin{macrocode} \font\mfp@dummy=dummy scaled 1042 \fontdimen100\mfp@dummy=0pt % \end{macrocode} % % Some versions of \file{dummy.tfm} have values already assigned to font % dimensions 0 through 22. It would probably not hurt to use those, but % we'll be cautious and use only font dimensions 23 and up, making 78 % available. % % We use an auxiliary count register to keep track of new font dimens. % \begin{macrocode} \newcount\mfp@fdc \mfp@fdc=22 % \end{macrocode} % \DescribeMacro{\newfdim} % We define a macros that mimics the behavior of \cs{newdimen}, for % allocating font dimension numbers. It increments \cs{mfp@fdc} and % defines its argument \texttt{\#1} to expand to an assignment of the % current \cs{fontdimen}. % \begin{macrocode} \newdef\newfdim#1{% \global\advance\mfp@fdc 1 \xdef#1{\fontdimen\number\mfp@fdc\mfp@dummy}% \wlog{\string#1=\string\fontdimen\number\mfp@fdc\mfp@dummy}}% % \end{macrocode} % The definition (\cs{xdef}) is global since font dimension % assignments are always global anyway. \TeX{} will not accept font % dimensions in its syntax for the dimension arithmetic commands % \cs{advance}, \cs{multiply} and \cs{divide}. In the rare cases where we % need to do this we assign the value to a temporary register and % calculate with it. It is, however OK to use them with a numeric factor. % % We allocate a couple of boxes. At the end of an \mfpic{} % environment, \cs{@wholegraph} is loaded with the picture (possibly % null) as it exists then. Inside the environment, when text labels are % processed, \cs{@textbox} holds this text temporarily so it can be % measured, moved about, etc. We also define abbreviations for the % frequent commands that specify the dimensions of \cs{@textbox} % \begin{macrocode} \mfp@DBlog{A box register for whole labeled graph, % and a temporary one.}% \newbox\@wholegraph \newbox\@textbox \newdef\tb@ht{\ht\@textbox}% height, \newdef\tb@dp{\dp\@textbox}% depth and \newdef\tb@wd{\wd\@textbox}% width of the text label. % \end{macrocode} % % When labels are processed, they are accumulated in the box % \cs{@alltlabels}. We allocate it, and four \cs{newfdim}\,s for the % location of the four sides. % \begin{macrocode} \newbox\@alltlabels \newfdim\@tlabelstop \newfdim\@tlabelsbot \newfdim\@tlabelsleft \newfdim\@tlabelsright % \end{macrocode} % % It can be argued that dimensions not needed by \TeX{} should be stored % in the output file rather than allocating (font) dimensions. These are % everything below from \cs{pointsize} through \cs{symbolspace}, % inclusive. This would make syncronictity between \TeX{} and \MF{} easier % to maintain. Those that are needed by \TeX{} are then few enough to be % regular \cs{dimen} registers, making them automatically local to each % \env{mfpic} environment. Unfortunately, changing to such a scheme could % break some past \mfpic{} files. It would also require recoding every % command that now writes one of these dimensions to the output. % % One of these (\cs{@graphright}) is unused, except for debugging. % We could also code around \cs{@graphwd} because it is always % \cs{wd}\cs{@wholegraph}. ^^A Is this true? Check it out. % \begin{macrocode} \mfp@DBlog{Internal dimension parameters for graph dimensions...}% \newfdim\@graphwd \newfdim\@graphright \newfdim\@graphleft \newfdim\@graphtop \newfdim\@graphbot \mfp@DBlog{...and dimension parameters for tlabel positioning.}% \newfdim\tb@raise \newfdim\tb@moveright \newfdim\tb@totalht % \end{macrocode} % % The following are for label adjustments. The first two are used to % implement the feature that all labels can be simultaneously shifted an % equal amount. The last is for the feature that the label can be a % certain distance separated from the point where it is placed. % \begin{macrocode} \newfdim\tlabel@hadj \newfdim\tlabel@vadj \newfdim\tlabel@sep \tlabel@hadj=0pt \tlabel@vadj=0pt \tlabel@sep=0pt % \end{macrocode} % % The following are default parameters for various graphics commands that % take an optional argument for the size of something. We allocate them, % and then initialize them. % \begin{macrocode} \mfp@DBlog{User level dimension parameters, with default settings.}% \newfdim\mfpicunit % unit of length \newfdim\pointsize % diameter of circle \newfdim\shadespace % spacing of shade dots \newfdim\polkadotspace % spacing of polkadots \newfdim\hatchspace % spacing of lines \newfdim\headlen % size of arrowhead (\arrow) \newfdim\axisheadlen % size of arrowhead (x, y axes) \newfdim\sideheadlen % size of arrowhead (border axes) \newfdim\hashlen % length of marks on axes \newfdim\dashlen % length of dashes (\dashed) \newfdim\dashspace % space between dashes \newfdim\dotsize % size of dots (\dotted) \newfdim\dotspace % space between dots \newfdim\symbolspace % space between symbols (\plot) % \mfpicunit=1pt \pointsize=2pt \shadespace=1pt \polkadotspace=10pt \hatchspace=3pt \headlen=3pt \axisheadlen=5pt \sideheadlen=0pt \hashlen=4pt \dashlen=4pt \dashspace=4pt \dotsize=0.5pt \dotspace=3pt \symbolspace=5pt % \end{macrocode} % % Font dimensions are global, and so not restricted to an \env{mfpic} % environment even when assigned inside one. This would require the % user to restore a value every time one picture needed a different % value from the rest. To avoid requiring this, the following macro is % used to save all values of these dimensions at the start of a picture, % and to restore the saved values at the end. (Some internal dimensions % (\cs{@graph...}, for example) don't need saving since they are reset % with each picture.) % \begin{macrocode} \newdef\save@mfpicdimens{% \edef\restore@mfpicdimens{% \mfpicunit =\the\mfpicunit \pointsize =\the\pointsize \shadespace =\the\shadespace \polkadotspace =\the\polkadotspace \hatchspace =\the\hatchspace \headlen =\the\headlen \axisheadlen =\the\axisheadlen \sideheadlen =\the\sideheadlen \hashlen =\the\hashlen \dashlen =\the\dashlen \dashspace =\the\dashspace \dotsize =\the\dotsize \dotspace =\the\dotspace \symbolspace =\the\symbolspace \tlabel@hadj =\the\tlabel@hadj \tlabel@vadj =\the\tlabel@vadj \tlabel@sep =\the\tlabel@sep}}% % \end{macrocode} % % \DescribeMacro{\mfpframesep} % \DescribeMacro{\mfpframethickness} % \DescribeMacro{\mfpicheight} % \DescribeMacro{\mfpicwidth} % \DescribeMacro{\mfpiccaptionskip} % Here are the few dimension registers we do allocate. The first two are % scratch registers, the next two govern frames, and the last two are set % after each picture to that pictures size. A \cs{vskip} of % \cs{mfpiccaptionskip} is placed between figure and caption by % \cs{tcaption}. % \begin{macrocode} \newdimen\mfp@scratch \newdimen\mfp@scratchB \newdimen\mfpframesep \newdimen\mfpframethickness \newdimen\mfpicheight \newdimen\mfpicwidth \newskip\mfpiccaptionskip \mfpframethickness0.4pt \mfpframesep2pt \mfpiccaptionskip=\medskipamount % \end{macrocode} % % % \section{Helper macros}\label{helper} % % \DescribeMacro{\mfpicnumber} % We make a user-level macro for setting the number of the next graph. % The purpose of this is so that the output file can be used as a font, % setting the figure numbers to the ascii codes of printable characters. % Then creating a composite figure is as easy as changing fonts: % \marg{\cs{pic} ABABAAB}. The motivation came from a discussion on % \texttt{comp.text.tex} started by someone who wanted to input a sequence % of 0's and 1's and get a corresponding sequence of black and white % squares. % \begin{macrocode} \def\mfpicnumber#1{\global\mfp@count=#1\relax}% % \end{macrocode} % % \DescribeMacro{\mfpaddto} % When placing text at intervals on an axis, we need to automatically % calculate coordinates to feed to the \cs{tlabel} command. The % following is a utility macro to add two real numbers. It is currently % used only in the \cs{axislabels} command, so it needn't be globally % defined, but it might be handy in the future. % \begin{itemize} % \item[] \texttt{\#1} is a \emph{macro} that expands to some number. % \item[] \texttt{\#2} is a number to add to it. % \end{itemize} % The result is stored again in \texttt{\#1}, overwriting the old value. % % \DescribeMacro{\mfpmultiply} % For my personal use (or for power users), this is the multiplicative % version, with the same syntax and behavior. % \begin{macrocode} \newdef\mfpaddto#1#2{\mfp@scratch=#1pt\advance\mfp@scratch#2pt \edef#1{\mfp@strippt\mfp@scratch}}% \newdef\mfpmultiply#1#2{\mfp@scratch=#1pt \mfp@scratch#2\mfp@scratch \edef#1{\mfp@strippt\mfp@scratch}}% \begingroup \@makeother P\@makeother T\lowercase{\gdef\mfp@factor#1PT{#1}}% \endgroup \newdef\mfp@strippt{\@xp\mfp@factor\the}% % \end{macrocode} % % A few user-level utilities. % % \DescribeMacro{\pointdef} % A point defining macro, suggested by a user. % \begin{itemize} % \item[] \texttt{\#1} is a symbolic name for a point, only letters. % \item[] \texttt{\#2} and \texttt{\#3} are the coordinates. % \item[] Usage: \cs{pointdef}\marg{A}\parg{2,5} makes \cs{A} expand % to \texttt{(2,5)}, \cs{Ax} to \texttt{2}, and \cs{Ay} to % \texttt{5}. % \end{itemize} % \begin{macrocode} \newdef\pointdef#1(#2,#3){% \@namedef{#1}{(#2,#3)}\@namedef{#1x}{#2}\@namedef{#1y}{#3}}% % \end{macrocode} % % \DescribeMacro{\pairarray} % \DescribeMacro{\numericarray} % The first enables the simultaneous definition of \MF{} pair variables % \mfc{A1}, \mfc{A2}, etc, \mfc{A[n]} by writing, % \cs{pairarray}\marg{A}\marg{\meta{list}}, the list being a list of % $n$ ordred pairs. Numeric variables can be created similarly with the % second command. % \begin{macrocode} \newdef\pairarray#1{% \mfcmd{save #1}\mfsrc{textpairs (#1)}\mfp@writedata}% \newdef\numericarray#1{\mfcmd{save #1; numeric #1; numeric #1[]}% \mfsrc{list (#1)}\mfp@writedata}% % \end{macrocode} % % \DescribeMacro{\lightershade} % \DescribeMacro{\darkershade} % Shade adjustment macros. They just multiply or divide \cs{shadespace} % by 1.2. % \begin{macrocode} \newdef\lightershade{\shadespace=1.2\shadespace}% \newdef\darkershade{\shadespace=.833333\shadespace}% % \end{macrocode} % % \DescribeMacro{\dashlineset} % \DescribeMacro{\dotlineset} % The following arrange for contrastive dashed lines. \cs{dashlineset} % just resets the default parameters that the \cs{dashed} macro uses, % \cs{dotlineset} sets these parameters so that \cs{dashed} produces % something almost dotted. % \begin{macrocode} \newdef\dashlineset{\dashlen=4pt \dashspace=4pt}% \newdef\dotlineset{\dashlen=1pt \dashspace=2pt}% % \end{macrocode} % % \DescribeMacro{\ifpointfill} % With the commands \cs{pointfilltrue} or \cs{pointfillfalse} the user % can specify points drawn with the \cs{point} command to be either % filled in or not. % \begin{macrocode} \let\ifpointfill\iftrue \newdef\pointfilltrue{\mfp@let\ifpointfill\iftrue}% \newdef\pointfillfalse{\mfp@let\ifpointfill\iffalse}% % \end{macrocode} % % % \section{Macros to implement prefix commands}\label{prefix} % % \Mfpic{} prefix macros change the behavior of the figure macros. % Normally we want \cs{circle}\marg{...} to draw the solid outline of a % circle. So normally \cs{circle}\marg{...} will write a drawing command % followed by a path expression giving the circle to draw. But % \cs{dashed}\cs{circle}\marg{...} should write a \emph{dashing} command % and \emph{omit} the drawing command. Thus, \emph{rendering} macros % like \cs{dashed} need to set a switch, and figure macros like % \cs{circle} need to test that switch. % % Similar considerations hold for prefix macros that transform the % figure. The logic is that, at the \MF{} level, every figure macro % is syntactically a path expression. Every prefix accepts a path % expression as input and has a path as its return value, so a % combination prefix + path expression is again a path expression. % Prefixes may also have side effects, such as adding some ink to the % current picture. Such prefixes are called \emph{rendering} macros. % Rendering macros normally return the same path as their argument, but % there are macros that modify the path. Some applying a linear % transform, some close an open path, some return a subpath. These we call % \emph{modification} macros. % % This scheme is quite simple, but unfortunately too simple. To avoid % having to explicitly type a rendering prefix every time, we need % the above mentioned ability to pass information to the figure macros. % Moreover, \MF{} abhors an `isolated expression', so the first prefix % has to write something with a different syntax, and pass the info that % it has already done so on to later prefixes, who need to test that % info. % \begin{macrocode} \mfp@DBlog{Tests to control multiple prefix commands.}% % \end{macrocode} % % Every prefix macro needs to know if it is the first or a later one. % They test this \cs{if} command and also set it to false. The % figure macros, which are last in the chain, close by resetting it true. % \begin{macrocode} \newif\if@startfig\@startfigtrue % \end{macrocode} % % If a prefix is a rendering prefix, it writes the rendering code % and sets the following switch to false, letting the figure macro know % it needn't invoke the default rendering, % Figure macros close by resetting it true. Some modification macros don't % touch it at all (the \cs{@modmac}\,s) others just test it % (\cs{@closmac}\,s). % \begin{macrocode} \newif\if@imrend\@imrendtrue % \end{macrocode} % % The following macro is always (and only) invoked by the first prefix % macro. It writes the code that prevents an isolated expression. It % stores the following path expression in the variable \gbc{curpath}. Thus % every combination of prefixes followed by a figure macro is % syntactically a \MF{} variable assignment command. % \begin{macrocode} \newdef\store@path{\mfsrc{\@nl store (curpath)}}% % \end{macrocode} % % Every prefix and figure macro has to invoke \cs{@firststage}, since % each is potentially the first in the sequence. If % \cs{if@startfig} is true, it writes the storing command, sets % \cs{@startfigfalse}, and says that rendering is needed. (The % rendering macros immediately cancel that switch.) % \begin{macrocode} \newdef\@firststage{\relax \if@startfig \store@path \@imrendtrue \@startfigfalse\fi}% % \end{macrocode} % % \DescribeMacro{\@rendmac} % Every rendering macro invokes this command. After the first-stage code % it writes its rendering command (via \cs{mfsrc}) and passes on the info % that rendering is no longer required of the figure macro. % \begin{macrocode} \newdef\@rendmac{\@firststage \@imrendfalse \mfsrc}% % \end{macrocode} % % \DescribeMacro{\@modmac} % It is possible we should call this something else, as only \cs{arrow} % and \cs{reverse} use \cs{@modmac}. Other modifications cause the % modified path to be drawn as if (modifier+figure) were a solitary figure % macro. This would be pointless for a reversed path or a path with % arrowhead added, as presumably the original path would already be drawn. % Moreover, it can be argued (for \MP{} at least) that the arrowhead % should be drawn on top of the shaft. This is the only significant effect of % coding \cs{arrow} and \cs{reverse} as \cs{@modmac}\,s. % % It simply invokes the common first-stage code and writes its \MF{} code. % \begin{macrocode} \newdef\@modmac{\@firststage \mfsrc}% % \end{macrocode} % % \DescribeMacro{\@closmac} % Other modification macros were added later, and it turned out that % they needed the same treatment as the closure macros that already % existed. Therefore, most modification macros invoke \cs{@closmac}. The % \emph{figure} macros proceed as follows: they invoke the \cs{@firststage} % code, then write a rendering macro if necessary, then make % \cs{@starfigtrue} (for the next figure), then write \MF{} code that % defines the path. These modification macros do only the first two, % counting on the figure macro to follow to invoke the last two. The idea % is that {closure + figure} should act the same as if the path it defines % were encoded as a single figure command. % % The \cs{@modmac} and \cs{@closmac} macros differ only when there are % no preceeding rendering macros. In that case it is as if \cs{draw} (or % more generally \cs{@render}) precedes the \cs{@closmac} macro. That % drawing happens \emph{in addition to} any rendering macros that follow. % This implicitly added \cs{draw} is not present for \cs{@modmac} macros, % unless it is added by the following figure macro itself. % \begin{macrocode} \newdef\@closmac{\@firststage \if@imrend\@xp\@render\fi \mfsrc}% % \end{macrocode} % % \DescribeMacro{\setrender} % As mentioned above, when a figure macro is invoked without a % rendering prefix, it will invoke some default. That default is stored % in the macro \cs{@render}, which can be changed for special effects. % Initially we define it as \cs{draw} to draw solid paths, but provide a % command for the user to change it. % \begin{macrocode} \newdef\@render{\draw[]}% \newdef\setrender#1{\mfp@def\@render{#1}}% % \end{macrocode} % % \DescribeMacro{\@figmac} % A figure macro will invoke the common first-stage code, then check % if rendering is needed. If so, it issues the \cs{@render} command. % It also resets the startfig switche. Since a figure macro completes % an assignment command in \MF, we use \cs{mfcmd}, which places a % semicolon at the end of the code it writes. We define the first part % (all but the writing) as a separate command because there are a few cases % where we need to delay that writing. % \begin{macrocode} \newdef\@figmacstart{% \@firststage \if@imrend\@xp\@render\fi \@startfigtrue}% \newdef\@figmac{\@figmacstart\mfcmd}% % \end{macrocode} % % \DescribeMacro{\@listmac} % The list macros take as their last argument a list of $(x,y)$ pairs. % That list can either be typed directly into % the \TeX{} source file (inside braces, separated by commas) or be % present in an external datafile. Either way, the data is written % as a list of \MF{} pairs within an enclosing pair of % parentheses. Since these are all figure macros, \cs{@listmac} starts out % just like \cs{@figmac}, but it writes only part of its arguments, the % last one being handled by \cs{mfp@writedata}. % % \cs{mfp@writedata} looks ahead to see if the token \cs{datafile} % follows, if it does \cs{mfp@writefile} is invoked, which gobbles % the \cs{datafile} token and processes the filename that should follow it. % Otherwise, \cs{mflist} is invoked to write the list in braces % that should follow. % % \cs{mfp@writedata} is also used by non-figure macros such as the axis % marks macros, plus \cs{piechart} and \cs{barchart}. % \begin{macrocode} \newdef\@listmac#1{\@figmacstart\mfsrc{#1}\mfp@writedata}% \newdef\mfp@writedata{% \mfp@ifnextchar\datafile{\mfp@writefile}{\mflist}}% \newdef\mfp@writefile\datafile#1{\@processdatafile{#1}{\mfp@rwdata}}% % \end{macrocode} % % \DescribeMacro{\mftitle} % \DescribeMacro{\tmtitle} % These go here because they didn't seem to go anywhere else. The are % mainly for debugging the example files. \cs{getmfp@toks} assigns the % following group to a token register and then invokes its argument. % \cs{mftitle} and \cs{tmtitle} use this to write the code into % the string argument of the \grafbase{} command \gbc{mftitle}. % \cs{mftitle} does only that, while \cs{tmtitle} also writes the argument % to the \file{.log} file and typesets it in the document. % % We write the argument as a token list because that is the the easiest % verbatim-like way to do it. % \begin{macrocode} \newif\if@mfpswitch \newdef\mftitle{\@bsphack\@mfpswitchtrue\mfp@gettoks\mf@title}% \newdef\tmtitle{\mfp@gettoks\tm@title}% \newdef\mfp@gettoks#1{\afterassignment#1\mfp@toks=}% \newdef\tm@title{\@mfpswitchfalse\mf@title \wlog{\the\mfp@toks}{\the\mfp@toks}}% \newdef\mf@title{\mfsrc{}% \immediate\write\mfp@out{mftitle "\the\mfp@toks";}% \if@mfpswitch\@esphack\fi}% % \end{macrocode} % % \DescribeMacro{\noship} % \DescribeMacro{\stopshipping} % \DescribeMacro{\resumeshipping} % To turn off character shipping for duration of innermost enclosing % group (eg, \env{mfpic} environment). As far as I know it has never been % tested with \MP. (It hasn't been tested recently even in \MF.) The \MF{} % code prevents the figure from being added to the font, the \TeX{} switch % \texttt{shipping} is checked before \cs{endmfpic} attempts to add the % (nonexistent) figure to the document. % \begin{macrocode} \newdef\stopshipping{\mfp@let\if@shipping\iffalse \@ifmfpfileisopen{\mfcmd{save shipit;def shipit = relax enddef}}{}}% \newdef\resumeshipping{\mfp@let\if@shipping\iftrue \@ifmfpfileisopen{\mfcmd{save shipit;def shipit = shipit_ enddef}}{}}% \newlet\noship\stopshipping \resumeshipping % \end{macrocode} % % % \section{Macros for getting data from files}\label{rwdata} % % The following command contains the common code to open a data file for % reading. The first parameter is the filename, the second is what to do % if it exists and is nonempty. We first try to \cs{openin} the file and % issue an error message if that fails. Then we skip any initial blank % lines and comments and complain if that takes us to the end of the % file. Otherwise we execute the command specified. Afterwards, since % each \cs{plotdata} command in a given \env{mfpic} environment % starts with the linetype at which the previous one ended, we allow the % value of \cs{mfp@linetype} to survive the group. If \texttt{\#2} is % not \cs{plotdata}, this is harmless (I hope). % \begin{macrocode} \newdef\@processdatafile#1#2{% \openin\mfp@data=#1\relax \ifeof\mfp@data \nodatafileerror{#1}% \else \begingroup \mfp@resetwhitespace \mfp@setcomment \skipBlanksandComments \ifeof\mfp@data \emptydatafileerror{#1}\else #2\fi \global\mfp@n=\mfp@linetype \endgroup \mfp@linetype=\mfp@n \fi \closein\mfp@data}% % \end{macrocode} % % \DescribeMacro{\nodatafileerror} % \DescribeMacro{\emptydatafileerror} % These are error messages for missing or empty data files: % \begin{macrocode} \newdef\nodatafileerror#1{% \mfp@errmsg{No data file: #1 .}% {The data file you tried to plot can't be found.}}% \newdef\emptydatafileerror#1{% \mfp@errmsg{Empty data file: #1 .}% {The file you tried to plot contains only empty lines and comments.}}% % \end{macrocode} % % When reading files it is important that white space in the files % always have the same meaning for \TeX{}. This utility resets spaces, % tabs and EOLs to the standard categories. % \begin{macrocode} \newdef\mfp@resetwhitespace{% \catcode`\^^M=5 \catcode`\ =10 \catcode`\^^I=10 }% % \end{macrocode} % % \DescribeMacro{\skipcomments} % This does what it says, skipping comments in a data file. It reads a % line from a previously opened file (input stream \cs{mfp@data}) and % compares it to \cs{@empty}. It calls itself when they are equal (a % comment line). When this macro finishes, \cs{mfp@temp} contains either % \cs{par} (blank line or EOF) or real data. % \begin{macrocode} \mfp@ifdefined\@empty{}{\def\@empty{}}% \newdef\skipcomments{\read\mfp@data to \mfp@temp \ifx\mfp@temp\@empty \@xp\skipcomments\fi}% % \end{macrocode} % % \DescribeMacro{\skipBlanksandComments} % This command first skips comments. After that \cs{mfp@temp} can contain % \cs{par}, indicating either EOF or a blank line, or something else. % In the first case (EOF) the macro terminates, in the second case (blank) % it calls itself again, in the third case it also terminates, having % presumably found real data. % % When this is called, a file should already be open (by % \cs{@processdatafile}) using the handle \cs{mfp@data}. % % The macro \cs{@XP} causes two macros after the next token to be % expanded, removing the two \cs{fi}\,s (and so avoiding deep nesting). % \begin{macrocode} \newdef\skipBlanksandComments{\skipcomments \ifeof\mfp@data \else\ifx\mfp@temp\mfp@par \@XP\skipBlanksandComments \fi\fi}% % \end{macrocode} % % The following two commands, \cs{mfp@rwdata} and \cs{mfp@rwdataloop} % perform the work of writing the file (read stream \cs{mfp@data} opened % by \cs{@processdatafile}). % % The counter \cs{mfp@n} is used to keep track of how many lines of the % data file have been written to one line of the output. The token % \cs{sequence} in a \cs{using} specification will expand to the value of % the counter \cs{mfp@sequence}. % % When this first macro is called, a non-blank line has been read to the % macro \cs{mfp@temp}, to which we now add a space. The macro % \cs{mfp@buffer} is what will be written to the output file as soon as it % is long enough. We initialize it by defining it to be an open % parenthesis followed by the result of applying \cs{parse@data} to the % contents of \cs{mfp@temp}. Then we call \cs{mfp@rwdataloop}, which does % the actual reading and writing. % \begin{macrocode} \def\mfp@rwdata{\mfp@n=1 \mfp@sequence=1 \def\sequence{\number\mfp@sequence}% \edef\mfp@temp{\mfp@temp\space}% \edef\mfp@buffer{(\@xp\parse@data\mfp@temp\mfp@delim}% \mfp@rwdataloop}% % \end{macrocode} % % At this point, the buffer has been started with the first datum, so we % read another line. If that is blank, we write the buffer (and the closing % parenthesis and a semicolon) and terminate the loop. Otherwise we go % through a loop: % \begin{enumerate} % \item Increment the sequence counter, % \item add a comma to the buffer, % \item test whether the buffer is `full', and % \item add the datum to the buffer. If the buffer is full in step~3, it is % written to the output and cleared before going to step~4. % \end{enumerate} % \cs{mfp@rwdataloop} loops by calling itself at the end. Whenever % \cs{mfp@temp} is empty (comment line read), (1)--(4) are skipped and % another line read. % \begin{macrocode} \def\mfp@rwdataloop{% \read\mfp@data to \mfp@temp \ifx\mfp@temp\mfp@par \mfcmd{\mfp@buffer)}% \else \ifx\mfp@temp\@empty % comment line, read another \else \edef\mfp@temp{\mfp@temp\space}% \advance\mfp@sequence1 \edef\mfp@buffer{\mfp@buffer\mfp@join}% \ifnum\mfp@n<\mfpdataperline\relax \advance\mfp@n1 \else \mfsrc{\mfp@buffer}% \mfp@n=1 \def\mfp@buffer{}% \fi \edef\mfp@buffer{\mfp@buffer \@xp\parse@data\mfp@temp\mfp@delim}% \fi \@xp\mfp@rwdataloop \fi}% % \end{macrocode} % % % \section{Various \CMF{} Settings.}\label{MFsettings} % % \DescribeMacro{\drawpen} % \DescribeMacro{\pen} % \DescribeMacro{\penwd} % Macros that write changes in default \grafbase{} variables now use the % construct ``\gbc{save x; x; x := ;}'' (via a call to % \cs{setmfvariable}). This makes changes local if inside a given \env{mfpic} % environment, global if outside. An exception is \gbc{penwd} which, as an % internal variable uses `\gbc{interim}' instead (via the \grafbase{} % command \gbc{resizedrawpen}). Both \cs{drawpen} and \cs{pen} have been % used in the past, while \cs{penwd} is more consistent with other % commands, so we keep all three. % \begin{macrocode} \newdef\drawpen#1{\mfcmd{\@nl resizedrawpen (#1)}}% \newlet\pen=\drawpen \newlet\penwd=\drawpen % \end{macrocode} % % \DescribeMacro{\shadewd} % The \cs{shade} macro works in \MF{} by adding many copies of the small % picture \gbc{shadedot} to the figure, in \MP{} the parameters % \gbc{shadewd} and \cs{shadespace} are simply used to calculate a level % of gray and a color fill is used. % % \DescribeMacro{\polkadotwd} % However, both \MF{} and \MP{} handle polkadots the same. The only % difference is \MF's need for fitting to a pixel grid. But that is % handled in \grafbase. % \begin{macrocode} \newdef\shadewd#1{\setmfnumeric{shadewd}{#1}}% \newdef\polkadotwd#1{\setmfnumeric{polkadotwd}{#1}}% % \end{macrocode} % % \DescribeMacro{\hatchwd} % The thickness of lines in the hatching fill. % \begin{macrocode} \newdef\hatchwd#1{\setmfnumeric{hatchwd}{#1}% \setmfvariable{pen}{hatchpen}{pencircle scaled hatchwd}}% % \end{macrocode} % % \DescribeMacro{\dashpattern} % A dash pattern consists (internal to \MF) of three arrays. The % \grafbase{} command \gbc{dashpat} accepts a name, and a sequence of % numbers representing the sizes of dashes and spaces, and builds these % arrays. % \begin{macrocode} \newdef\dashpattern#1#2{\mfcmd{save #1; dashpat (#1) (#2)}}% % \end{macrocode} % % \DescribeMacro{\settension} % This sets the default tension for \cs{curve} commands, as well as for % any command that takes an optional argument of the form % \oarg{s\meta{tens}}. This includes \cs{function}, \cs{plrfcn}, % \cs{fcncurve}, \cs{datafile}, \cs{plotdata} and others. It also sets the % default tension for \cs{sclosed} and \cs{bclosed}. The value should be % at least $3/4$. % \begin{macrocode} \newdef\settension#1{\setmfnumeric{default_tension}{#1}}% % \end{macrocode} % % % \section{Settings for text label placement in % figures}\label{labelsettings} % % \cs{tlabel}\,s are `justified' by placing a particular point of the % text at the location specified. The \cs{tlabel} command accepts an % optional argument containing two letters. There are 4 possibilities % for the first and three for the second. It turns out to be easier to % process these if we have a command that converts these to numbers, and % then \cs{ifcase} can be used. There is a third part of the optional % argument usable only in \MP{}: a number indicating degrees of rotation. % % \DescribeMacro{\tlabeljustify} % The multi-part definition of \cs{tlabeljustify} is to guard % against confusing error messages if some part of this optional argument % is empty. The code assumes that if there are only 2, 1 or no parts, then % later parts should be left unchanged. The rotation part is empty by % default (rather than 0), because some commands will emit a warning if % a nonempty rotation exists without \opt{mlabels}. % % The result of \cs{tlabeljustify} is that \cs{tl@vpos} is set equal to % $-1$ if the first letter is (default) \texttt{B} (for Baseline), and % 0--2 if it is \texttt{b} (bottom), \texttt{c} (center) or \texttt{t} % (top). Similarly, \cs{tl@hpos} is set equal to $-1$ if the second % letter is (default) \texttt{l} (for left), and 0 or 1 if it is % \texttt{c} (center) or \texttt{r} (right). % % The rotation part is just saved in \cs{tlabel@rot}. This is now true % even without \opt{mplabels} in case it is turned on later. It is % ignored by \cs{tlabel} without \opt{mplabels}, but a warning is issued % here anyway. % \begin{macrocode} \newcount\tl@vpos \newcount\tl@hpos \tl@vpos=-1 \tl@hpos=-1 \newdef\tlabel@rot{}% % \newdef\tlabeljustify#1{% \mfp@ifempty{#1}{}{\mfp@justify#1\mfp@delim}}% \def\mfp@justify#1#2\mfp@delim{\mfp@local\mfp@vconv{#1}% \mfp@ifempty{#2}{}{\@mfp@justify#2\mfp@delim}}% \newdef\@mfp@justify#1#2\mfp@delim{% \mfp@local\mfp@hconv{#1}\mfp@local\edef\tlabel@rot{#2} \@ifmplabels{}% {\mfp@ifempty{#2}{}% {\Mfpic@warn{Rotation of labels is not supported without the mplabels\@msgbreak option. Rotation may be ignored\@online .}}}}% \newdef\mfp@vconv#1{% \if B#1\tl@vpos=-1 \else \if b#1\tl@vpos= 0 \else \if c#1\tl@vpos= 1 \else \if t#1\tl@vpos= 2 \else \tl@vpos=-1 \mfp@justifyerror \fi\fi\fi\fi}% \newdef\mfp@hconv#1{% \if l#1\tl@hpos=-1 \else \if c#1\tl@hpos= 0 \else \if r#1\tl@hpos= 1 \else \tl@hpos=-1 \mfp@justifyerror \fi\fi\fi}% \newdef\mfp@justifyerror{% \mfp@errmsg{Invalid justification parameter for text label.}% {The optional argument for a text label must be^^J% one of B, b, c or t^^J followed by l or r or c,^^J% followed by an angle (optionally).}}% % \end{macrocode} % % \DescribeMacro{\tlpathjustify} % This acts just like \cs{tlabeljustify} from the user's point of view. % Since it is only for users, and not used internally, it merely defines % three macros that \cs{@@@tlpath} passes on to \cs{tlabeljustify} when no % justification parameter is present. % \begin{macrocode} \newdef\tlpathjustify#1{% \mfp@ifempty{#1}{}{\tlp@justify#1\mfp@delim}}% \newdef\tlp@justify#1#2\mfp@delim{\mfp@def\tlpath@v{#1}% \mfp@ifempty{#2}{}{\tlp@@justify#2\mfp@delim}}% \newdef\tlp@@justify#1#2\mfp@delim{% \mfp@def\tlpath@h{#1}\mfp@def\tlpath@r{#2}}% \tlpathjustify{cc}% % \end{macrocode} % % \DescribeMacro{\tlabelsep} % \DescribeMacro{\tlabeloffset} % \cs{tlabelsep} takes an absolute length as its argument and sets % parameters that determine by how much a label is separated from the % point it is placed at. This is in case something is drawn at that point, % such as a dot or a hash mark on an axis. % % \cs{tlabeloffset}, on the other hand, takes a pair of dimensions, % representing offsets. This is mainly so that, if labels seem to be off, % they can all be shifted with one command. % % Both these values are written to the \MF{} file for the sake of the % commands that draw rectangles or ovals around labels. % \begin{macrocode} \newdef\tlabelsep#1{\mfp@local\tlabel@sep=#1\relax \setmfnumeric{label_sep}{\the\tlabel@sep}}% \newdef\tlabeloffset#1#2{% \mfp@local\tlabel@hadj=#1\relax \mfp@local\tlabel@vadj=#2\relax \setmfvariable{pair}{label_adjust}% {(\the\tlabel@hadj,\the\tlabel@vadj)}}% % \end{macrocode} % % \DescribeMacro{\everytlabel} % Every line of a multiline label is written inside a group, so % adjustments to baselineskip and other things are difficult or impossible. % Therefore, \cs{everytlabel} is provided to define tokens to be inserted % before the label code, outside these groups. It is not itself a token % variable, so that that it can write the tokens to the \MP{} file once, % instead of at every label. % \begin{macrocode} \newdef\everytlabel{\afterassignment\@everytlabel \mfp@local\every@tlabel}% \newdef\@everytlabel{% \mfp@ifmpost {\@ifmfpfileisopen {\mfcmd{verbatimtex\@nl \def\noexpand\everylabel{\the\every@tlabel} etex}}% {}}% {}}% % \end{macrocode} % % % \section{Other settings}\label{othersettings} % % \DescribeMacro{\headshape} % This sets the arrowhead shape. The parameters are: the ratio of width % to length, the tension (see \file{grafbase.dtx}) and a boolean % (\gbc{true} or \gbc{false}) to say whether the the head is filled, or % only the barbs are drawn. (In retrospect, it would have been more % consistent with other commands to have one \TeX{} parameter with commas % separating the components.) % \begin{macrocode} \newdef\headshape#1#2#3{\mfcmd{\@nl headshape (#1, #2, #3)}}% % \end{macrocode} % % \DescribeMacro{\mfpdefinecolor} % \prog{Mfpic} supports color under \MP{} by writing all color % definitions to the output \file{.mp} file. In order to support a % \LaTeX-like color syntax, all the color models allowed by the color % package correspond to a \grafbase{} function that returns a \MP{} % color value. For example, \gbc{cmyk(.3,.3,0,.7)} returns \gbc{(0,0,.3)}, % a very dark blue. This can be set by % \cs{mfpdefinecolor}\marg{vdblue}\marg{cmyk}\marg{.3,.3,0,.7}. % % \DescribeMacro{\fillcolor} % \DescribeMacro{\drawcolor} % \DescribeMacro{\headcolor} % \DescribeMacro{\hatchcolor} % \DescribeMacro{\pointcolor} % \DescribeMacro{\tlabelcolor} % \DescribeMacro{\backgroundcolor} % To support the syntax % \cs{fillcolor}\oarg{\meta{model}}\marg{\meta{parameters}}, we just % call \cs{@mfpcolor} with the \grafbase{} color variable name % \gbc{fillcolor}. % \begin{macrocode} \newdef\mfpdefinecolor#1#2#3{\setmfcolor{#1}{#2(#3)}}% \newdef\fillcolor{\@mfpcolor{fillcolor}}% \newdef\drawcolor{\@mfpcolor{drawcolor}}% \newdef\headcolor{\@mfpcolor{headcolor}}% \newdef\hatchcolor{\@mfpcolor{hatchcolor}}% \newdef\pointcolor{\@mfpcolor{pointcolor}}% \newdef\tlabelcolor{\@mfpcolor{tlabelcolor}}% \newdef\backgroundcolor{\@mfpcolor{background}}% \newdef\@mfpcolor#1{% \mfp@ifnextchar[{\mfp@color{#1}}{\setmfcolor{#1}}}% \newdef\mfp@color#1[#2]#3{\setmfcolor{#1}{#2(#3)}}% % \end{macrocode} % % When \cs{plotdata} is used to draw several graphs from one file, each % sequence of non-blank lines corresponds to a different curve with a % different style of rendering. The user has the option to cycle through % different dashing patterns, different colors, or different symbols. % % Internally, \cs{plotdata} issues the command \cs{mfp@setstyle} (which % can be defined to be any rendering macro), followed by a path defining % command such as \cs{curve} or \cs{polyline}, followed by a command % that reads the data and writes it in a suitable format. The following % commands essentially allow the user to select the rendering macro. % They start by resetting \cs{mfp@linetype}, the count register that keeps % track of how many curves have been drawn, then they define % \cs{mfp@setstyle}. % % \DescribeMacro{\dashedlines} % \cs{dashedlines} uses the rendering prefix \cs{gendashed} with 6 % different dashing patterns \gbc{dashtype0} through \gbc{dashtype5}. % These are actually selected in \MF{} through the command % \gbc{getdashpat}. This takes care of cycling back to % \gbc{dashtype0} when the number of available dash patterns is exceeded. % Dashed lines is the default. % \begin{macrocode} \newdef\dashedlines{\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\gendashed{getdashpat\number\mfp@linetype}}}% \dashedlines % \end{macrocode} % % \DescribeMacro{\coloredlines} % This uses \cs{draw} with an optional color parameter set % to \gbc{colortype0} through (by default) \gbc{colortype 7}. These are % color variables defined by \grafbase{}. It also issues a warning if % \MF{} is being used. As with \cs{dashedlines}, a \MP{} command % \gbc{getcolor} selects these colors. % \begin{macrocode} \newdef\coloredlines{% \mfp@ifmpost {\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\draw [getcolor\number\mfp@linetype]}}% {\Mfpic@warn{You can't use \string\coloredlines\space in Metafont.\@msgbreak Using \dashedlines instead}% \dashedlines}}% % \end{macrocode} % % \DescribeMacro{\pointedlines} % This makes a sort of dotted line, except the dots are actually different % symbols. It uses the rendering macro \cs{plot} with a parameter cycling % through 9 different symbols. % \begin{macrocode} \newdef\pointedlines{\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\plot{getsymbol\number\mfp@linetype}}}% % \end{macrocode} % % \DescribeMacro{\datapointsonly} % \cs{datapointsonly} uses symbols like \cs{pointedlines}, but places % them only at the data points from the file. It uses the rendering macro % \cs{plotnodes} with a parameter cycling through the same 9 symbols. % \begin{macrocode} \newdef\datapointsonly{\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\relax \plotnodes{getsymbol \number\mfp@linetype}}}% % \end{macrocode} % % \DescribeMacro{\reconfigureplot} % This command allows the user to set the dashes, colors and symbols used % by the \cs{plotdata} command. The first argument is the plotting method % to be changed (\texttt{dashes}, \texttt{colors}, or \texttt{symbols}) % and the second argument is a comma separated list of appropriate type % variables for \cs{plotdata} to cycle through. For example, % \cs{reconfigureplot}\marg{dashes} takes a list of dashing patterns % (previously defined by the \cs{dashpattern} command) separated by % commas. It writes a command instructing \MF{} to redefine the arrays % \mfc{dashtype0}, \mfc{dashtype1}, etc., used with \cs{gendashed} when % \cs{dashedlines} is in effect. The number of patterns is counted by \MF, % which also handles the mod-ing operation now. % % \cs{reconfigureplot}\marg{colors} takes a list of colors (expressions or % color names previously defined) separated by commas. It redefines % \gbc{colortype0}, etc., used with \cs{plotdata} when \cs{coloredlines} % is in effect. % % \cs{reconfigureplot}\marg{symbols} takes a list of symbols (\MF{} path % expressions, one of the symbols available to \cs{plotsymbol}, or path % names defined by \cs{store}) separated by commas. It redefines % \gbc{pointtype0}, etc., used by \cs{plotdata} when \cs{pointedlines} or % \cs{datapointsonly} is in effect. % % \DescribeMacro{\defaultplot} % This restores \mfpic's predefined defaults for dash patterns, colors and % symbols in \cs{plotdata}. The one argument is one of the words % \texttt{dashes}, \texttt{colors}, or \texttt{symbols}, indicating which % plotting method is to be restored. % \begin{macrocode} \newdef\reconfigureplot#1{\mfsrc{setdata#1}\mfp@writedata}% \newdef\defaultplot#1{\mfcmd{default#1}}% % \end{macrocode} % % \DescribeMacro{\mfplinetype} % \DescribeMacro{\mfplinestyle} % The user-level commands \cs{mfplinetype} and \cs{mfplinestyle} allow the % user to set the starting value of \cs{mfp@linetype}. The default is to % start at $0$. The names ``linestyle'' and ``linetype'' come from % an analogous system of changing rendering in \prog{gnuplot}. % \begin{macrocode} \newdef\mfplinetype#1{\mfp@local\mfp@linetype=#1}% \newlet\mfplinestyle\mfplinetype \mfplinetype{0}% % \end{macrocode} % % \prog{Mfpic} has 6 possible axes, the x- and y-axes pass through the % origin, $(0,0)$, the four border axes are at the edges of the graph % space, possibly offset from it by some amount. These four commands hold % the amount of that offset in graph units, the default being 0. % \begin{macrocode} \newdef\mfp@lshift{0}% \newdef\mfp@bshift{0}% \newdef\mfp@rshift{0}% \newdef\mfp@tshift{0}% % \end{macrocode} % % \DescribeMacro{\axismargin} % \DescribeMacro{\setaxismargins} % \DescribeMacro{\setallaxismargins} % These are the user-level command for setting the above offsets. The % first argument to \cs{axismargin} is one of the letters l, b, r, or t to % select the axis and the second is the offset in graph units. A positive % offset represents an inward shift, which is why we call them % \emph{margins}. The arguments of \cs{setaxismargins} are four offsets % for the axes (in the above order, which is anticlockwise, starting % with the left). \cs{setallaxismargins} takes one offset and applies it % to all axes. % % The values are passed on to \MF{} in the variables \gbc{laxis}, % \gbc{baxis}, \gbc{raxis}, and \gbc{taxis}. They are also needed by the % \cs{axislabels} command so they are saved in macros. % \begin{macrocode} \newdef\axismargin#1#2{\setmfnumeric{#1axis}{#2}% \mfp@local\@namedef{mfp@#1shift}{#2}}% \newdef\setaxismargins#1#2#3#4{\axismargin l{#1}\axismargin b{#2}% \axismargin r{#3}\axismargin t{#4}}% \newdef\setallaxismargins#1{\setaxismargins{#1}{#1}{#1}{#1}}% % \end{macrocode} % % The following converts axis letters to a numeric, making conditionals for % axes simpler to code (\cs{ifcase} versus the six nested \cs{if}\,s we % see here.) Plus we get to define the error message only once. The % first argument is the letter and the second argument is the calling % command (for the error message). % \begin{macrocode} \newcount\mfp@axisnum \def\get@axisnum#1#2{% \if x#1\relax \mfp@axisnum0 \else\if y#1\relax \mfp@axisnum1 \else\if l#1\relax \mfp@axisnum2 \else\if b#1\relax \mfp@axisnum3 \else\if r#1\relax \mfp@axisnum4 \else\if t#1\relax \mfp@axisnum5 \else \mfp@errmsg {Invalid axis letter "#1".}% {The command #2 requires an axis to be designated by one of^^J% the following letters: x, y, l, b, r, or t. If you proceed, ^^J% x will be assumed.}% \fi\fi\fi\fi\fi\fi}% % \end{macrocode} % % \DescribeMacro{\setaxismarks} % \DescribeMacro{\setxmarks} % \DescribeMacro{\setymarks} % \DescribeMacro{\setbordermarks} % \DescribeMacro{\setallbordermarks} % The tick marks (or hash marks) on the axes can be in three possible % positions: centered on the axes, all on one side, or all on the other % side. The default for the x- and y-axes is centered, for the border axes % it is inside. For changing this we provide the \cs{setaxismarks} command, % whose first argument is the axis letter, and whose second argument is % one of the words \texttt{inside}, \texttt{outside}, \texttt{centered}, % \texttt{ontop}, \texttt{onbottom}, \texttt{onleft}, or \texttt{onright}. % \begin{macrocode} \newdef\setaxismarks#1#2{\setmfnumeric{#1tick}{#2}}% \newdef\setxmarks#1{\setaxismarks x{#1}}% \newdef\setymarks#1{\setaxismarks y{#1}}% \newdef\setbordermarks#1#2#3#4{\setaxismarks l{#1}\setaxismarks b{#2}% \setaxismarks r{#3}\setaxismarks t{#4}}% \newdef\setallbordermarks#1{\setbordermarks{#1}{#1}{#1}{#1}}% % \end{macrocode} % % \DescribeMacro{\smoothdata} % \DescribeMacro{\unsmoothdata} % The \cs{datafile} and \cs{plotdata} commands originally just created % polygonal paths, but users requested the ability to draw smooth ones. % Originally only the commands below (\cs{smoothdata} and % \cs{unsmoothdata}) were written to do this. Later, these file % manipulation commands were given optional arguments to achieve the same % effect, so now the commands below just set the defaults for the optional % parameter, storing them in the macros \cs{mfp@smoothness} and % \cs{mfp@tension}. The latter can be used to adjust the tension of the % \MF{} path if smoothness is `s'. Default tension is now empty rather % than 1 so we can implement a scheme to change the actual default used. % \begin{macrocode} \newdef\smoothdata{\null@opt\@smoothdata}% \newdef\@smoothdata[#1]{\mfp@def\mfp@smoothness{s}% \mfp@def\mfp@tension{#1}}% \newdef\unsmoothdata{\mfp@def\mfp@smoothness{p}% \mfp@def\mfp@tension{}}% \unsmoothdata% default % \end{macrocode} % % \DescribeMacro{\using} % \DescribeMacro{\usingpairdefault} % \DescribeMacro{\usingnumericdefault} % These commands control how we interpret data in a file. % The command \cs{using} is named after a keyword in \prog{gnuplot}. It % controls which datum is plotted against which by \cs{plotdata} and % \cs{datafile}. The default is to read the first two space separated % words on a line as the x- and y-coordinate of a point. To allow that % there might be more data on a line, it is also assumed that the second % word is followed by a space and the rest of the line is read as a third % parameter that is not used. In case there are only two words, % \mfpic{} will always add a space on the end and then the third % parameter will be empty. % % The \cs{parse@data} command reads its argument as delimited % parameters, and the \cs{using} command tells what those delimiters are. % For example, in the first part of % \cs{using}\marg{\#1 \#2 \#3}\marg{(\#1,\#2)}, we are telling % \cs{parse@data} that everything on a line up to the first space is the % first parameter, and everything up to the second space is the second % parameter and the rest of the line is the third parameter. In the second % part we are telling it that what we write to the output is a pair in % parentheses with the first two parameters separated by a comma. This % example is the default as we see here in \cs{usingpairdefault}. This % command can be issued by a user to return to that default. The user can % also issue \cs{usingnumericdefault} to write the first space separated % word as a single numeric. This is for commands like \cs{piechart}. % % \DescribeMacro{\mfpdataperline} % \cs{mfpdataperline} is a user level macro that controls the maximum % number of points that will be written to a single line in the output. % \begin{macrocode} \newdef\using#1#2{\mfp@def\parse@data#1\mfp@delim{#2}}% \newdef\usingpairdefault{\using{##1 ##2 ##3}{(##1,##2)}}% \newdef\usingnumericdefault{\using{##1 ##2}{##1}}% \usingpairdefault \newdef\mfpdataperline{5}% % \end{macrocode} % % The following macros are used internally by \cs{datafile} and \cs{plotdata}. % A comment line is read by \TeX{} as empty so we need an empty macro to % test against, and a blank line is read as \cs{par} (not the primitive % \cs{par}, but the literal token \cs{par}, so it tests as equal to % \cs{mfp@par}. Early versions of \cs{plotdata} wrote a literal \MF{} path % expression to the output file and \cs{mfp@join} created the \mfc{--} % between points. Now we write one of the \grafbase{} list-to-path % commands followed by a comma separated list of points, so \cs{mfp@join} % has morphed into a comma. % \begin{macrocode} \newdef\mfp@par{\par}% \newdef\mfp@join{,}% % \end{macrocode} % % \DescribeMacro{\makepercentother} % \DescribeMacro{\makepercentcomment} % \DescribeMacro{\mfpdatacomment} % The user can change the comment character for data files with % something like \cs{mfpdatacomment}\marg{\cs{\#}}. This also changes the % percent character to category `other'. We can also use the percent sign % as part of the numeric data by sandwiching the \cs{using} command % between \cs{makepercentother} and \cs{makepercentcomment}. Every file % reading command issues \cs{mfp@setcomment} before reading. The count % register \cs{@datacomment} hold the ASCII code of the current comment % character, the default being the percent sign. % \begin{macrocode} \newcount\@datacommentchar \@datacommentchar`\% \newdef\makepercentother{\@makeother\%}% \newdef\makepercentcomment{\catcode`\%=14 }% \newdef\mfpdatacomment#1{\mfp@local\@datacommentchar`#1}% \newdef\mfp@setcomment{\makepercentother\catcode\@datacommentchar14 }% % \end{macrocode} % % \DescribeMacro{\fdef} % The following is for defining functions to be used in \cs{function} % through \cs{plrregion}. The first argument is the name of the function, % the second is its variable, the last is the \MF{} code. Obviously its % use requires a knowledge of the \MF{} language. The function produced is % a \mfc{vardef}, and can contain almost arbitrary \MF{} code, but must % end with an expression. Normally it must be a numerical expression, to % be use in \cs{function}, or a pair expression so it can be used alone in % the last argument of \cs{parafcn}. % % We apply \cs{@makeother} to \texttt{\#} so it doesn't get doubled. The % \texttt{\#} is frequent in vardefs among the \MF{} gurus. % \begin{macrocode} \newdef\fdef{\begingroup\@makeother\#\preservelines\@fdef}% \newdef\@fdef#1#2#3{\mfcmd{\@nl save #1;\@nl vardef #1 (expr #2) = \@nl #3\@nl enddef}\endgroup}% % \end{macrocode} % % The following is executed last inside \cs{@mfpic@graf@macs}. It is a % hook for adding new definitions. It is initialized to empty, and add-on % packages can add to it. % \begin{macrocode} \newdef\mfp@additions{}% % \end{macrocode} % % % \section{The main graphics macros}\label{main} % % In order to avoid redefining commands of other packages and in order % to avoid having other packages redefine \mfpic{} commands, all mfpic % commands that cannot be used outside the \env{mfpic} environment are % defined anew with every such environment. This is accomplished by having % the \cs{mfpic} command execute \cs{@mfpic@graf@macs}, which expands to % all those definitions. Grouping localizes the definitions, so outside % \env{mfpic} environments, these commands revert to being undefined, or % to there original definitions if they had any. As might be expected it % is quite long, over 300 lines of code at last count. % \begin{macrocode} \newdef\@mfpic@graf@macs{% % \end{macrocode} % % \subsection{Plotting data from files}\label{datafiles} % % \DescribeMacro{\plotdata} % Most of the \mfpic{} graphic commands take optional arguments. Most of % them follow the scheme below: \cs{@plotdata} takes a mandatory argument % enclosed in brackets, and does the work. \cs{plotdata} is simply defined % to test for an optional argument and pass it or a default to % \cs{@plotdata}. In this case, the default option is signaled by % passing empty brackets via \cs{null@opt}. % % \cs{@plotdata} follows the scheme of most of the data file processing % commands: it calls \cs{@processdatafile} with the name of the file (the % second parameter of \cs{@plotdata}) and another command, \cs{mfp@doplots}, % which really does the work. The argument of \cs{mfp@doplots} is the % original optional parameter of \cs{plotdata}. This optional parameter is % the smoothness, which may be \oarg{s\meta{tension}} for a smooth path % or \oarg{p} for a polygonal path, or empty to select whatever default % was created by \cs{smoothdata}. % \begin{macrocode} \newdef\plotdata{\null@opt\@plotdata}% \newdef\@plotdata[##1]##2{\@processdatafile{##2}{\mfp@doplots{##1}}}% % \end{macrocode} % % \cs{mfp@doplots} is a self-looping macro. It issues the rendering % prefix (in \cs{mfp@setstyle}), increments the linetype, and writes the % path expression defined by the first set of data in the file (via % \cs{do@datafile}, which \emph{really} does the work and which stops at a % blank line). That part, when prefixed by \cs{@figmacstart}, functions % as a \cs{@figmac}. When finished with one figure, \cs{@if@enddata} % checks if there is another set of data in the file. If so, % \cs{mfp@doplots} calls itself again. % % The argument is the smoothness parameter(s), which it merely passes on. % There is no filename argument: since \cs{@processdatafile} has already % opened the input stream \cs{mfp@data} and subsequent macros will read % from it. % \begin{macrocode} \def\mfp@doplots##1{\mfp@setstyle \advance\mfp@linetype1 \@figmacstart \do@datafile{##1}% \@if@enddata{}{\mfp@doplots{##1}}}% % \end{macrocode} % % When two blank lines occur in succession, \cs{plotdata} is suppose to % stop. \cs{@ifenddata} is called when \cs{do@datafile} ends (one blank % line was found), it checks for another blank line (or end-of-file) % and, if it finds one, selects the first of the two alternatives that % follow. % \begin{macrocode} \newdef\@if@enddata{% check for another blank line \ifeof\mfp@data \@xp\@firstoftwo \else \skipcomments \ifx\mfp@temp\mfp@par \@XP\@firstoftwo \else \@XP\@secondoftwo \fi \fi}% % \end{macrocode} % % \DescribeMacro{\datafile} % \cs{datafile} defines a path connecting the points in a datafile. The % optional parameter is the smoothness, as in \cs{plotdata}. The other % parameter is the filename. \cs{@datafile} does the figure macro stuff, % opens the data file, and calls \cs{do@datafile} which does all the work. % \begin{macrocode} \newdef\datafile{\null@opt\@datafile}% \newdef\@datafile[##1]##2{\@figmacstart \@processdatafile{##2}{\do@datafile{##1}}}% % \end{macrocode} % % I lied. Actually all \cs{do@datafile} does is handle any empty % optional parameter and call \cs{@do@datafile} to do the work. % \begin{macrocode} \newdef\do@datafile##1{% \do@mtparam{##1}{\mfp@smoothness\mfp@tension}\@do@datafile}% % \end{macrocode} % % And \cs{@do@datafile} is mainly just a wrapper, processing the optional % parameter (passed by either \cs{plotdata} or \cs{datafile}) which % selects what figure making code should be written. For % \oarg{s\meta{tension}} a \gbc{curve} command is used. For \oarg{p}, a % \gbc{polyline}. (The `\cs{mf@F}' means the curve is not closed). % % After that, \cs{mfp@rwdata} is called, which reads and writes the % data. % \begin{macrocode} \newdef\@do@datafile[##1##2]{% \mfsrc{% \if s##1 \mfp@ifempty{##2}{curve }{tcurve (##2) }% \else polyline \fi (\mf@F)}\mfp@rwdata}% % \end{macrocode} % % \subsection{The prefix commands}\label{prefixcommands} % % \subsubsection{Storing and reusing a figure}\label{storing} % % \DescribeMacro{\store} % This stores an \mfpic{} path in a \MF{} path variable. The argument is % the variable name. It should be followed by an \mfpic{} figure macro % (such as \cs{rect}\marg{...}). The stored path can be reused via the % \cs{mfobj} command. This command is written as a \cs{@rendmac} even % though it does no rendering. This is so (1)~it will turn off implicit % rendering (any rendering must be explicitly written) and (2) it can be % placed anywhere within the prefix area. This is new behavior with % version 0.7. Prior to this it was required to place the path to be % stored as a second argument. Though that argument could contain other % prefixes in addition to the path, it was required that no other prefixes % precede \cs{store}. Note that \cs{store} takes a second argument but % it merely puts it back. This is so that the old syntax (with the figure % macro in braces) will continue to work. % \begin{macrocode} \newdef\store##1##2{\@rendmac{stored (##1)}##2}% % \end{macrocode} % % \DescribeMacro{\mfobj} % \DescribeMacro{\mpobj} % This is the interface to use a \cs{store}-d object. % \cs{mfobj}\marg{\meta{name}} is a figure macro, and should act pretty % much exactly the same as if the figure macro that had been stored in the % variable were typed in its place. Its one argument, the variable name, % is read by \cs{@figmac}, which operates as described previously, either % implicitly rendering the path, or allowing it to be picked up by % preceding prefix macros. % \begin{macrocode} \newlet\mfobj\@figmac \newlet\mpobj\@figmac % \end{macrocode} % % \subsubsection{Subpaths} % % \DescribeMacro{\cutoffbefore} % This macro take one mandatory argument which is an object stored with % \cs{store}. It modifies the path it is prefixed to so that it starts % at its first point of intersection with the object, cutting off any % earlier part of the path. % % \DescribeMacro{\cutoffafter} % This is similar, except the modified path ends at the last point of % intersection between the following path and the object, cutting off % any later part of the path. It is internally the same as applying % \cs{cutoffbefore} to the reversed path and reversing the result. % % \DescribeMacro{\trimpath} % This trims off the specified amounts from the start and end of the % path. The amounts are two absolute dimensions, separated by commas. % They may be \TeX{} dimensions. If the first dimension is absent, it is % set to \texttt{0pt}, if the second is absent, it is set equal to the % first. (So if both are absent, nothing is trimmed.) % \begin{macrocode} \newdef\cutoffafter##1{\@closmac{cutoffafter (##1)}}% \newdef\cutoffbefore##1{\@closmac{cutoffbefore (##1)}}% \newdef\trimpath##1{\@getdimens##1,,\mfp@delim \@closmac{trimmedpath (\the\mfp@scratch, \the\mfp@scratchB)}}% \newdef\@getdimens##1,##2,##3\mfp@delim{% \mfp@scratch \@ifmtsub{##1}{\z@}\relax \mfp@scratchB\@ifmtsub{##2}{\mfp@scratch}\relax}% % \end{macrocode} % % \DescribeMacro{\partpath} % \DescribeMacro{\subpath} % These produce a subpath of the following path. Each takes a mandatory % parameter containing two numbers separated by a comma. In % \cs{partpath}, these should be between 0 and 1 and produce a fraction % of the following path. In \cs{subpath}, these are absolute numbers between % 0 and the number of segments in the path, and it produces the equivalent of % \MF's \mfc{subpath} primitive. % \begin{macrocode} \newdef\partpath##1{\@closmac{partialpath (##1)}}% \newdef\subpath##1{\@closmac{gsubpath (##1)}}% % \end{macrocode} % % \subsubsection{Drawing a curve}\label{drawing} % % These are rendering macros that draw the curve in some fashion: solid, % dashed, colored, etc. % % \DescribeMacro{\draw} % \cs{draw} is the initial definition of \cs{@render}. It takes one % optional argument, a color. In \MF{}, where color are just numerics, if % it is ${}\ge 1$ (representing white) the path is subtracted from the % picture, otherwise it is drawn in black. % % \begin{macrocode} \newdef\draw{\null@opt\@draw}% \newdef\@draw[##1]{% \@rendmac{\mfp@ifempty{##1}{drawn}{colordrawn (##1)}}}% % \end{macrocode} % % \DescribeMacro{\dashed} % \cs{dashed} (as well as \cs{dotted}) takes one optional argument, % which should contain the length of the dashes (diameter of dots) and % the length of the spaces between, separated by a comma. The defaults % can be seen in the code below. % \begin{macrocode} \newdef\dashed{\simple@opt\@dashed{\the\dashlen,\the\dashspace}}% \newdef\@dashed##1{\@rendmac{DASHED (##1)}}% \newdef\dotted{\simple@opt\@dotted{\the\dotsize,\the\dotspace}}% \newdef\@dotted##1{\@rendmac{dotted (##1)}}% % \end{macrocode} % % \cs{gendashed} takes one mandatory argument, the name of a dash pattern % previously defined by \cs{dashpattern} % \begin{macrocode} \newdef\gendashed##1{\@rendmac{gendashed (##1)}}% % \end{macrocode} % % \cs{plot} is like \cs{dotted}, except the dots are variously shaped % symbols. It takes one optional argument containing the size of the % symbol and the spacing, separated by a comma, and one mandatory % argument, the name of the symbol. This can in principal be any % expression of type \mfc{picture} or \mfc{path}. (In \MP, type % \mfc{string} is also permitted). For the size parameter to work % correctly, the symbol should be a path, and it should have 1 as it's % natural size. \Mfpic{} provides the predefined paths % \texttt{Triangle}, \texttt{Square}, \texttt{Circle}, \texttt{Star}, % \texttt{Diamond}, \texttt{Plus}, \texttt{Cross} and \texttt{Asterisk}. % The first 5 have filled-in versions: \texttt{SolidTriangle}, etc. % \begin{macrocode} \newdef\plot{\simple@opt\@plot{\the\pointsize, \the\symbolspace}}% \newdef\@plot##1##2{\@rendmac{doplot (##2, ##1)}}% % \end{macrocode} % % Sometimes, rather than equally spaced dots or symbols, we would rather % have a symbol at each `node' of the following path. If the path is % created by a list macro, then usually each point in the list is a node % (but the spline paths are exceptions). For other figures, the nodes % can seem pretty random. For example, a \cs{circle} command without optional % argument produces a curve with 8 equally spaced nodes, but with optional % argument the nodes depend on how it is drawn and the size of any angle % parameter. % % \cs{plotnodes} has almost the same syntax as \cs{plot}, but since it % places the symbols only at the nodes of the path, there is no spacing % parameter in the optional argument. % \begin{macrocode} \newdef\plotnodes{\simple@opt\@plotnodes{\the\pointsize}}% \newdef\@plotnodes##1##2{\@rendmac{plotnodes (##2, ##1)}}% % \end{macrocode} % % \subsubsection{Closing a curve}\label{closing} % % \DescribeMacro{\sclosed} % \DescribeMacro{\bclosed} % \DescribeMacro{\lclosed} % \DescribeMacro{\cbclosed} % \DescribeMacro{\qbclosed} % \DescribeMacro{\uclosed} % These close a path defined by whatever figure macro follows it. The % first closes smoothly in the same manner that \cs{curve} creates a % smooth path, the second uses an ordinary \MF{} B\'ezier. These two have % an optional argument: the amount of tension to put in the connecting % link. Higher tension produces a linking segment with sharper turns near % the endpoints and a flatter path in between. This makes no sense with % \cs{lclosed}, \cs{qbclosed} or \cs{cbclosed}. The first always draws a % straight line and the other two requires a link explicitly determined by % the beginning and ending segments of the path: a cubic B-spline for % \cs{cbclosed} and a quadratic B-spline for \cs{qbclosed}. See % \cs{closedcspline} and \cs{closedqspline} described later. % % Due to a misunderstanding on my part, \cs{uclosed} was defined in a more % complicated manner than necessary, and actually produced exactly the % same path as \cs{bclosed}. So now they are just made to be equal. % \begin{macrocode} \newdef\@closed##1##2{% \@closmac{##1closed\mfp@ifempty{##2}{}{t (##2)}}}% \newdef\bclosed{\null@opt\@bclosed}% \newdef\@bclosed[##1]{\@closed b{##1}}% \newdef\sclosed{\null@opt\@sclosed}% \newdef\@sclosed[##1]{\@closed s{##1}}% \newdef\lclosed{\@closed l{}}% \newdef\cbclosed{\@closed{cb}{}}% \newdef\qbclosed{\@closed{qb}{}}% \newlet\uclosed\bclosed % \end{macrocode} % % \subsubsection{Filling a closed curve}\label{filling} % % The next few prefix macros fill the interior of the closed path that % follows with some sort of pattern. The path must be either already % closed (like that produced by \cs{rect} or \cs{circle}) or explicitly % closed with a closing prefix. A non-closed path will simply be drawn % with a solid line. % % \DescribeMacro{\tess} % \cs{tess} takes one mandatory argument, the name of a previously defined % tile, and fills with shifted copies of the tile. % \begin{macrocode} \newdef\tess##1{\@rendmac{tess (##1)}}% % \end{macrocode} % % \DescribeMacro{\shade} % \DescribeMacro{\polkadot} % \cs{shade} and \cs{polkadot} take one optional parameter, the separation % between dots, defaulting to \cs{shadespace} (resp., \cs{polkadotspace}). % The size of the dots is set by issuing the command \cs{shadewd} (resp., % \cs{polkadotwd}). % \begin{macrocode} \newdef\shade{\simple@opt\@shade{\the\shadespace}}% \newdef\@shade##1{\@rendmac{shade (##1)}}% \newdef\polkadot{\simple@opt\@polkadot{\the\polkadotspace}}% \newdef\@polkadot##1{\@rendmac{polkadot (##1)}}% % \end{macrocode} % % \DescribeMacro{\thatch} % \DescribeMacro{\lhatch} % \DescribeMacro{\rhatch} % \DescribeMacro{\xhatch} % The hatching macros mostly take two optional parameters, the % separation of the hatching lines (default \cs{hatchspace}) and their % color. One slight exception is \cs{thatch}, which is called by all the % others. Its first optional argument is the separation \emph{and} the % angle (default $0$) of the lines, separated by a comma. The other % hatching macros have a fixed angle. \cs{lhatch} has lines at a $-45$ % degree angle (upper left to lower right), \cs{rhatch} produces the opposite % diagonal, and \cs{xhatch} does both sets of lines (cross hatching). % \begin{macrocode} \newdef\thatch{\simple@opt\@thatch{\the\hatchspace,0}}% \newdef\@thatch##1{\null@opt{\@@thatch{##1}}}% \newdef\@@thatch##1[##2]{\@rendmac{% \mfp@ifempty{##2}{thatch}{colorthatch (##2)} (##1)}}% \newdef\lhatch{\simple@opt\@lhatch{\the\hatchspace}}% \newdef\@lhatch##1{\@thatch{##1,-45}}% \newdef\rhatch{\simple@opt\@rhatch{\the\hatchspace}}% \newdef\@rhatch##1{\@thatch{##1,45}}% \newdef\xhatch{\simple@opt\@xhatch{\the\hatchspace}}% \newdef\@xhatch##1{\null@opt{\@@xhatch{##1}}}% \newdef\@@xhatch##1[##2]{\@rendmac{% \mfp@ifempty{##2}{xhatch}{colorxhatch (##2)} (##1)}}% \newlet\hatch=\xhatch % \end{macrocode} % % Commands that might conceivably interfere with small bits of \TeX{} % code in labels have been renamed. Thus, instead of \cs{fill}, which is a % \LaTeX{} text mode command, we have \cs{gfill}. We also have \cs{gclear} % and \cs{gclip}. The `g' is for `graphic'. Later, commands that deal % with text (labels and captions), have `t' prepended to their more % natural name, thus \cs{tlabel} and \cs{tcaption}. % % \DescribeMacro{\gfill} % \DescribeMacro{\gclear} % \DescribeMacro{\gclip} % \cs{gfill} take one optional argument, the color with which to fill. % Under \MF{} the color must be a numeric (representing a level of gray) % or one of the color functions, which are defined in \file{grafbase.mf} % to return numeric values. % % \cs{gclear} will actually fill with the color \texttt{background} in \MP. % \cs{gclip} might seem to be the inverse of \cs{gclear} (clearing the % outside of a region), but in \MP{} the mechanism is completely % different. One wishes \MP{} had an `inverse clip' command to use % instead of filling with \gbc{background}. The figure macro following % these commands must be a closed path. % \begin{macrocode} \newdef\gfill{\null@opt\@gfill}% \newdef\@gfill[##1]{% \@rendmac{\mfp@ifempty{##1}{filled}{colorfilled (##1)}}}% \newdef\gclear{\@rendmac{unfilled}}% \newdef\gclip{\@rendmac{Clip}}% % \end{macrocode} % % \subsubsection{Transforming a curve}\label{transforming} % % The following are transformation prefixes. They are all but one % implemented with \cs{@closmac} for reasons covered earlier. Most have a % mandatory argument, the parameters of the transformation. Because of the % implementation, one can insert rendering macros between a transformation % macro and the path being transformed, and they will apply to the % untransformed path. % % If the \env{mfpic} environment has different x and y scales, the % \cs{rotatepath} and \cs{reflectpath} compensates so that the result is % congruent to the original. The others do not because this is what users % seem to expect. % \begin{itemize} % \item \cs{reverse} and \cs{xyswappath} have no argument. % \item \cs{rotatepath} takes \marg{\meta{point},\meta{angle}}. % \item \cs{shiftpath} takes \marg{\meta{pair}}. % \item \cs{scalepath} takes \marg{\meta{center of scaling},\meta{factor}}. % \item \cs{xscalepath} takes \marg{\meta{x-center},\meta{factor}}. % \item \cs{yscalepath} takes \marg{\meta{y-center},\meta{factor}}. % \item \cs{slantpath} takes \marg{\meta{y-pivot},\meta{factor}}. % \item \cs{xslantpath} = \cs{slantpath}. % \item \cs{yslantpath} takes \marg{\meta{x-pivot},\meta{factor}}. % \item \cs{reflectpath} takes \marg{\meta{point1},\meta{point2}}, the % endpoints of a `mirror'. % \item \cs{transformpath} takes \marg{\meta{transformer}}, a \MF{} % `transformer' (see ``The \MF book'', page~212). % \end{itemize} % % All of them simply write the \grafbase{} command of nearly the same % name. % \begin{macrocode} \newdef\reverse{\@modmac{reverse}}% \newdef\xyswappath{\@closmac{xyswappedpath}}% \newdef\rotatepath##1{\@closmac{rotatedpath (##1)}}% \newdef\shiftpath##1{\@closmac{shiftedpath (##1)}}% \newdef\scalepath##1{\@closmac{scaledpath (##1)}}% \newdef\xscalepath##1{\@closmac{xscaledpath (##1)}}% \newdef\yscalepath##1{\@closmac{yscaledpath (##1)}}% \newdef\slantpath##1{\@closmac{xslantedpath (##1)}}% \newlet\xslantpath\slantpath \newdef\yslantpath##1{\@closmac{yslantedpath (##1)}}% \newdef\reflectpath##1{\@closmac{reflectedpath (##1)}}% \newdef\transformpath##1{\@closmac{transformedpath (##1)}}% % \end{macrocode} % % \subsubsection{Appending an arrowhead}\label{arrowhead} % % \DescribeMacro{\arrow} % The four macros beginning \cs{@h} are assigned default values at the % start and changed only if an option calls for it. % Each option starts with a letter (The initial letters of % `backset', `color', `length', or `rotate'), followed by a value % to assign to the corresponding variable (defaulting to \mfc{0pt}, % \meta{empty}, \cs{the}\cs{headlen} and \gbc{0 deg}). Then \cs{arrow} % finishes with the invokation of \cs{@arrow}. % \begin{macrocode} \def\arrow{\def\@hbackset{0}\def\@hcolour{}% \edef\@hlength{\the\headlen}\def\@hrotate{0}% \@arrow}% % \end{macrocode} % % \cs{@arrow} calls \cs{@arrowoption} if it finds an optional parameter. % After processing the parameter, \cs{@arrowoption} calls \cs{@arrow} % again. This loop will end when optional arguments run out. Then % \cs{@@arrow} finishes with the actual \MF{} code. % \begin{macrocode} \newdef\@arrow{\mfp@ifnextchar[{\@arrowoption}{\@@arrow}}% \newdef\@@arrow{% \@modmac{% \mfp@ifempty{\@hcolour}{headpath}{colorheadpath (\@hcolour)}% \space(\@hlength, \@hrotate, \@hbackset)}}% % \end{macrocode} % % Since the \cs{arrow} command takes up to 4 optional arguments in any % order, we have this utility \cs{@arrowoption} which examines an option's % contents and assigns a value to an appropriate macro. Since rather nasty % error messages will result if the contents are empty, we test for this % and do nothing when there is nothing to process. \cs{@@arrowoption} % makes the appropriated definitions, then \cs{@arrow} is iterated to % catch another optional parameter. % \begin{macrocode} \newdef\@arrowoption[##1]{% \mfp@ifempty{##1}{}{\@@arrowoption##1\mfp@delim}\@arrow}% \newdef\@@arrowoption##1##2\mfp@delim{% \if l##1\relax \mfp@ifempty{##2}{}{\def\@hlength{##2}}% \else\if r##1\relax \mfp@ifempty{##2}{}{\def\@hrotate{##2}}% \else\if b##1\relax \mfp@ifempty{##2}{}{\def\@hbackset{##2}}% \else\if c##1\relax \mfp@ifempty{##2}{}{\def\@hcolour{##2}}% \else \Mfpic@warn{Improper option to \string\arrow\@online .}% \fi\fi\fi\fi}% % \end{macrocode} % % This ends the prefix macros. % % \subsection{Transforming the coordinate system}\label{coordinate} % % \DescribeMacro{\coords} % \DescribeMacro{\endcoords} % The following apply transforms to the \MF{} coordinate system, and % these can be localized with \cs{coords} $\ldots$ \cs{endcoords}. The % transforms apply when the curve is \emph{rendered} and have no effect % on paths merely stored with \cs{store} and \cs{patharr}. Moreover, if a % path is created with \cs{connect}, it is transformed as a whole. % % \DescribeMacro{\applyT} % These are implemented by \cs{applyT} which takes as its argument a \MF{} % `transformer'. % % These commands (except \cs{turn}, kept for backward compatibility) have % at most one argument, the parameters of the transformation. \cs{rotate} % rotates around the origin, \cs{rotatearound} rotates around a given % point, \cs{turn} takes the point as an optional argument. % % Transformations are applied in reverse of the order they appear in the % file (i.e., the most recent first). % \begin{macrocode} \newdef\coords{\mfsrc{\@nl bcoords\@nl}}% \newdef\endcoords{\mfsrc{\@nl ecoords\@nl}}% \newdef\applyT##1{\mfsrc{\@nl hide(apply_t (##1))}}% \def\rotate##1{\applyT{rotated ##1}}% \newdef\rotatearound##1##2{% \applyT{rotatedaround (##1, ##2)}}% \newdef\turn{\simple@opt\@turn{(0,0)}}% \newdef\@turn##1##2{\rotatearound{##1}{##2}}% \newdef\reflectabout##1##2{% \applyT{reflectedabout (##1, ##2)}}% line ##1--##2. \let\mirror=\reflectabout \newdef\shift##1{\applyT{shifted ##1}}% pair. \def\scale##1{\applyT{scaled ##1}}% same scaling \newdef\xscale##1{\applyT{xscaled ##1}}% \newdef\yscale##1{\applyT{yscaled ##1}}% \newdef\zscale##1{\applyT{zscaled ##1}}% \newdef\xslant##1{\applyT{xslant ##1}}% \newdef\yslant##1{\applyT{yslant ##1}}% \newdef\zslant##1{\applyT{zslant ##1}}% \newdef\boost##1{\applyT{boost ##1}}% \newdef\xyswap{\applyT{xyswap}}% % \end{macrocode} % % \subsection{Axes and grids}\label{axes} % % \DescribeMacro{\axes} % \DescribeMacro{\xaxis} % \DescribeMacro{\yaxis} % An axis would normally not be thought of as a figure macro, because one % would not want to position them arbitrarily nor transform them. One % would also not want the hassle of having always to specify the origin, % etc. However, one would want to occasionally make them dotted or dashed % or colored. % % The original \cs{axes} was therefore not a figure macro. It always drew % both axes with solid lines. Later \cs{xaxis} and \cs{yaxis} were % introduced, which mimicked the behavior of \cs{axes}. For backward % compatibility, the old behavior is supported with the old commands. The % optional argument to \cs{axes}, \cs{xaxis} and \cs{yaxis} is the length % of the arrowhead, defaulting to \cs{the}\cs{axisheadlength}. % \begin{macrocode} \newdef\xaxis{\simple@opt\@xaxis{\the\axisheadlen}}% \newdef\yaxis{\simple@opt\@yaxis{\the\axisheadlen}}% \newdef\axes{\simple@opt\@axes{\the\axisheadlen}}% \newdef\@axes##1{\mfcmd{\@nl axes (##1)}}% \newdef\@xaxis##1{\mfcmd{\@nl xaxis (##1)}}% \newdef\@yaxis##1{\mfcmd{\@nl yaxis (##1)}}% % \end{macrocode} % % \DescribeMacro{\axis} % When border axes were added, all the code was revamped, and now we % create axes as figure macros. It also became clear there was so % much common code that it would be better to implement the syntax % \cs{axis}\marg{l}, etc., rather than have separate commands \cs{laxis}, % etc. for all six possible axes. Therefore, only the x- and y-axes have % their own commands. The \cs{axis} command has one optional argument % (the arrowhead length) and one mandatory argument, a single letter % designating the axis to draw. % % The only complication is that the x- and y-axis have one default head % length, \cs{axisheadlength} (initially \texttt{5pt}), while the side % axes have a different default, \cs{sideheadlength} (initially \texttt{0pt}). % Therefore we don't know which default to use until the mandatory argument % is read. In \cs{@@axis}, we use \cs{get@axisnum} to check this % mandatory argument and convert it to a number \cs{mfp@axisnum}, which is % used to select the head length. % \begin{macrocode} \newdef\axis{\null@opt\@axis}% \newdef\@axis[##1]##2{\get@axisnum{##2}\axis \mfp@ifempty{##1}% {\edef\mfp@param{% \ifnum\mfp@axisnum<2 \the\axisheadlen \else \the\sideheadlen \fi}\@@axis{\mfp@param}}{\@@axis{##1}}{##2}}% \newdef\@@axis##1##2{\arrow[l##1]\@figmac{axisline.##2}}% % \end{macrocode} % % \DescribeMacro{\doaxes} % \cs{doaxes} takes one optional argument, the arrowhead length, and one % mandatory argument, all the axes to draw. These should be just letters % with nothing separating them except optional spaces. \cs{doaxes} is % implemented via the self-looping macro \cs{do@axis}, which applies % one of two commands to the letter, depending on whether the optional % parameter was present (\cs{@axis}) or not (\cs{@@axis}). % \begin{macrocode} \newdef\doaxes{\null@opt\@doaxes}% \newdef\@doaxes[##1]##2{\def\mfp@axis{\@axis[##1]}% \do@axis##2\mfp@delim}% \newdef\do@axis##1{% \ifx\mfp@delim##1\relax\else\mfp@axis{##1}\@xp\do@axis\fi}% % \end{macrocode} % % \DescribeMacro{\axismarks} % \DescribeMacro{\xmarks} % \DescribeMacro{\ymarks} % \DescribeMacro{\lmarks} % \DescribeMacro{\bmarks} % \DescribeMacro{\rmarks} % \DescribeMacro{\tmarks} % Hash marks (or tick marks) on the axes are provided by the % \cs{axismarks} command (\cs{marks} was the original choice, but that % turned out to conflict with a primative of e\TeX). For brevity, therefore, % we also have separate commands \cs{xmarks}, etc. \cs{axismarks} has two % mandatory arguments: the letter for the axis, and a comma separated % list of numbers giving the positions on the axis. It functions as a list % macro (see previous discussion of types of macros) and so the list of % numbers can be prescribed by an external file % \cs{datafile}\marg{\meta{file}}. One must be sure to issue an % appropriate \cs{using} command to produce a numeric list in the output. % This is the main reason for the \cs{usingnumericdefault} command. % % I had a change of heart after the \cs{axis} command, and I made things % simpler to code here by putting the optional argument of \cs{axismarks} % after the first mandatory argument. I could justify this because I % expect most users will use the shorter versions that don't require the % first argument (that is, the expectation that optional arguments come % first is still satisfied). The optional argument is the length of the % marks. The position of the marks is controlled separately by the % \cs{setaxismarks} command, described previously. % \begin{macrocode} \newdef\axismarks##1{\simple@opt{\@marks{##1}}{\the\hashlen}}% \newdef\@marks##1##2{\mfsrc{\@nl ##1marks (##2)}\mfp@writedata}% \newdef\xmarks{\axismarks x}% \newdef\ymarks{\axismarks y}% \newdef\lmarks{\axismarks l}% \newdef\bmarks{\axismarks b}% \newdef\rmarks{\axismarks r}% \newdef\tmarks{\axismarks t}% % \end{macrocode} % % \DescribeMacro{\grid} % \DescribeMacro{\gridpoints} % \DescribeMacro{\lattice} % The first one is, I think, inaccurately named: the word `grid' calls % to mind a set of lines. It functions in a similar way: allowing a % visualization of the coordinates, but it actually produces dots. The % dots are located at the points whose coordinates are integer multiples % of two numbers, which are given in the single mandatory argument % separated by commas. The optional first argument is the diameter of the % dots this defaults to \texttt{0.5bp} (hard coded in \file{grafbase}). % Because of the name, I have provided two aliases: \cs{gridpoints} % (for consistency with \cs{gridlines}, below) and \cs{lattice}. % % \DescribeMacro{\gridlines} % Macro \cs{gridlines} takes the same mandatory argument and draws % horizontal and vertical lines intersecting at all the dots that % \cs{grid} would draw. Some packages (and \ConTeXt) define a \cs{grid} % command so we use \cs{def} here instead of \cs{newdef} or \cs{redef}. % % \DescribeMacro{\hgridlines} % \DescribeMacro{\vgridlines} % These two draw only the horizontal or vertical lines, and their % argument is the separation (in graph units) between successive lines. % \begin{macrocode} \def\grid{\null@opt\@grid}% \newdef\@grid[##1]##2{% \mfcmd{\mfp@ifempty{##1}{grid}{vgrid (##1)} (##2)}}% \newlet\gridpoints=\grid \newlet\lattice=\grid \newdef\gridlines##1{\mfcmd{\@nl gridlines (##1)}}% \newdef\vgridlines##1{\mfcmd{\@nl vgridlines (##1)}}% \newdef\hgridlines##1{\mfcmd{\@nl hgridlines (##1)}}% % \end{macrocode} % % \DescribeMacro{\plrgrid} % \DescribeMacro{\plrgridpoints} % \DescribeMacro{\gridarcs} % \DescribeMacro{\gridrays} % \DescribeMacro{\plrpatch} % The command \cs{plrgrid} takes one mandatory argument which contains two % numbers separated by a comma. The first is a radius and the second an % angle. It draws circular arcs at integer multiples of the radius, and % radial lines at integer multiples of the angle. It fills the % picture rectangle and is clipped to that rectangle. \cs{plrgridpoints} % is similar but places only dots at the intersections of these arcs and % rays. It takes an optional argument for the size of the dots, normally % \cs{dotsize}. \cs{gridarcs} draws only the arcs, \cs{gridrays} only the % rays. These last two take only one parameter each: the radius separating % the arcs, and the angle separating the rays. % % \cs{plrpatch} draws: a circular arc at a starting % radius, then increments that radius by a step size and draws another % arc, etc., and finally draws an arc at the ending radius. It does a similar % thing for radial lines and angles. It takes one mandatory argument, % which contains 6 numbers separated by commas: starting radius, ending % radius, step size, starting angle, ending angle, step size. % \begin{macrocode} \newdef\plrgrid##1{\mfcmd{\@nl polargrid (##1)}}% \newdef\plrgridpoints{\simple@opt\@plrgp{\the\dotsize}}% \newdef\@plrgp##1##2{\mfcmd{\@nl polargridpoints (##1, ##2)}}% \newdef\gridarcs##1{\mfcmd{\@nl gridarcs (##1)}}% \newdef\gridrays##1{\mfcmd{\@nl gridrays (##1)}}% \newdef\plrpatch##1{\mfcmd{\@nl polarpatch (##1)}}% % \end{macrocode} % % \subsection{Visualizing points}\label{points} % % \DescribeMacro{\point} % \DescribeMacro{\plotsymbol} % \cs{point} draws a dot or a small circle. It takes one optional % argument, the diameter of the dot, and one mandatory argument, the ordered % pair (or comma separated list of them) at which to draw a dot. After % \cs{pointfillfalse}, the dots will be unfilled (i.e., small circles), % after \cs{pointfilltrue} (the default), they will be solid. Like the % grid macros, it is not a figure macro, but merely does its drawing and % is not subject to any prefix macros. % % In order to mark points with other than circles, we have the % \cs{plotsymbol} command, so-called because it uses the same symbols as % the \cs{plot} command (previously discussed). There is an optional % argument that gives the size of the symbol, a mandatory argument with % the name of the symbol, and a second mandatory argument which % is a comma separated list of ordered pairs for the locations. % % For both these commands, the default optional argument is % \cs{the}\cs{pointsize}. % \begin{macrocode} \newdef\point{\simple@opt\@point{\the\pointsize}}% \newdef\@point##1{% \mfsrc{\@nl pointd (##1, \ifpointfill\mf@T\else\mf@F\fi)}% \mfp@writedata}% \newdef\plotsymbol{\simple@opt\@plotsymbol{\the\pointsize}}% \newdef\@plotsymbol##1##2{% \mfsrc{\@nl plotsymbol (##2, ##1)}\mfp@writedata}% % \end{macrocode} % % \DescribeMacro{\plottext} % In \MP{}, \TeX{} labels can be used in place of the symbols in % \cs{plotsymbol}. Moreover, multiple copies of text can be placed with % the \cs{tlabel} command (under \opt{mplabels}), as it supports a list of % points for the location parameter. For \MF{} we supply an alternative, % \cs{plottext}, which loops through the list of coordinates and issues % \cs{tlabel} commands. The text can be anything that works in \cs{tlabel}. % % It takes one optional argument, the justification of the text (as in the % \cs{tlabel command}, below---see also \cs{tlabeljustify}, above), % defaulting to \oarg{cc}. There are two mandatory arguments: the text, % and a comma separated list of ordered pairs. For consistency with % \cs{plotsymbol} (and because it works better), we now require the same % syntax for the points (i.e., no braces around individual points in the % list as are allowed in \cs{tlabel} commands). % % We start by handling the justification, resetting whitespace, % and loading the text into a token register. Then we read the list of % points with \cs{@@plottext}. Under \opt{mplabels} we process the whole % list with a single \cs{tlabel} command. Otherwise we prepare to loop % through the list of points. The \cs{begingroup} in \cs{@plottext} is % ended by the command called in \cs{@@plottext}. % \begin{macrocode} \newdef\plottext{\simple@opt\@plottext{cc}}% \newdef\@plottext##1{% \begingroup \mfp@resetwhitespace \tlabeljustify{##1}% \@ifmplabels{\@makeother\#}{}% \mfp@gettoks\@@plottext}% \newdef\@@plottext##1{% \@ifmplabels {\mfp@setMPpos \def\mfp@points{##1}\@@@tlabel}% {\@@@plottext##1,\mfp@delim}}% % \end{macrocode} % After reading the list of points and appending ending tokens, we % loop through them. The ending condition is that the next token is % \cs{mfp@delim}. Otherwise we read the coordinates as delimited macros, % and call \cs{@tlabel}, feeding it the coordinates and the text to % plot there (the \cs{begingroup} in \cs{x@plottext} matches the % \cs{endgroup} in \cs{@tlabel}). Then we recall \cs{@@@plottext} for % another loop. Since we have used two internal commands of \cs{tlabel} % code, we have to remember to check this if ever we rewrite \cs{tlabel}. % \begin{macrocode} \newdef\@@@plottext{% \mfp@ifnextchar\mfp@delim{\@firstoftwo\endgroup}{\x@plottext}}% \newdef\x@plottext(##1,##2),{\begingroup \@tlabel{##1}{##2}{\the\mfp@toks}\@@@plottext}% % \end{macrocode} % % \subsection{Figure macros}\label{figure} % % \subsubsection{Common geometric objects}\label{geometric} % % Finally we get to the real figure macros. These are implemented as % \MF{} paths that can be variously rendered, transformed, etc., with the % prefix macros. % % The first few (\cs{rect} through \cs{makesector}) are closed paths and % need not be prefixed with a closing macro before filling, etc. % % \DescribeMacro{\rect} % This takes one mandatory argument, the two diagonally opposite % corners of the rectangle separated by a comma, and draws the rectangle % with horizontal and vertical sides having these as two corners. The % direction of the path (which seldom makes a difference) is such that it % starts at the first specified point and moves horizontally first. % \begin{macrocode} \newdef\rect##1{\@figmac{rect (##1)}}% % \end{macrocode} % % \DescribeMacro{\regpolygon} % There are four arguments. The first is the number of sides. The second % is the name of a variable to represent the vertices. The other % two should be equations locating two vertices or the center and one % vertex. If the name used is \gbc{Ver}, then the vertices will be % \gbc{Ver1}, \gbc{Ver2}, etc., numbering anticlockwise. The center is % \gbc{Ver0}. Case is significant. After the command, the points can be % referred to in other \mfpic{} commands (except text label commands % when \opt{mplabels} is not in effect). % \begin{macrocode} \newdef\regpolygon##1##2##3##4{% \@figmac{regularpolygon(##1)(##2)(##3;##4;)}}% % \end{macrocode} % % \DescribeMacro{\circle} % This has one optional argument containing one of the letters % \texttt{t}, \texttt{p} (the default), \texttt{c}, or \texttt{s}. Its % purpose is to specify what kind of data is in the single mandatory % argument. These are a subset of the optional arguments that the \cs{arc} % commad (below) takes, and have almost the same meaning: % \begin{itemize} % \item \oarg{t}, the three point form needs three points (of course). % \item \oarg{p}, the polar form needs the center point and the radius. % This is the default when the optional argument is absent. % \item \oarg{c}, the center/point form needs the center and one point on % the circle. % \item \oarg{s}, the point-sweep form requires two points and the angle of % arc between them. The angle may be positive or negative. A % positive angle indicates the number of degrees anticlockwise from % the first point to the second. Negative means clockwise. % \end{itemize} % % Supplying \cs{arc} with the same parameters, or the appropriate superset % in the case of \oarg{p} and \oarg{c}, would produce a sub-arc of the % circle that \cs{circle} produces. This is the reason for giving % \cs{circle} these options: to make diagrams which show a circle and an % arc on it. (This can also be done with an ellipse by using a % transform on a circle and its arc. % % We use \cs{def} instead of \cs{newdef} or \cs{redef} because we know % \LaTeX{} has already defined a \cs{circle} command, but plain \TeX{} has % not. Instead of passing the default \texttt{p}, we pass a null % argument, causing the code to compare various letters to \cs{relax} % (always false) and then execute the default code. % \begin{macrocode} \def\circle{\null@opt\circl@}% \newdef\circl@[##1]##2{% \if t##1\relax \@figmac{circleppp (##2)}% \else\if c##1\relax \@figmac{circlecp (##2)}% \else\if s##1\relax \@figmac{circlepps (##2)}% \else \@figmac{circle (##2)}% \fi\fi\fi}% % \end{macrocode} % % \DescribeMacro{\ellipse} % \cs{ellipse} has one optional argument, an angle of rotation and one % mandatory argument, containing the center, the horizontal radius (before % rotation) and the vertical radius, separated by commas. % \begin{macrocode} \newdef\ellipse{\simple@opt\@ellipse{0}}% \newdef\@ellipse##1##2{\@figmac{ellipse (##2, ##1)}}% % \end{macrocode} % % \DescribeMacro{\sector} % This is the closed curve starting at the center of a circle, out % along a radius to the circumference of the circle, along an arc of the % circle, then back to the center. It has one mandatory argument % containing the center, the radius, and the two angles, separated by % commas. % % \DescribeMacro{\makesector} % Takes a following arc and draws the sector (even if the center point % is not known). It is really a prefix macro (closing an arc with two % straight lines), but the combination \cs{makesector}\cs{arc} acts like a % figure. % \begin{macrocode} \newdef\sector##1{\@figmac{sector (##1)}}% \newdef\makesector{\@closmac{makesector}}% % \end{macrocode} % % \DescribeMacro{\arc} % A circular arc can be specified in several ways and we support most of % them. \cs{arc} takes an optional argument: a letter to indicate which % specification. It has one mandatory argument containing the data for % that specification, separated by commas. % % The available letters and the corresponding required data are: % \begin{itemize} % \item \oarg{t}, the three point form needs three ordered pairs. % \item \oarg{p}, the polar form needs the center point, two angles and % the radius. % \item \oarg{a}, the alternative polar form needs the center, the radius % and two angles. % \item \oarg{c}, the center-point-sweep form needs the center, the % starting point, and the angle. % \item \oarg{s}, the point-sweep form requires the starting point, the % ending point and the angle. % \end{itemize} % % The default optional argument is \oarg{s}. (I don't know why. It % certainly doesn't seem the most natural. I would have picked \oarg{a}.) % Like \cs{circle}, an empty argument is passed by default. % \begin{macrocode} \newdef\arc{\null@opt\@arc}% \newdef\@arc[##1]##2{% \if t##1\relax \@figmac{arcppp (##2)}% \else\if p##1\relax \@figmac{arcplr (##2)}% \else\if a##1\relax \@figmac{arcalt (##2)}% \else\if c##1\relax \@figmac{arccps (##2)}% \else \@figmac{arcpps (##2)}% \fi\fi\fi\fi}% % \end{macrocode} % % \DescribeMacro{\plr} % \DescribeMacro{\midpoint} % A little utility to convert a list of pairs into another list of % pairs, where the given list are assumed to be polar coordinates and the % results are their Cartesian counterparts. And one to calculate the % midpoint, given two points separated by a comma. % \begin{macrocode} \newdef\plr##1{map (polar) (##1)}% \newdef\midpoint##1{(0.5[##1])}% % \end{macrocode} % % \subsubsection{List macros}\label{list} % % The next several figure macros are all list macros. They draw a path % determined by a list of points. The list can be explicitly given as a % mandatory argument containing a comma-separated list of ordered pairs, % or it can be taken from an external datafile. This is true for % \cs{polyline} through \cs{turtle}. These macros differ only in % how the points determine the path. (The splines don't actually connect % the points given, but rather use the points in a different way to % determine a curve.) The list of points is not an argument of any of % these. It should follow, and is picked up and written to output by the % ending code of \cs{@listmac}. This is basic to list macros, and will not % be repeated for each one. % % \DescribeMacro{\polyline} % \DescribeMacro{\polygon} % The most basic, a polyline or polygonal path, \cs{polyline} % draws line segments from each point to the next. \cs{lines} is an % alias. \cs{polygon} does the same, except it closes the path by % connecting the last point to the first. % % In \cs{@polyline}, the argument is \mfc{true} or \mfc{false}, % indicating whether the path is to be closed. % \begin{macrocode} \newdef\polyline{\@polyline\mf@F}% \newlet\lines=\polyline \newdef\polygon{\@polyline\mf@T}% \newdef\@polyline##1{\@listmac{polyline (##1)}}% % \end{macrocode} % % \DescribeMacro{\curve} % \DescribeMacro{\cyclic} % \cs{curve} draws a smooth curve connecting a list of points. it arranges % for the curve, at point $p\sb n$ to be traveling parallel to the direction % from $p\sb {n-1}$ to $p\sb {n+1}$ (except at the first and last point). % % \cs{cyclic} is similar, except the curve is closed, and at the first % point it also travels parallel to the direction from the previous point % (the last one listed) to the next. % % There is an optional argument, which is the tension. This is a number % greater than .75. The larger it is, the closer to a polyline one gets. % The default is 1 (set in \file{grafbase}) or more generally, the value % set by \cs{settension}. % \begin{macrocode} \newdef\curve {\null@opt{\@curve\mf@F}}% \newdef\cyclic{\null@opt{\@curve\mf@T}}% \newdef\@curve##1[##2]{% \@listmac{\mfp@ifempty{##2}{curve}{tcurve (##2)} (##1)}}% % \end{macrocode} % % \DescribeMacro{\fcncurve} % A `function curve' is the graph of a function of $x$. It should always % travel left to right. This is not guaranteed by the \cs{curve} macro, % above, even if the x-coordinates are listed in order. \cs{fcncurve} is % guaranteed to do this if the list of points has the x-coordinates so % ordered. % % The optional argument is called tension. Internally, it is not quite the % same as the tension argument to \cs{curve}, but it also governs how % closely the curve stays to the corresponding polyline. If the optional % argument is missing, this command uses $1.2$ (more precisely, it uses % $1.2$ times the value set with \cs{settension}). The above guarantee is % voided if the value used is less than $1$. However, most curves will % satisfy the guarantee with some lower values. % \begin{macrocode} \newdef\fcncurve{\null@opt\@fcncurve}% \newdef\@fcncurve[##1]{% \@listmac{\mfp@ifempty{##1}{fcncurve}{functioncurve (##1)}}}% % \end{macrocode} % % \DescribeMacro{\qspline} % \DescribeMacro{\closedqspline} % \DescribeMacro{\cspline} % \DescribeMacro{\closedcspline} % These are supposed to be types of splines, about which I know only a % little. The list or datafile that should follow each command should % contain not the points passed through, but instead the control data. % For quadratic B-splines the points create the path as follows: for % successive points $p\sb i, p\sb {i+1}$ in the list, the path passes through % the midpoint of the line segment connecting $p\sb i$ and $p\sb {i+1}$, tangent % to that line segment. % % Cubic splines determine the curve as follows: for successive points % $p\sb i, p\sb {i+1}$ in the list, the line segment connecting them is divided % into thirds with two points $q\sb i$ and $q\sb i'$. The curve then passes % through the midpoint of the segment from $q\sb {i-1}'$ to $q\sb i$ and tangent % to that segment. % % `Control' is obtained as follows: the farther apart the points $p\sb i$ % and $p\sb {i+1}$ (quadratic) or $q\sb {i-1}'$ and $q\sb i$ (cubic) the % less the curvature of the curve at the midpoint. % % The `\texttt{q}' versions produce quadratic splines, the `\texttt{c}' % versions produce cubic splines. % \begin{macrocode} \newdef\qspline{\@listmac{openqbs}}% \newdef\closedqspline{\@listmac{closedqbs}}% \newdef\cspline{\@listmac{opencbs}}% \newdef\closedcspline{\@listmac{closedcbs}}% % \end{macrocode} % % \DescribeMacro{\mfbezier} % \DescribeMacro{\closedmfbezier} % These produce the standard \MF{} cubic B\'ezier (the connection is % \mfc{..} unless the optional argument is used) with tension given by % an optional argument. A mandatory argument (not shown) contains the % list of points. % % \DescribeMacro{qbeziers} % \DescribeMacro{closedqbeziers} % These produce the equivalent of a sequence of \LaTeX{} \cs{qbezier} % commands. The mandatory argument will be a list of points alternating % between nodes and control points. Note that quadratic B\'eziers need % not be smooth at the nodes unless the control points line up. Our % plural name distinguishes it from the \LaTeX{} command. % \begin{macrocode} \newdef\mfbezier{\null@opt{\@mfbezier\mf@F}}% \newdef\closedmfbezier{\null@opt{\@mfbezier\mf@T}}% \newdef\@mfbezier##1[##2]{% \@listmac{\mfp@ifempty{##2}{bezier}{tbezier (##2)} (##1)}}% \newdef\qbeziers{\@listmac{qbezier (\mf@F)}}% \newdef\closedqbeziers{\@listmac{qbezier (\mf@T)}}% % \end{macrocode} % % \DescribeMacro{\turtle} % Many years ago there was a tool for teaching programming concepts to % young children. They could draw a figure on a screen by programming a % `turtle' with a sequence of turns and distances. The following is % similar. It has a mandatory argument containing a list of ordered pairs. % The first is the coordinates of the starting point, and each of the rest % is interpreted as a displacement from the current position, along which % a line segment is to be drawn. The terminal point of that segment is the % new current position % \begin{macrocode} \newdef\turtle{\@listmac{turtle}}% % \end{macrocode} % % \subsubsection{Graphing functions}\label{functions} % % \DescribeMacro{\function} % \prog{Mfpic} provides the ability to plot the graph of any function that % can be defined in \MF. This is done with the \cs{function} command, a % figure macro which takes one optional parameter that selects % the smoothness of the \MF{} path produced. It can be \oarg{p}, which % draws a polyline path through selected points (much like \cs{polyline}), % or \oarg{s\meta{tension}} which selects a smooth path (much like % \cs{curve}\oarg{\meta{tension}}). The tension may be omitted and then % defaults to 1 (set in \file{grafbase}). The default is \oarg{s}. % % There are two mandatory arguments. The second is the function, which % must be written as a formula (strictly speaking, a \MF{} numerical % expression) containing only one variable, \texttt{x}. The first % mandatory argument contains three numbers separated by commas. They are, % in order, the starting value of \texttt{x}, the ending value, and the % step size. % % \DescribeMacro{\parafcn} % \cs{parafcn} is similar, except its formula must be an ordered pair of % formulas (strictly speaking, a \MF{} pair expression) in which % \texttt{t} is the only variable. % % \DescribeMacro{\plrfcn} % \cs{plrfcn} is similar, except its argument is a formula (a \MF{} % numeric expression) representing the radius, in which \texttt{t} is the % only variable, interpreted as the angle coordinate, $\theta$, in degrees. % % These three commands are so alike that all they do is set the name to % be written to the output and call the common code. % \begin{macrocode} \newdef\function{\def\mfp@name{function}\mfp@fcn}% \newdef\parafcn{\def\mfp@name{parafcn}\mfp@fcn}% \newdef\plrfcn{\def\mfp@name{plrfcn}\mfp@fcn}% \newdef\mfp@fcn{\simple@opt\@mfp@fcn{s}}% \newdef\@mfp@fcn##1{\@@mfp@fcn##1\mfp@delim}% \newdef\@@mfp@fcn##1##2\mfp@delim##3##4{% \@figmac{\mfp@ifempty{##2}{}{t}\mfp@name\space (\if p##1\mf@F\else\mf@T\fi \mfp@ifempty{##2}{}{, ##2}) (##3) (##4)}}% % \end{macrocode} % % \DescribeMacro{\btwnfcn} % The region between two functions \cs{btwnfcn} is a figure macro. It is % mostly intended for shading or other filling operations so it is already % closed and, by default, it is not `smooth'. Its parameters are the % same as those of \cs{function} (above), with two exceptions: the default % optional argument is \oarg{p} and it has an additional mandatory % argument, the other function. The resulting \MF{} path travels along one % the graph of the first function from the starting $x$ to the ending $x$, % thence vertically to the graph of the second function, along it (in % reverse) to the starting $x$ and finally, vertically to the start of the % first function's graph. % % \DescribeMacro{\plrregion} % The figure macro \cs{plrregion} also produces a closed \MF{} path. It % has the same parameters as \cs{plrfcn}, and the path produced begins at % the origin, travels along a straight line in the direction of the % starting angle to the beginning of the graph of the expression, along % that graph to the ending angle and then straight back to the origin. Its % default option is also \oarg{p}. % \begin{macrocode} \newdef\btwnfcn{\simple@opt\@btwnfcn{p}}% \newdef\@btwnfcn##1{\@@btwnfcn##1\mfp@delim}% \newdef\@@btwnfcn##1##2\mfp@delim##3##4##5{\btwn@params{##1}{##2}% \@figmac{\t@pref btwnfcn (\s@vals) (##3) (##4) (##5)}}% \newdef\btwn@params##1##2{% \edef\s@vals{\if s##1\mf@T\else\mf@F\fi}% \mfp@ifempty{##2}{\def\t@pref{}}% {\def\t@pref{t}\edef\s@vals{\s@vals, ##2}}}% \newdef\plrregion{\simple@opt\@plrregion{p}}% \newdef\@plrregion##1{\@@plrregion##1\mfp@delim}% \newdef\@@plrregion##1##2\mfp@delim##3##4{\btwn@params{##1}{##2}% \@figmac{((0,0)--(\t@pref plrfcn (\s@vals) (##3) (##4))% --cycle)}}% % \end{macrocode} % % \subsection{Some composite objects}\label{composite} % % \DescribeMacro{\tile} % A tile is syntactically a \MF{} picture variable. The commands between % \cs{tile} (or \cs{begin}\marg{tile}) and \cs{endtile} (or % \cs{end}\marg{tile}) should be any sequence of \mfpic{} figure macros % with possible prefix macros. They will be drawn not on the main picture % (\gbc{currentpicture}), but on the picture given by the name in the % \cs{tile} command's argument. % % The argument has five parts separated by commas, the first is the % name, the second is the unit of length (some absolute dimension like % \mfc{1pt}), the next two are the width and height (pure numbers, the % actual dimensions being these numbers times the unit of length), the % last is one of the words \mfc{true} or \mfc{false}, indicating whether % tile should be clipped to these dimensions (true) or allowed to extend % beyond them (false). % \begin{macrocode} \newdef\tile##1{\mfcmd{\@nl tile (##1)}}% \newdef\endtile{\mfsrc{endtile;\@nl}}% % \end{macrocode} % % \DescribeMacro{\patharr} % A path array is a set of \MF{} path variables each having the same name % followed by a different numeric suffix. This command turns off rendering % and simply assigns these variables in order to the path expressions % written by the figure macros between \cs{patharr} and \cs{endpatharr}. % It works by redefining \cs{store@path}, issued by all the figure % macros. These variables can be accessed in \mfpic{} by using the % \cs{mfobj} command. % % \emph{Explicit} rendering commands will work in the sense that the % affected path will be rendered in addition to being assigned to the % variable. The only parameter is the common name of the variables. % \begin{macrocode} \newdef\patharr##1{\begingroup \mfsrc{hide(numeric ##1; path ##1[]; ##1 = 0)}% \def\store@path{\mfsrc{\@nl store (##1[incr ##1])}}% \setrender{}}% \newdef\endpatharr{\endgroup}% % \end{macrocode} % % \DescribeMacro{\connect} % \DescribeMacro{\endconnect} % These define an environment that can contain any sequence of figure % macros. It functions as a single large \cs{@figmac}, the figure being % the path obtained by connecting all the paths within by straight lines % from the end of one to the beginning of the next. It is implemented via % a path array, so the individual figures within the environment have % implicit rendering turned off. Explicit rendering commands within the % environment will have the expected effect. % % The \cs{if@mfp@latex} stuff at the end allows \cs{connect} to be used as % a \LaTeX{} environment. % \begin{macrocode} \newdef\connect{\@figmac{begingroup; save nexus}% \patharr{nexus}}% \newdef\endconnect{\endpatharr \mfcmd{\@nl mkpoly (\mf@F, nexus)\@nl endgroup}% \if@mfp@latex \def\mfptmp@a{connect}% \ifx\mfptmp@a\@currenvir \aftergroup\@startfigtrue %\aftergroup\@imrendtrue \fi \fi}% % \end{macrocode} % % \subsection{Other graphical features}\label{otherfeatures} % % And now for something completely different: pie charts and bar charts % (or bar graphs, or histograms). % % \DescribeMacro{\piechart} % The \cs{piechart} command takes one optional argument containing a % letter and an angle, and one mandatory argument containing the data. The % letter can be `\texttt{c}' for clockwise or `\texttt{a}' for anticlockwise % and determines the direction around the pie the different wedges will be % drawn. The angle determines the angle of the first edge (in the given % direction) of the first wedge. The default is \oarg{c90} which starts % the first wedge at 12 o'clock and proceeds clockwise from there. The % data in the mandatory argument are numbers separated by commas. The size % of a wedge is proportional to the size of the corresponding number. % \cs{piechart} is a list macro and can take the data from an external % file. % % \DescribeMacro{\piewedge} % Actually, nothing is drawn, it only defines a path array and a few % other internal variables. Each individual wedge (elements of the just % mentioned array) may be drawn using the \cs{piewedge} command, which is % a figure macro. That command takes one optional argument that determines % how the wedge is drawn, as described below, and one mandatory argument, % the number of the wedge. Without the optional argument, % \cs{piewedge}\marg{1} draws the first wedge in the position given by the % arguments of the \cs{piechart} command. % % The optional arguments can be: % \begin{itemize} % \item \oarg{x\meta{distance}}, the wedge is exploded, drawn % shifted outward from its position by \meta{distance} (in graph % units). % \item \oarg{s(\meta{dx},\meta{dy})}, the wedge is shifted from its % position by \meta{dx} horizontally and \meta{dy} vertically (in % graph units). % \item \oarg{m(\meta{x},\meta{y})}, the wedge is moved so that its % point is at coordinates \parg{\meta{x},\meta{y}}. % \end{itemize} % \begin{macrocode} \newdef\piechart{\simple@opt\@piechart{c}}% \newdef\@piechart##1{\@@piechart##1\mfp@delim}% \newdef\@@piechart##1##2\mfp@delim##3{% \mfsrc{\@nl piechart(\if a##1 \else-\fi1, % \mfp@mtsub{##2}{90}, ##3)}\mfp@writedata}% \newdef\piewedge{\simple@opt\@piewedge{d}}% \newdef\@piewedge##1{\@@piewedge##1\mfp@delim}% \newdef\@@piewedge##1##2\mfp@delim##3{% \@figmac{(piewedge[##3]% \if x##1 shifted (##2*piedirection[##3])% \else\if s##1 shifted (##2)% \else\if m##1 shifted (##2 - piecenter)% \else \fi\fi\fi)}}% % \end{macrocode} % % \DescribeMacro{\barchart} % \DescribeMacro{\bargraph} % \DescribeMacro{\gantt} % \DescribeMacro{\histogram} % The \cs{barchart} command takes one optional and two mandatory % arguments. The last mandatory argument contains the data, separated by % commas and these determine the length of the bars in graph units. This % is also a list macro and instead of the list, an external file can hold % the data. % % The optional argument determines the position and width of the bars and % the first mandatory argument determines the orientation. The mandatory % argument can be \marg{v} for vertical bars with base on the x-axis, or % \marg{h} for horizontal bars with base on the y-axis. % The optional argument contains three numbers separated by commas. The % first is the coordinate of the leading edge of the first bar, the second % is the distance (in graph coordinates) between the leading edge of one % bar and that of the next, and the third is the fraction of that distance % that is occupied by the bar. The default is \oarg{0,1,1}. % % We provide the aliases \cs{bargraph} and \cs{histogram}. % % \DescribeMacro{\chartbar} % \DescribeMacro{\ganttbar} % \DescribeMacro{\graphbar} % \DescribeMacro{\histobar} % The \cs{barchart} command does not actually draw anything, but defines a % path array. The \cs{chartbar} command can then be used to draw a bar % (one of the members of the just mentioned array). It is a figure macro % and take the number of the bar as its mandatory argument. Aliases % \cs{graphbar} and \cs{histobar} are provided. We avoid \cs{bar} because % it is a math accent command. % \begin{macrocode} \newdef\barchart{\simple@opt\@barchart{0,1,1}}% \newdef\@barchart##1##2{% \mfsrc{\@nl barchart (##1, \if h##2\mf@F\else\mf@T\fi)}% \mfp@writedata}% \newlet\bargraph=\barchart \newlet\histogram=\barchart \newlet\gantt\barchart \newdef\chartbar##1{\@figmac{chartbar[##1]}}% \newlet\graphbar=\chartbar \newlet\histobar=\chartbar \newlet\ganttbar=\chartbar % \end{macrocode} % % One can add to \cs{mfp@additions} to extend \mfpic. Currently it % is empty. This ends \cs{@mfpic@graf@macs}. % \begin{macrocode} \newdef\pinumber{3.14159}% \mfp@additions }% % \end{macrocode} % % % \section{The \env{mfpic} environment}\label{mfpicenv} % % \subsection{Initializations}\label{mfpicinitializations} % % \DescribeMacro{\mfpic} % This command (or the \LaTeX{} environment \cs{begin}\marg{mfpic}) takes % two optional arguments: the xscale and the yscale. When both are % omitted, they are both set to 1, if the yscale is omitted, it is set % equal to the xscale. % % There are also 4 mandatory arguments: the first two give the minimum and % maximum extent of the x coordinates and the last two do the same for the % y coordinates. The coordinates used in the figure commands within an % mfpic environment are multiplied by the corresponding scales, and that % is the multiple of \cs{mfpicunit} used in positioning, drawing, etc. % % The optional arguments are converted by the option handling code to % mandatory arguments for \cs{@mfpic}, which contains the actual % definition. % \begin{macrocode} \newdef\mfpic{\simple@opt\@mfpicA{1}}% \newdef\@mfpicA#1{\simple@opt{\@mfpic{#1}}{#1}}% \newdef\@mfpic#1#2#3#4#5#6{% % \end{macrocode} % % We start by saving \mfpic{} extra fontdimen values. They will be % restored by \cs{endmfpic}. This makes the values local (font dimensions % are normally always global). Then we begin a group to localize ordinary % \TeX{} definitions and assignments, disable writes to the output if % \cs{opengraphsfile} hasn't occurred yet. save the current font in % \cs{@tcurr} for restoration inside text labels and captions, set the % switch that says we are in an \cs{mfpic} environment, disable \cs{par} % so that blank lines have (little or) no effect, and switch to % \cs{nullfont} so that stray characters (always an error) and spaces (not % an error), have no effect. I wonder if \cs{@empty} is a better % disabling definition for \cs{par} than \cs{relax}. % \begin{macrocode} \save@mfpicdimens \begingroup % ended near end of \endmfpic \@ifmfpfileisopen{}% {\if@mfp@nowrite\else \nooutputfileerror{\mfpic}% \def\@mfsrc##1##2{}% \fi}% \mfp@DBlog{Starting mfpic \number\mfp@count \@online.}% \font\@tcurr=\fontname\font\relax \let\ifin@mfpicenv\iftrue % \let\par\relax \let\par\@empty \nullfont % \end{macrocode} % % The graphics macros are undefined outside the \env{mfpic} environment. % They are defined now by invoking \cs{@mfpic@graf@macs}. % \begin{macrocode} \@mfpic@graf@macs % \end{macrocode} % % Then we define two utility macros used to convert graph coordinates into % actual dimensions relative to the lower left corner of the picture. The % first argument is a dimension, but it is normally obtained by first % multiplying a coordinate value by \cs{mfpicunit}. Since font dimensions % may be involved, we assign \texttt{\#\#1} to a scratch dimension % register first, since \TeX{} won't \cs{advance} font dimensions. We make % the final assignment global for consistency. % \begin{macrocode} \newdef\@xconv##1{% {\mfp@scratch = ##1\relax \advance\mfp@scratch by -#3\mfpicunit \mfp@scratch = #1\mfp@scratch \global ##1 = \mfp@scratch}}% \newdef\@yconv##1{% {\mfp@scratch=##1\relax \advance\mfp@scratch by -#5\mfpicunit \mfp@scratch = #2\mfp@scratch \global ##1 = \mfp@scratch}}% % \end{macrocode} % % We are going to add all text labels to a box \cs{@alltlabels} and put % that whole box on top of the graph during \cs{endmfpic}. % We initialize the box here. The dimensions \cs{@tlabelsbot}, etc., % are also initialized. Each will be changed as labels are added, so a % `non-maxdimen' value at \cs{endmfpic} means there are labels to add. % \begin{macrocode} \setbox\@alltlabels\vbox{\hbox{}}% \@tlabelsbot \maxdimen \@tlabelstop -\maxdimen \@tlabelsleft \maxdimen \@tlabelsright-\maxdimen % \end{macrocode} % % The graph is loaded into a box register at the end of the mfpic % environment. The size of that box register may have to correspond to the % arguments of the \cs{mfpic} command. Since \cs{endmfpic} doesn't receive % these arguments we process them now. % % Dimensions \cs{@graphright}, etc., represent the extent of the graph % box. We increase them when the text is added if it extends beyond the % edges of the graph. These are all font dimensions, so they are global % assignments. % \begin{macrocode} \@graphright=#4\mfpicunit \@xconv\@graphright \@graphtop=#6\mfpicunit \@yconv\@graphtop \@graphleft=0pt \@graphbot=0pt \@graphwd=\@graphright % \end{macrocode} % % \subsection{Initialization code for the current % picture}\label{current} % % Each \env{mfpic} environment produces a \gbc{beginmfpic...endmfpic} % environment in the output file. Here we initialize the variables that % correspond there to the 6 arguments and \cs{mfpicunit}, then begin the % \MF{} environment. \gbc{beginmfpic} takes the number of the current % figure as its only argument. For debugging purposes we write a \MF{} % comment the contains the line number in the \TeX{} source file where the % \cs{mfpic} command occurred. We also write a line of dashes % (\cs{mf@d}) to make it easier to find the start of the environment. This % will be removed in the public release. % % When \opt{mplabels} is in effect we need to set the font for the labels % to the saved \cs{@tcurr} by writing some \mfc{verbatimtex} code. Since % \opt{mplabels} can be turned on at any time, we write this whenever the % \opt{metapost} option is in effect. It is a common misconception that % \mfc{verbatimtex} can be used only once at the start of a \MP{} file. In % fact it can be used any number of times. It's purpose is to be at an % outer level, while \mfc{btex} is localized inside a box % \begin{macrocode} \mfsrc{\@nl \mf@p\mf@d\mf@d\mf@d\@nl unitlen := \the\mfpicunit\mf@s;\@nl xscale := #1; yscale := #2;\@nl bounds (#3, #4, #5, #6);\@nl \@nl beginmfpic(\number\mfp@count); \mf@p\space\@mfplineno. \mfp@ifmpost {\@nl verbatimtex \@nl \begingroup\space\font\noexpand\MFPcfont=\fontname\@tcurr\@nl etex;}{}}% % \end{macrocode} % % \subsection{Placing text labels}\label{textlabels} % % All the rest of \cs{@mfpic} defines commands that in some way or another % produce labels. The easiest part is defining \cs{tlabel} under % \opt{mplabels} where most of the work takes place in \file{grafbase.mp}. % The most involved is the definition of \cs{tlabel} without % \opt{mplabels}. All the rest (except \cs{tcaption}) add labels by % calling \cs{tlabel}. Some of those could be simpler under \opt{mplabels} % but then we'd need two versions of each. % % \DescribeMacro{\tlabel} % This is the common code, processing optional arguments, etc. for % \cs{tlabel}. It ultimately calls one of \cs{@tlabel} (no % \opt{mplabels}) or \cs{@@tlabel} (\opt{mplabels}). It takes an optional % argument describing the justification and rotation, followed by a % location in one of two syntaxes (which adds to the complication, but we % want to be backward compatible), followed by the text of the label % (\TeX{} code). % % The location can be in the form \parg{\meta{x},\meta{y}}, but if \MP{} % is processing labels we would like to be able to use \MP{} expressions, % which can contain parentheses and commas. This would mess up \TeX's % token matching for reading the two coordinates. Therefore we allow the % whole point to be enclosed in braces. Under \opt{mplabels} the contents % of the braces will be written to the output file without any further % parsing. Without \opt{mplabels}, there should be either no braces, or % inside the braces is the previously described syntax. % % We start with \cs{begingroup} to hide changes, then reset whitespace to % its normal catcodes. Without \opt{mplabels} we reset \cs{tlabel@rot} to % empty. Finally, we check for an optional parameter and run \cs{@tlabel@}, % feeding it an empty optional argument if there is none. % \begin{macrocode} \newdef\tlabel{% \begingroup % ended in \@(@@)tlabel \mfp@resetwhitespace \@ifmplabels{}{\def\tlabel@rot{}}% \null@opt\@tlabel@}% % \end{macrocode} % % We run \cs{tlabeljustify} on the optional parameter. This keeps the % default values of \cs{tl@vpos}, \cs{tl@hpos} and \cs{tlabel@rot} if % the parameter is empty, otherwise it modifies them inside the current % group. % % We then check for a left parenthesis and assume the % \parg{\meta{x},\meta{y}} syntax in that case, calling \cs{@@tlabel@} % to process it. Under \opt{mplabels} it stuffs the whole point into % braces and call the main code \cs{@@tlabel} with that argument, % otherwise it pulls out the two coordinates and feeds them as the first % two arguments of the main code \cs{@tlabel}. % \begin{macrocode} \newdef\@tlabel@[##1]{\tlabeljustify{##1}% \mfp@ifnextchar({\@@tlabel@}{\@@tlabel@@}}% \newdef\@@tlabel@(##1,##2){% \@ifmplabels {\@@tlabel{(##1,##2)}}{\@tlabel{##1}{##2}}}% % \end{macrocode} % % If no parenthesis, we assume braces surround the point. Under % \opt{mplabels} we call the main code (\cs{@@tlabel}) with that argument. % Otherwise, we re-call the above \cs{@@tlabel@} on the contents of the % braces, assuming (without checking) that the contents are coordinates in % parentheses. % \begin{macrocode} \newdef\@@tlabel@@##1{% \@ifmplabels {\@@tlabel{##1}}{\@@tlabel@##1}}% % \end{macrocode} % % \DescribeMacro{\extraendtlabel} % We now come to the main code under \opt{mplabels}, which should just % arrange to write the correct commands to the output file. All labels are % passed as \mfc{btex ... etex} structures. The definition of \cs{MFPtext} % will have been written earlier by \cs{opengraphsfile}. % \cs{extraendtlabel} is a hook currently only used by the \cs{tlabels} % command to force a loop. % \begin{macrocode} \newdef\mfp@btex##1{btex \noexpand\MFPtext{##1} etex}% \newdef\extraendtlabel{}% % \end{macrocode} % % The command \gbc{newgblabel}, defined in \file{graphbase.mp} for placing % labels, uses three parameters to justify the text. If we didn't have to % support the \texttt{B} vertical placement option, there would be only % two. All the other options involve placement \emph{relative} to the % bounding box. But the baseline is absolute: \MP{} always puts it at % y-coordinate 0 in the picture returned by \gbc{btex}. The first two % parameters are numerical and the third is boolean. The % first represents the fraction of the text that lies left of given % point. The second is the fraction of the text below the point. If the % third parameter is \mfc{true}, this fraction ignores the depth of the % text (so $0$ indicates baseline placement); if it is false, the depth % is accounted for (so $0$ indicates the very bottom of the text). % % By this point the letters of the optional parameter have been converted % to integer values for \cs{tl@hpos} and \cs{tl@vpos} by % \cs{tlabeljustify}. The following converts these integers to comma % separated parameters as described above using \cs{ifcase}. % % The fourth parameter of \gbc{newgblabel} is the angle of rotation. Empty % rotation is converted to the angle 0, otherwise it is written as is. % All four parameters are stored in \cs{mfp@MPpos}. % \begin{macrocode} \newdef\mfp@setMPpos{% \edef\mfp@MPpos{% \ifcase\tl@hpos .5\or 1\else 0\fi, % horizontal \ifcase\tl@vpos 0\or .5\or 1\else 0\fi, % vertical \ifnum \tl@vpos < 0 \mf@T\else\mf@F\fi, % true=Baseline \mfp@mtsub{\tlabel@rot}{0}}}% % \end{macrocode} % % \cs{@@tlabel} is the code called by \cs{tlabel} when \opt{mplabels} is % in effect. The argument is a \MP{} pair expression, or comma separated % list of them. It should be followed by the \TeX{} code for the label. % We will load the label into a token register afterwards. First % we restore the meaning of blank lines and then make sure any % \texttt{\#}'s in the \TeX{} code are not doubled by changing their % category. % % We load the label in a token register because writing that is (almost) % verbatim (blank lines become \cs{par}, \texttt{\#} symbols are % doubled if we're not careful, and control names have a space appended). % One day maybe we'll try to obtain a true verbatim writing mode. % \begin{macrocode} \newdef\@@tlabel##1{\def\mfp@points{##1}\mfp@restorepar \mfp@setMPpos \@makeother\#\mfp@gettoks\@@@tlabel}% % \end{macrocode} % Then the \gbc{newgblabel} command is written with the justification % parameters, and two more: the label tokens, and the point (or list of % points). The group (begun by \cs{tlabel}) is ended, and the % \cs{extraendtlabel} command invoked. % \begin{macrocode} \newdef\@@@tlabel{% \mfcmd{\@nl newgblabel(\mfp@MPpos)(\mfp@btex{\the\mfp@toks})(\mfp@points)}% \endgroup \extraendtlabel}% % \end{macrocode} % % When \opt{mplabels} is not in effect, we use \TeX{} to position the % label. By this point, the optional justification parameter to % \cs{tlabel} has been converted to integer values of \cs{tl@vpos} and % \cs{tl@hpos}, and the coordinates of the location are passed as the % first two arguments of \cs{@tlabel}. The third argument is the \TeX{} % code for the label. % % We put the label in a box (\cs{@textbox}) so we can measure and position % it. It is a \cs{vbox} so we can have multiline labels. This is effected % by wrapping it in a simple, left-aligned, one column \cs{halign}, % defining \cs{\bsl} to be \cs{cr}. We make this procedure a separate % macro, since we need to do the identical thing in the \cs{tlabelpath} % code. % \begin{macrocode} \newdef\set@textbox##1{% \setbox\@textbox=\vbox{\def\\{\cr}\mfp@restorepar \@tcurr\the\every@tlabel\halign{####\hfil\cr##1\crcr}}}% % \end{macrocode} % % We then compute its total height to simplify later code. % \begin{macrocode} \newdef\@tlabel##1##2##3{% \set@textbox{##3}% \mfp@scratch\tb@ht \advance\mfp@scratch\tb@dp \tb@totalht\mfp@scratch % \end{macrocode} % % The following computes whether the rightmost extent of the picture will % be increased by the addition of the label. We convert the x-coordinate % of the label's location to a distance from the left edge of the picture. % We then add to that the amount of the label extending to the right of % this location. Then we add or subtract the separation of the label % from its location. Finally, we simply add the horizontal adjustment % defined by the user with \cs{tlabeloffset}. The value of % \cs{@tlabelsright} is set equal to this if it was less. We could omit % this group: we never use \cs{@tlabelsright} except in debugging. % % The macro \cs{tb@wd} expands to \cs{wd}\cs{@textbox}. % \begin{macrocode} \mfp@scratch=##1\mfpicunit \@xconv\mfp@scratch \begingroup \ifcase\tl@hpos \advance\mfp@scratch 0.5\tb@wd % center \or \advance\mfp@scratch -\tlabel@sep % right \else \advance\mfp@scratch \tb@wd % left \advance\mfp@scratch \tlabel@sep \fi \advance\mfp@scratch \tlabel@hadj \ifdim \mfp@scratch>\@tlabelsright \@tlabelsright=\mfp@scratch \fi \endgroup % \end{macrocode} % % The following is the same as the previous calculations, but with respect % to the leftmost extension of picture and label. Here, however, we save % the calculated value in \cs{tb@moveright}, because it is exactly the % amount we'll need to \cs{kern} later to position the label. % \begin{macrocode} \begingroup \ifcase\tl@hpos \advance\mfp@scratch -0.5\tb@wd % center \or \advance\mfp@scratch -\tb@wd % right \advance\mfp@scratch -\tlabel@sep \else \advance\mfp@scratch \tlabel@sep % left \fi \advance\mfp@scratch \tlabel@hadj \tb@moveright=\mfp@scratch \ifdim \mfp@scratch<\@tlabelsleft \@tlabelsleft=\mfp@scratch \fi \endgroup % \end{macrocode} % % Now we base the calculations on the vertical extent of picture and % label. Otherwise the idea is the same, and we may increase % \cs{@graphtop}. The macro \cs{tb@ht} means \cs{ht}\cs{@textbox} and % \cs{tb@dp} means \cs{dp}\cs{@textbox}. Again we save the calculated % result (in \cs{tb@raise}) for later positioning of the label. % \begin{macrocode} \mfp@scratch=##2\mfpicunit \@yconv\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 \fi \advance\mfp@scratch \tlabel@vadj \tb@raise=\mfp@scratch \ifdim \mfp@scratch>\@tlabelstop \@tlabelstop=\mfp@scratch \fi \endgroup % \end{macrocode} % % Finally we compute the bottom-most extent. % \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 \fi \advance\mfp@scratch \tlabel@vadj \ifdim \mfp@scratch<\@tlabelsbot \@tlabelsbot=\mfp@scratch \fi \endgroup % \end{macrocode} % % Now we've computed the new size of \cs{@alltlabels} and we put the % new label on top of it with the above calculated kerns. % \begin{macrocode} \global \setbox\@alltlabels=% \vtop{\unvbox\@alltlabels \vbox to 0pt{\kern-\tb@raise \hbox{\kern\tb@moveright\box\@textbox}\vss}}% \endgroup % group begun in \tlabel \extraendtlabel}% End \@tlabel % \end{macrocode} % % \subsection{Surrounding the label with a path}\label{surrounding} % % These next macros place labels, but also define a path surrounding the % label This allows one to clear a space for the label, create a % background, draw a box around it, etc. They take two optional arguments. % The first optional argument depends on the type of path being created. % It is described below. The second one is the justification as in the % \cs{tlabel} command. There are two mandatory arguments, the location % (same syntax as for \cs{tlabel}) and the text. They also have % star-forms, which create the path but doesn't place the label. % % All the curves are sized to just contain what I will call the % \emph{label strip}. Imagine a rectangle that just fits around the text. % Now extend it on all sides by the value defined with \cs{tlabelsep}. % This rectangle is the label strip. % % \DescribeMacro{\tlabelrect} % \cs{tlabelrect} creates the rectangular boundaries of the label strip by % default. With the optional argument a rectangle with rounded corners is % produced; the optional argument is the radius of the quarter circles used. % These quarter circles pass through the corners of the label strip and are % joined together with straight lines to create the rest of the rectangle. % As a special case, the optional argument can contain the keyword % `\texttt{roundends}' to produce a rectangle with the short sides % replaced by a semicircle. % % \DescribeMacro{\tlabeloval} % \cs{tlabeloval} produces an ellipse which, by default has the same % aspect ratio as the label strip. It is sized to just include that label strip, % passing through its four corners. The optional argument contains a % numerical factor $m$ that, if greater than 1, increases the width and % decreases the height to maintain this relationship with the label strip, % while multiplying the width to height ratio by $m$. The default value of % $m$ is 1. % % \DescribeMacro{\tlabelellipse} % \cs{tlabelellipse} produces an ellipse, where the optional argument $a$ % is the ratio of its width to its height. The default for $a$ is 1, which % produces a circle. % % \DescribeMacro{\tlabelcircle} % To get a circle the user can \cs{tlabelellipse} without the optional % argument, or with argument \oarg{1}. However, it makes for a more % readable source if the command reflects the shape. \cs{tlabelcircle} is % defined to be essentially \cs{tlabelellipse}\oarg{1}, but it first % checks for the \texttt{*} and passes it along in front of the \oarg{1}. % % We implement the other three by calling \cs{tlpath} with the name of the % curve (\texttt{rect}, \texttt{oval}, or \texttt{ellipse}) and the % default value of the optional argument (\texttt{0}, \texttt{1}, and % \texttt{1}, respectively) as arguments. % \begin{macrocode} \newdef\tlabelrect{\tlpath{rect}{0}}% \newdef\tlabeloval{\tlpath{oval}{1}}% \newdef\tlabelellipse{\tlpath{ellipse}{1}}% \newdef\tlabelcircle{% \mfp@ifnextchar*{\@firstoftwo{\tlabelellipse*[1]}}% {\tlabelellipse[1]}}% % \end{macrocode} % % We store the name of the path in \cs{mfp@name} and the default argument % in \cs{mfp@param}, then check for a \texttt{*} and set a switch based % on it before calling \cs{@tlpath}. The \cs{@figmacstart} must be outside % the group so the switches it sets will survive for later commands to % detect. % \begin{macrocode} \newdef\tlpath##1##2{\@figmacstart \begingroup % ended in \tlabelpath@ \def\mfp@name{##1}\def\mfp@param{##2}% \mfp@ifnextchar*% {\@mfpswitchtrue\@firstoftwo{\@tlpath}}% gobbles the star {\@mfpswitchfalse\@tlpath}}% % \end{macrocode} % Process first optional argument. First one has value of \cs{mfp@param} % as default. The second one has a default justification set by the user % with \cs{tlpathjustify} or the initial \texttt{[cc]} setting. Once these % are processed, we check whether a parentheses follows, calling one of % two different handlers for the location parameter(s). % \begin{macrocode} \newdef\@tlpath{\null@opt\@@tlpath}% \newdef\@@tlpath[##1]{% \edef\mfp@param{\mfp@mtsub{##1}{\mfp@param}}% \mfp@resetwhitespace \simple@opt\@@@tlpath{\tlpath@v\tlpath@h\tlpath@r}}% \newdef\@@@tlpath##1{\tlabeljustify{##1}% \mfp@setMPpos \mfp@ifnextchar({\@tlabelpath}{\@@tlabelpath}}% % \end{macrocode} % % These handlers just stuff the point into a macro and call the command % that reads the label code. The name \cs{mfp@points} is plural (even % though only one point is supported) because the internal command that % places the label expects this macro. We use \cs{@firstofone} so % that the braces will not be written to the output, but they will % function as braces for \TeX's parameter matching. % \begin{macrocode} \newdef\@tlabelpath (##1,##2){% \def\mfp@points{(\@firstofone{##1},\@firstofone{##2})}% \@@@tlabelpath}% \newdef\@@tlabelpath##1{\def\mfp@points{##1}\@@@tlabelpath}% \newdef\@@@tlabelpath{\mfp@restorepar \@ifmplabels{\@makeother\#}{}\mfp@gettoks\tlabelpath@}% % \end{macrocode} % % Under \opt{mplabels} we just call on \MP{} to do everything (including % measuring the text). Otherwise we measure the text in \TeX{} and feed % the bounding box corners to \MF{} for making the path. Then we optionally % place the text based on the switch previously set. All the data needed % have already been stored in macros by previous commands in the chain. % \begin{macrocode} \newdef\tlabelpath@{% \@ifmplabels {\mfcmd{text\mfp@name x (\mfp@MPpos)\@nl(origin, % dummy parameter \mfp@btex{\the\mfp@toks}, \mfp@param, \mfp@points)}}% {\measure@textbox{\the\mfp@toks}% \mfcmd{text\mfp@name x (\mfp@MPpos)\@nl(\tb@ll, \tb@ur, % text bbox \mfp@param, \mfp@points)}}% \if@mfpswitch \endgroup % *-form, no label placed \else % tlabel commands contain \endgroup \@ifmplabels{\@@@tlabel}% {\@xp\@@tlabel@\mfp@points{\the\mfp@toks}}% \fi}% % \end{macrocode} % % Here we define the command that measures the text. It is almost a clone % of a similar code sequence in \cs{@tlabel}, but it produces the \gbc{ll} % and \gbc{ur} (corners of the boundingbox) that the \grafbase{} code % needs. % \begin{macrocode} \newdef\measure@textbox##1{% \set@textbox{##1}% \edef\tb@ll{(0, -(\the\tb@dp))}% \edef\tb@ur{(\the\tb@wd, \the\tb@ht)}}% % \end{macrocode} % % \subsection{Placing multiple text labels}\label{multiple} % % \DescribeMacro{\tlabels} % One of the more onerous things about labels in \env{mfpic} environments % was the shear number of them. The following was intended to reduce the % amount of typing by having to repeat only the arguments. \cs{tlabels} % takes only one argument: any sequence of valid arguments for a \cs{tlabel} % command, optionally separated by whitespace (but not blank lines). % % We begin a group, reset whitespace to normal, and call the command that % reads the argument. That command arranges to make the main code % self-looping by defining \cs{extraendtlabel} to call the beginning of the % loop, then it feeds its argument to \cs{do@tlabels} followed by a % delimiter to signal the end of the loop. % \begin{macrocode} \newdef\tlabels{% \begingroup % ended in \do@tlabels \mfp@resetwhitespace \@tlabels}% \newdef\@tlabels##1{\def\extraendtlabel{\do@tlabels}% \do@tlabels##1\mfp@delim}% % \end{macrocode} % % If \cs{do@tlabels} sees the end-of-loop delimiter it ends the group and % gobbles the delimiter. Otherwise it calls \cs{tlabel}, which sees the % next set of arguments, and repeats the loop. % \begin{macrocode} \newdef\do@tlabels{% \mfp@ifnextchar\mfp@delim{\@firstoftwo\endgroup}{\tlabel}}% % \end{macrocode} % % Labelling axes generates a lot of \cs{tlabel} commands or a single % \cs{tlabels} command with a lot of arguments. Given that such labels % have much in common (e.g., for the x-axis the y-coordinate and the % justification are usually the same for all the labels) we can do still % better at abbreviating this task. % % \DescribeMacro{\axislabels} % The \cs{axislabels} command takes a mandatory argument (the axis) % followed by an optional argument (the justification, as in the % \cs{tlabel} command), followed by another mandatory argument, a comma % separated list of items of the form % \marg{\meta{label}}\meta{coordinate}. The label is placed at that % coordinate on the given axis. This command is complicated by the fact % that the default justification should be different for each axis (for % example, for the y-axis it is \oarg{cr} but for the x-axis it is % \oarg{tc}). For all of them, one of the parts is \texttt{c}, so after % resetting whitespace we initialize them both to this and later change % only the one that needs it. % % Also, one of the coordinates of a label will be given by the argument, % while the other is the location of the axis. However, which coordinate % is which is different for different axes. What we do is feed the % argument to \cs{mfp@xcoord} and \cs{mfp@ycoord}. Both are initialized to % the identity macro, but one is changed to expand to just the axis % position. % % The axis position for x- and y-axis is 0. For border axes it is % calculated by adding the border axis shift to the border coordinate. % \begin{macrocode} \newdef\axislabels##1{% \begingroup % ended in \do@axislabel \mfp@resetwhitespace \tlabeljustify{cc}% \let\mfp@xcoord=\@firstofone \let\mfp@ycoord=\@firstofone \get@axisnum{##1}\axislabels \ifcase\mfp@axisnum \tl@vpos=2 % x-axis -->[tc] \def\mfp@ycoord{0}% \or \tl@hpos=1 % y-axis-->[cr] \def\mfp@xcoord{0} \or \tl@hpos=1 % left -->[cr] \edef\mfp@xcoord{\mfp@lshift}\mfpaddto\mfp@xcoord{#3}% \or \tl@vpos=2 % bottom-->[tc] \edef\mfp@ycoord{\mfp@bshift}\mfpaddto\mfp@ycoord{#5}% \or \tl@hpos=-1 % right -->[cl] \edef\mfp@xcoord{-\mfp@rshift}\mfpaddto\mfp@xcoord{#4}% \or \tl@vpos=0 % top -->[bc] \edef\mfp@ycoord{-\mfp@tshift}\mfpaddto\mfp@ycoord{#6}% \fi % \end{macrocode} % % Now one of \cs{mfp@xcoord} or \cs{mfp@ycoord} expands to the axis % position. We change it so that it does this while gobbling a parameter. % And then call \cs{@axislabels}, feeding it an empty argument as the % default optional argument. % \begin{macrocode} \ifx\@firstofone\mfp@xcoord \edef\mfp@ycoord####1{\mfp@ycoord}% \else \edef\mfp@xcoord####1{\mfp@xcoord}% \fi \null@opt\@axislabels}% % \end{macrocode} % % \cs{@axislabels} processes the contents of the optional parameter and % calls \cs{do@axislabel} on the list in the argument. An additional item % is added that signals the end of the loop. % \begin{macrocode} \newdef\@axislabels[##1]##2{% \tlabeljustify{##1}% \do@axislabel~ ##2,\mfp@delim}% % \end{macrocode} % % We add some code that traps the most common typos: a comma between the % label and the coordinate, or a missing coordinate, or a doubled comma. % It seems impossible to detect which of the first two has happened, and % assuming the first case produces really awful results if the second is % true. Therefore when a coordinate seems to be missing, we just lose the % text (as we have no place to put it) and resume the loop. If the first % case is true, the next iteration will see only the number, read one % digit or decimal as the text and the rest as the coordinate. The output % will be wrong, but at least \TeX{} can proceed. % % Above we prepended a `\verb*+~ +' so that if the coordinate is missing, % the braces around the argument won't be lost; the space will be % consumed in the argument processing of \cs{do@@axislabel}. % % The first argument should be the label, and everything from that to the % comma is the location. In the above error cases, the second argument % is empty % \begin{macrocode} \newdef\do@axislabel~##1,{% \@ifmtarg{##1}{\x@axislabel}{\do@@axislabel##1\@nil}}% \newdef\do@@axislabel##1##2\@nil{% \@ifmtarg{##2}% {\Mfpic@warn{Possible extra comma, missing coordinate, or missing\@msgbreak braces in \string\axislabels\@online. Skipping this label.}}% {\tlabel(\mfp@xcoord{##2},\mfp@ycoord{##2}){##1}}% \x@axislabel}% \newdef\x@axislabel{% check for end of list \mfp@ifnextchar\mfp@delim{\@firstoftwo\endgroup}{\do@axislabel~ }}% % \end{macrocode} % % \subsection{Captions}\label{captions} % % Captions are not added immediately by the \cs{tcaption} command. That % command redefines \cs{@docaption} to add it, and \cs{endmfpic} executes % \cs{@docaption}. For now, \cs{@docaption} does nothing. % \begin{macrocode} \newdef\@docaption{}% % \end{macrocode} % % \DescribeMacro{\tcaption} % \cs{tcaption} takes an optional argument that holds two numbers, % separated by a comma. The first number determines the maximum width of a % one line caption. Captions larger than that multiple of the width of the % graphic will be reset as a paragraph, whose lines have length the second % number times the width of the graph. The defaults are \oarg{1.2,1}. % % \cs{@tcaption} has one mandatory argument, the caption's text. In it, the % \cs{\bsl} command forces line breaks. This works by forcing the width to % be greater than any reasonable setting of the maximum line width. When % this happens, the caption is reset in a \cs{vbox} and \cs{\bsl} is % redefined like a normal line break. % \begin{macrocode} \newdef\tcaption{\simple@opt\tcaption@{1.2, 1.0}}% \newdef\tcaption@##1{\@tcaption##1\mfp@delim}% \long\def\@tcaption##1,##2\mfp@delim##3{% \def\@docaption{% \setbox\@textbox=% \hbox{\def\\{\hskip\@M\p@}\mfp@restorepar \@tcurr##3}% % \end{macrocode} % % If the above \cs{hbox} is too wide, we re-assign \cs{@textbox} to a % \cs{vbox} with \cs{hsize} determined by the second part of the optional % argument, and with \cs{leftskip} and \cs{rightskip} defined according % to the setting of \opt{centeredcaptions}. % \begin{macrocode} \@graphwd=\wd\@wholegraph \ifdim\tb@wd>##1\@graphwd \setbox\@textbox=% \hbox{% \vbox{% \if@mfp@latex % keep LaTeX's `\\' \else \def\\{\unskip\hbox{}\hfil\penalty-\@M\ignorespaces}% \fi \if@mfp@centcapt \leftskip=0pt plus 0.5fil \rightskip=0pt plus -0.5fil \parfillskip=0pt plus 1fil \else \leftskip=0pt \rightskip=0pt \fi \hsize=##2\@graphwd \mfp@restorepar \noindent\@tcurr ##3% }% End vbox. }% End hbox. \fi % \end{macrocode} % % Here we determine the wider of the graph or the caption, then put the % graph and caption together by centering them in \cs{hbox}es with this % width, stacked one atop the other with \cs{mfpiccaptionskip} (default: % \cs{medskipamount}) in between. % \begin{macrocode} \mfp@scratch=\wd\@wholegraph \ifdim \mfp@scratch<\tb@wd \mfp@scratch=\tb@wd \fi \global\setbox\@wholegraph=% \vbox{\hbox to \mfp@scratch{\hss\box\@wholegraph\hss}% \nointerlineskip \vskip\mfpiccaptionskip \hbox to \mfp@scratch{\hss\box\@textbox\hss}}% End vbox. }% End \@docaption. % \ignorespaces }% End \@tcaption. % \ignorespaces }% End of \@mfpic % \end{macrocode} % % % \section{Placing the picture: \cs{endmfpic}}\label{endmfpic} % % By the time \cs{endmfpic} is reached, the \MF{} code for the figure has % all been written to the output file. The labels have all been % accumulated and arrangements have been made to add the caption. % % \DescribeMacro{\endmfpic} % Under \opt{metapost}, write \cs{endgroup} to match beginning written % by \cs{mfpic} Then write the \cs{grafbase} command \gbc{endmfpic}, % followed by a comment telling which figure number it is, and the line % number in the \TeX{} source where the \cs{endmfpic} occurred. % \begin{macrocode} \mfp@DBlog{Definition of closure of mfpic environment.}% \newdef\endmfpic{% \mfsrc{\mfp@ifmpost{\@nl verbatimtex \endgroup\space etex;}{}\@nl endmfpic;\mf@p (\number\mfp@count) \space\@mfplineno.\@nl \mf@p\mf@d\mf@d\mf@d\@nl}% \ifmfpicdebug\wlog{}\wlog{Mfpic: ENTERED endmfpic.}\wlog{}\fi % \end{macrocode} % The code to load and place the box is skipped if figure shipping was % turned off. % \begin{macrocode} \if@shipping % % \end{macrocode} % % \subsection{Loading and measuring the graphic}\label{loading} % % Now we load the graphic. It would be at this point that we could add a % \cs{write18} to process the figure on-the-fly. Of course that would % require re-initializing the output file with each graphic (i.e., the % equivalent of issuing \cs{opengraphsfile} at every \cs{mfpic} and % \cs{closegraphsfile} at every \cs{endmfpic}.) % \begin{macrocode} \global\setbox\@wholegraph=% \vbox{% % \end{macrocode} % % If draft mode has been detected or set by the user, we just make a box % of the size specified with the figure number inside it. % \begin{macrocode} \ifmfpicdraft \vbox to \@graphtop{\vss \hbox to \@graphwd{\kern2pt\tt\#\number\mfp@count\hss}% \kern2pt}% \else % \end{macrocode} % % The \opt{truebbox} option works at the \MP{} level. Without it the % height of the EPS bounding box will actually be the calculated value % of \cs{@graphtop} (but increased by up to \texttt{2bp} due to rounding). % With it, the box will be its natural height. In either case, the actual % height is what we use in the \MP{} case. For \MF{} we use the nominal % height calculated in \cs{mfpic}. % \begin{macrocode} \mfp@ifmpost{\vbox}{\vbox to \@graphtop}% {\vss % \end{macrocode} % % \cs{@graphfilename} holds the name of the \MP{} output figure. (It will be % ignored by the \opt{metafont} option.) We test if the file exists before % doing the graphic inclusion because of the large number of confusing error % messages many graphic inclusion packages generate otherwise. When absent % we substitute the figure number for \cs{@setmfpicgraphic}. When present, % and if in \LaTeXe, we arrange for the current numerical extension to be % accepted as an EPS or MPS file by the \cs{includegraphics} command of the % graphics package. % \begin{macrocode} \edef\@graphfilename{\setfilename{\mfp@filename}% {\number\mfp@count}}% \mfp@ifmpost {\openin\mfp@graph=\@graphfilename\relax \ifeof\mfp@graph \Mfpic@msg{No graph file: \@graphfilename\space.}% \def\@setmfpicgraphic##1{\raise2pt\hbox{\kern2pt\tt ##1}}% \closein\mfp@graph \else\if@mfp@latexe \@namedef{Gin@rule@.\number\mfp@count}##1{% {\mfp@Gtype}{.\number\mfp@count}{##1}}% \fi\fi}{}% % \end{macrocode} % % We put the graphic in an \cs{hbox} of the required width and close off % the boxes. % \begin{macrocode} \mfp@ifmpost{\hbox}{\hbox to \@graphwd}% {\@xp\@setmfpicgraphic\@xp{\@graphfilename}\hss}% End hbox. \kern0pt }% End vbox \fi }%% End vbox (\setbox\@wholegraph) % \end{macrocode} % % We change the horizontal and vertical dimensions under \opt{metapost} in % case \opt{truebbox} was in effect, but also because they are almost always % rounded up to whole numbers of \texttt{bp} and therefore, even without % \opt{truebbox} the calculated values needn't be correct. % \begin{macrocode} \mfp@ifmpost {\@graphright=\wd\@wholegraph \@graphtop=\ht\@wholegraph \@graphwd=\@graphright}{}% \ifmfpicdebug \wlog{Mfpic: graphleft = \the\@graphleft}% \wlog{Mfpic: graphright = \the\@graphright}% \wlog{Mfpic: graphtop = \the\@graphtop}% \wlog{Mfpic: graphbot = \the\@graphbot}% \wlog{Mfpic: graphwd = \the\wd\@wholegraph}% \wlog{Mfpic: graphht = \the\ht\@wholegraph}% \wlog{Mfpic: graphdp = \the\dp\@wholegraph}% \wlog{}% \fi % \end{macrocode} % % \subsection{Adding labels and caption}\label{addlabel} % % We now add the box \cs{@alltlabels} onto the graph box. The box should % still have 0pt height and depth, so we can just stick it under the graph % box. But first we have to adjust for \cs{mfpicllx} and \cs{mfpiclly} % which can only be known after the graphics inclusion. We reset the box % \cs{@alltlabels} so its contents are shifted by these values. We only % need to do this if labels have have actually been added. The signal that % this has happened is that the label dimensions are no longer % $\pm$\cs{maxdimen}. % \begin{macrocode} \ifmfpicdebug \wlog{Mfpic: tlabelsleft = \the\@tlabelsleft}% \wlog{Mfpic: tlabelsright = \the\@tlabelsright}% \wlog{Mfpic: tlabelstop = \the\@tlabelstop}% \wlog{Mfpic: tlabelsbot = \the\@tlabelsbot}% \wlog{}% \fi \ifdim\@tlabelsleft < \maxdimen \setbox\@alltlabels\vtop to 0pt{% \kern \mfpiclly bp \moveleft \mfpicllx bp \box\@alltlabels \vss}% % \end{macrocode} % Then we adjust \cs{@tlabelsleft}, etc. for the boundingbox offset. % \begin{macrocode} \mfp@scratch\@tlabelsleft \advance\mfp@scratch-\mfpicllx bp \ifdim\mfp@scratch<\@graphleft \@graphleft\mfp@scratch \fi \mfp@scratch\@tlabelsright \advance\mfp@scratch-\mfpicllx bp \ifdim\mfp@scratch>\@graphright \@graphright\mfp@scratch \fi \mfp@scratch\@tlabelstop \advance\mfp@scratch-\mfpiclly bp \ifdim\mfp@scratch>\@graphtop \@graphtop\mfp@scratch \fi \mfp@scratch\@tlabelsbot \advance\mfp@scratch-\mfpiclly bp \ifdim\mfp@scratch<\@graphbot \@graphbot\mfp@scratch \fi \setbox\@wholegraph=\vtop{% \unvbox\@wholegraph\box\@alltlabels}% \fi % \end{macrocode} % % The method for putting labels in \cs{@alltlabels} does not add any width % on the left, nor any height to the top or depth to the bottom of that box % (that \TeX{} can detect), but we have saved their values and now we can % use them. For example, if \cs{@graphleft} is negative after the above, % then a label sticks out to the left, but \TeX{} thinks it has no width. % Therefore put \cs{kern}\texttt{-}\cs{@graphleft} to move the graph % rightward. The height and depth are taken care of by putting it in % \cs{vbox} with the calculated total height and moving the graph upward % with \cs{kern}\texttt{-}\cs{@graphbot}. The rightward extensions do get % detected by \TeX. % \begin{macrocode} \ifmfpicdebug \wlog{Mfpic: tlabelsleft = \the\@tlabelsleft}% \wlog{Mfpic: tlabelsright = \the\@tlabelsright}% \wlog{Mfpic: tlabelstop = \the\@tlabelstop}% \wlog{Mfpic: tlabelsbot = \the\@tlabelsbot}% \wlog{}% \fi \mfp@scratch=\@graphtop \advance\mfp@scratch by -\@graphbot \global \setbox\@wholegraph=% \vbox to \mfp@scratch{\vss \hbox{\kern-\@graphleft\box\@wholegraph}% \kern-\@graphbot}% End vbox. % \end{macrocode} % % Now add the caption, then set the parameters \cs{mfpicheight} and % \cs{mfpicwidth} for user to examine. The debug info now should show % graphwd${}={}$graphright${}-{}$graphleft, % graphht${}={}$graphtop${}-{}$graphbot, and graphdp${}= 0$. % \begin{macrocode} \ifmfpicdebug \wlog{Mfpic: graphleft = \the\@graphleft}% \wlog{Mfpic: graphright = \the\@graphright}% \wlog{Mfpic: graphtop = \the\@graphtop}% \wlog{Mfpic: graphbot = \the\@graphbot}% \wlog{Mfpic: graphwd = \the\wd\@wholegraph}% \wlog{Mfpic: graphht = \the\ht\@wholegraph}% \wlog{Mfpic: graphdp = \the\dp\@wholegraph}% \wlog{}% \fi \@docaption \global\mfpicheight\ht\@wholegraph \global\mfpicwidth\wd\@wholegraph \ifmfpicdebug \wlog{Mfpic: graphleft = \the\@graphleft}% \wlog{Mfpic: graphright = \the\@graphright}% \wlog{Mfpic: graphtop = \the\@graphtop}% \wlog{Mfpic: graphbot = \the\@graphbot}% \wlog{Mfpic: graphwd = \the\wd\@wholegraph}% \wlog{Mfpic: graphht = \the\ht\@wholegraph}% \wlog{Mfpic: graphdp = \the\dp\@wholegraph}% \wlog{}% \fi % \end{macrocode} % % \subsection{Placing the graphic}\label{placing} % % Add a frame around the box \cs{@wholegraph} in draft mode (so its size % can be seen) since there is practically nothing in it except the picture % number % \begin{macrocode} \ifmfpicdraft \setbox\@wholegraph=% \hbox{\@mfpframed{-\mfpframethickness}{\box\@wholegraph}}% \fi % \end{macrocode} % % If the \cs{savepic} command occurred prior to this, then \cs{s@vemfpic} % is defined and we save this picture in the box named in that % \cs{savepic} command and stored in the macro \cs{s@vemfpic}. Otherwise, % \cs{s@vemfpic} is undefined, and we place the picture (\cs{@wholegraph}) % in the document. Afterward, we undefine \cs{s@vemfpic}. % \begin{macrocode} \mfp@ifdefined\s@vemfpic {\global\setbox\s@vemfpic=\box\@wholegraph}% {\leavevmode\box\@wholegraph}% \global\let\s@vemfpic\UndEfInEd % \end{macrocode} % % Now we advance the figure count, end the group started by the \cs{mfpic} % command, restore the values of extra font dimensions that were saved, % then arrange for spaces to be ignored in case the syntax % \cs{begin}\marg{mfpic}$\ldots$\cs{end}\marg{mfpic} was used. % \begin{macrocode} \global \advance\mfp@count1 \fi % end of \if@shipping \endgroup % Begun near start of \@mfpic \restore@mfpicdimens \if@mfp@latex \def\mfptmp@a{mfpic}% \ifx\mfptmp@a\@currenvir \@ignoretrue% so \endmfpic and \end{mfpic} have the same effect. \fi \fi \ignorespaces }% % \end{macrocode} % % % \section{Additional features}\label{additional} % % \subsection{Saving a copy of the picture}\label{saving} % % \DescribeMacro{\newsavepic} % One saves a picture by first allocating a save box with % \cs{newsavepic}\marg{\cs{mypic}}, then saying % \cs{savepic}\marg{\cs{mypic}} beforehand. The \cs{endmfpic} code % detects that this has been done and saves the picture in \cs{mypic}. % It can be placed with \cs{usepic}{\cs{mypic}}. % % \cs{newsavepic} is just a clone of \LaTeX's \cs{newsavebox}. The one % argument is a control sequence. % \begin{macrocode} \newdef\newsavepic#1{% \if@mfp@latex \newsavebox{#1}% \else \mfp@ifdefined{#1}% {\mfp@errmsg {Command \string #1 already defined.}% {You have used \newsavepic with an already defined or an^^J% improper control sequence. Replace #1 with another name.^^J% If you proceed, \newsavepic will be ignored.}}% {\csname newbox\endcsname#1}% \fi}% \newlet\newpic=\newsavepic % compatibility % \end{macrocode} % % \DescribeMacro{\savepic} % All \cs{savepic} really does is define \cs{s@vepic} to its argument, % which should be a control sequence defined by \cs{newsavepic} (or % \cs{newbox}). % \begin{macrocode} \newdef\savepic#1{\relax \mfp@ifdefined{#1}{\gdef\s@vemfpic{#1}}% {\mfp@errmsg{Box \string#1 undefined.}% {You tried to save a picture in a box which had not been^^J% previously allocated. Use \newsavepic to allocate a box.}}}% % \end{macrocode} % % \DescribeMacro{\usepic} % \cs{usepic} takes one argument, a control sequence that should have % been previously used in a \cs{savepic} comamnd. It just places the box % with the primitive \cs{copy} command. % \begin{macrocode} \newdef\usepic#1{\leavevmode \copy#1\relax}% % \end{macrocode} % % \subsection{Putting a frame around it}\label{frame} % % This is essentially code I wrote years ago to have a framing command % that had two properties not enjoyed by come example `\cs{boxit}' commands % for plain\TeX: It should have a baseline the same as the baseline of the % contents, and it should work as an environment, not by reading an % argument (so verbatim material could be included). % % \DescribeMacro{\mfpframed} % \DescribeMacro{\mfpframe} % \cs{mfpframed} takes an optional argument (the separation) and a % mandatory argument, the contents. \cs{mfpframe}$\ldots$\cs{endmfpframe} % is an environment and \cs{mfpframe} also takes the separation as an % optional argument. % % \DescribeMacro{\framed} % \cs{framed} is a common command (\ConTeXt{} has one, a few packages also % define it), therefore we only define it if it is not already defined. % \begin{macrocode} \newdef\mfpframed{\simple@opt\@mfpframed\mfpframesep}% \newdef\mfpframe{\simple@opt\@mfpframe\mfpframesep}% \newdef\@mfpframed#1#2{\@mfpframe{#1}#2\endmfpframe}% \newdef\@mfpframe#1{% \leavevmode\hbox\bgroup \mfpframesep#1\relax \vrule width\mfpframethickness \vtop\bgroup \vbox\bgroup \hrule height\mfpframethickness \kern\mfpframesep \hbox\bgroup \kern\mfpframesep \ignorespaces}% \newdef\endmfpframe{\unskip \kern\mfpframesep \egroup % end hbox \egroup % end vbox \kern\mfpframesep \hrule height\mfpframethickness \egroup % end vtop \vrule width\mfpframethickness \egroup}% end hbox \mfp@ifdefined\framed{}{\newlet\framed=\mfpframed}% % \end{macrocode} % % \subsection{Adding \mfc{verbatimtex} to the \file{.mp} % file}\label{verbatimtex} % % \DescribeMacro{mfpverbtex} % This is a user level utility for putting some \mfc{verbatimtex} material % in the output file for \MP. We allow the user to do this even before % \cs{opengraphsfile} by storing it in a token register and setting a flag % for that command to test. % \begin{macrocode} \newif\if@mfp@verbtex \def\mfpverbtex{% % \end{macrocode} % % We start a group, make sure lines will be preserved in writing the % material, make sure that \texttt{\#} characters will not be doubled by % changing its category, then continue after loading the code into the % token register \cs{mfp@verbtex}. % \begin{macrocode} \begingroup \preservelines \@makeother\#% \afterassignment\mfp@writetex\global\mfp@verbtex=}% % \end{macrocode} % % We end the group and then either set the switch to tell % \cs{opengraphsfile} that the material is ready, or we write it to the % output, between the commands \gbc{verbatimtex} and \cs{etex}. % \begin{macrocode} \def\mfp@writetex{% \endgroup \@ifmfpfileisopen {\mfp@ifmpost {\mfsrc{verbatimtex}\mfsrc{\the\mfp@verbtex}\mfcmd{etex}}% {\noMP@error{verbatimtex}}% \global\@mfp@verbtexfalse\mfp@verbtex{}}% {\global\@mfp@verbtextrue}}% % \end{macrocode} % % % \section{Finale}\label{finale} % % Set the default starting graphic number. % \begin{macrocode} \global\mfp@count=1 % 1 because we now advance it in \endmfpic. % \end{macrocode} % % Create a system for adding patches in the file \file{mfppatch.tex}, % and for user defaults in a file \file{mfpic.usr}. % \begin{macrocode} \newdef\MFPICinput#1{% \immediate\openin\mfp@graph=#1 \ifeof\mfp@graph \immediate\closein\mfp@graph \else \immediate\closein\mfp@graph \input #1 \fi}% \MFPICinput{mfppatch.tex}% % \end{macrocode} % % Restore the meaning of \cs{+}, and of the \cs{newlinechar}, and execute % the command that restores all the saved category codes. % \begin{macrocode} \mfp@DBlog{Punctuation, etc., will revert to old catcodes now.}% \let\+\mfpsaveplus \restorenewlinechar \MFPicpackagE% \MFPICinput{mfpic.usr}% % % \end{macrocode} % % Generate a (far too) simple wrapper for \LaTeX. % \begin{macrocode} %<*sty> \input mfpic.tex\relax % % \end{macrocode} %\clearpage %\Finale