%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 ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Backend Macros / PDF} %registerctxluafile{lpdf-aux}{1.001} % common helpers \registerctxluafile{lpdf-ini}{1.001} \registerctxluafile{lpdf-nod}{1.001} \registerctxluafile{lpdf-col}{1.000} \registerctxluafile{lpdf-xmp}{1.001} \registerctxluafile{lpdf-ano}{1.001} \registerctxluafile{lpdf-res}{1.001} \registerctxluafile{lpdf-mis}{1.001} \registerctxluafile{lpdf-ren}{1.001} \registerctxluafile{lpdf-grp}{1.001} \registerctxluafile{lpdf-wid}{1.001} \registerctxluafile{lpdf-fld}{1.001} \registerctxluafile{lpdf-mov}{1.001} \registerctxluafile{lpdf-u3d}{1.001} \registerctxluafile{lpdf-swf}{1.001} \registerctxluafile{lpdf-tag}{1.001} \registerctxluafile{lpdf-fmt}{1.001} \registerctxluafile{lpdf-epd}{1.001} \registerctxluafile{lpdf-epa}{1.001} \registerctxluafile{back-pdf}{1.001} % some code will move to lpdf-* \unprotect %D We will minimize the number of calls to \PDF\ specific primitives %D and delegate all management and injection of code to the backend. %D %D Here we initialize some internal quantities. We also protect them. \outputmode\plusone \let\outputmode\relax \newcount\outputmode \outputmode\plusone %D Because we do a lot in \LUA\ and don't want interferences, we nil most of the %D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable}, %D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably %D have bad side effects. %D These are no-ops and don't even intercept what comes next. Maybe some day %D I'll write a parser that maps onto \CONTEXT. \unexpanded\def\unsupportedpdfprimitive#1% {\writestatus{error}{the primitive \string#1\space is not supported}} \unexpanded\def\pdfcolorstack {\unsupportedpdfprimitive\pdfcolorstack} \unexpanded\def\pdfcolorstackinit{\unsupportedpdfprimitive\pdfcolorstackinit} %unexpanded\def\pdfannot {\unsupportedpdfprimitive\pdfannot} \unexpanded\def\pdfstartlink {\unsupportedpdfprimitive\pdfstartlink} \unexpanded\def\pdfendlink {\unsupportedpdfprimitive\pdfendlink} \unexpanded\def\pdfoutline {\unsupportedpdfprimitive\pdfoutline} %unexpanded\def\pdfdest {\unsupportedpdfprimitive\pdfdest} \unexpanded\def\pdfthread {\unsupportedpdfprimitive\pdfthread} \unexpanded\def\pdfstartthread {\unsupportedpdfprimitive\pdfstartthread} \unexpanded\def\pdfendthread {\unsupportedpdfprimitive\pdfendthread} \unexpanded\def\pdffontattr {\unsupportedpdfprimitive\pdffontattr} \unexpanded\def\pdfglyphtounicode{\unsupportedpdfprimitive\pdfglyphtounicode} \unexpanded\def\pdfannot{\clf_pdfannot} \unexpanded\def\pdfdest {\clf_pdfdest} %D Here we do intercept (silently) what gets passed. One should use the %D \CONTEXT\ interfaces instead. \let\pdfcatalog \relax \newtoks\pdfcatalog \let\pdfinfo \relax \newtoks\pdfinfo \let\pdfnames \relax \newtoks\pdfnames \let\pdftrailer \relax \newtoks\pdftrailer \let\pdfpageresources \relax \newtoks\pdfpageresources \let\pdfpageattr \relax \newtoks\pdfpageattr \let\pdfpagesattr \relax \newtoks\pdfpagesattr \let\pdfxformattr \relax \newtoks\pdfxformattr \let\pdfxformresources\relax \newtoks\pdfxformresources %D We use the \LUA\ interface (which then permits more control over %D possible pdf/x extensions). \let\pdfcompresslevel \relax \newcount\pdfcompresslevel \let\pdfobjcompresslevel\relax \newcount\pdfobjcompresslevel %D But we still provide: \unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} \unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } \unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} %D These might even become no-ops as we don't need them in \CONTEXT: \unexpanded\def\pdfmapfile#1{\clf_setmapfile{#1}} \unexpanded\def\pdfmapline#1{\clf_setmapline{#1}} %D We don't support these directives, at least not this way. If they are needed %D by third party modules we can provide some interface. \let\pdfcreationdate \relax \newtoks \pdfcreationdate \let\pdfdecimaldigits \relax \newcount\pdfdecimaldigits \let\pdfdestmargin \relax \newcount\pdfdestmargin \let\pdffontname \relax \newcount\pdffontname \let\pdffontobjnum \relax \newcount\pdffontobjnum \let\pdffontsize \relax \newcount\pdffontsize \let\pdfgamma \relax \newcount\pdfgamma \let\pdfgentounicode \relax \newcount\pdfgentounicode \let\pdfhorigin \relax \newcount\pdfhorigin \let\pdfignoreunknownimages \relax \newcount\pdfignoreunknownimages \let\pdfimageaddfilename \relax \newcount\pdfimageaddfilename \let\pdfimageapplygamma \relax \newcount\pdfimageapplygamma \let\pdfimagegamma \relax \newcount\pdfimagegamma \let\pdfimagehicolor \relax \newcount\pdfimagehicolor \let\pdfimageresolution \relax \newcount\pdfimageresolution \let\pdfincludechars \relax \newtoks \pdfincludechars \let\pdfinclusioncopyfonts \relax \newcount\pdfinclusioncopyfonts \let\pdfinclusionerrorlevel \relax \newcount\pdfinclusionerrorlevel \let\pdfinfoomitdate \relax \newcount\pdfinfoomitdate \let\pdflastannot \relax \newcount\pdflastannot \let\pdflastlink \relax \newcount\pdflastlink \let\pdflinkmargin \relax \newcount\pdflinkmargin \let\pdfminorversion \relax \newcount\pdfminorversion \let\pdfpagebox \relax \newcount\pdfpagebox \let\pdfpageref \relax \newcount\pdfpageref \let\pdfpkfixeddpi \relax \newcount\pdfpkfixeddpi \let\pdfpkmode \relax \newtoks \pdfpkmode \let\pdfpkresolution \relax \newcount\pdfpkresolution \let\pdfretval \relax \newcount\pdfretval \let\pdfsuppressoptionalinfo \relax \newcount\pdfsuppressoptionalinfo \let\pdfsuppressptexinfo \relax \newcount\pdfsuppressptexinfo \let\pdftexrevision \relax \newcount\pdftexrevision \let\pdftexversion \relax \newcount\pdftexversion \let\pdfthreadmargin \relax \newcount\pdfthreadmargin \let\pdftrailerid \relax \newtoks \pdftrailerid \let\pdfuniqueresname \relax \newcount\pdfuniqueresname \let\pdfvorigin \relax \newcount\pdfvorigin \let\pdfxformmargin \relax \newcount\pdfxformmargin \let\pdfxformname \relax \newcount\pdfxformname %D These are still accepted but are normally not needed. \let\pdflastxform \lastsavedboxresourceindex \let\pdflastximage \lastsavedimageresourceindex \let\pdflastximagepages \lastsavedimageresourcepages \let\pdflastxpos \lastxpos \let\pdflastypos \lastypos \let\pdfrefxform \useboxresource \let\pdfrefximage \useimageresource \let\pdfsavepos \savepos \let\pdfxform \saveboxresource \let\pdfximage \saveimageresource %D For the moment we keep these as they are but they will become \LUA\ %D calls eventually, after which we will nil the three \type {\pdf} %D interface primitives. \normalprotected\def\pdfliteral {\pdfextension literal } \normalprotected\def\pdfobj {\pdfextension obj } \def\pdflastobj {\numexpr\pdffeedback lastobj\relax} \normalprotected\def\pdfrefobj {\pdfextension refobj } \normalprotected\def\pdfrestore {\pdfextension restore\relax} \normalprotected\def\pdfsave {\pdfextension save\relax} \normalprotected\def\pdfsetmatrix{\pdfextension setmatrix } %D This one can be consulted by users although the suffix is also %D a system mode. \back_job_set_suffix{pdf} %D PDF/X (maybe combine the two lua calls) \setupbackend [xmpfile=] \appendtoks \doifsomething{\backendparameter{xmpfile}} {\clf_setxmpfile{\backendparameter{xmpfile}}}% \to \everysetupbackend % \doifsomething{\backendparameter\c!format} .. at the lua end \appendtoks \clf_setformat format {\backendparameter\c!format}% level {\backendparameter\c!level}% option {\backendparameter\c!option}% profile {\backendparameter\c!profile}% intent {\backendparameter\c!intent}% file {\backendparameter\c!file}% \relax \to \everysetupbackend %D For the moment we keep these. %newtoks \pdfbackendeveryximage \newtoks \pdfbackendeveryxform %D These are the only official methods to add stuff to the resources. \unexpanded\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog {#1}{#2}} \unexpanded\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo {#1}{#2}} \unexpanded\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames {#1}{#2}} \unexpanded\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes {#1}{#2}} \unexpanded\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes {#1}{#2}} \unexpanded\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources {#1}{#2}} \unexpanded\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate {#1}{#2}} \unexpanded\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}} \unexpanded\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern {#1}{#2}} \unexpanded\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade {#1}{#2}} \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources} \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax} \let\PDFcolor\pdfcolor %D Transformations % rotation \unexpanded\def\dostartrotation#1% {\forcecolorhack \clf_pdfstartrotation#1\relax} % todo: implement without Q q \unexpanded\def\dostoprotation {\clf_pdfstoprotation \forcecolorhack} % scaling \unexpanded\def\dostartscaling#1#2% {\forcecolorhack \clf_pdfstartscaling rx #1 ry #2\relax} \unexpanded\def\dostopscaling {\clf_pdfstopscaling \forcecolorhack} % mirroring \unexpanded\def\dostartmirroring {\clf_pdfstartmirroring} \unexpanded\def\dostopmirroring {\clf_pdfstopmirroring} % transform \unexpanded\def\dotransformnextbox#1#2#3#4#5#6% {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}} \unexpanded\def\dodotransformnextbox#1#2#3#4#5#6% {\hpack {\kern #5\onebasepoint \raise#6\onebasepoint \hpack {\clf_pdfstartmatrix rx #1 sx #2 sy #3 ry #4\relax \box\nextbox \clf_pdfstopmatrix}}} % somehow the shift is not happening .. bug in luatex? % % \unexpanded\def\dodotransformnextbox#1#2#3#4#5#6% % {\ctxcommand{pdftransformbox(\number\nextbox,#1,#2,#3,#4,\number\dimexpr#5\onebasepoint,\number\dimexpr#6\onebasepoint)}% % \box\nextbox} % % \startluacode % function commands.pdftransformbox(box,rx,sx,sy,ry,tx,ty) % if rx == 1 and sx == 0 and sy == 0 and ry == 1 then % if tx == 0 and ty == 0 then % local b = nodes.hpack(nodes.concat { % nodes.pool.kern(tx), % nodes.takebox(box), % }) % b.shift = -ty % tex.setbox(box,b) % else % -- no need to transform % end % else % local b = nodes.hpack(nodes.concat { % nodes.pool.kern(tx), % nodes.pool.pdfsave(), % nodes.pool.pdfsetmatrix(rx,sx,sy,ry), % nodes.takebox(box), % nodes.pool.pdfsetmatrix(-rx,-sx,-sy,-ry), % nodes.pool.pdfrestore(), % }) % b.shift = -ty % tex.setbox(box,b) % end % end % \stopluacode % clipping \unexpanded\def\dostartclipping#1#2#3% we can move this to lua and only set a box here {\forcecolorhack \PointsToBigPoints{#2}\width \PointsToBigPoints{#3}\height \meta_grab_clip_path{#1}\width\height{% 0 0 m % \width\space 0 l % \width\space \height\space l % 0 \height\space l% }% \pdfliteral{q 0 w \MPclippath\space W n}} \unexpanded\def\dostopclipping {\pdfliteral{Q}} %D Temporary hack, will be removed or improved or default. % attr {/Group << /S /Transparency /I false /K true >>} %def\TransparencyHack{\ctxlua{backends.codeinjections.addtransparencygroup()}} \def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]} % \let\lastpredefinedsymbol\empty % some day we can do more at the lua end % % \unexpanded\def\predefinesymbol[#1]% % {\begingroup % \xdef\lastpredefinedsymbol{#1}% % \settightobject{SYM}{#1}\hbox{\symbol[#1]}% to be checked ... maybe only fitting % \dogetobjectreference{SYM}{#1}\m_back_object_reference % \clf_registerbackendsymbol{#1}\m_back_object_reference\relax % \endgroup} % Still here: %D \macros %D {back_ovalbox} %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. This code is %D somewhat obsolete as we now have metapost embedded. % \def\back_oval_calculate#1#2#3% % {\PointsToBigPoints{\dimexpr#2+#3\relax}#1} \unexpanded\def\back_ovalbox#1#2#3#4#5#6#7#8% {\forcecolorhack \bgroup % \scratchdimen#4% % \divide\scratchdimen\plustwo % \back_oval_calculate\xmin \zeropoint\scratchdimen % \back_oval_calculate\xmax {#1}{-\scratchdimen}% % \back_oval_calculate\ymax {#2}{-\scratchdimen}% % \back_oval_calculate\ymin {-#3}\scratchdimen % \advance\scratchdimen by #5% % \back_oval_calculate\xxmin \zeropoint\scratchdimen % \back_oval_calculate\xxmax {#1}{-\scratchdimen}% % \back_oval_calculate\yymax {#2}{-\scratchdimen}% % \back_oval_calculate\yymin {-#3}\scratchdimen % \back_oval_calculate\stroke{#4}\zeropoint % \back_oval_calculate\radius{#5}\zeropoint % \PointsToBigPoints{#4} \stroke \PointsToBigPoints{#5} \radius \scratchdimen\dimexpr#4/\plustwo\relax \PointsToBigPoints \scratchdimen \xmin \PointsToBigPoints{\dimexpr #1-\scratchdimen}\xmax \PointsToBigPoints{\dimexpr #2-\scratchdimen}\ymax \PointsToBigPoints{\dimexpr-#3+\scratchdimen}\ymin \advance\scratchdimen by #5\relax \PointsToBigPoints \scratchdimen \xxmin \PointsToBigPoints{\dimexpr #1-\scratchdimen}\xxmax \PointsToBigPoints{\dimexpr #2-\scratchdimen}\yymax \PointsToBigPoints{\dimexpr-#3+\scratchdimen}\yymin % \edef\dostroke{\number#6}% \edef\dofill{\number#7}% \edef\mode{\number#8}% % no \ifcase, else \relax in pdfcode \setbox\scratchbox\naturalhpack {\ifnum\dostroke\dofill>\zerocount \pdfliteral {q \stroke\space w \ifcase\mode\space \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>\pluseight\space 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} \unexpanded\def\pdfbackendactualtext#1#2% not interfaced {\clf_startactualtext{#2}% #1% \clf_stopactualtext} \let\pdfactualtext\pdfbackendactualtext % \starttext % text \pdfbackendactualtext{Meier}{Müller} text % \stoptext \protect \endinput % \chapter{FIRST} % % \goto{bar}[bar] % % HERE \pdfannot width 20pt height 20pt depth 20pt {/Subtype /Link /Dest (bar) /Border [1 1 1] /F 4}\par % HERE \pdfannot width 20pt height 20pt depth 20pt {/Subtype /Link /Dest (foo) /Border [1 1 1] /F 4}\par % % \chapter[bar]{SECOND} % % THERE \pdfdest name {foo} \par