%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. %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 %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 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=5 % %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 \starttypen %D \usespecials[tpd] %D \stoptypen %D %D we get ourselves full \PDF\ output. %D For some internal testing we need to know the output %D suffix. \def\jobsuffix{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=0 \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 %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 {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=#3pt \PointsToReal{.01\scratchdimen}\xscale \scratchdimen=#4pt \PointsToReal{.01\scratchdimen}\yscale \convertMPtoPDF{#1}\xscale\yscale \global\let\PDFimagereference\empty}} %D The old, \TEX\ base \PDF\ insertion macro: %D %D \starttypen %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{#5sp}{#6sp}{#7sp}{#8sp}} %D \stoptypen %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 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% {\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}{\pdfimageresolution=72}% \doif{\filesuffix}{pdf}{\pdfimageresolution=72}% % 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 \doifvalidpdfimagefileelse{#1} {\checkpdfimagepagenumber{#9}% \immediate\pdfximage \ifcase#7 \else \!!width #7sp\fi \ifcase#8 \else \!!height #8sp\fi \pdfimagepagenumber {#1}% \xdef\PDFimagereference{\the\pdflastximage}% \xdef\nofinsertpages{\the\pdflastximagepages}% \pdfrefximage\pdflastximage} {\framed[\c!breedte=#7sp,\c!hoogte=#8sp]{#1}}% \egroup} \else \def\handlepdfimage#1#2#3#4#5#6#7#8#9% {\bgroup \doifvalidpdfimagefileelse{#1} {\pdfimage \ifcase#7 \else \!!width #7sp\fi \ifcase#8 \else \!!height #8sp\fi {#1}}% {\framed[\c!breedte=#7sp,\c!hoogte=#8sp]{#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. \ifnum\pdftexversion>13 \def\checkpdfimageattributes% {\ifx\PDFfigurereference\empty \global\let\pdfimageattributes\empty \else \immediate\pdfobj% {[ << /Image \PDFfigurereference\space0 R /DefaultForPrinting true >> ]}% \xdef\pdfimageattributes% {attr {/Alternates \the\pdflastobj\space0 R}}% \fi} \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 \checkpdfimagepagenumber{#3}% \checkpdfimageattributes \global\setbox\foundexternalfigure=\vbox {\immediate\pdfximage \pdfimageattributes \pdfimagepagenumber{#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 %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\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} %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% {\ScaledPointsToBigPoints{#2}\width \ScaledPointsToBigPoints{#3}\height \grabMPclippath{#1}{1}{\width}{\height} {0 0 m \width\space 0 l \width \height l 0 \height l}% \pdfliteral {q 0 w \MPclippath\space W n}} \definespecial\dostopclipping% {\pdfliteral{Q}} %D \macros %D {dosetupinteraction, %D dosetupopenaction,dosetupcloseaction} %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}} \definespecial\dosetupopenaction {\doPDFsetupopenaction} \definespecial\dosetupcloseaction{\doPDFsetupcloseaction} %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} %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) \the\pdflastobj\space 0 R}}% \processcommalist[#1]\docommando \immediate\pdfobj{<< /Names [ \compositeJScode ] >>}% \pdfnames{/JavaScript \the\pdflastobj\space 0 R}% \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} %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#1#2#3#4#5% {\bgroup \enablePDFdocencoding \pdfinfo {%Producer (pdfTeX) % already there /Title (#1) /Subject (#2) /Author (#3) /Creator (#4)}% \egroup} %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 #2sp height #3sp 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 \immediate\pdfxform resources {\currentPDFresources}\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\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 \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} %D %D Text annotation, or comments, are provided too: \definespecial\doinsertcomment{\doPDFinsertcomment} %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 \ifnum\pdftexversion>13 \def\doPDFaction width #1 height #2 action #3% {\ifcollectreferenceactions \xdef\lastPDFaction{#3}% \else \xdef\lastPDFaction{<<#3>>}% \ifcase\similarreference\relax\or\ifsharePDFactions \immediate\pdfobj{\lastPDFaction}% \xdef\lastPDFaction{\the\pdflastobj\space0 R}% \fi\fi \pdfannot width #1sp height #2sp depth 0sp {/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 \xdef\lastPDFaction{<<#3>>}% \ifcase\similarreference\relax\or\ifsharePDFactions \immediate\pdfobj{\lastPDFaction}% \xdef\lastPDFaction{\the\pdflastobj\space0 R}% \fi\fi \pdfannotlink % could be \pdfannot if not the - problem was there width #1sp height #2sp depth 0sp 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 0sp {#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 #1sp height #2sp depth 0sp {#3}} \else \def\doPDFannotation width #1 height #2 data #3% {\hbox{\raise#2sp\hbox{\pdfannot width #1sp height #2sp depth 0sp {#3}}}} \fi %D \macros %D {doPDFannotationobject} %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% % {\pdfannot width #3sp height -#4sp depth 0sp {#5}% % \dosetobjectreference{#1}{#2}{\the\pdflastannot}} \def\doPDFannotationobject class #1 name #2 width #3 height #4 data #5% {\doPDFannotation width #3 height #4 data {#5}% \dosetobjectreference{#1}{#2}{\the\pdflastannot}} %D \macros %D {doPDFaddtocatalog,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\doPDFpageattribute#1% {\expanded{\global\pdfpageattr{#1\the\pdfpageattr}}} \def\doPDFpagesattribute#1% {\expanded{\global\pdfpagesattr{#1\the\pdfpagesattr}}} \def\doPDFresetattributes% {\global\pdfpageattr{}} \appendtoksonce \doPDFresetattributes \to \everyaftershipout %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 {<>}% \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#3\space0 R\fi}} %D \macros %D {initializePDFnegative} %D %D Here follow some rather obscure macros. They will only %D come into action when one wants negated output. \let\PDFextgstates\empty \def\initializePDFnegative% {%\bgroup %\pdfcompresslevel=0 \immediate\pdfobj stream attr {/FunctionType 4 /Range [0 1] /Domain [0 1]} {{1 exch sub}}% \immediate\pdfobj{<>}% \xdef\PDFextgstates{\PDFextgstates/GSnegative \the\pdflastobj\space0 R}% \immediate\pdfobj{<>}% \xdef\PDFextgstates{\PDFextgstates/GSpositive \the\pdflastobj\space0 R}% \global\let\initializePDFnegative\relax %\egroup \expanded{\global\pdfpageresources{/ExtGState <<\PDFextgstates>>}}} % %D We can set \METAPOST\ prologues to~2: \def\MPprologues{2} %D Now we can finish this module. \stopspecials \protect \endinput