diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkii/supp-mps.mkii')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkii/supp-mps.mkii | 2134 |
1 files changed, 2134 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkii/supp-mps.mkii b/Master/texmf-dist/tex/context/base/mkii/supp-mps.mkii new file mode 100644 index 00000000000..3991280e6d4 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkii/supp-mps.mkii @@ -0,0 +1,2134 @@ +%D \module +%D [ file=supp-mps, +%D version=1997.07.05, +%D title=\CONTEXT\ Support Macros, +%D subtitle=\METAPOST\ Inclusion, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Forget about generic modules \unknown\ ... + +\ifx \undefined \contextversion \endinput \fi + +%D \METAPOST\ is John Hobbys alternative for \METAFONT\ and +%D produces superior \POSTSCRIPT\ code. In this module we +%D integrate \METAPOST\ support int \CONTEXT. We offer two +%D tracks: +%D +%D \startitemize +%D \item generating \METAPOST\ code, running this program from +%D within \TEX\ using \type{\write18}, and importing the +%D result +%D \item generating \METAPOST\ code, processing the code +%D afterward, and importing the result in a second pass +%D \stopitemize +%D +%D The first approach uses a non standard \TEX\ feature, +%D implemented in Web2c. I'm not going to discuss the pros and +%D cons of running programs from within others, but all +%D arguments against this can be overcome by implementing a +%D \TEX\ worthy primitive: +%D +%D \starttyping +%D \excuteMetaPost filename +%D \stoptyping +%D +%D Ok then, let's start: + +\writestatus{loading}{ConTeXt Support Macros / MetaPost Inclusion} + +\unprotect + +\def\@@MPG{@MPG@} + +%D First we define a handy constant: + +\bgroup \catcode`\%=\@@other \xdef\letterpercent{\string%} \egroup + +% todo : sort out ^^M, \par and ; mess + +%D \macros +%D {everyMPgraphic} +%D +%D Because some graphics interact with \TEX\ (i.e.\ \CONTEXT), we +%D provide a hook for additional actions: \type {\everyMPgraphic}. + +\newtoks\everyMPgraphic \everyMPgraphic{\everyMPgraphic\emptytoks} + +%D \macros +%D {startMPgraphic} +%D +%D From within \TEX\ one can execute \METAPOST\ code by putting +%D it between the two commands +%D +%D \starttyping +%D \startMPgraphic +%D \stopMPgraphic +%D \stoptyping +%D +%D This is implemented as: + +\let\stopMPgraphic\relax + +\long\def\startMPgraphic#1\stopMPgraphic + {\startwritingMPgraphic + \writecheckedMPgraphic{#1}% % potential speedup: pass #1 as macro + \stopwritingMPgraphic} + +%D \macros +%D {startMPrun} +%D +%D If we just want to run \METAPOST\ code, that is, not to +%D explictly generate a figure in terms of \type{beginfig} and +%D \type{endfig}, we can use: +%D +%D \starttyping +%D \startMPgraphic +%D \stopMPgraphic +%D \stoptyping +%D +%D \starttyping +%D \startMPrun +%D \stopMPrun +%D \stoptyping +%D +%D The next booleans are for internal purposes only. + +% some day a bit more more clear: +% +% run directly/run afterwards/run external defined +% insert directly/insert whenever +% use object/don't use objects + +\newif\ifMPgraphics \MPgraphicstrue +\newif\ifMPrun \MPrunfalse +\newif\ifMPwrapper \MPwrappertrue + +\let\stopMPrun\relax + +\ifCONTEXT + + \long\def\dostartMPrun#1#2\stopMPrun + {\bgroup + \MPruntrue + \doifsomething{#1}{\def\MPgraphicfile{#1}}% + \startwritingMPgraphic + \writecheckedMPgraphic{#2}% + \stopwritingMPgraphic + \egroup} + + \def\startMPrun + {\dosinglegroupempty\dostartMPrun} + +\else + + \long\def\startMPrun#1\stopMPrun + {\MPruntrue + \startwritingMPgraphic + \writecheckedMPgraphic{#1}% + \stopwritingMPgraphic + \MPrunfalse} + +\fi + +%D \macros +%D {startwritingMPgraphic, +%D writeMPgraphic, +%D stopwritingMPgraphic} +%D +%D If the writing process is divided into more steps, one can +%D use the components of this macro directly. +%D +%D \starttyping +%D \startwritingMPgraphic +%D ... +%D \writeMPgraphic{...} +%D ... +%D \writeMPgraphic{...} +%D ... +%D \stopwritingMPgraphic +%D \stoptyping + +%D \macros +%D {ifrunMPgraphics,ifrunMPTEXgraphics,ifinsertMPgraphics} +%D +%D These macros look a bit more complicated that one would +%D expect at first sight. This is due to the two ways of +%D processing these graphics, mentioned in a previous +%D paragraph. Which method is used, the direct or indirect +%D one, depends on a boolean. + +\newif\ifrunMPgraphics \runMPgraphicsfalse +\newif\ifrunMPTEXgraphics \runMPTEXgraphicsfalse +\newif\ifinsertMPgraphics \insertMPgraphicstrue + +%D If set to true, one can do with a single pass, else one must +%D process the \METAPOST\ file \type{mpgraph} between two +%D succesive \TEX\ runs. + +\ifx\MPgraphicfile\undefined + +\def\MPgraphicfile{mp\ifMPrun run\else graph\fi} +\def\MPruntimefile{mprun} + +\fi + +%D \macros +%D {MPgraphic} +%D +%D When we run \METAPOST\ from within \TEX, each graphic is +%D processed at once, which means that we reuse this file many +%D times. When however the execution is delayed, all graphics +%D are saved in a separate figure. The current graphic is +%D characterized bij a \COUNTER. This counter is available +%D in \type{\MPgraphic}. + +\newcount\nofMPgraphics +\newcount\currentMPgraphic + +\def\MPgraphic{0} + +% %D \macros +% %D {ifreuseMPgraphics} +% %D +% %D If one want to reuse grapics, one can save much redundant +% %D run time by setting the next switch to true. +% +% \newif\ifreuseMPgraphics \reuseMPgraphicstrue + +%D The three macros responsible for writing the graphic +%D implement both schemes. + +%D \macros +%D {MPinclusions, startMPinclusions, MPinitializations} +%D +%D One can include for instance common input commands by +%D passing them to \type{\MPinclusions}: +%D +%D \starttyping +%D \startMPinclusions +%D input mp-mine ; +%D \stopMPinclusions +%D \stoptyping +%D +%D \starttyping +%D \MPinclusions{input mp-mine} +%D \stoptyping +%D +%D These commands reset their content each time. You can append +%D code as follows: +%D +%D \starttyping +%D \startMPinclusions[+] +%D input mp-mine ; +%D \stopMPinclusions +%D \stoptyping +%D +%D The token register \type {\MPinitializations} is expanded +%D before all other inclusions, the extensions are expanded +%D only once per run. + +%D The next hack prevents too long lines: + +\long\def\runtimeobeyMPlines + {\catcode35=11\relax % goodie + \ifx\rawcharacter\undefined + \let\obeyedline\space + \else + \obeylines + \ifx\outputnewlinechar\undefined + \edef\obeyedline{\rawcharacter{\endlinechar}}% + \else + \let\obeyedline\outputnewlinechar + \fi + \fi} + +\long\def\obeyMPlines % anyhow, we end up with ^^M's in the input + {\obeylines + \let\obeyedline\relax} % delay expansion + +\ifx\everydump\undefined + % maybe we're not using context +\else + \appendtoks + \let\obeyMPlines\runtimeobeyMPlines + \to \everydump +\fi + +%D We use two distinguished token registers: + +\newtoks \MPextensions % once per run (can be multiple graphics) +\newtoks \MPinitializations % each graphic + +\let\stopMPextensions \relax % so that we can use it in \expanded +\let\stopMPinitializations\relax % so that we can use it in \expanded +\let\stopMPinclusions \relax % so that we can use it in \expanded + +\def\startMPextensions % no text checking done here ! + {\begingroup + \obeyMPlines + \dostartMPextensions} + +\def\dostartMPextensions#1\stopMPextensions + {\endgroup + \MPextensions\expandafter{\the\MPextensions#1}} + +\def\startMPinitializations % no text checking done here ! + {\begingroup + \obeyMPlines + \dostartMPinitializations} + +\def\dostartMPinitializations#1\stopMPinitializations + {\endgroup + \MPinitializations\expandafter{\the\MPinitializations#1}} + +\def\startMPinclusions + {\begingroup + \dosingleempty\dostartMPinclusions} + +\long\def\dostartMPinclusions + {\obeyMPlines + \dodostartMPinclusions} + +\long\def\dodostartMPinclusions[#1]#2\stopMPinclusions % document wide + {\endgroup + \doifelse{#1}{+} + {\@EA\long\@EA\def\@EA\theMPinclusions\@EA + {\theMPinclusions + \writeMPgraphic{#2}}} + {\long\def\theMPinclusions + {% \expanded ! +% \@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPextensions;}}% new + \writeMPgraphic{#2}}}} + +\def\MPinclusions + {\dosingleempty\doMPinclusions} + +\long\def\doMPinclusions[#1]#2% + {\startMPinclusions[#1]#2\stopMPinclusions} + +\def\theMPextensions + {\@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPextensions;}}} + +\def\theMPinitializations + {\@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPinitializations;}}} + +\startMPinclusions \stopMPinclusions + +%D \macros +%D {iflongMPlines} +%D +%D When grabbing a graphic deifnition, newlines are turned +%D into spaces. By default we split the graphic definition +%D at the colon, but long lines are still possible by +%D setting the next boolean to true. + +\newwrite\MPwrite +\newwrite\MPstaticwrite + +\newif\iflongMPlines \longMPlinestrue % we now have \obeyMPlines + +\ifx \overlaywidth \undefined \def \overlaywidth {4cm} \fi +\ifx \overlayheight \undefined \def \overlayheight {3cm} \fi +\ifx \overlaylinewidth \undefined \def \overlaylinewidth {0pt} \fi + +\def\presetMPdefinitions + {\edef\overlaywidth {\overlaywidth \space}% + \edef\overlayheight {\overlayheight \space}% + \edef\overlaylinewidth {\overlaylinewidth\space}% + \edef\currentwidth {\the\hsize \space}% + \edef\currentheight {\the\vsize \space}} + +%D The \type {;} aware method (the \type {\else} branch) also +%D takes care of \type {btex}||\type {etex}, \type +%D {verbatimtex}||\type {etex}. The space after \type {tex} +%D is essential, since it protects \type {text}. + +\newif\ifMPTEXgraphic + +\let\bufferedMPgraphicsline\empty + +\appendtoks + \globallet\bufferedMPgraphicsline\empty +\to \everyMPgraphic + +\chardef\MPgraphicsscanmode\plustwo % 0=no scanning, 1=simple scanning, 2=less simple, 3=even less + +% the next fails with \chardef\MPgraphicsscanmode\plusone +% +% \startMPextensions +% gp_num_points_with_tex := 3 ; +% \stopMPextensions + +\def\writeMPgraphic % no big #1 passing here + {\iflongMPlines + \ifMPTEXgraphic + \ifcase\MPgraphicsscanmode + \let\next\writeMPgraphiclongR + \else + \let\next\writeMPgraphiclongT + \fi + \else + \let\next\writeMPgraphiclongN + \fi + \else + \ifMPTEXgraphic + \ifcase\MPgraphicsscanmode + \let\next\writeMPgraphicshortN % we could \let \writeMPgraphicshortR\writeMPgraphicshortN + \else + \let\next\writeMPgraphicshortT + \fi + \else + \let\next\writeMPgraphicshortN + \fi + \fi + \next} + +\appendtoks \obeyMPlines \to \everyMPgraphic % more efficient than in each following grouped write + +\long\def\writeMPgraphiclongR#1% fast, no scanning + {\bgroup + \let\par\space + \immediate\write\MPwrite{#1}% + \egroup} + +\long\def\writeMPgraphiclongT#1% + {\bgroup + \let\par\space + \longMPflushT#1\empty\par\relax\par + \egroup} + +\long\def\writeMPgraphicshortT#1% + {\bgroup + \let\par\space + \shortMPflushT#1\empty;\relax;% + \egroup} + +\long\def\longMPflushT#1#2\par + {\ifx#1\relax \else + \dowriteMPgraphicline#1#2tex \relax etex\MPend + \expandafter\longMPflushT + \fi} + +\long\def\shortMPflushT#1#2;% + {\ifx#1\relax \else + \dowriteMPgraphicline#1#2tex \relax etex\MPend + \expandafter\shortMPflushT + \fi} + +\long\def\writeMPgraphiclongN#1% + {\bgroup + \let\par\space + \longMPflushN#1\empty\par\relax\par + \egroup} + +\long\def\writeMPgraphicshortN#1% + {\bgroup + \let\par\space + \shortMPflushN#1\empty;\relax;% + \egroup} + +\long\def\longMPflushN#1#2\par + {\ifx#1\relax \else + \nowriteMPgraphicline#1#2\MPend + \expandafter\longMPflushN + \fi} + +\long\def\shortMPflushN#1#2;% + {\ifx#1\relax \else + \nowriteMPgraphicline#1#2\MPend + \expandafter\shortMPflushN + \fi} + +\def\dowriteMPgraphicline{\futurelet\next\dodowriteMPgraphicline} +\def\nowriteMPgraphicline{\futurelet\next\nonowriteMPgraphicline} + +%D Will move (check if next is needed): + +\long\def\nonowriteMPgraphicline#1\MPend + {\ifx\next\empty\else\ifx\next\relax\else + \bgroup + \let\par\space + \iflongMPlines + %\immediate\write\MPwrite{#1;}% oeps, ; invalid + \immediate\write\MPwrite{#1}% + \else + \long\edef\ascii{#1}% + \expandafter\flushMPgraphicline\ascii\empty;\relax;% + \fi + \egroup + \fi\fi} + +%D A first version: +%D +%D \starttyping +%D \long\def\dodowriteMPgraphicline#1tex #2#3etex#4\MPend% +%D {\ifx\next\empty\else\ifx\next\relax\else +%D \bgroup +%D \let\par=\space +%D \ifx#2\relax +%D \immediate\write\MPwrite{#1;}% +%D \egroup +%D \else +%D \global\MPTEXgraphictrue +%D \convertargument#2#3\to\ascii +%D \immediate\write\MPwrite{#1tex \ascii etex}% +%D \egroup +%D \dowriteMPgraphicline#4tex \relax etex\MPend +%D \fi +%D \fi\fi} +%D \stoptyping + +%D The next alternative also handles inclusions well. + +\newtoks \everyMPTEXgraphic + +\newif\ifforceMPTEXgraphic + +%D Before we supported the graph module, we had: +%D +%D \starttyping +%D \convertargument etex\to\MPasciiB +%D \convertargument textext\to\MPasciiC % geen "text" +%D \convertargument graphictext\to\MPasciiD % geen "text" +%D +%D \long\def\checkMPTEXgraphic#1% +%D {\ifforceMPTEXgraphic +%D \global\MPTEXgraphictrue +%D \else +%D \expandafter\convertargument#1\to\MPasciia +%D \doifstringinstringelse\MPasciiB\MPasciia{\global\MPTEXgraphictrue} +%D {\doifstringinstringelse\MPasciiC\MPasciia{\global\MPTEXgraphictrue} +%D {\doifstringinstringelse\MPasciiD\MPasciia{\global\MPTEXgraphictrue} +%D {\global\MPTEXgraphicfalse}}}% +%D \fi} +%D \stoptyping +%D +%D The next alternative permits extensions in other modules +%D without the need to know the details of testing. + +\newtoks\MPTEXgraphicchecks + +\long\def\writecheckedMPgraphic#1% + {\ifforceMPTEXgraphic + \global\MPTEXgraphictrue + \else + \global\MPTEXgraphicfalse + \edef\ascii{#1}\convertcommand\ascii\to\MPascii + \the\MPTEXgraphicchecks\relax % \relax is end condition! + \fi + \flushMPTEXgraphic % verbatimtex etc + \writeMPgraphic{#1}} % potential optimization: pass \ascii + +%D We could have used a kind of array approach using a +%D counter appended to \type {MPascii}, but this is an +%D as efficient alternative. (The uglyness comes from +%D expanding after the string \type {#1}). + +\let\MPTEXchecklist\empty + +\def\forceMPTEXcheck#1% + {\addtocommalist{#1}\MPTEXchecklist + \expanded{\convertargument#1\noexpand\to + \@EA\noexpand\csname MPascii#1\endcsname}% + \@EA\appendtoks + \@EA\doifincsnameelse\csname MPascii#1\endcsname\MPascii + {\global\MPTEXgraphictrue\gobbleuntil\relax}\donothing + \to \MPTEXgraphicchecks} + +\forceMPTEXcheck{etex} +\forceMPTEXcheck{textext} +\forceMPTEXcheck{graphictext} + +%D \starttyping +%D \forceMPTEXgraphictrue +%D +%D \forceMPTEXcheck{lintext} +%D \forceMPTEXcheck{logtext} +%D +%D \startMPcode +%D draw hlintext.lft(0, 20, 5, 20cm, "@3e") ; +%D draw vlogtext.bot(0, 10, 9, 10cm, "@3e") ; +%D \stopMPcode +%D \stoptyping + +%D A goodie for Mojca (the gnuplot wizzard): +%D +%D \starttyping +%D \startMPcode +%D draw fullcircle scaled 4cm ; +%D draw \textext{$\sqrt{\frac{3}{2}^3}$} ; +%D \stopMPcode +%D \stoptyping + +\long\def\textext#1{\normalunexpanded{textext("#1")}} % or \detokenize + +\def\flushMPTEXgraphic + {\ifMPTEXgraphic + \immediate\write\MPwrite{verbatimtex \the\everyMPTEXgraphic\space etex;}% + \fi} + +\long\def\flushMPgraphicline#1#2;% + {\ifx#1\relax \else + \immediate\write\MPwrite{#1#2;}% + \expandafter\flushMPgraphicline + \fi} + +% the next one fails on btex \vbox {\hbox .. leading to \vbox \hbox +% +% \long\def\dodowriteMPgraphicline#1tex #2#3etex#4\MPend +% {\ifx\next\empty\else\ifx\next\relax\else +% \bgroup +% \let\par\space +% \ifx#2\relax +% \iflongMPlines +% \immediate\write\MPwrite{#1;}% +% \else +% \edef\ascii{#1}% +% \expandafter\flushMPgraphicline\ascii\empty;\relax;% +% \fi +% \egroup +% \else +% \convertargument#2#3\to\ascii +% \immediate\write\MPwrite{#1tex \ascii etex}% +% \egroup +% \dowriteMPgraphicline#4tex \relax etex\MPend +% \fi +% \fi\fi} +% +% so we need a two step approach + +% \long\def\dodowriteMPgraphicline#1tex % +% {\doifnextcharelse\relax +% {\nododowriteMPgraphicline{#1}} +% {\redodowriteMPgraphicline{#1}}} +% +% better and faster + +% \long\def\dodowriteMPgraphicline#1tex #2% +% {\ifx#2\relax +% \expandafter\nododowriteMPgraphicline +% \else +% \expandafter\redodowriteMPgraphicline +% \fi{#1} #2} +% +% \long\def\redodowriteMPgraphicline#1#2etex#3\MPend +% {\ifx\next\empty\else\ifx\next\relax\else +% \bgroup +% \let\par\space +% \convertargument#2\to\ascii +% \immediate\write\MPwrite{#1tex \ascii etex}% +% \egroup +% \dowriteMPgraphicline#3tex \relax etex\MPend +% \fi\fi} +% +% \long\def\nododowriteMPgraphicline#1#2\MPend +% {\ifx\next\empty\else\ifx\next\relax\else +% \bgroup +% \let\par\space +% \iflongMPlines +% \immediate\write\MPwrite{#1;}% +% \else +% \long\edef\ascii{#1}% +% \expandafter\flushMPgraphicline\ascii\empty;\relax;% +% \fi +% \egroup +% \fi\fi} + +% extra scanning + +\long\def\dodowriteMPgraphicline#1tex #2% kind of ok + {\ifx#2\relax + \expandafter\nododowriteMPgraphicline + \else + \ifcase\MPgraphicsscanmode + % can't happen + \or + \@EAEAEA\redodowriteMPgraphicline + \or + \doifinstringelse{b$} {#1$}{\@EAEAEA\redodowriteMPgraphicline}% + {\doifinstringelse{verbatim$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}% + {\@EAEAEA\dododowriteMPgraphicline}}% + \else + \doifinstringelse { b$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}% + {\doifinstringelse {(b$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}% + {\doifinstringelse {=b$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}% + {\doifinstringelse{verbatim$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}% + {\@EAEAEA\dododowriteMPgraphicline}}}}% + \fi + \fi{#1} #2} + +\def\dododowriteMPgraphicline#1#2\MPend + {\doifsomething{#1}{\xdef\bufferedMPgraphicsline{\bufferedMPgraphicsline#1tex }}% + \dowriteMPgraphicline#2tex \relax etex\MPend} + +\long\def\redodowriteMPgraphicline#1#2etex#3\MPend + {\ifx\next\empty + \else\ifx\next\relax + \else + \bgroup + \let\par\space + \convertargument#2\to\ascii + \immediate\write\MPwrite{\bufferedMPgraphicsline#1tex \ascii etex}% + \globallet\bufferedMPgraphicsline\empty + \egroup + \dowriteMPgraphicline#3tex \relax etex\MPend + \fi\fi} + +\long\def\nododowriteMPgraphicline#1#2\MPend + {\ifx\next\empty + \else\ifx\next\relax + \else + \bgroup + \let\par\space + \iflongMPlines + \immediate\write\MPwrite{\bufferedMPgraphicsline#1;}% + \globallet\bufferedMPgraphicsline\empty + \else + \long\edef\ascii{\bufferedMPgraphicsline#1}% + \expandafter\flushMPgraphicline\ascii\empty;\relax;% + \fi + \egroup + \fi\fi} + +%D This stripper is suboptimal in the sense that more +%D \type{;}'s are output than feasible. Anyhow, \METAPOST\ +%D can handle this and users may consider it being a sort +%D of error prevention bonus. + +\ifx\blabelgroup\undefined + + \let\blabelgroup\bgroup + \let\elabelgroup\egroup + +\fi + +\newconditional\firstMPgraphic \settrue\firstMPgraphic + +\appendtoks + \let \# \letterhash + \let \_ \letterunderscore + \let \& \letterampersand + \let \{ \letteropenbrace + \let \} \letterclosebrace +\to \everyMPgraphic + +%D Not the best place but we need to make sure that no funny +%D active characters creep in. Some day we will move this code. + +\ifx\disablediscretionaries\undefined + \let\disablediscretionaries\relax +\fi + +\appendtoks + \disablediscretionaries +\to \everyMPgraphic + +\def\writeMPgraph + {\immediate\write\MPwrite{mpgraph:=\the\currentMPgraphic;}} + +\def\startwritingMPgraphic + {\blabelgroup + \global\advance\nofMPgraphics \plusone + \ifMPrun \else + \allocateMPslot\currentMPgraphic + \fi + \enableincludeMPgraphics + \xdef\MPgraphic{\the\currentMPgraphic}% + \the\everyMPgraphic + \presetMPdefinitions % moved to here from \writeMPgraphic + \ifrunMPgraphics + \openMPgraphicfile1{runtime}% + % no reset here ! + \theMPextensions + \theMPinclusions + \else + \openMPgraphicfile0{collected}% + % reset here ! global added (due to adding \blabelgroup) + \theMPextensions + \theMPinclusions + \global\let\theMPextensions\relax + \global\let\theMPinclusions\relax + \fi + \theMPinitializations % always + \ifMPrun + \else + \ifMPwrapper + \immediate\write\MPwrite{let mprunend = end ;}% + \immediate\write\MPwrite{beginfig(\the\currentMPgraphic);}% + \fi + \fi + \globallet\flushMPgraphics\closeMPgraphicfiles % \dodostopwritingMPgraphic + \globallet\stopwritingMPgraphic\dostopwritingMPgraphic} + +\let\MPgraphicfiles\empty + +\let\MPinputtranslation\empty + +\def\openMPgraphicfile#1#2% #1=alwaysopen #2=message + {\@EA\ifx\csname\@@MPG\@@MPG\MPgraphicfile\endcsname\relax + \donetrue + % \@EA\newwrite\csname\@@MPG\@@MPG\MPgraphicfile\endcsname + % for the sake of plain usage + \@EA\@EA\csname newwrite\endcsname\csname\@@MPG\@@MPG\MPgraphicfile\endcsname + \doglobal\addtocommalist\MPgraphicfile\MPgraphicfiles + \else + \ifcase#1\relax\donefalse\else\donetrue\fi + \fi + \@EA\let\@EA\MPwrite\csname\@@MPG\@@MPG\MPgraphicfile\endcsname + \ifdone + \immediate\openout\MPwrite\MPgraphicfile.mp\relax + \ifx\MPinputtranslation\empty\else + \immediate\write\MPwrite{\MPinputtranslation}% + \immediate\write\MPwrite{verbatimtex \MPinputtranslation etex ;}% + \fi + \immediate\write\MPwrite{\letterpercent\space #2 graphics of job "\jobname"}% + \writeMPgraph + \setMPrandomseed + \fi} + +\def\dostopwritingMPgraphic + {\ifMPrun \else + \ifMPwrapper + \immediate\write\MPwrite{endfig;}% + \immediate\write\MPwrite{let end=mprunend;}% + \fi + \fi + \ifrunMPgraphics + \dodostopwritingMPgraphic + \fi + \elabelgroup} + +\def\dodostopwritingMPgraphic + {\ifnum\currentMPgraphic>\zerocount + \donetrue + \else\ifMPrun + \donetrue + \else + \donefalse + \fi\fi + \ifdone + \finishwritingMPgraphics + \runMPgraphic\MPgraphicfile + \fi + \globallet\flushMPgraphics\relax} + +\def\finishwritingMPgraphics + {\ifMPwrapper\immediate\write\MPwrite{end.}\fi + \immediate\closeout\MPwrite} + +\def\closeMPgraphicfiles + {\ifrunMPgraphics \else \ifx\MPgraphicsfiles\empty\else + \def\docommand##1% + {\message{[flush and process ##1.mp afterwards]}% + \@EA\let\@EA\MPwrite\csname\@@MPG\@@MPG##1\endcsname + \finishwritingMPgraphics}% + \processcommacommand[\MPgraphicfiles]\docommand + \fi \fi} + +\let\stopwritingMPgraphic\relax +\let\flushMPgraphics \relax + +%D By default each graphic gets its own slot (number). Later +%D on we will define a recycle bin. + +\def \allocateMPslot#1{\global\advance#1\plusone} +\def\deallocateMPslot#1{} + +%D \macros +%D {translateMPinput} +%D +%D For my polish friends: +%D +%D \starttyping +%D % translate=il2-pl +%D +%D \translateMPinput{il2-pl} +%D +%D \startMPenvironment[global] +%D \setupbodyfont[plr] +%D \stopMPenvironment +%D +%D \TeX: ± ¶ +%D +%D \startMPcode +%D draw btex MetaPost: ± ¶ etex scaled 5 ; +%D \stopMPcode +%D \stoptyping + +\def\translateMPinput#1% +% {\xdef\MPinputtranslation{\letterpercent -translate-file=#1\space}} % at some point +% {\xdef\MPinputtranslation{\letterpercent --8bit}} % some time later + {\globallet\MPinputtranslation\empty} % the new mpost is 8 bit clean + +%D \macros +%D {setMPrandomseed} +%D +%D Did you notice the random seed initialization? This is +%D needed because \METAPOST\ has a rather poor initialization, +%D which in some implementations depends on the time in +%D minutes. So, in quick successive runs, random is not that +%D random. + +\newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default + +\def\setMPrandomseed + {\ifsetMPrandomseed \ifx\getrandomnumber\undefined \else + \getrandomnumber\localMPseed\zerocount{4095}% + \writeMPgraphic{randomseed:=\localMPseed;}% + \fi\fi} + +%D This feature has become optional. Thanks to Fabrice Popineau, +%D \METAPOST\ can now do a far better job! + +%D \macros +%D {flushMPgraphics} +%D +%D When we use the indirect method, all graphics are saved in +%D one file. This means that we cannot close this file after +%D every \type{\stopMPgraphic}. Therefore we need to say: +%D +%D \starttyping +%D \flushMPgraphics +%D \stoptyping +%D +%D else the file is closed without writing the \METAPOST\ end +%D command. One will notice this fast enough when in indirect +%D mode. When using the direct mode this command is not +%D implicitly needed, but ommiting it makes files less +%D portable. + +%D \macros +%D {loadcurrentMPgraphic, +%D placeMPgraphic} +%D +%D Once defined, we can call for this graphic by saying: +%D +%D \starttyping +%D \loadcurrentMPgraphic{setups} +%D \placeMPgraphic +%D \stoptyping +%D +%D This two stage insert permits some intermediate manipulations +%D of the graphic, which temporary saved in: + +\newbox\MPgraphicbox + +\def\doloadcurrentMPgraphic#1% + {\loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{#1}% + \deallocateMPslot\currentMPgraphic} % added + +\ifCONTEXT + \def\loadcurrentMPgraphic{\dosinglegroupempty\doloadcurrentMPgraphic} +\else + \let\loadcurrentMPgraphic\doloadcurrentMPgraphic +\fi + +\def\loadMPgraphic#1#2% + {\setbox\MPgraphicbox\hbox{\ifinsertMPgraphics\insertMPfile{#1}{#2}\fi}} + +\def\MPllx{0} +\def\MPlly{0} + +% \def\placeMPgraphic% +% {\ifMPshiftdrawing +% \hbox{\hskip\MPllx\onebasepoint\raise\MPlly\onebasepoint\box\MPgraphicbox}% +% \else +% \box\MPgraphicbox +% \fi} +% +% experimental: + +\def\placeMPgraphic + {\ifMPshiftdrawing + \edef\next + {\wd\MPgraphicbox\the\wd\MPgraphicbox + \ht\MPgraphicbox\the\ht\MPgraphicbox + \dp\MPgraphicbox\the\dp\MPgraphicbox}% + \setbox\MPgraphicbox\hbox + {\hskip\MPllx\onebasepoint\raise\MPlly\onebasepoint\box\MPgraphicbox}% + \next + \fi + \box\MPgraphicbox} + +%D \macros +%D {startreusableMPgraphic, reuseMPgraphic, useMPbox} +%D +%D One can use the next macro for defining graphics that are +%D to be reused. When the next switch is set, graphics are +%D cached. + +\newif\ifuseMPbox \useMPboxtrue + +%D We assume that one can set objects: +%D +%D \starttyping +%D \def\douseMPbox#1% +%D {\setobject{MP}{#1}\vbox +%D {\forgetall +%D \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}% +%D \deallocateMPslot\currentMPgraphic +%D \placeMPgraphic}% +%D \setgvalue{#1}{\getobject{MP}{#1}}} +%D \stoptyping +%D +%D More safe is to use a number for \type {{MP}{#1}} which permits +%D redefinition. We also saves the boundingbox. This helps positioning +%D reused graphics in layers. + +\newcount\MPobjectcounter + +\ifx\getobject\undefined \def\setobject#1#2{\setbox\scratchbox} \fi % makes dep check happy +\ifx\getobject\undefined \def\getobject#1#2{\box \scratchbox} \fi % makes dep check happy + +\def\douseMPbox#1% + {\global\advance\MPobjectcounter\plusone + \setobject{MP}{\number\MPobjectcounter}\vbox + {\forgetall + \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}% + \deallocateMPslot\currentMPgraphic + \placeMPgraphic}% + \setxvalue{#1}% + {\noexpand\dodouseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}} + +\def\dodouseMPbox#1#2#3#4#5% space delimiting would save some tokens + {\xdef\MPllx{#2}% but it's not worth the effort and looks + \xdef\MPlly{#3}% ugly as well + \xdef\MPurx{#4}% + \xdef\MPury{#5}% + \getobject{MP}{#1}} + +\def\nouseMPbox#1% + {\setxvalue{#1}% + {\noexpand\forgetall + \noexpand\loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}% + \noexpand\deallocateMPslot{\currentMPgraphic}% + \noexpand\placeMPgraphic}} + +\ifCONTEXT \else \let\douseMPbox\nouseMPbox \fi +\ifCONTEXT \else \let\doifobjectssupportedelse\relax \fi + +\long\def\handlereusableMPgraphic#1#2% + {\blabelgroup + \enableincludeMPgraphics + \startMPgraphic#2\stopMPgraphic + \doifobjectssupportedelse\donothing\useMPboxfalse + \ifuseMPbox + \expandafter \douseMPbox + \else + \expandafter \nouseMPbox + \fi {\@@MPG#1}% + \getvalue{\@@MPG#1}% + \elabelgroup} + +% \long\def\startreusableMPgraphic#1#2\stopreusableMPgraphic +% {\ifundefined{\@@MPG#1}% +% \long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}}% +% \fi} + +\long\def\dostartreusableMPgraphic#1#2\stopreusableMPgraphic + {\blabelgroup + \long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}}% + \elabelgroup} + +\def\reuseMPgraphic#1% + {\blabelgroup + \getvalue{\@@MPG#1}% + \elabelgroup} + +\let\stopreusableMPgraphic \relax % so that we can use it in \expanded + +%D \macros +%D {startuseMPgraphic,useMPgraphic} +%D +%D The every||time||it's||used original one is defined below. +%D This one makes sense when the graphic uses random numbers. +%D +%D We can run (process graphic) without including them at that +%D particular place. Therefore we explicitly disable +%D inclusions (resulting in an dummy figure) when we are in MP +%D run mode (see mfun-004 for an example, we process an +%D example buffer which produced graphics). + +\long\def\handleuseMPgraphic#1#2% + {\bgroup + \enableincludeMPgraphics + \startMPgraphic#2\stopMPgraphic + \ifMPrun \else + \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}% + \placeMPgraphic + \fi + \deallocateMPslot\currentMPgraphic + \egroup} + +\long\def\startuseMPgraphic + {\blabelgroup + \obeyMPlines + \dostartuseMPgraphic} + +\long\def\dostartuseMPgraphic#1#2\stopuseMPgraphic + {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}}% + \elabelgroup} + +\long\def\startusableMPgraphic + {\blabelgroup + \obeyMPlines + \dostartusableMPgraphic} + +\long\def\dostartusableMPgraphic#1#2\stopusableMPgraphic + {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}}% + \elabelgroup} + +\let\useMPgraphic\reuseMPgraphic + +\let\stopuseMPgraphic \relax % so that we can use it in \expanded +\let\stopusableMPgraphic \relax % so that we can use it in \expanded + +%D \macros +%D {doifMPgraphicelse} +%D +%D For (mainly internal) purposes we provide a test macro. + +% \def\doifMPgraphicelse#1% +% {\doifdefinedelse{\@@MPG#1}} + +\def\doifMPgraphicelse#1% + {\blabelgroup + \doifdefinedelse{\@@MPG#1}% + {\elabelgroup\firstoftwoarguments} + {\elabelgroup\secondoftwoarguments}} + +%D \macros +%D {includeMPgraphic} +%D +%D In a graphic one can call up another (predefined one) +%D like: +%D +%D \starttyping +%D \startuseMPgraphic{a} +%D fill fullcircle scaled 100 ; +%D \stopuseMPgraphic +%D +%D \startuseMPgraphic{b} +%D \includeMPgraphic{a} +%D fill fullsquare rotated 45 scaled 50 withcolor red ; +%D \stopuseMPgraphic +%D +%D \useMPgraphic{b} +%D \stoptyping + +\def\includeMPgraphic#1% + {\executeifdefined{\@@MPG#1};} % ; if not found + +\def\enableincludeMPgraphics + {\let\handleuseMPgraphic \secondoftwoarguments + \let\handlereusableMPgraphic\secondoftwoarguments} + +%D We didn't yet define the macro responsible for processing +%D the graphic from within \TEX. + +\def\runMPgraphic#1% + {\ifrunMPgraphics + \executeMETAPOST{#1}% + \else + % \message{[flush and process \MPgraphicfile.mp afterwards]}% + \fi} + +%D \macros +%D {useMETAFUNformat} +%D +%D For faster running, one can generate a format, saying +%D +%D \starttyping +%D mpost -ini context +%D \stoptyping +%D +%D (The resulting \type {mem} file should be moved to the +%D right location. Watch out for misatching \type {progname} +%D directives, since they can clutter memory. + +\newif\ifuseMETAFUNformat + +%D \macros +%D {executeMetaPost, executeMETAPOST, executesystemcommand} +%D +%D With \type{\executeMETAPOST} being defined as: + +\ifx\undefined\executeMETAPOST + \def\executeMETAPOST#1{\executesystemcommand{\executeMetaPost{#1}}} +\fi + +%D There are two system dependant definitions: + +\ifx\undefined\executesystemcommand + \def\executesystemcommand#1{\immediate\write18{#1}} +\fi + +\ifx\TEXEXECcommand \undefined \def\TEXEXECcommand{texmfstart texexec} \fi + +\ifx\undefined\executeMetaPost + + \ifx\undefined\interactionmode \chardef\interactionmode=255 \fi + + \def\MPOSTbatchswitch {-interaction=batchmode} % was -int, but newer mpost does not support partial flags + \def\MPOSTnonstopswitch {-interaction=nonstopmode} % was -int, but newer mpost does not support partial flags + \def\MPOSTformatswitch {-progname=metafun -mem=} + \def\MPOSTdriver {dvips} + + \def\executeMPOST#1% direct call + {mpost + \ifcase\interactionmode\MPOSTbatchswitch\or\MPOSTnonstopswitch\fi + \space\ifuseMETAFUNformat \MPOSTformatswitch metafun \fi #1} + + \def\executeMPTEX#1% slower, due to nested texexec call + {\TEXEXECcommand\space + --batch \ifcase\interactionmode --logfile='mptex.log' \fi + --output=\MPOSTdriver\space + \ifuseMETAFUNformat --mpformat=metafun \fi --mptex --nomp --once #1} + + \def\executeMetaPost + {\ifrunMPTEXgraphics + \ifMPTEXgraphic + \@EAEAEA\executeMPTEX + \else + \@EAEAEA\executeMPOST + \fi + \else + \@EA\executeMPOST + \fi} + +\fi + +%D The batchmode and nonstopmode (introduced in 2003 for +%D Patrick Gundlach) switches may differ per binary and are +%D supported by \TEXEXEC. + +%D \macros +%D {insertMPfile} +%D +%D One can define this command in advance or redefine it after +%D loading this module. The same goes for the forward +%D reference to the figure loading macro: + +\ifx\undefined\insertMPfile + + \def\insertMPfile#1#2% + {\ifx\undefined\externalfigure + \message{[insert file #1 here]}% + \else + \externalfigure + [#1] + [\c!type=\c!mps,\c!object=\v!no, + \c!symbol=\v!yes,\c!reset=\v!yes, + \c!maxwidth=,\c!maxheight=, + \c!frame=\v!off,\c!background=, + #2]% + \fi} + +\fi + +%D This macro takes {\em two} arguments, the second one can be +%D used to pass info to the inclusion macro. Some examples +%D of its use can be found in the modules \type{supp-tpi} and +%D \type{prag-log}. + +%D This module can be used in \PLAIN\ \TEX too. When using +%D \DVIPS, just try to process: +%D +%D \starttyping +%D \input supp-mps +%D +%D \runMPgraphicstrue +%D +%D \def\insertMPfile#1#2% +%D {\special{psfile=#1}} +%D +%D \startuseMPgraphic{1} +%D prologues := 1; +%D draw (0,0) withpen pencircle scaled 100; +%D \stopuseMPgraphic +%D +%D \useMPgraphic{1} +%D \stoptyping +%D +%D Don't forget to enable \type{\write18}. When does not say +%D \type{\runMPgraphicstrue}, the \METAPOST\ scratch file +%D must be closed by saying +%D +%D \starttyping +%D \flushMPgraphics +%D \stoptyping +%D +%D When using the indirect method, one has to process the file +%D \type{mpgraph.mp} between two successive \TEX\ runs. +%D +%D \METAPOST\ needs the public domain \DVI\ to \POSTSCRIPT\ +%D converter \DVIPS. This symbiosis originates in the need to +%D include the fonts (glyphs) that \METAPOST\ uses in the +%D \POSTSCRIPT\ file. Driver independancy was one of my +%D prerequisites for using \METAPOST, so I decided to build +%D this kind of support myself. Personally I consider driver +%D dependancy a drawback for the dissemination of such a +%D package. The second part of this module more or less +%D decouples \METAPOST\ and \DVIPS. +%D +%D The macros hereafter are copied from the module +%D \type{m-metapost}. After writing module \type{supp-pdf} I +%D added this method to the module named and after a while +%D decided to hook it into module \type{spec-yy}. Therefore +%D they made it into a support module, but in a slightly +%D different way. + +%D \macros +%D {includeMPfonts, ifincludeMPfonts} +%D +%D The method we use is both robust and simple: one can do +%D with calling the next macro with the filename as argument: +%D +%D \starttyping +%D \includeMPfonts{filename} +%D \stoptyping +%D +%D We can turn of this mechanism with: +%D +%D \starttyping +%D \includeMPfontsfalse +%D \stoptyping +%D +%D {\em Currently this method fails for situations where the +%D font definition is not on one line, which is he case when +%D unkerned fonts are used along with long lines. One solution +%D for this is to increase the value of \type {max_print_line} +%D in \type {texmf.cnf}.}} + +\newif\ifincludeMPfonts \includeMPfontstrue + +\def\includeMPfonts#1% + {\ifincludeMPfonts + \bgroup + \message{[MP fonts #1]}% + %\uncatcodespecials + \endlinechar\minusone + \setMPspecials + \obeyMPspecials + \setbox\scratchbox\hbox + {\hskip-\maxdimen + \doprocessfile\scratchread{#1}\handleMPfont}% + \smashbox\scratchbox + \box\scratchbox + \egroup + \fi} + +\def\UseMetaPostGraphic {\includeMPfonts} % upward compatible +\def\DontUseMetaPostGraphics {\includeMPfontsfalse} % upward compatible + +%D The characters are collected in a box and moved as far as +%D possible into the left margin. The resulting box has no +%D dimensions and can be prepended (appended) to the special +%D that handles the inclusion. The characters are in the file +%D but made invisible. +%D +%D In \CONTEXT\ font handling is intergrated in the figure +%D inclusion macros. A decent plain \TEX\ alternative is: +%D +%D \starttyping +%D \def\includeMPgraphic#1% +%D {\hbox\bgroup +%D \includeMPfonts{#1}% +%D \dogetEPSboundingbox{#1}{\dimen2}{\dimen4}{\dimen6}{\dimen8}% +%D \advance\dimen6 by -\dimen2 +%D \advance\dimen8 by -\dimen4 +%D \vbox to \dimen8 +%D {\forgetall +%D \vfill +%D \hsize\dimen6 +%D \special +%D {PSfile="#1"\space +%D llx=\EPSllx\space +%D lly=\EPSlly\space +%D urx=\EPSurx\space +%D ury=\EPSury\space}}% +%D \egroup} +%D \stoptyping +%D +%D This macro needs \type {supp-eps.tex} and provided no +%D scaling. For \LATEX\ users the next one will do: +%D +%D \starttyping +%D \def\includeMPgraphic#1#% +%D {\hbox\bgroup +%D \def\includeMPgraphics##1% +%D {\includeMPfonts{##1}% +%D \includegraphics[typetype=mps,#1]{##1}% or whatever type they use +%D \egroup}% +%D \includeMPgraphics} +%D \stoptyping + +%D We scan the graphics file for the \type{fshow} operator, +%D that is, lines that start with \type{(}. If found it +%D interprets the line, which looks like: +%D +%D \starttyping +%D (string ... string) font size fshow +%D \stoptyping +%D +%D Font definitions specified in the preamble are simply +%D ignored. Only lines starting with \type{(} are interpreted. + +\def\dohandleMPfont#1#2\relax + {\if#1(\expandafter\includeMPcharacters\fileline\relax\fi} + +\def\handleMPfont + {\expandafter\dohandleMPfont\fileline\relax} + +%D Before we start scanning for data, we first change some +%D \CATCODES. The first set of macro's is copied from module +%D \type{supp-pdf}. This scheme is a bit overdone for this +%D module, but using the same macros saves us some memory. + +\def\octalMPcharacter#1#2#3% + {\char'#1#2#3\relax} + +\bgroup +\catcode`\|=\@@comment +\catcode`\%=\@@active +\catcode`\[=\@@active +\catcode`\]=\@@active +\catcode`\{=\@@active +\catcode`\}=\@@active +\catcode`B=\@@begingroup +\catcode`E=\@@endgroup +\gdef\keepMPspecials| + B\let%\letterpercent| + \def[B\noexpand[E| + \def]B\noexpand]E| + \def{B\noexpand{E| + \def}B\noexpand}EE +\gdef\ignoreMPspecials| + B\let%\letterpercent| + \def[BE| + \def]BE| + \def{BE| + \def}BEE +\gdef\obeyMPspecials| + B\def%B\char 37\relax E| + \def[B\char 91\relax E| + \def]B\char 93\relax E| + \def{B\char123\relax E| + \def}B\char125\relax EE +\gdef\setMPspecials| + B\setnaturalcatcodes + \catcode`\\=\@@escape + \catcode`\%=\@@active + \catcode`\[=\@@active + \catcode`\]=\@@active + \catcode`\{=\@@active + \catcode`\}=\@@active + \lccode`\-=0 | latex sets this to `\- + \lccode`\%=`\% | otherwise it's seen as a number + \def\(B\char40\relax E| + \def\)B\char41\relax E| + \def\\B\char92\relax E| + \def\0B\octalMPcharacter0E| + \def\1B\octalMPcharacter1E| + \def\2B\octalMPcharacter2E| + \def\3B\octalMPcharacter3E| + \def\4B\octalMPcharacter4E| + \def\5B\octalMPcharacter5E| + \def\6B\octalMPcharacter6E| + \def\7B\octalMPcharacter7E| + \def\8B\octalMPcharacter8E| + \def\9B\octalMPcharacter9EE +\egroup + +%D The lines starting with \type{(} are interpreted and +%D handled by +%D +%D \starttyping +%D \def\includeMPcharacters(#1) #2 #3 #4\relax% +%D {\font\temp=#2 at #3bp\temp#1} +%D \stoptyping +%D +%D While processing some \TUG~98 proceedings, I also had to +%D deal with: +%D +%D \starttyping +%D /nfont {10 div dup scale 10} def +%D (T) ANTTB 7.13086 nfont fshow +%D \stoptyping +%D +%D which comes to rounding sizes. This is something +%D experimental. (The macro in supp-pdf.tex is more +%D advanced.) + +\def\PSnfont{nfont} + +\def\includeMPcharacters(#1) #2 #3 #4#5#6#7#8#9\relax + {\edef\temp{#4#5#6#7#8}% + \ifx\temp\PSnfont % round font size (to pt) + \scratchdimen#3\onepoint + \ifdim\scratchdimen<\onepoint + \def\size{1pt}% + \else + \advance\scratchdimen .5\onepoint + \def\size##1.##2\relax{\def\size{##1pt}}% + \expandafter\size\the\scratchdimen\relax + \fi + \else + \edef\size{#3bp}% + \fi + \font\temp=#2 at \size + \temp\if#1 \char32\else#1\fi} + +%D This method is both robust and reasonable fast. The only +%D disadvantage is that when not embedded properly in the +%D graphics inclusion macros, one has to load all graphics by +%D hand. + +%D Now let's see if things work all right and show the example +%D files that are part of the \METAPOST\ distribution: +%D +%D \setupexternalfigures[directory={../sample}] +%D \startlinecorrection +%D \setupalign[middle] +%D \leavevmode +%D \startcombination[3*3] +%D {\externalfigure[mp-exa-1][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-2][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-3][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-4][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-5][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-6][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-7][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-8][frame=on,width=.2\hsize]} {} +%D {\externalfigure[mp-exa-9][frame=on,width=.2\hsize]} {} +%D \stopcombination +%D \stoplinecorrection +%D +%D Here we used calls like: +%D +%D \starttyping +%D \externalfigure[mp-exa-1][methode-mps,frame=on,width=.2\hsize] +%D \stoptyping + +%D \macros +%D {convertMPcolors, +%D ifconvertMPcolors,ifreduceMPcolors,ifforceMPcolors} +%D +%D When I told the editors that I wanted to use colored +%D \METAPOST\ graphics in the color issue of the \MAPS, I was +%D asked to use the \cap{CMYK} colorspace instead of \cap{RGB} +%D one. However, \METAPOST\ only supports \cap{RGB} colors. I +%D decided to write a utility to convert the \type +%D {setrgbcolor} operators into \type {setcmykcolor} ones, and +%D some experiments showed me that I could best let \TEX\ do it +%D itself. Here it is: +%D +%D There are two booleans that control the conversion process. +%D These are false by default. + +\newif\ifconvertMPcolors +\newif\ifreduceMPcolors +\newif\ifforcegrayMPcolors + +%D The main macro is called as: +%D +%D \starttyping +%D \convertMPcolors{filename} +%D \stoptyping +%D +%D When active, this macro returns a message saying if indeed +%D conversion took place. The old file is overwritten! This +%D saves time in a succesive passes and can't harm, simply +%D because MP can generate them anew. + +\def\convertMPcolorpath{} +\def\convertMPcolorfile{metacmyk.tmp} + +\def\convertMPcolors#1% todo: open on local path, no copy + {\bgroup + \ifforcegrayMPcolors + \donetrue + \else\ifconvertMPcolors + \donetrue + \else + \donefalse + \fi\fi + \ifdone + \message{[MP color conversion #1}% + \endlinechar\minusone + \uncatcodespecials + \donefalse + \immediate\openout\scratchwrite\convertMPcolorpath\convertMPcolorfile\relax + \doprocessfile\scratchread{#1}\handleMPcolor + \immediate\closeout\scratchwrite + \ifdone + \immediate\openout\scratchwrite\convertMPcolorpath#1\relax + \doprocessfile\scratchread{\convertMPcolorpath \convertMPcolorfile}\handleMPcopy + \immediate\closeout\scratchwrite + \message{done]}% + \else + \message{not needed]}% + \fi + \immediate\openout\scratchwrite\convertMPcolorpath\convertMPcolorfile + \immediate\closeout\scratchwrite + \fi + \egroup} + +%D The process is rather simple: read a line, look for the +%D \type {setrgbcolor} operator, recalculate the components and +%D check for gray reduction or black removal, write the result +%D to a temporary file, and go on. Afterwards, the file is +%D copied back. We don't have to reduce to gray scales; +%D \METAPOST\ already takes care of that. + +%D The next macro is needed for forced conversion. This macro +%D is copied from \type{colo-ini}, just in case one uses this +%D module outside \CONTEXT. + +\ifx\@@cl@@s \undefined \def\@@cl@@s{0} \fi + +\ifx\convertRGBtoGRAY\undefined + +\def\convertRGBtoGRAY#1#2#3% + {\scratchdimen#1\onepoint + \scratchdimen300\scratchdimen + \scratchcounter\scratchdimen + \scratchdimen#2\onepoint + \scratchdimen590\scratchdimen + \advance\scratchcounter \scratchdimen + \scratchdimen#3\onepoint + \scratchdimen110\scratchdimen + \advance\scratchcounter \scratchdimen + \advance\scratchcounter \!!medcard + \divide\scratchcounter \!!maxcard + \edef\@@cl@@s{\realcolorvalue\scratchcounter}} + +\fi + +%D BTW, this code is quite old, and not as complete as the +%D \PDF\ converter, which also handles spot colors and so. + +\def\handleMPcolor + {\expandafter\dohandleMPcolor\fileline setrgbcolor*\\} + +\def\dohandleMPcolor#1setrgbcolor#2#3\\% + {\if#2*% + \immediate\write\scratchwrite{#1}% + \else + \dodohandleMPcolor#1setrgbcolor#2#3\\% + \fi} + +\def\dodohandleMPcolor#1 #2 #3setrgbcolor#4setrgbcolor*\\% old and maybe broke + {\bgroup + \ifdim#1pt=.123pt + \immediate\write\scratchwrite{#1 #2 #3 setrgbcolor}% + \else + \ifforcegrayMPcolors + \convertRGBtoGRAY{#1}{#2}{#3}% + \immediate\write\scratchwrite + {\@@cl@@s \space setgray #4}% + \else + \dimen0=\onepoint \advance\dimen0 -#1\points + \dimen2=\onepoint \advance\dimen2 -#2\points + \dimen4=\onepoint \advance\dimen4 -#3\points + \ifreduceMPcolors + \dimen6\dimen0 + \ifdim\dimen2<\dimen6 \dimen6\dimen2 \fi + \ifdim\dimen4<\dimen6 \dimen6\dimen4 \fi + \advance\dimen0 -\dimen6 + \advance\dimen2 -\dimen6 + \advance\dimen4 -\dimen6 + \else + \dimen6\zeropoint + \fi + \immediate\write\scratchwrite + {\withoutpt\the\dimen0 \space + \withoutpt\the\dimen2 \space + \withoutpt\the\dimen4 \space + \withoutpt\the\dimen6 \space setcmykcolor #4}% + \fi + \fi + \egroup + \donetrue} % needed for message + +\def\handleMPcopy + {\immediate\write\scratchwrite{\fileline}} + +%D The next examples show the color conversion macros in +%D action. These examples also demonstrate in||text \METAPOST\ +%D handling. As we will see, the conversion is hooked into the +%D \CONTEXT\ color mechanism. +%D +%D By setting both \type{rgb} and \type{cmyk} to off, we force +%D conversion to gray scales using: +%D +%D \placeformula[-] +%D \startformula +%D G = .30r + .59g + .11b +%D \stopformula +%D +%D By using buffers, we keep the \ASCII\ layout clean: +%D +%D \startbuffer +%D \startbuffer[rgb] +%D \setupcolors[rgb=ja,cmyk=nee,reduction=no,conversion=no] +%D \useMPgraphic{hans} +%D \stopbuffer +%D +%D \startbuffer[cmyk] +%D \setupcolors[rgb=nee,cmyk=ja,reduction=no,conversion=no] +%D \useMPgraphic{hans} +%D \stopbuffer +%D +%D \startbuffer[cmy] +%D \setupcolors[rgb=nee,cmyk=ja,reduction=yes,conversion=no] +%D \useMPgraphic{hans} +%D \stopbuffer +%D +%D \startbuffer[gray] +%D \setupcolors[rgb=nee,cmyk=nee,reduction=no,conversion=no] +%D \useMPgraphic{hans} +%D \stopbuffer +%D \stopbuffer +%D +%D \typebuffer +%D \getbuffer +%D +%D The graphic is rather simple and is generated each time +%D it's called: +%D +%D \global\runMPgraphicstrue +%D +%D \startbuffer +%D \startbuffer[graphic] +%D \startuseMPgraphic{hans} +%D width :=\the\textwidth/5; +%D height := width/4; +%D fill fullcircle +%D xscaled width +%D yscaled height +%D withcolor (\RedGreenBlue); +%D \stopuseMPgraphic +%D \stopbuffer +%D \stopbuffer +%D +%D \typebuffer +%D \getbuffer +%D +%D Next we combine the four alternative interpretations in a +%D combination: +%D +%D \startbuffer +%D \startbuffer[result] +%D \startcombination[4] +%D {\getbuffer[rgb]} {\tfxx original} +%D {\getbuffer[cmyk]} {\ttxx\string\convertMPcolorstrue} +%D {\getbuffer[cmy]} {\ttxx\string\reduceMPcolorstrue} +%D {\getbuffer[gray]} {\ttxx\string\forcegrayMPcolorstrue} +%D \stopcombination +%D \stopbuffer +%D \stopbuffer +%D +%D \typebuffer +%D \getbuffer +%D +%D Finally we call the buffers, using different setting: +%D +%D \startbuffer +%D \placefigure +%D {\METAPOST\ color conversions} +%D {\def\RedGreenBlue{.1,.4,.6}\getbuffer[graphic]\getbuffer[result]\vskip6pt +%D \def\RedGreenBlue{.1,.6,.4}\getbuffer[graphic]\getbuffer[result]\vskip6pt +%D \def\RedGreenBlue{.4,.1,.6}\getbuffer[graphic]\getbuffer[result]\vskip6pt +%D \def\RedGreenBlue{.4,.6,.1}\getbuffer[graphic]\getbuffer[result]\vskip6pt +%D \def\RedGreenBlue{.6,.1,.4}\getbuffer[graphic]\getbuffer[result]\vskip6pt +%D \def\RedGreenBlue{.6,.4,.1}\getbuffer[graphic]\getbuffer[result]} +%D \stopbuffer +%D +%D \typebuffer +%D \getbuffer +%D +%D By the way, when the \POSTSCRIPT\ file resulting from +%D this input is converted into \PDF\ and viewed in Acrobat +%D Reader, one can quite different colors from those +%D displayed in \GHOSTSCRIPT, which view equals the +%D \POSTSCRIPT\ originals. + +%D \macros +%D {experimental} +%D +%D Some experimental macros: +%D +%D \starttyping +%D \startMPdrawing +%D \stopMPdrawing +%D \pushMPdrawing +%D \popMPdrawing +%D \resetMPdrawing +%D \ifMPdrawingdone +%D \getMPdrawing +%D \MPdivten[number] +%D \stoptyping +%D +%D These macros are used in \PPCHTEX. + +\let\MPdrawingdata\empty + +\newif\ifMPdrawingdone \MPdrawingdonefalse +\newif\ifMPshiftdrawing \MPshiftdrawingfalse + +\def\resetMPdrawing + {\globallet\MPdrawingdata\empty + \global\MPdrawingdonefalse} + +% why global push/pop here? + +\def\pushMPdrawing + {\globalpushmacro\MPdrawingdata + \globallet\MPdrawingdata\empty} + +\def\popMPdrawing + {\globalpopmacro\MPdrawingdata} + +\def\getMPdrawing + {\ifMPdrawingdone + \expandafter\startMPgraphic\MPdrawingdata\stopMPgraphic + \loadcurrentMPgraphic{}% + \deallocateMPslot\currentMPgraphic + \placeMPgraphic + \fi} + +\def\startMPdrawing + {\dosingleempty\dostartMPdrawing} + +\long\def\dostartMPdrawing[#1]#2\stopMPdrawing + {\relax + \bgroup + \enableincludeMPgraphics + \presetMPdefinitions % in case #2 has measures + \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}% + \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}% + \egroup} + +\let\stopMPdrawing\relax + +\def\MPdivten[#1]% + {\@EA\@EA\@EA\doMPdivten\@EA\@EA\@EA[\@EA#1]} + +\def\doMPdivten[#1]% + {\ifnum#1> 9999 \dodoMPdivtenB#1\else + \ifnum#1> 999 \dodoMPdivtenC#1\else + \ifnum#1> 99 \dodoMPdivtenD#1\else + \ifnum#1> 9 \dodoMPdivtenE#1\else + \ifnum#1> 0 \dodoMPdivtenF#1\else + \ifnum#1<-9999 \dodoMPdivtenA#1\else + \ifnum#1< -999 \dodoMPdivtenB#1\else + \ifnum#1< -99 \dodoMPdivtenC#1\else + \ifnum#1< -9 \dodoMPdivtenD#1\else + \ifnum#1< 0 \dodoMPdivtenE#1\else + 0 \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +\def\dodoMPdivtenA#1#2#3#4#5#6{#1#2#3#4#5.#6} +\def\dodoMPdivtenB #1#2#3#4#5{#1#2#3#4.#5} +\def\dodoMPdivtenC #1#2#3#4{#1#2#3.#4} +\def\dodoMPdivtenD #1#2#3{#1#2.#3} +\def\dodoMPdivtenE #1#2{#1.#2} +\def\dodoMPdivtenF #1{.#1} + +% if we assume etex ... \def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax} + +%D \macros +%D {startMPclip,grabMPclippath} +%D +%D We can use \METAPOST\ to calculate arbitrary clipping +%D paths. Such a path is defined by (for instance): +%D +%D \starttyping +%D \startMPclip{window} +%D clip currentpicture to fullcircle xscaled \width yscaled \height ; +%D \stopMPclip +%D \stoptyping +%D +%D Such a path can be extracted (processed) by: +%D +%D \starttyping +%D \grabMPclippath{window}{method}{width}{height}{default path} +%D \stoptyping +%D +%D Currently only method 1 makes sense; it produces \PDF\ +%D code. This macro only makes sense when hooked into a +%D special routine. + +\let\MPclippath\empty + +\long\def\startMPclip#1#2\stopMPclip + {\blabelgroup + \long\setgvalue{MPC:#1}{\startMPgraphic#2\stopMPgraphic\dograbMPclippath}% + \elabelgroup} + +\let\stopMPclip\relax + +\def\grabMPclippath#1#2#3#4#5% + {\blabelgroup + \edef\width {#3\space}\let\overlaywidth \width + \edef\height{#4\space}\let\overlayheight\height + \doifdefinedelse{MPC:#1} + {\getvalue{MPC:#1}% + \setxvalue{MPC:#1}{\noexpand\xdef\noexpand\MPclippath{\MPclippath}}}% + {\xdef\MPclippath{#5}}% + \ifcase#2\else % method 1 : + \doglobal\stripcharacter urveto\from\MPclippath\to\MPclippath + \doglobal\stripcharacter oveto\from\MPclippath\to\MPclippath + \doglobal\stripcharacter ineto\from\MPclippath\to\MPclippath + \fi + \elabelgroup} + +%D We pose some restrictions to the \METAPOST\ code and pickup +%D the clip path from the file. +%D +%D We turn the slash into a comment. The \type {\hbox} grabs spaces +%D and the \type {%} triggers the grabber. Next we filter the +%D clipping path, or actually, the first path. + +% \bgroup +% \catcode`\%=\@@active +% \catcode`\/=\@@comment +% \gdef\dograbMPclippath/ +% {\setbox\scratchbox=\hbox\bgroup/ +% \catcode`\%=\@@active +% \obeylines\let\obeyedline\space +% \def\do##1newpath##2closepath##3\od/ +% {\xdef\MPclippath{##2}\endinput}/ +% \def%##1%%EOF/ +% {\do##1newpathclosepath\od\endinput}/ +% \readfile{\MPgraphicfile.\the\currentMPgraphic}{}{}/ +% \deallocateMPslot\currentMPgraphic / new +% \egroup} +% \egroup + +\bgroup +\catcode`\%=\@@active +\catcode`\/=\@@comment +\gdef\dograbMPclippath/ + {\setbox\scratchbox=\hbox\bgroup/ + \catcode`\%=\@@active + \obeylines\let\obeyedline\space + \def\do##1q n##2p W##3\od/ + {\xdef\MPclippath{##2}\endinput}/ + \def%##1%%EOF/ + {\do##1q np W\od\endinput}/ + \readfile{\MPgraphicfile.\the\currentMPgraphic}{}{}/ + \ifx\MPclippath\empty + \def\do##1newpath##2closepath##3\od/ + {\xdef\MPclippath{##2}\endinput}/ + \def%##1%%EOF/ + {\do##1newpathclosepath\od\endinput}/ + \readfile{\MPgraphicfile.\the\currentMPgraphic}{}{}/ + \fi + \deallocateMPslot\currentMPgraphic / new + \egroup} +\egroup + +%D \macros +%D {recycleMPslots} +%D +%D When coding and embedding many \METAPOST\ figures in a +%D document, one can save quite some disk space by using +%D \PDFTEX\ and setting the next switch: + +\newif\ifrecycleMPslots \recycleMPslotstrue + +%D When a graphic takes space in the text flow, we can run +%D into deadlock typesetting. In the first pass, the graphic +%D is not available, but in the second pass it is. The +%D placeholder that was put there in the first pass in now +%D replace by the real graphic and as a result the document +%D shrinks or grows and pages are removed or added. This in +%D turn can trigger generation of other graphics, like those +%D in the background. Graphics start swapping place and again +%D page breaks change. You can imagine the mess we en dup +%D with. +%D +%D This is why we provide was to use a dedicate range if +%D numbers for fixed graphcs. Such graphics will not en dup +%D in the text flow (at least their dimensions don't +%D contribute to the main vertical list, and thereby they +%D cannot interfere. We use a rather safe maximum of 4000 +%D graphics here and 8000 in \type {meta-ini}. + +\newcount \maxnofMPgraphics \maxnofMPgraphics = 4000 % 8000 +\newcount \minnofMPgraphics \minnofMPgraphics = 1 + +\newif \ifMPstaticgraphic \MPstaticgraphicfalse % determines slot allocation + +\def\locateMPslot#1% slightly faster on one slot, much faster on multiple slots + {\ifundefined{\number#1MP}% no \ifcsname + \letgvalueempty{\number#1MP}% + \expandafter\gobbletwoarguments + \else + \global\advance#1\plusone + \fi + \locateMPslot#1} + +\def\allocateMPslot#1% + {\ifrunMPgraphics + \ifx\pdfliteral\undefined + \recycleMPslotsfalse % quite certainly not pdftex + \else\ifcase\pdfoutput + \recycleMPslotsfalse % dvi mode or not pdftex (we need to handle dvipdfmx) + \fi\fi + \else + \recycleMPslotsfalse + \fi + \ifrecycleMPslots + % \doloop % slow but used seldom + % {\doifundefined{\recurselevel MP} + % {\letgvalueempty{\recurselevel MP}% + % \global#1\recurselevel + % \exitloop}}% + \global#1\plusone + \locateMPslot#1% + % \message{[MP slot + \number#1]% + \else\ifMPstaticgraphic % beware not the same as static graphics + \global#1\maxnofMPgraphics + \global\advance\maxnofMPgraphics \minusone + \else + \global#1\minnofMPgraphics + \global\advance\minnofMPgraphics \plusone + \fi\fi + \ifnum\minnofMPgraphics<\maxnofMPgraphics \else + \writestatus\m!systems{increase \string\maxnofMPgraphics}% + \fi} + +\def\deallocateMPslot#1% + {\ifrunMPgraphics + \ifcase\pdfoutput \recycleMPslotsfalse \fi + \else + \recycleMPslotsfalse + \fi + \ifrecycleMPslots + \global\letbeundefined{\number#1MP}% + %\message{[MP slot - \number#1]}% + \fi} + +%D Experimental and overloaded later, since we need to be +%D more clever due to \METAPOST's limit of 4~open files. + +\def\MPdatafile + {mp-\the\currentMPgraphic.mpd} + +\def\getMPdata + {\input \MPdatafile\relax} + +%D \macros +%D {MPtoks, MPbox} +%D +%D For convenience, we provide some scratch registers: + +\ifx\undefined\MPtoks \newtoks\MPtoks \fi +\ifx\undefined\MPbox \newbox \MPbox \fi + +%D \macros +%D {startMPcode} +%D +%D We can save some typing with: +%D +%D \starttyping +%D \startMPcode whatever \stopMPcode +%D \stoptyping +%D +%D this automatically places the graphic + +\long\def\startMPcode + {\begingroup + \obeyMPlines + \dostartMPcode} + +\long\def\dostartMPcode#1\stopMPcode + {\startuseMPgraphic{@@}#1\stopuseMPgraphic + \useMPgraphic{@@}% + \endgroup} + +\let\stopMPcode\relax + +%D \macros +%D {startstaticMPgraphic} +%D +%D Dedicated to Aditya Mahajan. See meta-ini for usage. + +% \long\def\startstaticMPgraphic#1#2\stopstaticMPgraphic +% {\bgroup +% \MPstaticgraphictrue +% \setMPrandomseedfalse +% \def\MPgraphicfile{#1}% no \jobname here +% \let\allocateMPslot \gobbleoneargument +% \let\deallocateMPslot\gobbleoneargument +% \let\runMPgraphic \gobbleoneargument +% \MPextensions\emptytoks +% \MPinitializations\emptytoks +% \runMPgraphicstrue +% \MPwrapperfalse +% \enableincludeMPgraphics +% \def\sometxt##1{\string\sometxt{##1}}% +% \currentMPgraphic\plusone % hack, else no close +% \startMPgraphic#2\stopMPgraphic +% \executeMPgraphicfile +% \egroup} + +% different version, less messy hooked into the rest + +\long\def\startstaticMPgraphic#1#2\stopstaticMPgraphic + {\blabelgroup + \def\MPgraphicfile{#1}% no \jobname here + \let\MPwrite\MPstaticwrite + \immediate\openout\MPwrite=\MPgraphicfile.mp + \setMPrandomseedfalse + \enableincludeMPgraphics + \def\sometxt##1{\string\sometxt{##1}}% + \the\everyMPgraphic + \presetMPdefinitions + \theMPinclusions % brrr + \writeMPgraphic{\letterpercent mpenvironment: \the\everyMPTEXgraphic}% + \writeMPgraphic{beginfig(1);}% + \writeMPgraphic{#2}% + \writeMPgraphic{endfig; end.}% + \immediate\closeout\MPwrite + \executeMPgraphicfile + \elabelgroup} + +% this will go to meta-ini + +\def\delaysystemcommand + {\ifx\installprogram\undefined + \expandafter\executesystemcommand + \else + \expandafter\installprogram + \fi} + +\def\MPgraphicfilerunner + {texmfstart --ifchanged=\MPgraphicfile.mp texexec --mpstatic \MPgraphicfile.mp} + +\ifx\doifmode\undefined + \def\executeMPgraphicfile + {\ifrunMPgraphics\@EA\executesystemcommand\else\@EA\delaysystemcommand\fi{\MPgraphicfilerunner}} +\else + \def\executeMPgraphicfile{\doifmode{*\v!first} + {\ifrunMPgraphics\@EA\executesystemcommand\else\@EA\delaysystemcommand\fi{\MPgraphicfilerunner}}} +\fi + +%D Special for \XETEX\ (problem with newlines). This will go +%D away once the version supporting \type {--8bit} is +%D widespread. + +\ifnum\texengine=\xetexengine + \let\obeyMPlines\relax + \longMPlinesfalse % alas +\fi + +\protect \endinput |