diff options
Diffstat (limited to 'tex/context/base/back-pdf.mkiv')
-rw-r--r-- | tex/context/base/back-pdf.mkiv | 3226 |
1 files changed, 3226 insertions, 0 deletions
diff --git a/tex/context/base/back-pdf.mkiv b/tex/context/base/back-pdf.mkiv new file mode 100644 index 000000000..b7de1051f --- /dev/null +++ b/tex/context/base/back-pdf.mkiv @@ -0,0 +1,3226 @@ +%D \module +%D [ file=back-pdf, +%D version=2009.04.15, +%D title=\CONTEXT\ Backend Macros, +%D subtitle=\PDF, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright=\PRAGMA] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Backend Macros / PDF} + +\registerctxluafile{back-pdf}{1.001} + +\unprotect + +%D When dealing with resources, we share the resource dictionaries +%D between all xforms. This is inefficent in the sense that when no +%D resources are used, redundant entries take space, but on the other +%D hand we save redundant dictionaries so it's a nice compromise. Maybe +%D that in \LUATEX\ I will reimplement most of the code here anyway. + +%D Initialization of fields is tricky. If a field has no +%D value, it is kind of not there. If ResetForm is used, the +%D default is assigned, but pushbuttons are spoiled. Adding a +%D \type {/MK} dictionary helps, but gives ugly down +%D appearances (displaced with background). What a mess. +%D Also, in order to get at least something, the \type {/AS} +%D key should be provided. + +%D A couple of variables: + +\newtoks \everybackendshipout +\newtoks \everylastbackendshipout + +\let\lastPDFaction\empty + +\ifdefined\everyPDFximage \else \newtoks\everyPDFximage \fi +\ifdefined\everyPDFxform \else \newtoks\everyPDFxform \fi +\ifdefined\everygoto \else \newtoks\everygoto \fi +\ifdefined\everysetfield \else \newtoks\everysetfield \fi + +%D A few helpers: + +\let\PDFcode \pdfliteral +\def\PDFcontentcode{\pdfliteral} +\def\PDFdirectcode {\pdfliteral direct} + +%D \macros +%D {PDFobjref} +%D +%D Just a shortcut. + +% Watch out, \def\PDFobjref#1{\purenumber#1 0 R} also works, but not when +% #1 == \the\whatever + +\def\PDFobjref#1{\purenumber{#1} 0 R} + +%D \macros +%D {PDFswapdir} + +\let\PDFswapdir\empty \def\PDFswapdir{\ifcase\inlinedirection\or\or-\fi} + +% the pdf spec changed cq. viewers started behaving differently / 5+ + +\chardef\overcomePDFpage\plusone % page numbers/ beware: optimizers remove this one +\chardef\overcomePDFpage\plustwo % page:number +\chardef\overcomePDFpage\plusthree % pdftex page ref feature + +%D \macros +%D {setPDFdestination} +%D +%D \PDF\ destinations should obey the specifications laid down +%D in the \PDF\ reference manual. The next macro strips illegal +%D characters from the destination name. + +\def\setPDFdestination #1{\xdef\PDFdestination{\ctxlua{pdf.cleandestination("\luaescapestring{#1}")}}} +\def\hexifiedPDFstring #1{\ctxlua{pdf.hexify("\luaescapestring{#1}")}} +\def\sanitizePDFencoding#1\to#2{\xdef#2{\ctxlua{pdf.hexify("\luaescapestring{#1}")}}} + +%D + +\def\appendtopdfpageresources #1{\normalexpanded{\global\pdfpageresources{#1\the\pdfpageresources}}} +\def\appendtopdfpageattributes #1{\normalexpanded{\global\pdfpageattr {#1\the\pdfpageattr }}} +\def\appendtopdfpagesattributes#1{\normalexpanded{\global\pdfpagesattr {#1\the\pdfpagesattr }}} +\def\appendtopdfcatalog {\pdfcatalog} +\def\appendtopdfinfo {\pdfinfo} + +\def\resetpdfpageattributes{\global\pdfpageattr\emptytoks} +\def\resetpdfpageresources {\global\pdfpageresources\emptytoks} + +%D Due to the fact that \PDFTEX\ has a different concept of +%D page attributes, we need: + +\appendtoksonce + \resetpdfpageattributes + \resetpdfpageresources +\to \everyaftershipout + +%D \macros +%D {insertpdfaction, +%D insertpdfannotation, +%D insertpdfannotationobject, +%D createpdfdictionaryobject, +%D createpdfarrayobject, +%D defaultobjectreference, +%D doPDFgetobjectreference} +%D +%D This module deals with \PDF\ support, including fill||in +%D forms. Before we present the largely unreadable bunch of +%D macros, we introduce the here||not||defined low level +%D interface macros. These must be provided by the special +%D drivers \type{pdf} (\ACROBAT) and \type{tpd} (\PDFTEX). +%D +%D \starttyping +%D \insertpdfaction #1#2#3 width height action +%D \insertpdfannotation #1#2#3 width height data +%D \createpdfannotationobject #1#2#3#4#5 class name width height data +%D \createpdfdictionaryobject #1#2#3 class name data +%D \createpdfarrayobject #1#2#3 class name data +%D +%D \defaultobjectreference #1#2 class name +%D \doPDFgetobjectreference #1#2#3 class name \PDFobjectreference +%D \doPDFgetobjectpagereference #1#2#3 class name \PDFobjectreference +%D \stoptyping +%D +%D The keywords reflect their use. For the moment we stick to +%D keywords, because that way at we get an indication of what +%D we're doing. + +\def\createpdfdictionaryobject#1#2#3% + {\flushatshipout + {\immediate\pdfobj{<< #3 >>}% + \dosetobjectreference{#1}{#2}{\the\pdflastobj}}} + +\def\createpdfarrayobject#1#2#3% + {\flushatshipout + {\immediate\pdfobj{[ #3 ]}% + \dosetobjectreference{#1}{#2}{\the\pdflastobj}}} + +\def\createpdfannotationobject#1#2#3#4#5% + {\insertpdfannotation{#3}{#4}{#5}% + \dosetobjectreference{#1}{#2}{\the\pdflastannot}} + +\def\createpdfactionobject#1#2#3#4#5% + {\insertpdfaction{#3}{#4}{#5}% + \dosetobjectreference{#1}{#2}{\the\pdflastannot}} + +%D \macros +%D {insertpdfaction,insertpdfannotation,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 + +\def\insertpdfaction#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} + +\def\insertpdfannotation#1#2#3% + {\pdfannot width #1 height #2 depth \zeropoint{#3}} + +%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% to be renamed + {\doPDFgetpagereference{#4}\PDFobjectreference + \pdfoutline + user {<</S /GoTo /D [\PDFobjectreference\space\PDFpageviewwrd]>>}% + \ifcase#2 \else count \ifcase#5-\fi#2 \fi + {#3}} + +%D For special (\METAPOST) effects, we need to build +%D resource dictionaries. Here is the framework. + +\let\docuPDFextgstates \empty +\let\docuPDFcolorspaces\empty +\let\docuPDFshades \empty + +\def\checkPDFextgstates + {\ifx\docuPDFextgstates\empty \else + \ifnum\realpageno=\lastpage\relax + \createpdfdictionaryobject{FDF}{docuextgstates}{\docuPDFextgstates}% + \fi + \doPDFgetobjectreference{FDF}{docuextgstates}\PDFobjectreference + \appendtopdfpageresources{/ExtGState \PDFobjectreference}% + \fi} + +\def\checkPDFcolorspaces + {\ifx\docuPDFcolorspaces\empty \else + \ifnum\realpageno=\lastpage\relax + \createpdfdictionaryobject{FDF}{colorspaces}{\docuPDFcolorspaces}% + \fi + \doPDFgetobjectreference{FDF}{colorspaces}\PDFobjectreference + \appendtopdfpageresources{/ColorSpace \PDFobjectreference}% + \fi} + +\def\checkPDFshades + {\ifx\docuPDFshades\empty \else + \ifnum\realpageno=\lastpage\relax + \createpdfdictionaryobject{FDF}{docushades}{\docuPDFshades}% + \fi + \doPDFgetobjectreference{FDF}{docushades}\PDFobjectreference + \appendtopdfpageresources{/Shading \PDFobjectreference}% + \fi} + +\def\appendtoPDFdocumentextgstates #1{\xdef\docuPDFextgstates {\docuPDFextgstates \space#1}} +\def\appendtoPDFdocumentcolorspaces#1{\xdef\docuPDFcolorspaces{\docuPDFcolorspaces\space#1}} +\def\appendtoPDFdocumentshades #1{\xdef\docuPDFshades {\docuPDFshades \space#1}} + +%D Page actions: + +\let\lastpdfopenaction \empty +\let\lastpdfcloseaction\empty + +\def\dosetupopenaction {\appendtopdfcatalog{/OpenAction <<\lastPDFaction>>}} +\def\dosetupcloseaction{\appendtopdfcatalog{/CloseAction <<\lastPDFaction>>}} + +\def\dosetupopenpageaction {\glet\lastpdfopenaction \lastPDFaction} +\def\dosetupclosepageaction{\glet\lastpdfcloseaction\lastPDFaction} + +\def\checkPDFpageactions + {\iflocation % important since direct + \donefalse + \ifx\lastpdfopenaction \empty\!!doneafalse\else\donetrue\!!doneatrue\fi + \ifx\lastpdfcloseaction\empty\!!donebfalse\else\donetrue\!!donebtrue\fi + \ifdone + \appendtopdfpageattributes + {/AA <<\if!!donea/O <<\lastpdfopenaction >> \fi + \if!!doneb/C <<\lastpdfcloseaction>> \fi>>}% + \fi + \glet\lastpdfopenaction \empty + \glet\lastpdfcloseaction\empty + \fi} + +%D \macros +%D {ifPDFstrokecolor} +%D +%D We can reduce the filesize a bit by setting the next switch +%D to false. The amount of reduction depends on the use of +%D color, but don't expect more than a few percent. Zip +%D compression is already rather efficient in itself. + +\newif\ifPDFstrokecolor \PDFstrokecolortrue + +%D When submitting forms, we need to communicate the format. + +\chardef\submitoutputformat=0 % 0=unknown 1=HTML 2=FDF 3=XML + +\def\setsubmitoutputformat#1% + {\doifinsetelse{#1}{FDF,fdf} + {\chardef\submitoutputformat2} + {\doifinsetelse{#1}{XML,xml} + {\chardef\submitoutputformat3} + {\chardef\submitoutputformat1}}% + \relax} + +%D Handy to have this available asap: + +\ifdefined\everyPDFxform \newtoks\everyPDFxform \fi +\ifdefined\everyPDFximage \newtoks\everyPDFximage \fi + +% 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 + +%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. + +\pdfoutput = 1 +\pdfhorigin = 1 true in +\pdfvorigin = 1 true in +\pdfimageresolution = 300 +\pdfpkresolution = 600 +\pdfdecimaldigits = 10 +\pdfinclusionerrorlevel = 0 +\pdfminorversion = 5 +%pdfuniqueresname = 1 + +\def\PDFversion{1.\number\pdfminorversion} + +%D For some internal testing we need to know the output +%D suffix. + +\setjobsuffix{pdf} + +%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: + +\def\dosetuppaper#1#2#3% + {\global\pdfpagewidth #2\relax + \global\pdfpageheight#3\relax} + +%D \macros +%D {doloadmapfile,doloadmapline,doresetmapfilelist} + +\def\doresetmapfilelist + {\global\let\doresetmapfilelist\relax + \pdfmapfile{original-empty.map}} + +\def\doloadmapfile #1#2{\pdfmapfile{#1#2}} +\def\doloadmapline #1#2{\pdfmapline{#1#2}} + +%D nasty but needed + +\appendtoksonce \loadallfontmapfiles \to \everyPDFximage +\appendtoksonce \loadallfontmapfiles \to \everyPDFxform + +%D left overs: + + \let\currentmovie\s!unknown + + \def\doPDFinsertmov + {\bgroup + \xdef\currentmovie{\@@DriverImageLabel}% + \PointsToBigPoints\@@DriverImageWidth \width + \PointsToBigPoints\@@DriverImageHeight\height + \let\pdf@@options\empty + \let\pdf@@actions\empty + \donefalse + \expanded{\processallactionsinset[\@@DriverImageOptions]} + [\v!controls=>\donetrue, + \v!repeat=>\edef\pdf@@actions{\pdf@@actions /Mode /Repeat }, + \v!preview=>\edef\pdf@@options{\pdf@@options /Poster true }]% + \edef\pdf@@actions{\pdf@@actions /ShowControls \ifdone true\else false\fi}% + \insertpdfannotation\@@DriverImageWidth\@@DriverImageHeight + {/Subtype /Movie + /Border [0 0 0] + /T (movie \currentmovie) + /Movie << /F (\@@DriverImageFile) /Aspect [\width\space\height] \pdf@@options >> + /A << \pdf@@actions >>}% + \egroup} + +%D \macros +%D {doinsertsoundtrack} +%D +%D We use numbers instead of labels to keep track of sounds. + +\let\currentsound\s!unknown + +\def\doinsertsoundtrack#1#2#3% + {\bgroup + \xdef\currentsound{#2}% + \let\pdf@@actions\empty + \@EA\processallactionsinset\@EA + [#3] + [\v!repeat=>\edef\pdf@@actions{\pdf@@actions /Mode /Repeat }]% + \collectdriverresource + %\flushatshipout % since it can be buried in a chained box + {\insertpdfannotation{0pt}{0pt} + {/Subtype /Movie + /Border [0 0 0] + /T (sound \currentsound) + /Movie <</F (#1)>>% + \ifx\pdf@@actions\empty\else/A << \pdf@@actions >>\fi}}% + \egroup} + +%D \macros +%D {doPDFattachfile} + +\def\doPDFfilestreamobject#1#2#3#4% + {} + +\def\doPDFfilestreamidentifier#1% + {0} + +\def\doPDFgetfilestreamreference#1#2% + {0 0 R} + +\def\doattachfile#1#2#3#4#5#6#7#8% + {\bgroup % title width height color symbol file + \edefconvertedargument\PDFfile{#8}% + % beware: the symbol may (indirectly) use the file + % reference when typesetting the object number; + \presetPDFsymbolappearance{#5}{#6}{#2}{#3}{#4}% sets width/height + \startPDFsymbolappearance + \doPDFembedfile\PDFfile{#7}{#8}% + \doPDFgetembeddedfilereference\PDFfile\PDFobjectreference + \setFDFlayer\@@DriverAttachmentLayer + \insertpdfannotation{\width}{\totalheight} + {/Subtype /FileAttachment + /FS \PDFobjectreference\space + /Contents (#1) + \PDFsymbol + \FDFlayer + \PDFattributes}% + \stopPDFsymbolappearance + \egroup} + +% semi-public + +\def\doPDFembedfile#1#2#3% symbolic name | filename | user name + {\edefconvertedargument\PDFfile{#1}% + \doifnotflagged{a:\PDFfile}% + {\doPDFfilestreamobject{PDFEF}{\PDFfile}{#2}{#3}% + \doglobal\setflag{a:\PDFfile}}} + +\def\doPDFgetembeddedfilereference#1#2% + {\edefconvertedargument\PDFfile{#1}% + \doPDFgetobjectreference{PDFEF}\PDFfile#2} + +\def\doPDFgetembeddedfilestreamreference#1#2% + {\edefconvertedargument\PDFfile{#1}% + \doPDFgetfilestreamreference\PDFfile#2} % == \doPDFgetobjectreference{PDFFS}\PDFfile#2 + +% requested by Jens-Uwe Morawski: permits usage of pdftosrc +% in viewers that don't support attachments: +% +% \definesymbol +% [ObjectNumber] +% % [object number {\PDFattachmentnumber[xx]}] % named +% [object number \PDFattachmentnumber] % current +% +% \useattachment[test][xx][test.tex] +% \setupattachments[symbol=ObjectNumber] +% \attachment[test] + +\def\PDFattachmentnumber + {\dosingleargument\doPDFattachmentnumber} + +\def\doPDFattachmentnumber[#1]% + {\iffirstargument + \doPDFfilestreamidentifier{#1}% + \else + \doPDFfilestreamidentifier\PDFfile + \fi} + +%D \macros +%D {...} +%D +%D Rather preliminary. We have to wait till the complete specs +%D show up. As usual, we cannot really check it (Acrobat 6.0 +%D has a bug that inhibits us to make a test file). Half a day +%D of testing made clear that trying to control the plugin fails +%D in most cases (we need plugin specs -). We also miss a feature +%D to let acrobat wait with proceeding (action processing) till +%D the media clip is ready. + +% aiff audio/aiff +% au audio/basic +% avi video/avi +% mid audio/midi +% mov video/quicktime +% mp3 audio/x-mp3 (mpeg) +% mp4 audio/mp4 +% mp4 video/mp4 +% mpeg video/mpeg +% smil application/smil +% swf application/x-shockwave-flash + +% beware, this is preliminary code, should be improved + +\def\PDFrenderingspecs#1{\executeifdefined{PDFMR:#1}\empty} + +\def\PDFexecutestartrendering {/Rendition /OP 0 \PDFrenderingspecs\argumentA} +\def\PDFexecutestoprendering {/Rendition /OP 1 \PDFrenderingspecs\argumentA} +\def\PDFexecutepauserendering {/Rendition /OP 2 \PDFrenderingspecs\argumentA} +\def\PDFexecuteresumerendering {/Rendition /OP 3 \PDFrenderingspecs\argumentA} + +% todo : sub files +% +% \doPDFembedfile{pier-39.png}{pier-39.png}{pier-39.png}% +% \doPDFgetembeddedfilestreamreference{pier-39.png}\xPDFobjectreference +% \edef\xxxx{/RF [(pier-39.png) \xPDFobjectreference]}% + +% todo: alternative renderings +% +% object_1 -> <</Type /Rendition /S /MR /C << /Type /MediaClip ... >> >> +% object_2 -> <</Type /Rendition /S /MR /C << /Type /MediaClip ... >> >> +% rendering -> <</Type /Rendition /S /MS [objref_1 objref_2]>> + +\def\doinsertrendering#1#2#3#4% tag mime file options + {\ifundefined{PDFMR:#1}% + \doifinstringelse{://}{#3}\donetrue\donefalse % evt url as keyword + \createpdfdictionaryobject{PDFMF}{#1} + {/Type /Rendition + /S /MR + % does not work: /SP << /Type /MediaScreenParam /BE << /B [1 0 0] /O 0.5 >> >> + /C << /Type /MediaClip + /S /MCD + /N (#1) + /Alt [() (file not found)] % language id + message + /D << /Type /Filespec + /F (#3) + \ifdone/FS /URL\fi >> + /CT (#2) >>}% + % common code + \doifobjectreferencefoundelse{PDFMS}{#1} + {\doPDFgetobjectreference{PDFMS}{#1}\PDFobjectreferenceB} + {\doPDFgetobjectreference{PDFMU}{#1}\PDFobjectreferenceB}% + \doPDFgetobjectreference{PDFMF}{#1}\PDFobjectreferenceA + \setxvalue{PDFMR:#1}% needed /AA actions in /Screen + {/R \PDFobjectreferenceA + /AN \PDFobjectreferenceB}% + \doifobjectreferencefoundelse{PDFMS}{#1}\donothing + {\dodoinsertrenderingwindow{PDFMU}{#1}\zeropoint\zeropoint{#4}}% + \fi} + +\def\doinsertrenderingobject#1#2#3#4% tag class objectname options + {\ifundefined{PDFMR:#1}% + \doPDFgetobjectreference{#2}{#3}\PDFobjectreference + \createpdfdictionaryobject{PDFMF}{#1} + {/Type /Rendition + /S /MR + /C << /Type /MediaClip + /S /MCD + /N (#1) + /D \PDFobjectreference>>}% + % common code + \doifobjectreferencefoundelse{PDFMS}{#1} + {\doPDFgetobjectreference{PDFMS}{#1}\PDFobjectreferenceB} + {\doPDFgetobjectreference{PDFMU}{#1}\PDFobjectreferenceB}% + \doPDFgetobjectreference{PDFMF}{#1}\PDFobjectreferenceA + \setxvalue{PDFMR:#1}% needed /AA actions in /Screen + {/R \PDFobjectreferenceA + /AN \PDFobjectreferenceB}% + \doifobjectreferencefoundelse{PDFMS}{#1}\donothing + {\dodoinsertrenderingwindow{PDFMU}{#1}\zeropoint\zeropoint{#4}}% + \fi} + +\def\doinsertrenderingwindow + {\dodoinsertrenderingwindow{PDFMS}} + +\def\dodoinsertrenderingwindow#1#2#3#4#5% + {\vbox to #4 \bgroup + \checkPDFscreenactions{#2}{#5}% + \doPDFgetobjectpagereference{PDFMF}{#2}\PDFobjectreferenceA + \doPDFgetobjectreference {PDFMF}{#2}\PDFobjectreferenceB + \vss + \hbox to #3 \bgroup + \createpdfannotationobject{#1}{#2}{#3}{#4} + {/Subtype /Screen + /P \PDFobjectreferenceA + /A \PDFobjectreferenceB + \PDFattributes + /Border [0 0 0]}% + \hss + \egroup + \egroup} + +\global\let\PDFrenderingopenpageaction \empty +\global\let\PDFrenderingclosepageaction\empty + +\def\checkPDFscreenactions#1#2% + {\let\PDFattributes\empty + \iflocation % important since direct -) + % the action can either (already) be set by the window handler + % or (normally when no window [i.e a zero dimensions one] is present) by keyword + \doifinset\v!auto{#2} + {% brrr, here instead of in navigation module, must move and become special + % now two sided dependency + \let\checkrendering\gobbleoneargument + \ifx\PDFrenderingopenpageaction \empty + \handlereferenceactions{\v!StartRendering{#1}}\dosetuprenderingopenpageaction + \fi + \ifx\PDFrenderingclosepageaction\empty + \handlereferenceactions{\v!StopRendering {#1}}\dosetuprenderingclosepageaction + \fi + }% + \donefalse + \ifx\PDFrenderingopenpageaction \empty\!!doneafalse\else\donetrue\!!doneatrue\fi + \ifx\PDFrenderingclosepageaction\empty\!!donebfalse\else\donetrue\!!donebtrue\fi + \ifdone + \edef\PDFattributes + {/AA <<\if!!donea/PO <<\PDFrenderingopenpageaction >> \fi + \if!!doneb/PC <<\PDFrenderingclosepageaction>> \fi>>}% + \fi + \global\let\PDFrenderingopenpageaction \empty + \global\let\PDFrenderingclosepageaction\empty + \fi} + +\def\dosetuprenderingopenpageaction {\global\let\PDFrenderingopenpageaction \lastPDFaction} +\def\dosetuprenderingclosepageaction{\global\let\PDFrenderingclosepageaction\lastPDFaction} + +%D For the moment we don't test for alternatives that +%D themselves have alternatives, especially cylcic +%D dependencies. + +% \def\pdfimmediateximage{\immediate\pdfximage} +% +% \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} + +%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). + + \def\doregisterfigure#1#2% + {\doifundefined{IM::#1::#2} + {\setxvalue{IM::#1::#2}{\the\pdflastximage}}% + \xdef\PDFfigurereference{\getvalue{IM::#1::#2}}} + +%D \macros +%D {doovalbox} +%D +%D Drawing frames with round corners is inherited from the +%D main module. +%D +%D For drawing ovals we use quite raw \PDF\ code. The next +%D implementation does not differ that much from the one +%D implemented in the \POSTSCRIPT\ driver. + +\def\doPDFovalcalc#1#2#3% + {\PointsToBigPoints{\dimexpr#1+#2\relax}#3} + +\def\doovalbox#1#2#3#4#5#6#7#8% todo: \scratchdimen/\scatchbox + {\forcecolorhack + \bgroup + \dimen0=#4\divide\dimen0 \plustwo + \doPDFovalcalc{0pt}{+\dimen0}\xmin + \doPDFovalcalc{#1}{-\dimen0}\xmax + \doPDFovalcalc{#2}{-\dimen0}\ymax + \doPDFovalcalc{-#3}{+\dimen0}\ymin + \advance\dimen0 by #5% + \doPDFovalcalc{0pt}{+\dimen0}\xxmin + \doPDFovalcalc{#1}{-\dimen0}\xxmax + \doPDFovalcalc{#2}{-\dimen0}\yymax + \doPDFovalcalc{-#3}{+\dimen0}\yymin + \doPDFovalcalc{#4}{\zeropoint}\stroke + \doPDFovalcalc{#5}{\zeropoint}\radius + \edef\dostroke{#6}% + \edef\dofill{#7}% + \edef\mode{\number#8 \space}% + % no \ifcase, else \relax in pdfcode + \setbox\scratchbox\hbox + {\ifnum\dostroke\dofill>\zerocount + \ifPDFstrokecolor\else\ifnum\dostroke=\plusone + \writestatus\m!colors{pdf stroke color will fail}\wait + \fi\fi + \PDFcode + {q + \stroke\space w + \ifcase\mode + \xxmin\space \ymin \space m + \xxmax\space \ymin \space l + \xmax \space \ymin \space \xmax \space \yymin\space y + \xmax \space \yymax\space l + \xmax \space \ymax \space \xxmax\space \ymax \space y + \xxmin\space \ymax \space l + \xmin \space \ymax \space \xmin \space \yymax\space y + \xmin \space \yymin\space l + \xmin \space \ymin \space \xxmin\space \ymin \space y + h + \or % 1 + \xxmin\space \ymin \space m + \xxmax\space \ymin \space l + \xmax \space \ymin \space \xmax \space \yymin\space y + \xmax \space \ymax \space l + \xmin \space \ymax \space l + \xmin \space \yymin\space l + \xmin \space \ymin \space \xxmin\space \ymin \space y + h + \or % 2 + \xxmin\space \ymin \space m + \xmax \space \ymin \space l + \xmax \space \ymax \space l + \xxmin\space \ymax \space l + \xmin \space \ymax \space \xmin \space \yymax\space y + \xmin \space \yymin\space l + \xmin \space \ymin \space \xxmin\space \ymin \space y + h + \or % 3 + \xmin \space \ymin \space m + \xmax \space \ymin \space l + \xmax \space \yymax\space l + \xmax \space \ymax \space \xxmax\space \ymax \space y + \xxmin\space \ymax \space l + \xmin \space \ymax \space \xmin \space \yymax\space y + \xmin \space \ymin \space l + h + \or % 4 + \xmin \space \ymin \space m + \xxmax\space \ymin \space l + \xmax \space \ymin \space \xmax \space \yymin\space y + \xmax \space \yymax\space l + \xmax \space \ymax \space \xxmax\space \ymax \space y + \xmin \space \ymax \space l + \xmin \space \ymin\space l + h + \or % 5 + \xmin \space \ymin \space m + \xmax \space \ymin \space l + \xmax \space \yymax\space l + \xmax \space \ymax \space \xxmax\space \ymax \space y + \xmin \space \ymax \space l + \xmin \space \ymin \space l + h + \or % 6 + \xmin \space \ymin \space m + \xxmax\space \ymin \space l + \xmax \space \ymin \space \xmax \space \yymin\space y + \xmax \space \ymax \space l + \xmin \space \ymax \space l + \xmin \space \ymin \space l + h + \or + \xxmin\space \ymin \space m + \xmax \space \ymin \space l + \xmax \space \ymax \space l + \xmin \space \ymax \space l + \xmin \space \yymin\space l + \xmin \space \ymin \space \xxmin\space \ymin \space y + h + \or + \xmin \space \ymin \space m + \xmax \space \ymin \space l + \xmax \space \ymax \space l + \xxmin\space \ymax \space l + \xmin \space \ymax \space \xmin \space \yymax\space y + \xmin \space \ymin \space l + h + \or % 9 top open + \xmin \space \ymax \space m + \xmin \space \yymin\space l + \xmin \space \ymin \space \xxmin\space \ymin \space y + \xxmax\space \ymin \space l + \xmax \space \ymin \space \xmax \space \yymin\space y + \xmax \space \ymax \space l + \or % 10 right open + \xmax \space \ymax \space m + \xxmin\space \ymax \space l + \xmin \space \ymax \space \xmin \space \yymax\space y + \xmin \space \yymin\space l + \xmin \space \ymin \space \xxmin\space \ymin \space y + \xmax\space \ymin \space l + \or % 11 bottom open + \xmax \space \ymin \space m + \xmax \space \yymax\space l + \xmax \space \ymax \space \xxmax \space \ymax\space y + \xxmin\space \ymax \space l + \xmin \space \ymax \space \xmin \space \yymax\space y + \xmin \space \ymin \space l + \or % 12 left open + \xmin \space \ymax \space m + \xxmax\space \ymax \space l + \xmax \space \ymax \space \xmax \space \yymax\space y + \xmax \space \yymin\space l + \xmax \space \ymin \space \xxmax\space \ymin \space y + \xmin \space \ymin \space l + \or % 13 + \xmin \space \ymax \space m + \xxmax\space \ymax \space l + \xmax \space \ymax \space \xmax \space \yymax\space y + \xmax\space \ymin \space l + \or % 14 + \xmax \space \ymax \space m + \xmax \space \yymin\space l + \xmax \space \ymin \space \xxmax\space \ymin \space y + \xmin \space \ymin \space l + \or % 15 + \xmax \space \ymin \space m + \xxmin\space \ymin \space l + \xmin \space \ymin \space \xmin \space \yymin\space y + \xmin \space \ymax \space l + \or % 16 + \xmin \space \ymin \space m + \xmin \space \yymax\space l + \xmin \space \ymax \space \xxmin\space \ymax \space y + \xmax \space \ymax \space l + \or % 17 + \xxmax\space \ymax \space m + \xmax \space \ymax \space \xmax \space \yymax\space y + \or % 18 + \xmax \space \yymin\space m + \xmax \space \ymin \space \xxmax\space \ymin \space y + \or % 19 + \xxmin\space \ymin \space m + \xmin \space \ymin \space \xmin \space \yymin\space y + \or % 20 + \xmin \space \yymax\space m + \xmin \space \ymax \space \xxmin\space \ymax \space y + \or % 21 + \xxmax\space \ymax \space m + \xmax \space \ymax \space \xmax \space \yymax\space y + \xmin \space \yymax\space m + \xmin \space \ymax \space \xxmin\space \ymax \space y + \or % 22 + \xxmax\space \ymax \space m + \xmax \space \ymax \space \xmax \space \yymax\space y + \xmax \space \yymin\space m + \xmax \space \ymin \space \xxmax\space \ymin \space y + \or % 23 + \xmax \space \yymin\space m + \xmax \space \ymin \space \xxmax\space \ymin \space y + \xxmin\space \ymin \space m + \xmin \space \ymin \space \xmin \space \yymin\space y + \or % 24 + \xxmin\space \ymin \space m + \xmin \space \ymin \space \xmin \space \yymin\space y + \xmin \space \yymax\space m + \xmin \space \ymax \space \xxmin\space \ymax \space y + \or % 25 + \xxmax\space \ymax \space m + \xmax \space \ymax \space \xmax \space \yymax\space y + \xmax \space \yymin\space m + \xmax \space \ymin \space \xxmax\space \ymin \space y + \xxmin\space \ymin \space m + \xmin \space \ymin \space \xmin \space \yymin\space y + \xmin \space \yymax\space m + \xmin \space \ymax \space \xxmin\space \ymax \space y + \or % 26 + \xmax \space \yymin\space m + \xmax \space \ymin \space \xxmax\space \ymin \space y + \xmin \space \yymax\space m + \xmin \space \ymax \space \xxmin\space \ymax \space y + \or % 27 + \xxmax\space \ymax \space m + \xmax \space \ymax \space \xmax \space \yymax\space y + \xxmin\space \ymin \space m + \xmin \space \ymin \space \xmin \space \yymin\space y + \or % 28 + \fi + \ifnum\mode>8 + S + \else + \ifnum\dostroke=\plusone S \fi + \ifnum\dofill =\plusone f \fi + \fi + Q}% + \fi}% + \wd\scratchbox#1\ht\scratchbox#2\dp\scratchbox#3\box\scratchbox + \egroup} + +%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} + +\def\dostartrotation#1% grouped + {\setcalculatedcos\cos{#1}% + \setcalculatedsin\sin{#1}% + \forcecolorhack + \PDFcode{q \cos\space\sin\space\negated\sin\space\cos\space0 0 cm}} + +\def\dostoprotation + {\PDFcode{Q}} + +\def\@@PDFzeroscale{.0001} + +\def\dostartscaling#1#2% the test is needed because acrobat is bugged! + {\forcecolorhack + \PDFcode{q \ifdim#1\points=\zeropoint\@@PDFzeroscale\else#1\fi\space 0 0 + \ifdim#2\points=\zeropoint\@@PDFzeroscale\else#2\fi\space 0 0 cm}} + +\def\dostopscaling + {\PDFcode{Q}} + +\def\dostartmirroring{\PDFcode{-1 0 0 1 0 0 cm}} +\def\dostopmirroring {\PDFcode{-1 0 0 1 0 0 cm}} + +\def\dostartnegative {\ifdefined\initializePDFnegative \initializePDFnegative \PDFcode{/GSnegative gs}\fi} +\def\dostopnegative {\ifdefined\initializePDFnegative \initializePDFnegative \PDFcode{/GSpositive gs}\fi} +\def\dostartoverprint{\ifdefined\initializePDFoverprint\initializePDFoverprint\PDFcode{/GSoverprint gs}\fi} +\def\dostopoverprint {\ifdefined\initializePDFoverprint\initializePDFoverprint\PDFcode{/GSknockout gs}\fi} % wrong + +%D \macros +%D {doPDFstartgraymode,doPDFstopgraymode, +%D doPDFstartrgbcolormode,doPDFstartcmykcolormode,doPDFstartgraycolormode, +%D doPDFstopcolormode} +%D +%D In \PDF\ there are two color states, one for strokes and one +%D for fills. This means that we have to set the color in a +%D rather redundant looking way. Unfortunately this makes the +%D \PDF\ file much larger than needed. We can save few bytes +%D by not setting the stroke color. Due to zip compression we +%D only save a few percent. + +\def\dostartgraymode #1{\PDFcode{#1 g\ifPDFstrokecolor\space#1 G\fi}} +\def\dostopgraymode {\PDFcode{0 g\ifPDFstrokecolor\space 0 G\fi}} +\def\dostartrgbcolormode #1#2#3{\PDFcode{#1 #2 #3 rg\ifPDFstrokecolor\space#1 #2 #3 RG\fi}} +\def\dostartcmykcolormode#1#2#3#4{\PDFcode{#1 #2 #3 #4 k\ifPDFstrokecolor\space#1 #2 #3 #4 K\fi}} +\def\dostartgraycolormode #1{\PDFcode{#1 g\ifPDFstrokecolor\space#1 G\fi}} +\def\dostopcolormode {\PDFcode{0 g\ifPDFstrokecolor\space0 G\fi}} + +\def\dostartspotcolormode#1#2% redefining spotcolors is not possible anyway + {\ifundefined{pdf:scs:#2}% + \bgroup + \getcommacommandsize[#2]% + \ifcase\commalistsize\or + \setxvalue{pdf:scs:#2}{#2 SCN #2 scn}% \setxvalue{pdf:scs:#2}{#2 SC #2 sc}% + \else + \let\PDFspotcolorspecs\empty + \def\dospotcolorcommand##1{\edef\PDFspotcolorspecs{\PDFspotcolorspecs##1\space}}% + \processcommacommand[#2]\dospotcolorcommand + \setxvalue{pdf:scs:#2}{\PDFspotcolorspecs SCN \PDFspotcolorspecs scn}% + \fi + \egroup + \fi + \PDFcode{/#1 cs /#1 CS \PDFgetspotcolorspec{#2}}} + +\def\PDFgetspotcolorspec#1% + {\executeifdefined{pdf:scs:#1}\empty} % better no default than one with too less args + +\def\dostartnonecolormode + {\PDFcode{/None CS 1 SC /None cs 1 sc}} + +%D We need to register the spot colors and their fallbacks. + +% we cannot use /DeviceN since GS <=7.21 breaks on it +% and Jaws does not handle it at all {[/DeviceN [/All|/None] +% /Device#2 \PDFobjref\pdflastobj]} so we use separation +% colors that work and print ok + +\def\doPDFregistersomespotcolor#1#2#3#4% implemented in the driver + {\writestatus\m!systems{missing spot color definition}\wait} + +\def\doregisternonecolor % internal command + {\doregistergrayspotcolor{None}{1}% + \globallet\doregisternonecolor\relax} + +\def\dodoPDFregisterrgbspotcolor#1#2#3#4#5#6#7% name noffractions names p's r g b + {\doPDFregistersomespotcolor{#1}{#2}{#3}{#4}{RGB}{0.0 1.0 0.0 1.0 0.0 1.0}% + {\ifcase#2\or dup #5 mul exch dup #6 mul exch #7 mul\else#5 #6 #7\fi}} + +\def\dodoPDFregistercmykspotcolor#1#2#3#4#5#6#7#8% name noffractions names p's c m y k + {\doPDFregistersomespotcolor{#1}{#2}{#3}{#4}{CMYK}{0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0}% + {\ifcase#2\or dup #5 mul exch dup #6 mul exch dup #7 mul exch #8 mul\else #5 #6 #7 #8\fi}} + +\def\dodoPDFregistergrayspotcolor#1#2#3#4#5% name noffractions names p's s + {\doPDFregistersomespotcolor{#1}{#2}{#3}{#4}{Gray}{0.0 1.0}% + {\ifcase#2\or #5 mul\else #5\fi}} + +\def\doregisterrgbspotcolor#1#2#3#4#5#6#7% name noffractions names p's r g b + {\ifRGBsupported + \dodoPDFregisterrgbspotcolor{#1}{#2}{#3}{#4}{#5}{#6}{#7}% + \else + \edef\@@cl@@r{#5}\edef\@@cl@@g{#6}\edef\@@cl@@b{#7}% + \ifCMYKsupported + \convertRGBtoCMYK\@@cl@@r\@@cl@@g\@@cl@@b + \dodoPDFregistercmykspotcolor{#1}{#2}{#3}{#4}\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k + \else + \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b + \dodoPDFregistergrayspotcolor{#1}{#2}{#3}{#4}\@@cl@@s + \fi + \fi} + +\def\doregistercmykspotcolor#1#2#3#4#5#6#7#8% name noffractions names p's c m y k + {\ifCMYKsupported + \dodoPDFregistercmykspotcolor{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}% + \else + \edef\@@cl@@c{#5}\edef\@@cl@@m{#6}\edef\@@cl@@y{#7}\edef\@@cl@@k{#8}% + \ifRGBsupported + \convertCMYKtoRGB\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k + \dodoPDFregisterrgbspotcolor{#1}{#2}{#3}{#4}\@@cl@@r\@@cl@@g\@@cl@@b + \else + \convertCMYKtoGRAY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k + \dodoPDFregistergrayspotcolor{#1}{#2}{#3}{#4}\@@cl@@s + \fi + \fi} + +\def\doregistergrayspotcolor{\dodoPDFregistergrayspotcolor} + +%D New and very experimental. + +\def\doregistercmykindexcolor#1#2#3#4#5#6#7#8% name noffractions names p's c m y k + {\doPDFregistersomeindexcolor{#1}{#2}{#3}{#4}{CMYK}{0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0}% + {dup #5 mul exch dup #6 mul exch dup #7 mul exch #8 mul}} + +\def\doregisterrgbindexcolor#1#2#3#4#5#6#7% name noffractions names p's r g b + {\doPDFregistersomeindexcolor{#1}{#2}{#3}{#4}{RGB}{0.0 1.0 0.0 1.0 0.0 1.0}% + {dup #5 mul exch dup #6 mul exch #7 mul}} + +\def\doregistergrayindexcolor#1#2#3#4#5% name noffractions names p's s + {\doPDFregistersomeindexcolor{#1}{#2}{#3}{#4}{Gray}{0.0 1.0}% + {pop}} + +\let\checkpredefinedcolor\predefineindexcolor % we need an index in order to negate bitmaps + +\def\doregisterfigurecolor#1% always an index color + {\dogetobjectreference{PDFIX}{\internalspotcolorname{#1}}\PDFimagecolorreference} + +\def\doregisterspotcolorname#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/##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. + +\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 Transparency support: + +\def\PDFtransparancydictionary#1#2#3% type fraction extras + {<</Type /ExtGState + /ca #2 /CA #2 + /BM /\ifcase#1 Normal\or Normal\or Multiply\or Screen\or + Overlay\or SoftLight\or HardLight\or ColorDodge\or + ColorBurn\or Darken\or Lighten\or Difference\or + Exclusion\else Compatible\fi + #3>>} + +\def\dodoPDFstarttransparency#1#2% + {\presetPDFtransparency{#1}{#2}% + \PDFcode{\PDFtransparencyidentifier\space gs }} + +\def\dodoPDFstoptransparency + {\PDFcode{/Tr0 gs }} + +\def\dostarttransparency + {\global\let\dostarttransparency\dodoPDFstarttransparency + \global\let\dostoptransparency \dodoPDFstoptransparency + \initializetransparency + \dostarttransparency} + +% This is tricky: because a text stream is handled before +% the page body is built, we can run into stops that will +% match an outer start; however, the stop is needed in case +% of a text color: [text color text] [other color text] on a +% first page combined with color splitting will go wrong if +% we stick to the relaxing method. + +% \def\dostoptransparency +% {\initializetransparency +% \dodoPDFstoptransparency} + +%D These use: + +\let\initializetransparency\relax + +\let\PDFtransparencyresetreference \empty +\let\PDFtransparencyresetidentifier\empty + +\let\PDFtransparencyreference \empty +\let\PDFtransparencyidentifier\empty + +%D New trickery: + +\def\dostartgraphicgroup{\PDFcode{q}} +\def\dostopgraphicgroup {\PDFcode{Q}} + +%D \macros +%D {dostartclipping,dostopclipping} +%D +%D Clipping in \PDFTEX\ is rather trivial. We can even hook +%D in \METAPOST\ without problems. + +\def\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}} + +\def\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. + +\def\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. + +%D In the goto specials we took care of secondary references. +%D Here we define the macros used. + +\def\doresetgotowhereever + {\global\let\secondaryPDFreferences\empty} + +\doresetgotowhereever % just to be sure + +% we can (in etex) share more by testing on this + +\def\savesecondaryPDFreference#1% + {\@EA\xdef\csname PDF-SR:\the\nofsecondaryreferences\endcsname{#1}} + +\def\savesecondaryPDFreference % #1 == \action + {\global\@EA\let\csname PDF-SR:\the\nofsecondaryreferences\endcsname} + +% test should happen in core-ref + +\def\getsecondaryPDFreferences + {\ifcase\nofsecondaryreferences\else + \ifcsname PDF-SR:\the\nofsecondaryreferences\endcsname + \xdef\secondaryPDFreferences{/Next <<\csname PDF-SR:\the\nofsecondaryreferences\endcsname\space\secondaryPDFreferences>>}% + \fi + \global\advance\nofsecondaryreferences \minusone + \expandafter\getsecondaryPDFreferences + \fi} + +%D \macros +%D {dostartthisislocation} +%D +%D Next we define the macros that deal with hyperreferencing, +%D graphic inclusion and general document features. These are +%D the olderst ones. I won't comment much because one needs +%D knowledge of \PDF\ itself, and explaning \PDF\ is beyond +%D this documentation. + +\def\dostartthisislocation#1% + {\bgroup + \setPDFdestination{#1}% + \ifx\PDFdestination\empty \else + \pdfdest name {\PDFdestination}\PDFpageviewkey + \fi + \egroup} + +\def\locationfilesuffix{pdf} + +\def\dostartgotolocation#1#2#3#4#5#6% + {\bgroup + \doifelsenothing{#3} + {\setPDFdestination{#5}% + \doifelsenothing\PDFdestination + {\let\action\empty} + {\doifelsenothing{#4} + {\let\PDFfile\empty} + {\expanded{\beforesplitstring#4}\at.\to\PDFfile + \doifparentfileelse\PDFfile % {#4} + {\let\PDFfile\empty} + %{\setreferencefilename#4.\locationfilesuffix\to\PDFfile + {\@EA\setreferencefilename\PDFfile.\locationfilesuffix\to\PDFfile + \edef\PDFfile + {R /F (\PDFfile)\ifgotonewwindow\space/NewWindow true \fi}}}% + \edef\action% + {/S /GoTo\PDFfile\space /D (\PDFdestination)}}} + {\doifelsenothing{#4} + {\let\PDFfile\empty + \let\PDFdestination\empty} + {\setreferencefilename/#4\to\PDFfile + \setPDFdestination{#5}% + \doifsomething\PDFdestination + {\edef\PDFdestination{\letterhash\PDFdestination}}}% + \edef\action{/S /URI /URI (#3\PDFfile\PDFdestination)}}% + \ifx\action\empty\else + \ifsecondaryreference + \savesecondaryPDFreference\action + \else + \getsecondaryPDFreferences + \insertpdfaction{\PDFswapdir#1}{#2}{\action \secondaryPDFreferences}% + \fi + \fi + \egroup} + +\def\PDFgotonewwindow{\ifgotonewwindow\space/NewWindow true \fi} + +% optimization in tpd driver +% +% \edef\PDFdestination{(page:\the\scratchcounter)}% +% +% ==> +% +% \advance\scratchcounter 1 +% \edef\PDFdestination{[\pdfpageref \PDFobjref\scratchcounter\PDFpageviewwrd]}% +% +% \doPDFgetpagedestination#1#2% pagenumber macro % % fuzzy hack + +\def\dostartgotorealpage#1#2#3#4#5% watch the R append trick + {\bgroup + \doifelsenothing{#3}% #1 = url + {\scratchcounter0#5\relax + \ifnum\scratchcounter>0 + \doifelsenothing{#4} + {\let\PDFfile\empty} + {\expanded{\beforesplitstring#4}\at.\to\PDFfile + \doifparentfileelse\PDFfile % {#4} + {\let\PDFfile\empty} + %{\setreferencefilename#4.\locationfilesuffix\to\PDFfile + {\@EA\setreferencefilename\PDFfile.\locationfilesuffix\to\PDFfile + \edef\PDFfile{R /F (\PDFfile)\PDFgotonewwindow}}}% + \ifx\PDFfile\empty + \ifcase\overcomePDFpage + \or % pdf starts numbering at zero + \advance\scratchcounter \minusone + \edef\PDFdestination{[\the\scratchcounter\space\PDFpageviewwrd]}% + \or % pdf starts numbering at zero + \advance\scratchcounter \minusone + \edef\PDFdestination{(page:\the\scratchcounter)}% + \or % pdftex starts numbering at one + \edef\PDFdestination{[\pdfpageref\scratchcounter\space0 R \PDFpageviewwrd]}% + \fi + \else % across files it's a page number / pdf starts numbering at zero + \advance\scratchcounter \minusone + \edef\PDFdestination{[\the\scratchcounter\space\PDFpageviewwrd]}% + \fi + \edef\action{/S /GoTo\PDFfile\space /D \PDFdestination}% + \else + \let\action\empty + \fi} + {\doifelsenothing{#4} + {\let\PDFfile\empty} + {\setreferencefilename/#4\to\PDFfile}% + \edef\action{/S /URI /URI (#3\PDFfile)}}% + \ifx\action\empty\else + \ifsecondaryreference + \savesecondaryPDFreference\action + \else + \getsecondaryPDFreferences + \insertpdfaction{\PDFswapdir#1}{#2}{\action \secondaryPDFreferences}% + \fi + \fi + \egroup} + +\let\lastfakedPDFpage\!!zerocount + +\def\fakePDFpagedestination % as in pdf, we start numbering at zero + {\iflocation \ifarrangingpages \ifnum\overcomePDFpage=\plustwo \else + \ifnum\lastfakedPDFpage<\realpageno + \bgroup + \xdef\lastfakedPDFpage{\realfolio}% + \advance\realpageno \minusone % is \expanded needed ? + \normalexpanded{\noexpand\pdfdest name {page:\realfolio}\PDFpageviewkey}% + \egroup + \fi + \fi \fi \fi} + +\def\dostartgotoJS#1#2#3% + {\bgroup + \doPSsanitizeJScode#3\to\sanitizedJScode + \edef\action{/S /JavaScript /JS (\sanitizedJScode)}% + \ifsecondaryreference + \savesecondaryPDFreference\action + \else + \getsecondaryPDFreferences + \insertpdfaction{\PDFswapdir#1}{#2}{\action \secondaryPDFreferences}% + \fi + \egroup} + +%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. + +%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 + +\def\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. + +\let\dostarthide\donothing +\let\dostophide \donothing + +%D \macros +%D {doPDFsetupscreen,doPDFsetupidentity} +%D +%D Opposite to \DVI\ drivers, \PDF\ ones must know which what +%D page dimensions they are dealing. We also use the +%D opportunity to launch full screen (1) or show bookmarks (2). +%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. + +\def\dosetupscreen{\doPDFsetupscreen\pdfpageheight} + +\let\currentPDFpagemode \empty % document catalog +\let\currentPDFviewerprefs\empty % document catalog + +\let\currentPDFcropbox \empty % page attributes +\let\currentPDFbleedbox \empty % page attributes +\let\currentPDFartbox \empty % page attributes +\let\currentPDFtrimbox \empty % page attributes + +\def\doPDFsetupscreen#1#2#3#4#5#6% watch the extra argument + {\bgroup + \xdef\currentPDFpagemode + {\ifnum#6=4 + /PageLayout /TwoColumnRight + \else + /PageMode \ifcase#6 + /UseNone\or/FullScreen\or/UseOutlines\else/UseNone\fi + \fi}% + \xdef\currentPDFviewerprefs % space after #6 needed, else \relax + {\ifcase#6 \or\or\else /ViewerPreferences << /FitWindow true >>\fi}% + \egroup} + +\def\addPDFdocumentinfo + {\appendtopdfcatalog{\currentPDFpagemode\currentPDFviewerprefs}% + \appendtopdfcatalog{/Version \ifdim\PDFversion00\points>100\points 1.\fi\PDFversion}% + \appendtopdfinfo{/Trapped /False}% + \appendtopdfinfo{/ConTeXt.Version (\contextversion)}% + \appendtopdfinfo{/ConTeXt.Time (\number\normalyear.\twodigits\normalmonth.\twodigits\normalday\space \twodigits\currenthour:\twodigits\currentminute)}% + \appendtopdfinfo{/ConTeXt.Jobname (\jobname)}% + \appendtopdfinfo{/ConTeXt.Url (www.pragma-ade.com)}% + \glet\addPDFdocumentinfo\relax} + +\def\PDFversion{1.5} + +\appendtoksonce + \def\PDFversion{1.5}% +\to \everyresetspecials + +\def\doPDFsetupwhateverbox#1#2#3#4#5#6% watch the extra arguments + {\bgroup + \!!widtha \dimexpr#5+#3\relax + \!!heightb\dimexpr#2-#4\relax + \!!heighta\dimexpr\!!heightb-#6\relax + % sometimes whole values give better results + % \PointsToWholeBigPoints{#3}\left + % \PointsToWholeBigPoints\!!heighta\bottom + % \PointsToWholeBigPoints\!!widtha \width + % \PointsToWholeBigPoints\!!heightb\height + % but since pdf/x does not round when checking if + % the boxes fit inside the media box ... + \PointsToBigPoints{#3}\left + \PointsToBigPoints\!!heighta\bottom + \PointsToBigPoints\!!widtha \width + \PointsToBigPoints\!!heightb\height + \xdef#1{[\left\space\bottom\space\width\space\height]}% + \egroup} + +\gdef\currentPDFtrimbox{\currentPDFcropbox} % default, needed for pdf/x + +\def\dosetupartbox {\doPDFsetupwhateverbox\currentPDFartbox \pdfpageheight} +\def\dosetupcropbox {\doPDFsetupwhateverbox\currentPDFcropbox \pdfpageheight} +\def\dosetupbleedbox{\doPDFsetupwhateverbox\currentPDFbleedbox\pdfpageheight} +\def\dosetuptrimbox {\doPDFsetupwhateverbox\currentPDFtrimbox \pdfpageheight} + +\def\flushPDFpageboxes + {\edef\currentPDFtrimbox{\currentPDFtrimbox}% + \ifx\currentPDFartbox \empty\else\appendtopdfpageattributes{/ArtBox \currentPDFartbox }\fi + \ifx\currentPDFcropbox \empty\else\appendtopdfpageattributes{/CropBox \currentPDFcropbox }\fi + \ifx\currentPDFbleedbox\empty\else\appendtopdfpageattributes{/BleedBox \currentPDFbleedbox}\fi + \ifx\currentPDFtrimbox \empty\else\appendtopdfpageattributes{/TrimBox \currentPDFtrimbox }\fi} + +%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. +%D +%D At the cost of much auxiliary placeholders, we can pretty +%D fast convert the command asked for. This is how the \PDF\ +%D code looks like. + +\def\PDFmoviecode#1#2#3% + {/Movie + /T (\ifcase#1movie \else sound \fi\ifx\argumentA\empty#2\else\argumentA\fi) + /Operation /\ifcase#3Play\or Stop\or Pause\or Resume\fi\space} + +\def\PDFexecutestartmovie {\PDFmoviecode0\currentmovie0} +\def\PDFexecutestopmovie {\PDFmoviecode0\currentmovie1} +\def\PDFexecutepausemovie {\PDFmoviecode0\currentmovie2} +\def\PDFexecuteresumemovie {\PDFmoviecode0\currentmovie3} + +\def\PDFexecutestartsound {\PDFmoviecode1\currentsound0} +\def\PDFexecutestopsound {\PDFmoviecode1\currentsound1} +\def\PDFexecutepausesound {\PDFmoviecode1\currentsound2} +\def\PDFexecuteresumesound {\PDFmoviecode1\currentsound3} + +\def\PDFformcode#1% + {\doiffieldset{#1}{/Field [\dogetfieldset{#1}]}} + +% bit 3 = html +% bit 6 = xml +% bit 4 = get + +\ifx\PDFsubmitfiller\undefined \let\PDFsubmitfiller\empty \fi + +\chardef\PDFformmethod=1 % 0=GET 1=POST + +\def\PDFformflag#1#2{\ifcase\PDFformmethod#1\else#2\fi} + +\def\PDFexecuteimportform {/Named /N /AcroForm:ImportFDF} +\def\PDFexecuteexportform {/Named /N /AcroForm:ExportFDF} +\def\PDFexecuteresetform {/ResetForm \PDFformcode\argumentA} +\def\PDFexecutesubmitform {/SubmitForm \PDFformcode\argumentB + /Flags \ifcase\submitoutputformat\space + \PDFformflag{12} {4} % 0=unknown + \or \PDFformflag{12} {4} % 1=HTML + \or \PDFformflag {8} {0} % 2=FDF + \or \PDFformflag{40}{32} % 3=XML + \else \PDFformflag{12} {4} % ?=unknown + \fi + /F (\argumentA)\PDFsubmitfiller} + +% urifill permits url substitution + +\def\PDFexecutehide {/Hide /T (\argumentA) /H true} +\def\PDFexecuteshow {/Hide /T (\argumentA) /H false} + +\def\PDFexecutefirst {/Named /N /FirstPage} +\def\PDFexecuteprevious {/Named /N /PrevPage} +\def\PDFexecutenext {/Named /N /NextPage} +\def\PDFexecutelast {/Named /N /LastPage} +\def\PDFexecutebackward {/Named /N /GoBack} +\def\PDFexecuteforward {/Named /N /GoForward} +\def\PDFexecuteprint {/Named /N /Print} +\def\PDFexecuteexit {/Named /N /Quit} +\def\PDFexecuteclose {/Named /N /Close} +\def\PDFexecutesave {/Named /N /Save} +\def\PDFexecutesavenamed {/Named /N /SaveAs} +\def\PDFexecuteopennamed {/Named /N /Open} +\def\PDFexecutehelp {/Named /N /HelpUserGuide} +\def\PDFexecutetoggle {/Named /N /FullScreen} +\def\PDFexecutesearch {/Named /N /Find} +\def\PDFexecutesearchagain {/Named /N /FindAgain} +\def\PDFexecutegotopage {/Named /N /GoToPage} +\def\PDFexecutequery {/Named /N /AcroSrch:Query} +\def\PDFexecutequeryagain {/Named /N /AcroSrch:NextHit} +\def\PDFexecutefitwidth {/Named /N /FitWidth} +\def\PDFexecutefitheight {/Named /N /FitHeight} + +\let\PDFobjectclass\empty +\let\PDFobjectname \empty + +\def\dostartexecutecommand#1#2#3#4% + {\doifdefined{PDFexecute#3} + {\bgroup + \edef\argument{#4}% + \ifx\argument\empty + \let\argumentA\empty + \let\argumentB\empty + \else + \@EA\dogetcommalistelement\@EA1\@EA\from#4\to\argumentA + \@EA\dogetcommalistelement\@EA2\@EA\from#4\to\argumentB + \fi + \edef\action% + {/S \getvalue{PDFexecute#3}}% + \ifsecondaryreference + \savesecondaryPDFreference\action + \else + \getsecondaryPDFreferences +% \ifx\PDFobjectclass\empty +% \let\next\insertpdfaction +% \else +% \edef\next{\createpdfactionobject{\PDFobjectclass}{\PDFobjectname}}% +% \globalletempty\PDFobjectclass +% \globalletempty\PDFobjectname +% \fi +% \next + \insertpdfaction{\PDFswapdir#1}{#2}{\action \secondaryPDFreferences}% + \fi + \egroup}} + +%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. + +\def\dosetupidentity#1#2#3#4#5#6% + {\normalexpanded{\noexpand\appendtopdfinfo + {/Title <\hexifiedPDFstring{#1}> + /Subject <\hexifiedPDFstring{#2}> + /Author <\hexifiedPDFstring{#3}> + /Creator <\hexifiedPDFstring{#4}> + /ModDate (#4) + /ID (\jobname.#5) % needed for pdf/x + /Keywords <\hexifiedPDFstring{#6}>}}} + +%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. + +\def\dostartrunprogram#1#2#3#4% new: #3 => #3#4 + {\bgroup + %\edef\string{#3}% + %\@EA\beforesplitstring\string\at{ }\to\program + %\@EA\aftersplitstring \string\at{ }\to\parameters + %\edef\action% + % {/S /Launch /F (\program) /P (\parameters) /D (.)}% + \edef\action + {/S /Launch /F (#3) /P (#4) /D (.)}% + \ifsecondaryreference + \savesecondaryPDFreference\action + \else + \getsecondaryPDFreferences + \insertpdfaction{\PDFswapdir#1}{#2}{\action \secondaryPDFreferences}% + \fi + \egroup} + +%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. + +\def\dostartgotoprofile#1#2#3% to be done: file + {\bgroup + \setPDFdestination{#3}% + \doifsomething\PDFdestination + {\edef\action + {/S /Thread /D (\PDFdestination)}% + \ifsecondaryreference + \savesecondaryPDFreference\action + \else + \getsecondaryPDFreferences + \insertpdfaction{\PDFswapdir#1}{#2}{\action \secondaryPDFreferences}% + \fi}% + \egroup} + +%D Some day, I'll reimplement threading in a useful way. +%D Currently the viewers handle threads rather diffuse. + +\def\dobeginofprofile#1#2#3#4% + {\setPDFdestination{#1}% + \doifsomething\PDFdestination + {\pdfthread + width #2 height #3 + attr {/Title (\PDFdestination)} % can be omitted + name {\PDFdestination}}} + +\def\doendofprofile + {} + +%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. + +\def\doinsertbookmark#1#2#3#4#5% level sublevels text page open=1 + {\bgroup + \doPDFgetpagereference{#4}\PDFobjectreference + \pdfoutline + user {<</S /GoTo /D [\PDFobjectreference\space\PDFpageviewwrd]>>}% + \ifcase#2 \else count \ifcase#5-\fi#2 \fi +% {<\hexifiedPDFstring{#3}>}% goes wrong + {<#3>}% + \egroup} + +%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 + +\def\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}} + +\def\dostopobject + {\dodostopobject + \egroup} + +\def\doresetobjects + {\global\let\PDFimagereference\empty} + +\def\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} + +\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. +%D +%D This array holds a reasonable selection of transitions +%D (watch out: \type{replace} is not in this list). Most of +%D the transitions look awful anyway. By the way, \CONTEXT\ is +%D able to select transitions randomly. + +\def\pagetransitions + {{split,in,vertical},{split,in,horizontal}, + {split,out,vertical},{split,out,horizontal}, + {blinds,horizontal},{blinds,vertical}, + {box,in},{box,out}, + {wipe,east},{wipe,west},{wipe,north},{wipe,south}, + dissolve, + {glitter,east},{glitter,south}, + {fly,in,east},{fly,in,west},{fly,in,north},{fly,in,south}, + {fly,out,east},{fly,out,west},{fly,out,north},{fly,out,south}, + {push,east},{push,west},{push,north},{push,south}, + {cover,east},{cover,west},{cover,north},{cover,south}, + {uncover,east},{uncover,west},{uncover,north},{uncover,south}, + fade} + +%D Again, we use macros as placeholders for \PDF\ key||value +%D pairs. + +\def\PDFpagesplit {/S /Split } +\def\PDFpageblinds {/S /Blinds } +\def\PDFpagebox {/S /Box } +\def\PDFpagewipe {/S /Wipe } +\def\PDFpagedissolve {/S /Dissolve } +\def\PDFpageglitter {/S /Glitter } +\def\PDFpagereplace {/S /R } + +\def\PDFpagefly {/S /Fly } % 1.5 +\def\PDFpagepush {/S /Push } % 1.5 +\def\PDFpagecover {/S /Cover } % 1.5 +\def\PDFpageuncover {/S /Uncover } % 1.5 +\def\PDFpagefade {/S /Fade } % 1.5 + +\def\PDFpagehorizontal {/Dm /H } +\def\PDFpagevertical {/Dm /V } +\def\PDFpagein {/M /I } +\def\PDFpageout {/M /O } +\def\PDFpageeast {/Di 0 } +\def\PDFpagenorth {/Di 90 } +\def\PDFpagewest {/Di 180 } +\def\PDFpagesouth {/Di 270 } + +\def\dodoPDFsetpagetransition#1% + {\doifdefined{PDFpage#1} + {\edef\PDFpagetransitions{\PDFpagetransitions\getvalue{PDFpage#1}}}} + +\def\dosetpagetransition#1#2% + {\let\PDFpagetransitions\empty + \processcommalist[#1]\dodoPDFsetpagetransition + \appendtopdfpageattributes + %{\ifnum#2>0 /Dur #2 \fi + {\ifnum0<0#2 /Dur #2 \fi + \ifx\PDFpagetransitions\empty\else/Trans <<\PDFpagetransitions>>\fi}} + +%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: + +%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. + +%D \macros +%D {dodefinefieldset,dogetfieldset,doiffieldset} +%D +%D Field sets, needed for reset and submit handling, are +%D taken care of by: + +%D The next section of this module is dedicated to form +%D support. These macros are complicated by the fact that +%D cloning is possible. + +%D \macros +%D {FDFflag...,FDFplus...} +%D +%D The \type{/FT} key determines the type of field: text, +%D button or choice. The latter two come in several disguises, +%D which are set by flipping bits in the \type{/Ff}. Other bits +%D are used to set states. Personally I hate this bitty way of +%D doing things. The next six bit determine the field sub type: + +\def\FDFflagMultiLine {4096} % 13 +\def\FDFflagNoToggleToOff {16384} % 15 +\def\FDFflagRadio {32768} % 16 +\def\FDFflagPushButton {65536} % 17 +\def\FDFflagPopUp {131072} % 18 +\def\FDFflagEdit {262144} % 19 + +% bugged anyway, so we need to drop it: + +\def\FDFflagRadiosInUnison {33554432} % 26 + +%D A few more (pdf 1.4) flags, what the spell check one: for +%D obscure reasons for Adobe downward compatibility means +%D enabling features that harm old applications like testing. + +\def\FDFflagDoNotSpellCheck {4194304} % 23 +\def\FDFflagDoNotScroll {8388608} % 24 + +%D The next bits (watch how strange the bits are organized) +%D take care of the states: + +\def\FDFflagReadOnly {1} % 1 +\def\FDFflagRequired {2} % 2 +\def\FDFflagNoExport {4} % 3 +\def\FDFflagPassword {8192} % 14 +\def\FDFflagSort {524288} % 20 +\def\FDFflagFileSelect {1048576} % 21 + +%D There is a second, again bitset oriented, \type{/F} flag: + +\def\FDFplusInvisible {1} % 1 +\def\FDFplusHidden {2} % 2 +\def\FDFplusPrintable {4} % 3 + +%def\FDFplusNoView {32} % 6 +%def\FDFplusToggleNoView {256} % 9 + +\def\FDFplusAutoView {256} % {288} % 6+9 + +%D \macros +%D {setFDFswitches} +%D +%D The non||type bits are mapped onto user||interface +%D swithes, to be used later on: + +\def\@@FDFflag{FDFflag} +\def\@@FDFplus{FDFplus} + +\letvalue {\@@FDFflag\v!readonly}=\FDFflagReadOnly +\letvalue {\@@FDFflag\v!required}=\FDFflagRequired +\letvalue {\@@FDFflag\v!protected}=\FDFflagPassword +\letvalue {\@@FDFflag\v!sorted}=\FDFflagSort +\letvalue {\@@FDFflag\v!unavailable}=\FDFflagNoExport +\letvalue {\@@FDFflag\v!nocheck}=\FDFflagDoNotSpellCheck +\letvalue {\@@FDFflag\v!fixed}=\FDFflagDoNotScroll +\letvalue {\@@FDFflag\v!file}=\FDFflagFileSelect + +\letvalue {\@@FDFplus\v!hidden}=\FDFplusHidden +\letvalue {\@@FDFplus\v!printable}=\FDFplusPrintable + +\letvalue {\@@FDFplus\v!auto}=\FDFplusAutoView + +%D A set of switches is collected into the flags we mentioned +%D before by the next macro (we don't handle negations yet, +%D but do take care of redundancy): + +\def\FDFflag{0} +\def\FDFplus{0} + +\def\setFDFswitches[#1]% + {\bgroup + \!!counta\zerocount + \!!countb\zerocount + \def\docommand##1% + {\doifsomething{##1} + {\advance\!!counta 0\getvalue{\@@FDFflag##1}% + \setvalue{\@@FDFflag##1}{0}% + \advance\!!countb 0\getvalue{\@@FDFplus##1}% + \setvalue{\@@FDFplus##1}{0}}}% + \processcommacommand[#1]\docommand + \xdef\FDFflag{\the\!!counta}% + \xdef\FDFplus{\the\!!countb}% + \egroup} + +%D \macros +%D {setFDFvalues} +%D +%D Menu items are passed as an array of \type{(string)}'s and +%D the content of this array is build with: + +\let\FDFvalues \empty +\let\FDFfirstvalues \empty +\let\FDFsecondvalues\empty +\let\FDFkidlist \empty +\let\FDFdefaultindex\!!zerocount +\let\FDFdefaultvalue\empty + +% Why do we need to tweak this mechanism each time acrobat updates ... +% it would make sense to have version specific sections in pdf files +% since my guess is that it never will be done right since each year +% new programmers have new ideas about what is supposed to happen with +% kids. So .. best is not to trust this feature esp not for radio +% widgets. (new flags, different interpretation of AS etc etc) + +\def\setFDFvalues[#1][#2]% #1 = list (item=>value) #2 = default + {\let\FDFvalues \empty + %when radio opt works ok + %\let\FDFfirstvalues \empty + %\let\FDFsecondvalues\empty + \let\FDFkidlist \empty + %\let\FDFdefaultindex\!!zerocount + %\let\FDFdefaultvalue\empty + %\scratchcounter\zerocount + \def\dodocommand##1=>##2=>##3\end + {\addtocommalist{##1}\FDFkidlist + %\edef\FDFfirstvalues{\FDFfirstvalues(##1)}% + %\doif{##1}{#2}{\edef\FDFdefaultindex{\the\scratchcounter}}% + %\advance\scratchcounter\plusone + \doifelsenothing{##2} + {\doif{##1}{#2}{\edef\FDFdefaultvalue{##1}}% + %\edef\FDFsecondvalues{\FDFsecondvalues(##1)}% + \edef\FDFvalues{\FDFvalues [(##1)(##1)] }} + {\doif{##1}{#2}{\edef\FDFdefaultvalue{##2}}% + %\edef\FDFsecondvalues{\FDFsecondvalues(##2)}% + \edef\FDFvalues{\FDFvalues [(##2)(##1)] }}}% ! ##1 is shown + \def\docommand##1% + {\dodocommand##1=>=>\end}% + \expanded{\processcommalist[#1]}\docommand} + +%D This macro accepts comma separated \type{visual=>result} +%D pairs. + +%D \macros +%D {setFDFalignment} +%D +%D Text and line fields can be entered and showed in three +%D alternative alingments, indicated by a digit: + +\def\FDFalign{0} + +\def\setFDFalignment[#1]% + {\processaction + [#1] + [ \v!left=>\edef\FDFalign{2}, % raggedleft + \v!middle=>\edef\FDFalign{1}, % raggedcenter + \v!right=>\edef\FDFalign{0}]} % raggedright + +%D \macros +%D {setFDFattributes} +%D +%D The weak part of (at least version 2.1 \PDF) is that only +%D default fonts are handled well. Another restriction is that +%D the encoding vector must be the standard \PDF\ document one. +%D Although the \PDF\ reference explictly states that one could +%D use the normal text operators, leading is not yet handled. +%D +%D For the moment the current \CONTEXT\ font is mapped onto +%D one best suitable default font. The color attribute is +%D less problematic and is directly derived from the \CONTEXT\ +%D color. + +\def\FDFattributes{/Helv 12 Tf 0 g 14.4 TL} + +\def\FDFrm {TiRo} \def\FDFss {Helv} \def\FDFtt {Cour} +\def\FDFrmtf{TiRo} \def\FDFsstf{Helv} \def\FDFtttf{Cour} +\def\FDFrmbf{TiBo} \def\FDFssbf{HeBo} \def\FDFttbf{CoBo} +\def\FDFrmit{TiIt} \def\FDFssit{HeOb} \def\FDFttit{CoOb} +\def\FDFrmsl{TiIt} \def\FDFsssl{HeOb} \def\FDFttsl{CoOb} +\def\FDFrmbi{TiBI} \def\FDFssbi{HeBO} \def\FDFttbi{CoBO} +\def\FDFrmbs{TiBI} \def\FDFssbs{HeBO} \def\FDFttbs{CoBO} + +\let\FDFusedfonts=\FDFsstf + +\def\setFDFattributes[#1,#2,#3,#4]% style, color, backgroundcolor, framecolor + {\bgroup % nog interlinie: n TL + \setbox\scratchbox\hbox + \bgroup + \doconvertfont{#1}{}% + \PointsToBigPoints\bodyfontsize\size % x/xx, so better the actual size + \doifdefinedelse{FDF\fontstyle\fontalternative} + {\xdef\FDFattributes{\getvalue{FDF\fontstyle\fontalternative}}} + {\doifdefinedelse{FDF\fontstyle} + {\xdef\FDFattributes{\getvalue{FDF\fontstyle}}} + {\xdef\FDFattributes{\FDFrm}}}% + \doglobal\addtocommalist\FDFattributes\FDFusedfonts + \xdef\FDFattributes% move up with "x.y Ts" + {/\FDFattributes\space\size\space Tf\space\PDFcolor{#2}}% + \doifelsenothing{#3} + {\global\let\FDFsurroundings\empty} + {\xdef\FDFsurroundings{/BG \FDFcolor{#3}}}% + \doifsomething{#4} + {\xdef\FDFsurroundings{\FDFsurroundings\space /BC \FDFcolor{#4}}}% + \ifx\FDFsurroundings\empty \else + \xdef\FDFsurroundings{/MK << \FDFsurroundings\space>>}% + \fi + \egroup + \egroup} + +%D \macros +%D {setFDFactions} +%D +%D Depending on the type of the field, one can assign +%D \JAVASCRIPT\ code to a mouse event or keystroke. The next +%D preparation macro shows what events are handled. + +\let\FDFactions\empty + +\def\setFDFactions[#1,#2,#3,#4,#5,#6,#7,#8,% + {\global\let\FDFactions\empty + \setFDFaction D#1% mousedown + \setFDFaction U#2% mouseup + \setFDFaction E#3% enterregion + \setFDFaction X#4% exitregion + \setFDFaction K#5% afterkeystroke + \setFDFaction F#6% formatresult + \setFDFaction V#7% validateresult + \setFDFaction C#8% calculatewhatever + \setFDFactionsmore} + +\def\setFDFactionsmore#1,#2]% + {\setFDFaction{Fo}#1% focusin + \setFDFaction{Bl}#2% focusout % was I (now pdf ref manual explicitly talks about lowercase l) + \ifx\FDFactions\empty\else + \xdef\FDFactions{/AA << \FDFactions >>}% since 1.3 no longer inherited + \fi} + +% todo, when new var scheme is implemented +% +% \setFDFaction{PO}\@@DriverFieldPageOpen +% \setFDFaction{PC}\@@DriverFieldPageClose +% \setFDFaction{PV}\@@DriverFieldPageVisible +% \setFDFaction{PI}\@@DriverFieldPageInVisible + +%D The event handler becomes something: +%D +%D \starttyping +%D /AA << /D << /S ... >> ... /C << /S ... >> +%D /A << /S /JavaScript /JS (...) >> +%D \stoptyping + +\def\setFDFaction#1#2% + {\bgroup + \def\docommand{\xdef\FDFactions{\FDFactions /#1 << \lastPDFaction >> }}% + \@EA\handlereferenceactions\@EA{#2}\docommand % one level expansion + \egroup} + +%D \macros +%D {testFDFactions} +%D +%D This rather confusion prone series of script can be tested +%D with: +%D +%D \starttyping +%D \testFDFactions +%D \stoptyping +%D +%D which simply redefined the previous macro to one that prints +%D a message to the console. + +\def\testFDFactions + {\def\setFDFaction##1##2% + {\doPSsanitizeJScode console.show();console.println("executing:##1"); \to\sanitizedJScode + \edef\FDFactions{\FDFactions /##1 << /S /JavaScript /JS (\sanitizedJScode) >> }}} + +%D \macros +%D {doregistercalculationset} +%D +%D There is at most one calculation order list, which defines +%D the order in which fields are calculated. The calculation +%D order is defined using: + +\let\PDFcalculationset\empty + +\def\doregistercalculationset#1% + {\def\PDFcalculationset{#1}} + +%D \macros +%D {registerFDFobject,everylastshipout} +%D +%D Officially one needs to embed some general datastructures +%D that tell the viewer what fields are present in the file, as +%D well as what resources they use. The next mechanism does that +%D job automatically when one registers the field. + +\def\flushFDFnames + {\ifx\FDFcollection\empty\else + \defineFDFfonts + \createpdfarrayobject{FDF}{local:fields}{\FDFcollection}% + \doPDFgetobjectreference{FDF}{local:fields}\PDFobjectreference + % The /NeedAppearances is pretty important because + % otherwise Acrobat 5 blows up on cloned radio widgets + \createpdfdictionaryobject{FDF}{local:acroform} + {/Fields \PDFobjectreference\space + /NeedAppearances true + \doiffieldset\PDFcalculationset{/CO [\dogetfieldset\PDFcalculationset]} + /DR << /Font << \FDFfonts >> >> + /DA (/Helv 10 Tf 0 g)}% + \doPDFgetobjectreference{FDF}{local:acroform}\PDFobjectreference + \appendtopdfcatalog + {/AcroForm \PDFobjectreference}% + \global\let\FDFcollection\empty + \global\let\flushFDFnames\relax + \fi} + +\let\FDFcollection\empty + +\def\registerFDFobject#1% + {\ifx\flushFDFnames\relax + \writestatus{FDF}{second run needed for field list (#1)}% + \fi + \doPDFgetobjectreference{FDF}{#1}\PDFobjectreference + \xdef\FDFcollection{\FDFcollection\space\PDFobjectreference}} + +\appendtoksonce \flushFDFnames \to \everylastshipout % test \everybye / was \prependtoksonce + +%D \macros +%D {defineFDFfonts} +%D +%D Another datastruture concerns the fonts used. We only +%D define the fonts we use. + +\def\defineFDFfonts + {\let\FDFfonts\empty + \processcommacommand[\FDFusedfonts]\defineFDFfont} + +\def\defineFDFfont#1% + {\createpdfdictionaryobject{FDF}{local:#1} + {/Type /Font + /Subtype /Type1 + /Name /#1 + /BaseFont /\getvalue{FDFname#1}}% + \doPDFgetobjectreference{FDF}{local:#1}\PDFobjectreference + \edef\FDFfonts{\FDFfonts \space/#1 \PDFobjectreference}} + +%D Another list of constants: + +\def\FDFnameTiRo {Times-Roman} +\def\FDFnameTiBo {Times-Bold} +\def\FDFnameTiIt {Times-Italic} +\def\FDFnameTiBI {Times-BoldItalic} +\def\FDFnameHelv {Helvetica} +\def\FDFnameHeBo {Helvetica-Bold} +\def\FDFnameHeOb {Helvetica-Oblique} +\def\FDFnameHeBO {Helvetica-BoldOblique} +\def\FDFnameCour {Courier} +\def\FDFnameCoBo {Courier-Bold} +\def\FDFnameCoOb {Courier-Oblique} +\def\FDFnameCoBO {Courier-BoldOblique} + +%D \macros +%D {currentFDFmode,currentFDFparent,currentFDFkids,currenrFDFroot} +%D +%D There are three more quasi global interfacing variables +%D that need to be set. + +\let\currentFDFmode \fieldlonermode +\let\currentFDFkids \empty +\let\currentFDFparent\empty +\let\currentFDFroot \empty + +%D \macros +%D {dosetfieldstatus} +%D +%D And here comes the special that deals with them. + +\def\dosetfieldstatus#1#2#3#4% + {\chardef\currentFDFmode #1% + \edef\currentFDFparent {#2}% + \edef\currentFDFkids {#3}% + \edef\currentFDFroot {#4}} + +%D We already dealt with the encoding vector. Conversion from +%D \TEX\ \ASCII\ encoding to the other one, is accomplished by +%D the next few macros. Wach out: we don't group here. + +\appendtoksonce + \simplifycommands +\to \everysetfield + +%D \macros +%D {doPDFinsertcomment} +%D +%D An example its use is the next special, one that deals with +%D text annotations. + +\newcounter\nofFDFcomments + +\newif\ifPDFpopupcomments \PDFpopupcommentstrue + +\def\doflushcomments + {\box\PDFsymbolbox} + +\long\def\doinsertcomment#1#2#3#4#5#6#7#8% % \@@DriverCommentLayer set otherwise + {\bgroup % title width height color open symbol collect data + \presetPDFsymbolappearance{#4}{#6}{#2}{#3}\!!zeropoint% sets width/height + \doifelsenothing{#1} + {\let\PDFidentifier\empty} + {\sanitizePDFencoding#1\to\PDFcommenttitle + \def\PDFidentifier{/T <\PDFcommenttitle>}}% + \sanitizePDFencoding#8\to\PDFdata + \setFDFlayer\@@DriverCommentLayer + \startPDFsymbolappearance + \ifPDFpopupcomments + \doglobal\increment\nofFDFcomments + \doifobjectreferencefoundelse{FDF}{c:\nofFDFcomments} + {\doPDFgetobjectreference{FDF}{c:\nofFDFcomments}\PDFobjectreference + \donetrue} + \donefalse + \ifdone + \setbox\scratchbox\hbox + {\createpdfannotationobject{FDF}{c::\nofFDFcomments}{#2}{#3}% text window, size does not work + {/Subtype /Popup + /Parent \PDFobjectreference}}% + \ifcase#7\relax + \vbox to \height{\forgetall\vskip#3\box\scratchbox\vss}% + \else % incredible trial and error hack + % it's quite a mess, the annot width cannot be set, well, it can + % but the appearance and text sizes get mixed up +% \setbox\scratchbox\vbox to \height{\forgetall\vskip#3\box\scratchbox\vss}% +% \global\setbox\PDFsymbolbox\vbox +% {\hsize#2% +% \forgetall +% \vsmash{\box\PDFsymbolbox} +% \box\scratchbox}% + % this may change when acrobat gets less bugged + \setbox\scratchbox\vbox to #3{\forgetall\vss\box\scratchbox}% + \wd\scratchbox#2% + \global\setbox\PDFsymbolbox\vbox + {\startoverlay{\box\PDFsymbolbox}{\box\scratchbox}\stopoverlay}% + \fi + \fi + % generic + \doifobjectreferencefoundelse{FDF}{c::\nofFDFcomments} + {\doPDFgetobjectreference{FDF}{c::\nofFDFcomments}\PDFobjectreference + \donetrue} + \donefalse + \createpdfannotationobject{FDF}{c:\nofFDFcomments}{\width}{\height} + {/Subtype /Text + \ifcase#5 \else/Open true\fi + % pdftex (efficient) + % \ifdone /Popup \PDFobjref\pdflastannot\fi + % generic (less efficient) + \ifdone /Popup \PDFobjectreference\fi + /Contents <\PDFdata> + \PDFidentifier + \FDFlayer + \PDFsymbol + \PDFattributes}% + \else + \insertpdfannotation{#2}{#3} + {/Subtype /Text + \ifcase#5 \else/Open true\fi + /Contents <\PDFdata> + \FDFlayer + \PDFsymbol + \PDFidentifier + \PDFattributes}% + \fi + \stopPDFsymbolappearance + \egroup} + +% symbols with a reasonable default of 18/24 pt + +\newbox\PDFsymbolbox + +\def\PDFsymbolNew {/Insert} +\def\PDFsymbolBalloon {/Comment} +\def\PDFsymbolAddition {/NewParagraph} +\def\PDFsymbolHelp {/Help} +\def\PDFsymbolParagraph {/Paragraph} +\def\PDFsymbolKey {/Key } + +\def\PDFsymbolGraph {/Graph} +\def\PDFsymbolPaperclip {/Paperclip} +\def\PDFsymbolAttachment{/Attachment} +\def\PDFsymbolTag {/Tag} + +\def\startPDFsymbolappearance + {\setbox\scratchbox\vbox to \totalheight \bgroup \vfill} + +\def\stopPDFsymbolappearance + {\egroup + \setbox\scratchbox\hbox{\lower\depth\box\scratchbox}% + \wd\scratchbox\width + \ht\scratchbox\height + \dp\scratchbox\depth + \box\scratchbox} + +\def\presetPDFsymbolappearance#1#2#3#4#5% symbol color width height depth + {\doifelsenothing{#1} + {\let\PDFattributes\empty} + {\def\PDFattributes{/C \FDFcolor{#1}}}% + \scratchdimen#3\edef\width {\the\scratchdimen}% + \scratchdimen#4\edef\height{\the\scratchdimen}% + \scratchdimen#5\edef\depth {\the\scratchdimen}% + \advance\scratchdimen\height\edef\totalheight{\the\scratchdimen}% + \doifelsenothing{#2} + {\let\PDFsymbol\empty} + {\ifundefined{PDFsymbol#2}% + \getfromcommacommand[#2][1]\let\PDFsymbolnormalsymbol\commalistelement + \getfromcommacommand[#2][2]\let\PDFsymboldownsymbol \commalistelement + \doifsymboldefinedelse\PDFsymbolnormalsymbol + {\doifsymboldefinedelse\PDFsymboldownsymbol + {\dopresetPDFsymbolappearance + \PDFsymbolnormalsymbol\PDFsymboldownsymbol} + {\dopresetPDFsymbolappearance + \PDFsymbolnormalsymbol\PDFsymbolnormalsymbol}} + {\doifsymboldefinedelse\PDFsymboldownsymbol + {\dopresetPDFsymbolappearance + \PDFsymboldownsymbol\PDFsymboldownsymbol} + {\let\PDFsymbol\empty}}% + \else + \def\PDFsymbol{/Name \getvalue{PDFsymbol#2} }% + \fi}} + +\def\dopresetPDFsymbolappearance#1#2% + {\dopresetfieldsymbol{#1}% + \dopresetfieldsymbol{#2}% + \setbox\scratchbox\hbox{\symbol[#1]}% + \edef\width {\the\wd\scratchbox}% + \edef\height{\the\ht\scratchbox}% + \edef\depth {\the\dp\scratchbox}% + \scratchdimen\height \advance\scratchdimen\depth + \edef\totalheight{\the\scratchdimen}% + \doPDFgetobjectreference{SYM}{#1}\FDFsymbolNappearance + \doPDFgetobjectreference{SYM}{#2}\FDFsymbolDappearance + \edef\PDFsymbol + {/AP <</N \FDFsymbolNappearance /D \FDFsymbolDappearance>>}} + +%D Hooked into \CONTEXT, this special supports +%D +%D \starttyping +%D \startcomment +%D hello beautiful\\world +%D \stopcomment +%D +%D \startcomment[hello] +%D de \'e\'erste keer +%D the f\'irst time +%D \stopcommen +%D +%D \startcommentaar[hallo][color=green,width=4cm,height=3cm] +%D first +%D +%D second +%D \stopcommentaar +%D \stoptyping +%D +%D So, special characters, forced linebreaks using \type{\\} +%D and \type{\par} are handled in the appropriate way. + +%D \macros +%D {dosetuppageview} +%D +%D Because this command will seldom be called, we can permit +%D slow action processing. We need three settings, one for +%D direct \PDF\ inclusion, the other as \PDFTEX\ keyword, an +%D a last one for form. All determine in what way the +%D screen is adapted when going to a destination. Watch the +%D space. + +\def\PDFpageviewkey{fit} +\def\PDFpageviewwrd{/Fit} +\def\PDFpageview {/View [\PDFpageviewwrd] } +\def\PDFpagexyzspec{0 0 0} % hack, pdftex does handle this +\let\PDFpagexyzspec\empty % hack, pdftex does not accept spec + +\def\dosetuppageview#1% watch the v-h swapping here + {\processaction + [#1] + [ \v!fit=>\def\PDFpageviewkey {fit}\def\PDFpageviewwrd{/Fit}, + \v!width=>\def\PDFpageviewkey {fith}\def\PDFpageviewwrd{/FitH}, + \v!height=>\def\PDFpageviewkey {fitv}\def\PDFpageviewwrd{/FitV}, + \v!minwidth=>\def\PDFpageviewkey{fitbh}\def\PDFpageviewwrd{/FitBH}, + \v!minheight=>\def\PDFpageviewkey{fitbv}\def\PDFpageviewwrd{/FitBV}, + \v!standard=>\def\PDFpageviewkey{xyz \PDFpagexyzspec}\def\PDFpageviewwrd{/XYZ \PDFpagexyzspec}, + \s!unknown=>\def\PDFpageviewkey {fit}\def\PDFpageviewwrd{/Fit}]% + \edef\PDFpageview{/View [\PDFpageviewwrd]}} + +%D \macros +%D {setFDFkids} +%D +%D Clones as well as radiofields (which themselves can have +%D cloned components) need a list of kids. The next macro +%D builds one. + +\def\setFDFkids[#1][#2]% tag commalist + {\let\FDFkids\empty + \def\docommand##1% + {\doPDFgetobjectreference{FDF}{#1##1}\PDFobjectreference + \edef\FDFkids{\FDFkids\PDFobjectreference\space}}% + \@EA\processcommalist\@EA[#2]\docommand + \ifx\FDFkids\empty\else\edef\FDFkids{/Kids [\FDFkids]}\fi} + +%D \macros +%D {dopresetlinefield,dopresettextfield, +%D dopresetchoicefield,dopresetpopupfield,dopresetcombofield, +%D dopresetpushfield,dopresetcheckfield, +%D dopresetfield,dopresetradiorecord} +%D +%D I would say: read the \PDF\ reference manual first and see +%D what happens here next. Lucky us that they have so much in +%D common. + +\def\dopresetlinefield#1#2#3#4#5#6#7#8#9% + {\bgroup + \setFDFlayer\@@DriverFieldLayer + \setFDFswitches[#7]% + \setFDFattributes[#6]% + \setFDFalignment[#8]% + \setFDFactions[#9]% + \edef\FDFtext{\hexifiedPDFstring{#4}}% + \ifcase\currentFDFmode + \createpdfannotationobject{FDF}{#1}{#2}{#3} + {/Subtype /Widget /T (#1) /FT /Tx + /MaxLen \ifcase0#5 1000 \else#5 \fi + %/DV (#4) /V (#4) % value added + /DV <\FDFtext> /V <\FDFtext> + /Ff \FDFflag\space + /F \FDFplus\space + /DA (\FDFattributes) + \FDFlayer\space + \FDFsurroundings\space + /Q \FDFalign\space + \FDFactions}% + \registerFDFobject{#1}% + \or + \setFDFkids[kids:][\currentFDFkids]% + \createpdfdictionaryobject{FDF}{#1} + {/T (#1) /FT /Tx + /MaxLen \ifcase0#5 1000 \else#5 \fi + \FDFkids\space + %/DV (#4) /V (#4) % value added + /DV <\FDFtext> /V <\FDFtext> + /Ff \FDFflag\space + /F \FDFplus\space + /DA (\FDFattributes) + \FDFlayer\space + \FDFsurroundings\space + /Q \FDFalign\space + \FDFactions}% + \registerFDFobject{#1}% + \or + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference + /Ff \FDFflag\space + /F \FDFplus\space + /DA (\FDFattributes) + \FDFlayer\space + \FDFsurroundings\space + /Q \FDFalign\space + \FDFactions}% + \or + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference + /F \FDFplus + \FDFactions}% + \fi + \egroup} + +\def\dopresettextfield#1#2#3#4#5#6#7#8#9% + {\dopresetlinefield{#1}{#2}{#3}{#4}{#5}{#6}{MultiLine,#7}{#8}{#9}} + +\def\dopresetchoicefield#1#2#3#4#5#6#7#8% + {\bgroup + \setFDFlayer\@@DriverFieldLayer + \setFDFswitches[#6]% + \setFDFattributes[#5]% + \setFDFvalues[#7][#4]% + \setFDFactions[#8]% + \ifcase\currentFDFmode + \createpdfannotationobject{FDF}{#1}{#2}{#3} + {/Subtype /Widget + /T (#1) /FT /Ch + /DV (#4) /V (#4) + /Ff \FDFflag\space + /F \FDFplus\space + /DA (\FDFattributes) + \FDFlayer\space + \FDFsurroundings\space + /Opt [\FDFvalues] + \FDFactions}% + \registerFDFobject{#1}% + \or + \setFDFkids[kids:][\currentFDFkids]% + \createpdfdictionaryobject{FDF}{#1} + {/T (#1) /FT /Ch + \FDFkids\space + /DV (#4) /V (#4) + /Ff \FDFflag\space + /F \FDFplus\space + /DA (\FDFattributes) + \FDFlayer\space + \FDFsurroundings\space + /Opt [\FDFvalues] + \FDFactions}% + \registerFDFobject{#1}% + \or + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference + /Ff \FDFflag\space + /F \FDFplus\space + /DA (\FDFattributes) + \FDFlayer\space + \FDFsurroundings\space + \FDFactions}% + \or + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference + /F \FDFplus + \FDFactions}% + \fi + \egroup} + +\def\dopresetpopupfield#1#2#3#4#5#6#7#8% + {\dopresetchoicefield{#1}{#2}{#3}{#4}{#5}{PopUp,#6}{#7}{#8}} + +\def\dopresetcombofield#1#2#3#4#5#6#7#8% + {\dopresetchoicefield{#1}{#2}{#3}{#4}{#5}{PopUp,Edit,#6}{#7}{#8}} + +\newif\ifFDFvalues + +\def\doFDFpresetpushcheckfield#1#2#3#4#5#6#7#8% in acro<5 (\FDFdefault) + {\bgroup % in acro>5 /\FDFdefault + \setFDFlayer\@@DriverFieldLayer + \ifcase#8\relax\FDFvaluesfalse\else\FDFvaluestrue\fi + \setFDFswitches[#5]% + \setFDFactions[#7]% + \doifelse{#4}{1} + {\def\FDFdefault{On}} + {\def\FDFdefault{Off}}% + \ifcase\currentFDFmode + \doFDFappearance{On}{#6}{#8}% + \createpdfannotationobject{FDF}{#1}{#2}{#3} + {/Subtype /Widget /T (#1) /FT /Btn + \ifFDFvalues + /DV /\FDFdefault\space + /V /\FDFdefault\space + /AS /\FDFdefault\space + \fi + \FDFlayer + /Ff \FDFflag\space + /F \FDFplus\space + \FDFlayer\space + \FDFappearance\space +% /IF << /SW /N >> % strange, only works for stupid buttons + \FDFactions}% + \registerFDFobject{#1}% + \or % no appearance and layer ? + \setFDFkids[kids:][\currentFDFkids]% + \createpdfdictionaryobject{FDF}{#1} + {/T (#1) /FT /Btn + \FDFkids\space + \ifFDFvalues + /DV /\FDFdefault\space + /V /\FDFdefault\space + /AS /\FDFdefault\space + \fi + /Ff \FDFflag\space + /F \FDFplus\space + \FDFactions}% + \registerFDFobject{#1}% + \or + \doFDFappearance{On}{#6}{#8}% + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference\space + \ifFDFvalues + /DV /\FDFdefault\space + /V /\FDFdefault\space + /AS /\FDFdefault\space + \fi + /Ff \FDFflag\space + /F \FDFplus\space + \FDFlayer\space + \FDFappearance\space + \FDFactions}% + \or + \doFDFappearance{On}{#6}{#8}% + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference\space + /F \FDFplus\space + \ifFDFvalues + /DV /\FDFdefault\space + /V /\FDFdefault\space + /AS /\FDFdefault\space + \fi + \FDFlayer\space + \FDFappearance + \FDFactions}% + \fi + \egroup} + +\def\dopresetpushfield#1#2#3#4#5#6#7% + {\doFDFpresetpushcheckfield{#1}{#2}{#3}{#4}{PushButton,#5}{#6}{#7}{0}} + +\def\dopresetcheckfield#1#2#3#4#5#6#7% + {\doFDFpresetpushcheckfield{#1}{#2}{#3}{#4}{#5}{#6}{#7}{1}} + +\def\dopresetradiofield#1#2#3#4#5#6#7#8% + {\bgroup + \setFDFlayer\@@DriverFieldLayer + \FDFvaluestrue + \setFDFswitches[#5]% + \setFDFactions[#8]% + \doifelsenothing{#4} + {\def\FDFdefault{Off}} + {\def\FDFdefault{#4}}% + \@EA\aftersplitstring\FDFdefault\at=>\to\FDFdefaultvalue + \ifx\FDFdefaultvalue\empty\else\let\FDFdefault\FDFdefaultvalue\fi + \ifcase\currentFDFmode + \doFDFappearance{#1}{#7}{1}% + \doPDFgetobjectreference{FDF}{#6}\PDFobjectreference + \createpdfannotationobject{FDF}{#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference\space + /F \FDFplus\space + /AS /\FDFdefault\space + \FDFlayer\space + \FDFappearance\space + \FDFactions}% + \registerFDFobject{#1}% + \or + \setFDFkids[kids:][\currentFDFkids]% + \doPDFgetobjectreference{FDF}{#6}\PDFobjectreference + \createpdfdictionaryobject{FDF}{#1} + {/Parent \PDFobjectreference\space + \FDFkids\space + /F \FDFplus\space + \FDFactions}% + \registerFDFobject{#1}% + \or + %\doFDFappearance{#1}{#7}{1}% + \doFDFappearance{\currentFDFparent}{#7}{1}% + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue % nb + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference\space + /AS /\FDFdefault\space + /F \FDFplus\space + \FDFlayer\space + \FDFappearance\space + \FDFactions}% + \or + %\doFDFappearance{#1}{#7}{1}% + \doFDFappearance{\currentFDFparent}{#7}{1}% + \doPDFgetobjectreference{FDF}\currentFDFparent\PDFobjectreference + %\global\objectreferencingtrue + \createpdfannotationobject{FDF}{kids:#1}{#2}{#3} + {/Subtype /Widget + /Parent \PDFobjectreference\space + /AS /\FDFdefault\space + /F \FDFplus\space + \FDFlayer\space + \FDFappearance\space + \FDFactions}% + \fi + \egroup} + +% Beware, RadiosInUnison is really needed in the pre 1.5/6 time this +% was the default but out of a sudden it's no longer the case. Also +% the NoToggleToOff interferes with kids of kids and both it will +% break older documents, i.e. so much for pdf as standard. With +% features like widgets we can probably best wait till adobe tools +% themselves support it because that's probably the moment that +% functionality gets frozen/becomes definitive. Actually, acrobat +% flattens the kids tree, so that's yet another situation. The +% interesting thing is that it worked ok in acrobat 2/3 but got bugged +% in later versions. [The rationale is in html compatibility, which +% seems to be more important than compatibility of documents, which in +% turn renders acrobat useless for forms.] Anyway, synchronization is +% broken or not depending on the combination pdfversion/acrobatversion. + +\def\dopresetradiorecord#1#2#3#4#5% + {\bgroup + % < pdf 1.5 (1.5 was broken) + % \setFDFswitches[Radio,NoToggleToOff,RadiosInUnison,#3]% + % > pdf 1.5 + \setFDFswitches[Radio,RadiosInUnison,#3]% + % older, else fatal error + % \setFDFkids[#4][]% + % newer + \setFDFvalues[#4][#2]% inits kidlist + \expanded{\setFDFkids[][\FDFkidlist]}% + % + \setFDFactions[#5]% + \createpdfdictionaryobject{FDF}{#1} + {%/Subtype /Widget + /FT /Btn /T (#1) /Rect [0 0 0 0] + % used to be this + % /V (#2) + % then this + % /DV (#2) + % since this bomded in 5 + % /V (#2) + % and now finally this works + /H /N + % /opt is buggy in 5.05, only works once, sigh + %\ifx\FDFfirstvalues\FDFsecondvalues + /V /#2 + %\else + % /V /\FDFdefaultindex\space + % /Opt [\FDFsecondvalues] + %\fi + /Ff \FDFflag\space + /F \FDFplus\space + \FDFkids\space + \FDFactions}% + \egroup} + +%D At the cost of some more references, we can save bytes, +%D by sharing appearance dictionaries. This code needs more +%D documentation. Surprise: + +\def\dodoFDFappearance#1#2% + {\ifx#2\empty\else + \dogetcommacommandelement1\from#2\to\commalistelement + \ifx\commalistelement\empty\else + \doPDFgetobjectreference{SYM}\commalistelement\PDFobjectreference + \edef\N{\ifFDFvalues\N /#1 \fi\PDFobjectreference\space}% + \fi + \dogetcommacommandelement2\from#2\to\commalistelement + \ifx\commalistelement\empty\else + \doPDFgetobjectreference{SYM}\commalistelement\PDFobjectreference + \edef\R{\ifFDFvalues\R /#1 \fi\PDFobjectreference\space}% + \fi + \dogetcommacommandelement3\from#2\to\commalistelement + \ifx\commalistelement\empty\else + \doPDFgetobjectreference{SYM}\commalistelement\PDFobjectreference + \edef\D{\ifFDFvalues\D /#1 \fi\PDFobjectreference\space}% + \def\FDFappearance{/H /P }% + \fi + \fi} + +\def\redoFDFappearance#1% + {\ifx#1\empty\else + \dogetcommacommandelement3\from#1\to\commalistelement + \ifx\commalistelement\empty\else + \def\FDFappearance{/H /P }% + \fi + \fi} + +\def\doFDFappearance#1#2#3% + {\ifcase#3\relax % push only field + \edef\yes{#2}% + \let\no\empty + \else % on / off field + \dogetcommacommandelement1\from#2,\to\yes + \dogetcommacommandelement2\from#2,\to\no + \fi + \def\FDFappearance{/H /N}% + \doifobjectfoundelse{FDF}{ap:#1:\yes:\no} + {\redoFDFappearance\yes + \redoFDFappearance\no} + {\presetobject{FDF}{ap:#1:\yes:\no}% funny hack + \let\N\empty\let\R\empty\let\D\empty + \dodoFDFappearance{#1}\yes + \dodoFDFappearance{Off}\no + \createpdfdictionaryobject{FDF}{ap:#1:\yes:\no} + {\ifx\N\empty\else/N \ifFDFvalues<<\N>>\else\N\fi\fi + \ifx\R\empty\else/R \ifFDFvalues<<\R>>\else\R\fi\fi + \ifx\D\empty\else/D \ifFDFvalues<<\D>>\else\D\fi\fi}}% + \doPDFgetobjectreference{FDF}{ap:#1:\yes:\no}\PDFobjectreference + \edef\FDFappearance{\FDFappearance /AP \PDFobjectreference}} + +\def\doFDFdefault#1#2% + {\doifelse{#2}{1}{\def\FDFdefault{On}}{\def\FDFdefault{Off}}} + +%D Layer support: + +\def\setFDFlayer#1% todo : \ifx\PDFobjectreference\noPDFobjectreference ipv found + {\letempty\FDFlayer + \doifsomething{#1}% + {\checkproperty[#1]% == \dodocheckproperty\@@DriverFieldLayer + \doifobjectreferencefoundelse{PDLN}{#1} + {\doPDFgetobjectreference{PDLN}{#1}\!!stringa % we need to avoid a clash with other macros + \edef\FDFlayer{/OC \!!stringa}}% + \donothing}} + +%D The three appearances {\em normal}, \type{roll over} and +%D \type{push down} are passed as comma separated triplets, +%D that is, the second argument can look like: +%D +%D \starttyping +%D {yes,ok,fine},{no,rubish,awful} +%D \stoptyping + +%D \macros +%D {dodefinefieldset,dogetfieldset,doiffieldset} +%D +%D Field sets, the ones we use in submitting and resetting +%D fields, are implemented using the next low level specials: +%D +%D \starttyping +%D \doFDFdefinefieldset{TAG}{name,name,...} +%D \doFDFgetfieldset{TAG} +%D \doiffieldset{TAG}{sequence} +%D \stoptyping + +\def\dodefinefieldset#1#2% tag commalist + {\let\FDFfieldset\empty + \def\docommand##1% + {\doPDFgetobjectreference{FDF}{##1}\PDFobjectreference + \edef\FDFfieldset{\FDFfieldset\PDFobjectreference\space}}% + \processcommacommand[#2]\docommand % nb: command + \setevalue{FDF:set:#1}{\FDFfieldset}} + +\def\dogetfieldset#1% + {\getvalue{FDF:set:#1}} + +\def\doiffieldset#1#2% + {\ifundefined{FDF:set:#1}\else#2\fi} + +%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% + {\dogetobjectreferencepage{#1}{#2}#3% + \ifx#3\empty\def#3{1}\fi} + +\def\doPDFgetobjectpagereference#1#2#3% + {\dogetobjectreferencepage{#1}{#2}#3% + \ifx#3\empty + \doPDFgetpagereference\realfolio#3% + \else + \doPDFgetpagereference#3#3% we assume that #3 gets expanded + \fi} + +\def\doPDFgetpagereference#1#2% number macro + {\edef#2{\ifnum#1>\zerocount\PDFobjref{\pdfpageref#1}\else null\fi}} + +\def\thePDFpagereference#1#2% number macro + {\ifnum#1>\zerocount\PDFobjref{\pdfpageref#1}\else null\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. + +\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#1#2#3#4% + {\immediate\pdfobj stream file{#4}% + \edef\PDFlaststreamobject{\the\pdflastobj}% + \dosetobjectreference{PDFFS}{#2}{\PDFlaststreamobject}% + \createpdfdictionaryobject{#1}{#2}{/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}} + +% MP ? + + \def\setMPPDFobject#1#2% resources boxnumber + {\the\everyPDFxform + \finalizeobjectbox{#2}% + \immediate\pdfxform resources{#1}#2% + \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}} + + \let\getMPPDFobject\relax + + \def\doinsertMPfile#1% + {\doiffileelse{./#1}{\includeMPasPDF{./#1}}{\message{[MP #1]}}} + +%D Even newer trickery: + +% resource -> prop -> mc's -> OCG|OCMD (nested) +% ocg: +% /Intent/Design +% ocmd +% /P /AllOn +% kan zelf ocmd bevatten + +\let\PDFtextlayers\empty +\let\PDFpagelayers\empty +\let\PDFhidelayers\empty +\let\PDFvidelayers\empty + +\def\dostartlayer#1{\PDFcode{/OC /#1 BDC}} +\def\dostoplayer {\PDFcode {EMC}} + +\def\dodefineviewerlayer#1#2#3#4#5% tag title visible type printable + {\createpdfdictionaryobject{PDLN}{#1} + {/Type /OCG + \ifcase#4 \or + /Intent /Design % disable layer hiding by user + \fi + \ifnum#5=\zerocount + /Usage << /Print << /PrintState /OFF >> >> % printable or not + \fi + /Name (#2)}% + \doPDFgetobjectreference{PDLN}{#1}\PDFobjectreference + \xdef\PDFtextlayers{\PDFtextlayers\space\PDFobjectreference}% + \doifelse{#3}\v!start + {\xdef\PDFvidelayers{\PDFvidelayers\space\PDFobjectreference}}% + {\xdef\PDFhidelayers{\PDFhidelayers\space\PDFobjectreference}}% + \createpdfdictionaryobject{PDLD}{#1} + {/Type /OCMD + /OCGs [\PDFobjectreference]}% + \doPDFgetobjectreference{PDLD}{#1}\PDFobjectreference + \xdef\PDFpagelayers{\PDFpagelayers\space /#1 \PDFobjectreference}} + +\def\flushPDFtextlayers + {\ifx\PDFtextlayers\empty \else + \driverreferenced \createpdfarrayobject{PDF}{textlayers}{\PDFtextlayers}% + \doPDFgetobjectreference{PDF}{textlayers}\!!stringa + \ifx\PDFvidelayers\empty + \def\!!stringb{[null]}% + \else + \driverreferenced \createpdfarrayobject{PDF}{videlayers}{\PDFvidelayers}% + \doPDFgetobjectreference{PDF}{videlayers}\!!stringb + \fi + \ifx\PDFhidelayers\empty + \def\!!stringc{[null]}% + \else + \driverreferenced \createpdfarrayobject{PDF}{hidelayers}{\PDFhidelayers}% + \doPDFgetobjectreference{PDF}{hidelayers}\!!stringc + \fi + \appendtopdfcatalog + {/OCProperties + << % display in menu + /D << /Order \!!stringa + /ON \!!stringb + /OFF \!!stringc >> + % used properties + /OCGs \!!stringa >>}% + \globallet\flushPDFtextlayers\relax + \fi} + +\def\flushPDFpagelayers + {\ifx\PDFpagelayers\empty \else + \appendtopdfpageresources{/Properties <<\PDFpagelayers>>}% + \fi} + +\def\PDFlayeractionlist{null} + +\def\PDFexecutehidelayer {/SetOCGState /State [/OFF \PDFlayeractionlist]} +\def\PDFexecutevidelayer {/SetOCGState /State [/ON \PDFlayeractionlist]} +\def\PDFexecutetogglelayer {/SetOCGState /State [/Toggle \PDFlayeractionlist]} + +\def\domakeviewerlayerlist#1% + {\bgroup + \globallet\PDFlayeractionlist\empty + \def\docommand##1% + {\doPDFgetobjectreference{PDLN}{##1}\PDFobjectreference + \xdef\PDFlayeractionlist{\PDFlayeractionlist\space\PDFobjectreference}}% + \processcommalist[#1]\docommand + \egroup} + +%D Something rather pdf dependent: + +% #1 => 1=fill 2=stroke 3=strokedfill 4=invisible +% #2 => linewidth +% #3 => spacing (beware, one needs to set the hsize as well) + +\def\dostartfonteffect#1#2#3% + {\ifdim#2>\zeropoint + \PointsToBigPoints{#2}\ascii + \PDFcode{\ascii\space w}% + \fi + \ifdim#3\points=\onepoint\else + \scratchdimen#3\points + \PDFcode{\withoutpt{\the\scratchdimen}\space Tc}% + \fi + \PDFcode{\purenumber#1 Tr}} + +\def\dostopfonteffect + {\PDFcode{1 w 0 Tc 0 Tr}} + +%D Handy for the \METAPOST\ to \PDF\ converter: + +\appendtoksonce + \collectPDFresources + \global\let\currentPDFresources\collectedPDFresources +\to \everyPDFxform + +\let\collectedPDFresources\empty + +\def\collectPDFresources % suboptimal + {\doifobjectreferencefoundelse{FDF}{docushades} % redundant, we have an reserved object now + {\doPDFgetobjectreference{FDF}{docushades}\PDFobjectreference + \xdef\collectedPDFresources{\collectedPDFresources/Shading \PDFobjectreference}}\donothing + \doifobjectreferencefoundelse{FDF}{docuextgstates} + {\doPDFgetobjectreference{FDF}{docuextgstates}\PDFobjectreference + \xdef\collectedPDFresources{\collectedPDFresources/ExtGState \PDFobjectreference}}\donothing + \doifobjectreferencefoundelse{FDF}{colorspaces} + {\doPDFgetobjectreference{FDF}{colorspaces}\PDFobjectreference + \xdef\collectedPDFresources{\collectedPDFresources/ColorSpace \PDFobjectreference}}\donothing + \global\let\collectPDFresources\relax} + +\appendtoks + \flushPDFpagelayers + \flushJSpreamble + \flushJSpreamble + \checkPDFextgstates + \checkPDFcolorspaces + \checkPDFshades + \checkPDFpageactions + \fakePDFpagedestination + \flushPDFpageboxes + \addPDFdocumentinfo +\to \everybackendshipout + +\appendtoks + \flushPDFtextlayers + \finalflushJSpreamble +\to \everylastbackendshipout + +%D Temporary hack: + +\def\TransparencyHack % png: /CS /DeviceRGB /I true + {\appendtoksonce + \appendtopdfpageattributes{/Group << /S /Transparency /I true /K true>>}% + \to \everyPDFxform + \appendtoksonce + \appendtopdfpageattributes{/Group << /S /Transparency /I true /K true>>}% + \to \everyshipout} + +\protect \endinput |