meta-pdh.mkiv / last modification: 2020-01-30 14:16
%D \module
%D   [       file=meta-pdf,
%D        version=2006.06.07,
%D          title=\METAPOST\ Graphics,
%D       subtitle=Conversion to \PDF,
%D         author=Hans Hagen \& others (see text),
%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.

\endinput

%D Formerly known as supp-pdf.tex and supp-mpe.tex and meta-pdf.mkiv.
%D
%D Beware: this file is not used but kept for historic purposed! Never
%D mix this one into mkiv again as it uses other variables.

% \useMPgraphic{1}
% \testfeatureonce{250}{\setbox0\hbox{\convertMPtoPDF{test-mps-mpgraph.1}{1}{1}}}
%
%  8.4 : mkii, direct parsing by tex
% 11.8 : mkiv, dirty conversion (10.8 with dirty tricks)
% 14.5 : mkiv, clean conversion
%  7.4 : mkiv, simulated clean direct lua from mp
%  0.3 : time taken by tex to handle converted code
%
% timings may differ now that we revamped the backend

\registerctxluafile{meta-pdf}{}

%D We will clean up the color mess later.

\writestatus{loading}{MetaPost Graphics / MPS to PDF}

\unprotect

%D First we define a handy constant:

\bgroup \catcode\commentasciicode\othercatcode \xdef\letterpercent{\string%} \egroup

%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
%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 \newconstant\makeMPintoPDFobject    \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%
  {\glet\MPwidth    \!!zeropoint
   \glet\MPheight   \!!zeropoint
   \glet\MPllx      \!!zerocount
   \glet\MPlly      \!!zerocount
   \glet\MPurx      \!!zerocount
   \glet\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% watch the transparency reset
  {\resetMPvariables{#1}{#2}{#3}%
   \vpack\bgroup
     \forgetall
     \offinterlineskip
     \setbox\scratchbox\vpack\bgroup
        \setnormalcatcodes % we can be in verbatim or so
        \message{[MP to PDF]}%
        \startMPresources
        \pdfliteral{\letterpercent\space mps begin}%
        \pdfliteral{q 1 0 0 1 0 0 cm}%
        \ctxlua{metapost.mptopdf.convertmpstopdf("\MPfilename")}\removeunwantedspaces
        \pdfliteral{Q}%
        \pdfliteral{\letterpercent\space mps end}%
        \stopMPresources
     \egroup
     \setbox\scratchbox\hpack\bgroup
        \hskip-\MPllx\onebasepoint
        \raise-\MPlly\onebasepoint
        \box\scratchbox
     \egroup
     \setbox\scratchbox\vpack to \MPheight\bgroup
       \vfill
       \hsize\MPwidth
       \smashbox\scratchbox
       \box\scratchbox
     \egroup
     \wd\scratchbox\MPwidth
     \ht\scratchbox\MPheight
     \dopackageMPgraphic\scratchbox
   \egroup}

\let\processMPtoPDFfile\convertMPtoPDF

%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)
     \makeMPintoPDFobject\plusone
   \fi\fi
   \ifcase\makeMPintoPDFobject
     \box#1%
   \or
     \scratchdimen\PDFMPformoffset\relax
     \ifdim\scratchdimen>\zeropoint % compensate for error
       \setbox#1\vpack spread 2\scratchdimen
         {\forgetall\vss\hpack spread 2\scratchdimen{\hss\box#1\hss}\vss}%
     \fi
     \setMPPDFobject{\currentPDFresources}{#1}%
     \ifdim\scratchdimen>\zeropoint % compensate for error
       \vpack to \MPheight
         {\forgetall\vss\hpack to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
     \else
       \getMPPDFobject
     \fi
     \glet\currentPDFresources\empty
   \else
     \box#1%
   \fi}

\def\setMPPDFobject#1#2% resources boxnumber
  {\ifx\everyPDFxform\undefined\else\the\everyPDFxform\fi
   \immediate\saveboxresource resources{#1}#2%
   \edef\getMPPDFobject{\noexpand\useboxresource\the\lastsavedboxresourceindex}}

\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 <size> <data> <number> <identifier>
%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  : <data> <number> <identifier> <size> 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
  \glet\currentPDFresources\empty % kind of redundant
\to \MPstartresources

% \appendtoks
%    \collectPDFresources
%    \glet\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

%D Specials:

% \settrue \manyMPspecials \newcount\nofMParguments \let\extraMPpathcode\empty
%
% \def\@@MP  {@@MP}
% \def\@@MPSK{@MPSK@}
%
% \def\MPspecial{\@@MPSK\@@MPSK\gMPs\nofMParguments}
%
% \unexpanded\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]}

% \let\revokeMPtransparencyspecial\relax

%D Transparency support used specials 60 (rgb) and 61
%D (cmyk).
%D
%D \startbuffer
%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 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\dosetMPsomePDFshade#1#2%
%   {\immediate\pdfobj
%      {<</FunctionType 2
%         /Domain [\gMPs1 \gMPs2]
%         /C0 [\MPshadeA]
%         /C1 [\MPshadeB]
%         /N \gMPs3>>}%
%    \immediate\pdfobj
%      {<</ShadingType #1
%         /ColorSpace /\MPresolvedspace
%         /Function \the\pdflastobj\space 0 R
%         /Coords [\MPshadeC]
%         /Extend [true true]>>}%
%    \global\advance\currentPDFshade \plusone
%    \ctxlua{lpdf.adddocumentshade("Sh\the\currentPDFshade",lpdf.reference(\the\pdflastobj))}%
%    \setxvalue{\@@MPSK#2}{\noexpand\dohandleMPshade{\the\currentPDFshade}}}
%
% \def\dosetMPlinearshade  {\dosetMPsomePDFshade2}% #1
% \def\dosetMPcircularshade{\dosetMPsomePDFshade3}% #1
%
% \defineMPspecial{30}
%   {\normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
%    \normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs{9}}{\gMPs{10}}{\gMPs{11}}}\to\MPshadeB
%    \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs{12} \gMPs{13}}%
%    \dosetMPlinearshade{\gMPs{14}}}
%
% \defineMPspecial{31}
%   {\normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
%    \normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}}\to\MPshadeB
%    \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs9 \gMPs{13} \gMPs{14} \gMPs{15}}%
%    \dosetMPcircularshade{\gMPs{16}}}
%
% \defineMPspecial{32}
%   {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
%    \normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
%    \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
%    \dosetMPlinearshade{\gMPs{16}}}
%
% \defineMPspecial{33}
%   {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
%    \normalexpanded{\noexpand\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{34}
%   {\normalexpanded{\noexpand\resolveMPspotcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
%    \normalexpanded{\noexpand\resolveMPspotcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
%    \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
%    \dosetMPlinearshade{\gMPs{16}}}
%
% \defineMPspecial{35}
%   {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
%    \normalexpanded{\noexpand\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}%
%    \pdfliteral{q /Pattern cs}}
%
% \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
%   {\letgvalueempty{\@@MPSK#8}%
%    \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\s!width\onebasepoint\s!height\onebasepoint{#7}%
%                  \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}%
%                 {\message{[reusing figure #7]}}%
%               \pdfliteral{q #1 #2 #3 #4 #5 #6 cm}%
%               \rlap{\getvalue{mps:x:#7}}%
%               \pdfliteral{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

% \defineMPspecial{20}
%   {\setxvalue{\@@MPSK\gMPs6}%
%      {\noexpand\handleMPhyperlink{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}}}
%
% \def\handleMPhyperlink#1#2#3#4#5#6%
%   {\letgvalueempty{\@@MPSK#6}%
%    \setbox\scratchbox\hbox
%      {\setbox\scratchbox\emptyhbox
%       \wd\scratchbox\dimexpr-#1\onebasepoint+#3\onebasepoint\relax
%       \ht\scratchbox\dimexpr-#2\onebasepoint+#4\onebasepoint\relax
%       \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

\startMPinitializations
  mp_shade_version := 2 ;
\stopMPinitializations

%D This is done much cleaner in \MPLIB.

\def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
  {\def\MPtextdata{#3}%  % delegate the splitter to lua + redesign
   \def\MPtextsize{#2}%
   \def\lastMPmoveX{#4}%
   \def\lastMPmoveY{#5}%
   \defconvertedcommand\MPtextdata\MPtextdata % no edef
   \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
   \executeifdefined{handleMPtext\MPtexttag}
     {\setbox\scratchbox\hbox % text
        {\font\temp=#1\space at #2\onebasepoint
         \let\c\char
         \temp
         \MPfshowcommand{#3}}%
      \setbox\scratchbox\hpack
        {\hskip#4\onebasepoint
         \raise#5\onebasepoint
         \box\scratchbox}%
      \smashbox\scratchbox
      \box\scratchbox}}

%D We save the special variables on a stack. It's not that
%D fast, but it make implementing the special more convenient.

% \def\MPSbegin
%   {\nofMParguments\zerocount}
%
% \def\MPSend
%   {\csname\MPspecial\endcsname}
%
% \def\MPSset
%   {\advance\nofMParguments\plusone
%    \expandafter\def\csname\@@MP\number\nofMParguments\endcsname}
%
% \def\gMPs#1{\csname\@@MP\number#1\endcsname}

%D The boundingbox.

\def\MPSboundingbox#1#2#3#4%
  {\xdef\MPllx{#1}\xdef\MPlly{#2}\xdef\MPurx{#3}\xdef\MPury{#4}%
   \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
   \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}

\MPSboundingbox0000

% \def\MPSspecial#1#2%
%   {\csname\@@MPSK#2\endcsname}

%D A path is (in most cases) just a sequence of \PDF\ commands.

% \newconditional\ignoreMPpath

% \def\MPSpath
%   {\pdfliteral}

% \def\MPScode % hack, will be improved
%   {\ifconditional\ignoreMPpath
%      \pdfliteral{h W n}%
%      \ifx\extraMPpathcode\empty\else
%        \pdfliteral{\extraMPpathcode}%
%        \let\extraMPpathcode\empty
%      \fi
%      \setfalse\ignoreMPpath
%      \expandafter\gobbleoneargument
%    \else
%      \expandafter\pdfliteral
%    \fi}

%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

% We cannot use attributes for switching colors in mp literals because
% grouping (qQ) interferes.

% \def\dohandleMPshade#1%
%   {\revokeMPtransparencyspecial
%    \settrue\ignoreMPpath
%    \def\extraMPpathcode{/#1 sh Q}%
%    \pdfliteral{q /Pattern cs}}

\protect \endinput