%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 / Hans Hagen \& Ton Otten}] %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 \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 \startopsomming %D \som generating \METAPOST\ code, running this program from %D within \TEX\ using \type{\write18}, and importing the %D result %D \som generating \METAPOST\ code, processing the code %D afterward, and importing the result in a second pass %D \stopopsomming %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 \starttypen %D \excuteMetaPost filename %D \stoptypen %D %D Ok then, let's start: \ifx \undefined \writestatus \input supp-mis.tex \relax \fi \ifx \undefined \letterhash \else \input supp-ini.tex \relax \fi \ifx \undefined \startMPgraphic \else \expandafter \endinput \fi \writestatus{loading}{Context Support Macros / MetaPost Inclusion} \unprotect \def\@@MPG{@MPG@} %D \macros %D {startMPgraphic} %D %D From within \TEX\ one can execute \METAPOST\ code by putting %D it between the two commands %D %D \starttypen %D \startMPgraphic %D \stopMPgraphic %D \stoptypen %D %D This is implemented as: \long\def\startMPgraphic#1\stopMPgraphic {\checkMPTEXgraphic{#1}% % potential speedup: pass #1 as macro \startwritingMPgraphic \writeMPgraphic{#1}% \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 \starttypen %D \startMPgraphic %D \stopMPgraphic %D \stoptypen %D %D \starttypen %D \startMPrun %D \stopMPrun %D \stoptypen %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 \ifCONTEXT \long\def\dostartMPrun#1#2\stopMPrun {\bgroup \MPruntrue \doifsomething{#1}{\def\MPgraphicfile{#1}}% \checkMPTEXgraphic{#2}% \startwritingMPgraphic \writeMPgraphic{#2}% \stopwritingMPgraphic \egroup} \def\startMPrun {\dosinglegroupempty\dostartMPrun} \else \long\def\startMPrun#1\stopMPrun {\MPruntrue \checkMPTEXgraphic{#1}% \startwritingMPgraphic \writeMPgraphic{#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 \starttypen %D \startwritingMPgraphic %D ... %D \writeMPgraphic{...} %D ... %D \writeMPgraphic{...} %D ... %D \stopwritingMPgraphic %D \stoptypen %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 \starttypen %D \MPinclusions{input mp-mine} %D \stoptypen %D %D The token register \type {\MPinitializations} is expanded %D before all other inclusions. \newtoks \MPinitializations % buggy % % \long\def\startMPinclusions#1\stopMPinclusions % {\long\def\theMPinclusions % {% \expanded ! % \@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPinitializations;}}% % \writeMPgraphic{#1}}} \long\def\startMPinclusions#1\stopMPinclusions {\long\def\theMPinclusions {% \expanded ! % \@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPinitializations;}}% \writeMPgraphic{#1}}} \long\def\MPinclusions#1% {\startMPinclusions#1\stopMPinclusions} \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 \newif\iflongMPlines \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}} \def\writeMPgraphic % no big #1 passing here {\iflongMPlines \expandafter\writeMPgraphiclong \else \expandafter\writeMPgraphicshort \fi} \long\def\writeMPgraphiclong#1% {\bgroup \presetMPdefinitions \let\par\space \longMPflush#1\empty\par\relax\par \egroup} \long\def\writeMPgraphicshort#1% {\bgroup \presetMPdefinitions \let\par\space \shortMPflush#1\empty;\relax;% \egroup} \long\def\longMPflush#1#2\par {\ifx#1\relax \else \immediate\write\MPwrite{#1#2}% \expandafter\longMPflush \fi} \long\def\shortMPflush#1#2;% {\ifx#1\relax \else \dowriteMPgraphicline#1#2tex \relax etex\MPend \expandafter\shortMPflush \fi} %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 \def\dowriteMPgraphicline {\futurelet\next\dodowriteMPgraphicline} %D A first version: %D %D \starttypen %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 \stoptypen %D The next alternative also handles inclusions well. \newtoks \everyMPTEXgraphic \newif\ifforceMPTEXgraphic %D Before we supported the graph module, we had: %D %D \starttypen %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 \stoptypen %D %D The next alternative permits extensions in other modules %D without the need to know the details of testing. \newtoks\MPTEXgrapicchecks \long\def\checkMPTEXgraphic#1% {\ifforceMPTEXgraphic \global\MPTEXgraphictrue \else \global\MPTEXgraphicfalse \expandafter\convertargument#1\to\MPascii \the\MPTEXgrapicchecks\relax \fi} %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}). \def\forceMPTEXcheck#1% {\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 \MPTEXgrapicchecks} \forceMPTEXcheck{etex} \forceMPTEXcheck{textext} \forceMPTEXcheck{graphictext} \def\flushMPTEXgraphic {\ifMPTEXgraphic \ifx\everyMPTEXgraphic\emptytoks \else \immediate\write\MPwrite{verbatimtex \the\everyMPTEXgraphic\space etex;}% \fi \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}}} \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 \edef\ascii{#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. %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} \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 \def\writeMPgraph {\immediate\write\MPwrite{mpgraph:=\the\currentMPgraphic;}} \beginTEX \ifx \honorunexpanded \undefined \else % not really needed \prependtoks \honorunexpanded \to \everyMPgraphic \fi \endTEX % buggy (at least in collected graphics, lazy expansion) % % \def\startwritingMPgraphic % {\blabelgroup % \global\advance\nofMPgraphics 1 % \ifMPrun \else % \allocateMPslot\currentMPgraphic % \fi % \enableincludeMPgraphics % \xdef\MPgraphic{\the\currentMPgraphic}% % \the\everyMPgraphic % \ifrunMPgraphics % \openMPgraphicfile1{runtime}% % % no reset here ! % \theMPinclusions % \else % \openMPgraphicfile0{collected}% % % reset here ! global added (due to adding \blabelgroup) % \theMPinclusions % \global\let\theMPinclusions\relax % \fi % \flushMPTEXgraphic % \ifMPrun \else % \immediate\write\MPwrite{let mprunend = end ;}% % \immediate\write\MPwrite{beginfig(\the\currentMPgraphic);}% % \fi % \globallet\flushMPgraphics\closeMPgraphicfiles % \dodostopwritingMPgraphic % \globallet\stopwritingMPgraphic=\dostopwritingMPgraphic} \def\startwritingMPgraphic {\blabelgroup \global\advance\nofMPgraphics 1 \ifMPrun \else \allocateMPslot\currentMPgraphic \fi \enableincludeMPgraphics \xdef\MPgraphic{\the\currentMPgraphic}% \the\everyMPgraphic \ifrunMPgraphics \openMPgraphicfile1{runtime}% % no reset here ! \theMPinclusions \@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPinitializations;}}% \else \openMPgraphicfile0{collected}% % reset here ! global added (due to adding \blabelgroup) \theMPinclusions \global\let\theMPinclusions\relax \fi \flushMPTEXgraphic \ifMPrun \else \immediate\write\MPwrite{let mprunend = end ;}% \immediate\write\MPwrite{beginfig(\the\currentMPgraphic);}% \@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPinitializations;}}% \fi \globallet\flushMPgraphics\closeMPgraphicfiles % \dodostopwritingMPgraphic \globallet\stopwritingMPgraphic=\dostopwritingMPgraphic} \let\MPgraphicfiles\empty \let\MPinputtranslation\empty \def\openMPgraphicfile#1#2% #1=alwaysopen #2=message {%\doifundefinedelse{\@@MPG\@@MPG\MPgraphicfile} % {\donetrue % \@EA\newwrite\csname\@@MPG\@@MPG\MPgraphicfile\endcsname}% % {\ifcase#1\donefalse\else\donetrue\fi}% \@EA\ifx\csname\@@MPG\@@MPG\MPgraphicfile\endcsname\relax %\donetrue \@EA\newwrite\csname\@@MPG\@@MPG\MPgraphicfile\endcsname % for the sake of plain usage \donetrue \@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 \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 \immediate\write\MPwrite{endfig;}% \immediate\write\MPwrite{let end = mprunend ;}% \fi \ifrunMPgraphics \dodostopwritingMPgraphic \fi \elabelgroup} \def\dodostopwritingMPgraphic {\ifnum\currentMPgraphic>0 \donetrue \else\ifMPrun \donetrue \else \donefalse \fi\fi \ifdone \finishwritingMPgraphics \runMPgraphic\MPgraphicfile \fi \globallet\flushMPgraphics\relax} \def\finishwritingMPgraphics {\immediate\write\MPwrite{end.}% \immediate\closeout\MPwrite} \def\closeMPgraphicfiles {\ifrunMPgraphics \else \ifx\MPgraphicsfiles\empty\else \def\docommando##1% {\message{[flush and process ##1.mp afterwards]}% \@EA\let\@EA\MPwrite\csname\@@MPG\@@MPG##1\endcsname \finishwritingMPgraphics}% \processcommacommand[\MPgraphicfiles]\docommando \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 1 } \def\deallocateMPslot#1{} %D \macros %D {translateMPinput} %D %D For my polish friends: %D %D \starttypen %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 \stoptypen \def\translateMPinput#1% {\xdef\MPinputtranslation{\letterpercent -translate-file=#1\space}} %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{0}{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 \starttypen %D \flushMPgraphics %D \stoptypen %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 \starttypen %D \loadcurrentMPgraphic{setups} %D \placeMPgraphic %D \stoptypen %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 bp\raise\MPlly bp\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 bp\raise\MPlly bp\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 \starttypen %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 \stoptypen %D %D More save is to use a number for {MP}{#1} which permits %D redefinition. \newcount\MPobjectcounter \def\douseMPbox#1% {\global\advance\MPobjectcounter\plusone \setobject{MP}{\number\MPobjectcounter}\vbox {\forgetall \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}% \deallocateMPslot\currentMPgraphic \placeMPgraphic}% \setxvalue{#1}{\noexpand\getobject{MP}{\number\MPobjectcounter}}} \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} %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#1#2\stopuseMPgraphic {\blabelgroup \long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}}% \elabelgroup} \long\def\startusableMPgraphic#1#2\stopusableMPgraphic % dummy {\blabelgroup \long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}}% \elabelgroup} \let\useMPgraphic=\reuseMPgraphic %D \macro %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 \starttypen %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 \stoptypen \def\includeMPgraphic#1% {\csname\@@MPG#1\endcsname} \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 \starttypen %D mpost -ini context %D \stoptypen %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\undefined\executeMetaPost \ifx\undefined\interactionmode \chardef\interactionmode=255 \fi \def\MPOSTbatchswitch {-int=batchmode} \def\MPOSTnonstopswitch {-int=nonstopmode} \def\MPOSTformatswitch {-progname=mpost -mem=} \def\MPOSTdriver {dvips} \def\executeMPOST#1% {mpost \ifcase\interactionmode\MPOSTbatchswitch\or\MPOSTnonstopswitch\fi \space\ifuseMETAFUNformat \MPOSTformatswitch metafun \fi #1} \def\executeMPTEX#1% {texexec --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!nee, \c!symbool=\v!ja,\c!reset=\v!ja, \c!maxbreedte=,\c!maxhoogte=, \c!kader=\v!uit,\c!achtergrond=, #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 \starttypen %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 \stoptypen %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 \starttypen %D \flushMPgraphics %D \stoptypen %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 \starttypen %D \includeMPfonts{filename} %D \stoptypen %D %D We can turn of this mechanism with: %D %D \starttypen %D \includeMPfontsfalse %D \stoptypen %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=-1 \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 \starttypen %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 \stoptypen %D %D This macro needs \type {supp-eps.tex} and provided no %D scaling. For \LATEX\ users the next one will do: %D %D \starttypen %D \def\includeMPgraphic#1#% %D {\hbox\bgroup %D \def\includeMPgraphics##1% %D {\includeMPfonts{##1}% %D \includegraphics[type=mps,#1]{##1}% or whatever type they use %D \egroup}% %D \includeMPgraphics} %D \stoptypen %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 \starttypen %D (string ... string) font size fshow %D \stoptypen %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\ignoreMPspecials| B\def%BE| \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 \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 \starttypen %D \def\includeMPcharacters(#1) #2 #3 #4\relax% %D {\font\temp=#2 at #3bp\temp#1} %D \stoptypen %D %D While processing some \TUG~98 proceedings, I also had to %D deal with: %D %D \starttypen %D /nfont {10 div dup scale 10} def %D (T) ANTTB 7.13086 nfont fshow %D \stoptypen %D %D which comes to rounding sizes. This is something %D experimental. \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#3pt \ifdim\scratchdimen<1pt \def\size{1pt}% \else \advance\scratchdimen .5pt \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 \startregelcorrectie %D \steluitlijnenin[midden] %D \leavevmode %D \startcombinatie[3*3] %D {\externfiguur[mp-exa-1][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-2][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-3][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-4][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-5][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-6][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-7][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-8][kader=aan,breedte=.2\hsize]} {} %D {\externfiguur[mp-exa-9][kader=aan,breedte=.2\hsize]} {} %D \stopcombinatie %D \stopregelcorrectie %D %D Here we used calls like: %D %D \starttypen %D \externfiguur[mp-exa-1][methode-mps,kader=aan,breedte=.2\hsize] %D \stoptypen %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 \kap{CMYK} colorspace instead of \kap{RGB} %D one. However, \METAPOST\ only supports \kap{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 \starttypen %D \convertMPcolors{filename} %D \stoptypen %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 \doprocessfile\scratchread{#1}\handleMPcolor \immediate\closeout\scratchwrite \ifdone \immediate\openout\scratchwrite=\convertMPcolorpath#1 \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 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*\\% {\bgroup %\ifnum\MPspecialsignal=123 % color spec / hardcoded hack \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=1\s!pt \advance\dimen0 -#1\s!pt \dimen2=1\s!pt \advance\dimen2 -#2\s!pt \dimen4=1\s!pt \advance\dimen4 -#3\s!pt \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 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\convertRGBtoGRAY\undefined \def\convertRGBtoGRAY#1#2#3% {\scratchdimen#1\s!pt \scratchdimen300\scratchdimen \scratchcounter\scratchdimen \scratchdimen#2\s!pt \scratchdimen590\scratchdimen \advance\scratchcounter \scratchdimen \scratchdimen#3\s!pt \scratchdimen110\scratchdimen \advance\scratchcounter \scratchdimen \advance\scratchcounter \!!medcard \divide\scratchcounter \!!maxcard \edef\@@cl@@s{\realcolorvalue\scratchcounter}} \fi %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 \plaatsformule[-] %D \startformule %D G = .30r + .59g + .11b %D \stopformule %D %D By using buffers, we keep the \ASCII\ layout clean: %D %D \startbuffer %D \startbuffer[rgb] %D \stelkleurenin[rgb=ja,cmyk=nee,reductie=nee,conversie=nee] %D \useMPgraphic{hans} %D \stopbuffer %D %D \startbuffer[cmyk] %D \stelkleurenin[rgb=nee,cmyk=ja,reductie=nee,conversie=nee] %D \useMPgraphic{hans} %D \stopbuffer %D %D \startbuffer[cmy] %D \stelkleurenin[rgb=nee,cmyk=ja,reductie=ja,conversie=nee] %D \useMPgraphic{hans} %D \stopbuffer %D %D \startbuffer[gray] %D \stelkleurenin[rgb=nee,cmyk=nee,reductie=nee,conversie=nee] %D \useMPgraphic{hans} %D \stopbuffer %D \stopbuffer %D %D \typebuffer %D \haalbuffer %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\tekstbreedte/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 \haalbuffer %D %D Next we combine the four alternative interpretations in a %D combination: %D %D \startbuffer %D \startbuffer[result] %D \startcombinatie[4] %D {\haalbuffer[rgb]} {\tfxx original} %D {\haalbuffer[cmyk]} {\ttxx\string\convertMPcolorstrue} %D {\haalbuffer[cmy]} {\ttxx\string\reduceMPcolorstrue} %D {\haalbuffer[gray]} {\ttxx\string\forcegrayMPcolorstrue} %D \stopcombinatie %D \stopbuffer %D \stopbuffer %D %D \typebuffer %D \haalbuffer %D %D Finally we call the buffers, using different setting: %D %D \startbuffer %D \plaatsfiguur %D {\METAPOST\ color conversions} %D {\def\RedGreenBlue{.1,.4,.6}\haalbuffer[graphic]\haalbuffer[result]\vskip6pt %D \def\RedGreenBlue{.1,.6,.4}\haalbuffer[graphic]\haalbuffer[result]\vskip6pt %D \def\RedGreenBlue{.4,.1,.6}\haalbuffer[graphic]\haalbuffer[result]\vskip6pt %D \def\RedGreenBlue{.4,.6,.1}\haalbuffer[graphic]\haalbuffer[result]\vskip6pt %D \def\RedGreenBlue{.6,.1,.4}\haalbuffer[graphic]\haalbuffer[result]\vskip6pt %D \def\RedGreenBlue{.6,.4,.1}\haalbuffer[graphic]\haalbuffer[result]} %D \stopbuffer %D %D \typebuffer %D \haalbuffer %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 \starttypen %D \startMPdrawing %D \stopMPdrawing %D \pushMPdrawing %D \popMPdrawing %D \resetMPdrawing %D \ifMPdrawingdone %D \getMPdrawing %D \MPdivten[number] %D \stoptypen %D %D These macros are used in \PPCHTEX. \let\MPdrawingdata\empty \newif\ifMPdrawingdone \MPdrawingdonefalse \newif\ifMPshiftdrawing \MPshiftdrawingfalse \def\resetMPdrawing {\globallet\MPdrawingdata\empty \global\MPdrawingdonefalse} \def\pushMPdrawing {\pushmacro\MPdrawingdata \globallet\MPdrawingdata\empty} \def\popMPdrawing {\popmacro\MPdrawingdata} \def\getMPdrawing {\ifMPdrawingdone \expandafter\startMPgraphic\MPdrawingdata\stopMPgraphic \loadcurrentMPgraphic\empty \deallocateMPslot\currentMPgraphic \placeMPgraphic \fi} \def\startMPdrawing {\dosingleempty\dostartMPdrawing} \long\def\dostartMPdrawing[#1]#2\stopMPdrawing {\relax \bgroup \enableincludeMPgraphics \presetMPdefinitions \doifelse{#1}{-} {\convertargument#2\to\asciiA} {\long\def\asciiA{#2}}% \long\xdef\MPdrawingdata{\MPdrawingdata\asciiA}% \egroup} \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} %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 \starttypen %D \startMPclip{window} %D clip currentpicture to fullcircle xscaled \width yscaled \height ; %D \stopMPclip %D \stoptypen %D %D Such a path can be extracted (processed) by: %D %D \starttypen %D \grabMPclippath{window}{method}{width}{height}{default path} %D \stoptypen %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} \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 %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 graphcis. 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 \def\allocateMPslot#1% {\ifrunMPgraphics \ifcase\pdfoutput \recycleMPslotsfalse \fi \else \recycleMPslotsfalse \fi \ifrecycleMPslots \doloop % slow but used seldom {\doifundefined{\recurselevel MP} {\letgvalueempty{\recurselevel MP}% \global#1=\recurselevel \exitloop}}% % \message{[MP slot + \number#1]% \else\ifMPstaticgraphic \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 \starttypen %D \startMPcode whatever \stopMPcode %D \stoptypen %D %D this automatically places the graphic \long\def\startMPcode#1\stopMPcode {\startuseMPgraphic{@@}#1\stopuseMPgraphic\useMPgraphic{@@}} \protect \endinput