%D \module
%D   [       file=spec-tpd,
%D        version=1996.01.25,
%D          title=\CONTEXT\ Special Macros,
%D       subtitle=\PDFTEX,
%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.

% once we can be sure that the latest versions of pdftex are
% available we can use:
%
% \pdfobj reserveobjnum \edef\one{\the\pdflastobj}
% \pdfobj reserveobjnum \edef\two{\the\pdflastobj}
%
% \pdfobj useobjnum \one {x}
% \pdfobj useobjnum \two {x}
%
% we then can rewrite part of spec-fdf because the other drivers
% already support symbolic references

% layers and links don't work while the spec says they should

% method = auto
%
% \definefileinsertion{tpd}{auto}#1#2#3#4#5#6#7#8#9%
%   {\executesystemcommand{t:/ruby/pstopdf.rb #2}%
%    \dodoinsertfile{tpd}{pdf}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}

% \let\PDFdestvoffset\zeropoint
% \newbox\pdfdestbox
%
% \def\doPDFdestination name #1%
%   {\ifdim\PDFdestvoffset=\zeropoint\relax
%      \pdfdest name {#1} \PDFpageviewkey
%    \else
%      \setbox\pdfdestbox\hbox to \zeropoint
%        {\raise\PDFdestvoffset\hbox{\pdfdest name {#1} \PDFpageviewkey}}%
%      \ht\pdfdestbox\zeropoint
%      \box\pdfdestbox
%    \fi}
%
% \def\PDFdestvoffset{2\lineheight} % {1.5\strutht}

%D \macros
%D   {jobsuffix}
%D
%D Being one of the first typographical systems able to support
%D advances \PDF\ support, \TEX\ is also one of the first
%D systems to produce high quality \PDF\ code directly. Thanks
%D to Han The Thanh c.s. the \TEX\ community can leap forward
%D once again.
%D
%D One important characteristic of \PDFTEX\ is that is can
%D produce standard \DVI\ code as well as \PDF\ code. This
%D enables us to use one format file to support both output
%D formats.

%D All modules in this group use specials to tell drivers what
%D non||\TEX\ actions to take. Because from the \TEX\ point of
%D view, there is no difference between \DVI\ and \PDF, we
%D therefore only have to bend the \DVI\ driver support into
%D \PDF\ support. Technically spoken, specials no longer serve
%D a purpose, except from ending up as comment in the \PDF\
%D file.
%D
%D Before we continue we need to make sure if indeed those
%D \PDFTEX\ primitives are permitted. If no primitives are
%D available, we just stop reading any further.

\unprotect

\ifx\pdftexversion\undefined
  \writestatus{\m!systems}{you should use pdfTeX binaries}\wait
  \protect\expandafter\endinput
\fi

\ifnum\pdftexversion<13
  \writestatus{\m!systems}{your pdfTeX version is much too old}\wait
  \protect\expandafter\endinput
\fi

\ifnum\pdftexversion<14
  \writestatus{\m!systems}{please update your pdfTeX binaries}
\fi

\ifnum\pdftexversion>19
  \pdfhorigin=1 true in
  \pdfvorigin=1 true in
\fi

%D We default to 300 dots per inch image resolution.

\ifx\pdfimageresolution\undefined
  \newcount\pdfimageresolution
\fi

\pdfimageresolution=300

%D Another downward compatible hack:

\ifx\pdflastximagepages\undefined
  \newcount\pdflastximagepages \pdflastximagepages=1
\fi

%D And:

\ifx\pdfpageresources\undefined
  \newtoks\pdfpageresources
\fi

%D In order to get high quality \METAPOST\ inclusion, we set
%D the number of digits to~5 (prevents rounding errors).

\ifx\pdfdecimaldigits\undefined
  \newcount\pdfdecimaldigits
\fi

\pdfdecimaldigits=10

\ifx\pdfinclusionerrorlevel\undefined
  \ifx\pdfoptionpdfinclusionerrorlevel\undefined
    \newcount\pdfinclusionerrorlevel
  \else
    \let\pdfinclusionerrorlevel\pdfoptionpdfinclusionerrorlevel
  \fi
\fi

\pdfinclusionerrorlevel=0

\ifx\pdfminorversion\undefined
  \ifx\pdfoptionpdfminorversion\undefined
    \newcount\pdfminorversion
  \else
    \let\pdfminorversion\pdfoptionpdfminorversion
  \fi
\fi

\pdfminorversion=5

\def\PDFversion{1.\number\pdfminorversion}

% %D Why are the Acrobat viewers so buggy? To prevent font cache
% %D mismatches, we say:
%
% \ifx\pdfuniqueresname\undefined \else
%   \pdfuniqueresname=1
% \fi

%D Once we are sure that we're indeed supporting \PDFTEX, we
%D force \PDF\ output at the highest compression. For debugging
%D purposes one can set the compresslevel to~0. We also have to
%D make sure no other specials are supported, else \PDFTEX\
%D will keep on telling us that we're wrong. We also load the
%D general \PDF\ macros that are shared between this driver and
%D the \ACROBAT\ one.

\startspecials[tpd][reset,fdf]

%D This means that by saying
%D
%D \starttyping
%D \usespecials[tpd]
%D \stoptyping
%D
%D we get ourselves full \PDF\ output.

%D For some internal testing we need to know the output
%D suffix.

\setjobsuffix{pdf}

%D We don't use specials here, which means that we must flush
%D settings before the page is shipped out.

\specialbasedsettingsfalse

%D Some more internal settings.

\appendtoksonce
  \pdfoutput\zerocount
\to \everyresetspecials

\pdfoutput       =1 % we reset that one with \everyresetspecials
\pdfcompresslevel=9 % apart from debugging, no reason for value 0

%D Just in case we mimmick specials, we have to make sure no
%D default specials end up in the process.

\let\defaultspecial=\gobbleoneargument

\appendtoksonce
  \let\defaultspecial\normalspecial
\to \everyresetspecials

\let\PDFcode        \pdfliteral
\def\PDFcontentcode{\pdfliteral}
\def\PDFdirectcode {\pdfliteral direct}

%D \macros
%D   {everyPDFximage}
%D
%D This token register is flushed before an ximage is loaded.

\newevery \everyPDFximage \relax
\let      \everyPDFxform  \everyPDFximage

%D \macros
%D   {dosetuppaper}
%D
%D If we don't set the paper size, \PDFTEX\ will certainly do
%D it in a way we don't want, therefore we need:

\definespecial\dosetuppaper#1#2#3%
  {\global\pdfpagewidth #2\relax
   \global\pdfpageheight#3\relax}

%D \macros
%D   {doloadmapfile,doloadmapline,doresetmapfilelist}

\ifx\pdfmapfile\undefined \let\pdfmapfile\gobbletwoarguments \fi
\ifx\pdfmapline\undefined \let\pdfmapline\gobbletwoarguments \fi

\definespecial\doresetmapfilelist{\pdfmapfile{original-empty.map}}

\ifnum\pdftexversion<120

  \definespecial\doloadmapfile #1#2{\pdfmapfile{+#2}}
  \definespecial\doloadmapline #1#2{}

\else

  \definespecial\doloadmapfile #1#2{\pdfmapfile{#1#2}}
  \definespecial\doloadmapline #1#2{\pdfmapline{#1#2}}

\fi

%D nasty but needed

\appendtoksonce \loadallfontmapfiles \to \everyPDFximage

%D \macros
%D   {doinsertfile,dogetnofinsertpages}
%D
%D Graphics are not part of \TEX\ and therefore not part of the
%D \DVI\ standard. \PDF\ on the other hand has several graphic
%D primitives. During the multi||step process \TEX\
%D $\rightarrow$ \DVI\ $\rightarrow$ \POSTSCRIPT\ $\rightarrow$
%D \PDF\ one can insert graphics using specials. In \PDFTEX\
%D however there is only one step! This means that \PDFTEX\
%D itself has to do the inclusion.
%D
%D At the moment \PDFTEX\ supports inclusion of bitmap \PNG\
%D graphics as well as not too complicated \PDF\ code. Using
%D this last option, we are able to include both \METAPOST\ and
%D \PDF\ output produced by \GHOSTSCRIPT.
%D
%D We fall back on the generic \CONTEXT\ module supp-pdf to
%D accomplish \PDF\ inclusion. The methods implemented there
%D are hooked into both the figure placement mechanisms of
%D \CONTEXT\ and the specials inclusion mechanism.

\definespecial\doinsertfile#1#2#3#4#5#6#7#8#9%
  {\bgroup
   \dodoinsertfile{tpd}{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}%
   \egroup}

%D The number of pages in (for instance an \PDF) insert
%D file, can be asked for using:

\definespecial\dogetnofinsertpages#1%
  {\xdef\nofinsertpages{1}% global
   \doifvalidpdfimagefileelse{#1}%
     {\pdfximage{#1}\xdef\nofinsertpages{\the\pdflastximagepages}}
     {}}

%D Currently we support \type{pdf} for \PDF\ files, \type{mps}
%D for \METAPOST\ graphics, \type{png} and \type{jpg} for
%D bitmap graphics.

\definefileinsertion{tpd}{mps}#1#2#3#4#5#6#7#8#9%
  {\hbox
     {%\convertMPcolors{#1}% plugged in supp-mpe
      \scratchdimen#3\points \PointsToReal{.01\scratchdimen}\xscale
      \scratchdimen#4\points \PointsToReal{.01\scratchdimen}\yscale
      \convertMPtoPDF{#1}\xscale\yscale
      \global\let\PDFimagereference\empty}}

%D The old, \TEX\ base \PDF\ insertion macro:
%D
%D \starttyping
%D \def\dotpdinsertpdf#1#2#3#4#5#6#7#8#9%
%D   {\beforesplitstring#1\at.\to\filename
%D    \scratchdimen=#3pt \PointsToReal{.01\scratchdimen}\xscale
%D    \scratchdimen=#4pt \PointsToReal{.01\scratchdimen}\yscale
%D    \convertPDFtoPDF{\filename.pdf}\xscale\yscale{#5}{#6}{#7}{#8}}
%D \stoptyping
%D
%D superseded by the next macros.

\definefileinsertion{tpd}{pdf}{\handlepdfimage}
\definefileinsertion{tpd}{png}{\handlepdfimage}
\definefileinsertion{tpd}{jpg}{\handlepdfimage}
%definefileinsertion{tpd}{tif}{\handlepdfimage} % unstable

%D Experimental:

% \definefileinsertion{tpd}{svg}{\doPDFinsertsvg}
% \definefileinsertion{tpd}{svgz}{\doPDFinsertsvg}

\def\doPDFinsertsvg#1#2#3#4#5#6#7#8#9%
  {\externalfigureplaceholder{#1}{#7}{#8}}

%D The main file insertion macro is as follows. Because
%D \PDFTEX\ does not support arbitrary suffixes, we double
%D check on a user supplied filename, because \PDFTEX\ chokes
%D on unknown suffixes.

\def\doifvalidpdfimagefileelse#1% todo: greedy split
  {\doiffileelse{#1}
     {\edef\filesuffix{#1}%
      \doloop
        {\@EA\aftersplitstring\filesuffix\at.\to\temp
         \ifx\temp\empty
           \exitloop
         \else
           \let\filesuffix\temp
           % a temporary hack
           \doif\filesuffix{PDF}{\pdfimageresolution72}%
           \doif\filesuffix{pdf}{\pdfimageresolution72}%
           % because pdfTeX scales back
         \fi}}
      {\let\filesuffix\s!unknown}%
   \doiffileinsertionsupportedelse\filesuffix}

\ifx\pdflastximagepages\undefined \chardef\pdflastximagepages=1 \fi

\ifnum\pdftexversion>13

\def\checkpdfimagepagenumber#1%
  {\let\pdfimagepagenumber\empty
   \getfromcommacommand[#1][1]%
   \doifnumberelse\commalistelement
     {\ifcase\commalistelement\else
        \edef\pdfimagepagenumber{page \commalistelement}%
       %\message{(pdf image \pdfimagepagenumber)}%
      \fi}
     {}}

\def\handlepdfimage#1#2#3#4#5#6#7#8#9%
  {\bgroup
   \the\everyPDFximage
   \doifvalidpdfimagefileelse{#1}
     {\checkpdfimagepagenumber{#9}%
      \immediate\pdfximage
        \ifdim#7>\zeropoint \!!width  #7\fi
        \ifdim#8>\zeropoint \!!height #8\fi
        \pdfimagepagenumber
\@@DriverImageBox
        {#1}%
      \xdef\PDFimagereference{\the\pdflastximage}%
      \xdef\nofinsertpages{\the\pdflastximagepages}%
      \pdfrefximage\pdflastximage}
     {\framed[\c!width=#7,\c!height=#8]{#1}}%
   \egroup}

\else

\def\handlepdfimage#1#2#3#4#5#6#7#8#9%
  {\bgroup
   \doifvalidpdfimagefileelse{#1}
     {\pdfimage
        \ifdim#7>\zeropoint \!!width  #7\fi
        \ifdim#8>\zeropoint \!!height #8\fi
        {#1}}%
     {\framed[\c!width=#7,\c!height=#8]{#1}}%
   \egroup}

\fi

%D As we will see now, \PDFTEX\ not only directly supports
%D \type{mps}, \type{png}, \type{pdf}, \type{jpg} but also
%D \type{mov}. In \CONTEXT\ we support movie inserts in a way
%D similar to figure inclusion. The next macro calls the
%D general \PDF\ one.

\definefileinsertion{tpd}{mov}{\doPDFinsertmov}
\definefileinsertion{tpd}{avi}{\doPDFinsertmov}

%D \macros
%D   {doinsertsoundtrack}
%D
%D We use numbers instead of labels to keep track of sounds.

\definespecial\doinsertsoundtrack{\doPDFinsertsoundtrack}

%D \macros
%D   {measureTPDfiguresizetrue}
%D
%D Because \PDFTEX\ measures the figure itself, we can use
%D this feature to bypass the normal prescan. Watch the
%D double check on the suffix. Else \PDFTEX\ would choke.

\newif\ifmeasureTPDfiguresize \measureTPDfiguresizetrue

%D For the moment we don't test for alternatives that
%D themselves have alternatives, especially cylcic
%D dependencies.

% some day we will do a proper check on bitmap depth,
%
% \pdfobj reserveobjnum\relax
% \pdfximage colorspace \pdflastobj {some file}
% ... \pdflastximagecolordepth ...
% \immediate\pdfobj useobjnum \pdflastobj {some spec}

\ifx\@@DriverImageBox\undefined \def\@@DriverImageBox{artbox} \fi

% \def\doguessTPDimagesize#1% does not work as expected
%   {\ifx\@@DriverImageBox\empty
%      \global\setbox\foundexternalfigure\hbox{\pdfximage \pdfimagepagenumber ArtBox {#1}\pdfrefximage\pdflastximage}%
%      \ifdim\ht\foundexternalfigure>\zeropoint
%        \def\@@DriverImageBox{ArtBox}%
%      \else
%        \global\setbox\foundexternalfigure\hbox{\pdfximage \pdfimagepagenumber TrimBox {#1}\pdfrefximage\pdflastximage}%
%        \ifdim\ht\foundexternalfigure>\zeropoint
%          \def\@@DriverImageBox{TrimBox}%
%        \else
%          \global\setbox\foundexternalfigure\hbox{\pdfximage \pdfimagepagenumber CropBox {#1}\pdfrefximage\pdflastximage}%
%          \ifdim\ht\foundexternalfigure>\zeropoint
%            \def\@@DriverImageBox{CropBox}%
%          \fi
%        \fi
%      \fi
%    \fi
%    \@@DriverImageBox}

\ifnum\pdftexversion>13

\def\checkpdfimageattributes
  {\ifx\PDFfigurereference\empty
     \global\let\pdfimageattributes\empty
   \else
     \immediate\pdfobj
       {[ << /Image \PDFobjref\PDFfigurereference
             /DefaultForPrinting true >> ]}%
     \xdef\pdfimageattributes
       {attr {/Alternates \PDFobjref\pdflastobj}}%
   \fi}

\global\let\PDFimagecolorreference\empty

\def\checkpdfimagecolorspecs
  {\ifx\pdflastximagecolordepth \undefined
     \global\let\pdfimagecolorspecs\empty
   \else\ifx\PDFimagecolorreference\empty
     \global\let\pdfimagecolorspecs\empty
   \else
     \xdef\pdfimagecolorspecs{colorspace \PDFimagecolorreference\space}%
   \fi\fi
   \global\let\PDFimagecolorreference\empty}

\def\dogetTPDfiguresize#1#2#3#4#5#6#7%
  {\ifmeasureTPDfiguresize
     #4\zeropoint
     #5\zeropoint
     \doifvalidpdfimagefileelse{#2}
       {\ifvoid\foundexternalfigure
          \donetrue
        \else\ifx\PDFfigurereference\empty
          \donetrue
        \else
          \doifinstringelse\filesuffix{\c!png,\c!jpg}\donetrue\donefalse
        \fi\fi}
       {\donefalse}%
     \ifdone
       \the\everyPDFximage
       \checkpdfimagepagenumber{#3}%
       \checkpdfimageattributes
       \checkpdfimagecolorspecs
       \global\setbox\foundexternalfigure\hbox
         {\immediate\pdfximage
            \pdfimageattributes
            \pdfimagecolorspecs
            \pdfimagepagenumber
            \@@DriverImageBox
            {#2}%
          \xdef\PDFimagereference{\the\pdflastximage}%
          \xdef\nofinsertpages{\the\pdflastximagepages}%
          \pdfrefximage\pdflastximage}%
       #6\wd\foundexternalfigure
       #7\ht\foundexternalfigure
       \global\let\PDFfigurereference\empty
       \global\let\PDFimageattributes\empty
     \else
       #6\zeropoint
       #7\zeropoint
     \fi
  \else
    #1{#2}{#3}{#4}{#5}{#6}{#7}% \normaldogetfiguresize...
  \fi}

\else

  \def\dogetTPDfiguresize#1#2#3#4#5#6#7%
    {\ifmeasureTPDfiguresize
       #4\zeropoint
       #5\zeropoint
       \doifvalidpdfimagefileelse{#2}
         {\global\setbox\foundexternalfigure\vbox{\pdfimage{#2}}%
          #6\wd\foundexternalfigure
          #7\ht\foundexternalfigure}
         {#6\zeropoint
          #7\zeropoint}%
     \else
       #1{#2}{#3}{#4}{#5}{#6}{#7}% \normaldogetfiguresize...
     \fi}

\fi

\let\normaldogetfiguresizepdf=\dogetfiguresizepdf
\let\normaldogetfiguresizepng=\dogetfiguresizepng
\let\normaldogetfiguresizetif=\dogetfiguresizetif
\let\normaldogetfiguresizejpg=\dogetfiguresizejpg

\def\dogetfiguresizepdf{\dogetTPDfiguresize\normaldogetfiguresizepdf}
\def\dogetfiguresizepng{\dogetTPDfiguresize\normaldogetfiguresizepng}
\def\dogetfiguresizetif{\dogetTPDfiguresize\normaldogetfiguresizetif}
\def\dogetfiguresizejpg{\dogetTPDfiguresize\normaldogetfiguresizejpg}

\appendtoksonce
  \let\dogetfiguresizepdf\normaldogetfiguresizepdf
  \let\dogetfiguresizepng\normaldogetfiguresizepng
  \let\dogetfiguresizetif\normaldogetfiguresizetif
  \let\dogetfiguresizejpg\normaldogetfiguresizejpg
\to \everyresetspecials

%D \macros
%D   {doregisterfigure}
%D
%D Here is the fuzzy, very special dependant figure
%D registration special. We need to refer to the innermost
%D object (ximage).

\ifnum\pdftexversion>13

  \definespecial\doregisterfigure#1#2%
    {\doifundefined{IM::#1::#2}
       {\setxvalue{IM::#1::#2}{\the\pdflastximage}}%
     \xdef\PDFfigurereference{\getvalue{IM::#1::#2}}}

\fi

%D \macros
%D  {doovalbox}
%D
%D Drawing frames with round corners is inherited from the
%D main module.

\definespecial\doovalbox {\doPDFovalbox}

%D \macros
%D   {dostartgraymode,dostopgraymode,
%D    dostartrgbcolormode,dostartcmykcolormode,dostartgraycolormode,
%D    dostopcolormode,
%D    dostartrotation,dostoprotation,
%D    dostartscaling,dostopscaling,
%D    dostartmirroring,dostopmirroring,
%D    dostartnegative,dostopnegative,
%D    dostartoverprint,dostopoverprint}
%D
%D These are implemented in the main \PDF\ module.

\definespecial\dostartgraymode     {\doPDFstartgraymode}
\definespecial\dostopgraymode      {\doPDFstopgraymode}
\definespecial\dostartrgbcolormode {\doPDFstartrgbcolormode}
\definespecial\dostartcmykcolormode{\doPDFstartcmykcolormode}
\definespecial\dostartgraycolormode{\doPDFstartgraycolormode}
\definespecial\dostartspotcolormode{\doPDFstartspotcolormode}
\definespecial\dostopcolormode     {\doPDFstopcolormode}
\definespecial\dostartrotation     {\doPDFstartrotation}
\definespecial\dostoprotation      {\doPDFstoprotation}
\definespecial\dostartscaling      {\doPDFstartscaling}
\definespecial\dostopscaling       {\doPDFstopscaling}
\definespecial\dostartmirroring    {\doPDFstartmirroring}
\definespecial\dostopmirroring     {\doPDFstopmirroring}
\definespecial\dostartnegative     {\doPDFstartnegative}
\definespecial\dostopnegative      {\doPDFstopnegative}
\definespecial\dostartoverprint    {\doPDFstartoverprint}
\definespecial\dostopoverprint     {\doPDFstopoverprint}

\definespecial\doregistercmykspotcolor{\doPDFregistercmykspotcolor}
\definespecial\doregisterrgbspotcolor {\doPDFregisterrgbspotcolor}
\definespecial\doregistergrayspotcolor{\doPDFregistergrayspotcolor}

\definespecial\doregistercmykindexcolor{\doPDFregistercmykindexcolor}
\definespecial\doregisterrgbindexcolor {\doPDFregisterrgbindexcolor}
\definespecial\doregistergrayindexcolor{\doPDFregistergrayindexcolor}

\definespecial\doregisterfigurecolor{\doPDFregisterfigurecolor}

\definespecial\dostartnonecolormode{\doPDFstartnonecolormode}
\definespecial\doregisternonecolor {\doPDFregisternonecolor}

\def\doPDFregisterspotcolorname#1#2%
  {\bgroup
   \let\ascii\empty
   \def\docommand##1%
     {\edef\ascii{\ascii
      \ifx\nexthandledtoken\space
        \letterhash20%
      \else\ifx\nexthandledtoken\blankspace
        \letterhash20%
      \else
        ##1%
      \fi\fi}}%
   \expanded{\handletokens#2}\with\docommand
   \letgvalue{@@pdf@@scn@@#1}\ascii
   \egroup}

\def\doPDFregistersomespotcolor#1#2#3#4#5#6#7% name fractions names p's space domain function
  {\bgroup
   \let\spotpops\empty
   \ifcase#2\or
     %def\PDFspotcolornames{/Separation /#1}%
     \edef\PDFspotcolornames{/Separation /\executeifdefined{@@pdf@@scn@@#1}{#1}}%
     \def\PDFspotcolordomain{0.0 1.0}%
   \else
     \dorecurse{#2}{\edef\spotpops{\spotpops pop }}%
     \let\PDFspotcolornames \empty
     \let\PDFspotcolordomain\empty
     \def\dospotcolorcommand##1%
       {\edef\PDFspotcolornames {\PDFspotcolornames/\executeifdefined{@@pdf@@scn@@##1}{##1}\space}%
        \edef\PDFspotcolordomain{\PDFspotcolordomain 0.0 1.0\space}}%
     \processcommacommand[#3]\dospotcolorcommand
     \edef\PDFspotcolornames{/DeviceN [\PDFspotcolornames]}%
   \fi
   \immediate \pdfobj stream attr
     {/FunctionType 4 /Domain [\PDFspotcolordomain] /Range [#6]}{{\spotpops#7}}%
   \immediate \pdfobj
     {[\PDFspotcolornames\space /Device#5 \PDFobjref\pdflastobj]}%
   \dosetobjectreference{PDFCS}{#1}{\the\pdflastobj}%
   \appendtoPDFdocumentcolorspaces{/#1 \PDFobjref\pdflastobj}%
   \egroup}

%D New and very experimental.

% \def\doPDFregistersomeindexcolor#1#2#3#4#5#6#7% name fractions names p's space domain function
%   {\bgroup
%    \let\spotpops\empty
%    \dorecurse{#2}{\edef\spotpops{\spotpops exch pop\space}}%
%    \let\PDFspotcolornames \empty
%    \let\PDFspotcolordomain\empty
%    \def\docommand##1%
%      {\edef\PDFspotcolornames{\PDFspotcolornames/\executeifdefined{@@pdf@@scn@@##1}{##1}\space}%
%       \edef\PDFspotcolordomain{\PDFspotcolordomain 0.0 1.0\space}}%
%    \processcommacommand[#3,None]\docommand
%    \let\PDFcolorindexvector\empty
%    \def\docommand##1%
%      {\scratchdimen##1\points
%       \scratchdimen\recurselevel\scratchdimen
%       \scratchcounter\scratchdimen
%       \divide\scratchcounter \maxcard
%       \edef\PDFcolorindexvector{\PDFcolorindexvector\uchexnumbers\scratchcounter}}%
%    \dostepwiserecurse\zerocount{255}\plusone
%      {\rawprocesscommacommand[#4,1]\docommand
%       \xdef\PDFcolorindexvector{\PDFcolorindexvector\space}}%
%    \immediate \pdfobj stream attr
%      {/FunctionType 4 /Domain [\PDFspotcolordomain] /Range [#6]}{{\spotpops#7}}%
%    \immediate \pdfobj
%      {[/Indexed
%          [/DeviceN [\PDFspotcolornames] /Device#5 \PDFobjref\pdflastobj] %
%          255 <\PDFcolorindexvector>]}%
%    \dosetobjectreference{PDFIX}{#1}{\the\pdflastobj}%
%    \appendtoPDFdocumentcolorspaces{/#1_INDEXED \PDFobjref\pdflastobj}%
%    \egroup}

% we reverse the index; an alternative is to negate the graphic itself (\start/stop negative)

\def\doPDFregistersomeindexcolor#1#2#3#4#5#6#7% name fractions names p's space domain function
  {\bgroup
   \let\spotpops\empty
   \dorecurse{#2}{\edef\spotpops{\spotpops exch pop\space}}%
   \let\PDFspotcolornames \empty
   \let\PDFspotcolordomain\empty
   \def\docommand##1%
     {%\edef\PDFspotcolornames {\PDFspotcolornames/##1\space}%
      \edef\PDFspotcolornames{\PDFspotcolornames/\executeifdefined{@@pdf@@scn@@##1}{##1}\space}%
      \edef\PDFspotcolordomain{\PDFspotcolordomain 0.0 1.0\space}}%
   \processcommacommand[#3,None]\docommand
   \let\PDFcolorindexvector\empty
   \def\docommand##1%
     {\scratchdimen##1\points
      \scratchdimen\recurselevel\scratchdimen
      \scratchcounter\scratchdimen
      \divide\scratchcounter \maxcard
      \edef\PDFcolorindexvector{\PDFcolorindexvector\uchexnumbers\scratchcounter}}%
   %\dostepwiserecurse\zerocount{255}\plusone
   \dostepwiserecurse{255}\zerocount\minusone % we need to negate
     {\rawprocesscommacommand[#4,1]\docommand
      \xdef\PDFcolorindexvector{\PDFcolorindexvector\space}}%
   \immediate \pdfobj stream attr
     {/FunctionType 4 /Domain [\PDFspotcolordomain] /Range [#6]}{{\spotpops#7}}%
   \immediate \pdfobj
     {[/Indexed
         [/DeviceN [\PDFspotcolornames] /Device#5 \the\pdflastobj\space0 R] %
         255 <\PDFcolorindexvector>]}%
   \dosetobjectreference{PDFIX}{#1}{\the\pdflastobj}%
   \appendtoPDFdocumentcolorspaces{/#1_INDEXED \the\pdflastobj\space0 R}%
   \egroup}

%D \macros
%D   {dostarttransparency,dostoptransparency}
%D
%D For transparency, we need to implement a couple of
%D auxiliary macros. If needed, we will generalize tham later.

\definespecial\dostarttransparency{\doPDFstarttransparency}
\definespecial\dostoptransparency {\doPDFstoptransparency}

\PDFtransparencysupportedtrue

\def\@@PDT{@PDT@}

\ifx\PDFcurrenttransparency\undefined
  \newcount\PDFcurrenttransparency \PDFcurrenttransparency=0 % -1
\fi

\def\assignPDFtransparency#1#2%
  {\edef\PDFtransparencyidentifier{/Tr#1}%
   \edef\PDFtransparencyreference{\PDFobjref{#2}}}

\def\presetPDFtransparency#1#2%
  {\initializePDFtransparency
   \executeifdefined{\@@PDT#1:#2}{\dopresetPDFtransparency{#1}{#2}}}

\def\dopresetPDFtransparency#1#2%
  {\global\advance\PDFcurrenttransparency \plusone
   \immediate\pdfobj{\PDFtransparancydictionary{#1}{#2}{}}%
   \edef\PDFtransparencyidentifier{/Tr\the\PDFcurrenttransparency}%
   \edef\PDFtransparencyreference {\PDFobjref\pdflastobj}%
   \setxvalue{\@@PDT#1:#2}%
     {\noexpand\assignPDFtransparency{\the\PDFcurrenttransparency}{\the\pdflastobj}}%
   \appendtoPDFdocumentextgstates
     {\PDFtransparencyidentifier\space
      \PDFtransparencyreference\space}}

\def\initializePDFtransparency
  {\immediate\pdfobj{\PDFtransparancydictionary{1}{1}{/AIS false}}%
   \xdef\PDFtransparencyresetidentifier{/Tr0}%
   \xdef\PDFtransparencyresetreference{\PDFobjref\pdflastobj}%
   \setxvalue{\@@PDT0:0}%
     {\noexpand\assignPDFtransparency{0}{\the\pdflastobj}}%
   \appendtoPDFdocumentextgstates
     {\PDFtransparencyresetidentifier\space
      \PDFtransparencyresetreference\space}%
   \global\let\initializePDFtransparency\relax}

%D \macros
%D   {dostartclipping,dostopclipping}
%D
%D Clipping in \PDFTEX\ is rather trivial. We can even hook
%D in \METAPOST\ without problems.

\definespecial\dostartclipping#1#2#3%
  {\PointsToBigPoints{#2}\width
   \PointsToBigPoints{#3}\height
   \grabMPclippath{#1}{1}\width\height
     {0 0 m \width\space 0 l \width \height l 0 \height l}%
   \pdfliteral % PDFcode ?
     {q 0 w \MPclippath\space W n}}

\definespecial\dostopclipping
  {\pdfliteral{Q n}} % PDFcode

%D \macros
%D   {dosetupinteraction}
%D
%D Nothing special is needed to enable \PDF\ commands and
%D interaction. We stick with a message.

\definespecial\dosetupinteraction
  {\showmessage\m!interactions{21}{pdftex}}

%D \macros
%D   {doresetgotowhereever,
%D    dostartthisisrealpage,dostartthisislocation,
%D    dostartgotorealpage,dostartgotolocation,dostartgotoJS}
%D
%D The interactions macros are the core of this module. We
%D support both page destinations and named ones. We don't
%D need the \type{\stop}||alternatives. We also don't need
%D to set the special that sets the real page number.

\definespecial\doresetgotowhereever {\doPDFresetgotowhereever}
\definespecial\dostartthisislocation{\doPDFstartthisislocation}

%D When going to a location, we obey the time and space saving
%D boolean \type{\ifusepagedestination}. Named destinations are
%D stripped and made robust. This all happens in the macros
%D called for.

\definespecial\dostartgotolocation{\doPDFstartgotolocation}
\definespecial\dostartgotorealpage{\doPDFstartgotorealpage}
\definespecial\dostartgotoJS      {\doPDFstartgotoJS}

\let\PDFpagexyzspec\empty % hack, pdftex does not accept spec

%D \macros
%D   {doflushJSpreamble}
%D
%D It does not make sense to duplicate common \JAVASCRIPT\
%D functions, and therefore they can be predefined and must be
%D output separately. Currently this special is not shared
%D with the \ACROBAT\ one, simply because \DISTILLER\ does not
%D yet support something \type{\pdfnames}.

% \oneJSpreamblefalse  % buggy in acrobat

\definespecial\doflushJSpreamble#1%
  {\bgroup
   \let\compositeJScode\empty
   \def\docommando##1%
     {\edef\sanitizedJScode{\getJSpreamble{##1}}%
      \@EA\doPSsanitizeJScode\sanitizedJScode\to\sanitizedJScode
      \immediate\pdfobj {<< /S /JavaScript /JS (\sanitizedJScode) >>}%
      \edef\compositeJScode
        {\compositeJScode\space (##1) \PDFobjref\pdflastobj}}%
   \processcommalist[#1]\docommando
   \immediate\pdfobj{<< /Names [ \compositeJScode ] >>}%
   \pdfnames{/JavaScript \PDFobjref\pdflastobj}%
   \egroup}

%D \macros
%D   {dostarthide,dostophide}
%D
%D Hiding parts of the document for printing is not yet
%D supported by \PDF\ and therefore \PDFTEX.

\definespecial\dostarthide{}
\definespecial\dostophide {}

%D \macros
%D   {dosetupscreen}
%D
%D Setting of the screen boundingbox involves some
%D calculations. Here we also take care of (non) full screen
%D startup. The dimensions are rounded. Because \PDFTEX\ and
%D \ACROBAT\ handle setting the page dimensions in a
%D different way, we do not share this special.

\definespecial\dosetupscreen  {\doPDFsetupscreen  \pdfpageheight}

\definespecial\dosetupartbox  {\doPDFsetupartbox  \pdfpageheight}
\definespecial\dosetupcropbox {\doPDFsetupcropbox \pdfpageheight}
\definespecial\dosetupbleedbox{\doPDFsetupbleedbox\pdfpageheight}
\definespecial\dosetuptrimbox {\doPDFsetuptrimbox \pdfpageheight}

%D \macros
%D   {dostartexecutecommand}
%D
%D \PDF\ viewers enable us to navigate using menus and shortcut
%D keys. These navigational tools can also be accessed by using
%D annotations. The next special takes care of inserting them.

\definespecial\dostartexecutecommand{\doPDFstartexecutecommand}

%D \macros
%D   {dosetupidentity}
%D
%D Documents can be tagged with an application accessible title
%D and subtitle, the authorname, a date, the creator, keywords
%D etc. For the moment \PDFTEX\ only supports the first three
%D of these.

\definespecial\dosetupidentity{\doPDFsetupidentity}

%D \macros
%D   {dostartrunprogam}
%D
%D We can run a program form within a document, although this
%D feature is rather weak, due to path problems and buggy
%D argument passing.

\definespecial\dostartrunprogram{\doPDFstartrunprogram}

%D \macros
%D   {dostartgotoprofile, dostopgotoprofile,
%D    dobeginofprofile, doendofprofile}
%D
%D \CONTEXT\ user profiles and version control fall back on
%D \PDF\ article threads. Unfortunately one cannot influence
%D the view yet in an (for me) acceptable way.

\definespecial\dostartgotoprofile{\doPDFstartgotoprofile}

%D Some day, I'll reimplement threading in a useful way.
%D Currently the viewers handle threads rather diffuse.

\ifnum\pdftexversion>13

\definespecial\dobeginofprofile#1#2#3#4%
  {\setPDFdestination{#1}%
   \doifsomething\PDFdestination
     {\pdfthread
        width #2 height #3
        attr {/Title (\PDFdestination)} % can be omitted
        name {\PDFdestination}}}

\definespecial\doendofprofile%
  {}

\fi

%D \macros
%D  {doinsertbookmark}
%D
%D In \PDF\ bookmarks are the building blocks of a viewer
%D provided sort of table of contents. \TEX\ has to provide
%D the entry as well as the number of child entries. Strings
%D need to be sanatized as good as possible to suit the default
%D encoding. In \CONTEXT\ users can overrule this string by
%D supplying an alternative one. Look at the macro called for
%D to see how funny these bookmarks are defined.

\definespecial\doinsertbookmark{\doPDFinsertbookmark}

%D \macros
%D  {dostartobject,dostopobject,doinsertobject}
%D
%D Due to \PDF's object oriented character, we can include and
%D reuse objects. These can be compared with \TEX's boxes. The
%D \TEX\ counterpart is defined in the module \type{spec-dvi}.
%D We don't use the dimensions here.
%D
%D The next solution is not that beautiful. Because objects are
%D containers for whatever kind of content, graphics can be
%D part of this content, and a graphic object can be part of
%D the more general type. In practice this means that an ximage
%D would be embedded in an xform, which in itself is not that
%D big a problem, apart from a few bytes overhead. However, for
%D reasons unknown to me alternative images must be pure
%D ximages |<|indeed, somehow one cannot use a vector graphic
%D as alternative|>| that are not embedded into forms, so this
%D is why the object handler treats them different. This
%D implies knowledge of the calling routines, especially the
%D \type{FIG} trigger, that signals that we just embedded an
%D image. Alternatively I could have introduced a dual object
%D system, but the overhead in duplicate specials is currently
%D not what we want. I'd rather implement a more mature
%D object support system from scratch.

\let\currentPDFresources\empty
\let\PDFimageattributes \empty
\let\PDFfigurereference \empty
\let\PDFimagereference  \empty

\ifnum\pdftexversion>13

  \definespecial\dostartobject#1#2#3#4#5%
    {\bgroup
     \setbox\nextbox\vbox\bgroup
     \def\dodostopobject
       {\egroup
        \ifx\PDFimagereference\empty
          % We also flush page resources, since shared
          % resources end up there; otherwise transparencies
          % won't work in xforms; some day I will optimize
          % this.
          \the\everyPDFxform
          \immediate\pdfxform
            resources {\currentPDFresources\the\pdfpageresources}%
            \nextbox
          \global\let\currentPDFresources\empty
          \dosetobjectreference{#1}{#2}{\the\pdflastxform}%
        \else
          \dosetobjectreference{#1}{#2}{-\PDFimagereference}%
          \global\let\PDFimagereference\empty
        \fi}}

  \definespecial\dostopobject
    {\dodostopobject
     \egroup}

  \definespecial\doresetobjects
    {\global\let\PDFimagereference\empty}

  \definespecial\doinsertobject#1#2%
    {\bgroup
     \doifobjectreferencefoundelse{#1}{#2}
       {\dogetobjectreference{#1}{#2}\PDFobjectreference
        \ifnum\PDFobjectreference<0
          \@EA\@EA\@EA\pdfrefximage\@EA\gobbleoneargument\PDFobjectreference
        \else
          \pdfrefxform\PDFobjectreference
        \fi}%
       {}%
     \egroup}

\else

  \definespecial\dostartobject#1#2#3#4#5%
    {\bgroup
     \setbox\nextbox\vbox\bgroup
     \def\dodostopobject
       {\egroup
        \the\everyPDFxform
        \pdfform\nextbox
        \dosetobjectreference{#1}{#2}{\the\pdflastform}}}

  \definespecial\dostopobject
    {\dodostopobject
     \egroup}

  \definespecial\doinsertobject#1#2%
    {\bgroup
     \dogetobjectreference{#1}{#2}\PDFobjectreference
     \pdfrefform\PDFobjectreference
     \egroup}

\fi

%D \macros
%D   {dosetpagetransition}
%D
%D Page transitions only make sence in presentations. They are
%D passed as raw \PDF\ code to the page object. Take a look
%D at the implementation to get an impression of the rubish
%D passed on.

\definespecial\dosetpagetransition{\doPDFsetpagetransition}

%D The expansion is needed because else the \type{\pdfpageattr}
%D token list flushes an unexpanded \type{\csname}. The
%D \type{\global} is needed because the assignment can take
%D place deeply buried (for instance in the \type{\shipout}
%D box.

%D \macros
%D   {doinsertcomment, doflushcomments}
%D
%D Text annotation, or comments, are provided too:

\definespecial\doinsertcomment{\doPDFinsertcomment}
\definespecial\doflushcomments{\doPDFflushcomments}

%D \macros
%D   {dopresetlinefield,dopresettextfield,
%D    dopresetchoicefield,dopresetpopupfield,dopresetcombofield,
%D    dopresetpushfield,dopresetcheckfield,
%D    dopresetradiofield,dopresetradiorecord}
%D
%D \PDF\ offers extensive field support. The next bunch of
%D definitions map the specials.

\definespecial\dopresetlinefield  {\doFDFpresetlinefield}
\definespecial\dopresettextfield  {\doFDFpresettextfield}
\definespecial\dopresetchoicefield{\doFDFpresetchoicefield}
\definespecial\dopresetpopupfield {\doFDFpresetpopupfield}
\definespecial\dopresetcombofield {\doFDFpresetcombofield}
\definespecial\dopresetpushfield  {\doFDFpresetpushfield}
\definespecial\dopresetcheckfield {\doFDFpresetcheckfield}
\definespecial\dopresetradiofield {\doFDFpresetradiofield}
\definespecial\dopresetradiorecord{\doFDFpresetradiorecord}

%D \macros
%D   {dodefinefieldset,dogetfieldset,doiffieldset}
%D
%D Field sets, needed for reset and submit handling, are
%D taken care of by:

\definespecial\dodefinefieldset{\doFDFdefinefieldset}
\definespecial\dogetfieldset   {\doFDFgetfieldset}
\definespecial\doiffieldset    {\doFDFiffieldset}

%D \macros
%D   {doregistercalculationset}
%D
%D The calculation order is defined using:

\definespecial\doregistercalculationset{\doFDFregistercalculationset}

%D \macros
%D   {dosetposition, dosetpositionwdh, dosetpositionplus}
%D
%D Opposite to its \DVI\ counterpart, the \PDFTEX\ backend
%D can provide positional information directly. Since
%D \CONTEXT\ only uses relative positions, the origin is of
%D less importance.

% \def\doTPDsetposition#1#2#3%
%   {\bgroup
%    \edef\doTPDsetposition%
%      {\writeutilitycommand
%         {#1%
%          {#2}%
%          {\noexpand\realfolio}%
%          {\noexpand\number\pdflastxpos}%
%          {\noexpand\number\pdflastypos}%
%          #3}}%
%    \pdfsavepos
%    \doTPDsetposition
%    \egroup}
%
% \definespecial\dosetposition#1%
%   {\doTPDsetposition{\pospxy}{#1}{}}
%
% \definespecial\dosetpositionwhd#1#2#3#4%
%   {\doTPDsetposition{\pospxywhd}{#1}{{#2}{#3}{#4}}}

\definespecial\dosetposition#1%
  {\pdfsavepos
   \dolazysaveposition
     {#1}%
     {\noexpand\realfolio}%
     {\noexpand\number\pdflastxpos}%
     {\noexpand\number\pdflastypos}}%

\definespecial\dosetpositionwhd#1#2#3#4%
  {\pdfsavepos
   \dolazysavepositionwhd
     {#1}%
     {\noexpand\realfolio}%
     {\noexpand\number\pdflastxpos}%
     {\noexpand\number\pdflastypos}%
     {#2}{#3}{#4}}

\definespecial\dosetpositionplus#1#2#3#4#5%
  {\pdfsavepos
   \dolazysavepositionplus
     {#1}%
     {\noexpand\realfolio}%
     {\noexpand\number\pdflastxpos}%
     {\noexpand\number\pdflastypos}%
     {#2}{#3}{#4}{#5}}

%D \macros
%D   {doPDFdestination}
%D
%D Finally we implement some low level macros to deal with
%D flushing \PDF\ code. First we handle the named destinations.

\def\doPDFdestination name #1%
  {\pdfdest name {#1} \PDFpageviewkey}

%D \macros
%D   {doPDFaction,doPDFannotation,ifsharePDFactions}
%D
%D Next we handle annotations. All link annotations are
%D implemented using the action dictionary. This enables us to
%D use multiple actions. The second macro is for instance
%D used for movie inclusion.

\newif\ifsharePDFactions \sharePDFactionstrue

% hm, due to some stupid optimization this feature has been
% disabled for some time, watch out \lastPDFaction is to be
% persistent

\ifnum\pdftexversion>13

  \def\doPDFaction width #1 height #2 action #3%
    {\ifcollectreferenceactions
       \xdef\lastPDFaction{#3}%
     \else
       \ifsharePDFactions
         \ifcase\similarreference\relax
           \xdef\lastPDFaction{<<#3>>}%
         \or
           \immediate\pdfobj{<<#3>>}%
           \xdef\lastPDFaction{\PDFobjref\pdflastobj}%
         \else
           % leave \lastPDFaction untouched
         \fi
       \else
         \xdef\lastPDFaction{<<#3>>}%
       \fi
       \pdfannot
         width #1 height #2 depth \zeropoint
           {/Subtype /Link
            /Border [0 0 0]
            \ifhighlighthyperlinks \else /H /N \fi
            /A \lastPDFaction}%
      \fi}

  % less #2 passing

  \def\doPDFaction width #1 height #2 action #3%
    {\xdef\lastPDFcontent{#3}%
     \ifcollectreferenceactions
       \global\let\lastPDFaction\lastPDFcontent
     \else
       \ifsharePDFactions
         \ifcase\similarreference\relax
           \xdef\lastPDFaction{<<\lastPDFcontent>>}%
         \or
           \immediate\pdfobj{<<\lastPDFcontent>>}%
           \xdef\lastPDFaction{\PDFobjref\pdflastobj}%
         \else
           % leave \lastPDFaction untouched
         \fi
       \else
         \xdef\lastPDFaction{<<\lastPDFcontent>>}%
       \fi
       \pdfannot
         width #1 height #2 depth \zeropoint
           {/Subtype /Link
            /Border [0 0 0]
            \ifhighlighthyperlinks \else /H /N \fi
            /A \lastPDFaction}%
      \fi}

\else

  \def\doPDFaction width #1 height #2 action #3%
    {\ifcollectreferenceactions
       \xdef\lastPDFaction{#3}%
     \else
       \ifsharePDFactions
         \ifcase\similarreference\relax
           \xdef\lastPDFaction{<<#3>>}%
         \or
           \immediate\pdfobj{<<#3>>}%
           \xdef\lastPDFaction{\PDFobjref\pdflastobj}%
         \else
           % leave \lastPDFaction untouched
         \fi
       \else
         \xdef\lastPDFaction{<<#3>>}%
       \fi
       \pdfannotlink % could be \pdfannot if not the - problem was there
         width #1 height #2 depth \zeropoint
         user {/Subtype /Link
               /Border [0 0 0]
               \ifhighlighthyperlinks \else /H /N \fi
               /A \lastPDFaction}%
       \pdfendlink
     \fi}

\fi

% pdftex and viewers give problems with this one (printing forms)
%
%\def\doPDFannotation width #1 height #2 data #3%
%  {\pdfannot width #1sp height -#2sp depth \zeropoint{#3}}
%
% This is corrected in version 14. When this version is wide
% spread, this will be cleaned up.

\ifnum\pdftexversion>13

  \def\doPDFannotation width #1 height #2 data #3%
    {\pdfannot width #1 height #2 depth \zeropoint{#3}}

\else

  \def\doPDFannotation width #1 height #2 data #3%
    {\hbox{\raise#2\hbox{\pdfannot width #1 height #2 depth \zeropoint{#3}}}}

\fi

%D \macros
%D   {doPDFannotationobject,doPDFactionobject}
%D
%D For field support we need annotation objects. Although in
%D many cases we can do without indirect references (and use
%D the last annotation object number directly), we take the
%D save route.

\def\doPDFannotationobject class #1 name #2 width #3 height #4 data #5%
  {\doPDFannotation width #3 height #4 data {#5}%
   \dosetobjectreference{#1}{#2}{\the\pdflastannot}}

\def\doPDFactionobject class #1 name #2 width #3 height #4 action #5%
  {\doPDFaction width {#3} height {#4} action {#5}%
   \dosetobjectreference{#1}{#2}{\the\pdflastannot}}

%D \macros
%D   {doPDFaddtocatalog,doPDFaddtoinfo,
%D    doPDFpageattribute,doPDFpagesattribute}
%D
%D Next some simple ones. Watch the global directive and the
%D expansion in the page attribute macro.

\def\doPDFaddtocatalog
  {\pdfcatalog}

\def\doPDFaddtoinfo
  {\pdfinfo}

\def\doPDFpageattribute#1%
  {\expanded{\global\pdfpageattr{#1\the\pdfpageattr}}}

\def\doPDFpageresource#1%
  {\expanded{\global\pdfpageresources{#1\the\pdfpageresources}}}

\def\doPDFpagesattribute#1%
  {\expanded{\global\pdfpagesattr{#1\the\pdfpagesattr}}}

\def\doPDFresetpageattributes
  {\global\pdfpageattr\emptytoks}

\def\doPDFresetpageresources
  {\global\pdfpageresources\emptytoks}

%D \macros
%D   {doPDFbookmark}
%D
%D Well, isn't the next one ugly? Thanks to the \PDF\
%D standard.

% obsolete cq. buggy in pdfTeX
%
% \def\doPDFbookmark level #1 n #2 text #3 page #4 open #5%
%   {\pdfoutline
%      goto page #4\space
%      \ifcase#2 \else count \ifcase#5-\fi#2 \fi
%      {#3}}

% \def\doPDFbookmark level #1 n #2 text #3 page #4 open #5%
%   {\pdfoutline
%      user {<</S /GoTo /D [#4\space\PDFpageviewwrd]>>}%
%      \ifcase#2 \else count \ifcase#5-\fi#2 \fi
%      {#3}}

\def\doPDFbookmark level #1 n #2 text #3 page #4 open #5%
  {\doPDFgetpagereference{#4}\PDFobjectreference
   \pdfoutline
     user {<</S /GoTo /D [\PDFobjectreference\space\PDFpageviewwrd]>>}%
     \ifcase#2 \else count \ifcase#5-\fi#2 \fi
     {#3}}

%D \macros
%D   {doPDFdictionaryobject,doPDFarrayobject}
%D
%D Where \PDFTEX\ has only one object primitive, optionally a
%D stream one, \ACROBAT\ has several operators.

\def\doPDFdictionaryobject class #1 name #2 data #3%
  {\flushatshipout
     {\immediate\pdfobj{<< #3 >>}%
      \dosetobjectreference{#1}{#2}{\the\pdflastobj}}}

\def\doPDFarrayobject class #1 name #2 data #3%
  {\flushatshipout
     {\immediate\pdfobj{[ #3 ]}%
      \dosetobjectreference{#1}{#2}{\the\pdflastobj}}}

%D \macros
%D   {defaultobjectreference,doPDFgetobjectreference}
%D
%D Because in \PDFTEX\ we have to construct the object
%D references \type{N 0 R}, we can default to the non existing
%D zero object number.

\def\defaultobjectreference#1#2%
  {0}

\def\doPDFgetobjectreference#1#2#3%
  {\dogetobjectreference{#1}{#2}#3%
   \edef#3{\ifx#3\empty null\else\PDFobjref{#3}\fi}}

% \def\doPDFgetobjectpage         #1#2#3{..}
% \def\doPDFgetobjectpagereference#1#2#3{..}

\ifx\pdfpageref\undefined

  \def\doPDFgetpagereference % number macro
    {\installprogram{texutil --filter \jobname}%
     \gdef\doPDFgetpagereference##1{\doPDFgetobjectreference{PDFP}{\number##1}}% {##2}
     \doPDFgetpagereference}

\else

  \def\doPDFgetpagereference#1#2% number macro
    {\edef#2{\ifnum#1>\zerocount\PDFobjref{\pdfpageref#1}\else null\fi}}

\fi

%D \macros
%D   {initializePDFnegative,initializePDFoverprint}
%D
%D Here follow some rather obscure macros. They will only
%D come into action when one wants negated output.

%D Todo: move code to fdf module and

\def\initializePDFnegative
  {\immediate\pdfobj stream attr {/FunctionType 4 /Range [0 1] /Domain [0 1]} {{1 exch sub}}%
   \immediate\pdfobj{<</Type /ExtGState /TR \PDFobjref\pdflastobj>>}%
   \appendtoPDFdocumentextgstates{/GSnegative \PDFobjref\pdflastobj}%
   \immediate\pdfobj{<</Type /ExtGState /TR /Identity>>}%
   \appendtoPDFdocumentextgstates{/GSpositive \PDFobjref\pdflastobj}%
   \global\let\initializePDFnegative\relax}

\def\initializePDFoverprint
  {\immediate\pdfobj{<</Type /ExtGState /OP false /OPM 0>>}% /op defaults to /OP
   \appendtoPDFdocumentextgstates{/GSknockout \PDFobjref\pdflastobj}%
   \immediate\pdfobj{<</Type /ExtGState /OP true /OPM 1>>}% /op defaults to /OP
   \edef\PDFobjectreferenceB{\the\pdflastobj}%
   \appendtoPDFdocumentextgstates{/GSoverprint \PDFobjref\pdflastobj}%
   \global\let\initializePDFoverprint\relax}

%D File embedding. Storing the stream identifier is needed
%D to get access to the number. When typeset, the user can
%D feed this number to \type {pdftosrc} and filter the
%D file from the \PDF\ file.

\let\PDFlaststreamobject   \s!unknown
%def\PDFlaststreamreference{0 0 R}

\def\doPDFfilestreamobject class #1 name #2 file #3 source #4%
  {\immediate\pdfobj stream file{#4}%
   \edef\PDFlaststreamobject{\the\pdflastobj}%
   \dosetobjectreference{PDFFS}{#2}{\PDFlaststreamobject}%
   \doPDFdictionaryobject class {#1} name {#2} data
     {/Type /Filespec /F (#3) /EF <</F \PDFobjref\PDFlaststreamobject>>}}

\def\doPDFgetfilestreamreference#1#2%
  {\doPDFgetobjectreference{PDFFS}{#1}#2}

\def\doPDFfilestreamidentifier#1%
  {\doifsomething{#1}
     {\doPDFgetfilestreamreference{#1}\PDFobjectreference
      \@EA\beforesplitstring\PDFobjectreference\at{ }\to\PDFlaststreamobject
      \PDFlaststreamobject}}

% %D We can set \METAPOST\ prologues to~2:

\def\MPprologues{2}

%D Experimental:

\definespecial\dostartfonteffect{\doPDFstartfonteffect}
\definespecial\dostopfonteffect {\doPDFstopfonteffect}

%D Some MP stuff:

\let\handleMPfshow\dohandleMPfshow % default anyway

\ifnum\pdftexversion<14

  \def\setMPPDFobject#1#2% resources boxnumber
    {\def\getMPPDFobject{\box#2}}

\else

  \def\setMPPDFobject#1#2% resources boxnumber
    {\immediate\pdfxform resources{#1}#2%
     \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}}

\fi

\let\getMPPDFobject\relax

\definespecial\doinsertMPfile#1%
  {\doiffileelse{./#1}{\includeMPasPDF{./#1}}{\message{[MP #1]}}}

%D Now we can finish this module.

\stopspecials

\protect \endinput
