%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 In due time this file will replace \type {supp-pdf} and
%D \type {supp-mpe}.

% \input supp-pdf
% \input supp-mpe
%
% \endinput

% we're going to experiment a bit with new code

%D To be tested: texopt.rb on this file.

%D Prelude to an optimized version:

%D \module
%D   [       file=supp-pdf,
%D        version=2004.12.16,
%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 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 \zeropoint here since it may be
% defined in the range \dimen 0 - 20 which we happen to use
% as scratch registers; inside context we may consider
% using dedicated registers.

%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 / PDF (2004.03.26)}

\unprotect

\ifx\PDFcode\undefined
  \ifx\pdfliteral\undefined
    \def\PDFcode#1{\special{PDF: #1}}
  \else\ifx\pdfoutput\undefined
    \def\PDFcode#1{\special{PDF: #1}}
  \else\ifcase\pdfoutput
    \def\PDFcode#1{\special{PDF: #1}}
  \else % pdftex as well as in pdf mode
    \let\PDFcode\pdfliteral
  \fi\fi\fi
\else
  % we probably use context
\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  <optional dimensions> {file}
%D \pdfimages <optional dimensions> {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 <optional dimensions> {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\wd\scratchbox
     \advance\hsize -#3%
     \advance\hsize -#4%
     \vsize\ht\scratchbox
     \advance\vsize -#5%
     \advance\vsize -#6%
     \setbox\scratchbox\vbox to \vsize
       {\vskip-#5\hbox to \hsize{\hskip-#3\box\scratchbox\hss}}%
     \pdfxform\scratchbox
     \pdfrefxform\pdflastxform
     \egroup}

\fi \fi

%D If you want to save a few hash entries, you may prefer the
%D less readable alternatives, like:
%D
%D \starttyping
%D \def\pdfimage#1#% This one is less readable but needs no additional
%D   {\bgroup      % hash entry for the second stage macro.
%D    \def\pdfimage##1%
%D      {\immediate\pdfximage##1{#2}%
%D       \pdfrefximage\pdflastximage\egroup}}
%D \stoptyping

%D \macros
%D   {convertMPtoPDF}
%D
%D The next set of macros implements \METAPOST\ to \PDF\
%D conversion. Because we want to test as fast as possible, we
%D first define the \POSTSCRIPT\ operators that \METAPOST\
%D uses. We don't define irrelevant ones, because these are
%D skipped anyway.

%D The converter can be made a bit faster by replacing the
%D two test macros (the ones with the many \type {\if's}) by
%D a call to named branch macros (something \typ {\getvalue
%D {xPSmoveto}}. For everyday documents with relatively
%D small graphics the gain in speed can be neglected.

\def \PScurveto          {curveto}
\def \PSlineto           {lineto}
\def \PSmoveto           {moveto}
\def \PSshowpage         {showpage}
\def \PSnewpath          {newpath}
\def \PSfshow            {fshow}
\def \PSclosepath        {closepath}
\def \PSfill             {fill}
\def \PSstroke           {stroke}
\def \PSclip             {clip}
\def \PSrlineto          {rlineto}
\def \PSsetlinejoin      {setlinejoin}
\def \PSsetlinecap       {setlinecap}
\def \PSsetmiterlimit    {setmiterlimit}
\def \PSsetgray          {setgray}
\def \PSsetrgbcolor      {setrgbcolor}
\def \PSsetcmykcolor     {setcmykcolor}
\def \PSsetdash          {setdash}
\def \PSgsave            {gsave}
\def \PSgrestore         {grestore}
\def \PStranslate        {translate}
\def \PSscale            {scale}
\def \PSconcat           {concat}
\def \PSdtransform       {dtransform}
\def \PSsetlinewidth     {setlinewidth}
\def \PSpop              {pop}

\def \PSnfont            {nfont}    % was needed for TUG98 proceedings
\def \PSspecial          {special}  % extensions to MetaPost

%D A previous version set \type {%} to ignore, which
%D simplified the following definitions. At the start of
%D conversion the percent character was made active again.
%D Because the whole graphic is one paragraph (there are no
%D empty lines) this does not give the desired effect. This
%D went unnoticed untill Scott Pakin sent me a test file
%D percent characters in a string. So, from now on we have
%D to prefix the following strings with percentages.

%D Some day I'll figure out a better solution (line by line reading
%D using \ETEX).

\edef \PSBoundingBox      {\letterpercent\letterpercent BoundingBox:}
\edef \PSHiResBoundingBox {\letterpercent\letterpercent HiResBoundingBox:}
\edef \PSExactBoundingBox {\letterpercent\letterpercent ExactBoundingBox:}
\edef \PSMetaPostSpecial  {\letterpercent\letterpercent MetaPostSpecial:}
\edef \PSMetaPostSpecials {\letterpercent\letterpercent MetaPostSpecials:}
\edef \PSPage             {\letterpercent\letterpercent Page:}

%D By the way, the \type {setcmykcolor} operator is not
%D output by \METAPOST\ but can result from converting the
%D \cap{RGB} color specifications, as implemented in
%D \type{supp-mps}.

%D In \POSTSCRIPT\ arguments precede the operators. Due to the
%D fact that in some translations we need access to those
%D arguments, and also because sometimes we have to skip them,
%D we stack them up. The stack is one||dimensional for non path
%D operators and two||dimensional for operators inside a path.
%D This is because we have to save the whole path for
%D (optional) postprocessing. Values are pushed onto the stack
%D by:
%D
%D \starttyping
%D \setMPargument {value}
%D \stoptyping
%D
%D They can be retrieved by the short named macros:
%D
%D \starttyping
%D \gMPa {number}
%D \gMPs {number}
%D \stoptyping
%D
%D When scanning a path specification, we also save the
%D operator, using
%D
%D \starttyping
%D \setMPkeyword {n}
%D \stoptyping
%D
%D The path drawing operators are coded for speed: \type{clip},
%D \type{stroke}, \type{fill} and \type{fillstroke} become
%D 1, 2, 3 and~4.
%D
%D When processing the path this code can be retrieved
%D using
%D
%D \starttyping
%D \getMPkeyword % {n}
%D \stoptyping
%D
%D When setting an argument, the exact position on the stack
%D depends on the current value of the \COUNTERS\
%D \type{\nofMPsegments} and \type{\nofMParguments}.

\newcount\nofMPsegments
\newcount\nofMParguments

%D These variables hold the coordinates. The argument part of
%D the stack is reset by:
%D
%D \starttyping
%D \resetMPstack
%D \stoptyping
%D
%D We use the prefix \type{@@MP} to keep the stack from
%D conflicting with existing macros. To speed up things a bit
%D more, we use the constant \type{\@@MP}.

\def\@@MP{@@MP}

\def\setMPargument% #1%
  {\advance\nofMParguments \plusone
   \expandafter\def
     \csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname} % {#1}

\def\letMPargument
  {\advance\nofMParguments \plusone
   \expandafter\let
     \csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname}

\def\setMPsequence#1 %
  {\advance\nofMParguments \plusone
   \expandafter\def
     \csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname{#1}%
   \handleMPsequence}

\def\gMPa#1%
  {\csname\@@MP0\number#1\endcsname}

\def\gMPs#1%
  {\csname\@@MP\the\nofMPsegments\number#1\endcsname}

\def\dogMPa#1%
  {\@EAEAEA\do\csname\@@MP0\number#1\endcsname}

\def\setMPkeyword#1 %
  {\expandafter\def\csname\@@MP\the\nofMPsegments0\endcsname{#1}%
   \advance\nofMPsegments \plusone
   \nofMParguments\zerocount}

\def\getMPkeyword% #1%
  {\csname\@@MP\the\nofMPsegments0\endcsname} % {\csname\@@MP#10\endcsname}

\def\docleanupMPargument#1% we need this because args can have [ or ] pre/appended
  {\expandafter\edef\csname\@@MP\the\nofMPsegments\number#1\endcsname
     {\csname\@@MP\the\nofMPsegments\number#1\endcsname}}

%D When we reset the stack, we can assume that all further
%D comment is to be ignored and handled in strings.
%D By redefining the reset macro after the first call, we
%D save some run time. Only use this macro after all
%D comments are processed and use the simple alternative
%D when dealing with comments.

\def\doresetMPstack
  {\nofMParguments\zerocount}

\def\resetMPstack
  {\let\handleMPgraphic\handleMPendgraphic
   \let\resetMPstack\doresetMPstack
   \resetMPstack}

%D The arguments are saved with the preceding command
%D \type{\do}. By default this command expands to nothing, but
%D when we deal with strings it's used to strip off the
%D \type{(} and \type{)}.
%D
%D Strings are kind of tricky, because characters can be
%D passed verbatim \type{(hello)}, by octal number
%D \type{(\005)} or as command \type{(\()}. We therefore
%D cannot simply ignore \type{(} and \type{)}, the way we do
%D with \type{[} and \type{]}. Another complication is that
%D strings may contain characters that normally have a
%D special meaning in \TEX, like \type{$} and \type{{}}.
%D
%D A previous solution made \type{\} an active character and
%D let it look ahead for a number or characters. We had to
%D abandon this scheme because of the need for verbatim
%D support. The next solution involved some \CATCODE\
%D trickery but works well.

\def\octalMPcharacter#1#2#3%
  {\char'#1#2#3\relax}

%D curly braces and squarly brackets are stored in the argument stack
%D as part  of strings, for instance in:
%D
%D \starttyping
%D /fshow {exch findfont exch scalefont setfont show}bind def
%D [3 3 ] 0 setdash
%D \stoptyping
%D
%D but we need to keep them in situation like
%D
%D \starttyping
%D ([bla bla] bla bla) ec-lmr10 9.96265 fshow
%D ({bla bla} bla bla) ec-lmr10 9.96265 fshow
%D \stoptyping
%D
%D So, when we store the snippets, we keep the special tokens, and
%D when needed we either ignore or obey them

\bgroup
\catcode`\|=\@@comment
\catcode`\%=\@@active
\catcode`\[=\@@active
\catcode`\]=\@@active
\catcode`\{=\@@active
\catcode`\}=\@@active
\catcode`B=\@@begingroup
\catcode`E=\@@endgroup
\gdef\keepMPspecials|
  B\let%\letterpercent|
   \def[B\noexpand[E|
   \def]B\noexpand]E|
   \def{B\noexpand{E|
   \def}B\noexpand}EE
\gdef\ignoreMPspecials|
  B\let%\letterpercent|
   \def[BE|
   \def]BE|
   \def{BE|
   \def}BEE
\gdef\obeyMPspecials|
  B\def%B\char 37\relax E|
   \def[B\char 91\relax E|
   \def]B\char 93\relax E|
   \def{B\char123\relax E|
   \def}B\char125\relax EE
\gdef\setMPspecials|
  B\setnaturalcatcodes
   \catcode`\\=\@@escape
   \catcode`\%=\@@active
   \catcode`\[=\@@active
   \catcode`\]=\@@active
   \catcode`\{=\@@active
   \catcode`\}=\@@active
   \lccode`\-=0 | latex sets this to `\-
   \lccode`\%=`\% | otherwise it's seen as a number
   \def\(B\char40\relax     E|
   \def\)B\char41\relax     E|
   \def\\B\char92\relax     E|
   \def\0B\octalMPcharacter0E|
   \def\1B\octalMPcharacter1E|
   \def\2B\octalMPcharacter2E|
   \def\3B\octalMPcharacter3E|
   \def\4B\octalMPcharacter4E|
   \def\5B\octalMPcharacter5E|
   \def\6B\octalMPcharacter6E|
   \def\7B\octalMPcharacter7E|
   \def\8B\octalMPcharacter8E|
   \def\9B\octalMPcharacter9EE
\egroup

%D We use the comment symbol as a sort of trigger. Beware!
%D The whole graphic is seen as on eparagraph, which means
%D that we cannot change the catcodes in between.

\bgroup
\catcode`\%=\@@active
\gdef\startMPscanning{\let%=\startMPconversion}
\egroup

%D In earlier versions we used the sequence
%D
%D \starttyping
%D \expandafter\handleMPsequence\input filename\relax
%D \stoptyping
%D
%D Persistent problems in \LATEX\ however forced us to use a
%D different scheme. Every \POSTSCRIPT\ file starts with a
%D \type{%}, so we temporary make this an active character
%D that starts the scanning and redefines itself. (The problem
%D originates in the redefinition by \LATEX\ of the
%D \type{\input} primitive.)

\def\startMPconversion
  {\keepMPspecials
   \handleMPsequence}

%D Here comes the main loop. Most arguments are numbers. This
%D means that they can be recognized by their \type{\lccode}.
%D This method saves a lot of processing time. We could
%D speed up the conversion by handling the \type{path}
%D seperately.

\def\@EAEAEA{\expandafter\expandafter\expandafter} % to be sure

\def\dohandleMPsequence#1%
  {\ifdone
     \ifcase\lccode`#1\relax
       \@EAEAEA\dohandleMPsequenceA
     \else
       \@EAEAEA\dohandleMPsequenceB
     \fi
   \else
     \@EA\dohandleMPsequenceC
   \fi#1}

\let\dohandleMPsequenceA\setMPsequence

\def\dohandleMPsequenceB#1 %
  {\edef\somestring{#1}%
   \ifx\somestring\PSmoveto
     \edef\lastMPmoveX{\gMPa1}%
     \edef\lastMPmoveY{\gMPa2}%
     \PDFcode{\!MPgMPa1 \!MPgMPa2 m}%
     \resetMPstack
   \else\ifx\somestring\PSnewpath
     \let\handleMPsequence\handleMPpath
   \else\ifx\somestring\PSgsave
     \PDFcode{q}%
     \resetMPstack
   \else\ifx\somestring\PSgrestore
     \PDFcode{Q}%
     \resetMPstack
   \else\ifx\somestring\PSdtransform  % == setlinewidth
     \let\handleMPsequence\handleMPdtransform
     % after that we will encounter more tokens until setlinewidth+pop
     % or pop+setlinewidth which we catch next; we explicitly need to
     % reset the stack since [] n setdash may follow; a more clever
     % approach would be to read on till the condition is met, but it's
     % the only pop / setlinewidth we will encounter so ...
   \else\ifx\somestring\PSsetlinewidth
     % already handled in dtransform
     \resetMPstack
   \else\ifx\somestring\PSpop
     % already handled in dtransform
     \resetMPstack
   \else\ifx\somestring\PSconcat
     \cleanupMPconcat
     \PDFcode{\gMPa1 \gMPa2 \gMPa3 \gMPa4 \gMPa5 \gMPa6 cm}%
     \resetMPstack
   \else\ifx\somestring\PSsetrgbcolor
     \handleMPrgbcolor
     \resetMPstack
   \else\ifx\somestring\PSsetcmykcolor
     \handleMPcmykcolor
     \resetMPstack
   \else\ifx\somestring\PSsetgray
     \handleMPgraycolor
     \resetMPstack
   \else\ifx\somestring\PStranslate
     \PDFcode{1 0 0 1 \gMPa1 \gMPa2 cm}%
     \resetMPstack
   \else\ifx\somestring\PSsetdash
     \handleMPsetdash
     \resetMPstack
   \else\ifx\somestring\PSsetlinejoin
     \PDFcode{\gMPa1 j}%
     \resetMPstack
   \else\ifx\somestring\PSsetmiterlimit
     \PDFcode{\gMPa1 M}%
     \resetMPstack
   \else\ifx\somestring\PSfshow
     \PDFcode{n}%
     \handleMPfshow
     \resetMPstack
   \else\ifx\somestring\PSsetlinecap
     \PDFcode{\gMPa1 J}%
     \resetMPstack
   \else\ifx\somestring\PSrlineto
     \PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l S}%
     \resetMPstack
   \else\ifx\somestring\PSscale
     \PDFcode{\gMPa1 0 0 \gMPa2 0 0 cm}%
     \resetMPstack
   \else\ifx\somestring\PSspecial
     \handleMPspecialcommand
     \resetMPstack
   \else
     \handleMPgraphic% {#1}%
   \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
   \handleMPsequence}

\def\dohandleMPsequenceC#1 %
  {\edef\somestring{#1}%
   \handleMPgraphic % {#1}%
   \handleMPsequence}

%D Since colors are not sensitive to transformations, they
%D are sometimes used for signaling. Therefore, we handle them
%D separately. The next macro can be redefined if needed.

\def\handleMPrgbcolor
  {\PDFcode{\!MPgMPa1 \!MPgMPa2 \!MPgMPa3 rg
            \!MPgMPa1 \!MPgMPa2 \!MPgMPa3 RG}}

\def\handleMPcmykcolor
  {\PDFcode{\!MPgMPa1 \!MPgMPa2 \!MPgMPa3 \!MPgMPa4 k
            \!MPgMPa1 \!MPgMPa2 \!MPgMPa3 \!MPgMPa4 K}}

\def\handleMPgraycolor
  {\PDFcode{\!MPgMPa1 g
            \!MPgMPa1 G}}

\def\handleMPspotcolor
  {\PDFcode{0 g
            0 G}}

%D Beginning and ending the graphics is taken care of by the
%D macro \type{\handleMPgraphic}, which is redefined when
%D the first graphics operator is met.

\def\handleMPendgraphic % #1%
  {\ifx\somestring\PSshowpage
     \let\handleMPsequence\finishMPgraphic
   \else
     \letMPargument\somestring % {#1}%
   \fi}

\def\handleMPbegingraphic % #1%
  {\ifx\somestring\PSBoundingBox
     \def\handleMPsequence{\handleMPboundingbox1}%
   \else\ifx\somestring\PSHiResBoundingBox
     \def\handleMPsequence{\handleMPboundingbox2}%
   \else\ifx\somestring\PSExactBoundingBox
     \def\handleMPsequence{\handleMPboundingbox3}%
   \else\ifx\somestring\PSshowpage
     \let\handleMPsequence\finishMPgraphic
   \else\ifx\somestring\PSPage
     \let\handleMPsequence\handleMPpage
   \else\ifx\somestring\PSMetaPostSpecials
     \let\handleMPsequence\handleMPspecialscomment
   \else\ifx\somestring\PSMetaPostSpecial
     \let\handleMPsequence\handleMPspecialcomment
   \else
     \letMPargument\somestring % {#1}%
   \fi\fi\fi\fi\fi\fi\fi}

\let\handleMPgraphic=\handleMPbegingraphic

%D We check for three kind of bounding boxes: the normal one
%D and two high precision ones:
%D
%D \starttyping
%D BoundingBox: llx lly ucx ucy
%D HiResBoundingBox: llx lly ucx ucy
%D ExactBoundingBox: llx lly ucx ucy
%D \stoptyping
%D
%D The original as well as the recalculated dimensions are
%D saved for later use.

\newif\ifskipemptyMPgraphic \skipemptyMPgraphicfalse

\chardef\currentMPboundingbox=0

\def\handleMPboundingbox#1#2 #3 #4 #5
  {\ifnum#1>\currentMPboundingbox
     \xdef\MPllx{#2}\xdef\MPlly{#3}%
     \xdef\MPurx{#4}\xdef\MPury{#5}%
     \dimen0=#2\onepoint
     \dimen0=-\MPxscale\dimen0
     \dimen2=#3\onepoint
     \dimen2=-\MPyscale\dimen2
     \xdef\MPxoffset{\withoutpt\the\dimen0}%
     \xdef\MPyoffset{\withoutpt\the\dimen2}%
     \dimen0=#2\onebasepoint
     \dimen0=-\dimen0
     \dimen2=#3\onebasepoint
     \dimen2=-\dimen2
     \advance\dimen0 #4\onebasepoint
     \dimen0=\MPxscale\dimen0
     \xdef\MPwidth{\the\dimen0}%
     \advance\dimen2 #5\onebasepoint
     \xdef\MPyshift{\the\dimen2}% unscaled
     \dimen2=\MPyscale\dimen2
     \xdef\MPheight{\the\dimen2}%
     \chardef\currentMPboundingbox#1\relax
   \fi
   \doresetMPstack
   \let\handleMPsequence\dohandleMPsequence
   \let\next\handleMPsequence
   \ifskipemptyMPgraphic
     \ifdim\MPheight=\zeropoint\relax\ifdim\MPwidth=\zeropoint\relax
       \def\next{\endinput\finishMPgraphic}%
     \fi\fi
   \fi
   \next}

%D Unless defined otherwise, we simply ignore specialcomments.

\def\handleMPspecialcomment
  {\doresetMPstack
   \let\handleMPsequence\dohandleMPsequence
   \handleMPsequence}

\let\handleMPspecialscomment\handleMPspecialcomment

%D We use the \type{page} comment as a signal that
%D stackbuilding can be started.

\def\handleMPpage #1 #2
  {\doresetMPstack
   \donetrue
   \let\handleMPsequence\dohandleMPsequence
   \handleMPsequence}

%D The same applies to the special extensions.

\def\handleMPspecialcommand
  {\doresetMPstack
   \let\handleMPsequence\dohandleMPsequence
   \handleMPsequence}

%D \METAPOST\ draws its dots by moving to a location and
%D invoking \type{0 0 rlineto}. This operator is not
%D available in \PDF. Our solution is straightforward: we draw
%D a line from $(current\_x, current\_y)$ to itself. This
%D means that the arguments of the preceding \type{moveto} have
%D to be saved.

\def\lastMPmoveX{0}
\def\lastMPmoveY{0}

%D These saved coordinates are also used when we handle the
%D texts. Text handling proved to be a bit of a nuisance, but
%D finally I saw the light. It proved that we also had to
%D take care of \type{(split arguments)}.

\def\setMPfshowfont#1#2%
  {\font\temp=#1\space at #2\relax\temp}

\let\MPfshowcommand\empty

% \def\dohandleMPfshow
%   {\bgroup
%    \setbox\scratchbox\hbox
%      {\obeyMPspecials
%       \let\ \relax % mp breaks long lines and appends a \
%       \edef\size{\gMPa\nofMParguments}%
%       \ifx\size\PSnfont % round font size (to pt)
%         \advance\nofMParguments \minusone
%         \expandafter\scratchdimen\gMPa\nofMParguments\onepoint\relax
%         \ifdim\scratchdimen<\onepoint
%           \def\size{1pt}%
%         \else
%           \advance\scratchdimen .5\onepoint
%           \def\size##1.##2\relax{\def\size{##1pt}}%
%           \expandafter\size\the\scratchdimen\relax
%         \fi
%       \else
%         \edef\size{\size bp}%
%       \fi
%       \advance\nofMParguments \minusone
%      %\font\temp=\gMPa\nofMParguments\space at \size
%       \let\temp\relax % to be sure
%       \setMPfshowfont{\gMPa\nofMParguments}\size
%       \advance\nofMParguments \minusone
%       \temp
%       \MPfshowcommand
%         {\ifnum\nofMParguments=\plusone
%            \def\do(##1){##1}%
%            \dogMPa1%
%          \else
%            % we need to catch ( a ) (a a a) (\123 \123 \123) etc
%            \scratchcounter\plusone
%            \def\dodo##1% Andreas Fieger's bug: (\304...)
%              {\edef\!!stringa{##1\empty\empty}% and another one: ( 11) -> \ifx 11
%               \ifx\!!stringa\MPspacechar\MPspacechar\else\expandafter##1\fi}%
%            \def\do(##1{\dodo{##1}}%
%            \dogMPa\scratchcounter\MPspacechar
%            \let\do\relax
%            \loop
%              \advance\scratchcounter \plusone
%              \ifnum\scratchcounter<\nofMParguments\relax
%                \gMPa\scratchcounter\MPspacechar
%            \repeat
%            \def\do##1){\dodo{##1}}%
%            \dogMPa\scratchcounter
%          \fi
%          \unskip}}%
%   %
%   % this fails in some versions of pdftex
%   %
%   % \dimen0=\lastMPmoveY bp
%   % \advance\dimen0 by \ht0
%   % \ScaledPointsToBigPoints{\number\dimen0}\lastMPmoveY
%   % \PDFcode{n q 1 0 0 1 \lastMPmoveX\space\lastMPmoveY\space cm}%
%   % \dimen0=\ht0
%   % \advance\dimen0 by \dp0
%   % \box0
%   % \vskip-\dimen0
%   % \PDFcode{Q}%
%   % \egroup}
%   %
%    \setbox\scratchbox\hbox
%      {\hskip\lastMPmoveX\onebasepoint\raise\lastMPmoveY\onebasepoint\box\scratchbox}%
%    \ht\scratchbox\zeropoint
%    \dp\scratchbox\zeropoint
%    \wd\scratchbox\zeropoint
%    \box\scratchbox
%    \egroup}
%
% \let\handleMPfshow\dohandleMPfshow % so we can overload this one later
%
% we will support plug-ins:

\def\dohandleMPfshow
  {\setbox\scratchbox\hbox
     {\obeyMPspecials
      \edef\MPtextsize{\gMPa\nofMParguments}%
      \def\do(##1){##1}%
      \edef\MPtextdata{\dogMPa1}% beware, stack can have more
      \handleMPtext}%
   \setbox\scratchbox\hbox
     {\hskip\lastMPmoveX\onebasepoint\raise\lastMPmoveY\onebasepoint
      \box\scratchbox}%
  %
  % this fails in some versions of pdftex
  %
  % \dimen0=\lastMPmoveY bp
  % \advance\dimen0 by \ht0
  % \ScaledPointsToBigPoints{\number\dimen0}\lastMPmoveY
  % \PDFcode{n q 1 0 0 1 \lastMPmoveX\space\lastMPmoveY\space cm}%
  % \dimen0=\ht0
  % \advance\dimen0 by \dp0
  % \box0
  % \vskip-\dimen0
  % \PDFcode{Q}%
  % \egroup}
  %
   \ht\scratchbox\zeropoint
   \dp\scratchbox\zeropoint
   \wd\scratchbox\zeropoint
   \box\scratchbox}

\def\handleMPtext {\handleMPtextnormal} % so we can overload this one later
\def\handleMPfshow{\dohandleMPfshow   } % so we can overload this one later

\def\handleMPtext
  {\ifnum\nofMParguments>\plusthree
     \handleMPtextnormal
   \else
     \convertcommand\MPtextdata\to\MPtextdata
     \expanded{\splitstring\MPtextdata}\at::::\to\MPtexttag\and\MPtextnumber
     \executeifdefined{handleMPtext\MPtexttag}\handleMPtextnormal
   \fi}

% elsewhere we will implement \handleMPtextmptxt

\def\handleMPtextnormal
  {\let\ \relax % mp breaks long lines and appends a \
   \ifx\MPtextsize\PSnfont % round font size (to pt)
     \advance\nofMParguments \minusone
     \expandafter\scratchdimen\gMPa\nofMParguments\onepoint\relax
     \ifdim\scratchdimen<\onepoint
       \def\MPtextsize{1pt}%
     \else
       \advance\scratchdimen .5\onepoint
       \def\MPtextsize##1.##2\relax{\def\MPtextsize{##1pt}}%
       \expandafter\MPtextsize\the\scratchdimen\relax
     \fi
   \else
     \edef\MPtextsize{\MPtextsize bp}%
   \fi
   \advance\nofMParguments \minusone
   \font\temp=\gMPa\nofMParguments\space at \MPtextsize
   \let\temp\relax % to be sure
   \setMPfshowfont{\gMPa\nofMParguments}\MPtextsize
   \advance\nofMParguments \minusone
   \temp
   \MPfshowcommand
     {\ifnum\nofMParguments=\plusone
        \def\do(##1){##1}%
        \dogMPa1%
      \else
        % we need to catch ( a ) (a a a) (\123 \123 \123) etc
        \scratchcounter\plusone
        \def\dodo##1% Andreas Fieger's bug: (\304...)
          {\edef\!!stringa{##1\empty\empty}% and another one: ( 11) -> \ifx 11
           \ifx\!!stringa\MPspacechar\MPspacechar\else\expandafter##1\fi}%
        \def\do(##1{\dodo{##1}}%
        \dogMPa\scratchcounter\MPspacechar
        \let\do\relax
        \loop
          \advance\scratchcounter \plusone
          \ifnum\scratchcounter<\nofMParguments\relax
            \gMPa\scratchcounter\MPspacechar
        \repeat
        \def\do##1){\dodo{##1}}%
        \dogMPa\scratchcounter
      \fi
      \unskip}}

%D You could consider the following definition to be the most
%D natural one.

% \def\MPspacechar{\space} % normal case

\def\MPspacechar{\char32\relax} % old solution does not work with math

%D However, the following implementation is more robust, since
%D some fonts have funny visible spaces in the space slot. This
%D gives a mismatch between the space that \METAPOST\ took into
%D account and the \quote {natural} space. This only happens in
%D labels, since \type {btex}||\type {etex} thingies don't have
%D spaces. This phenomena showed up when preparing the
%D \METAFUN\ manual, where Palatino fonts are used. We can
%D safely assume that \METAPOST\ considers \type {\char32} to
%D be the space.

\def\MPspacechar{\setbox\scratchbox\hbox{\char32}\kern\wd\scratchbox}

%D Well, this does not work with math fonts, so:

\def\MPspacechar{\char32\relax}

%D Most operators are just converted and keep their
%D arguments. Dashes however need a bit different treatment,
%D otherwise \PDF\ viewers complain loudly. Another
%D complication is that one argument comes after the \type{]}.
%D When reading the data, we simply ignore the array boundary
%D characters. We save ourselves some redundant newlines and
%D at the same time keep the output readable by packing the
%D literals.

\def\handleMPsetdash
  {\bgroup
   \ignoreMPspecials
   \def\somestring{[}%
   \scratchcounter\plusone
   \loop
     \ifnum\scratchcounter<\nofMParguments
       \edef\somestring{\somestring\space\gMPa\scratchcounter}%
       \advance\scratchcounter \plusone
   \repeat
   \edef\somestring{\somestring]\gMPa\scratchcounter\space d}%
   \PDFcode{\somestring}%
   \egroup}

%D The \type{setlinewidth} commands looks a bit complicated. There are
%D two alternatives, that result in a similar look in both
%D $x$- and $y$-dorection. As John Hobby says:
%D
%D \startnarrower \switchtobodyfont[ss]
%D \starttyping
%D x 0 dtransform exch truncate exch idtransform pop setlinewidth
%D 0 y dtransform truncate idtransform setlinewidth pop
%D \stoptyping
%D
%D These are just fancy versions of \type{x setlinewidth} and
%D \type{y setlinewidth}. The \type{x 0 ...} form is used if
%D the path is {\em primarily vertical}. It rounds the width
%D so that vertical lines come out an integer number of pixels
%D wide in device space. The \type{0 y ...} form does the same
%D for paths that are {\em primarily horizontal}. The reason
%D why I did this is Knuth insists on getting exactly the
%D widths \TEX\ intends for the horizontal and vertical rules
%D in \type{btex...etex} output. (Note that PostScript scan
%D conversion rules cause a horizontal or vertical line of
%D integer width $n$ in device space to come out $n+1$ pixels
%D wide, regardless of the phase relative to the pixel grid.)
%D \stopnarrower
%D
%D The common operator in these sequences is \type{dtransform},
%D so we can use this one to trigger setting the linewidth.

\def\handleMPdtransform
  {\ifdim\gMPa1\onepoint>\zeropoint
     \PDFcode{\gMPa1 w}%
     \def\next##1 ##2 ##3 ##4 ##5 ##6 {\handleMPsequence}%
   \else
     \PDFcode{\gMPa2 w}%
     \def\next##1 ##2 ##3 ##4 {\handleMPsequence}%
   \fi
   \let\handleMPsequence\dohandleMPsequence
   \resetMPstack
   \next}

%D The most complicated command is \type{concat}. \METAPOST\
%D applies this operator to \type{stroke}. At that moment the
%D points set by \type{curveto} and \type{moveto}, are already
%D fixed. In \PDF\ however the \type{cm} operator affects the
%D points as well as the pen (stroke). Like more \PDF\
%D operators, \type{cm} is defined in a bit ambiguous way.
%D The only save route for non||circular penshapes, is saving
%D the path, recalculating the points and applying the
%D transformation matrix in such a way that we can be sure
%D that its behavior is well defined. This comes down to
%D inverting the path and applying \type{cm} to that path as
%D well as the pen. This all means that we have to save the
%D path.

%D In \METAPOST\ there are three ways to handle a path $p$:
%D
%D \starttyping
%D draw p;  fill p;  filldraw p;
%D \stoptyping
%D
%D The last case outputs a \type{gsave fill grestore} before
%D \type{stroke}. Handling the path outside the main loops
%D saves about 40\% run time.\footnote{We can save some more by
%D following the \METAPOST\ output routine, but for the moment
%D we keep things simple.} Switching between the main loop and
%D the path loop is done by means of the recursely called
%D macro \type{\handleMPsequence}.

\def\handleMPpath
  {\chardef\finiMPpath0
   \let\closeMPpath\relax
   \let\flushMPpath\flushnormalMPpath
   \resetMPstack
   \nofMPsegments\plusone
   \let\handleMPsequence\dohandleMPpath
   \dohandleMPpath}

%D Most paths are drawn with simple round pens. Therefore we've
%D split up the routine in two.

\def\flushnormalMPsegment
  {\ifcase\getMPkeyword\relax
     \PDFcode{\!MPgMPs1 \!MPgMPs2 l}%
   \or
     \PDFcode{\!MPgMPs1 \!MPgMPs2 \!MPgMPs3 \!MPgMPs4 \!MPgMPs5 \!MPgMPs6 c}%
   \or
     \PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l S}%
   \or
     \edef\lastMPmoveX{\gMPs1}% evt \!MP here
     \edef\lastMPmoveY{\gMPs2}%
     \PDFcode{\!MP\lastMPmoveX\space \!MP\lastMPmoveY\space m}%
   \fi}

\def\flushconcatMPsegment
  {\ifcase\getMPkeyword\relax
     \doMPconcat{\gMPs1}\a{\gMPs2}\b%
     \PDFcode{\!MP\a\space\!MP\b\space l}%
   \or
     \doMPconcat{\gMPs1}\a{\gMPs2}\b%
     \doMPconcat{\gMPs3}\c{\gMPs4}\d%
     \doMPconcat{\gMPs5}\e{\gMPs6}\f%
     \PDFcode{\!MP\a\space\!MP\b\space
              \!MP\c\space\!MP\d\space
              \!MP\e\space\!MP\f\space c}%
   \or
     \bgroup
     \noMPtranslate
     \doMPconcat\lastMPmoveX\a\lastMPmoveY\b%
     \PDFcode{\!MP\a\space\!MP\b\space l S}%
     \egroup
   \or
     \edef\lastMPmoveX{\gMPs1}%
     \edef\lastMPmoveY{\gMPs2}%
     \doMPconcat\lastMPmoveX\a\lastMPmoveY\b%
     \PDFcode{\!MP\a\space\!MP\b\space m}%
   \fi}

\def\doflushsomeMPpath
  {\dodoflushsomeMPpath
   \advance\nofMPsegments \plusone
   \ifnum\nofMPsegments<\scratchcounter
     \expandafter\doflushsomeMPpath
   \fi}

\def\flushsomeMPpath
  {\scratchcounter\nofMPsegments
   \nofMPsegments\plusone
   \doflushsomeMPpath}

\def\flushnormalMPpath{\let\dodoflushsomeMPpath\flushnormalMPsegment\flushsomeMPpath}

%OLD \def\flushconcatMPpath{\let\dodoflushsomeMPpath\flushconcatMPsegment\flushsomeMPpath}

%NEW pre-calculate 1/D so it needn't be repeated for each control point.

\def\flushconcatMPpath
  {\MPreciprocaldeterminant
   \let\dodoflushsomeMPpath\flushconcatMPsegment\flushsomeMPpath}

%D The transformation of the coordinates is handled by one of
%D the macros Tanmoy posted to the \PDFTEX\ mailing list.
%D I rewrote and optimized the original macro to suit the other
%D macros in this module.
%D
%D \starttyping
%D \doMPconcat {x position} \xresult {y position} \yresult
%D \stoptyping
%D
%D By setting the auxiliary \DIMENSIONS\ \type{\dimen0} upto
%D \type{\dimen10} only once per path, we save over 20\% run
%D time. Some more speed was gained by removing some parameter
%D passing. These macros can be optimized a bit more by using
%D more constants. There is however not much need for further
%D optimization because penshapes usually are round and
%D therefore need no transformation. Nevertheless we move the
%D factor to the outer level and use a bit different \type{pt}
%D removal macro. Although the values represent base points,
%D we converted them to pure points, simply because those can
%D be converted back.

%OLD \mathchardef\MPconcatfactor=256 % beware don't remove spaces before it

%OLD \def\doMPreducedimen#1
%OLD   {\count0\MPconcatfactor
%OLD    \advance\dimen#1 \ifdim\dimen#1>\zeropoint .5\else -.5\fi\count0
%OLD    \divide\dimen#1 \count0\relax}

%OLD % too inaccurate (see old pragma logo)
%OLD
%OLD \def\doMPreducedimen#1
%OLD   {\count0=\MPconcatfactor
%OLD    \divide\dimen#1 \count0\relax}

%OLD \def\doMPreducedimen#1
%OLD   {\advance\dimen#1 \ifdim\dimen#1>\zeropoint .5\else -.5\fi\MPconcatfactor
%OLD    \divide\dimen#1 \MPconcatfactor}

%D The transformation code is rewritten by Daniel H. Luecking who
%D describes his patch as follows:
%D
%D We would like to divide 1 by $X$, but all divisions are integer so
%D for accuracy we want to convert to large integers and make sure the
%D integer quotient has as many significant digits as possible. Thus we
%D need to replace $1/X$ with $M/N$ where $N$ is as large as possible
%D and $M/N$ is as large as possible. Also for simplicity $M$ should be
%D a power of 2. So we make $M = 2^{30}$ \footnote{$2^{31} - 1$ is the
%D largest legal integer. Using it (and simply ignoring the inaccuracy
%D caused by $-1$) turns out to be at least as accurate in all cases,
%D and more accurate in some.} (largest legal power of 2) and adjust
%D $X$ downward (if necessary) to the the range $1-2^{16}$. This gives
%D at least 15 significant binary digits, (almost as accurate as
%D \METAPOST\ for numbers near 1) or almost 5 significant figures
%D (decimal).

\newcount\MPscratchCnt
\newdimen\MPscratchDim % will be assigned global

\def\MPadjustdimen   % sets \MPscratchDim and \MPscratchCnt
  {\MPscratchCnt\zerocount
   \doMPadjustdimen}

\def\doMPadjustdimen
  {\ifdim\MPscratchDim>\onepoint
     \divide\MPscratchDim 2
     \advance\MPscratchCnt \plusone
     \expandafter\doMPadjustdimen
   \fi}

%OLD \def\doMPexpanddimen#1
%OLD   {\multiply\dimen#1 \MPconcatfactor\relax}

%D DHL: When viewed as an integer, $1 \hbox{pt}=2^{16}$ so $2^{32}/X$
%D is  the right way to do $(1 \hbox{pt})/(X \hbox{pt})$ and get the
%D answer  in points. But we are limited to $2^{30}/X$. However, we
%D actually do  $[ 2^{30} / (X/2^K) ]*2^{2-K}$ where $K$ is the number
%D of halvings it takes to bring $X$ below $1 \hbox{pt}$. If $K$ is 0
%D or 1 we readjust by multiplying by 4 or 2, otherwise by halving
%D $(K-2)$ times \type {\MPscratchCnt} holds the value of $K$ from
%D \type {\MPadjustdimen}.

\def\MPreadjustdimen  % acts on \MPscratchDim and MPscratchCnt
  {\ifcase\MPscratchCnt
     \multiply\scratchdimen 4
   \or
     \multiply\scratchdimen 2
   \else
     \expandafter\doMPreadjustdimen
   \fi}

\def\doMPreadjustdimen
  {\ifnum\MPscratchCnt>2
     \divide\scratchdimen 2
     \advance\MPscratchCnt \minusone
     \expandafter\doMPreadjustdimen
   \fi}

\def\MPreciprocaldeterminant
  {\scratchdimen\withoutpt\the\dimen0 \dimen6            % s_x*s_y
   \advance\scratchdimen - \withoutpt\the\dimen2 \dimen4 % s_x*s_y - r_x*r_y
   \ifdim\scratchdimen<\zeropoint  % we need a positive dimension
     \scratchdimen-\scratchdimen   % for \MPadjustdimen (?)
     \doMPreciprocal
     \scratchdimen-\scratchdimen
   \else
     \doMPreciprocal
   \fi
   \edef\MPreciprocal{\withoutpt\the\scratchdimen}}

\newcount\MPnumerator \MPnumerator = 1073741824 % 2^{30}

% todo: dimexpr

\def\doMPreciprocal % replace \scratchdimen with its reciprocal
  {\ifdim\scratchdimen=\onepoint \else
     \MPadjustdimen
     \scratchcounter\MPnumerator
     \divide\scratchcounter\scratchdimen
     \scratchdimen1\scratchcounter % 1 needed !
     \MPreadjustdimen
  \fi}

%OLD \def\presetMPconcat
%OLD  {\dimen 0=\gMPs1\onepoint \doMPreducedimen 0    % r_x
%OLD   \dimen 2=\gMPs2\onepoint \doMPreducedimen 2    % s_x
%OLD   \dimen 4=\gMPs3\onepoint \doMPreducedimen 4    % s_y
%OLD   \dimen 6=\gMPs4\onepoint \doMPreducedimen 6    % r_y
%OLD   \dimen 8=\gMPs5\onepoint \doMPreducedimen 8    % t_x
%OLD   \dimen10=\gMPs6\onepoint \doMPreducedimen10 }  % t_y
%OLD
%OLD \def\presetMPscale
%OLD   {\dimen 0=\gMPs1\onepoint \doMPreducedimen 0
%OLD    \dimen 2 \zeropoint
%OLD    \dimen 4 \zeropoint
%OLD    \dimen 6=\gMPs2\onepoint \doMPreducedimen 6
%OLD    \dimen 8 \zeropoint
%OLD    \dimen10 \zeropoint}

\def\cleanupMPconcat
  {\ignoreMPspecials
   \docleanupMPargument1%
   \docleanupMPargument6%
   \keepMPspecials}

\def\presetMPconcat
  {\dimen 0=\gMPs1\onepoint   % s_x
   \dimen 2=\gMPs2\onepoint   % r_x
   \dimen 4=\gMPs3\onepoint   % r_y
   \dimen 6=\gMPs4\onepoint   % s_y
   \dimen 8=\gMPs5\onepoint   % t_x
   \dimen10=\gMPs6\onepoint}  % t_y

\def\presetMPscale
  {\dimen 0=\gMPs1\onepoint
   \dimen 2 \zeropoint
   \dimen 4 \zeropoint
   \dimen 6=\gMPs2\onepoint
   \dimen 8 \zeropoint
   \dimen10 \zeropoint}

\def\noMPtranslate % use this one grouped
  {\dimen 8 \zeropoint        % t_x
   \dimen10 \zeropoint}       % t_y

%D \starttyping
%D \def\doMPconcat#1#2#3#4%
%D   {\dimen12=#1 pt \doMPreducedimen12 % p_x
%D    \dimen14=#3 pt \doMPreducedimen14 % p_y
%D    %
%D    \dimen16  \dimen 0
%D    \multiply \dimen16  \dimen 6
%D    \dimen20  \dimen 2
%D    \multiply \dimen20  \dimen 4
%D    \advance  \dimen16 -\dimen20
%D    %
%D    \dimen18  \dimen12
%D    \multiply \dimen18  \dimen 6
%D    \dimen20  \dimen14
%D    \multiply \dimen20  \dimen 4
%D    \advance  \dimen18 -\dimen20
%D    \dimen20  \dimen 4
%D    \multiply \dimen20  \dimen10
%D    \advance  \dimen18  \dimen20
%D    \dimen20  \dimen 6
%D    \multiply \dimen20  \dimen 8
%D    \advance  \dimen18 -\dimen20
%D    %
%D    \multiply \dimen12 -\dimen 2
%D    \multiply \dimen14  \dimen 0
%D    \advance  \dimen12  \dimen14
%D    \dimen20  \dimen 2
%D    \multiply \dimen20  \dimen 8
%D    \advance  \dimen12  \dimen20
%D    \dimen20  \dimen 0
%D    \multiply \dimen20  \dimen10
%D    \advance  \dimen12 -\dimen20
%D    %
%D    \doMPreducedimen16
%D    \divide   \dimen18  \dimen16 \doMPexpanddimen18
%D    \divide   \dimen12  \dimen16 \doMPexpanddimen12
%D    %
%D    \edef#2{\withoutpt\the\dimen18}% % p_x^\prime
%D    \edef#4{\withoutpt\the\dimen12}} % p_y^\prime
%D \stoptyping

%D The following optimization resulted from some tests by
%D and email exchanges with Sanjoy Mahajan.
%D
%D \starttyping
%D \def\doMPconcat#1#2#3#4%
%D   {\dimen12=#1 pt \doMPreducedimen12 % p_x
%D    \dimen14=#3 pt \doMPreducedimen14 % p_y
%D    %
%D    \dimen16  \dimen 0
%D    \multiply \dimen16  \dimen 6
%D    \dimen20  \dimen 2
%D    \multiply \dimen20  \dimen 4
%D    \advance  \dimen16 -\dimen20
%D    %
%D    \dimen18  \dimen12
%D    \multiply \dimen18  \dimen 6
%D    \dimen20  \dimen14
%D    \multiply \dimen20  \dimen 4
%D    \advance  \dimen18 -\dimen20
%D    \dimen20  \dimen 4
%D    \multiply \dimen20  \dimen10
%D    \advance  \dimen18  \dimen20
%D    \dimen20  \dimen 6
%D    \multiply \dimen20  \dimen 8
%D    \advance  \dimen18 -\dimen20
%D    %
%D    \multiply \dimen12 -\dimen 2
%D    \multiply \dimen14  \dimen 0
%D    \advance  \dimen12  \dimen14
%D    \dimen20  \dimen 2
%D    \multiply \dimen20  \dimen 8
%D    \advance  \dimen12  \dimen20
%D    \dimen20  \dimen 0
%D    \multiply \dimen20  \dimen10
%D    \advance  \dimen12 -\dimen20
%D    %
%D   %\ifdim\dimen16>1pt % oeps, can be < 1pt too
%D    \ifdim\dimen16=1pt \else
%D      \ifdim\dimen16>\MPconcatfactor pt
%D        \doMPreducedimen16
%D        \divide \dimen18 \dimen16 \doMPexpanddimen18
%D        \divide \dimen12 \dimen16 \doMPexpanddimen12
%D      \else
%D        \divide \dimen18 \dimen16 \doMPexpanddimen18 \doMPexpanddimen18
%D        \divide \dimen12 \dimen16 \doMPexpanddimen12 \doMPexpanddimen12
%D      \fi
%D    \fi
%D    %
%D    \edef#2{\withoutpt\the\dimen18}% % p_x^\prime
%D    \edef#4{\withoutpt\the\dimen12}} % p_y^\prime
%D \stoptyping
%D
%D But, this one is still too inaccurate, so we now have:

%D We cannot use \type {\beginETEX} here since in plain we
%D get \type {\outer} problems, sigh.

%OLD \beginTEX
%OLD
%OLD \def\MPcriteriumA {512pt} % scale
%OLD \def\MPcriteriumB   {2pt} % scale
%OLD
%OLD \endTEX
%OLD
%OLD \ifx\MPcriteriumA\undefined
%OLD
%OLD   \newdimen\MPcriteriumA \MPcriteriumA=512pt
%OLD   \newdimen\MPcriteriumB \MPcriteriumB=  2pt
%OLD
%OLD \fi

%OLD \def\doMPconcat#1#2#3#4%
%OLD   {\dimen12=#1pt % p_x
%OLD    \dimen14=#3pt % p_y
%OLD    %
%OLD    \chardef\MPfactor\zerocount
%OLD    \ifdim\dimen4<\MPcriteriumB\ifdim\dimen4>-\MPcriteriumB
%OLD      \ifdim\dimen6<\MPcriteriumB\ifdim\dimen6>-\MPcriteriumB
%OLD        \ifdim\dimen8<\MPcriteriumB\ifdim\dimen8>-\MPcriteriumB
%OLD          \ifdim\dimen10<\MPcriteriumB\ifdim\dimen10>-\MPcriteriumB
%OLD            \chardef\MPfactor\plusone
%OLD          \fi\fi
%OLD        \fi\fi
%OLD      \fi\fi
%OLD    \fi\fi
%OLD    \ifcase\MPfactor % spurious 0 removed
%OLD      \chardef\MPfactor\plusone
%OLD      \ifdim\dimen12<\MPcriteriumA\ifdim\dimen12>-\MPcriteriumA
%OLD        \ifdim\dimen14<\MPcriteriumA\ifdim\dimen14>-\MPcriteriumA
%OLD          \chardef\MPfactor16
%OLD        \fi\fi
%OLD      \fi\fi
%OLD    \fi
%OLD    %
%OLD    \multiply\dimen12 \MPfactor
%OLD    \multiply\dimen14 \MPfactor
%OLD    %
%OLD    \doMPreducedimen12
%OLD    \doMPreducedimen14
%OLD    %
%OLD    \dimen16  \dimen 0
%OLD    \multiply \dimen16  \dimen 6
%OLD    \dimen20  \dimen 2
%OLD    \multiply \dimen20  \dimen 4
%OLD    \advance  \dimen16 -\dimen20
%OLD    %
%OLD    \dimen18  \dimen12
%OLD    \multiply \dimen18  \dimen 6
%OLD    \dimen20  \dimen14
%OLD    \multiply \dimen20  \dimen 4
%OLD    \advance  \dimen18 -\dimen20
%OLD    \dimen20  \dimen 4
%OLD    \multiply \dimen20  \dimen10
%OLD    \advance  \dimen18  \dimen20
%OLD    \dimen20  \dimen 6
%OLD    \multiply \dimen20  \dimen 8
%OLD    \advance  \dimen18 -\dimen20
%OLD    %
%OLD    \multiply \dimen12 -\dimen 2
%OLD    \multiply \dimen14  \dimen 0
%OLD    \advance  \dimen12  \dimen14
%OLD    \dimen20  \dimen 2
%OLD    \multiply \dimen20  \dimen 8
%OLD    \advance  \dimen12  \dimen20
%OLD    \dimen20  \dimen 0
%OLD    \multiply \dimen20  \dimen10
%OLD    \advance  \dimen12 -\dimen20
%OLD    %
%OLD    \ifdim\dimen16=\onepoint \else
%OLD      \ifdim\dimen16>\MPconcatfactor \onepoint \relax
%OLD        \doMPreducedimen16
%OLD        \divide \dimen18 \dimen16 \doMPexpanddimen18
%OLD        \divide \dimen12 \dimen16 \doMPexpanddimen12
%OLD      \else
%OLD        \divide \dimen18 \dimen16 \doMPexpanddimen18 \doMPexpanddimen18
%OLD        \divide \dimen12 \dimen16 \doMPexpanddimen12 \doMPexpanddimen12
%OLD      \fi
%OLD    \fi
%OLD    %
%OLD    \divide\dimen18 \MPfactor
%OLD    \divide\dimen12 \MPfactor
%OLD    %
%OLD    \edef#2{\withoutpt\the\dimen18}% % p_x^\prime
%OLD    \edef#4{\withoutpt\the\dimen12}} % p_y^\prime

%D DHL: Ideally, $r_x$, $r_y$, $s_x$, $s_y$ should be in macros, not
%D dimensions (they are scalar quantities after all, not lengths). I
%D suppose the authors decided to do calculations with integer
%D arithmetic instead of using real factors because it's faster.
%D However, the actual macros test slower, possibly because I've
%D omitted three nested loops. In my test files, my approach is more
%D accurate. It is also far simpler and overflow does not seem to be a
%D significant concern. The scale factors written by Metapost are (?)
%D always $<=1$ (it scales coordinates internally) and coordinates are
%D always likely to be less than \type {\maxdimen}.
%D
%D If this should ever cause problems, the scale factors can be reduced.

\def\doMPconcat#1#2#3#4%
  {\dimen12=#1pt % p_x % #1\onepoint
   \dimen14=#3pt % p_y % #3\onepoint
   \advance\dimen12 -\dimen8  % p_x - t_x
   \advance\dimen14 -\dimen10 % p_y - t_y
   \dimen18=\withoutpt\the\dimen6 \dimen12          % s_y(p_x - t_x)
   \advance\dimen18 -\withoutpt\the\dimen4 \dimen14 %   - r_y(p_y-t_y)
   \dimen14=\withoutpt\the\dimen0 \dimen14          % s_x(p_y-t_y)
   \advance\dimen14 -\withoutpt\the\dimen2 \dimen12 %   - r_x(p_x-t_x)
   % \MPreciprocal contains precomputed 1/D:
   \dimen18=\MPreciprocal\dimen18
   \dimen14=\MPreciprocal\dimen14
   \edef#2{\withoutpt\the\dimen18}% % p_x^\prime
   \edef#4{\withoutpt\the\dimen14}} % p_y^\prime

% faster but not that often used
%
% \def\doMPconcat#1#2#3#4%
%   {\dimen12\dimexpr#1\points-\dimen 8\relax % p_x-t_x
%    \dimen14\dimexpr#3\points-\dimen10\relax % p_y-t_y
%    \dimen18\dimexpr\withoutpt\the\dimen6\dimen12-\withoutpt\the\dimen4\dimen14\relax % s_y(p_x-t_x)-r_y(p_y-t_y)
%    \dimen14\dimexpr\withoutpt\the\dimen0\dimen14-\withoutpt\the\dimen2\dimen12\relax % s_x(p_y-t_y)-r_x(p_x-t_x)
%    \edef#2{\withoutpt\the\dimexpr\MPreciprocal\dimen18\relax}% % p_x^\prime
%    \edef#4{\withoutpt\the\dimexpr\MPreciprocal\dimen14\relax}} % p_y^\prime

%D One reason for Daniel to write this patch was that at small sizes
%D the accuracy was less than optimal. Here is a test that demonstrates
%D that his alternative is pretty good:
%D
%D \startlinecorrection
%D \startMPcode
%D for i = 5cm,1cm,5mm,1mm,.5mm,.1mm,.01mm :
%D     draw fullcircle scaled i withpen pencircle xscaled (i/10) yscaled (i/20) rotated 45 ;
%D endfor ;
%D \stopMPcode
%D \stoplinecorrection

%D The following explanation of the conversion process was
%D posted to the \PDFTEX\ mailing list by Tanmoy. The original
%D macro was part of a set of macro's that included sinus and
%D cosinus calculations as well as scaling and translating. The
%D \METAPOST\ to \PDF\ conversion however only needs
%D transformation.

%M \start \switchtobodyfont [ss]

%D Given a point $(U_x, U_y)$ in user coordinates, the business
%D of \POSTSCRIPT\ is to convert it to device space. Let us say
%D that the device space coordinates are $(D_x, D_y)$. Then, in
%D \POSTSCRIPT\ $(D_x, D_y)$ can be written in terms of
%D $(U_x, U_y)$ in matrix notation, either as
%D
%D \placeformula
%D   \startformula
%D   \pmatrix{D_x&D_y&1\cr} = \pmatrix{U_x&U_y&1\cr}
%D                            \pmatrix{s_x&r_x&0\cr
%D                                     r_y&s_y&0\cr
%D                                     t_x&t_y&1\cr}
%D   \stopformula
%D
%D or
%D
%D \placeformula
%D   \startformula
%D    \pmatrix{D_x\cr D_y\cr 1} = \pmatrix{s_x&r_y&t_x\cr
%D                                         r_x&s_y&t_y\cr
%D                                         0  &0  &1  \cr}
%D                                \pmatrix{U_x\cr
%D                                         U_y\cr
%D                                         1  \cr}
%D   \stopformula
%D
%D both of which is a shorthand for the same set of equations:
%D
%D \placeformula
%D   \startformula
%D      D_x = s_x U_x + r_y U_y + t_x
%D   \stopformula
%D
%D \placeformula
%D   \startformula
%D      D_y = r_x U_x + s_y U_y + t_y
%D   \stopformula
%D
%D which define what is called an `affine transformation'.
%D
%D \POSTSCRIPT\ represents the `transformation matrix' as a
%D six element matrix instead of a $3\times 3$ array because
%D three of the elements are always~0, 0 and~1. Thus the above
%D transformation is written in postscript as $[s_x\, r_x\,
%D r_y\, s_y\, t_x\, t_y]$. However, when doing any
%D calculations, it is useful to go back to the original
%D matrix notation (whichever: I will use the second) and
%D continue from there.
%D
%D As an example, if the current transformation matrix is
%D $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$ and you say \typ{[a b
%D c d e f] concat}, this means:
%D
%D \startnarrower
%D Take the user space coordinates and transform them to an
%D intermediate set of coordinates using array $[a\, b\, c\, d\,
%D e\, f]$ as the transformation matrix.
%D
%D Take the intermediate set of coordinates and change them to
%D device coordinates using array $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$
%D as the transformation matrix.
%D \stopnarrower
%D
%D Well, what is the net effect? In matrix notation, it is
%D
%D \placeformula
%D   \startformula
%D     \pmatrix{I_x\cr I_y\cr 1\cr} = \pmatrix{a&c&e\cr
%D                                             b&d&f\cr
%D                                             0&0&1\cr}
%D                                    \pmatrix{U_x\cr
%D                                             U_y\cr
%D                                             1  \cr}
%D   \stopformula
%D
%D \placeformula
%D   \startformula
%D     \pmatrix{D_y\cr D_y\cr 1\cr} = \pmatrix{s_x&r_y&t_x\cr
%D                                             r_x&s_y&t_y\cr
%D                                             0  &0  &1  \cr}
%D                                    \pmatrix{I_x\cr
%D                                             I_y\cr
%D                                             1  \cr}
%D   \stopformula
%D
%D where $(I_x, I_y)$ is the intermediate coordinate.
%D
%D Now, the beauty of the matrix notation is that when there is
%D a chain of such matrix equations, one can always compose
%D them into one matrix equation using the standard matrix
%D composition law. The composite matrix from two matrices can
%D be derived very easily: the element in the $i$\high{th}
%D horizontal row and $j$\high{th} vertical column is
%D calculated by`multiplying' the $i$\high{th} row of the first
%D matrix and the $j$\high{th} column of the second matrix (and
%D summing over the elements). Thus, in the above:
%D
%D \placeformula
%D   \startformula
%D   \pmatrix{D_x\cr D_y\cr 1} = \pmatrix{s_x^\prime&r_y^\prime&t_x^\prime\cr
%D                                        r_x^\prime&s_y^\prime&t_y^\prime\cr
%D                                        0         &0         &0        \cr}
%D                               \pmatrix{U_x\cr
%D                                        U_y\cr
%D                                        1  \cr}
%D   \stopformula
%D
%D with
%D
%D \placeformula
%D   \startformula
%D      \eqalign
%D        {s_x^\prime & = s_x a + r_y b       \cr
%D         r_x^\prime & = r_x a + s_y b       \cr
%D         r_y^\prime & = s_x c + r_y d       \cr
%D         s_y^\prime & = r_x c + s_y d       \cr
%D         t_x^\prime & = s_x e + r_y f + t_x \cr
%D         t_y^\prime & = r_x e + s_y f + t_y \cr}
%D   \stopformula

%D In fact, the same rule is true not only when one is going
%D from user coordinates to device coordinates, but whenever
%D one is composing two `transformations' together
%D (transformations are `associative'). Note that the formula
%D is not symmetric: you have to keep track of which
%D transformation existed before (i.e.\ the equivalent of
%D $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$) and which was
%D specified later (i.e.\ the equivalent of $[a\, b\, c\, d\,
%D e\, f]$). Note also that the language can be rather
%D confusing: the one specified later `acts earlier',
%D converting the user space coordinates to intermediate
%D coordinates, which are then acted upon by the pre||existing
%D transformation. The important point is that order of
%D transformation matrices cannot be flipped (transformations
%D are not `commutative').
%D
%D Now what does it mean to move a transformation matrix
%D before a drawing? What it means is that given a point
%D $(P_x, P_y)$ we need a different set of coordinates
%D $(P_x^\prime, P_y^\prime)$ such that if the transformation
%D acts on $(P_x^\prime, P_y^\prime)$, they produce $(P_x,
%D P_y)$. That is we need to solve the set of equations:
%D
%D \placeformula
%D   \startformula
%D     \pmatrix{P_x\cr P_y\cr 1\cr} = \pmatrix{s_x&r_y&t_x\cr
%D                                             r_x&s_y&t_y\cr
%D                                             0  &0  &1  \cr}
%D                                    \pmatrix{P_x^\prime\cr
%D                                             P_y^\prime\cr
%D                                             1         \cr}
%D   \stopformula
%D
%D Again matrix notation comes in handy (i.e. someone has
%D already solved the problem for us): we need the inverse
%D transformation matrix. The inverse transformation matrix can
%D be calculated very easily:
%D
%D \placeformula
%D   \startformula
%D     \pmatrix{P_x^\prime\cr P_y^\prime\cr 1\cr} =
%D        \pmatrix{s_x^\prime&r_y^\prime&t_x^\prime\cr
%D                 r_x^\prime&s_y^\prime&t_y^\prime\cr
%D                 0  &0  &1  \cr}
%D        \pmatrix{P_x\cr
%D                 P_y\cr
%D                 1         \cr}
%D   \stopformula
%D
%D where, the inverse transformation matrix is given by
%D
%D \placeformula
%D   \startformula
%D     \eqalign
%D       {D          & = s_x s_y - r_x r_y           \cr
%D        s_x^\prime & = s_y / D                     \cr
%D        s_y^\prime & = s_x / D                     \cr
%D        r_x^\prime & = - r_x / D                   \cr
%D        r_y^\prime & = - r_y / D                   \cr
%D        t_x^\prime & = ( - s_y t_x + r_y t_y ) / D \cr
%D        t_y^\prime & = (   r_x t_x - s_x t_y ) / D \cr}
%D   \stopformula
%D
%D And you can see that when expanded out, this does
%D give the formulas:
%D
%D \placeformula
%D   \startformula
%D     P_x^\prime = { { s_y(p_x-t_x) + r_y(t_y-p_y) } \over
%D                    { s_x s_y-r_x r_y } }
%D   \stopformula
%D
%D \placeformula
%D   \startformula
%D     P_y^\prime = { { s_x(p_y-t_y) + r_x(t_x-p_x) } \over
%D                    { s_x*s_y-r_x*r_y } }
%D   \stopformula
%D
%D The code works by representing a real number by converting
%D it to a dimension to be put into a \DIMENSION\ register: 2.3 would
%D be represented as 2.3pt for example. In this scheme,
%D multiplying two numbers involves multiplying the \DIMENSION\
%D registers and dividing by 65536. Accuracy demands that the
%D division be done as late as possible, but overflow
%D considerations need early division.
%D
%D Division involves dividing the two \DIMENSION\ registers and
%D multiplying the result by 65536. Again, accuracy would
%D demand that the numerator be multiplied (and|/|or the
%D denominator divided) early: but that can lead to overflow
%D which needs to be avoided.
%D
%D If nothing is known about the numbers to start with (in
%D concat), I have chosen to divide the 65536 as a 256 in each
%D operand. However, in the series calculating the sine and
%D cosine, I know that the terms are small (because I never
%D have an angle greater than 45 degrees), so I chose to
%D apportion the factor in a different way.

%M \stop

%D The path is output using the values saved on the stack. If
%D needed, all coordinates are recalculated.

\def\finishMPpath
  {\PDFcode{\ifcase\finiMPpath W n\or S\or f\or B\fi}}

\def\processMPpath
  {\checkMPpath
   \ifcase\nofMPsegments\else
     \flushMPpath
     \closeMPpath
     \finishMPpath
   \fi
   \let\handleMPsequence\dohandleMPsequence
   \resetMPstack
   \nofMPsegments\zerocount
   \handleMPsequence}

%D The following \METAPOST\ code is quite valid but, when
%D processed and converted to \PDF, will make a file
%D unprintable on a Hewlett Packard printer (from Acrobat
%D $v<=5$). Who is to blame, the driver of the OS layer in
%D between, is hard to determine, so we add an additional
%D check.
%D
%D \starttyping
%D clip currentpicture to origin -- cycle ;
%D setbounds currentpicture to fullsquare scaled 5cm ;
%D \stoptyping

\def\checkMPpath
  {\ifcase\finiMPpath
     \ifnum\nofMPsegments<3 % n is one ahead
       \message{omitting zero clip path}%
       \nofMPsegments\zerocount
     \fi
   \fi}

%D In \PDF\ the \type{cm} operator must precede the path
%D specification. We therefore can output the \type{cm} at
%D the moment we encounter it.

\def\handleMPpathconcat
  {\presetMPconcat
   \PDFcode{\gMPs1 \gMPs2 \gMPs3 \gMPs4 \gMPs5 \gMPs6 cm}%
   \resetMPstack}

\def\handleMPpathscale
  {\presetMPscale
   \PDFcode{\gMPs1 0 0 \gMPs2 0 0 cm}%
   \resetMPstack}

%D This macro interprets the path and saves it as compact as
%D possible.

\def\dohandleMPpath#1%
  {\ifcase\lccode`#1\relax
     \@EA\dohandleMPpathA
   \else
     \@EA\dohandleMPpathB
   \fi#1}

\let\dohandleMPpathA\setMPsequence

\def\dohandleMPpathB#1 %
  {\def\somestring{#1}%
   \ifx\somestring\PSlineto
     \setMPkeyword0
   \else\ifx\somestring\PScurveto
     \setMPkeyword1
   \else\ifx\somestring\PSrlineto
     \setMPkeyword2
   \else\ifx\somestring\PSmoveto
     \setMPkeyword3
   \else\ifx\somestring\PSclip
   % \chardef\finiMPpath0 % already
     \let\handleMPsequence\processMPpath
   \else\ifx\somestring\PSgsave
     \chardef\finiMPpath3
   \else\ifx\somestring\PSgrestore
   \else\ifx\somestring\PSfill
     \ifcase\finiMPpath
       \chardef\finiMPpath2
       \let\handleMPsequence\processMPpath
     \fi
   \else\ifx\somestring\PSstroke
     \ifcase\finiMPpath
       \chardef\finiMPpath1
     \fi
     \let\handleMPsequence\processMPpath
   \else\ifx\somestring\PSclosepath
     \def\closeMPpath{\PDFcode{h}}%
   \else\ifx\somestring\PSconcat
     \cleanupMPconcat
     \let\flushMPpath\flushconcatMPpath
     \handleMPpathconcat
   \else\ifx\somestring\PSscale
     \let\flushMPpath\flushconcatMPpath
     \handleMPpathscale
   \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
   \handleMPsequence}

%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=0 \fi

\def\lastPDFMPobject{0}

%D The additional code needed can be made available in the
%D (global) macro \type {\currentPDFresources}.

\let\currentPDFresources\empty

\newtoks\everyMPtoPDFconversion

\def\convertMPtoPDF % #1#2#3%
  {\bgroup
   \ifx\pdfdecimaldigits\undefined\else \pdfdecimaldigits=5 \fi % new
   \setbox\scratchbox\vbox\bgroup
     \xdef\MPheight{\zeropoint}%
     \xdef\MPwidth {\zeropoint}%
     \forgetall
     \offinterlineskip
     \startMPresources
     \doprocessMPtoPDFfile} %

%D The next one is kind of private and probably will become obsolete):

\def\processMPtoPDFfile % file xscale yscale
  {\bgroup
   \let\finishMPgraphic\egroup
   \doprocessMPtoPDFfile}

\let\setMPextensions\relax

\def\doprocessMPtoPDFfile#1#2#3% file xscale yscale
  {% the following line is needed for latex where onepoint is not
   % onepoint but a number (maxdimen); some day i'll make a latex
   % variant of this file so that i no longer have to deal with such
   % issues; then i'll also speed up this module using a few context
   % tricks
   %
   \let\onepoint\onerealpoint
   %
   \setMPspecials
   \setMPextensions
   \the\everyMPtoPDFconversion
   \catcode`\^^M=\@@endofline
   \startMPscanning
   \let\do\empty
   \xdef\MPxscale{#2}%
   \xdef\MPyscale{#3}%
   \xdef\MPxoffset{0}%
   \xdef\MPyoffset{0}%
   \xdef\MPyshift{\zeropoint}%
   \donefalse
   \let\handleMPsequence\dohandleMPsequence
   \message{[MP to PDF]}% was: [MP to PDF #1] but there is a (#1) anyway
   \input#1\relax}

% strange rounding/clip in pdftex/viewer
%
% \def\finishMPgraphic
%   {\stopMPresources
%    \egroup
%    \ifx\pdftexversion\undefined\else\ifnum\pdftexversion<14 % for the moment
%      \chardef\makeMPintoPDFobject=0
%    \fi\fi
%    \ifcase\makeMPintoPDFobject\or\or\ifx\currentPDFresources\empty\else
%      \chardef\makeMPintoPDFobject=1
%    \fi\fi
%    \setbox\scratchbox=\vbox
%      {\forgetall
%       \hbox
%         {\PDFcode{q \MPxscale\space 0 0 \MPyscale\space \MPxoffset\space \MPyoffset\space cm}%
%          \lower\MPyshift\box\scratchbox % unscaled shift
%          \PDFcode{Q}}}%
%    \ht\scratchbox\MPheight
%    \wd\scratchbox\MPwidth
%    \dp\scratchbox\zeropoint
%    \ifcase\makeMPintoPDFobject
%      \box\scratchbox
%    \or
%      \immediate\pdfxform resources{\currentPDFresources}\scratchbox
%      \xdef\lastPDFMPobject{\the\pdflastxform}%
%      \pdfrefxform\lastPDFMPobject
%      \global\let\currentPDFresources\empty
%    \else
%      \box\scratchbox
%    \fi
%    \egroup}
%
% funny clip in viewer
%
% \setbox\scratchbox=\vbox
%   {\forgetall
%    \dimen0=\MPllx bp
%    \dimen2=\MPlly bp
%    \setbox\scratchbox=\hbox{\hskip-\dimen0\raise-\dimen2\box\scratchbox}%
%    \ht\scratchbox=\zeropoint
%    \dp\scratchbox=\zeropoint
%    \wd\scratchbox=\zeropoint
%    \hbox
%      {\PDFcode{q \MPxscale\space 0 0 \MPyscale\space 0 0 cm}%
%       \lower\MPshift\box\scratchbox
%       \PDFcode{Q}}}%

% \let\PDFMPformoffset\zeropoint

\def\PDFMPformoffset
  {\ifx\objectoffset\undefined\zeropoint\else\objectoffset\fi}

\def\finishMPgraphic
  {\stopMPresources
   \egroup
   \setbox\scratchbox\vbox
     {\forgetall
      \hbox
        {\PDFcode{q \MPxscale\space 0 0 \MPyscale\space \MPxoffset\space \MPyoffset\space cm}%
         \lower\MPyshift\box\scratchbox % unscaled shift
         \PDFcode{Q}}}%
   \ht\scratchbox\MPheight
   \wd\scratchbox\MPwidth
   \dp\scratchbox\zeropoint\relax
   \dopackageMPgraphic\scratchbox
   \egroup
   \endinput}

%D Alternative for \PDFTEX. We cannot come up with something more contexy
%D because this module is also used in \LATEX.

\def\dopackageMPgraphic#1% #1 = boxregister
  {%\ifx\pdfxform\undefined
   %  \chardef\makeMPintoPDFobject\zerocount % no pdftex at all
   %\else\ifx\pdftexversion\undefined
   %  \chardef\makeMPintoPDFobject\zerocount % no pdftex at all
   %\else\ifnum\pdftexversion<14
   %  \chardef\makeMPintoPDFobject\zerocount % no resource support
   %\else
   %                                         % keep the default value
   %\fi\fi\fi
   \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}
%D
%D Here are a few hooks for \CONTEXT\ specific things.

\ifx\deleteMPgraphic\undefined
  \def\deleteMPgraphic#1{}
\fi

\ifx\startMPresources\undefined
  \let\startMPresources\relax
  \let\stopMPresources\relax
\fi

%D \macros
%D   {twodigitMPoutput}
%D
%D We can limit the precision to two digits after the comma
%D by saying:
%D
%D \starttyping
%D \twodigitMPoutput
%D \stoptyping
%D
%D This option only works in \CONTEXT\ combined with \ETEX.

\def\twodigitMPoutput
  {\let\!MP        \twodigitrounding
   \def\!MPgMPs##1{\twodigitrounding{\gMPs##1}}%
   \def\!MPgMPa##1{\twodigitrounding{\gMPa##1}}}

\let\!MP    \empty
\let\!MPgMPa\gMPa
\let\!MPgMPs\gMPs

%D This kind of conversion is possible because \METAPOST\
%D does all the calculations. Converting other \POSTSCRIPT\
%D files would drive both me and \TEX\ crazy.

\ifx\undefined\StopLatexHack \else \StopLatexHack \fi

\protect % \endinput

%D \module
%D   [       file=supp-mpe,
%D        version=1999.07.10,
%D          title=\CONTEXT\ Support Macros,
%D       subtitle=METAPOST Special Extensions,
%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.

% fuzzy and complicating is the fact that we need to support
% context as well as mptopdf, so we cannot fall back on the
% special drivers and color module (although there may be
% good reasons to use a smaller context instead); also,
% shading is handled here while it should move to the special
% driver - to do!

%D This module is still experimental and deals with some
%D extensions to \METAPOST. When using \POSTSCRIPT\ output,
%D these extensions can be supplied by means of proper
%D preamble definitions, but when producing \PDF\ we have to
%D set up the appropriate datastructures ourselves. It acts as
%D a plug in into \type {supp-pdf}. As soon as we need more
%D extensions, we will generalize these macro. Some
%D definitions will move to the special drivers.

%D For usage in plain \TEX, say something:
%D
%D \starttyping
%D \input supp-pdf
%D \input supp-mpe
%D
%D \MPcmykcolorstrue
%D \MPspotcolorstrue
%D \chardef\makeMPintoPDFobject\plusone
%D \stoptyping

\writestatus{loading}{MetaPost Special Extensions}

%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
%D
%D The implementation below saves the data on the stack in
%D a way similar to the macros in \type {supp-pdf.tex}, and
%D just overload a few already defined handlers. That way,
%D the existing macros are still generic. \footnote {Actually,
%D the macros here are just as generic.}
%D
%D Currently the only extension concerns shading, which is
%D accomplished by handling yet another value of \type
%D {\finiMPpath}. The recource disctionary is stored and
%D later picked up by the general \CONTEXT\ figure inclusion
%D macros.

\unprotect

%D The \type {%%MetaPostSpecials: version.revision signal} line
%D triggers this module into handling color specifications kind
%D of special. We need this safeguard for non||special
%D usage.

\chardef\MPspecialversion  = 0  % specials when >1
\chardef\MPspecialrevision = 0  % specials when >1
\chardef\MPspecialsignal   = 0  % passed on by graphic

\chardef\inlineMPspecials  = 1  % only needed for stack resetting

%D This macro handles the special definitions that are
%D passed as comment.

\def\dohandleMPspecialcomment#1
  {\setMPargument{#1}%
   \advance\scratchcounter \minusone
   \ifcase\scratchcounter
     \handleMPspecialcommand
     \donetrue
     \doresetMPstack
     \let\handleMPsequence\dohandleMPsequence
     \expandafter\handleMPsequence
   \else
     \expandafter\dohandleMPspecialcomment
   \fi}

\def\handleMPspecialcomment #1 % number of arguments
  {\doresetMPstack
   \scratchcounter#1\relax
   \ifcase\scratchcounter % when zero, inline shading is used
     \chardef\inlineMPspecials\plusone
     \let\handleMPsequence\dohandleMPsequence
     \expandafter\handleMPsequence
   \else
     \chardef\inlineMPspecials\zerocount
     \expandafter\dohandleMPspecialcomment
   \fi}

%D When defined inline, we use another macro to handle the
%D definitions. Actually, this macro is called by the
%D previous ones.

\def\handleMPspecialcommand
  {\ifcase\inlineMPspecials\or
     \advance\nofMParguments \minusone % pop the size
   \fi
   \ifundefined\MPspecial
     \message{[unknown \MPspecial]}%
   \else
     \csname\MPspecial\endcsname
   \fi
   \ifcase\inlineMPspecials
     \doresetMPstack % 0
   \else
     \resetMPstack   % 1
   \fi}

%D This macro triggers special support. Currently, the
%D version and revision number are not used. Any version number
%D greater than zero will enable special support.

\newconditional\manyMPspecials % \settrue\manyMPspecials

\def\handleMPspecialscomment #1.#2 #3 % version.revision signal #4=div=1000|10000
  {\doresetMPstack
   \chardef\MPspecialversion #1%
   \chardef\MPspecialrevision#2%
   \chardef\MPspecialsignal  #3%
   \let\handleMPsequence\dohandleMPsequence
   \ifnum#1=\plusone
     \expandafter\handleMPsequence
   \else
     \expandafter\handleMPspecialscommentx
   \fi}

\def\handleMPspecialscommentx #1 % version 2
% {\doifelsedoifelse{#1}{10000}{\settrue\manyMPspecials}{\setfalse\manyMPspecials}% local
  {\ifnum10000=0#1\relax\settrue\manyMPspecials\else\setfalse\manyMPspecials\fi
   \handleMPsequence}

% one can say (in meta-ini):
%
% \prependtoks
%   _special_div_ := 1000\ifconditional\manyMPspecials0\fi ;
% \to \MPextensions

%D In case of \PDF, we need to prepare resourcs.

\newtoks\MPstartresources
\newtoks\MPstopresources

\def\startMPresources
  {\the\MPstartresources
   \ifx\currentPDFresources\empty\else
     \message{[unused resources]}%
   \fi
   \global\let\currentPDFresources\empty}

\def\stopMPresources
  {\let\currentPDFresources\empty
   \the\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

\ifx\normalhandleMPrgbcolor\undefined % in case we reload this module

  \let\normalhandleMPrgbcolor \handleMPrgbcolor
  \let\normalhandleMPcmykcolor\handleMPcmykcolor
  \let\normalhandleMPgraycolor\handleMPgraycolor
  \let\normalhandleMPspotcolor\handleMPspotcolor

\fi

%D When we are using \CONTEXT, we will fall back to the
%D better color conversion routines. This also has the advantage
%D that we don't have to parse and convert the file. In this
%D alternative, \type {\!MP} is not (yet) supported. Because
%D we can (for efficiency reasons) turn off strokecolor,
%D something we cannot do in \METAPOST\ converted code.

\newif\ifPDFMPstrokecolor \PDFMPstrokecolortrue

%D [This code should move to meta-ini.]

\ifCONTEXT % we can use this for a better xgstate handling

  \def\checkPDFMPstrokecolor
    {\ifPDFMPstrokecolor \PDFstrokecolortrue \fi}

  \def\normalhandleMPrgbcolor
    {{\checkPDFMPstrokecolor\execcolorR\gMPa1:\gMPa2:\gMPa3:0:0\od}}

  \def\normalhandleMPcmykcolor
    {{\checkPDFMPstrokecolor\execcolorC\gMPa1:\gMPa2:\gMPa3:\gMPa4:0:0\od}}

  \def\normalhandleMPgraycolor
    {{\checkPDFMPstrokecolor\execcolorS\gMPa1:0:0\od}}

  \def\normalhandleMPspotcolor % ???
    {{\checkPDFMPstrokecolor\execcolorP\gMPa1:\gMPa2:\gMPa3:\gMPa4:0:0\od}}

\fi

% In the previous macros we use the special drivers. A more
% direct approach would have been:
%
% \def\doPDFstartrgbcolormode#1#2#3%
%   {\PDFcode{#1 #2 #3 rg #1 #2 #3 RG}}
%
% \def\doPDFstartcmykcolormode#1#2#3#4%
%   {\PDFcode{#1 #2 #3 #4 k #1 #2 #3 #4 K}}
%
% \def\doPDFstartgraycolormode#1%
%   {\PDFcode{#1 g #1 G}}
%
% \appendtoks
%   \let\dostartrgbcolormode \doPDFstartrgbcolormode
%   \let\dostartcmykcolormode\doPDFstartcmykcolormode
%   \let\dostartgraycolormode\doPDFstartgraycolormode
% \to \everyMPtoPDFconversion

%D Now we can handle special color signals. We only do this
%D when special are detected.

% \def\MPrgbnumber#1{\expandafter\doMPrgbnumber#1000.0000\relax}
% \def\doMPrgbnumber#1.#2#3#4#5\relax{#2#3#4}

%D We cannot use \type {\everyMPtoPDFconversion} because in \MPTOPDF\
%D we don't have the \type {\appendtoks} macro available.

\def\setMPextensions
  {\ifconditional\manyMPspecials
     \def\MPrgbnumber##1{\expandafter\doMPrgbnumber##10000.00000\relax}%
     \def\doMPrgbnumber##1.##2##3##4##5##6\relax{##2##3##4##5}%
   \else
     \def\MPrgbnumber##1{\expandafter\doMPrgbnumber##1000.0000\relax}%
     \def\doMPrgbnumber##1.##2##3##4##5\relax{##2##3##4}%
  \fi}

%D The naive case looks like:
%D
%D \starttyping
%D \def\handleMPrgbcolor%
%D   {\setMPcolor
%D    \ifcase\MPspecialversion
%D      \resetMPcolor\normalhandleMPrgbcolor
%D    \else\ifnum\MPrgbnumber\lastMPrvalue=\MPspecialsignal
%D      % consider it to be a signal
%D    \else
%D      \resetMPcolor\normalhandleMPrgbcolor
%D    \fi\fi}
%D \stoptyping
%D
%D However, since we want \CMYK\ support, we will use the
%D following implementation:

% \def\setMPcolor
%   {\edef\lastMPrvalue{\gMPa1}%
%    \edef\lastMPgvalue{\gMPa2}%
%    \edef\lastMPbvalue{\gMPa3}}
%
% speed up (hardly called, so no let is needed)

\def\setMPcolor
  {\edef\lastMPrvalue{\csname\@@MP01\endcsname}%
   \edef\lastMPgvalue{\csname\@@MP02\endcsname}%
   \edef\lastMPbvalue{\csname\@@MP03\endcsname}}

\def\zeroMPrgbvalue{0.0}

\def\resetMPcolor
  {\let\lastMPrvalue\zeroMPrgbvalue
   \let\lastMPgvalue\zeroMPrgbvalue
   \let\lastMPbvalue\zeroMPrgbvalue}

\resetMPcolor

\def\@@MPSK{@MPSK@}
\def\@@MPSP{@MPSP@}

\def\interceptMPcmykcolor % todo : \ifMPcmykcolors
  {\ifcase\MPrgbnumber\lastMPgvalue
     % cannot happen
   \or
     % 1 == cmyk color spec
     \ifMPcmykcolors \dointerceptMPcmykcolor \fi
   \or
     % 2 == spot color
     \ifMPspotcolors \dointerceptMPspotcolor \fi
   \or
     % 3 == rgb transparency
     \invokeMPtransparencyspecial
   \or
     % 4 == cmyk transparency
     \ifMPcmykcolors \invokeMPtransparencyspecial \fi
   \or
     % 5 == spot transparency
     \ifMPspotcolors \invokeMPtransparencyspecial \fi
   \else
     % \writestatus{MPtoPDF}{unknown direct special}%
   \fi}

% ifcsname

\def\dointerceptMPcmykcolor
  {\revokeMPtransparencyspecial
   \@EA\ifx\csname\@@MPSK\number\MPrgbnumber\lastMPbvalue\endcsname\relax\else
     \@EA\@EA\@EA\setMPcmyk\csname\@@MPSK\number\MPrgbnumber\lastMPbvalue\endcsname
     \normalhandleMPcmykcolor
   \fi}

\def\dointerceptMPspotcolor
  {\revokeMPtransparencyspecial
   \@EA\ifx\csname\@@MPSP\number\MPrgbnumber\lastMPbvalue\endcsname\relax\else
     \@EA\@EA\@EA\setMPspot\csname\@@MPSP\number\MPrgbnumber\lastMPbvalue\endcsname
     \normalhandleMPspotcolor
   \fi}

\def\handleMPrgbcolor
  {\resetMPcolor
   \ifcase\MPspecialversion
     \normalhandleMPrgbcolor
   \else
     \setMPcolor
     \ifnum\MPrgbnumber\lastMPrvalue=\MPspecialsignal\relax
       \interceptMPcmykcolor
     \else
       \revokeMPtransparencyspecial
       \normalhandleMPrgbcolor
     \fi
   \fi}

\def\handleMPgraycolor
  {\resetMPcolor
   \ifcase\MPspecialversion \else \revokeMPtransparencyspecial \fi
   \normalhandleMPgraycolor}

\def\handleMPcmykcolor
  {\resetMPcolor
   \ifcase\MPspecialversion \else \revokeMPtransparencyspecial \fi
   \normalhandleMPcmykcolor}

%D Specials are define and recalled using:

\def\MPspecial
  {MP special \gMPs\nofMParguments}

\def\defineMPspecial#1#2%
  {\setvalue{MP special #1}{#2}}

%D The path processing macro is slightly extended.

\newtoks \invokeMPspecials

\def\finishMPpath
  {\PDFcode
     {\ifcase\finiMPpath W n\or S\or f\or B\else W n\fi
      \extraMPpathcode}}

\def\processMPpath
  {\checkMPpath % !
   \ifcase\nofMPsegments\else
     \let\extraMPpathcode\empty
     \ifcase\MPspecialversion\else
       \ifnum\MPrgbnumber\lastMPrvalue=\MPspecialsignal
         \ifnum\MPrgbnumber\lastMPgvalue>10 % really needed
           \scratchcounter\MPrgbnumber\lastMPbvalue
           \edef\currentMPspecial{\the\scratchcounter}%
           \ifnum\finiMPpath=2 % to outer level
             \the\invokeMPspecials
           \fi
         \fi
       \fi
     \fi
     \flushMPpath
     \closeMPpath
     \finishMPpath
   \fi
   \let\handleMPsequence\dohandleMPsequence
   \resetMPstack
   \nofMPsegments0
   \handleMPsequence}

%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
\let\currentMPshades\empty

\def\startMPshading#1%
  {\edef\currentMPspecial{\gMPs{#1}}}

\def\stopMPshading
  {\global\advance\currentPDFshade \plusone
   \setxvalue{obj:Sh:\currentMPspecial}%
     {/Sh\the\currentPDFshade\space\the\pdflastobj\space0 R }%
   \setxvalue{mps:Sh:\currentMPspecial}%
     {\the\currentPDFshade}}

\appendtoks
  \global\let\currentMPshades\empty
\to \MPstartresources

\appendtoks
  \ifx\currentMPshades\empty \else
    \xdef\currentPDFresources{\currentPDFresources
      /Shading <<\currentMPshades>>}%
  \fi
\to \MPstopresources

\def\invokeMPshadespecial
  {\ifundefined{mps:Sh:\currentMPspecial}\else
     \edef\currentMPshade{\getvalue{obj:Sh:\currentMPspecial}}%
     \doifinstringelse\currentMPshade\currentMPshades \donothing
       {\xdef\currentMPshades{\currentMPshades\currentMPshade}}%
     \def\extraMPpathcode{/Sh\getvalue{mps:Sh:\currentMPspecial} sh Q}%
     \chardef\finiMPpath\zerocount
     \PDFcode{q /Pattern cs}%
   \fi}

\appendtoks \invokeMPshadespecial \to \invokeMPspecials

%D We need to convert the \CMYK\ specials into colors, because
%D we have to do it twice, we define a macro.

\def\checkMPshadingcolor#1#2#3#4#5%
  {\edef\tempMPrvalue{\csname\@@MP0#1\endcsname}%
   \edef\tempMPgvalue{\csname\@@MP0#2\endcsname}%
   \edef\tempMPbvalue{\csname\@@MP0#3\endcsname}%
   \global\let\MPresolvedspace\MPgrayspace
   \global\let\MPresolvedcolor\!!zerocount
   \ifnum\MPrgbnumber\tempMPrvalue=\MPspecialsignal\relax
     \ifcase\MPrgbnumber\tempMPgvalue
     \or % 1 = cmyk
       \ifMPcmykcolors
         \expanded{\resolveMPcmykcolor\getvalue{\@@MPSK\number\MPrgbnumber\tempMPbvalue}}\end
       \fi
     \or % 2 = spot
       \ifMPspotcolors
         \expanded{\resolveMPspotcolor\getvalue{\@@MPSP\number\MPrgbnumber\tempMPbvalue}}\end
       \fi
     \or
       % 3 = rgb transparency
       %   to do
     \or
       % 4 == cmyk transparency
       % \ifMPcmykcolors
       %   to do
       % \fi
     \or
       % 5 == spot transparency
       % \ifMPspotcolors
       %   to do
       % \fi
     \fi
   \else
     \ifx\tempMPrvalue\tempMPgvalue
       \ifx\tempMPrvalue\tempMPbvalue
         \expanded{\resolveMPgraycolor\tempMPbvalue}\end
       \else
         \expanded{\resolveMPrgbcolor\tempMPrvalue\space\tempMPgvalue\space\tempMPbvalue}\end
       \fi
     \else
       \expanded{\resolveMPrgbcolor\tempMPrvalue\space\tempMPgvalue\space\tempMPbvalue}\end
     \fi
   \fi
   \let#4\MPresolvedcolor
   \let#5\MPresolvedspace}

%D We also need to make sure that we have two \RGB\ or
%D \CMYK colors, since we have to set the colorspace.

\def\setMPshadingcolors#1#2#3#4#5#6% color space
  {\checkMPshadingcolor{#1}{#2}{#3}\MPshadeAc\MPshadeAs
   \checkMPshadingcolor{#4}{#5}{#6}\MPshadeBc\MPshadeBs
   \ifx\MPshadeAs\MPshadeBs
     \let\MPshadeA\MPshadeAc
     \let\MPshadeB\MPshadeBc
     \let\MPshadeC\MPshadeAs
   \else\ifx\MPshadeAs\MPgrayspace
     \ifx\MPshadeBs\MPrgbspace
       \edef\MPshadeA{\MPshadeAc\space\MPshadeAc\space\MPshadeAc}%
     \else
       \negatecolorcomponent\MPshadeAc
       \edef\MPshadeA{0 0 0 \MPshadeAc}%
     \fi
     \let\MPshadeB\MPshadeBc
     \let\MPshadeC\MPshadeBs
   \else\ifx\MPshadeBs\MPgrayspace
     \let\MPshadeA\MPshadeAc
     \ifx\MPshadeAs\MPrgbspace
       \edef\MPshadeB{\MPshadeBc\space\MPshadeBc\space\MPshadeBc}%
     \else
       \negatecolorcomponent\MPshadeBc
       \edef\MPshadeB{0 0 0 \MPshadeBc}%
     \fi
     \let\MPshadeC\MPshadeAs
   \else
     % different color spaces
     \def\MPshadeA{1}%
     \def\MPshadeB{1}%
     \let\MPshadeC\MPgrayspace
   \fi\fi\fi}

\let\MPshadeA\MPcmykWhite
\let\MPshadeB\MPcmykBlack
\let\MPshadeC\MPgrayspace

%D The reason why this macro is a bit complicates is that we
%D handle black and white situations (otherwise we would have
%D to use \CMYK\ b/w in case of a \CMYK\ shade).

%D Here are the special handlers:

\defineMPspecial{30}
  {\startMPshading{14}% type 2
   \setMPshadingcolors{4}{5}{6}{9}{10}{11}%
   \immediate\pdfobj
     {<</FunctionType 2
        /Domain [\gMPs1 \gMPs2]
        /C0 [\MPshadeA]
        /C1 [\MPshadeB]
        /N \gMPs3>>}%
   \immediate\pdfobj
     {<</ShadingType 2
        /ColorSpace /\MPshadeC\space
        /Function \the\pdflastobj\space 0 R
        /Coords [\gMPs7 \gMPs8 \gMPs{12} \gMPs{13}]
        /Extend [true true]>>}%
   \stopMPshading}

\defineMPspecial{31}
  {\startMPshading{16}% type 3
   \setMPshadingcolors{4}{5}{6}{10}{11}{12}%
   \immediate\pdfobj
     {<</FunctionType 2
        /Domain [\gMPs1 \gMPs2]
        /C0 [\MPshadeA]
        /C1 [\MPshadeB]
        /N \gMPs3>>}%
   \immediate\pdfobj
     {<</ShadingType 3
        /ColorSpace /\MPshadeC\space
        /Function \the\pdflastobj\space 0 R
        /Coords [\gMPs7 \gMPs8 \gMPs9 \gMPs{13} \gMPs{14} \gMPs{15}]
        /Extend [true true]>>}%
   \stopMPshading}

%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.

\def\invokeMPfigurespecial%
  {\getvalue{mps:gr:\currentMPspecial}} % or \relax

\appendtoks \invokeMPfigurespecial \to \invokeMPspecials

\defineMPspecial{10}
  {\setxvalue{mps:gr:\gMPs8}%
     {\noexpand\handleMPfigurespecial
        {\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}%
      \noexpand\setxvalue{mps:gr:\gMPs8}{}}}

\def\handleMPfigurespecial#1#2#3#4#5#6#7% todo : combine with ext fig
  {\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{mps:hl:\gMPs6}%
     {\noexpand\handleMPhyperlink
        {\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}%
      \noexpand\setxvalue{mps:hl:\gMPs6}{}}}

\def\handleMPhyperlink#1#2#3#4#5%
  {%\ifcase\pdfoutput\or
     \setbox\scratchbox\hbox
       {\setbox\scratchbox\null
        \scratchdimen#1\onebasepoint\scratchdimen-\scratchdimen
        \advance\scratchdimen#3\onebasepoint
        \wd\scratchbox\scratchdimen
        \scratchdimen#2\onebasepoint\scratchdimen-\scratchdimen
        \advance\scratchdimen#4\onebasepoint
        \ht\scratchbox\scratchdimen
        \incolorfalse
        \gotobox{\box\scratchbox}[#5]}%
     \setbox\scratchbox\hbox
       {\scratchdimen\MPxoffset\onebasepoint\advance\scratchdimen#1\onebasepoint
        \hskip\scratchdimen
        \scratchdimen\MPyoffset\onebasepoint\advance\scratchdimen#2\onebasepoint
        \raise\scratchdimen\box\scratchbox}%
     \smashbox\scratchbox
     \box\scratchbox
   }%\fi}

\def\invokeMPhyperlinkspecial%
  {\getvalue{mps:hl:\currentMPspecial}} % or \relax

\appendtoks \invokeMPhyperlinkspecial \to \invokeMPspecials

%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\gMPs1}{\gMPs2 \gMPs3 \gMPs4 \gMPs5 }%
   \fi}

\def\setMPcmyk#1 #2 #3 #4 %
  {\setvalue{\@@MP01}{#1}%
   \setvalue{\@@MP02}{#2}%
   \setvalue{\@@MP03}{#3}%
   \setvalue{\@@MP04}{#4}}

\defineMPspecial{2}
  {\ifMPspotcolors
     \setxvalue{\@@MPSP\gMPs1}{\gMPs2 \gMPs3 \gMPs4 \gMPs5 }% space is essential
     \checkMPspot{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}%
   \fi}

\def\setMPspot#1 #2 #3 #4 %
  {\setvalue{\@@MP01}{#1}%
   \setvalue{\@@MP02}{#2}%
   \setvalue{\@@MP03}{#3}%
   \setvalue{\@@MP04}{#4}}

\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}

%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

\ifx\dosavepositionwhd\undefined
  \let\dosavepositionwhd\gobblesevenarguments
\fi

\defineMPspecial{50} % x y width height label
  {\bgroup
   \scratchdimen\MPllx\onebasepoint\scratchdimen-\scratchdimen
   % \scratchdimen-\MPllx\onebasepoint % moet ook werken
   \advance\scratchdimen\gMPs1\onebasepoint
   \edef\x{\number\scratchdimen}%
   \scratchdimen\gMPs2\onebasepoint
   \scratchdimen-\scratchdimen
   \advance\scratchdimen\MPury\onebasepoint
   \edef\y{\number\scratchdimen}%
   \scratchdimen\gMPs3\onebasepoint
   \edef\w{\number\scratchdimen}%
   \scratchdimen\gMPs4\onebasepoint
   \edef\h{\number\scratchdimen}%
   \dosavepositionwhd{\gMPs5}0\x\y\w\h0%
   \egroup}

%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
%D We save all the three components needed in one macro,
%D just to save hash space.

\def\@@MPST{@MPST@}

\def\assignMPStransparency#1#2#3%
  {\edef\PDFtransparencyidentifier{#1}%
   \edef\PDFtransparencyreference {#2}%
   \edef\PDFtransparencycolorspecs{#3}}

\def\PDFtransparencyspec % todo
  {\ifx\MPresolvedspace\MPgrayspace
     \MPresolvedcolor\space  g
     \MPresolvedcolor\space  G%
   \else\ifx\MPresolvedspace\MPrgbspace
     \MPresolvedcolor\space  rg
     \MPresolvedcolor\space  RG%
   \else\ifx\MPresolvedspace\MPcmykspace
     \MPresolvedcolor\space  k
     \MPresolvedcolor\space  K%
   \else\ifx\MPresolvedspace\empty\else
     /\MPresolvedspace\space cs
     /\MPresolvedspace\space CS
     \PDFgetspotcolorspec\MPresolvedcolor
  \fi\fi\fi\fi}

\defineMPspecial{3} % rgb
  {\edef\currentMPspecial{\gMPs6}%
   \presetPDFtransparency{\gMPs1}{\gMPs2}%
   \expanded{\resolveMPrgbcolor\gMPs3 \gMPs4 \gMPs5}\end
   \setevalue{\@@MPST\currentMPspecial}% was \setxvalue, bug !
     {\noexpand\assignMPStransparency
        {\PDFtransparencyidentifier}%
        {\PDFtransparencyreference}%
        {\PDFtransparencyspec}}}

\defineMPspecial{4} % cmyk
  {\edef\currentMPspecial{\gMPs7}%
   \presetPDFtransparency{\gMPs1}{\gMPs2}%
   \expanded{\resolveMPcmykcolor\gMPs3 \gMPs4 \gMPs5 \gMPs6}\end
   \setevalue{\@@MPST\currentMPspecial}% was \setxvalue, bug !
     {\noexpand\assignMPStransparency
        {\PDFtransparencyidentifier}%
        {\PDFtransparencyreference}%
        {\PDFtransparencyspec}}}

\defineMPspecial{5} % spot
  {\edef\currentMPspecial{\gMPs7}%
   \presetPDFtransparency{\gMPs1}{\gMPs2}%
   \checkMPspot{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}%
   \setevalue{\@@MPST\currentMPspecial}% was \setxvalue, bug !
     {\noexpand\assignMPStransparency
        {\PDFtransparencyidentifier}%
        {\PDFtransparencyreference}%
        {\PDFtransparencyspec}}}

% beware: for the moment only supported in pdftex; needs a cleanup!

\def\registerMPcolorspace
  {\doifobjectreferencefoundelse{PDFCS}\MPspotspace
     {\doPDFgetobjectreference{PDFCS}\MPspotspace\PDFobjectreference
      \xdef\currentMPcolorspaces
        {\currentMPcolorspaces\MPspotspacespec\PDFobjectreference\space}}
     \donothing}

%D We need to add resource specifications!

\appendtoks
  \global\let\currentMPcolorspaces\empty
\to \MPstartresources

\appendtoks
  \ifx\currentMPcolorspaces\empty \else
    \xdef\currentPDFresources{\currentPDFresources
       /ColorSpace <<\currentMPcolorspaces>>}%
  \fi
\to \MPstopresources

%D For efficiency reasons, we fall back on the allocation
%D mechanisms already present. For use within \MPTOPDF, we
%D provide a fall back routine.

\let\currentMPtransparencies\empty

% this one triggers a new graphic state

\def\invokeMPtransparencyspecial
  {\scratchcounter\MPrgbnumber\lastMPbvalue
   \edef\currentMPspecial{\the\scratchcounter}%
   \ifundefined{\@@MPST\currentMPspecial}\else
     \getvalue{\@@MPST\currentMPspecial}%
     \doifinstringelse\PDFtransparencyidentifier\currentMPtransparencies
       \donothing\registerMPtransparencyresource % slow
     \PDFcode
       {\PDFtransparencycolorspecs\space
        \PDFtransparencyidentifier\space gs}%
     % potential optimization
     % \setevalue{\@@MPST\currentMPspecial}%
     %   {\PDFcode
     %      {\PDFtransparencycolorspecs\space
     %       \PDFtransparencyidentifier\space gs}}%
     % \getvalue{\@@MPST\currentMPspecial}%
     \let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial
   \fi}

% this one does a reset

\let\revokeMPtransparencyspecial\relax

\appendtoks
  \revokeMPtransparencyspecial
\to \MPstopresources

\def\dorevokeMPtransparencyspecial % only called if state is set
  {\ifx\PDFtransparencyresetidentifier\empty\else
     \doifinstringelse\PDFtransparencyresetidentifier\currentMPtransparencies
       \donothing\registerMPtransparencyresetresource
     \PDFcode{\PDFtransparencyresetidentifier\space gs}%
     % potential optimization
     % \def\dorevokeMPtransparencyspecial
     %   {\PDFcode
     %      {\PDFtransparencycolorspecs\space
     %       \PDFtransparencyidentifier\space gs}}%
     \let\dorevokeMPtransparencyspecial\dodorevokeMPtransparencyspecial
     \let\revokeMPtransparencyspecial\relax % invoke sets it
   \fi}

% and this one does a simplified reset

\def\dodorevokeMPtransparencyspecial % used after first invocation
  {\PDFcode{\PDFtransparencyresetidentifier\space gs}%
   \let\revokeMPtransparencyspecial\relax} % invoke sets it

% add a resource entry

\def\registerMPtransparencyresource
  {\xdef\currentMPtransparencies
     {\currentMPtransparencies
      \PDFtransparencyidentifier\space
      \PDFtransparencyreference\space}}

\def\registerMPtransparencyresetresource
  {\xdef\currentMPtransparencies
     {\currentMPtransparencies
      \PDFtransparencyresetidentifier\space
      \PDFtransparencyresetreference\space}}

\appendtoks \invokeMPtransparencyspecial \to \invokeMPspecials

\ifCONTEXT \else

  \def\@@MPSTN{@MPSTN@}
  \def\@@MPSTO{@MPSTO@}

  \newcount\PDFcurrenttransparency

  \let\PDFtransparencyresetidentifier\empty
  \let\PDFtransparencyresetreference \empty

  \let\PDFtransparencyidentifier\empty
  \let\PDFtransparencyreference \empty

  \def\initializePDFtransparency
    {\global\let\initializePDFtransparency\relax
     \presetPDFtransparency{1}{1}%
     \xdef\PDFtransparencyresetidentifier{/Tr0}%
     \xdef\PDFtransparencyresetreference{\the\pdflastobj\space 0 R}}

  \def\presetPDFtransparency#1#2%
    {\initializePDFtransparency
     \@EA\ifx\csname\@@MPSTO#1:#2\endcsname\relax
       \global\advance\PDFcurrenttransparency \plusone
       \immediate\pdfobj{\PDFtransparencydictionary{#1}{#2}{}}%
       \setxvalue{\@@MPSTN#1:#2}{\the\PDFcurrenttransparency}%
       \setxvalue{\@@MPSTO#1:#2}{\the\pdflastobj}%
     \fi
     \edef\PDFtransparencyidentifier{/Tr\getvalue{\@@MPSTN#1:#2}}%
     \edef\PDFtransparencyreference{\getvalue{\@@MPSTO#1:#2} 0 R}}

  \def\PDFtransparencydictionary#1#2#3% type fraction extras
    {<</Type /ExtGState
       /ca #2 /CA #2
       /BM /\ifcase#1 Normal\or Normal\or Multiply\or Screen\or
            Overlay\or SoftLight\or HardLight\or ColorDodge\or
            ColorBurn\or Darken\or Lighten\or Difference\or
            Exclusion\else Compatible\fi
       #3>>}

\fi

\appendtoks
  \global\let\currentMPtransparencies\empty
\to \MPstartresources

\appendtoks
  \ifx\currentMPtransparencies\empty \else
    \xdef\currentPDFresources{\currentPDFresources
       /ExtGState <<\currentMPtransparencies>>}%
  \fi
\to \MPstopresources

%D In all cases, we need to keep track of the resources
%D used.

%D A few auxiliary macros:

\def\MPgrayspace{DeviceGray}
\def\MPrgbspace {DeviceRGB}
\def\MPcmykspace{DeviceCMYK}
\let\MPspotspace\MPgrayspace

\def\MPcmykBlack{0 0 0 0}
\def\MPcmykWhite{0 0 0 1}

\ifCONTEXT

  \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\end
    {\startMPcolorresolve
     \execcolorR#1:#2:#3:0:0\od
     \stopMPcolorresolve}

  \def\resolveMPcmykcolor#1 #2 #3 #4\end
    {\startMPcolorresolve
     \execcolorC#1:#2:#3:#4:0:0\od
     \stopMPcolorresolve}

  \def\resolveMPgraycolor#1\end
    {\startMPcolorresolve
     \execcolorS#1:0:0\od
     \stopMPcolorresolve}

  \def\resolveMPspotcolor#1 #2 #3 #4\end
    {\startMPcolorresolve
     \ifnum#2>\plusone
       \checkmultitonecolor{#1}%
     \fi
     \execcolorP#1:#2:#3:#4:0:0\od
     \stopMPcolorresolve}

\else

  \def\resolveMPspotcolor#1 #2\end
    {\global\let\MPresolvedspace\MPgrayspace
     \xdef\MPresolvedcolor{0}}

  \def\resolveMPrgbcolor#1 #2 #3\end
    {\global\let\MPresolvedspace\MPrgbspace
     \xdef\MPresolvedcolor{#1 #2 #3}}

  \def\resolveMPcmykcolor#1 #2 #3 #4\end
    {\global\let\MPresolvedspace\MPcmykspace
     \xdef\MPresolvedcolor{#1 #2 #3 #4}}

  \def\resolveMPgraycolor#1\end
    {\global\let\MPresolvedspace\MPgrayspace
     \xdef\MPresolvedcolor{#1}} % should be inverted

\fi

\protect \endinput
