diff options
author | Karl Berry <karl@freefriends.org> | 2009-10-03 14:58:41 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-10-03 14:58:41 +0000 |
commit | 556ccc6a2633ddbc27a22319d2e16e8a5d7483d1 (patch) | |
tree | 6f0b1301fabae1e14d1c00703e774efd67543d16 /Master/texmf-dist/source/generic | |
parent | 4d18074405a67946d5505fd5e0836e115d220541 (diff) |
mfpic 1.00 (30sep09)
git-svn-id: svn://tug.org/texlive/trunk@15602 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/generic')
-rw-r--r-- | Master/texmf-dist/source/generic/mfpic/grafbase.dtx | 910 | ||||
-rw-r--r-- | Master/texmf-dist/source/generic/mfpic/mfpic.dtx | 379 | ||||
-rw-r--r-- | Master/texmf-dist/source/generic/mfpic/mfpic.ins | 11 |
3 files changed, 996 insertions, 304 deletions
diff --git a/Master/texmf-dist/source/generic/mfpic/grafbase.dtx b/Master/texmf-dist/source/generic/mfpic/grafbase.dtx index fe734cbcc84..9d7c4bd010b 100644 --- a/Master/texmf-dist/source/generic/mfpic/grafbase.dtx +++ b/Master/texmf-dist/source/generic/mfpic/grafbase.dtx @@ -1,4 +1,7 @@ % \iffalse +%%% File: grafbase.dtx +%%% A part of mfpic 1.00 2009/09/22 +%%% % ------------------------------------------------------------------- % % Copyright 2002--2006, Daniel H. Luecking @@ -16,7 +19,7 @@ % %<*driver> \ProvidesFile{grafbase.dtx} - [2006/05/26 v0.9. Metafont/post macros to interface with mfpic.]% + [2009/09/22 v1.00. Metafont/post macros to interface with mfpic.]% \documentclass[draft]{ltxdoc} \usepackage{docmfp} @@ -110,7 +113,7 @@ %</driver> %\fi % -% \CheckSum{1369} +% \CheckSum{1465} % \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 @@ -137,12 +140,13 @@ % \file{.mp} file that, with the help of these macros and \MF{} (or \MP), % can be used to create pictures in the document, especially mathematical % pictures. There are two versions of \grafbase, one for \MF{} and one for -% \MP{}. As they are more alike than different (96\% of the code is +% \MP{}. As they are more alike than different (95\% of the code is % identical), we document both here. % % This file documents the \grafbase{} source code. The user manual for -% \mfpic{} is distributed as \file{mfpman.pdf} produced from -% \file{mfpman.tex}. +% \mfpic{} is distributed as \file{mfpic-doc.pdf}, produced from +% \file{mfpic-doc.tex}. An introductory guide to \mfpic{} is available +% in \file{mfpguide.pdf}, produced from \file{mfpguide.pdf} % \end{abstract} % % \StopEventually{\PrintIndex} @@ -181,7 +185,7 @@ fi boolean grafbase; grafbase := true; string fileversion, filedate; -fileversion := "0.9"; filedate := "2006/05/26"; +fileversion := "1.00"; filedate := "2009/09/22"; message " Loading grafbase macros, version " & fileversion & " " & filedate & "."; @@ -228,9 +232,10 @@ def checkversions (expr g)= fi enddef; -checkversions (90); +checkversions (100); % \end{macrocode} +% % We try to make sure that the macros of \file{plain.mf} or % \file{plain.mp} (where \mfc{base_name} is defined to be \mfc{"plain"}) % are available. @@ -250,7 +255,7 @@ fi % % Of course, \MP{} natively knows about colors but \MF{} doesn't, so we % use that to set a boolean \gbc{METAPOST}. We don't simply check if -% `\mfc{known blue}' is \mfc{true} because `\mfc{blue}' is certainly a legal +% `\mfc{blue}' is \mfc{known} because `\mfc{blue}' is certainly a legal % variable name in \MF. Instead we check `\mfc{known color X}' for % some unlikely \gbc{X}. In \MP, `\gbc{color X}' is either true or % false (\gbc{X} is a color or it isn't) and therefore always known, so @@ -260,28 +265,60 @@ fi % base name \mfc{color} and suffix \mfc{X}. % \begin{macrocode} boolean METAPOST; - -if known color Geamparalele din Babadag: - METAPOST := true; -else: - METAPOST := false; -fi +METAPOST := known color Geamparalele din Babadag; +numeric metapostversion; %<*MF> if METAPOST: GBerrmsg ("wrong compiler.") "This file is for Metafont. For Metapost use grafbase.mp."; fi +metapostversion := 0; %</MF> + %<*MP> if not METAPOST: GBerrmsg ("wrong compiler.") "This file is for Metapost. For Metafont use grafbase.mf."; fi -%</MP> % \end{macrocode} % +% \MP{} now exists in a couple of slightly incompatible versions. +% Versions 1.000 and later (beta versions 0.900 also) have native support for +% \texttt{CMYK} colors with a \mfc{cmykcolor} data type. It also +% supports grayscale colors (i.e., \mfc{withcolor} will accept a numeric +% expression), and has the alias \mfc{rgbcolor} for \mfc{color}. +% It also has a means to set the name of the output file: the +% \mfc{filenametemplate} command. In versions 1.2 and later, this is +% deprecated in favor of setting the internal string variable +% \mfc{outputtemplate}. +% \begin{macrocode} +numeric metapostversion; +boolean has_cmyk; +boolean has_filenametemplate; % e.g., filenametemplate "%j.%n; +boolean has_outputtemplate; % e.g., outputtemplate := "%j.%n; +if unknown mpversion: + % prior to introduction of cmykcolor and output filename templates. + % Latest such version was 0.641. + metapostversion := 0.641; + has_cmyk := false; + has_filenametemplate := false; + has_outputtemplate := false; +else: + metapostversion := scantokens (mpversion); + has_cmyk := true; + has_filenametemplate := true; + if metapostversion < 1.200: + has_outputtemplate := false; + else: + has_outputtemplate := true; + fi +fi + +%</MP> +% \end{macrocode} +% % \DescribeRoutine{GBdebug} % The \gbc{debug} flag is for developers, who should set it before % inputing \file{grafbase}. @@ -551,9 +588,12 @@ boolean showbbox; showbbox := false; % \begin{macrocode} %<*MF> let color = numeric; color black, white; +let rgbcolor = numeric; +let cmykcolor = numeric; black := 0; white := 1; def withcolor text t = enddef; %</MF> +%<MP>if not has_cmyk: let rgbcolor = color; let cmykcolor = color; fi def _wc_ = withcolor enddef; % \end{macrocode} @@ -580,110 +620,244 @@ background := white; % % \DescribeRoutine{snapto} % This truncates numerics to the $[0,1]$ range, but also returns a value -% ($0$) for unknown and non-numeric input. +% ($0$) for unknown input. It used to do the same for non-numeric input, +% but that should be an error. It would have made at least one of our +% bugs easier to find if it had produced an error message. % \begin{macrocode} vardef snapto expr t = - if unknown t: 0 - elseif not (numeric t): 0 - elseif t < 0: 0 - elseif t > 1: 1 - else: t + if numeric t: + if unknown t: 0 + elseif t < 0: 0 + elseif t > 1: 1 + else: t + fi + else: + GBerrmsg ("Improper expression type.") + "The argument to `snapto' must be a numeric."; fi + enddef; % \end{macrocode} % -% The \mfpic{} handling of \LaTeX-like color models relies on being able -% to convert those models to \MP's \opt{rgb} system. Because of the use of -% \gbc{snapto}, the following color functions will return \mfc{black} for -% unknown parameters. In the \MF{} case, they are all converted to -% numerics through \gbc{makeclr}. +% \DescribeRoutine{cmykgray} +% \DescribeRoutine{rgbgray} +% Now we deal with all the color functions and utilities that enable +% \mfpic{} users to use colors without knowing what they are doing. +% Since colors now come in three flavors, we start with gray levels in +% the three models. In early \MP{}, the \gbc{cmyk} function will return +% an \opt{rgb} color, so there is will be no difference between these +% two. In \MF{} \gbc{white} is a numeric and \gbc{cmyk} returns a +% numeric, so these can be used with \MF{}, and both produce the same +% result. % -% \DescribeRoutine{gray} -% The simplest is \gbc{gray} which converts a numeric to a multiple of -% white. In \MF, \gbc{white} is a numeric and equal to $1$ so this is -% almost redundant except for handling unknowns and out of range values. +% \DescribeRoutine{grayscalegray} +% The grayscale version should return a numeric in recent \MP{}, so +% it needs a different definition for early \MP{}. Thus, it occurs +% in the conditional code. Oddly, its definition is the same for \MF{} +% and recent \MP{}. +% \begin{macrocode} +vardef rgbgray (expr g) = (snapto g) * white enddef; +vardef cmykgray (expr g) = cmyk(0,0,0,1 - snapto g) enddef; + +% \end{macrocode} % -% \DescribeRoutine{makeclr} -% This is defined to convert a triple of numerics to a color, mainly for -% \MF. The formula has three desirable properties: it weights the -% different color coordinates approximately like some color luminescence -% models do, it assigns different graylevels to the eight colors that have -% components 0 or 1 only, and it is biased toward lighter grays. Of course -% it takes \mfc{black} to 0 and \mfc{white} to 1. In \MP, it simply turns -% three numeric parameters to a color triple in the obvious way. It does -% \emph{not} truncate the parameters, so if that is necessary, use -% \gbc{rgb}. +% In recent \MP{}, all the color functions are essentially no-ops. In +% early \MP{}, they all return an \opt{rgb} color expression. In \MF{} +% they all return a numeric. It is easiest if we simply separate the three +% cases and write the code for each, rather than load all the functions +% with three-way booleans (often containing nested booleans). % -% \DescribeRoutine{rgb} -% To simplify \mfpic, we have the nearly redundant \gbc{rgb} which -% converts a triple of numeric arguments to \opt{rgb}. Rather than make -% it formally the identity function under \MP, we define it to handle -% unknowns, and truncate out of range values. +% For all three engines we require a deginition of the color functions +% \gbc{gray(g)}, \gbc{rgb(r,g,b)}, and \gbc{cmyk(c,m,y,k)}, conversion +% functions \gbc{makegray(x)}, \gbc{makergb(x)}, amd \gbc{makecmyk(x)}, +% and the boolean \gbc{iscolor clr}. The first three have to return +% numerics for \MF{}, colors for early \MP{}, and the associated color +% type for recent \MP{}. % \begin{macrocode} -vardef gray (expr g) = (snapto g)*white enddef; - -vardef makeclr (expr r, g, b) = -%<MF> gray (sqrt((2r*r + 4g*g + b*b)/7)) -%<MP> (r, g, b) -enddef; +%<*MP> +if has_cmyk : + vardef grayscalegray (expr g) = snapto g enddef; + vardef gray (expr g) = grayscalegray (g) enddef; + vardef cmyk (expr c, m, y, k) = + (snapto c, snapto m, snapto y, snapto k) + enddef; -vardef rgb (expr r, g, b) = - makeclr (snapto r, snapto g, snapto b) -enddef; +% \end{macrocode} +% +% \DescribeRoutine{colorchoice} +% The \gbc{colorchoice} function (like \cs{mathchoice} in \TeX{}, after +% which it was named) returns one of four bits of code: \gbc{D} (default) +% if the first argument is unknown or not one of the recognized color +% models, \gbc{N} if it is numeric, \gbc{R} if it is \mfc{rgbcolor}, and +% \gbc{C} if it is \mfc{cmykcolor}. These arguments have to be \mfc{text}: +% if they were `\mfc{expr}' \MP{} would try to evaluate them, with +% possible errors since some of them apply functions that are not relevant +% to the other types. +% \begin{macrocode} + def colorchoice (expr clr) (text D)(text N)(text R)(text C) = + if unknown clr: D + elseif numeric clr: N + elseif rgbcolor clr: R + elseif cmykcolor clr: C + else: D + fi + enddef; % \end{macrocode} % -% \DescribeRoutine{cmyk} -% This algorithm for converting \opt{cmyk} values to \opt{rgb} values is -% the one used in the PostScript header file \file{color.pro} (distributed -% with \prog{dvips}). +% \DescribeRoutine{makecmyk}\DescribeRoutine{makergb}\DescribeRoutine{makegray} +% In \gbc{makecmyk} and all the other `\gbc{make}' conversions, the +% default is to return black in the appropriate model, numerics produce +% gray, and cmyk or rgb is either retained unchanged or converted to the +% appropriate model. +% +% \DescribeRoutine{iscolor} +% A variable is taken to be a color if it can validly follow +% \mfc{withcolor}. This includes boolean, though we hope no one tries to +% use it. % \begin{macrocode} -vardef cmyk (expr c, m, y, k) = - rgb (1-c-k, 1-m-k, 1-y-k) -enddef; + vardef makecmyk primary clr = + colorchoice (clr)(cmykblack)(cmykgray(clr)) + (rgbtocmyk(redpart clr,greenpart clr,bluepart clr)) + (clr) + enddef; + vardef makergb primary clr = + colorchoice (clr)(rgbblack)(rgbgray(clr))(clr) + (cmyktorgb(cyanpart clr, magentapart clr, yellowpart clr, blackpart clr)) + enddef; + vardef makegray primary clr = + colorchoice (clr)(grayscaleblack)(grayscalegray(clr)) + (rgbtogray (redpart clr, greenpart clr, bluepart clr)) + (cmyktogray(cyanpart clr, magentapart clr, yellowpart clr, + blackpart clr)) + enddef; + vardef iscolor expr clr = + (rgbcolor clr) or (cmykcolor clr) or (numeric clr) or (boolean clr) + enddef; +else: +% \end{macrocode} +% +% \DescribeRoutine{colorchoice} +% In early \MP{} \gbc{colorchoice} is a three-way choice, since +% \mfc{cmykcolor} is not an available data type, but numeric can still be +% interpreted as a gray. +% \DescribeRoutine{makecmyk} +% \DescribeRoutine{makergb} +% \DescribeRoutine{makegray} +% The \gbc{make*} functions are simpler in early \MP{}, though not as +% simple as in \MF{}. Ditto +% \DescribeRoutine{iscolor} +% \gbc{iscolor}. +% \begin{macrocode} + vardef gray (expr g) = rgbgray(g) enddef; + vardef grayscalegray (expr g) = rgbgray(g) enddef; + vardef cmyk (expr c, m, y, k) = rgb (1-c-k, 1-m-k, 1-y-k) enddef; + def colorchoice (expr clr) (text D)(text N)(text R) = + if unknown clr: D + elseif numeric clr: N + elseif rgbcolor clr: R + else: D + fi + enddef; + vardef makergb primary clr = + colorchoice (clr)(rgbblack)(rgbgray(clr))(clr) + enddef; + vardef makegray primary clr = + colorchoice (clr)(rgbblack)(rgbgray(clr)) + (rgbtogray (redpart clr, greenpart clr, bluepart clr)) + enddef; + def makecmyk = makergb enddef; + vardef iscolor expr clr = color clr enddef; +fi +%</MP> % \end{macrocode} % -% \DescribeRoutine{RGB} -% This merely rescales numbers in the range 0--255 to the range 0--1. +% \DescribeMacro{knowncolor} +% Once we have \gbc{iscolor} all we need to do is add a test for +% \mfc{known} to get this boolean test. +% \begin{macrocode} +vardef knowncolor expr clr = (known clr) and (iscolor clr) enddef; + +% \end{macrocode} % -% \DescribeRoutine{named} -% These last two, like \gbc{rgb}, are nearly redundant, but they convert -% numerics to gray, and convert other non-color variables and unknown -% color variables to black. -% \DescribeRoutine{forceclr} -% The difference between \gbc{named} and \gbc{forceclr} is that the -% former requires a suffix parameter (that is, a \emph{name}), while the -% latter takes an expression. It may be that the latter will never be -% needed, but for a time it seemed there were cases where we ought to use -% it to force an expression to be a color. +% These are the \MF{} versions. Everything pretty much returns its +% numeric argument or $0$ (black). % \begin{macrocode} -vardef RGB (expr R, G, B) = - rgb (R/255, G/255, B/255) +%<*MF> +vardef grayscalegray (expr g) = snapto g enddef; +vardef gray (expr g) = grayscalegray (g) enddef; +vardef cmyk (expr c, m, y, k) = rgb (1-c-k, 1-m-k, 1-y-k) enddef; +vardef makegray primary clr = + if knowncolor clr: clr else: black fi enddef; +def makergb = makegray enddef; +def makecmyk = makegray enddef; +vardef iscolor expr clr = color clr enddef; -vardef named (suffix c) = - if unknown c: black else: forceclr (c) fi -enddef; +%</MF> +% \end{macrocode} +% +% \DescribeRoutine{forcecolor} +% \DescribeRoutine{named} +% This is only used in the \gbc{named} function to force a color. In +% \MF{} the tests are all `\mfc{if numeric}'. In early \MP{} `\mfc{if +% cmykcolor}' is the same as `\mfc{if rgbcolor}'. +% \begin{macrocode} vardef forceclr (expr c) = - if numeric c: gray (c) - elseif color c: c - else: black + if unknown c : + if numeric c: grayscaleblack + elseif rgbcolor c: rgbblack + elseif cmykcolor c: cmykblack + else: black + fi + elseif numeric c: gray (c) + elseif iscolor c: c + else: black fi enddef; +vardef named (suffix c) = forceclr (c) enddef; % \end{macrocode} -% And then the standard colors. Using \gbc{rgb} ensures they are defined -% in \MF{} as well as \MP. +% +% \DescribeRoutine{togray} +% \DescribeRoutine{rgbtogray} +% \DescribeRoutine{cmyktogray} +% \DescribeRoutine{cmyktorgb} +% \DescribeRoutine{rgbtocmyk} +% These are used for the conversions. Strictly speaking they do not +% `convert' as they all take multiple numeric arguments rather than any +% sort of color. As \mfc{rgbcolor} exists in both early and recent +% \MP{} as the same data type, we need only distinguish \MF{} from \MP{} +% \DescribeRoutine{rgb} +% in the function \gbc{rgb}, % \begin{macrocode} -color red, green, blue, cyan, magenta, yellow; -red := rgb (1, 0, 0); -green := rgb (0, 1, 0); -blue := rgb (0, 0, 1); -cyan := rgb (0, 1, 1); -magenta := rgb (1, 0, 1); -yellow := rgb (1, 1, 0); +vardef togray (expr r, g, b) = + gray (sqrt((2r*r + 4g*g + b*b)/7)) +enddef; + +vardef rgbtogray (expr r, g, b) = + togray(snapto r, snapto g, snapto b) +enddef; +vardef cmyktogray (expr c, m, y, k) = + rgbtogray (1-c-k,1-m-k,1-y-k) +enddef; + +vardef cmyktorgb (expr c,m,y,k) = + rgb(1-c-k,1-m-k,1-y-k) +enddef; +vardef rgbtocmyk (expr r,g,b) = + cmyk(1-r,1-g,1-b,0) +enddef; + +vardef rgb (expr r, g, b) = +%<MF> togray (snapto r, snapto g, snapto b) +%<MP> (snapto r, snapto g, snapto b) +enddef; +vardef RGB (expr R, G, B) = + rgb (R/255, G/255, B/255) +enddef; % \end{macrocode} % @@ -717,7 +891,7 @@ yellow := rgb (1, 1, 0); def list (suffix v) (text lst) = v := 0; for _itm = lst: v[incr v] := _itm; endfor if v = 0: - GBerrmsg ("no list to process!") + GBerrmsg ("No list to process!") "An attempt was made to produce an array from a " & "list of expressions having no valid entries."; fi @@ -732,6 +906,7 @@ def map (text proc) (text lst) = enddef; % \end{macrocode} +% % \DescribeRoutine{knownnumericarray} % Checks if a suffix is the name of an array. Requires \gbc{arr} to be a % known positive integer, and all the variables \gbc{arr[n]} to be known @@ -898,7 +1073,7 @@ enddef; % \end{macrocode} % % \DescribeRoutine{xprod} -% A binary operation between pairs $z\sb1$ and $x\sb2$ that returns the +% A binary operation between pairs $z\sb1$ and $z\sb2$ that returns the % cross product $x\sb1 y\sb2 - x\sb2 y\sb1$. This gives, among other % things, twice the area of the triangle with two sides $z\sb1$ and % $z\sb2$. It is used only in \gbc{mkconvex}. @@ -1078,25 +1253,36 @@ enddef; % This is are mainly to save space in \mfpic-generated files. In \grafbase{} % itself the \mfc{save} is often inconvenient, but it turns out there are % many cases where it \emph{is} used; enough so that we have abbreviations +% \RoutineIndex{setnumeric}\gbc{setnumeric}, +% \RoutineIndex{setboolean}\gbc{setboolean}, +% \RoutineIndex{setpair}\gbc{setpair}, +% \RoutineIndex{setpath}\gbc{setpath}, % \RoutineIndex{setpicture}\gbc{setpicture}, -% \RoutineIndex{setpath}\gbc{setpath}, \RoutineIndex{setpair}\gbc{setpair} -% and \RoutineIndex{setboolean}\gbc{setboolean}, together with the +% and \RoutineIndex{setstring}\gbc{setstring}, together with the % common uses \RoutineIndex{newpicture}\gbc{newpicture} and -% \RoutineIndex{convertpath}\gbc{convertpath}. -% \DescribeRoutine{gsetvariable}\gbc{gsetvariable} is the global -% version. It has no abbreviations, but it is occasionally needed for -% \mfpic{}. The only difference is the lack of a \gbc{save}. None of these -% commands take the value as a parameter. That should follow, and is picked -% up by the ending \mfc{:=}. +% \RoutineIndex{convertpath}\gbc{convertpath}. There is also a +% \gbc{setcolor}, but that has such a different definition that we reserve +% it for later. +% +% For completeness, we also include the remaining two abbreviations, +% \RoutineIndex{setpen}\gbc{setpen} and +% \RoutineIndex{settransform}\gbc{settransform}, even though they are not +% used anywhere in \grafbase{}. +% +% \DescribeRoutine{gsetvariable}\gbc{gsetvariable} is the global version. +% It has no abbreviations, but it is occasionally needed for \mfpic{}. The +% only difference between it and the local version is the lack of a +% \gbc{save}. None of these commands take the value as a parameter. That +% should follow, and is picked up by the ending \mfc{:=}. % % \DescribeRoutine{setarray} % Then \gbc{setarray} is the array version. It takes the same parameters % as \gbc{setvariable}, but what should follow is a list of expressions in % parentheses. It calls \gbc{list} to read each item into -% \gbc{name1}, \gbc{name2}, etc. -% \DescribeRoutine{setpairs}\gbc{setpairs} is an abbreviation for arrays -% of pairs. There is also has a global version +% \gbc{name1}, \gbc{name2}, etc. There is also has a global version % \DescribeRoutine{gsetarray}\gbc{gsetarray}. +% \DescribeRoutine{setpairs}\gbc{setpairs} is an abbreviation for arrays +% of pairs. Historically, it came first. % \begin{macrocode} def setvariable (text kind) (suffix name) = save name; kind name; name := @@ -1108,8 +1294,10 @@ def setnumeric (suffix name) = save name; name := enddef; def setboolean = setvariable (boolean) enddef; def setpair = setvariable (pair) enddef; def setpath = setvariable (path) enddef; -def setcolor = setvariable (color) enddef; def setpicture = setvariable (picture) enddef; +def setstring = setvariable (string) enddef; +def settransform = setvariable (transform) enddef; +def setpen = setvariable (pen) enddef; def settension (suffix tn) expr tens = setnumeric (tn) if tens > 0: tens else: default_tension fi; enddef; @@ -1127,7 +1315,6 @@ def gsetarray (text kind) (suffix name) = enddef; % \end{macrocode} -% % The next are slightly different, but seem to belong here. % \DescribeRoutine{setbbox} @@ -1148,6 +1335,111 @@ def setsplit (suffix s) expr ss = setnumeric (s) emax (1, ceiling ss); enddef; +%<*MP> +if has_cmyk: + def setrgbcolor = setvariable (rgbcolor) enddef; + def setcmykcolor = setvariable (cmykcolor) enddef; + def setcolor (suffix name) expr val = + if boolean val : setboolean + elseif numeric val : setnumeric + elseif rgbcolor val : setrgbcolor + elseif cmykcolor val : setcmykcolor + % this should give a suitable error message: + else: setvariable (color) + fi (name) val; + enddef; + def gsetcolor (suffix name) expr val = + if boolean val : boolean name; + elseif numeric val : numeric name; + elseif rgbcolor val : rgbcolor name; + elseif cmykcolor val : cmykcolor name; + else: color name; + fi name := val; + enddef; +else: + def setrgbcolor = setcolor enddef; + def setcmykcolor = setcolor enddef; + def setcolor = setvariable (color) enddef; + def gsetcolor = gsetvariable (color) enddef; +fi +%</MP> +%<*MF> +def setrgbcolor = setcolor enddef; +def setcmykcolor = setcolor enddef; +def setcolor = setvariable (color) enddef; +def gsetcolor = gsetvariable (color) enddef; +%</MF> + +% \end{macrocode} +% +% And then the standard colors. Using the color functions ensures that +% they are defined in \MF{} as well as all versions of \MP{}. In early +% \MP{} they are all \mfc{rgbcolor}, in \MF{} they are all numeric. In +% recent \MP{}, they have the type correspondimg to the name of the +% color function, with \gbc{gray()} being numeric. +% \begin{macrocode} +setcolor(rgbblack) rgb(0,0,0); +setcolor(red) rgb(1,0,0); +setcolor(green) rgb(0,1,0); +setcolor(blue) rgb(0,0,1); +setcolor(rgbwhite) rgb(1,1,1); +setcolor(cmykwhite) cmyk(0,0,0,0); +setcolor(cyan) cmyk(1,0,0,0); % Maybe these should +setcolor(magenta) cmyk(0,1,0,0); % be rbg for backward +setcolor(yellow) cmyk(0,0,1,0); % compatibility? +setcolor(cmykblack) cmyk(0,0,0,1); +setcolor(grayscaleblack) gray(0); +setcolor(grayscalewhite) gray(1); + +%<*MP> +if has_outputtemplate: + def setoutputtemplate = outputtemplate := enddef; +elseif has_filenametemplate: + def setoutputtemplate = filenametemplate enddef; +else: + def setoutputtemplate text garbage = enddef; +fi +%</MP> +%<MF>def setoutputtemplate text garbage = enddef; + +def romannumeral = _romannumeral (true) enddef; +vardef _romannumeral (expr prefix, X) = + save Y, _tmp, U; string U; + + Y.m := X div 1000; % thousands digit + _tmp := X - 1000Y.m; % hundreds digits and lower + Y.c := _tmp div 100; % hundreds + _tmp := _tmp - 100Y.c; % tens and units + Y.x := _tmp div 10; % tens + Y.i := _tmp - 10Y.x; % units + + strrepeat("m", Y.m) & + romandigit(prefix, "c", "d", "m", Y.c) & + romandigit(prefix, "x", "l", "c", Y.x) & + romandigit(prefix, "i", "v", "x", Y.i) +enddef; + +vardef romandigit (expr prefix, bot, mid, top, n) = + if n > 9 : top & strrepeat(bot, n-10) % shouldn't happen + elseif n > 8 : + if prefix: bot & top % "ix" + else: mid & bot & bot & bot & bot % "viiii" + fi + elseif n > 4 : mid & strrepeat (bot, n-5) % "v"--"viii" + elseif n > 3 : + if prefix: bot & mid % "iv" + else: bot & bot & bot & bot % "iiii" + fi + else: strrepeat (bot, n) % ""--"iii" for 0--3 + fi +enddef; + +vardef strrepeat (expr st, rep) = + setstring (_sr) ""; + for i = 1 upto rep: _sr := _sr & st; endfor + _sr +enddef; + % \end{macrocode} % % \section{The \grafbase{} Coordinate System}\label{coordinate} @@ -1211,8 +1503,8 @@ enddef; % by \gbc{unitlen} gets us sharped coordinates. For \MF{}, % multiplication by \mfc{hppp} converts to device coordinates, while for % \MP{} sharped and device are the same (the printer's PostScript -% rasterizing engine---or \prog{GhostScript}---does the final conversion -% to actual pixels). +% rasterizing engine---\prog{GhostScript} perhaps---does the final +% conversion to actual pixels). % % In \MF{}, \mfc{currenttransform} (via the macro \mfc{.t_}, defined by % \mfc{mode_setup}) takes care of the aspect ratio. In \MP{} the final @@ -1554,7 +1846,7 @@ label_sep := 0; labelpath_sep := 0; % expressions, it will actually place any picture, \gbc{s}. If you feed it % a string or path, it will convert it to a picture (with the \mfc{infont} % operator or the \gbc{picpath} macro). - +% % The macro \gbc{newgblabel} takes 6 parameters. The first three % parameters could easily be condensed into two if \mfpic{} support were % all that was required, however I thought it best to make it general. @@ -1789,6 +2081,7 @@ def textovalx = xellipse (true) enddef; def textellipsex = xellipse (false) enddef; % \end{macrocode} +% % \DescribeRoutine{xellipse} % In \gbc{xellipse}, \gbc{aa} and \gbc{bb} are the horizontal and % vertical radii of the resulting ellipse, while \gbc{ww} and \gbc{hh} @@ -1904,6 +2197,7 @@ def TruncateWarn expr s = enddef; % \end{macrocode} +% % In addition to \mfc{sind} and \mfc{cosd} which take angles in degrees, % we define the remaining trig functions \gbc{tand}, \gbc{cotd}, % \gbc{secd}, and \gbc{cscd}. @@ -1935,6 +2229,7 @@ enddef; vardef cotd primary X = cosd(X)*cscd(X) enddef; % \end{macrocode} +% % These are the inverse functions, which return an angle in degrees: % \RoutineIndex{acos}\gbc{acos}, \RoutineIndex{asin}\gbc{asin} and % \RoutineIndex{atan}\gbc{atan}. @@ -1958,6 +2253,7 @@ enddef; vardef atan primary X = angle (1, X) enddef; % \end{macrocode} +% % Now the trig functions that take angles in radians: % \RoutineIndex{sin}\gbc{sin}, \RoutineIndex{cos}\gbc{cos}, % \RoutineIndex{tan}\gbc{tan}, \RoutineIndex{cot}\gbc{cot}, @@ -1979,6 +2275,7 @@ vardef csc primary X = cscd (X*radian) enddef; % \begin{macrocode} vardef degrees (expr t) = t*radian enddef; vardef radians (expr t) = t/radian enddef; + % \end{macrocode} % % And the inverses (\RoutineIndex{invsin}\gbc{invsin}, @@ -2007,19 +2304,6 @@ def logtwo = logbase( 2) enddef; def logten = logbase(10) enddef; % \end{macrocode} -% \CMF's pair variables are a decent replacement for complex variables. -% These give some of the more basic functions of standard complex -% analysis: \RoutineIndex{Arg}\gbc{Arg}, \RoutineIndex{Log}\gbc{Log}, -% \RoutineIndex{cis}\gbc{cis}, \RoutineIndex{zexp}\gbc{zexp} and -% \RoutineIndex{sgn}\gbc{sgn}. -% \begin{macrocode} -vardef Arg primary Z = (angle Z)/radian enddef; -vardef Log primary Z = (ln (abs Z), Arg Z) enddef; -vardef cis primary T = dir (T*radian) enddef; -vardef zexp primary Z = (exp (xpart Z)) * cis (ypart Z) enddef; -vardef sgn primary Z = if not (Z = origin): unitvector fi Z enddef; - -% \end{macrocode} % % The hyperbolic functions: \RoutineIndex{cosh}\gbc{cosh} % \RoutineIndex{sinh}\gbc{sinh}, \RoutineIndex{tanh}\gbc{tanh}, @@ -2074,6 +2358,7 @@ vardef coth primary X = enddef; % \end{macrocode} +% % The inverses of some of the hyperbolic functions: % \RoutineIndex{acosh}\gbc{acosh}, \RoutineIndex{asinh}\gbc{asinh} and % \RoutineIndex{atanh}\gbc{atanh}. @@ -2100,6 +2385,42 @@ enddef; % \end{macrocode} % +% \CMF's pair variables are a decent replacement for complex variables. +% These give some of the more basic functions of standard complex +% analysis: \RoutineIndex{Arg}\gbc{Arg}, \RoutineIndex{Log}\gbc{Log}, +% \RoutineIndex{cis}\gbc{cis}, \RoutineIndex{zexp}\gbc{zexp}, +% \RoutineIndex{sgn}\gbc{sgn}, and \RoutineIndex{conj}\gbc{conj}. +% \begin{macrocode} +vardef Arg primary Z = (angle Z)/radian enddef; +vardef Log primary Z = (ln (abs Z), Arg Z) enddef; +vardef cis primary T = dir (T*radian) enddef; +vardef zexp primary Z = (exp (xpart Z)) * cis (ypart Z) enddef; +vardef sgn primary Z = if not (Z = origin): unitvector fi Z enddef; +vardef conj primary Z = (xpart Z, -ypart Z) enddef; + +% \end{macrocode} +% +% \DescribeRoutine{Moebius} +% A less basic operation: the Moebius shift which takes the disk $|z| < +% 1$ onto itself. It is a hyperbolic geometry analog of shifting points +% in Euclidean geometry. Its mathematical definition (all variables are +% complex numbers): +% \[ +% M_a(z) = \frac{z + a}{1 - \bar az} +% \] +% \DescribeRoutine{pshdist} +% Related to \gbc{Moebius} is the pseudohyperbolic metric. The distance +% between $z$ and $w$ in this metric is $|z-w|/|1 - \bar wz|$. +% \begin{macrocode} +vardef Moebius (expr A) primary Z = + save _D; pair _D; + _D := (1, 0) + (Z zscaled (conj A)); + (Z + A)/(abs _D) rotated (- angle _D) +enddef; +vardef pshdist (expr Z,W) = abs(Moebius(-W)(Z)) enddef; + +% \end{macrocode} +% % \DescribeRoutine{polar} % \gbc{polar} converts a polar coordinate pair $(r, \theta)$ to the % corresponding rectangular coordinate pair. @@ -2125,6 +2446,7 @@ primarydef x**y = fi enddef; let ^ = **; + % \end{macrocode} % % \section{Coordinate Systems and Transformations}\label{systems} @@ -2146,6 +2468,7 @@ let ^ = **; % \begin{macrocode} transform T_stack[]; numeric T_stack; T_stack := 0; + def T_push (expr T) = T_stack[incr T_stack] := T; enddef; def T_pop (suffix $) = if T_stack > 0: @@ -2451,6 +2774,7 @@ enddef; def mono (suffix u) = cull u keeping (1, infinity); enddef; % \end{macrocode} +% % \DescribeRoutine{andto, picand} % The bitwise and: in the resulting picture, a pixel is \emph{on} if and % only if it is \emph{on} in both \gbc{u} and \gbc{v}. \gbc{andto} is @@ -2465,6 +2789,7 @@ primarydef u picand v = enddef; % \end{macrocode} +% % \DescribeRoutine{orto, picor} % The inclusive or: in the result, a pixel is \emph{on} if and only if it % is \emph{on} in \gbc{u} or \gbc{v} or both. I've written these so that @@ -2488,6 +2813,7 @@ primarydef u picor v = enddef; % \end{macrocode} +% % \DescribeRoutine{xorto, picxor} % The exclusive or, also called the symmetric difference: % in the result, a pixel is \emph{on} if and only if it is \emph{on} in @@ -2502,6 +2828,7 @@ primarydef u picxor v = enddef; % \end{macrocode} +% % \DescribeRoutine{subto} % The nonsymmetric difference: in the result, a pixel is \emph{on} if % and only if it is \emph{on} in \gbc{u} and off in \gbc{v}. It is @@ -3357,7 +3684,7 @@ enddef; % % \DescribeRoutine{stored} % The macro \gbc{stored} performs \gbc{store}, but passes the same path as -% its return value. This is used by \mfpic{} to implements the \cs{store} +% its return value. This is used by \mfpic{} to implement the \cs{store} % command, allowing it to also be a prefix macro % % I don't know if \gbc{store} needs to employ \mfc{hide()}, but it seems @@ -3366,7 +3693,7 @@ enddef; def store (suffix fs) expr f = hide ( if (not path f) and (not pair f): - GBerrmsg ("improper expression type.") + GBerrmsg ("Improper expression type.") "The second argument to `store' must be a path or pair."; fi if not path fs: path fs; fi @@ -4007,7 +4334,6 @@ vardef gendashed (suffix pat) expr f = picture _v; _v := nullpicture; _d0 := 0; _t0 := 0; dashit (_dpat.start) (_v); - % \end{macrocode} % The parameters to \gbc{dashit} are the name of the part of the dashing % pattern that is being drawn, and a temporary picture variable. The @@ -4228,7 +4554,6 @@ enddef; % \end{macrocode} % -% % The \mfpic{} command \cs{dashed} is now implemented by making a % dashpattern from the two arguments and calling gendashed. That is the % definition of \gbc{DASHED}. @@ -4324,6 +4649,7 @@ vardef colorshowcontrols (expr clr, syma, symb, size) expr f = enddef; % \end{macrocode} +% % \subsection{Double-line drawing}\label{doubleline} % % \DescribeRoutine{doubledraw} @@ -4585,6 +4911,7 @@ vardef axis@# (expr len) = headpath (len, 0, 0) axisline@# enddef; vardef borderrect = rect((xneg+laxis,yneg+baxis),(xpos-raxis,ypos-taxis)) enddef; + % \end{macrocode} % % Tick marks can be on the inside or outside of a border axis, @@ -4921,6 +5248,7 @@ def polargridpoints (expr dsize, rstep, tstep) = enddef; % \end{macrocode} +% % \DescribeRoutine{beginpolargrid} % This calls \gbc{getpolarbounds} to compute the bounds (on $r$ and % $\theta$) of the smallest polar coordinate patch that covers the graph @@ -5037,7 +5365,8 @@ enddef; % the upright rectangle with those points at opposite corners. It might be % noted that if the corners really are lower left and upper right, then % the path is anticlockwise, If they are on the other diagonal, the -% path is clockwise. The path is a cycle (closed). +% path is clockwise. The path is a cycle (closed). The starting/ending +% point (needed for arrows and the like) is the first point of the two. % % \DescribeRoutine{triangle} % Produces a closed path joining three points with straight lines; first @@ -5230,20 +5559,46 @@ enddef; % \begin{macrocode} vardef turtle (text t) = setnumeric (_tu) 0; - pair _tu[]; _tu0 := origin; - for _a = t: _tu[incr _tu] := _tu[_tu - 1] + _a; endfor + setpair (_tmp) origin; + pair _tu[]; + for _a = t: + _tmp := _tmp + _a; + _tu[incr _tu] := _tmp; + endfor if _tu = 0: NoPoints("turtle", _tu); fi mkpoly (false, _tu) enddef; % \end{macrocode} % +% \DescribeRoutine{brownianpath} +% I needed the following to illustrate Brownian motion. It takes a given +% starting point, a given number of steps and a scaling factor. It +% generates a sequence of random points, each one being chosen randomly +% using a Gaussian distribution centered at the previous point. Strictly +% speaking this is a Gaussian random walk, not Brownian motion. A true +% Brownian motion would be a limit of these, with \gbc{num} tending to +% $\infty$ and \gbc{sc} tending to 0. +% \begin{macrocode} +vardef brownianpath (expr start, num, sc) = + setnumeric (_brp) 1; + setpair (_tmp) start; + pair _brp[]; _brp1 := _tmp; + for _idx := 1 upto num: + _tmp := _tmp + sc/(sqrt 2)*(normaldeviate,normaldeviate); + _brp[incr _brp] := _tmp; + endfor + mkpoly (false, _brp) +enddef; + +% \end{macrocode} +% % \subsection{Smooth paths}\label{smooth} % % We added an optional parameter for the tension of smooth curves to % \mfpic. It used to be implemented this way: functions that implement a % tension parameter set \gbc{cur_tension} and called \gbc{mksmooth}, which -% uses that tension in its formation of a path. Since \gbc{mksmooth} was +% used that tension in its formation of a path. Since \gbc{mksmooth} was % only ever used in this way, I decided to change its syntax to include a % tension parameter. Only the functions \gbc{tcurve} and \gbc{mkpath} % actually call \gbc{mksmooth} directly, most other path building commands @@ -5276,6 +5631,7 @@ vardef mksmooth (expr tens, cyclic) (suffix pts) = enddef; % \end{macrocode} +% % \DescribeRoutine{mktenser} % This is just like \gbc{mksmooth}, except the tension value is preceded % by \mfc{atleast}. At this writing only \gbc{mkconvex} uses it (as a @@ -5313,7 +5669,7 @@ enddef; % the flatness is infinite and the curve is forced in that direction. We % measure the flatness using the square root of the area of the triangle % made by the given point and the the next two points. Those three points -% lie on a line just when the area is $0$. Using this measure of fltness +% lie on a line just when the area is $0$. Using this measure of flatness % can be disputed (two triangles can be equally flat in terms of angles % but different in terms of areas), but it has the advantage that if the % points are subjected to an affine transformation, the weighting is @@ -5453,22 +5809,25 @@ enddef; % % \DescribeRoutine{mkqbezier} % \gbc{mkqbezier} requires an even number of points for a cyclic path, -% an odd number for a noncyclic path. The \mfc{for}-loop ends on the last -% odd index. If \gbc{pts} is odd and \gbc{cyclic} is true we need to -% manufacture another control point for the connection back to the -% start. We take that to be a repetition of the last point. If \gbc{pts} -% is even and \gbc{cyclic} is false then the loop ends at \gbc{pts-1}. -% Again we need to pick a control to connect to the last point, and again -% we use that last point as the control. In these two cases the last -% link is a straight line. +% an odd number for a noncyclic path. It does not check for this, but +% the calling macro \gbc{qbezier} does. If the parity is incorrect, it +% repeats the last point in the list. This has the effect of making +% the last link a straight line. % % \DescribeRoutine{qbezier} % The \gbc{qbezier} command takes a list of points and creates an array % from then before calling \gbc{mkqbezier}. +% +% \DescribeRoutine{mkcbezier} +% This is like \gbc{mkqbezier}, but needs a multiple of 3 for a closed +% cubic bezier, one more (the endpoint) for an open cubic bezier. +% +% \DescribeRoutine{cbezier} +% Like \gbc{qbezier}, but calls \gbc{mkcbezier}. % \begin{macrocode} vardef mkqbezier (expr cyclic) (suffix pts) = pts1 - if pts=1: {0,0} + if pts=1: {0,0} else: for _i = 2 step 2 until pts - 1: ..controls 1/3[pts[_i], pts[_i-1] ] and 1/3[pts[_i], pts[_i+1] ].. @@ -5483,8 +5842,7 @@ enddef; vardef qbezier (expr cyclic) (text t) = setpairs (_qbz) (t); - if _qbz=0: NoPoints ("qbezier", _qbz); fi - if _qbz=1: onepointpath (cyclic, _qbz1) + if _qbz=0: NoPoints ("qbezier", _qbz); else: if (cyclic and odd _qbz) or (not cyclic and even _qbz): _qbz[incr _qbz] := _qbz[_qbz-1]; @@ -5493,6 +5851,45 @@ vardef qbezier (expr cyclic) (text t) = fi enddef; +vardef mkcbezier (expr cyclic) (suffix pts) = + pts1 + if pts=1: {0,0} + else: + for _i = 1 step 3 until pts - 3: + ..controls pts[_i+1] and pts[_i+2] .. pts[_i+3] + endfor + if cyclic: + ..controls pts[pts - 1] and pts[pts]..cycle + fi + fi +enddef; + +vardef cbezier (expr cyclic) (text t) = + setpairs (_cbz) (t); + if _cbz=0: NoPoints ("qbezier", _cbz); + else: + % Need 0 mod 3 for cyclic, otherwise 1 mod 3 + setnumeric (_mdt) _cbz mod 3; + if cyclic: + if _mdt <> 0: _cbz[incr _cbz] := _cbz[_cbz-1]; fi + if _mdt = 1 : _cbz[incr _cbz] := _cbz1; fi + else: % need 1 more, duplicate next to last + if _mdt = 0: + _cbz := _cbz + 1; + _cbz[_cbz] := _cbz[_cbz-1]; + _cbz[_cbz-1] := _cbz[_cbz-2]; + fi + if _mdt = 2: % need 2 more, duplicate last 2. + _cbz := _cbz + 2; % add 2 slots + _cbz[_cbz] := _cbz[_cbz-2]; % fill them + _cbz[_cbz-1] := _cbz[_cbz-2]; % with last node + _cbz[_cbz-2] := _cbz[_cbz-3]; % orig last slot = orig previous. + fi + fi + mkcbezier (cyclic) (_cbz) + fi +enddef; + % \end{macrocode} % % When calling \gbc{curve} or \gbc{tcurve} there can be a problem @@ -5513,13 +5910,13 @@ enddef; % ourselves. By default we choose the two controls so the \mfc{xpart}s % divide the $x$-interval into three equal parts. This makes the B\'ezier % $f(t)$ linear in the $x$-part and so has the added `advantage' that in -% each segment, $y$ is a cubic function of $x$. It is not a spline, as we -% compute the controls locally and allow them to be modified by an -% additional parameter. +% each segment, $y$ is a cubic function of $x$. It is not a spline, as +% the computation of the controls uses only the two nearest points, plus +% we allow them to be modified by an additional parameter. % % Another concern is what direction to place the controls. In % \gbc{mksmooth} we ask the direction at a given point to be the average -% of the straight line directions to adjacent points. We now do the same +% of the straight line directions to adjacent points. We do the same % here, though it is not clear if this is best. % % Finally, we permit a tension of sorts by dividing the distance to the @@ -5536,14 +5933,15 @@ enddef; % Following discussions with Stephan Hennig in \texttt{comp.text.tex} I % came to the conclusion that the method used ought to satisfy the % following: if the data are xscaled or yscaled, the control vectors ought -% to scale the same way. The current version does that. +% to scale the same way. The current version does that, the previous one +% did not. % % \DescribeRoutine{mkfcnpath} % This produces the path, calling \gbc{fcncontrol} to produce the controls. % % \DescribeRoutine{fcncurve} % This is the \mfpic{} interface; \gbc{fcncurve} calls \gbc{functioncurve} -% with the default tension, which \DescribeRoutine{functioncurve}then +% with the default tension, and \DescribeRoutine{functioncurve}then % takes a list of points, converts it to an array, and calls % \gbc{mkfcnpath} to build the path. % \begin{macrocode} @@ -5622,6 +6020,7 @@ vardef qspline (expr cyclic) (text t) = fi mkqbs (_qs) if cyclic: & cycle fi enddef; + % \end{macrocode} % % These cubic B-splines also require a list of `control' points. Each of @@ -5685,6 +6084,7 @@ vardef cspline (expr cyclic) (text t) = fi mkcbs (_cs) if cyclic: & cycle fi enddef; + % \end{macrocode} % % \subsection{Splines with computed controls}\label{computedsplines} @@ -5729,8 +6129,8 @@ enddef; % \DescribeRoutine{relaxed_spline_eqns}relaxed splines they force % the second derivative to be 0 at the first and last point. % -% The macro \gbc{mksplinepath} simply assembles the points and controls -% previously computed into a path. +% The macro \gbc{mksplinepath} simply assembles the previously computed +% points and controls into a path. % % \DescribeRoutine{mkspline}\gbc{mkspline} issues the % common equations and then either the closed equations (\gbc{closed = @@ -5791,6 +6191,7 @@ vardef dospline (expr closed) (text the_list) = enddef; % \end{macrocode} +% % The above computations produce a $2$-dimensional spline. A $1$-dimensional % cubic spline would be a function $f(t)$ with numeric values rather % than pair values. Such are often used to interpolate functions. That is, @@ -6078,9 +6479,12 @@ enddef; % the angle $\pm 180$, which produces a half circle. % \begin{macrocode} vardef arcpp (expr small, begpt, endpt, rad) = - save full, ang; full := signof (rad) 360; - if 2*abs(rad) > abs(begpt - endpt): - ang := if not small: full - fi 2*asin (abs(begpt-endpt)/(2rad)); + save full, diam, chord, ang; + full := signof (rad) 360; + diam := 2rad; + chord := abs(endpt-begpt); + if chord < abs(diam): + ang := if not small: full - fi 2*asin (chord/diam); else: ang := signof (rad) 180; fi arcpps (begpt, endpt, ang) @@ -6146,10 +6550,13 @@ vardef ellipse (expr center, radx, rady, angle) = fullcircle xscaled (2*radx) yscaled (2*rady) rotated angle shifted center enddef; + vardef circle (expr center, rad) = fullcircle scaled (2*rad) shifted center enddef; + % \end{macrocode} +% % The next four implement different ways of specifying a circle. % \DescribeRoutine{circlecp} % The first produces the circle with a given center passing through a @@ -6178,24 +6585,29 @@ enddef; vardef circlecp (expr center, point) = mkarc (center, point, point, 360) & cycle enddef; + vardef circleppp (expr one, two, three) = arcpps (one, two, 2*cornerangle (three, one, two)) & arcpps (two, three, 2*cornerangle (one, two, three)) & arcpps (three, one, 2*cornerangle (two, three, one)) & cycle enddef; + vardef circlepps (expr one, two, sweep) = save ang, full; full := signof (sweep) 360; ang := sweep mod full; arcpps (one, two, ang) & arcpps (two, one, full - ang) & cycle enddef; + vardef circlepp (expr small, one, two, rad) = arcpp (small, one, two, rad) & arcpp (not small, two, one, rad) & cycle enddef; + def circleppr (expr one, two, rad, small) = circleppr (one, two, rad, small) enddef; + % \end{macrocode} % % \DescribeRoutine{pathcenter} @@ -6283,6 +6695,64 @@ enddef; % \end{macrocode} % +% \DescribeRoutine{pshcircle} +% Here is a couple of circles maybe only I need. They are the +% pseudohyperbolic circles in the unit disk and upper half-plane. +% One supplies a point that must be inside the unit circle or above +% the $x$-axis, and a radius that must be less than $1$. Some degenerate +% cases will not generate an error. We code this with a boolean that +% determine whether the disk of the half-plane is to be assumed. +% \begin{macrocode} +vardef pshcircle (expr disk, ctr, rad) = + if disk: + if rad >= 1 : + if rad > 1: + GBerrmsg ("Impossible pseudohyperbolic circle.") + "The radius of a pseudohyperbolic circle can be at most 1."; + fi + circle ((0,0),1) + elseif abs(ctr) >= 1 : + if abs(ctr) > 1: + GBerrmsg ("Impossible pseudohyperbolic circle.") + "The center of a pseudohyperbolic circle must be in" + & "the unit disk."; + fi + onepointpath (true,ctr) + else: + % compute Euclidean center and radius (and a denominator used twice + % in calculations). + save _r, _dnm; + _r := abs(ctr); + _dnm := 1 - _r*_r*rad*rad; + circle ( (1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm) + fi + else: + if rad >= 1 : + GBerrmsg ("Impossible pseudohyperbolic circle.") + "The radius of a pseudohyperbolic circle must be less than 1."; + onepointpath (true,ctr) + elseif ypart ctr <= 0: + if ypart ctr < 0: + GBerrmsg ("Impossible pseudohyperbolic circle.") + "The center of a pseudohyperbolic circle must be in" + & "the upper half-plane."; + fi + onepointpath (true,ctr) + else: + % compute Euclidean center and radius (and a denominator used twice + % in calculations). + % Euclidean center at xpart ctr + (1 + R^2)/(1 - R^2)*ypart ctr + % Euclidean radius 4R/(1 - R^2)*ypart ctr + save _y, _dnm; + _y := ypart ctr; + _dnm := 1 - rad*rad; + circle ( (xpart ctr, (1 + rad*rad)/_dnm * _y), 2rad/_dnm*_y) + fi + fi +enddef; + +% \end{macrocode} +% % \DescribeRoutine{barycenter} % This is the average of the three corners of the triangle, or of any % path. If \gbc{t} is an open path with length $n$ and the nodes are @@ -6295,7 +6765,7 @@ enddef; % don't recall if this is the center of any important circle. % % The centers of the various circles associated with triangles can be -% found with \gbc{pathcenter}. Or by intersecting vasious lines: the +% found with \gbc{pathcenter}. Or by intersecting various lines: the % \emph{incenter} (center of the inscribed circle)is the intersection of % the angle bisectors; the \emph{circumcenter} is the intersection of the % prependicular bisectors. @@ -6319,7 +6789,6 @@ enddef; % \end{macrocode} % -% % \subsection{Plotting of functions}\label{functionplots} % % In these macros, if the boolean argument \gbc{sm} is true then the @@ -6470,6 +6939,7 @@ def plrregion (expr sm) = tplrregion (sm, default_tension) enddef; vardef tplrregion (expr sm, tn, tlo, thi, st) (text _ft) = (0,0)--tplrfcn (sm, tn, tlo, thi, st ) (_ft)--cycle enddef; + % \end{macrocode} % % \DescribeRoutine{mklevelset} @@ -6509,6 +6979,7 @@ enddef; % \begin{macrocode} numeric tolerancefactor; tolerancefactor := .02; + vardef mklevelset (expr sm, tens, X, Y, t, a, b, c, d) = save _inside_; vardef _inside_ (expr U, V) = @@ -6552,6 +7023,7 @@ vardef mklevelset (expr sm, tens, X, Y, t, a, b, c, d) = enddef; % \end{macrocode} +% % \DescribeRoutine{levelset} % This is the \mfpic{} interface. It checks the \gbc{t} parameter before % passing it to \gbc{mklevelset}, making sure it is not zero, it passes @@ -6603,6 +7075,7 @@ vardef lclosed expr f = enddef; % \end{macrocode} +% % \DescribeRoutine{sclosed} % This closes the path in the manner that \gbc{mksmooth} creates a path. % This will change the first and last segment of the original path. In @@ -6626,6 +7099,7 @@ vardef sclosedt (expr t) expr f = enddef; % \end{macrocode} +% % \DescribeRoutine{bclosed} % This closes with the basic default \MF{} Bezi\'er. It is a smooth % closure, but it does not have the same direction at the endpoints @@ -6641,6 +7115,7 @@ vardef bclosedt (expr t) expr f = enddef; % \end{macrocode} +% % \DescribeRoutine{uclosed} % Same as \gbc{bclosed}. Retained for backward compatibility. There is % a tense variant only for \DescribeRoutine{uclosedt}consistency. @@ -6649,6 +7124,7 @@ def uclosed = bclosed enddef; def uclosedt = bclosedt enddef; % \end{macrocode} +% % \DescribeRoutine{cbcontrols} % This utility is for use in \gbc{cbclosed}. It converts Bezier segment % key points of a path \gbc{f}, to cubic B-spline control points stored @@ -6726,6 +7202,7 @@ enddef; % computed by \gbc{pathcenter}. % \begin{macrocode} vardef makesector expr p = (pathcenter p)--p--cycle enddef; + % \end{macrocode} % % \DescribeRoutine{arccomplement} @@ -7057,6 +7534,19 @@ vardef colorGheadpath f enddef; + +% \end{macrocode} +% +% \DescribeVariable{cut_path} +% Additional clearing path, almost the same as plain.mf's \gbc{cut_} (no +% \gbc{cut_} in plain.mp) but rotated, and scaled differently. The odd +% scaling is so that if yscaled by the diameter of a dot, and the dot +% happens to be digitized to a square shape, then the \gbc{cut_path}, +% centered at the center of the dot and rotated 45 degrees, will encompass +% the whole square (theoretically). +% \begin{macrocode} +path cut_path; cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle; + % \end{macrocode} % % \DescribeRoutine{tailpath}\RoutineIndex{colortailpath} @@ -7263,6 +7753,7 @@ vardef randomlines (expr maxshift) expr f = fi fi enddef; + % \end{macrocode} % % \subsection{Parallelling a path} @@ -7424,7 +7915,6 @@ def setdatadashes (text lst) = forsuffixes _itm = lst: if knownnumericarray _itm : copyarray (_itm) (__type[__type]); -% __type := __type + 1; next __type; else: GBwarn "Improper dash pattern in setdatadashes."; fi @@ -7489,7 +7979,7 @@ def setdatasymbols (text lst) = __type[__type] := _itm; next __type; else: - GBwarn "Improper path in setdatasymbols()."; + GBwarn "Improper symbol in setdatasymbols()."; fi endfor if __type > 1: @@ -7566,7 +8056,6 @@ Diamond := undo_cycle SolidDiamond; Diamond.clear := SolidDiamond.clear := (right--(1,1)--(-1,1)--left--up--cycle) scaled .522 yscaled 1.44; -% As arrow heads, these have their "tips" at their center. Plus := ((0,0)--up--down--(0,0)--left--right) scaled .65; Plus.clear := (right--(1,1)--(-1,1)--(left)--cycle) scaled .65; @@ -7629,6 +8118,7 @@ forsuffixes S = SolidDiamond, SolidStar : S.tip := point 0 of S; endfor + % \end{macrocode} % % \DescribeRoutine{gcd} @@ -7655,23 +8145,11 @@ vardef gcd (expr n, m) = enddef; vardef lcm (expr n, m) = - n*m/gcd(n, m) + n/gcd(n, m)*m enddef; % \end{macrocode} % -% \DescribeVariable{cut_path} -% Additional clearing path, almost the same as plain.mf's \gbc{cut_} (no -% \gbc{cut_} in plain.mp) but rotated, and scaled differently. The odd -% scaling is so that if yscaled by the diameter of a dot, and the dot -% happens to be digitized to a square shape, then the \gbc{cut_path}, -% centered at the center of the dot and rotated 45 degrees, will encompass -% the whole square (theoretically). -% \begin{macrocode} -path cut_path; cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle; - -% \end{macrocode} -% % \DescribeRoutine{defaultsymbols} % The command for restoring the default symbols. % \begin{macrocode} @@ -7687,50 +8165,73 @@ defaultsymbols; % \DescribeRoutine{setdatacolors} % Finally, for \MP, we do a similar pair of commands for setting % the colors for the \cs{plotdata} command, and for -% \DescribeRoutine{getcolor}getting the next one. +% \DescribeRoutine{getcolor}getting the next one. The odd indirection +% (\gbc{colortype[]} is an array of strings, the names of variables +% having color values) is because \MP{} now has three different data +% types for colors. Arrays must be all one type. % % \DescribeRoutine{defaultcolors} % These default colors were tested on screen and on an inkjet printer. % The adjustments away from pure colors is based on a compromise between % those experiments. % \begin{macrocode} +%<*MP> def setdatacolors (text lst) = - save __type; color __type[]; - __type := 0; + setnumeric (__type) 0; + % First, just count and store the known colors in the list for _itm = lst: - if (known _itm) and (color _itm): - __type[__type] := _itm; + if knowncolor _itm : + if __type = 0 : def _datacolors = _itm enddef; + else: + expandafter def + expandafter _datacolors + expandafter = _datacolors, _itm enddef; + fi next __type; else: GBwarn "Improper color in setdatacolors()."; fi endfor if __type > 1: - save colortype; colortype := __type; - color colortype[]; - for _j = 0 upto colortype - 1: - colortype[_j] := __type[_j]; + save colortype, _tmpstr; + colortype := 0; + % colortype[] is an array of strings: + string colortype[], _tmpstr; + for _itm = _datacolors: % + % Each string is the name of some color variable + _tmpstr := "colortype_"&romannumeral(colortype); + setcolor (scantokens(_tmpstr)) _itm; + colortype[colortype] := _tmpstr; + next colortype; endfor else: SetdataWarn "colors"; fi enddef; -def getcolor expr n = colortype[n mod colortype] enddef; - -color dBlue, dOrange, dGreen, dMagenta, dCyan, dYellow; -dBlue := 0.80blue + .2white; -dOrange := 0.66yellow + .34red; -dGreen := 0.80green; -dMagenta := 0.85magenta; -dCyan := 0.85cyan; -dYellow := 0.85yellow; - -numeric colortype; color colortype[]; +def getcolor expr n = (scantokens (colortype[n mod colortype])) enddef; + +numeric colortype; string colortype[]; + +setcolor (dRed) (1, 0, 0); +setcolor (dBlue) (.2,.2,1); +setcolor (dOrange) (1,.34,0); +setcolor (dGreen) (0,.80,0); +setcolor (dBlack) cmykblack; +if has_cmyk : + setcolor (dCyan) cyan; + setcolor (dMagenta) magenta; + setcolor (dYellow) yellow; +else: % rgb colors seem to be lighter than the cmyk equivalents. + setcolor (dCyan) cmyk(.85,0,0,.15); + setcolor (dMagenta) cmyk(0,.85,0,.15); + setcolor (dYellow) cmyk(0,0,.85,.15); +fi def defaultcolors = - setdatacolors(black, red, dBlue, dOrange, dGreen, - dMagenta, dCyan, dYellow); + setdatacolors(dBlack, dRed, dBlue, dOrange, + dGreen, dMagenta, dCyan, dYellow); enddef; defaultcolors; +%</MP> % \end{macrocode} % % @@ -7985,22 +8486,19 @@ numeric gcode; gcode := 0; % % \subsection{Dvips names for colors}\label{dvipsnam} % -% In order to make \file{dvipsnam.mp} useful outside grafbase, we repeat -% the definition of \gbc{cmyk} here. +% In order to make \file{dvipsnam.mp} useful outside grafbase, we give +% here a definition for \gbc{cmyk} when \gbc{grafbaseversion} is unknown. % \begin{macrocode} %<*dvips> if unknown grafbaseversion: - vardef snapto expr t = - if unknown t: 0 - elseif not (numeric t): 0 - elseif t < 0: 0 - elseif t > 1: 1 - else: t - fi - enddef; - vardef cmyk (expr c, m, y, k) = - (snapto 1-c-k, snapto 1-m-k, snapto1-y-k) - enddef; + if unknown mpversion: + let cmykcolor=color; + vardef cmyk (expr c, m, y, k) = + (max(1-c-k,0), max(1-m-k,0), max(1-y-k,0)) + enddef; + else: + vardef cmyk (expr c, m, y, k) = (c, m, y, k) enddef; + fi fi % \end{macrocode} @@ -8017,7 +8515,7 @@ fi % Declare all the dvips color names to be color variables, and define % them as in \file{dvipsnam.def}: % \begin{macrocode} -color Apricot, Aquamarine, Bittersweet, Black, Blue, BlueGreen, +cmykcolor Apricot, Aquamarine, Bittersweet, Black, Blue, BlueGreen, BlueViolet, BrickRed, Brown, BurntOrange, CadetBlue, CarnationPink, Cerulean, CornflowerBlue, Cyan, Dandelion, DarkOrchid, Emerald, ForestGreen, Fuchsia, Goldenrod, Gray, Green, GreenYellow, JungleGreen, diff --git a/Master/texmf-dist/source/generic/mfpic/mfpic.dtx b/Master/texmf-dist/source/generic/mfpic/mfpic.dtx index daab8c0d9b6..fcc42f917cb 100644 --- a/Master/texmf-dist/source/generic/mfpic/mfpic.dtx +++ b/Master/texmf-dist/source/generic/mfpic/mfpic.dtx @@ -1,7 +1,10 @@ % \iffalse +%%% File: mfpic.dtx +%%% A part of mfpic 1.00 2009/09/22 +%%% % ------------------------------------------------------------------- % -% Copyright 2002--2006, Daniel H. Luecking +% Copyright 2002--2009, Daniel H. Luecking % % Mfpic may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3b of this license or (at @@ -19,7 +22,7 @@ %</driver> %<sty>\ProvidesPackage{mfpic} %<*sty> - [2006/05/26 v0.9. Macros for drawing with Metafont/MetaPost.]% + [2009/09/22 v1.00. Macros for drawing with Metafont/MetaPost.]% %</sty> %<*driver> \documentclass[draft]{ltxdoc} @@ -103,7 +106,7 @@ \end{document} %</driver> %\fi -% \CheckSum{4902} +% \CheckSum{5116} % \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 @@ -131,8 +134,9 @@ % produce the picture. The picture is then included on a second pass % through \TeX. % -% This file documents the source code. See \file{mfpman.pdf} or -% \file{mfpman.tex} for the user documentation. +% This file documents the source code. See \file{mfpic-doc.pdf} (source +% \file{mfpic.doc.tex} for the user documentation or \file{mfpguide.pdf} +% (source \file{}mfpguide.tex}) for an introductory guide. % \end{abstract} % % \StopEventually{\PrintIndex} @@ -166,9 +170,9 @@ \ifx\mfpfileversion\UndEfInEd\else\expandafter\endinput\fi% {% \catcode\lq\.12 \catcode\lq\/12% - \gdef\mfpfileversion{0.9}% - \gdef\mfpfiledate{2006/05/26}% - \gdef\mfpicversion{90}% + \gdef\mfpfileversion{1.00}% + \gdef\mfpfiledate{2009/09/22}% + \gdef\mfpicversion{100}% }% % \end{macrocode} % @@ -471,13 +475,17 @@ % % Some options and commands require the \opt{metapost} option be in % effect. We define an error message for the case where it is not in -% effect. +% effect. Rarely, we need a similar warning for the \opt{metafont} +% option. % \begin{macrocode} \newdef\mfp@noMP@error#1{% \mfp@errmsg {Metafont does not support #1, use MetaPost}% {Metafont doesn't support #1. Perhaps you forgot to turn on^^J% MetaPost support by using the metapost option or issuing the^^J% command \usemetapost. For now, I will ignore it.}}% +\newdef\mfp@noMF@warn#1{% + \Mfpic@warn + {Metapost does not support \string#1, it will be ignored.}}% % \end{macrocode} % % This next is like \cs{mfp@useMP@error}, but it is not so specific. @@ -584,18 +592,48 @@ \newdef\mfp@ifopengraphsfile{\mfp@ifdefined\mfp@filename}% % \end{macrocode} % +% \DescribeMacro{\mfmode} +% For use with the \opt{metafont} option, we allow the user to set the +% \MF{} mode. Example: \verb$\mfmode{ljfour}$ +% +% \DescribeMacro{\mfresolution} +% If modes are too esoteric, the user can at least set the resolution. +% This should be a pure number representing dots per inch. Example: +% \verb$\mfresolution{600}$ +% \begin{macrocode} +\newdef\mfmode#1{\edef\mfp@mode{#1}% + \mfp@ifopengraphsfile% + {\mfp@afteropen@error\mfmode}% + {\mfp@ifmpost{\mfp@noMF@warn\mfmode}{}}}% +\newdef\mfresolution#1{\edef\mfp@resolution{#1}% + \mfp@ifopengraphsfile% + {\mfp@afteropen@error\mfresolution}% + {\mfp@ifmpost{\mfp@noMF@warn\mfresolution}{}}}% +% \end{macrocode} +% % \DescribeMacro{\setmfvariable} % A useful abbreviation for a common requirement: declaring and setting % a \MF{} variable. I have decided to change it to a user-level macro for -% power users. -% \DescribeMacro{\setmpvariable}\cs{setmpvariable} is another name for it. -% It takes three arguments: the type of variable, the variable itself, and -% its value. Example:\\ +% power users. For consistency, \DescribeMacro{\setmpvariable}\cs{setmpvariable} +% is an alternative name for it. It takes three arguments: the type of +% variable, the variable itself, and its value. +% Example:\\ % \indent \cs{setmfvariable}\marg{numeric}\marg{shadewd}\marg{.7pt}.\\ -% Since 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. +% Since the \MF{} code \mfc{save}\,s the variable, there must be no +% suffix. This is not a big problem since mostly it is for internal use. +% We document that fact for power users and advise ordinary users on the +% naming of \MF{} variables. +% +% Since \MP{} has three (or four) data types for color, we have to write +% the command `\gbc{setcolor}' to the output file instead of +% `\gbc{setvariable (color)}' so that the datatype can be determined +% before declaring the variable. (Unlike the other data types the +% \grafbase{} command \gbc{setcolor} is more complicated than +% \gbc{setvariable(color)}.) For simplicity, we do this with all data +% types. For example \cs{setmfvariable}\marg{numeric} writes +% `\gbc{setnumeric}'. This makes spaces significant in the first argument, +% so we strip them off the ends with \cs{MFP@sp@def} (defined in +% section~\ref{optional}). % % We have abbreviations for the most common internal uses. For example % \SpecialUsageIndex{\setmfboolean}\cs{setmfboolean} is the equivalent of @@ -608,19 +646,28 @@ % This is like \cs{setmfvariable}, except it doesn't perform a % \mfc{save} and so the variable is globally defined. Also, % suffixed variables are permitted (but not numeric suffixes). +% Here, too, we have to write a different command for setting color. +% Thus, me need to test whether the first argument is `color'. Here again, +% spaces are significant. % \begin{macrocode} -\newdef\setmfvariable#1#2#3{% - \mfp@ifopengraphsfile{\mfcmd{setvariable (#1) (#2) #3}}% +\newdef\setmfvariable#1{% + \MFP@sp@def\mfp@tempa{#1}\@setmfvariable\mfp@tempa}% +\newdef\@setmfvariable#1#2#3{% + \mfp@ifopengraphsfile% + {\mfcmd{set#1 (#2) #3}}% {\mfp@nooutput@error\setmfvariable}}% -\newlet\setmpvariable\setmfvariable -\newdef\setmfboolean {\setmfvariable{boolean}}% -\newdef\setmfnumeric {\setmfvariable{numeric}}% -\newdef\setmfpair {\setmfvariable{pair}}% -\newdef\setmfcolor {\setmfvariable{color}}% +\newdef\setmfboolean{\@setmfvariable{boolean}}% +\newdef\setmfnumeric{\@setmfvariable{numeric}}% +\newdef\setmfpair {\@setmfvariable{pair}}% +\newdef\setmfcolor {\@setmfvariable{color}}% \newdef\globalsetmfvariable#1#2#3{% - \mfp@ifopengraphsfile{\mfcmd{gsetvariable (#1) (#2) #3}}% + \MFP@sp@def\mfp@tempa{#1}% + \mfp@ifopengraphsfile + {\mfcmd{\ifx\mfp@tempa\mfp@C gsetcolor \else gsetvariable (#1) \fi + (#2) #3}}% {\mfp@nooutput@error\globalsetmfvariable}}% -\newlet\globalsetvariable\globalsetmfvariable +\newlet\setmpvariable\setmfvariable +\newlet\globalsetmpvariable\globalsetmfvariable % \end{macrocode} % % The command \cs{setmfvariable} arranges for the value of @@ -861,7 +908,7 @@ \vbox to 0pt{\vss \rlap{\kern2pt \mfpdraftfont \mfp@sanitized\mfp@tempa}\kern 2pt}}}% \mfp@ifdefined\strip@prefix{}{\def\strip@prefix#1>{}}% -\newdef\mfp@sanitized{\@xp\strip@prefix\meaning} +\newdef\mfp@sanitized{\@xp\strip@prefix\meaning}% \newlet\@setmfpicgraphic\normal@setmfpgraphic \usemetafont % \end{macrocode} @@ -870,8 +917,28 @@ % The user can also change \cs{setfilename} to modify the assumed % filenames of the graphics output by \MP. The default is the output % file's basename (\arg1) with the picture number as the extension. +% +% \DescribeMacro{\setfilenametemplate} +% The user can also tell \MP{} what kind of filename he wishes it to +% produce. one uses \verb$\_$ in the template as a placeholder for the +% \file{.mp} filename (the name used in \cs{opengraphsfile}) and \verb$\#$ +% for the figure number. % \begin{macrocode} \newdef\setfilename#1#2{#1.#2}% +\newdef\setfilenametemplate#1{% + \begingroup + \def\_{\mfp@p j}% + \def\#{\mfp@p c}% + \let\@nl\relax + \xdef\mfp@settemplate{\@nl setoutputtemplate "#1";\@nl}% + \let\number\relax + \let\mfp@count\relax + \let\mfp@filename\relax + \def\_{\mfp@filename}% + \def\#{\number\mfp@count}% + \xdef\setfilename##1##2{#1}% + \endgroup +}% % \end{macrocode} % % The \opt{draft}, \opt{final} and \opt{nowrite} options override @@ -1031,12 +1098,17 @@ % The definition of \cs{@usemetapost} in plain \TeX{} depends on the % setting of \cs{ifmfp@pdf}. However both cases are so similar that we % define a helper macro \cs{mfp@useMP} that just needs to have the names -% of three commands and one file fed to it. +% of three commands and two files fed to it. % \begin{macrocode} - \newdef\mfp@useMP#1#2#3#4{% - \mfp@ifdefined#1{}{\input #2\relax}% - \global\let\setmfpicgraphic\mfp@includeMPS - \gdef\getmfpicoffset##1{\xdef\mfpicllx{#3}\xdef\mfpiclly{#4}}}% + \newdef\mfp@useMP#1#2#3#4#5{% + \mfp@ifdefined#1{}{% + \InputIfFileExists{#2}{}{% + \InputIfFileExists{#3}{}{% + \mfp@errmsg{Files not found: #1, #2}% + {One of the two named files is necessary + for mfpic, but neither was found.}}}}% + \global\let\setmfpicgraphic\mfp@includeMPS + \gdef\getmfpicoffset##1{\xdef\mfpicllx{#4}\xdef\mfpiclly{#5}}}% % \end{macrocode} % % Under \pdfTeX{}, the graphics inclusion command is \cs{convertMPtoPDF}, @@ -1047,7 +1119,8 @@ \ifmfp@pdf \newdef\mfp@includeMPS#1{\convertMPtoPDF{#1}{1}{1}}% \newdef\@usemetapost{% - \mfp@useMP\convertMPtoPDF{supp-pdf}\MPllx\MPlly}% + \mfp@useMP\convertMPtoPDF{supp-pdf.mkii}{supp-pdf.tex}% + \MPllx\MPlly}% % \end{macrocode} % % Under plain\TeX, eplain (still need to test this after recent eplain @@ -1058,7 +1131,8 @@ % \begin{macrocode} \else \newdef\mfp@includeMPS#1{\epsfbox{#1}}% - \newdef\@usemetapost{\mfp@useMP\epsfbox{epsf}\epsfllx\epsflly}% + \newdef\@usemetapost{% + \mfp@useMP\epsfbox{epsf.tex}{epsf.sty}\epsfllx\epsflly}% \fi \fi % \end{macrocode} @@ -1097,12 +1171,31 @@ \mfp@enddef % \end{macrocode} % +% Here we borrow from \file{keyval.sty}. We need a command that strips +% spaces off ends of an argument and stores the result in a macro. In +% \file{keyval}, that is \cs{KV@@sp@def}; we copy it here with name +% changes. Defining \cs{mfp@tempa}, and then calling it with a space as +% argument, ensures there will be an actual space token where needed in +% the definition of \cs{MFP@sp@def}. +% \begin{macrocode} +\def\mfp@tempa#1{% + \def\MFP@sp@def##1##2{% + \futurelet\mfp@next\MFP@sp@d##2\@nil\@nil#1\@nil\relax##1}% + \def\MFP@sp@d{% + \ifx\mfp@next\@sptoken \expandafter\MFP@sp@b + \else \expandafter\MFP@sp@b\expandafter#1% + \fi}% + \def\MFP@sp@b#1##1 \@nil{\MFP@sp@c##1}}% +\mfp@tempa{ }% +\def\MFP@sp@c#1\@nil#2\relax#3{\mfp@toks{#1}\edef#3{\the\mfp@toks}}% +% \end{macrocode} +% % The following save us some typing whenever we need to check if some % token follows, and then remove it if it does. That's what % \cs{mfp@iftoken} does, being just a generalized form of \LaTeX{}'s -% \cs{@ifstar}. All our star-form commands differ only in what parameter -% is passed to some other command. Thus \cs{mfp@ifstar} passes either -% \arg{2} or \arg{3} to command \arg{1}. +% \cs{@ifstar}. Almost all our star-form commands differ only in what +% parameter is passed to some other command. Thus \cs{mfp@ifstar} passes +% either \arg{2} or \arg{3} to command \arg{1}. % % The \cs{mfp@ifend} is for use in processing lists, which all end with % the token \cs{mfp@end}. \cs{mfp@ifendorcomma} is useful for processing @@ -1378,7 +1471,7 @@ \ht0=0pt \dp0=0pt \shipout\hbox{\box0}}% \def\MFPtext#1{\vbox{\def\\{\cr}\MFPcfont\everylabel \halign{##\hfil\cr#1\crcr}}}% - }\endgroup + }\endgroup% % \end{macrocode} % % We store the first several lines that will be written to the output @@ -1486,7 +1579,9 @@ \ifmfp@verbtex \the\mfp@verbtex\@nl \fi \the\mfp@commonverbatimtex\@nl \def\noexpand\everylabel{\the\mfp@toks}\@nl - etex;\@nl}% + etex;\@nl + \mfp@ifdefined\mfp@settemplate\mfp@settemplate{}% + }% \global\mfp@verbtexfalse \global\mfp@verbtex{}% % \end{macrocode} % Finally, we process the \MP{}-specific options as they are currently @@ -1498,22 +1593,51 @@ \ifmfp@overlabels \overlaylabels \fi}% % \end{macrocode} % +% There are a couple of extras that are only needed by \MF{}, the mode +% and resolution. Unlike the `MPextras' this does not write code, but +% rather \emph{is} code to write. It will occur inside a \cs{write} +% command. +% \begin{macrocode} +\def\mfp@MFextras{% + \mfp@ifdefined\mfp@resolution% + {GBresolution := \mfp@resolution;\@nl}{}% + \mfp@ifdefined\mfp@mode{mode := \mfp@mode;\@nl}{}}% +% \end{macrocode} +% +% All the characters likely to cause problems in a filename are rendered +% harmless with this command. We want to allow macros so backslashes, +% braces and spaces aren't touched. +% \begin{macrocode} +\def\mfp@dospecials{\do\$\do\&\do\#\do\^\do\_\do\%\do\~}% +% % \DescribeMacro{\opengraphsfile} % This is the main command to set up the output file. % The name of the output file is its only parameter, and it appends % the extension \file{.mf} or \file{.mp} depending on the whether option -% \opt{metafont} or \opt{metapost} was chosen. +% \opt{metafont} or \opt{metapost} was chosen. We first nullify \TeX{} +% special characters, then read the graphfile name, then store an +% expanded version. % \begin{macrocode} \mfp@DBlog{Macros to open and close graphs files.}% -\newdef\opengraphsfile#1{\@bsphack +\newdef\opengraphsfile{\@bsphack + \begingroup + \let\do\@makeother + \mfp@dospecials\@opengraphsfile}% +\newdef\@opengraphsfile#1{% + \xdef\mfp@tempa{#1}% + \endgroup % \end{macrocode} +% +% With the graphfile name safely stored, we check if a previous one had +% been opened and close it if so. Then we store in \cs{mfp@filename} +% a sanitized version of the name. +% % A command can determine if it occurs after \cs{opengraphsfile} but % before \cs{closegraphsfile} by testing whether \cs{mfp@filename} is % defined. We also save the name of the processing program (\MF{} or \MP) % and the file extension (\file{.mf} of \file{.mp}) in macros for use in % messages. % \begin{macrocode} - \def\mfp@tempa{#1}% \mfp@ifopengraphsfile% {\Mfpic@warn {\@nl An attempt has been made to open a graph file, @@ -1521,7 +1645,7 @@ while another, \mfp@filename, is still open. \@msgbreak Closing \mfp@filename.}\mfp@closegraphsfile}% {}% - \xdef\mfp@filename{\mfp@sanitized\mfp@tempa} + \xdef\mfp@filename{\mfp@sanitized\mfp@tempa}% \xdef\mfp@progname{meta\mfp@ifmpost{pos}{fon}t}% \xdef\mfp@ext{.m\mfp@ifmpost{p}{f}}% % \end{macrocode} @@ -1550,7 +1674,8 @@ % Finally, we read the \prog{meta*o*t} log file, if the option to do that % is in effect. % \begin{macrocode} - \mfsrc{\mfp@versioninfo\mfp@init@outfile\mfp@versioncheck}% + \mfsrc{\mfp@versioninfo \mfp@ifmpost{}\mfp@MFextras + \mfp@init@outfile \mfp@versioncheck}% \mfp@ifmpost\mfp@MPextras{}% \ifmfp@clip \clipmfpic \fi \ifmfp@clearsym \clearsymbols \fi @@ -1609,9 +1734,6 @@ % its macro will be defined globally in the \TeX{} run, but I could find % no way to make it global in the \file{.mp} file under \opt{mplabels}. % Thus, I've created a \cs{globalassignmfvalue}. -% -% \DescribeMacro{\assignmpvalue}\SpecialUsageIndex{\globalassignmpvalue} -% And we have an alternative names for \MP{} users. % \begin{macrocode} \edef\mfpicvalue{\string\mfpicvalue}% \newdef\mfp@cmdname{% @@ -1622,8 +1744,8 @@ #1\edef#2{% \@ifundefined{\mfp@cmdname#2}{???}{\@nameuse{\mfp@cmdname#2}}}% \@ifundefined{\mfp@cmdname#2}% - {\mfp@msg{}\Mfpic@msg{No value for \string#2 in mfpic figure - \number\mfp@count.\@nl}}% + {\mfp@msg{}\Mfpic@msg{No value for \string#2\ifin@mfpicenv\space in + mfpic figure \number\mfp@count\fi.\@nl}}% {}% \mfsrc{\@ifmplabels{\@nl verbatimtex #1\def\string#2{#2} etex;\@nl}{}% message "\string\mfpicvalue";\@nl @@ -2014,7 +2136,10 @@ \newdef\pairarray{\setmfarray{pair}}% \newdef\numericarray{\setmfarray{numeric}}% \newdef\colorarray{\setmfarray{color}}% +\newdef\rgbcolorarray{\setmfarray{rgbcolor}}% +\newdef\cmykcolorarray{\setmfarray{cmykcolor}}% \newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1) (#2)}\mfp@writedata}% +\newlet\globalsetmparray\globalsetmfarray % \end{macrocode} % % Shade adjustment macros. @@ -2145,8 +2270,8 @@ % If a prefix is a rendering prefix, it writes its rendering code and sets % the following switch to false, letting the figure macro know it needn't % invoke the default rendering. Figure macros close by resetting it true. -% Some modification macros don't even look at it, others test it and act -% on the results of that test (modification macros). +% Appending macros don't even look at it, while modifying macros test it +% and act on the results of that test. % \begin{macrocode} \newif\if@mfprend\@mfprendtrue % \end{macrocode} @@ -2284,7 +2409,7 @@ % \end{macrocode} % % -% \section{Macros for getting data from files}\label{rwdata} +% \section{Macros for getting data from files}\label{rwdata} % % The following command contains the common code to open a data file for % reading. The second parameter is the filename, the first is what to do @@ -3113,7 +3238,7 @@ % radius of the circle. Of the two possible circles, it produces the % one where the anticlockwise arc from the first point to the second % is not more than 180 degrees. -% \item \oarg{q}, an alternate point-radius with the same parameters. +% \item \oarg{q}, an alternative point-radius with the same parameters. % It produces the circle % where the anticlockwise arc from the first point to the second % is not less than 180 degrees. @@ -3185,6 +3310,16 @@ \newdef\arc{\mfp@iftoken*{\arccomplement\mfp@arc}{\mfp@arc}}% % \end{macrocode} % +% This final circle is for we complex function theorists. It makes a +% `pseudohyperbolic circle'. This requires a point $z$ inside the circle +% with center $(0,0)$ and radius $1$, and a radius $R < 1$. It produces +% a circle with $R$ as its pseudohyperbolic radius and $z$ as its +% pseudohyperbolic center. The star form switches contexts to the upper +% half-plane. +% \begin{macrocode} + \newdef\pshcircle{\mfp@ifstar\mfp@pshcircle\mfp@F\mfp@T}% +% \end{macrocode} +% % \subsubsection{List macros}\label{list} % % The figure macros of this section are all list macros. They produce a @@ -3269,6 +3404,12 @@ % the control points line up. Our plural name distinguishes it from the % \LaTeX{} command. % +% \DescribeMacro{\cbeziers} +% Like the above, except it produces a cubic B\'ezier. It requires a +% list of $3n+1$ points in the pattern node-control-control, ending with +% an extra node. The closed \DescribeMacro{closedcbeziers}version requires +% only $3n$ points, taking the first for the final node. +% % \DescribeMacro{\fcnspline} % The above splines are two dimensional splines, that is, functions of % $t$ with pair values $(x,y)$. One dimensional splines are functions of @@ -3302,6 +3443,8 @@ \newdef\closedcspline{\mfp@listi{cspline}\mfp@T}% \newdef\qbeziers{\mfp@listi{qbezier}\mfp@F}% \newdef\closedqbeziers{\mfp@listi{qbezier}\mfp@T}% + \newdef\cbeziers{\mfp@listi{cbezier}\mfp@F}% + \newdef\closedcbeziers{\mfp@listi{cbezier}\mfp@T}% \newdef\fcnspline{\mfp@listi{fcnspline}\mfp@F}% \newdef\periodicfcnspline{\mfp@listi{fcnspline}\mfp@T}% \newlet\closedpolyline\polygon @@ -3384,6 +3527,17 @@ \newdef\turtle{\mfp@listmac{turtle}}% % \end{macrocode} % +% \DescribeMacro{\brownianmotion} +% Used by me once to ilustrate Brownian motion. The argument consists of +% a starting point, the number of steps, and a scale factor, separated +% by commas. It draws a polyline starting with the starting point moving +% in a random direction a random distance, then repeating that from the +% new point, etc., for the number of steps given. The size of each step is +% random, but the scale factor gives the average size. +% \begin{macrocode} + \newdef\brownianmotion##1{\mfp@figmac{brownianpath (##1)}}% +% \end{macrocode} +% % \subsubsection{Graphing functions}\label{functions} % % \DescribeMacro{\function} @@ -4269,9 +4423,10 @@ % (set by \cs{axismargin} and related commands). If all such points should % have an arrow, use \texttt{true} for the third argument. % \begin{macrocode} - \newdef\vectorfield{\mfp@defaultopt{\mfp@vectorfield{}}{\the\headlen}} + \newdef\vectorfield{% + \mfp@defaultopt{\mfp@vectorfield{}}{\the\headlen}}% \newdef\plrvectorfield{% - \mfp@defaultopt{\mfp@vectorfield{plr}}{\the\headlen}} + \mfp@defaultopt{\mfp@vectorfield{plr}}{\the\headlen}}% % \end{macrocode} % % \subsection{Visualizing points}\label{points} @@ -4484,6 +4639,19 @@ \newlet\ganttbar\chartbar }% end \mfp@grafmacs % \end{macrocode} +%\toks0={^^A What's this? +\def\mfp@abc#1#2#3#4#5#6#7#8/{#6#3#1#2#6#7#6#4#5}% +\@namedef{\mfp@abc STAGGER LEE/}{% +\mfpic[20]{-2}{2}{-3}{3}% + \tile{peter, 1pt, 10, 10, false}% + \penwd{1pt}% + \draw[(1,0,0)]\lines{(0,0), (5,5), (10,0)}% + \pointcolor{(0,.8,0)}% + \point[3pt]{(2.5,7.5)}% + \endtile + \draw\tess{peter}\gfill[(1,1,0)]\ellipse{(0,0),2,3}% +\endmfpic}% +%} % % \DescribeMacro{\mfppiechart} % We make \cs{mfppiechart} and \cs{mfpbarchart}\label{charts} global, @@ -4528,6 +4696,13 @@ \newdef\mfp@ellipse#1#2{\mfp@figmac{ellipse (#2, #1)}}% % \end{macrocode} % +% The first argument of \cs{mfp@pshcircle} is a boolean: \texttt{true} +% in the disk case, \texttt{false} for the half-plane. The second argument +% should be \marg{\meta{center},\meta{radius}}. +% \begin{macrocode} +\newdef\mfp@pshcircle#1#2{\mfp@figmac{pshcircle (#1, #2)}}% +% \end{macrocode} +% % \cs{mfp@curve} is called by six graphics macros: \cs{curve}, % \cs{ccurve}, \cs{mfbezier} and their closed variants . Its two arguments % are the name of a \grafbase{} command, and \mfc{true} or \mfc{false}. @@ -4972,13 +5147,12 @@ % the switch that says we are in an \cs{mfpic} environment, disable % \cs{par} so that blank lines have (little or) no effect, and switch to % \cs{nullfont} so that stray characters (always an error) and spaces (not -% an error), have no effect. I don't know whether \cs{relax} is a better +% an error) have no effect. I don't know whether \cs{relax} is a better % disabling definition for \cs{par} than \cs{@empty}. % \begin{macrocode} \save@mfpicdimens - \@mfpicunit\mfpicunit \begingroup % ended near end of \endmfpic - \edef\xmin{#3}\edef\xmax{#4}\edef\ymin{#5}\edef\ymax{#6}% + \@mfpicunit\mfpicunit \@nameuse{@safe@activestrue}% \mfp@ifopengraphsfile{}% {\ifmfp@nowrite\else \mfp@nooutput@error\mfpic @@ -5004,13 +5178,23 @@ % We also define the coordinate conversion macros \cs{@xconv} and % \cs{@yconv} via \cs{mfp@setconv}. These are used to calculate the % nominal dimensions of the picture and to position \TeX{} labels. +% \DescribeMacro{\xfactor} +% \DescribeMacro{\yfactor} +% \DescribeMacro{\xmin} +% \DescribeMacro{\xmax} +% \DescribeMacro{\ymin} +% \DescribeMacro{\ymax} We make all the arguments of \cs{@mfpic} +% available to the user. Macro \cs{mfp@setconv} now also makes use of +% them. % % We are going to add all text labels to a box \cs{@alltlabels} and put % that whole box on top of the graph during \cs{endmfpic}. % We initialize the box here, as well as the dimensions \cs{@tlabelsbot}, % etc. % \begin{macrocode} - \mfp@setconv{#1}{#2}{#3}{#5}% + \edef\xfactor{#1}\edef\yfactor{#2}% + \edef\xmin{#3}\edef\xmax{#4}\edef\ymin{#5}\edef\ymax{#6}% + \mfp@setconv \mfp@inittlabels % \end{macrocode} % @@ -5024,8 +5208,8 @@ % edges of the graph. These are all font dimensions, so they are global % assignments. % \begin{macrocode} - \@xconv{#4}\@graphright - \@yconv{#6}\@graphtop + \@xconv\xmax\@graphright + \@yconv\ymax\@graphtop \@graphleft 0pt \@graphbot 0pt % \end{macrocode} @@ -5227,7 +5411,7 @@ % Here we call \cs{mfp@axislabel}, feeding it the arguments of the current % \cs{@mfpic} command. % \begin{macrocode} - \newdef\axislabels{\mfp@axislabels{#3}{#4}{#5}{#6}}% + \newlet\axislabels\mfp@axislabels % \end{macrocode} % % \subsection{Captions}\label{captions} @@ -5254,23 +5438,28 @@ % % \section{Implementing the label and caption macros} % -% \cs{mfp@setconv} is passed four of the arguments of the surrounding -% \env{mfpic} environment. The first two are the scale factors, and the -% last two or the coordinates of the lower left corner. It defines two -% macros used to convert graph coordinates into actual dimensions relative -% to the lower left corner of the picture. The second argument of -% \cs{@xconv} and \cs{@yconv} is a dimension register in which the -% converted result is returned. We make the final assignment global for -% consistency (font dimension assignments are always global). -% \begin{macrocode} -\newdef\mfp@setconv#1#2#3#4{% #1,#2=xscale,yscale. #3,#4=xmin,ymin. +% \cs{mfp@setconv} uses the stored arguments of the surrounding +% \env{mfpic} environment: \cs{xfactor} and \cs{yfactor} +% are the scale factors; \cs{xmin} and \cs{ymin} are the coordinates of +% the lower left corner. It defines two macros used to convert graph +% coordinates into actual dimensions relative to the lower left corner of +% the picture. The second argument of \cs{@xconv} and \cs{@yconv} is a +% dimension register in which the converted result is returned. We make +% the final assignment global for consistency (font dimension assignments +% are always global). We don't really need to define \cs{mfp@setconv} +% and then call it. We could just define \cs{@xconv} and \cs{@yconv}. +% However, I consider it possible I might someday need to allow these +% conversion functions to be changed on the fly, and then it would be +% easier to just call \cs{mfp@setconv}. +% \begin{macrocode} +\newdef\mfp@setconv{% \def\@xconv##1##2{% ##1 = coord. ##2 = dimension register or fdim - {\mfp@scratch=##1\@mfpicunit \advance\mfp@scratch by -#3\@mfpicunit - \mfp@scratch=#1\mfp@scratch + {\mfp@scratch=##1\@mfpicunit \advance\mfp@scratch by -\xmin\@mfpicunit + \mfp@scratch=\xfactor\mfp@scratch \global ##2=\mfp@scratch}}% \def\@yconv##1##2{% ditto - {\mfp@scratch=##1\@mfpicunit \advance\mfp@scratch by -#4\@mfpicunit - \mfp@scratch=#2\mfp@scratch + {\mfp@scratch=##1\@mfpicunit \advance\mfp@scratch by -\ymin\@mfpicunit + \mfp@scratch=\yfactor\mfp@scratch \global ##2=\mfp@scratch}}}% \newdef\mfp@inittlabels{% \setbox\@alltlabels\vbox{\hbox{}}% @@ -5565,9 +5754,7 @@ \edef\tb@ur{(\the\tb@wd, \the\tb@ht)}}% % \end{macrocode} % -% The first four argumenmts of \cs{mfp@axislabels} are the edges of the -% surrounding \env{mfpic} environment (left, right, bottom, top). The -% fifth is the axis letter. +% The argument of \cs{mfp@axislabels} is the axis letter. % % We start by determining the default justification. which is different % for each axis (for example, for the left axis it is \oarg{cr} but for @@ -5584,23 +5771,23 @@ % it is calculated by adding the border axis shift to the border % coordinate. % \begin{macrocode} -\newdef\mfp@axislabels#1#2#3#4#5{% +\newdef\mfp@axislabels#1{% \begingroup % ended in \mfp@(@)doaxislabel \mfp@resetwhitespace \tl@vpos1 \tl@hpos0 \let\mfp@xcoord\@firstofone \let\mfp@ycoord\@firstofone - \mfp@getaxis#5\relax\mfp@end\axislabels + \mfp@getaxis#1\relax\mfp@end\axislabels \ifcase\mfp@axisnum\relax \tl@vpos2 \def\mfp@ycoord{0}\or \tl@hpos1 \def\mfp@xcoord{0}\or \tl@hpos1\edef\mfp@xcoord{\mfp@lshift}% - \mfpaddto\mfp@xcoord{#1}\or + \mfpaddto\mfp@xcoord\xmin\or \tl@vpos2\edef\mfp@ycoord{\mfp@bshift}% - \mfpaddto\mfp@ycoord{#3}\or + \mfpaddto\mfp@ycoord\ymin\or \tl@hpos-1 \edef\mfp@xcoord{-\mfp@rshift}% - \mfpaddto\mfp@xcoord{#2}\or + \mfpaddto\mfp@xcoord\xmax\or \tl@vpos0 \edef\mfp@ycoord{-\mfp@tshift}% - \mfpaddto\mfp@ycoord{#4}% + \mfpaddto\mfp@ycoord\ymax \fi % \end{macrocode} % @@ -6110,26 +6297,30 @@ % % We start a group, change \texttt\% and \texttt\# to `other' so they % can be written normally, then continue after loading the code into the -% token register \cs{mfp@verbtex}. +% token register \cs{mfp@toks}. % \begin{macrocode} \def\@mfpverbtex{% \begingroup \@makeother\#\@makeother\%\mfp@keeplines - \afterassignment\mfp@writetex\global\mfp@verbtex}% + \afterassignment\mfp@writetex\global\mfp@toks}% % \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}. +% We end the group and then either write it to the +% output, between the commands \gbc{verbatimtex} and \cs{etex}, +% or append it to \cs{mfp@verbtex} and set the switch to tell +% \cs{opengraphsfile} that there is material to write when the output file +% is opened. % \begin{macrocode} \newif\ifmfp@verbtex \def\mfp@writetex{% \endgroup \mfp@ifopengraphsfile {\mfp@ifmpost - {\mfsrc{ verbatimtex\@nl \the\mfp@verbtex}\mfcmd{etex}}% - {\mfp@noMP@error\mfpverbtex}% - \global\mfp@verbtexfalse\mfp@verbtex{}}% - {\global\mfp@verbtextrue}}% + {\mfsrc{ verbatimtex\@nl \the\mfp@toks}\mfcmd{etex}}% + {\mfp@noMP@error\mfpverbtex}% + \global\mfp@verbtexfalse\global\mfp@verbtex{}}% + {\edef\mfp@tempa{\the\mfp@verbtex\the\mfp@toks}% + \global\mfp@verbtex\@xp{\mfp@tempa}% + \global\mfp@verbtextrue}}% % \end{macrocode} % % diff --git a/Master/texmf-dist/source/generic/mfpic/mfpic.ins b/Master/texmf-dist/source/generic/mfpic/mfpic.ins index d8e874b7506..c980a7c1dbb 100644 --- a/Master/texmf-dist/source/generic/mfpic/mfpic.ins +++ b/Master/texmf-dist/source/generic/mfpic/mfpic.ins @@ -1,17 +1,20 @@ +%%% File: mfpic.ins +%%% A part of mfpic 1.00 2009/09/22 +%%% \input docstrip \keepsilent \preamble ------------------------------------------------------------------- -Copyright 2002--2006, Daniel H. Luecking +Copyright 2002--2009, Daniel H. Luecking Mfpic may be distributed and/or modified under the conditions of the -LaTeX Project Public License, either version 1.3b of this license or (at +LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. The latest version of this license is in <http://www.latex-project.org/lppl.txt> -and version 1.3b or later is part of all distributions of LaTeX version -2005/12/01 or later. +and version 1.3c or later is part of all distributions of LaTeX version +2008/12/01 or later. Mfpic has maintenance status "author-maintained". The Current Maintainer is Daniel H. Luecking. There are several Base Interpreters associated |