%D \module %D [ file=meta-pdf, %D version=2006.06.07, %D title=\CONTEXT\ Support Macros, %D subtitle=\METAPOST\ to \PDF\ conversion, %D author=Hans Hagen \& others (see text), %D date=\currentdate, %D copyright=\PRAGMA] %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 Formerly known as supp-pdf.tex and supp-mpe.tex. %D These macros are written as generic as possible. Some %D general support macro's are loaded from a small module %D especially made for non \CONTEXT\ use. In this module I %D use a matrix transformation macro written by Tanmoy %D Bhattacharya. Thanks to extensive testing by Sebastian %D Ratz I was able to complete this module within reasonable %D time. This module has support for \METAPOST\ extensions %D built in. %D %D Daniel H. Luecking came up with a better (more precise) %D transformation method. You can recognize his comment by %D his initials. (We keep the old code around because it's a %D nice illustration on how a module like this evolves.) % Beware, we cannot use 0pt here by defaukt since it may be % defined in the range \dimen 0 - 20 which we happen to use % as scratch registers; for this reason we start allocating % scratch registers > 20 %D This module handles some \PDF\ conversion and insertions %D topics. By default, the macros use the \PDFTEX\ primitive %D \type{\pdfliteral} when available. Since \PDFTEX\ is now the %D default engine for \TEX\ distributions, we need a more complex %D test. \writestatus{loading}{Context Support Macros / MPS to PDF} \unprotect \ifx\PDFcode \undefined \let\PDFcode \gobbleoneargument \fi \ifx\PDFcomment\undefined \def\PDFcomment#1{\PDFcode{\letterpercent\space#1}} \fi %D First we define a handy constant: \bgroup \catcode`\%=\@@other \xdef\letterpercent{\string%} \egroup %D \macros %D {pdfimage,pdfimages,pdfclippedimage} %D %D Starting with pdftex version 14, images are included more %D natural to the form embedding. This enables alternative %D images to be embedded. %D %D \starttyping %D \pdfimage {file} %D \pdfimages {high res file} {low res file} %D \stoptyping %D %D The first one replaces the pre||version||14 original, %D while the latter provides alternative images. %D %D The next macro is dedicated to Maarten Gelderman, who %D needed to paste prepared \PDF\ pages into conference %D proceedings. %D %D \starttyping %D \pdfclippedimage {file} {l} {r} {t} {b} %D \stoptyping \ifx\pdftexversion\undefined \else \ifnum\pdftexversion>13 \def\pdfimage#1#% {\dopdfimage{#1}} \def\dopdfimage#1#2% {\immediate\pdfximage#1{#2}% \pdfrefximage\pdflastximage} \def\pdfimages#1#% {\dopdfimages{#1}} \def\dopdfimages#1#2#3% {\immediate\pdfximage#1{#2}% \immediate\pdfobj{[ << /Image \the\pdflastximage\space0 R /DefaultForPrinting true >> ]}% \immediate\pdfximage#1 attr {/Alternates \the\pdflastobj\space0 R}{#3}% \pdfrefximage\pdflastximage} \def\pdfclippedimage#1#% specs {file}{left}{right}{top}{bottom} {\dopdfclippedimage{#1}} \def\dopdfclippedimage#1#2#3#4#5#6% {\bgroup \pdfximage#1{#2}% \setbox\scratchbox\hbox{\pdfrefximage\pdflastximage}% \hsize\dimexpr\wd\scratchbox-#3-#4\relax \vsize\dimexpr\ht\scratchbox-#5-#6\relax \setbox\scratchbox\vbox to \vsize {\vskip-#5\hbox to \hsize{\hskip-#3\box\scratchbox\hss}}% \pdfxform\scratchbox \pdfrefxform\pdflastxform \egroup} \fi \fi %D \macros %D {convertMPtoPDF} %D %D The next set of macros implements \METAPOST\ to \PDF\ %D conversion. The traditional method is in the MkII file. %D The main conversion command is: %D %D \starttyping %D \convertMPtoPDF {filename} {x scale} {y scale} %D \stoptyping %D %D The dimensions are derived from the bounding box. So we %D only have to say: %D %D \starttyping %D \convertMPtoPDF{mp-pra-1.eps}{1}{1} %D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5} %D \stoptyping %D \macros %D {makeMPintoPDFobject,lastPDFMPobject} %D %D For experts there are a few more options. When attributes %D are to be added, the code must be embedded in an object %D accompanied with the appropriate directives. One can %D influence this process with \type {\makeMPintoPDFobject}. %D %D This option defaults to~0, because \CONTEXT\ takes care %D of objects at another level, which saves some bytes. %D %D \starttabulate[|l|l|p|] %D \NC 0 \NC never \NC don't use an object \NC\NR %D \NC 1 \NC always \NC always use an object \NC\NR %D \NC 2 \NC optional \NC use object when needed \NC\NR %D \stoptabulate %D %D The last object number used is avaliable in the macro %D \type {\lastPDFMPobject}. \ifx\makeMPintoPDFobject \undefined \chardef\makeMPintoPDFobject \zerocount \fi \ifx\blackoutMPgraphic \undefined \chardef\blackoutMPgraphic \plusone \fi \ifx\everyMPtoPDFconversion\undefined \newtoks\everyMPtoPDFconversion \fi \let\lastPDFMPobject \!!zerocount \let\currentPDFresources\empty \let\setMPextensions \relax \def\PDFMPformoffset {\ifx\objectoffset\undefined\zeropoint\else\objectoffset\fi} \def\resetMPvariables#1#2#3% {\global\let\MPwidth \!!zeropoint \global\let\MPheight\!!zeropoint \global\let\MPllx \!!zerocount \global\let\MPlly \!!zerocount \global\let\MPurx \!!zerocount \global\let\MPury \!!zerocount \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi \xdef\MPfilename {#1}} %D The main macro: \def\convertMPtoPDF#1#2#3% {\resetMPvariables{#1}{#2}{#3}% \mkconvertMPtoPDF} \def\processMPtoPDFfile#1#2#3% obsolete {\resetMPvariables{#1}{#2}{#3}% \mkprocessMPtoPDFfile} %D A common hook. \let\MPfshowcommand\empty %D Objects. \def\dopackageMPgraphic#1% #1 = boxregister {\ifcase\makeMPintoPDFobject\or\or\ifx\currentPDFresources\empty\else % an existing value of 2 signals object support (set elsewhere) \chardef\makeMPintoPDFobject\plusone \fi\fi \ifcase\makeMPintoPDFobject \box#1% \or \scratchdimen\PDFMPformoffset\relax \ifdim\scratchdimen>\zeropoint % compensate for error \setbox#1\vbox spread 2\scratchdimen {\forgetall\vss\hbox spread 2\scratchdimen{\hss\box#1\hss}\vss}% \fi \setMPPDFobject{\currentPDFresources}{#1}% \ifdim\scratchdimen>\zeropoint % compensate for error \vbox to \MPheight {\forgetall\vss\hbox to \MPwidth{\hss\getMPPDFobject\hss}\vss}% \else \getMPPDFobject \fi \global\let\currentPDFresources\empty \else \box#1% \fi} \def\setMPPDFobject#1#2% resources boxnumber {\ifx\pdfxform\undefined \def\getMPPDFobject{\box#2}% \else\ifx\pdftexversion\undefined \def\getMPPDFobject{\box#2}% \else\ifnum\pdftexversion<14 \def\getMPPDFobject{\box#2}% \else \ifx\everyPDFxform\undefined\else\the\everyPDFxform\fi \immediate\pdfxform resources{#1}#2% \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}% \fi\fi\fi} \let\getMPPDFobject\relax %D \macros %D {deleteMPgraphic, %D startMPresources, %D stopMPresources} \ifx\deleteMPgraphic\undefined \def\deleteMPgraphic#1{} \fi \ifx\startMPresources\undefined \let\startMPresources\relax \let\stopMPresources\relax \fi %D We implement extensions by using the \METAPOST\ special %D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones %D are flushed before or after the graphic data, but thereby %D are no longer connected to a position. %D %D We implement specials by overloading the \type {fill} %D operator. By counting the fills, we can let the converter %D treat the appropriate fill in a special way. The %D specification of the speciality can have two forms, %D determined by the setting of a boolean variable: %D %D \starttyping %D _inline_specials_ := false ; % comment like code (default) %D _inline_specials_ := true ; % command like code %D \stoptyping %D %D When the specification is embedded as comment, it looks %D like: %D %D \starttyping %D %%MetaPostSpecial %D \stoptyping %D %D The in||line alternative is more tuned for \POSTSCRIPT, %D since it permits us to define a macro \type {special}. %D %D \starttyping %D inline : special %D \stoptyping %D %D The \type {identifier} determines what to do, and the data %D can be used to accomplish this. A type~2 shading function %D has identifier~2. Alltogether, the number of parameters is %D specified in \type {size}. The \type {number} is the number %D of the fill that needs the special treatment. For a type~2 %D and~3 shaded fill, the datablock contains the following %D data: %D %D \starttyping %D from to n inner_r g b x y outer_r g b x y %D from to n inner_r g b x y radius outer_r g b x y radius %D \stoptyping \newconditional\manyMPspecials \settrue\manyMPspecials %D In case of \PDF, we need to prepare resourcs. \newtoks\MPstartresources \newtoks\MPstopresources \def\startMPresources {\the\MPstartresources} \def\stopMPresources {\the\MPstopresources} %D Some day we may consider collecting local resources. \appendtoks \global\let\currentPDFresources\empty % kind of redundant \to \MPstartresources % \appendtoks % \collectPDFresources % \global\let\currentPDFresources\collectedPDFresources % \to \MPstopresources \appendtoksonce \the\everyPDFxform \to \MPstopresources %D Since colors are not subjected to transformations, we can %D only use colors as signal. In our case, we use a dummy colored %D path with a red color component of \type {0.n}, so \type %D {0.001} is the first path and \type {0.010} the tenth. Since %D \METAPOST strips trailing zeros, we have to padd the string. \newif\ifMPcmykcolors \newif\ifMPspotcolors \def\dohandleMPrgb #1#2#3{\revokeMPtransparencyspecial\execcolorR #1:#2:#3:0:0\od} \def\dohandleMPcmyk#1#2#3#4{\revokeMPtransparencyspecial\execcolorC#1:#2:#3:#4:0:0\od} \def\dohandleMPgray #1{\revokeMPtransparencyspecial\execcolorS #1:0:0\od} \def\dohandleMPspot#1#2#3#4{\revokeMPtransparencyspecial\execcolorP#1:#2:#3:#4:0:0\od} %D Specials: \settrue \manyMPspecials \newcount\nofMParguments \let\extraMPpathcode\empty \def\@@MP {@@MP} \def\@@MPSK{@MPSK@} \def\MPspecial{\@@MPSK\@@MPSK\gMPs\nofMParguments} \def\defineMPspecial#1#2% {\setvalue{\@@MPSK\@@MPSK#1}{#2}} %D Special number~1 is dedicated to \CMYK\ support. If you %D want to know why: look at this: %D %D \startbuffer[mp] %D fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ; %D \stopbuffer %D %D \startbuffer[cmyk] %D \startcombination[4*1] %D {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3} %D {\definecolor[test][c=.9,y=.15] \processMPbuffer[mp]} {c=.9 y=.15} %D {\definecolor[test][c=.25,y=.8] \processMPbuffer[mp]} {c=.25 y=.8} %D {\definecolor[test][c=.45,y=.1] \processMPbuffer[mp]} {c=.45 y=.1} %D \stopcombination %D \stopbuffer %D %D \placefigure %D {\CMYK\ support disabled, %D conversion to \RGB.} %D {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]} %D %D \placefigure %D {\CMYK\ support enabled, %D no support in \METAPOST.} %D {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]} %D %D \placefigure %D {\CMYK\ support enabled, %D no conversion to \RGB, %D support in \METAPOST} %D {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]} \defineMPspecial{1} {\ifMPcmykcolors \setxvalue{\@@MPSK\gMPs6}{\noexpand\dohandleMPcmykcolor{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}}% \fi} \defineMPspecial{2} {\ifMPspotcolors \setxvalue{\@@MPSK\gMPs6}{\noexpand\dohandleMPspotcolor{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}}% % \checkMPspot{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}% \fi} % \def\checkMPspot#1#2#3#4% % {\expanded{\resolveMPspotcolor#1 #2 #3 #4}\end % \ifx\MPspotspace\MPresolvedspace % \edef\MPspotspacespec{/\MPspotspace\space}% % \doifinstringelse\MPspotspacespec\currentMPcolorspaces % \donothing\registerMPcolorspace % \fi} \let\revokeMPtransparencyspecial\relax \def\dohandleMPrgbcolor #1#2#3{\revokeMPtransparencyspecial\execcolorR #1:#2:#3:0:0\od} \def\dohandleMPcmykcolor#1#2#3#4{\revokeMPtransparencyspecial\execcolorC#1:#2:#3:#4:0:0\od} \def\dohandleMPgraycolor #1{\revokeMPtransparencyspecial\execcolorS #1:0:0\od} \def\dohandleMPspotcolor#1#2#3#4{\revokeMPtransparencyspecial\execcolorP#1:#2:#3:#4:0:0\od} %D Transparency support used specials 60 (rgb) and 61 %D (cmyk). %D %D \startbufferFshade %D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0); %D %D fill p rotated 90 withcolor transparent(1,.5,yellow) ; %D fill p rotated 210 withcolor transparent(1,.5,green) ; %D fill p rotated 330 withcolor transparent(1,.5,blue) ; %D \stopbuffer %D %D \typebuffer %D %D \startlinecorrection \processMPbuffer \stoplinecorrection %D %D One can also communicate colors between \CONTEXT\ and %D \METAPOST: %D %D \startbuffer %D \definecolor[tcyan] [c=1,k=.2,t=.5] %D \definecolor[tmagenta][m=1,k=.2,t=.5] %D \definecolor[tyellow] [y=1,k=.2,t=.5] %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0); %D %D fill p rotated 90 withcolor \MPcolor{tcyan} ; %D fill p rotated 210 withcolor \MPcolor{tmagenta} ; %D fill p rotated 330 withcolor \MPcolor{tyellow} ; %D \stopbuffer %D %D \startlinecorrection \processMPbuffer \stoplinecorrection %D %D We save all the three components needed in one macro, %D just to save hash space. \def\dohandleMPrgbtransparency #1#2#3#4#5{\execcolorR #1:#2:#3:#4:#5\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial} \def\dohandleMPcmyktransparency#1#2#3#4#5#6{\execcolorC#1:#2:#3:#4:#5:#6\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial} \def\dohandleMPgraytransparency #1#2#3{\execcolorS #1:#2:#3\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial} \def\dohandleMPspottransparency#1#2#3#4#5#6{\execcolorP#1:#2:#3:#4:#5:#6\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial} \def\dorevokeMPtransparencyspecial {\PDFcode{\PDFtransparencyresetidentifier\space gs}% \let\revokeMPtransparencyspecial\relax} \defineMPspecial{3} % rgb {\setxvalue{\@@MPSK\gMPs6}{\noexpand\dohandleMPrgbtransparency{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs1}{\gMPs2}}} \defineMPspecial{4} % cmyk {\setxvalue{\@@MPSK\gMPs7}{\noexpand\dohandleMPcmyktransparency{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs1}{\gMPs2}}} \defineMPspecial{5} % spot {\setxvalue{\@@MPSK\gMPs7}{\noexpand\dohandleMPspottransparency{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs1}{\gMPs2}}% }%\checkMPspot{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}} %D Shading is an example of a more advanced graphic feature, %D but users will seldom encounter those complications. Here %D we only show a few simple examples, but many other %D alternatives are possible by setting up the functions built %D in \PDF\ in the appropriate way. %D %D Shading has to do with interpolation between two or more %D points or user supplied ranges. In \PDF, the specifications %D of a shade has to be encapsulated in objects and passed on %D as resources. This is a \PDF\ level 1.3. feature. One can %D simulate three dimensional shades as well and define simple %D functions using a limited set of \POSTSCRIPT\ primitives. %D Given the power of \METAPOST\ and these \PDF\ features, we %D can achieve superb graphic effects. %D %D Since everything is hidden in \TEX\ and \METAPOST\ graphics, %D we can stick to high level \CONTEXT\ command, as shown in %D the following exmples. %D %D \startbuffer %D \startuniqueMPgraphic{CircularShade} %D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; %D circular_shade(p,0,.2red,.9red) ; %D \stopuniqueMPgraphic %D %D \startuniqueMPgraphic{LinearShade} %D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; %D linear_shade(p,0,.2blue,.9blue) ; %D \stopuniqueMPgraphic %D %D \startuniqueMPgraphic{DuotoneShade} %D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; %D linear_shade(p,2,.5green,.5red) ; %D \stopuniqueMPgraphic %D \stopbuffer %D %D \typebuffer %D %D \getbuffer %D %D These graphics can be hooked into the overlay mechanism, %D which is available in many commands. %D %D \startbuffer %D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}] %D \defineoverlay[demo 2][\uniqueMPgraphic {LinearShade}] %D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}] %D \stopbuffer %D %D \typebuffer %D %D \getbuffer %D %D These backgrounds can for instance be applied to \type %D {\framed}: %D %D \startbuffer %D \setupframed[width=3cm,height=2cm,frame=off] %D \startcombination[3*1] %D {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {} %D {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {} %D {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {} %D \stopcombination %D \stopbuffer %D %D \typebuffer %D %D \startlinecorrection %D \getbuffer %D \stoplinecorrection %D %D There are a few more alternatives, determined by the second %D parameter passed to \type {circular_shade} and alike. %D %D \def\SomeShade#1#2#3#4#5% %D {\startuniqueMPgraphic{Shade-#1} %D width := \overlaywidth ; %D height := \overlayheight ; %D path p ; p := unitsquare xscaled width yscaled height ; %D #2_shade(p,#3,#4,#5) ; %D \stopuniqueMPgraphic %D \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]% %D \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}} %D %D \startlinecorrection %D \startcombination[5*1] %D {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0} %D {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1} %D {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2} %D {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3} %D {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4} %D \stopcombination %D \stoplinecorrection %D %D \blank %D %D \startlinecorrection %D \startcombination[5*1] %D {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0} %D {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1} %D {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2} %D {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3} %D {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4} %D \stopcombination %D \stoplinecorrection %D %D \blank %D %D \startlinecorrection %D \startcombination[4*1] %D {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0} %D {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1} %D {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2} %D {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3} %D \stopcombination %D \stoplinecorrection %D %D These macros closely cooperate with the \METAPOST\ module %D \type {mp-spec.mp}, which is part of the \CONTEXT\ %D distribution. %D %D The low level (\PDF) implementation is based on the \TEX\ %D based \METAPOST\ to \PDF\ converter. Shading is supported %D by overloading the \type {fill} operator as implemented %D earlier. In \PDF\ type~2 and~3 shading functions are %D specified in terms of: %D %D \starttabulate[|Tl|l|] %D \NC /Domain \NC sort of meeting range \NC \NR %D \NC /C0 \NC inner shade \NC \NR %D \NC /C1 \NC outer shade \NC \NR %D \NC /N \NC smaller values, bigger inner circles \NC \NR %D \stoptabulate \newcount\currentPDFshade % 0 % global (document wide) counter \def\dosetMPlinearshade#1% {\immediate\pdfobj {<>}% \immediate\pdfobj {<>}% \global\advance\currentPDFshade \plusone \appendtoPDFdocumentshades{/Sh\the\currentPDFshade\space\the\pdflastobj\space0 R }% \setxvalue{\@@MPSK#1}{\noexpand\dohandleMPshade{\the\currentPDFshade}}} \defineMPspecial{30} {\expanded{\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA \expanded{\resolveMPrgbcolor{\gMPs{9}}{\gMPs{10}}{\gMPs{11}}}\to\MPshadeB \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs{12} \gMPs{13}}% \dosetMPlinearshade{\gMPs{14}}} \defineMPspecial{32} {\expanded{\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA \expanded{\resolveMPcmykcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}% \dosetMPlinearshade{\gMPs{16}}} \defineMPspecial{34} {\expanded{\resolveMPspotcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA \expanded{\resolveMPspotcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}% \dosetMPlinearshade{\gMPs{16}}} \def\dosetMPcircularshade#1% {\immediate\pdfobj {<>}% \immediate\pdfobj {<>}% \global\advance\currentPDFshade \plusone \appendtoPDFdocumentshades{/Sh\the\currentPDFshade\space\the\pdflastobj\space0 R }% \setxvalue{\@@MPSK#1}{\noexpand\dohandleMPshade{\the\currentPDFshade}}} \defineMPspecial{31} {\expanded{\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA \expanded{\resolveMPrgbcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}}\to\MPshadeB \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs9 \gMPs{13} \gMPs{14} \gMPs{15}}% \dosetMPcircularshade{\gMPs{16}}} \defineMPspecial{33} {\expanded{\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA \expanded{\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}% \dosetMPcircularshade{\gMPs{18}}} \defineMPspecial{35} {\expanded{\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA \expanded{\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}% \dosetMPcircularshade{\gMPs{18}}} \newconditional\ignoreMPpath \def\dohandleMPshade#1% {\revokeMPtransparencyspecial \settrue\ignoreMPpath \def\extraMPpathcode{/Sh#1 sh Q}% \chardef\finiMPpath\zerocount \PDFcode{q /Pattern cs}} %D Figure inclusion is kind of strange to \METAPOST, but when %D Santiago Muelas started discussing this with me, I was able %D to cook up a solution using specials. \defineMPspecial{10} {\setxvalue{\@@MPSK\gMPs8}% {\noexpand\handleMPfigurespecial{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}{\gMPs8}}} \def\handleMPfigurespecial#1#2#3#4#5#6#7#8% todo : combine with ext fig {\global\letvalue{\@@MPSK#8}\empty \vbox to \zeropoint {\vss \hbox to \zeropoint {\ifcase\pdfoutput\or % will be hooked into the special driver \doiffileelse{#7} {\doifundefinedelse{mps:x:#7} {\immediate\pdfximage\!!width\onebasepoint\!!height\onebasepoint{#7}% \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}% {\message{[reusing figure #7]}}% \PDFcode{q #1 #2 #3 #4 #5 #6 cm}% \rlap{\getvalue{mps:x:#7}}% \PDFcode{Q}} {\message{[unknown figure #7]}}% \fi \hss}}} %D An example of using both special features is the %D following. %D %D \starttyping %D \startMPpage %D externalfigure "hakker1b.png" scaled 22cm rotated 10 shifted (-2cm,0cm); %D externalfigure "hakker1b.png" scaled 10cm rotated -10 ; %D externalfigure "hakker1b.png" scaled 7cm rotated 45 shifted (8cm,12cm) ; %D path p ; p := unitcircle xscaled 15cm yscaled 20cm; %D path q ; q := p rotatedaround(center p,90) ; %D path r ; r := buildcycle(p,q) ; clip currentpicture to r ; %D path s ; s := boundingbox currentpicture enlarged 5mm ; %D picture c ; c := currentpicture ; currentpicture := nullpicture ; %D circular_shade(s,0,.2red,.9red) ; %D addto currentpicture also c ; %D \stopMPpage %D \stoptyping %D This is some experimental hyperlink driver that I wrote %D for Mark Wicks. \defineMPspecial{20} {\setxvalue{\@@MPSK\gMPs6}% {\noexpand\handleMPhyperlink{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}}} \def\handleMPhyperlink#1#2#3#4#5#6% {\global\letvalue{\@@MPSK#6}\empty \setbox\scratchbox\hbox {\setbox\scratchbox\null \wd\scratchbox\dimexpr-#1\onebasepoint+#3\onebasepoint\relax \ht\scratchbox\dimexpr-#2\onebasepoint+#4\onebasepoint\relax \incolorfalse \gotobox{\box\scratchbox}[#5]}% \setbox\scratchbox\hbox {\hskip\dimexpr\MPxoffset\onebasepoint+#1\onebasepoint\relax \raise\dimexpr\MPyoffset\onebasepoint+#2\onebasepoint\relax \box\scratchbox}% \smashbox\scratchbox \box\scratchbox} %D This special (number 50) passes positions to a tex file. %D This method uses a two||pass approach an (mis|)|used the %D context positioning macros. In \type {core-pos} we will %D implement the low level submacro needed. %D %D \startbuffer %D \definelayer[test] %D %D \setlayer %D [test] %D [x=\MPx{somepos-1},y=\MPy{somepos-1}] %D {Whatever we want here!} %D %D \setlayer %D [test] %D [x=\MPx{somepos-2},y=\MPy{somepos-2}] %D {Whatever we need there!} %D %D \startuseMPgraphic{oeps} %D draw fullcircle scaled 6cm withcolor red ; %D register ("somepos-1",1cm,2cm,center currentpicture) ; %D register ("somepos-2",4cm,3cm,(-1cm,-2cm)) ; %D \stopuseMPgraphic %D %D \framed[background=test,offset=overlay]{\useMPgraphic{oeps}} %D \stopbuffer %D %D \typebuffer %D %D Here the width and height are not realy used, but one can %D imagine situations where tex has to work with values %D calculated by \METAPOST. %D %D \startlinecorrection %D \getbuffer %D \stoplinecorrection %D %D Later we will implement a more convenient macro: %D %D \starttyping %D \setMPlayer [test] [somepos-1] {Whatever we want here!} %D \setMPlayer [test] [somepos-2] {Whatever we need there!} %D \stoptyping \defineMPspecial{50} % x y width height label {\dosavepositionwhd {\gMPs5}% {0}% {\the\dimexpr-\MPllx\onebasepoint+\gMPs1\onebasepoint\relax} {\the\dimexpr\gMPs2\onebasepoint-\scratchdimen+\MPury\onebasepoint\relax}% {\the\dimexpr\gMPs3\onebasepoint\relax}% {\the\dimexpr\gMPs4\onebasepoint\relax}% {0pt}} %D A few auxiliary macros. This will move to colo-ini. \def\MPgrayspace{DeviceGray} \def\MPrgbspace {DeviceRGB} \def\MPcmykspace{DeviceCMYK} \let\MPspotspace\MPgrayspace \def\MPcmykBlack{0 0 0 0} \def\MPcmykWhite{0 0 0 1} \def\startMPcolorresolve {\bgroup \def\dostartgraycolormode##1% {\global\let\MPresolvedspace\MPgrayspace \xdef\MPresolvedcolor{##1}}% \def\dostartrgbcolormode ##1##2##3% {\global\let\MPresolvedspace\MPrgbspace \xdef\MPresolvedcolor{##1 ##2 ##3}}% \def\dostartcmykcolormode##1##2##3##4% {\global\let\MPresolvedspace\MPcmykspace \xdef\MPresolvedcolor{##1 ##2 ##3 ##4}}% \def\dostartspotcolormode##1##2% {\global\let\MPspotspace\empty \xdef\MPresolvedspace{##1}% \xdef\MPresolvedcolor{##2}% \global\let\MPspotspace\MPresolvedspace}% signal \dostartgraycolormode\!!zerocount} % kind of hackery initialization \let\stopMPcolorresolve\egroup \def\resolveMPrgbcolor#1#2#3\to#4% {\startMPcolorresolve \execcolorR#1:#2:#3:0:0\od \stopMPcolorresolve \let#4\MPresolvedcolor} \def\resolveMPcmykcolor#1#2#3#4\to#5% {\startMPcolorresolve \execcolorC#1:#2:#3:#4:0:0\od \stopMPcolorresolve \let#5\MPresolvedcolor} \def\resolveMPgraycolor#1\end\to#2% {\startMPcolorresolve \execcolorS#1:0:0\od \stopMPcolorresolve \let#2\MPresolvedcolor} \def\resolveMPspotcolor#1#2#3#4\end\to#5% {\startMPcolorresolve \ifnum#2>\plusone \checkmultitonecolor{#1}% \fi \execcolorP#1:#2:#3:#4:0:0\od \stopMPcolorresolve \let#5\MPresolvedcolor} %D \macros %D {dogetPDFmediabox} %D %D The next macro can be used to find the mediabox of a \PDF\ %D illustration. %D %D \starttyping %D \dogetPDFmediabox %D {filename} %D {new dimen}{new dimen}{new dimen}{new dimen} %D \stoptyping %D %D Beware of dimen clashes: this macro uses the 5~default %D scratch registers! When no file or mediabox is found, the %D dimensions are zeroed. \def\dogetPDFmediabox#1#2#3#4#5% {\bgroup \def\PDFxscale{1}% \def\PDFyscale{1}% \uncatcodespecials \endlinechar\minusone \def\checkPDFtypepage##1/Type /Page##2##3\done% {\ifx##2\relax \else\if##2s% accept /Page and /Pages \let\doprocessPDFline\findPDFmediabox \else \let\doprocessPDFline\findPDFmediabox \fi\fi}% \def\findPDFtypepage {\expandafter\checkPDFtypepage\fileline/Type /Page\relax\done}% \def\checkPDFmediabox##1/MediaBox##2##3\done% {\ifx##2\relax \else \setPDFmediabox##2##3\done \fileprocessedtrue \fi}% \def\findPDFmediabox {\expandafter\checkPDFmediabox\fileline/MediaBox\relax\done}% \let\doprocessPDFline\findPDFtypepage \doprocessfile\scratchread{#1}\doprocessPDFline \egroup \ifx\PDFxoffset\undefined #2=\zeropoint #3=\zeropoint #4=\zeropoint #5=\zeropoint \else #2=\PDFxoffset\onebasepoint #3=\PDFyoffset\onebasepoint #4=\PDFwidth #5=\PDFheight \fi} \def\setPDFboundingbox#1#2#3#4#5#6% {\dimen0=#1\dimen0=#5\dimen0 \ScaledPointsToBigPoints{\number\dimen0}\PDFxoffset \dimen0=#3\dimen0=#5\dimen0 \xdef\PDFwidth{\the\dimen0}% \dimen0=#2\dimen0=#6\dimen0 \ScaledPointsToBigPoints{\number\dimen0}\PDFyoffset \dimen0=#4\dimen0=#6\dimen0 \xdef\PDFheight{\the\dimen0}% \global\let\PDFxoffset\PDFxoffset \global\let\PDFyoffset\PDFyoffset} \def\setPDFmediabox#1[#2 #3 #4 #5]#6\done {\dimen2=#2\onebasepoint\dimen2=-\dimen2 % \dimen2=-#2\onebasepoint also works since tex handles -- \dimen4=#3\onebasepoint\dimen4=-\dimen4 % \dimen4=-#3\onebasepoint also works since tex handles -- \dimen6=#4\onebasepoint\advance\dimen6 \dimen2 \dimen8=#5\onebasepoint\advance\dimen8 \dimen4 \setPDFboundingbox{\dimen2}{\dimen4}{\dimen6}{\dimen8}\PDFxscale\PDFyscale} %D End of soon obsolete code. %D The plugins: \startMPinitializations mp_shade_version := 2 ; \stopMPinitializations \loadmarkfile{meta-pdf} %D Test code: % \startMPcode % fill fullcircle scaled 3cm withcolor red ; % fill fullcircle scaled 2cm withcolor green ; % fill fullcircle scaled 1cm withcolor blue ; % currentpicture := currentpicture shifted (-4cm,0) ; % fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ; % fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ; % fill fullcircle scaled 1cm withcolor cmyk(0,0,1,0) ; % currentpicture := currentpicture shifted (-4cm,0) ; % draw fullcircle scaled 3cm dashed evenly ; % draw fullcircle scaled 2cm dashed withdots ; % draw origin withpen pencircle scaled 3mm; % currentpicture := currentpicture shifted (-4cm,0) ; % fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red); % fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red); % fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green); % fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5)); % currentpicture := currentpicture shifted (12cm,-4cm) ; % draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ; % currentpicture := currentpicture shifted (-4cm,0) ; % % bug: shift % draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30 ; % draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ; % filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ; % currentpicture := currentpicture shifted (-4cm,0) ; % % shade cannot handle shift % circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ; % circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ; % filldraw boundingbox currentpicture enlarged -3cm withpen pencircle scaled 1pt withcolor .5white ; % \stopMPcode \protect \endinput