%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 ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. % 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}% % {\executesystemcommand{t:/ruby/pstopdf.rb #2}% % \dofileinsertion{tpd}{pdf}} % \let\PDFdestvoffset\zeropoint % \newbox\pdfdestbox % % \def\doPDFdestination#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 and 600 dpi %D bitmap fonts (when asked for). \ifx\pdfimageresolution\undefined \newcount\pdfimageresolution \fi \ifx\pdfpkresolution \undefined \newcount\pdfpkresolution \fi \pdfimageresolution=300 \pdfpkresolution =600 %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 %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. \ifdefined\everyPDFximage \else \newtoks\everyPDFximage \fi \ifdefined\everyPDFxform \else \newtoks\everyPDFxform \fi %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 {\global\let\doresetmapfilelist\relax \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 \appendtoksonce \loadallfontmapfiles \to \everyPDFxform %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 {\dofileinsertion{tpd}{\truegraphictype\@@DriverImageType}} %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} {\hbox {\convertMPtoPDF\@@DriverImageFile{1}{1}% \global\let\PDFimagereference\empty}} \definefileinsertion{tpd}{pdf}{\handlepdfimage} \definefileinsertion{tpd}{png}{\handlepdfimage} \definefileinsertion{tpd}{jpg}{\handlepdfimage} \definefileinsertion{tpd}{jb2}{\handlepdfimage} % \definefileinsertion{tpd}{jpeg} {\handlepdfimage} % \definefileinsertion{tpd}{jbig2}{\handlepdfimage} %D Experimental: %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 \lowercasestring\temp\to\filesuffix % insertion check also needs lowercase % a temporary hack \doif\filesuffix{pdf}{\pdfimageresolution72}% % because pdfTeX scales back \fi}} {\let\filesuffix\s!unknown}% \doiffileinsertionsupportedelse\filesuffix} \ifx\pdflastximagepages\undefined \chardef\pdflastximagepages=1 \fi \def\checkpdfimagepagenumber {\edef\pdfimagepagenumber {\ifx\@@DriverImagePage\empty\else\ifnum\@@DriverImagePage>\zerocount \space page\space\@@DriverImagePage\space \fi\fi}} \ifnum\pdftexversion>13 \def\handlepdfimage {\bgroup \the\everyPDFximage \doifvalidpdfimagefileelse\@@DriverImageFile {\checkpdfimagepagenumber \ifx\pdfimagepagenumber\empty\@EA\pdfimmediateximage\else\@EA\pdfximage\fi \ifdim\@@DriverImageWidth >\zeropoint \!!width \@@DriverImageWidth \fi \ifdim\@@DriverImageHeight>\zeropoint \!!height\@@DriverImageHeight\fi \pdfimagepagenumber \@@DriverImageBox {\@@DriverImageFile} \xdef\PDFimagereference{\the\pdflastximage}% \xdef\nofinsertpages{\the\pdflastximagepages}% \pdfrefximage\pdflastximage} {\framed[\c!width=\@@DriverImageWidth,\c!height=\@@DriverImageHeight]{\@@DriverImageFile}}% \egroup} \else \def\handlepdfimage {\bgroup \doifvalidpdfimagefileelse\@@DriverImageFile {\pdfimage \ifdim\@@DriverImageWidth >\zeropoint \!!width \@@DriverImageWidth \fi \ifdim\@@DriverImageHeight>\zeropoint \!!height \@@DriverImageHeight\fi {\@@DriverImageFile}}% {\framed[\c!width=\@@DriverImageWidth,\c!height=\@@DriverImageHeight]{\@@DriverImageFile}}% \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 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\pdfimmediateximage{\immediate\pdfximage} \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 {\doifvalidpdfimagefileelse\@@DriverImageFile {\ifvoid\foundexternalfigure \donetrue \else\ifx\PDFfigurereference\empty \donetrue \else % hm, is this still needed \doifinstringelse\filesuffix{\c!png,\c!jpg}\donetrue\donefalse \fi\fi} {\donefalse}% \ifdone \the\everyPDFximage \checkpdfimageattributes \checkpdfimagecolorspecs \checkpdfimagepagenumber \global\setbox\foundexternalfigure\hbox {\ifx\pdfimagepagenumber\empty\@EA\pdfimmediateximage\else\@EA\pdfximage\fi \pdfimageattributes \pdfimagecolorspecs \pdfimagepagenumber \@@DriverImageBox {\@@DriverImageFile}% \xdef\PDFimagereference{\the\pdflastximage}% \xdef\nofinsertpages{\the\pdflastximagepages}% \pdfrefximage\pdflastximage}% \xdef\analyzedfigurewidth {\the\wd\foundexternalfigure}% \xdef\analyzedfigureheight{\the\ht\foundexternalfigure}% \global\let\PDFfigurereference\empty \global\let\PDFimageattributes\empty \else \global\let\analyzedfigurewidth \!!zeropoint \global\let\analyzedfigureheight\!!zeropoint \fi} \else \def\dogetTPDfiguresize {\doifvalidpdfimagefileelse\@@DriverImageFile {\global\setbox\foundexternalfigure\vbox{\pdfimage{\@@DriverImageFile}}% \xdef\analyzedfigurewidth {\the\wd\foundexternalfigure}% \xdef\analyzedfigureheight{\the\ht\foundexternalfigure}} {\global\let\analyzedfigurewidth \!!zeropoint \global\let\analyzedfigureheight\!!zeropoint}} \fi \definefilechecker{tpd}{pdf}{\dogetTPDfiguresize} \definefilechecker{tpd}{png}{\dogetTPDfiguresize} \definefilechecker{tpd}{jpg}{\dogetTPDfiguresize} \definefilechecker{tpd}{jb2}{\dogetTPDfiguresize} \definespecial\dogetfiguresize {\dofilechecker{tpd}{\truegraphictype\@@DriverImageType}} %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% no need for escape in luatex {\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 them 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 % 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\docommand##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]\docommand \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 \finalizeobjectbox\nextbox \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 \appendtoksonce \collectPDFresources \global\let\currentPDFresources\collectedPDFresources \to \everyPDFxform %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 {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#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#1#2#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#1#2#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#1#2#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#1#2#3% {\pdfannot width #1 height #2 depth \zeropoint{#3}} \else \def\doPDFannotation#1#2#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#1#2#3#4#5% {\doPDFannotation{#3}{#4}{#5}% \dosetobjectreference{#1}{#2}{\the\pdflastannot}} \def\doPDFactionobject#1#2#3#4#5% {\doPDFaction{#3}{#4}{#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. \def\doPDFbookmark#1#2#3#4#5% {\doPDFgetpagereference{#4}\PDFobjectreference \pdfoutline user {<>}% \ifcase#2 \else count \ifcase#5-\fi#2 \fi {\ifPDFunicode<#3>\else#3\fi}} %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#1#2#3% {\flushatshipout {\immediate\pdfobj{<< #3 >>}% \dosetobjectreference{#1}{#2}{\the\pdflastobj}}} \def\doPDFarrayobject#1#2#3% {\flushatshipout {\immediate\pdfobj{[ #3 ]}% \dosetobjectreference{#1}{#2}{\the\pdflastobj}}} % tricky .. too many xforms now % % \def\doreservePDFobject#1#2% % {\pdfobj reserveobjnum{}% % \driverreferenced\dosetobjectreference{#1}{#2}{\the\pdflastobj}} % % \def\doPDFreserveddictionaryobject#1#2#3% % {\doPDFgetobjectnumber{#1}{#2}\PDFobjectnumber % \immediate\pdfobj useobjnum \PDFobjectnumber {<< #3 >>}} % % \def\doPDFreservedarrayobject#1#2#3% % {\doPDFgetobjectnumber{#1}{#2}\PDFobjectnumber % \immediate\pdfobj useobjnum \PDFobjectnumber {[ #3 ]}} % \doreservePDFobject{FDF}{docuextgstates} % \doreservePDFobject{FDF}{colorspaces} % \doreservePDFobject{FDF}{docushades} %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\doPDFgetobjectnumber#1#2#3% {\dogetobjectreference{#1}{#2}#3% \edef#3{\ifx#3\empty 0\else#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 \def\initializePDFnegative {\immediate\pdfobj stream attr {/FunctionType 4 /Range [0 1] /Domain [0 1]} {{1 exch sub}}% \immediate\pdfobj{<>}% \appendtoPDFdocumentextgstates{/GSnegative \PDFobjref\pdflastobj}% \immediate\pdfobj{<>}% \appendtoPDFdocumentextgstates{/GSpositive \PDFobjref\pdflastobj}% \global\let\initializePDFnegative\relax} \def\initializePDFoverprint {\immediate\pdfobj{<>}% /op defaults to /OP \appendtoPDFdocumentextgstates{/GSknockout \PDFobjref\pdflastobj}% \immediate\pdfobj{<>}% /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#1#2#3#4% {\immediate\pdfobj stream file{#4}% \edef\PDFlaststreamobject{\the\pdflastobj}% \dosetobjectreference{PDFFS}{#2}{\PDFlaststreamobject}% \doPDFdictionaryobject{#1}{#2}{/Type /Filespec /F (#3) /EF <>}} \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~1: \def\MPprologues{1} %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 {\the\everyPDFxform \finalizeobjectbox{#2}% \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