%D \module %D [ file=meta-ini, %D version=2008.03.25, %D title=\METAPOST\ Graphics, %D subtitle=Initialization, %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. \writestatus{loading}{MetaPost Graphics / Initializations} \registerctxluafile{meta-ini}{1.001} \unprotect \newtoks \t_meta_extensions % mp, once \newtoks \t_meta_initializations % tex, each \newtoks \t_meta_userinclusions % mp, user \newtoks \everyMPgraphic % mp % public or not ? \appendtoks \restoreendofline % see interferences-001.tex \to \everyMPgraphic \def\MPruntimefile {mprun} \def\currentMPformat {metafun} \def\defaultMPinstance{metafun} %installcorenamespace{graphicvariable} % todo \installcorenamespace{mpinstance} \installcorenamespace{mpinstancetokens} \installcorenamespace{mpgraphic} \installcorenamespace{mpstaticgraphic} \installcorenamespace{mpclip} % The next command is, of course, dedicated to Mojca, who % needs it for gnuplot. Anyway, the whole multiple engine % mechanism is to keep her gnuplot from interfering. \unexpanded\def\startMPdefinitions {\dosinglegroupempty\meta_start_definitions} \def\meta_start_definitions#1#2\stopMPdefinitions {\edef\currentMPinstance{#1}% \ifx\currentMPinstance\empty \let\currentMPinstance\defaultMPinstance \fi \global\t_meta_instance\expandafter{\the\t_meta_instance#2}} \let\stopMPdefinitions\relax \unexpanded\def\startMPextensions#1\stopMPextensions {\global\t_meta_extensions\expandafter{\the\t_meta_extensions#1}} \let\stopMPextensions\relax \unexpanded\def\startMPinitializations#1\stopMPinitializations {\global\t_meta_initializations\expandafter{\the\t_meta_initializations#1}} \let\stopMPinitializations\relax \unexpanded\def\startMPinclusions {\dosingleempty\meta_start_inclusions} \def\meta_start_inclusions[#1]#2\stopMPinclusions {\edef\m_meta_option{#1}% \ifx\m_meta_option\!!plustoken \else \global\t_meta_userinclusions\emptytoks \fi \global\t_meta_userinclusions\expandafter{\the\t_meta_userinclusions#2}} \let\stopMPinclusions\relax \unexpanded\def\MPinclusions {\dosingleempty\meta_inclusions} \def\meta_inclusions[#1]#2% {\edef\m_meta_option{#1}% \ifx\m_meta_option\!!plustoken \else \global\t_meta_userinclusions\emptytoks \fi \global\t_meta_userinclusions\expandafter{\the\t_meta_userinclusions#2}} \def\meta_preset_definitions {\edef\overlaywidth {\overlaywidth \space}% \edef\overlayheight {\overlayheight \space}% \edef\overlaylinewidth{\overlaylinewidth\space}% \edef\currentwidth {\the\hsize \space}% \edef\currentheight {\the\vsize \space}} \def\t_meta_instance{\csname\??mpinstancetokens\currentMPinstance\endcsname} % token register \installcommandhandler \??mpinstance {MPinstance} \??mpinstance \setupMPinstance [\s!format=metafun, \s!extensions=\v!no, \s!initializations=\v!no, \c!textstyle=, \c!textcolor=] % \unexpanded\def\defineMPinstance % {\dodoubleargument\meta_define_instance} % \def\meta_define_instance[#1][#2]% % {\ifcsname\??mpinstancetokens#1\endcsname\else\expandafter\newtoks\csname\??mpinstancetokens#1\endcsname\fi % \t_meta_instance\emptytoks % in case we redefine % \getparameters[\??mpinstance#1][\s!format=mpost,\s!extensions=\v!no,\s!initializations=\v!no,#2]} \appendtoks \ifcsname\??mpinstancetokens\currentMPinstance\endcsname \else \expandafter\newtoks\csname\??mpinstancetokens\currentMPinstance\endcsname \fi \t_meta_instance\emptytoks % in case we redefine \to \everydefineMPinstance \unexpanded\def\resetMPinstance[#1]% {\writestatus\m!metapost{reset will be implemented when needed}} \def\meta_analyze_graphicname[#1]% {\meta_analyze_graphicname_indeed[#1::::]} \def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance :: {\edef\currentMPgraphicname{#2}% \ifx\currentMPgraphicname\empty \edef\currentMPgraphicname{#1}% \let\currentMPinstance\defaultMPinstance \else \edef\currentMPinstance{#1}% \fi \edef\currentMPformat{\MPinstanceparameter\s!format}} \def\currentMPinstance{\defaultMPinstance} \def\currentMPformat {\currentMPinstance} \defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] \defineMPinstance[extrafun][\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] \defineMPinstance[mprun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] \defineMPinstance[metapost][\s!format=mpost] \defineMPinstance[nofun] [\s!format=mpost] \newconditional\c_meta_include_extensions \newconditional\c_meta_include_initializations \def\meta_begin_graphic_group#1% {\begingroup \meta_analyze_graphicname[#1]} \def\meta_end_graphic_group {\endgroup} \def\MPaskedfigure{false} \def\meta_flush_current_initializations {\ifconditional\c_meta_include_initializations\the\t_meta_initializations;\fi\theMPrandomseed;} \def\meta_flush_current_preamble {\ifconditional\c_meta_include_extensions\the\t_meta_extensions;\the\t_meta_userinclusions;\fi\the\t_meta_instance;} \def\meta_start_current_graphic {\begingroup \meta_enable_include \the\everyMPgraphic \meta_preset_definitions \setMPrandomseed % this has to change % we need to preexpand the token lists \edef\p_extensions{\MPinstanceparameter\s!extensions}% \ifx\p_extensions\v!yes \settrue \c_meta_include_extensions \global\letMPinstanceparameter\s!extensions\v!no % needs checking \else \setfalse\c_meta_include_extensions \fi \edef\p_initializations{\MPinstanceparameter\s!initializations}% \ifx\p_initializations\v!yes \settrue \c_meta_include_initializations \else \setfalse\c_meta_include_initializations \fi \edef\p_setups{\MPinstanceparameter\c!setups}% \ifx\p_setups\empty \else \setups[\p_setups]% \fi \useMPinstancestyleandcolor\c!textstyle\c!textcolor} \def\meta_stop_current_graphic {\global\t_meta_instance\emptytoks \endgroup} \unexpanded\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig {\meta_start_current_graphic \forgetall \setbox\b_meta_graphic\hbox\bgroup % ; added 20100901 (as in mkii) \normalexpanded{\noexpand\ctxlua{metapost.graphic( "\currentMPinstance", "\currentMPformat", \!!bs#1;\!!es, \!!bs\meta_flush_current_initializations;\!!es, \!!bs\meta_flush_current_preamble;\!!es, \MPaskedfigure )}}% \egroup \placeMPgraphic \meta_stop_current_graphic} \newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default \def\setMPrandomseed {\let\theMPrandomseed\empty \ifsetMPrandomseed \ifx\getrandomnumber\undefined \else \getrandomnumber\localMPseed\zerocount{4095}% \def\theMPrandomseed{randomseed:=\localMPseed}% \fi\fi} %D Calling up previously defined graphics. \def\includeMPgraphic#1% gets expanded ! {\ifcsname\??mpgraphic#1\endcsname \csname\??mpgraphic#1\endcsname ; % ; is safeguard \fi} \unexpanded\def\meta_enable_include % public {\let\meta_handle_use_graphic \thirdofthreearguments \let\meta_handle_reusable_graphic\thirdofthreearguments} %D Drawings (stepwise built): \newif\ifMPdrawingdone \MPdrawingdonefalse \unexpanded\def\finalizeMPdrawing {\MPdrawingdonetrue} \let\MPdrawingdata\empty \unexpanded\def\resetMPdrawing {\global\let\MPdrawingdata\empty \global\MPdrawingdonefalse} \unexpanded\def\pushMPdrawing {\globalpushmacro\MPdrawingdata \global\let\MPdrawingdata\empty} \unexpanded\def\popMPdrawing {\globalpopmacro\MPdrawingdata} \unexpanded\def\getMPdrawing {\ifMPdrawingdone \expandafter\meta_process_graphic\expandafter{\MPdrawingdata}% is this expansion still needed? \fi} \def\startMPdrawing {\dosingleempty\meta_start_drawing} \def\meta_start_drawing[#1]#2\stopMPdrawing {\relax \bgroup \meta_enable_include \meta_preset_definitions % in case #2 has measures \doifelse{#1}{-}{\convertargument#2\to\asciia}{\def\asciia{#2}}% \xdef\MPdrawingdata{\MPdrawingdata\asciia}% \egroup} \let\stopMPdrawing\relax \def\MPdrawing#1% {\relax \bgroup \meta_enable_include \meta_preset_definitions \xdef\MPdrawingdata{\MPdrawingdata#1}% \egroup} \unexpanded\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less {\setgvalue{\??mpclip#1}{#2}} \let\stopMPclip\relax \unexpanded\def\meta_grab_clip_path#1#2#3#4% #4 is alternative (called in backend code) {\begingroup \edef\width {#2\space}\let\overlaywidth \width \edef\height{#3\space}\let\overlayheight\height \ifcsname\??mpclip#1\endcsname \meta_start_current_graphic \xdef\MPclippath{\normalexpanded{\noexpand\ctxlua{metapost.theclippath( "\currentMPinstance", "\currentMPformat", \!!bs\getvalue{\??mpclip#1}\!!es, \!!bs\meta_flush_current_initializations\!!es, \!!bs\meta_flush_current_preamble\!!es )}}}% \meta_stop_current_graphic \ifx\MPclippath\empty \xdef\MPclippath{#4}% \fi \else \xdef\MPclippath{#4}% \fi \endgroup} %D Since we want lables to follow the document settings, we %D also set the font related variables. \unexpanded\def\MPfontsizehskip#1% {\dontleavehmode \begingroup \definedfont[#1]% \hskip\cldcontext{fonts.hashes.parameters[font.current()].designsize}sp\relax \endgroup} \startMPinitializations % scale is not yet ok defaultfont:="\truefontname{Regular}"; defaultscale:=\the\bodyfontsize/10pt; \stopMPinitializations % watch out, this is a type1 font because mp can only handle 8 bit fonts \startMPinitializations % scale is not yet ok defaultfont:="rm-lmtt10"; \stopMPinitializations %D A signal that we're in combined \CONTEXT||\METAFUN mode: \startMPextensions string contextversion; contextversion:="\contextversion"; \stopMPextensions %D \macros %D {setupMPvariables} %D %D When we build collections of \METAPOST\ graphics, like %D background and buttons, the need for passing settings %D arises. By (mis|)|using the local prefix that belongs to %D \type {\framed}, we get a rather natural interface to %D backgrounds. To prevent conflicts, we will use the \type %D {-} in \METAPOST\ specific variables, like: %D %D \starttyping %D \setupMPvariables[meta:button][size=20pt] %D \stoptyping % \startlines % \def\xxx{\lineheight} \doprepareMPvariable{xxx} \xxx % \def\xxx{2pt} \doprepareMPvariable{xxx} \xxx % \def\xxx{2} \doprepareMPvariable{xxx} \xxx % \def\xxx{\scratchcounter} \doprepareMPvariable{xxx} \xxx % \def\xxx{red} \doprepareMPvariable{xxx} \xxx % \def\xxx{0.4} \doprepareMPvariable{xxx} \xxx % \stoplines % currently the inheritance of backgrounds does not work and % we might drop it anyway (too messy) \newbox\b_meta_variable_box \let \currentmpvariableclass \empty \let \m_meta_current_variable \empty \let \m_meta_current_variable_template\empty \def \meta_prepare_variable_default {\MPcolor{black}} % just to be sure we use a color but ... \edef\meta_unknown_variable_template {\??gv:\s!unknown} \letvalue{\??gv:\s!unknown}\empty \unexpanded\def\setupMPvariables {\dodoubleempty\meta_setup_variables} \def\meta_setup_variables[#1][#2]% {\ifsecondargument \getrawparameters[\??gv#1:][#2]% \else \getrawparameters[\??gv:][#1]% \fi} \unexpanded\def\presetMPvariable {\dodoubleargument\meta_preset_variable} \def\meta_preset_variable[#1][#2=#3]% {\ifcsname\??gv#1:#2\endcsname \else \setvalue{\??gv#1:#2}{#3}% \fi} \def\MPrawvar#1#2% no checking {\csname\??gv#1:#2\endcsname} \def\MPvariable#1% todo: could be a framed chain {\csname\??gv\currentmpvariableclass:#1\endcsname} \unexpanded\def\useMPvariables {\dodoubleargument\meta_use_variables} \def\meta_use_variables[#1][#2]% {\edef\currentmpvariableclass{#1}% \meta_prepare_variables{#2}} \unexpanded\def\meta_prepare_variables#1% {\processcommalist[#1]\meta_prepare_variable} \unexpanded\def\meta_prepare_variable#1% {\edef\m_meta_current_variable_template {\??gv\currentmpvariableclass:#1}% \edef\m_meta_current_variable {\csname\ifcsname\m_meta_current_variable_template\endcsname \m_meta_current_variable_template\else\meta_unknown_variable_template \fi\endcsname}% \ifx\m_meta_current_variable\empty \expandafter\meta_prepare_variable_nop \else \expandafter\meta_prepare_variable_yes \fi} \def\meta_prepare_variable_nop {\expandafter \let\csname\m_meta_current_variable_template\endcsname\meta_prepare_variable_default} \def\meta_prepare_variable_color {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\MPcolor\m_meta_current_variable}} \def\meta_prepare_variable_number {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\number\m_meta_current_variable}}% also accepts 0.number \def\meta_prepare_variable_dimension {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\the\dimexpr\m_meta_current_variable}} \def\meta_prepare_variable_yes {\defconvertedcommand\ascii\m_meta_current_variable % otherwise problems \doifcolorelse \ascii % with 2\bodyfontsize {\meta_prepare_variable_color} {\begingroup \setbox\b_meta_variable_box\hbox{\scratchdimen\m_meta_current_variable sp}% \ifzeropt\wd\b_meta_variable_box \endgroup\meta_prepare_variable_number \else \endgroup\meta_prepare_variable_dimension \fi}} \let\MPvar \MPvariable \let\setMPvariables\setupMPvariables %D \macros %D {startuniqueMPgraphic, uniqueMPgraphic} %D %D This macros is probably of most use to myself, since I like %D to use graphics that adapt themselves. The next \METAPOST\ %D kind of graphic is both unique and reused when possible. %D %D \starttyping %D \defineoverlay[example][\uniqueMPgraphic{test}] %D %D \startuniqueMPgraphic {test} %D draw unitsquare xscaled \overlaywidth yscaled \overlayheight ; %D \stopuniqueMPgraphic %D \stoptyping \def\overlaystamp % watch the \MPcolor, since colors can be redefined {\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor} %D A better approach is to let additional variables play a role %D in determining the uniqueness. In the next macro, the %D second, optional, argument is used to guarantee the %D uniqueness, as well as prepare variables for passing them to %D \METAPOST. %D %D \starttyping %D \startuniqueMPgraphic{meta:hash}{gap,angle,...} %D \stoptyping %D %D The calling macro also accepts a second argument. For %D convenient use in overlay definitions, we use \type {{}} %D instead of \type {[]}. %D %D \starttyping %D \uniqueMPgraphic{meta:hash}{gap=10pt,angle=30} %D \stoptyping \newcount\c_meta_object_counter \newbox \b_meta_graphic % hm, isn't this already done elsewhere? \unexpanded\def\meta_obey_box_depth {\setbox\b_meta_graphic\hbox\bgroup \raise\MPlly\box\b_meta_graphic \egroup} \unexpanded\def\meta_ignore_box_depth {\normalexpanded {\meta_obey_box_depth % hence the \unexpanded \wd\b_meta_graphic\the\wd\b_meta_graphic \ht\b_meta_graphic\the\ht\b_meta_graphic \dp\b_meta_graphic\the\dp\b_meta_graphic}} \unexpanded\def\meta_obey_box_origin {\setbox\b_meta_graphic\hbox\bgroup \hskip\MPllx\raise\MPlly\box\b_meta_graphic \egroup} \unexpanded\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth } \unexpanded\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth} \unexpanded\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin } \unexpanded\def\normalMPboxdepth{\let\meta_relocate_box\relax } \let\meta_relocate_box\relax \unexpanded\def\placeMPgraphic % the converter also displaces so in fact we revert {\meta_relocate_box \box\b_meta_graphic} \unexpanded\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens {\MPllx#2\MPlly#3\MPurx#4\MPury#5% \hbox{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent \def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although, {\begingroup % when there are that many they're probably not that unique anyway \edef\currentmpvariableclass{#1}% \extendMPoverlaystamp{#2}% incl prepare \ifcsname\??mpgraphic\overlaystamp:#1\endcsname\else \meta_enable_include % redundant \global\advance\c_meta_object_counter\plusone \setobject{MP}{\number\c_meta_object_counter}\hbox{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox \setxvalue{\??mpgraphic\overlaystamp:#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}% \fi \getvalue{\??mpgraphic\overlaystamp:#1}% \endgroup} \unexpanded\def\startuniqueMPgraphic {\dodoublegroupempty\meta_start_unique_graphic} \def\meta_start_unique_graphic#1#2#3\stopuniqueMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_unique_graphic{#1}{#2}{#3}}} \let\stopuniqueMPgraphic\relax \unexpanded\def\uniqueMPgraphic {\dodoublegroupempty\meta_unique_graphic} \def\meta_unique_graphic#1#2% {\meta_begin_graphic_group{#1}% \setupMPvariables[\currentMPgraphicname][#2]% \getvalue{\??mpgraphic\currentMPgraphicname}\empty \meta_end_graphic_group} \def\meta_handle_use_graphic#1#2#3% {\begingroup \edef\currentmpvariableclass{#1}% \meta_prepare_variables{#2}% \meta_enable_include % redundant \meta_process_graphic{#3}% \endgroup} \unexpanded\def\startuseMPgraphic {\dodoublegroupempty\meta_start_use_graphic} \def\meta_start_use_graphic#1#2#3\stopuseMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}} \let\stopuseMPgraphic\relax \unexpanded\def\startusableMPgraphic % redundant but handy {\dodoublegroupempty\meta_start_usable_graphic} \def\meta_start_usable_graphic#1#2#3\stopusableMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}} \let\stopusableMPgraphic\relax \def\meta_handle_reusable_graphic#1#2#3% {\begingroup \edef\currentmpvariableclass{#1}% \meta_prepare_variables{#2}% \meta_enable_include % redundant \global\advance\c_meta_object_counter\plusone \setobject{MP}{\number\c_meta_object_counter}\hbox{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox \setxvalue{\??mpgraphic#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}% \getvalue{\??mpgraphic#1}% \endgroup} \unexpanded\def\startreusableMPgraphic {\dodoublegroupempty\meta_start_reusable_graphic} \def\meta_start_reusable_graphic#1#2#3\stopreusableMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_reusable_graphic{#1}{#2}{#3}}} \let\stopreusableMPgraphic\relax \unexpanded\def\useMPgraphic {\dodoublegroupempty\meta_use_graphic} \def\meta_use_graphic#1#2% {\meta_begin_graphic_group{#1}% \doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}% \getvalue{\??mpgraphic\currentMPgraphicname}\empty \meta_end_graphic_group} \let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed \let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed \unexpanded\def\meta_enable_include {\let\meta_handle_use_graphic \thirdofthreearguments \let\meta_handle_reusable_graphic\thirdofthreearguments} %D \macros %D {startuniqueMPpagegraphic,uniqueMPpagegraphic} %D %D Experimental. \def\m_meta_page_prefix{\doifoddpageelse oe} \def\overlaypagestamp {\m_meta_page_prefix:\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor} \unexpanded\def\startuniqueMPpagegraphic {\dodoublegroupempty\meta_start_unique_page_graphic} \def\meta_start_unique_page_graphic#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined \let\stopuniqueMPpagegraphic\relax \unexpanded\def\uniqueMPpagegraphic {\dodoublegroupempty\meta_unique_page_graphic} \def\meta_unique_page_graphic#1#2% {\meta_begin_graphic_group{#1}% \let\overlaystamp\overlaypagestamp \setupMPvariables[\m_meta_page_prefix:\currentMPgraphicname][#2]% prefix is new here \getvalue{\??mpgraphic\m_meta_page_prefix:\currentMPgraphicname}{}% \meta_end_graphic_group} %D One way of defining a stamp is: %D %D \starttyping %D \def\extendMPoverlaystamp#1% %D {\def\docommand##1% %D {\edef\overlaystamp{\overlaystamp:\MPvariable{##1}}}% %D \processcommalist[#1]\docommand} %D \stoptyping %D Since we need to feed \METAPOST\ with expanded dimensions, %D we introduce a dedicated expansion engine. %D We redefine \type {\extendMPoverlaystamp} to preprocess %D variables using \type {\meta_prepare_variable}. \unexpanded\def\extendMPoverlaystamp#1% {\processcommalist[#1]\meta_extend_overlay_stamp} \def\meta_extend_overlay_stamp#1% {\meta_prepare_variable{#1}% \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}} %D \macros %D {MPdatafile} %D %D We redefine a macro from \type {supp-mps.tex}: % This will change ... \def\MPdataMPDfile{\jobname-mpgraph.mpd} \def\MPdataMPOfile{\jobname-mpgraph.mpo} \def\MPdataMPYfile{\jobname-mpgraph.mpy} \startMPextensions boolean collapse_data; collapse_data:=true; def data_mpd_file = "\MPdataMPDfile" enddef ; def data_mpo_file = "\MPdataMPOfile" enddef ; def data_mpy_file = "\MPdataMPYfile" enddef ; \stopMPextensions \unexpanded\def\getMPdata {\let\MPdata\secondoftwoarguments \startreadingfile % \startnointerference % no, else we need to do all data global \readlocfile\MPdataMPDfile\donothing\donothing % \stopnointerference \stopreadingfile} % We need this trick because we need to make sure that the tex scanner % sees newlines and does not quit. Also, we do need to flush the buffer % under a normal catcode regime in order to expand embedded tex macros. % As usual with buffers, \type {#1} can be a list. \unexpanded\def\processMPbuffer {\dosingleempty\meta_process_buffer} \def\meta_process_buffer[#1]% {\meta_begin_graphic_group{#1}% \meta_process_graphic{\ctxcommand{feedback("\currentMPgraphicname")}}% \meta_end_graphic_group} \unexpanded\def\runMPbuffer {\dosingleempty\meta_run_buffer} \def\meta_run_buffer[#1]% processing only {\startnointerference\meta_process_buffer[#1]\stopnointerference} %D \macros %D {startMPenvironment, resetMPenvironment} %D %D In order to synchronize the main \TEX\ run and the runs %D local to \METAPOST, environments can be passed. % \unexpanded\def\startMPenvironment % second arg gobbles spaces, so that reset gives \emptytoks % {\dodoubleempty\dostartMPenvironment} % \def\dostartMPenvironment[#1][#2]#3\stopMPenvironment % {\edef\m_meta_option{#1} % \ifx\m_meta_option\s!reset % \resetMPenvironment % reset mp toks % \else\ifx\m_meta_option\v!global % #3% % use in main doc too % \else\ifx\m_meta_option\!!plustoken % #3% % use in main doc too % \fi\fi\fi % \ctxlua{metapost.tex.set(\!!bs\detokenize{#3}\!!es)}} \unexpanded\def\startMPenvironment {\begingroup \catcode\endoflineasciicode \ignorecatcode \dosingleempty\dostartMPenvironment} \def\dostartMPenvironment[#1]#2\stopMPenvironment {\endgroup \edef\m_meta_option{#1} \ifx\m_meta_option\s!reset \resetMPenvironment % reset mp toks \else\ifx\m_meta_option\v!global #2% % use in main doc too \else\ifx\m_meta_option\!!plustoken #2% % use in main doc too \fi\fi\fi \ctxlua{metapost.tex.set(\!!bs\detokenize{#2}\!!es)}} \let\stopMPenvironment\relax \unexpanded\def\resetMPenvironment {\ctxlua{metapost.tex.reset()}} \unexpanded\def\useMPenvironmentbuffer[#1]% {\ctxlua{metapost.tex.set(buffers.content("#1"))}} %D This command takes \type {[reset]} as optional %D argument. %D %D \starttyping %D \startMPenvironment %D \setupbodyfont[pos,14.4pt] %D \stopMPenvironment %D %D \startMPcode %D draw btex \sl Hans Hagen etex scaled 5 ; %D \stopMPcode %D \stoptyping %D %D The most simple case: \unexpanded\def\startMPcode {\dosinglegroupempty\meta_start_code} \def\meta_start_code {\iffirstargument \expandafter\meta_start_code_instance \else \expandafter\meta_start_code_standard \fi} \def\meta_start_code_instance#1#2\stopMPcode {\meta_begin_graphic_group{#1::\s!dummy}% name does not matter \meta_enable_include \meta_process_graphic{#2}% \meta_end_graphic_group} \def\meta_start_code_standard#1#2\stopMPcode {\let\currentMPinstance\defaultMPinstance \meta_process_graphic{#2}} \let\stopMPcode\relax \unexpanded\def\MPcode {\dosinglegroupempty\meta_code} \def\meta_code {\iffirstargument \expandafter\meta_code_instance \else \expandafter\meta_code_standard \fi} \def\meta_code_instance#1#2% {\meta_begin_graphic_group{#1::\s!dummy}% name does not matter \meta_process_graphic{#2}% \meta_end_graphic_group} \def\meta_code_standard#1% #2 {\meta_process_graphic} % a bit nasty (also needed for compatibility: % \startMPrun input mp-www.mp ; \stopMPrun % \externalfigure[mprun.3][width=10cm,height=8cm] % \startMPrun{mprun} input mp-www.mp ; \stopMPrun % instance % \externalfigure[mprun.4][width=10cm,height=8cm] \let\MPruninstance\defaultMPinstance \unexpanded\def\useMPrun#1#2% name n {\begingroup \def\MPaskedfigure{#2}% \doifelsenothing{#1} {\useMPgraphic{mprun}}% {\useMPgraphic{#1}}% \endgroup} \unexpanded\def\startMPrun {\dosinglegroupempty\meta_start_run} \def\meta_start_run#1#2\stopMPrun {\iffirstargument \startuseMPgraphic{#1}#2\stopuseMPgraphic \else \startuseMPgraphic{mprun}#2\stopuseMPgraphic \fi} \let\stopMPrun\relax %D The \type {\resetMPenvironment} is a quick way to erase %D the token list. %D %D You should be aware of independencies. For instance, if you use a font %D in a graphic that is not used in the main document, you need to load the %D typescript at the outer level (either directly or by using the global %D option). %D %D \starttyping %D \usetypescript[palatino][texnansi] %D %D \startMPenvironment %D \usetypescript[palatino][texnansi] %D \enableregime[utf] %D \setupbodyfont[palatino] %D \stopMPenvironment %D %D \startMPpage %D draw btex aap‒noot coördinatie – één etex ; %D \stopMPpage %D \stoptyping %D Loading specific \METAPOST\ related definitions is %D accomplished by: \unexpanded\def\useMPlibrary[#1]{\ctxcommand{useMPlibrary(\!!bs#1\!!es)}} %D \macros %D {setMPtext, MPtext, MPstring, MPbetex} %D %D To be documented: %D %D \starttyping %D \setMPtext{identifier}{text} %D %D \MPtext {identifier} %D \MPstring{identifier} %D \MPbetex {identifier} %D \stoptyping \installcorenamespace{mptext} \unexpanded\def\setMPtext#1#2% todo : #1 must be made : safe {\defconvertedargument\ascii{#2}% \dodoglobal\letvalue{\??mptext#1}\ascii} \def\MPtext #1{\executeifdefined{\??mptext#1}\empty} \def\MPstring#1{"\executeifdefined{\??mptext#1}\empty"} \def\MPbetex #1{btex \executeifdefined{\??mptext#1}\empty\space etex} %D In order to communicate conveniently with the \TEX\ %D engine, we introduce some typesetting variables. % \setupcolors[state=stop,conversion=never] % quite tricky ... type mismatch % A dirty trick, ** in colo-ini.lua (mpcolor). \def\m_meta_colo_initializations{% no vardef, goes wrong with spot colors def OverlayLineColor=\MPcolor{\overlaylinecolor} enddef; def OverlayColor=\MPcolor{\overlaycolor} enddef; } \startMPextensions color OverlayColor,OverlayLineColor; \stopMPextensions \startMPinitializations CurrentLayout:="\currentlayout"; OverlayWidth:=\overlaywidth; OverlayHeight:=\overlayheight; OverlayDepth:=\overlayheight; OverlayLineWidth:=\overlaylinewidth; % \m_meta_colo_initializations % OverlayLineColor:=\MPcolor{\overlaylinecolor}; % OverlayColor:=\MPcolor{\overlaycolor}; % vardef OverlayLineColor=\MPcolor{\overlaylinecolor} enddef; % vardef OverlayColor=\MPcolor{\overlaycolor} enddef; % BaseLineSkip:=\the\baselineskip; LineHeight:=\the\baselineskip; BodyFontSize:=\the\bodyfontsize; % TopSkip:=\the\topskip; StrutHeight:=\strutheight; StrutDepth:=\strutdepth; % CurrentWidth:=\the\hsize; CurrentHeight:=\the\vsize; % EmWidth:=\the\emwidth; ExHeight:=\the\exheight; % PageNumber:=\the\pageno; RealPageNumber:=\the\realpageno; LastPageNumber:= \lastpage; \stopMPinitializations \appendtoks \disablediscretionaries \disablecompoundcharacters \to \everyMPgraphic % \appendtoks % before color, inefficient, replace by low level copy % \doregistercolor{currentcolor}\currentcolorname % \to \everyMPgraphic % \color[green]{abc \startMPcode % fill fullcircle scaled 3cm withoutcolor; % fill fullcircle scaled 2cm withcolor \MPcolor{currentcolor} ; % fill fullcircle scaled 1cm withcolor \MPcolor{red} ; % \stopMPcode def} \appendtoks \baselineskip1\baselineskip \lineheight 1\lineheight \topskip 1\topskip \to \everyMPgraphic \appendtoks \let \# \letterhash \let \_ \letterunderscore \let \& \letterampersand \let \{ \letteropenbrace \let \} \letterclosebrace \to \everyMPgraphic \startMPinitializations prologues:=0; mpprocset:=1; \stopMPinitializations %D \macros %D {PDFMPformoffset} %D %D In \PDF, forms are clipped and therefore we have to take %D precautions to get this right. Since this is related to %D objects, we use the same offset as used there. \def\PDFMPformoffset{\objectoffset} % %D \macros % %D {insertMPfile} % %D % %D Bypassing the special driver and figure mechanism is not % %D that nice but saves upto 5\% time in embedding \METAPOST\ % %D graphics by using the low level \PDF\ converter directly, % %D given of course that we use \PDFTEX. As a result we need to % %D fool around with the object trigger. \newtoks\everyinsertMPfile \startMPextensions def initialize_form_numbers = do_initialize_numbers; enddef; \stopMPextensions \startMPinitializations HSize:=\the\hsize ; VSize:=\the\vsize ; \stopMPinitializations \startMPextensions vardef ForegroundBox = unitsquare xysized(HSize,VSize) enddef ; vardef PageFraction = if \lastpage>1: (\realfolio-1)/(\lastpage-1) else: 1 fi enddef ; \stopMPextensions %D And some more. These are not really needed since we %D don't use the normal figure inclusion macros any longer. \appendtoks \externalfigurepostprocessors\emptytoks % safeguard \to \everyinsertMPfile %D We also take care of disabling fancy figure features, that %D can terribly interfere when dealing with symbols, %D background graphics and running (postponed) graphics. %D You won't believe me if I tell you what funny side effects %D can occur. One took me over a day to uncover when %D processing the screen version of the \METAFUN\ manual. \def\doifelseMPgraphic#1% {\ifcsname\??mpgraphic #1\endcsname \expandafter \firstoftwoarguments \else \ifcsname\??mpgraphic o:#1\endcsname \doubleexpandafter\firstoftwoarguments \else \ifcsname\??mpgraphic e:#1\endcsname \tripleexpandafter\firstoftwoarguments \else \tripleexpandafter\secondoftwoarguments \fi\fi\fi} \let\doifMPgraphicelse\doifelseMPgraphic %D New: \definelayerpreset % no dx,dy - else nasty non-mp placement [mp] [\c!y=-\MPury, \c!x=\MPllx, \c!method=\v!fit] \definelayer [mp] [\c!preset=mp] %D Usage: %D %D \starttyping %D \defineviewerlayer[one][state=start] %D \defineviewerlayer[two][state=stop] %D %D \startuseMPgraphic{step-1} %D fill fullcircle scaled 10cm withcolor red ; %D \stopuseMPgraphic %D %D \startuseMPgraphic{step-2} %D fill fullcircle scaled 5cm withcolor green ; %D \stopuseMPgraphic %D %D \setlayer[mp]{\viewerlayer[one]{\useMPgraphic{step-1}}} %D \setlayer[mp]{\viewerlayer[two]{\useMPgraphic{step-2}}} %D %D \ruledhbox{\flushlayer[mp]} %D \stoptyping %D %D Reusing graphics is also possible (now): %D %D \starttyping %D \startreusableMPgraphic{axis} %D tickstep := 1cm ; ticklength := 2mm ; %D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ; %D tickstep := tickstep/2 ; ticklength := ticklength/2 ; %D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ; %D \stopreusableMPgraphic %D %D \startuseMPgraphic{demo} %D drawpoint "1cm,1.5cm" ; %D \stopuseMPgraphic %D %D \definelayer[mp][preset=mp] %D \setlayer[mp]{\reuseMPgraphic{axis}} %D \setlayer[mp]{\useMPgraphic{demo}} %D \ruledhbox{\flushlayer[mp]} %D \stoptyping %D \macros %D {startstaticMPfigure,useMPstaticfigure} %D %D Static figures are processed only when there has been %D something changed. Here is Aditya Mahajan's testcase: %D %D \startbuffer %D \startstaticMPfigure{circle} %D fill fullcircle scaled 1cm withcolor blue; %D \stopstaticMPfigure %D %D \startstaticMPfigure{axis} %D drawarrow (0,0)--(2cm,0) ; %D drawarrow (0,0)--(0,2cm) ; %D label.llft(textext("(0,0)") ,origin) ; %D \stopstaticMPfigure %D \stopbuffer %D %D \typebuffer \getbuffer \unexpanded\def\startstaticMPfigure#1#2\stopstaticMPfigure {\startreusableMPgraphic{\??mpstaticgraphic#1}#2\stopreusableMPgraphic} \unexpanded\def\startstaticMPgraphic {\dodoublegroupempty\meta_start_static_graphic} \def\meta_start_static_graphic#1#2#3\stopstaticMPgraphic {\startreusableMPgraphic{\??mpstaticgraphic#1}{#2}#3\stopreusableMPgraphic} \let\stopstaticMPfigure \relax \let\stopstaticMPgraphic\relax \unexpanded\def\usestaticMPfigure {\dodoubleempty\meta_use_static_figure} \def\meta_use_static_figure[#1][#2]% {\ifsecondargument \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}% \else \reuseMPgraphic{\??mpstaticgraphic#1}% \fi} %D Goody for preventing overflows: \def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax} %D There is no way to distinguish the black color that you get when %D you issue a \type {draw} without color specification from a color %D that has an explicit black specification unless you set the %D variable \type {defaultcolormodel} to 1. Hoewever, in that case %D you cannot distinguish that draw from one with a \type %D {withoutcolor} specification. This means that we have to provide %D multiple variants of inheritance. %D %D In any case we need to tell the converter what the inherited color %D is to start with. Case~3 is kind of unpredictable as it closely %D relates to the order in which paths are flushed. If you want to %D inherit automatically from the surrounding, you can best stick to %D variant 1. Variant 0 (an isolated graphic) is the default. %D %D \startbuffer %D \startuseMPgraphic{test} %D drawoptions(withpen pencircle scaled 1pt) ; %D def shift_cp = currentpicture := currentpicture shifted (-15pt,0) ; enddef ; %D draw fullcircle scaled 10pt withoutcolor ; shift_cp ; %D fill fullcircle scaled 10pt ; shift_cp ; %D draw fullcircle scaled 10pt withoutcolor ; shift_cp ; %D fill fullcircle scaled 10pt withcolor red ; shift_cp ; %D draw fullcircle scaled 10pt withoutcolor ; shift_cp ; %D fill fullcircle scaled 10pt ; shift_cp ; %D \stopuseMPgraphic %D %D \starttabulate %D \NC 0\quad \NC \MPcolormethod0 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR %D \NC 1\quad \NC \MPcolormethod1 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR %D \NC 2\quad \NC \MPcolormethod2 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR %D \NC 3\quad \NC \MPcolormethod3 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR %D \stoptabulate %D \stopbuffer %D %D \typebuffer \getbuffer \newconstant\MPcolormethod \appendtoks \ctxlua{metapost.setoutercolor(\number\MPcolormethod,\number\attribute\colormodelattribute,\number\attribute\colorattribute,\number\dogetattribute{transparency})}% \to \everyMPgraphic \startMPinitializations defaultcolormodel := \ifcase\MPcolormethod1\or1\or3\else3\fi; \stopMPinitializations %D \macros %D {setupMPgraphics} %D %D Here is a generic setup command: \newtoks\everysetupMPgraphics \unexpanded\def\setupMPgraphics[#1]% {\getparameters[\??mp][#1]% \the\everysetupMPgraphics} %D Here we hook in the outer color. When \type {color} is set to \type %D {global} we get the outer color automatically. If you change this %D setting, you should do it grouped in order not to make other graphics %D behave in unexpected ways. \appendtoks \doifelse\@@mpcolor\v!global{\MPcolormethod\plusone}{\MPcolormethod\zerocount}% \to \everysetupMPgraphics \setupMPgraphics [\c!color=\v!local] %D Done. \protect \endinput