diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3drivers-pdf.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3drivers-pdf.dtx | 1934 |
1 files changed, 0 insertions, 1934 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers-pdf.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers-pdf.dtx deleted file mode 100644 index 62a3bea1119..00000000000 --- a/Master/texmf-dist/source/latex/l3kernel/l3drivers-pdf.dtx +++ /dev/null @@ -1,1934 +0,0 @@ -% \iffalse meta-comment -% -%% File: l3drivers-pdf.dtx -% -% Copyright (C) 2011-2019 The LaTeX3 Project -% -% It may be distributed and/or modified under the conditions of the -% LaTeX Project Public License (LPPL), either version 1.3c of this -% license or (at your option) any later version. The latest version -% of this license is in the file -% -% https://www.latex-project.org/lppl.txt -% -% This file is part of the "l3kernel bundle" (The Work in LPPL) -% and all files in that bundle must be distributed together. -% -% ----------------------------------------------------------------------- -% -% The development version of the bundle can be found at -% -% https://github.com/latex3/latex3 -% -% for those people who are interested. -% -%<*driver> -\documentclass[full,kernel]{l3doc} -\begin{document} - \DocInput{\jobname.dtx} -\end{document} -%</driver> -% \fi -% -% \title{^^A -% The \textsf{l3drivers-pdf} package\\ Driver PDF features^^A -% } -% -% \author{^^A -% The \LaTeX3 Project\thanks -% {^^A -% E-mail: -% \href{mailto:latex-team@latex-project.org} -% {latex-team@latex-project.org}^^A -% }^^A -% } -% -% \date{Released 2019-05-28} -% -% \maketitle -% -% \begin{documentation} -% -% \end{documentation} -% -% \begin{implementation} -% -% \section{\pkg{l3drivers-pdf} Implementation} -% -% \begin{macrocode} -%<*initex|package> -%<@@=driver> -% \end{macrocode} -% -% Setting up PDF resources is a complex area with only limited documentation -% in the engine manuals. The following code builds heavily on existing ideas -% from \pkg{hyperref} work by Sebastian Rahtz and Heiko Oberdiek, and -% significant contributions by Alexander Grahn, in addition to the specific -% code referenced a various points. -% -% \subsection{Shared code} -% -% A very small number of items that belong at the driver level but which -% are common to all drivers. -% -% \subsection{\texttt{dvips} driver} -% -% \begin{macrocode} -%<*dvips> -% \end{macrocode} -% -% \begin{macro}{\@@_pdfmark:n, \@@_pdfmark:x} -% Used often enough it should be a separate function. -% \begin{macrocode} -\cs_new_protected:Npn \@@_pdfmark:n #1 - { \@@_postscript:n { mark #1 ~ pdfmark } } -\cs_generate_variant:Nn \@@_pdfmark:n { x } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Catalogue entries} -% -% \begin{macro}{\driver_pdf_catalog_gput:nn, \driver_pdf_info_gput:nn} -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_catalog_gput:nn #1#2 - { \@@_pdfmark:n { { Catalog } << /#1 ~ #2 >> /PUT } } -\cs_new_protected:Npn \driver_pdf_info_gput:nn #1#2 - { \@@_pdfmark:n { /#1 ~ #2 /DOCINFO } } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Objects} -% -% \begin{variable}{\g_@@_pdf_object_int, \g_@@_pdf_object_prop} -% For tracking objects to allow finalisation. -% \begin{macrocode} -\int_new:N \g_@@_pdf_object_int -\prop_new:N \g_@@_pdf_object_prop -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\driver_pdf_object_new:nn} -% \begin{macro}[EXP]{\driver_pdf_object_ref:n} -% Tracking objects is similar to \texttt{dvipdfmx}. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_object_new:nn #1#2 - { - \int_gincr:N \g_@@_pdf_object_int - \int_const:cn - { c_@@_pdf_object_ \tl_to_str:n {#1} _int } - { \g_@@_pdf_object_int } - \prop_gput:Nnn \g_@@_pdf_object_prop {#1} {#2} - } -\cs_new:Npn \driver_pdf_object_ref:n #1 - { { driver.obj \int_use:c { c_@@_pdf_object_ \tl_to_str:n {#1} _int } } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\driver_pdf_object_write:nn} -% \begin{macro} -% { -% \@@_pdf_object_write_array:nn , -% \@@_pdf_object_write_dict:nn , -% \@@_pdf_object_write_stream:nn -% } -% \begin{macro}{\@@_pdf_object_write_stream:nnn} -% This is where we choose the actual type: some work to get things -% right. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_object_write:nn #1#2 - { - \@@_pdfmark:x - { - /_objdef ~ \driver_pdf_object_ref:n {#1} - /type - \str_case_e:nn - { \prop_item:Nn \g_@@_pdf_object_prop {#1} } - { - { array } { /array } - { dict } { /dict } - { fstream } { /stream } - { stream } { /stream } - } - /OBJ - } - \use:c - { @@_pdf_object_write_ \prop_item:Nn \g_@@_pdf_object_prop {#1} :nn } - {#1} {#2} - } -\cs_new_protected:Npn \@@_pdf_object_write_array:nn #1#2 - { - \@@_pdfmark:x - { - \driver_pdf_object_ref:n {#1} - [ ~ \exp_not:n {#2} ~ ] ~ /PUTINTERVAL - } - } -\cs_new_protected:Npn \@@_pdf_object_write_dict:nn #1#2 - { - \@@_pdfmark:x - { - \driver_pdf_object_ref:n {#1} - << \exp_not:n {#2} >> /PUT - } - } -\cs_new_protected:Npn \@@_pdf_object_write_stream:nn #1#2 - { - \exp_args:Nx - \@@_pdf_object_write_stream:nnn - { \driver_pdf_object_ref:n {#1} } - #2 - } -\cs_new_protected:Npn \@@_pdf_object_write_stream:nnn #1#2#3 - { - \@@_postscript:n - { - [nobreak] - mark ~ #1 ~ ( #3 ) /PUT ~ pdfmark ~ - mark ~ #1 ~ << #2 >> /PUT ~ pdfmark - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \subsubsection{Annotations} -% -% In \texttt{dvips}, annotations have to be constructed manually. As such, -% we need the object code above for some definitions. -% -% \begin{macro}{driver.globaldict} -% A small global dictionary for driver use. -% \begin{macrocode} -\@@_postscript_header:n - { - true ~ setglobal ~ - /driver.globaldict ~ 4 ~ dict ~ def ~ - false ~ setglobal - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% driver.cvs , -% driver.dvi.pt , -% driver.pt.dvi , -% driver.rect.ht -% } -% Small utilities for PostScript manipulations. Conversion to DVI dimensions -% is done here to allow for |Resolution|. The total height of a rectangle -% (an array) needs a little maths, in contrast to simply extracting a value. -% \begin{macrocode} -\@@_postscript_header:n - { - /driver.cvs { 65534 ~ string ~ cvs } def - /driver.dvi.pt { 72.27 ~ mul ~ Resolution ~ div } def - /driver.pt.dvi { 72.27 ~ div ~ Resolution ~ mul } def - /driver.rect.ht { dup ~ 1 ~ get ~ neg ~ exch ~ 3 ~ get ~ add } def - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{driver.linkmargin, driver.linkdp.pad, driver.linkht.pad} -% Settings which are defined up-front in |SDict|. -% \begin{macrocode} -\@@_postscript_header:n - { - /driver.linkmargin { 1 ~ driver.pt.dvi } def - /driver.linkdp.pad { 0 } def - /driver.linkht.pad { 0 } def - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% driver.rect , -% driver.save.ll , -% driver.save.ur , -% driver.save.linkll , -% driver.save.linkur , -% driver.llx , -% driver.lly , -% driver.urx , -% driver.ury -% } -% Functions for marking the limits of an annotation/link, plus drawing the -% border. We separate links for generic annotations to support adding a -% margin and setting a minimal size. -% \begin{macrocode} -\@@_postscript_header:n - { - /driver.rect - { /Rect [ driver.llx ~ driver.lly ~ driver.urx ~ driver.ury ] } def - /driver.save.ll - { - currentpoint - /driver.lly ~ exch ~ def - /driver.llx ~ exch ~ def - } - def - /driver.save.ur - { - currentpoint - /driver.ury ~ exch ~ def - /driver.urx ~ exch ~ def - } - def - /driver.save.linkll - { - currentpoint ~ - driver.linkmargin ~ add ~ - driver.linkdp.pad ~ add - /driver.lly ~ exch ~ def ~ - driver.linkmargin ~ sub - /driver.llx ~ exch ~ def - } - def - /driver.save.linkur - { - currentpoint ~ - driver.linkmargin ~ sub ~ - driver.linkht.pad ~ sub - /driver.ury ~ exch ~ def ~ - driver.linkmargin ~ add - /driver.urx ~ exch ~ def - } - def - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% driver.dest.anchor , -% driver.dest.x , -% driver.dest.y , -% driver.dest.point , -% driver.dest2device , -% driver.dev.x , -% driver.dev.y , -% driver.tmpa , -% driver.tmpb , -% driver.tmpc , -% driver.tmpd -% } -% For finding the anchor point of a destination link. We make the use case -% a separate function as it comes up a lot, and as this makes it easier to -% adjust if we need additional effects. We also need a more complex approach -% to convert a co-ordinate pair correctly when defining a rectangle: this -% can otherwise be out when using a landscape page. (Thanks to Alexander -% Grahn for the approach here.) -% \begin{macrocode} -\@@_postscript_header:n - { - /driver.dest.anchor - { - currentpoint ~ exch ~ - driver.dvi.pt ~ 72 ~ add ~ - /driver.dest.x ~ exch ~ def ~ - driver.dvi.pt ~ - vsize ~ 72 ~ sub ~ exch ~ sub ~ - /driver.dest.y ~ exch ~ def - } - def - /driver.dest.point - { driver.dest.x ~ driver.dest.y } def - /driver.dest2device - { - /driver.dest.y ~ exch ~ def - /driver.dest.x ~ exch ~ def ~ - matrix ~ currentmatrix ~ - matrix ~ defaultmatrix ~ - matrix ~ invertmatrix ~ - matrix ~ concatmatrix ~ - cvx ~ exec - /driver.dev.y ~ exch ~ def - /driver.dev.x ~ exch ~ def - /driver.tmpd ~ exch ~ def - /driver.tmpc ~ exch ~ def - /driver.tmpb ~ exch ~ def - /driver.tmpa ~ exch ~ def ~ - driver.dest.x ~ driver.tmpa ~ mul ~ - driver.dest.y ~ driver.tmpc ~ mul ~ add ~ - driver.dev.x ~ add ~ - driver.dest.x ~ driver.tmpb ~ mul ~ - driver.dest.y ~ driver.tmpd ~ mul ~ add ~ - driver.dev.y ~ add - } - def - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% driver.bordertracking , -% driver.bordertracking.begin , -% driver.bordertracking.end , -% driver.leftboundary , -% driver.rightboundary , -% driver.brokenlink.rect , -% driver.brokenlink.skip , -% driver.brokenlink.dict , -% driver.bordertracking.endpage , -% driver.bordertracking.continue , -% driver.originx , -% driver.originy -% } -% To know where a breakable link can go, we need to track the boundary -% rectangle. That can be done by hooking into |a| and |x| operations: -% those names have to be retained. The boundary is stored at the end of -% the operation. Special effort is needed at the start and end of pages -% (or rather galleys), such that everything works properly. -% \begin{macrocode} -\@@_postscript_header:n - { - /driver.bordertracking ~ false ~ def - /driver.bordertracking.begin - { - SDict ~ /driver.bordertracking ~ true ~ put ~ - SDict ~ /driver.leftboundary ~ undef ~ - SDict ~ /driver.rightboundary ~ undef ~ - /a ~ where - { - /a - { - currentpoint ~ pop ~ - SDict /driver.rightboundary ~ known ~ dup - { - SDict /driver.rightboundary ~ get ~ 2 ~ index ~ lt - { not } - if - } - if - { pop } - { SDict ~ exch /driver.rightboundary ~ exch ~ put } - ifelse ~ - moveto ~ - currentpoint ~ pop ~ - SDict /driver.leftboundary ~ known ~ dup - { - SDict /driver.leftboundary ~ get ~ 2 ~ index ~ gt - { not } - if - } - if - { pop } - { SDict ~ exch /driver.leftboundary ~ exch ~ put } - ifelse - } - put - } - if - } - def - /driver.bordertracking.end - { - /a ~ where { /a { moveto } put } if - /x ~ where { /x { 0 ~ exch ~ rmoveto } put } if ~ - SDict /driver.leftboundary ~ known - { driver.outerbox ~ 0 ~ driver.leftboundary ~ put } - if ~ - SDict /driver.rightboundary ~ known - { driver.outerbox ~ 2 ~ driver.rightboundary ~ put } - if ~ - SDict /driver.bordertracking ~ false ~ put - } - def - /driver.bordertracking.endpage - { - driver.bordertracking - { - driver.bordertracking.end ~ - true ~ setglobal ~ - driver.globaldict - /driver.brokenlink.rect [ driver.outerbox ~ aload ~ pop ] put ~ - driver.globaldict - /driver.brokenlink.skip ~ driver.baselineskip ~ put ~ - driver.globaldict - /driver.brokenlink.dict ~ - driver.link.dict ~ driver.cvs ~ put ~ - false ~ setglobal ~ - mark ~ driver.link.dict ~ cvx ~ exec ~ /Rect - [ - driver.llx ~ - driver.lly ~ - driver.outerbox ~ 2 ~ get ~ driver.linkmargin ~ add ~ - currentpoint ~ exch ~ pop ~ - driver.outerbox ~ driver.rect.ht ~ sub ~ driver.linkmargin ~ sub - ] - /ANN ~ driver.pdfmark - } - if - } - def - /driver.bordertracking.continue - { - /driver.link.dict ~ driver.globaldict - /driver.brokenlink.dict ~ get ~ def - /driver.outerbox ~ driver.globaldict - /driver.brokenlink.rect ~ get ~ def - /driver.baselineskip ~ driver.globaldict - /driver.brokenlink.skip ~ get ~ def ~ - driver.globaldict ~ dup ~ dup - /driver.brokenlink.dict ~ undef - /driver.brokenlink.skip ~ undef - /driver.brokenlink.rect ~ undef ~ - currentpoint - /driver.originy ~ exch ~ def - /driver.originx ~ exch ~ def - /a ~ where - { - /a - { - moveto ~ - SDict ~ - begin ~ - currentpoint ~ driver.originy ~ ne ~ exch ~ - driver.originx ~ ne ~ or - { - driver.save.linkll - /driver.lly ~ - driver.lly ~ driver.outerbox ~ 1 ~ get ~ sub ~ def ~ - driver.bordertracking.begin - } - if ~ - end - } - put - } - if - /x ~ where - { - /x - { - 0 ~ exch ~ rmoveto ~ - SDict~ - begin ~ - currentpoint ~ - driver.originy ~ ne ~ exch ~ driver.originx ~ ne ~ or - { - driver.save.linkll - /driver.lly ~ - driver.lly ~ driver.outerbox ~ 1 ~ get ~ sub ~ def ~ - driver.bordertracking.begin - } - if ~ - end - } - put - } - if - } - def - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% driver.breaklink , -% driver.breaklink.write , -% driver.count , -% driver.currentrect -% } -% Dealing with link breaking itself has multiple stage. The first step is to -% find the |Rect| entry in the dictionary, looping over key--value pairs. -% The first line is handled first, adjusting the rectangle to stay inside the -% text area. The second phase is a loop over the height of the bulk of the -% link area, done on the basis of a number of baselines. Finally, the end of -% the link area is tidied up, again from the boundary of the text area. -% \begin{macrocode} -\@@_postscript_header:n - { - /driver.breaklink - { - pop ~ - counttomark ~ 2 ~ mod ~ 0 ~ eq - { - counttomark /driver.count ~ exch ~ def - { - driver.count ~ 0 ~ eq { exit } if ~ - counttomark ~ 2 ~ roll ~ - 1 ~ index ~ /Rect ~ eq - { - dup ~ 4 ~ array ~ copy ~ - dup ~ dup ~ - 1 ~ get ~ - driver.outerbox ~ driver.rect.ht ~ - driver.linkmargin ~ 2 ~ mul ~ add ~ sub ~ - 3 ~ exch ~ put ~ - dup ~ - driver.outerbox ~ 2 ~ get ~ - driver.linkmargin ~ add ~ - 2 ~ exch ~ put ~ - dup ~ dup ~ - 3 ~ get ~ - driver.outerbox ~ driver.rect.ht ~ - driver.linkmargin ~ 2 ~ mul ~ add ~ add ~ - 1 ~ exch ~ put - /driver.currentrect ~ exch ~ def ~ - driver.breaklink.write - { - driver.currentrect ~ - dup ~ - driver.outerbox ~ 0 ~ get ~ - driver.linkmargin ~ sub ~ - 0 ~ exch ~ put ~ - dup ~ - driver.outerbox ~ 2 ~ get ~ - driver.linkmargin ~ add ~ - 2 ~ exch ~ put ~ - dup ~ dup ~ - 1 ~ get ~ - driver.baselineskip ~ add ~ - 1 ~ exch ~ put ~ - dup ~ dup ~ - 3 ~ get ~ - driver.baselineskip ~ add ~ - 3 ~ exch ~ put ~ - /driver.currentrect ~ exch ~ def ~ - driver.breaklink.write - } - 1 ~ index ~ 3 ~ get ~ - driver.linkmargin ~ 2 ~ mul ~ add ~ - driver.outerbox ~ driver.rect.ht ~ add ~ - 2 ~ index ~ 1 ~ get ~ sub ~ - driver.baselineskip ~ div ~ round ~ cvi ~ 1 ~ sub ~ - exch ~ - repeat ~ - driver.currentrect ~ - dup ~ - driver.outerbox ~ 0 ~ get ~ - driver.linkmargin ~ sub ~ - 0 ~ exch ~ put ~ - dup ~ dup ~ - 1 ~ get ~ - driver.baselineskip ~ add ~ - 1 ~ exch ~ put ~ - dup ~ dup ~ - 3 ~ get ~ - driver.baselineskip ~ add ~ - 3 ~ exch ~ put ~ - dup ~ 2 ~ index ~ 2 ~ get ~ 2 ~ exch ~ put - /driver.currentrect ~ exch ~ def ~ - driver.breaklink.write ~ - SDict /driver.pdfmark.good ~ false ~ put ~ - exit - } - { driver.count ~ 2 ~ sub /driver.count ~ exch ~ def } - ifelse - } - loop - } - if - /ANN - } - def - /driver.breaklink.write - { - counttomark ~ 1 ~ sub ~ - index /_objdef ~ eq - { - counttomark ~ -2 ~ roll ~ - dup ~ wcheck ~ - { - readonly ~ - counttomark ~ 2 ~ roll - } - { pop ~ pop } - ifelse - } - if ~ - counttomark ~ 1 ~ add ~ copy ~ - pop ~ driver.currentrect - /ANN ~ pdfmark - } - def - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% driver.pdfmark , -% driver.pdfmark.good , -% driver.outerbox , -% driver.baselineskip , -% driver.pdfmark.dict -% } -% The business end of breaking links starts by hooking into |pdfmarks|. -% Unlike \pkg{hypdvips}, we avoid altering any links we have not created -% by using a copy of the core |pdfmarks| function. Only mark types which -% are known are altered. At present, this is purely |ANN| marks, which are -% measured relative to the size of the baseline skip. If they are -% more than one apparent line high, breaking is applied. -% \begin{macrocode} -\@@_postscript_header:n - { - /driver.pdfmark - { - SDict /driver.pdfmark.good ~ true ~ put ~ - dup /ANN ~ eq - { - driver.pdfmark.store ~ - driver.pdfmark.dict ~ - begin ~ - Subtype /Link ~ eq ~ - currentdict /Rect ~ known ~ and ~ - SDict /driver.outerbox ~ known ~ and ~ - SDict /driver.baselineskip ~ known ~ and ~ - { - Rect ~ 3 ~ get ~ - driver.linkmargin ~ 2 ~ mul ~ add ~ - driver.outerbox ~ driver.rect.ht ~ add ~ - Rect ~ 1 ~ get ~ sub ~ - driver.baselineskip ~ div ~ round ~ cvi ~ 0 ~ gt - { driver.breaklink } - if - } - if ~ - end ~ - SDict /driver.outerbox ~ undef ~ - SDict /driver.baselineskip ~ undef ~ - currentdict /driver.pdfmark.dict ~ undef ~ - } - if ~ - driver.pdfmark.good - { pdfmark } - { cleartomark } - ifelse - } - def - /driver.pdfmark.store - { - /driver.pdfmark.dict ~ 65534 ~ dict ~ def ~ - counttomark ~ 1 ~ add ~ copy ~ - pop - { - dup ~ mark ~ eq - { - pop ~ - exit - } - { - driver.pdfmark.dict ~ - begin ~ def ~ end - } - ifelse - } - loop - } - def - } -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\l_@@_pdf_content_box} -% The content of an annotation. -% \begin{macrocode} -\box_new:N \l_@@_pdf_content_box -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_pdf_model_box} -% For creating model sizing for links. -% \begin{macrocode} -\box_new:N \l_@@_pdf_model_box -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\g_@@_pdf_annotation_int} -% Needed as objects which are not annotations could be created. -% \begin{macrocode} -\int_new:N \g_@@_pdf_annotation_int -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\driver_pdf_annotation:nnnn, \@@_pdf_annotation:nnnn} -% \begin{macro}{driver.llx, driver.lly, driver.urx, driver.ury} -% Annotations are objects, but we track them separately. Notably, they are -% not in the object data lists. Here, to get the co-ordinates of the -% annotation, we need to have the data collected at the PostScript level. -% That requires a bit of box trickery (effectively a \LaTeXe{} |picture| -% of zero size). Once the data is collected, use it to set up the annotation -% border. There is a split into two parts here to allow an easy way of -% applying the Adobe Reader fix. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_annotation:nnnn #1#2#3#4 - { - \@@_pdf_annotation:nnnn {#1} {#2} {#3} {#4} - \int_gincr:N \g_@@_pdf_object_int - \int_gset_eq:NN \g_@@_pdf_annotation_int \g_@@_pdf_object_int - \@@_pdfmark:x - { - - /_objdef { driver.obj \int_use:N \g_@@_pdf_object_int } - driver.rect ~ - #4 ~ - /ANN - } - } -\cs_new_protected:Npn \@@_pdf_annotation:nnnn #1#2#3#4 - { - \box_move_down:nn {#3} - { \hbox:n { \@@_postscript:n { driver.save.ll } } } - \hbox:n {#4} - \box_move_up:nn {#2} - { - \hbox:n - { - \tex_kern:D \dim_eval:n {#1} \scan_stop: - \@@_postscript:n { driver.save.ur } - } - } - \int_gincr:N \g_@@_pdf_object_int - \int_gset_eq:NN \g_@@_pdf_annotation_int \g_@@_pdf_object_int - \@@_pdfmark:x - { - /_objdef { driver.obj \int_use:N \g_@@_pdf_object_int } - driver.rect - /ANN - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\driver_pdf_annotation_last:} -% Provide the last annotation we created: could get tricky of course if -% other packages are loaded. -% \begin{macrocode} -\cs_new:Npn \driver_pdf_annotation_last: - { { driver.obj \int_use:N \g_@@_pdf_annotation_int } } -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\g_@@_pdf_link_int} -% To track annotations which are links. -% \begin{macrocode} -\int_new:N \g_@@_pdf_link_int -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\g_@@_pdf_link_dict_tl} -% To pass information to the end-of-link function. -% \begin{macrocode} -\tl_new:N \g_@@_pdf_link_dict_tl -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\g_@@_pdf_link_sf_int} -% Needed to save/restore space factor, which is needed to deal with the face -% we need a box. -% \begin{macrocode} -\int_new:N \g_@@_pdf_link_sf_int -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\g_@@_pdf_link_math_bool} -% Needed to save/restore math mode. -% \begin{macrocode} -\bool_new:N \g_@@_pdf_link_math_bool -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\g_@@_pdf_link_bool} -% Track link formation: we cannot nest at all. -% \begin{macrocode} -\bool_new:N \g_@@_pdf_link_bool -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_breaklink_pdfmark_tl} -% Swappable content for link breaking. -% \begin{macrocode} -\tl_new:N \l_@@_breaklink_pdfmark_tl -\tl_set:Nn \l_@@_breaklink_pdfmark_tl { pdfmark } -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\@@_breaklink_postscript:n} -% To allow dropping material unless link breaking is active. -% \begin{macrocode} -\cs_new_protected:Npn \@@_breaklink_postscript:n #1 { } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_breaklink_usebox:N} -% Swappable box unpacking or use. -% \begin{macrocode} -\cs_new_eq:NN \@@_breaklink_usebox:N \box_use:N -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_link_begin_goto:nnw, \driver_pdf_link_begin_user:nnw} -% \begin{macro}{\@@_pdf_link:nw, \@@_pdf_link_aux:nw} -% \begin{macro}{\driver_pdf_link_end:, \@@_pdf_link_end:} -% \begin{macro}{\@@_pdf_link_minima:} -% \begin{macro}{\@@_pdf_link_outerbox:n} -% \begin{macro}{\@@_pdf_link_sf_save:, \@@_pdf_link_sf_restore:} -% \begin{macro} -% { -% driver.linkdp.pad , -% driver.linkht.pad , -% driver.llx, driver.lly , -% driver.ury, driver.ury , -% driver.link.dict , -% driver.outerbox , -% driver.baselineskip -% } -% Links are crated like annotations but with dedicated code to allow for -% adjusting the size of the rectangle. In contrast to \pkg{hyperref}, we -% grab the link content as a box which can then unbox: this allows the same -% interface as for \pdfTeX{}. -% -% Taking the idea of |evenboxes| from \pkg{hypdvips}, we implement a minimum -% box height and depth for link placement. This means that \enquote{underlining} -% with a hyperlink will generally give an even appearance. However, to ensure -% that the full content is always above the link border, we do not allow -% this to be negative (contrast \pkg{hypdvips} approach). The result should -% be similar to \pdfTeX{} in the vast majority of foreseeable cases. -% -% The object number for a link is saved separately from the rest of the -% dictionary as this allows us to insert it just once, at either an -% unbroken link or only in the first line of a broken one. That makes the -% code clearer but also avoids a low-level PostScript error with the code -% as taken from \pkg{hypdvips}. -% -% Getting the outer dimensions of the text area may be better using a two-pass -% approach and |\tex_savepos:D|. That plus format mode are still to re-examine. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_link_begin_goto:nnw #1#2 - { \@@_pdf_link_begin:nw { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> } } -\cs_new_protected:Npn \driver_pdf_link_begin_user:nnw #1#2 - { \@@_pdf_link_begin:nw {#1#2} } -\cs_new_protected:Npn \@@_pdf_link_begin:nw #1 - { - \bool_if:NF \g_@@_pdf_link_bool - { \@@_pdf_link_begin_aux:nw {#1} } - } -\cs_new_protected:Npn \@@_pdf_link_begin_aux:nw #1 - { - \bool_gset_true:N \g_@@_pdf_link_bool - \@@_postscript:n - { /driver.link.dict ( #1 ) def } - \tl_gset:Nn \g_@@_pdf_link_dict_tl {#1} - \@@_pdf_link_sf_save: - \mode_if_math:TF - { \bool_gset_true:N \g_@@_pdf_link_math_bool } - { \bool_gset_false:N \g_@@_pdf_link_math_bool } - \hbox_set:Nw \l_@@_pdf_content_box - \@@_pdf_link_sf_restore: - \bool_if:NT \g_@@_pdf_link_math_bool - { \c_math_toggle_token } - } -\cs_new_protected:Npn \driver_pdf_link_end: - { - \bool_if:NT \g_@@_pdf_link_bool - { \@@_pdf_link_end: } - } -\cs_new_protected:Npn \@@_pdf_link_end: - { - \bool_if:NT \g_@@_pdf_link_math_bool - { \c_math_toggle_token } - \@@_pdf_link_sf_save: - \hbox_set_end: - \@@_pdf_link_minima: - \hbox_set:Nn \l_@@_pdf_model_box { Gg } - \exp_args:Nx \@@_driver_link_outerbox:n - { -%<*initex> - \l_galley_total_left_margin_dim -%</initex> -%<*package> - \int_if_odd:nTF { \value { page } } - { \oddsidemargin } - { \evensidemargin } -%</package> - } - \box_move_down:nn { \box_dp:N \l_@@_pdf_content_box } - { \hbox:n { \@@_postscript:n { driver.save.linkll } } } - \@@_breaklink_postscript:n { driver.bordertracking.begin } - \@@_breaklink_usebox:N \l_@@_pdf_content_box - \@@_breaklink_postscript:n { driver.bordertracking.end } - \box_move_up:nn { \box_ht:N \l_@@_pdf_content_box } - { - \hbox:n - { \@@_postscript:n { driver.save.linkur } } - } - \int_gincr:N \g_@@_pdf_object_int - \int_gset_eq:NN \g_@@_pdf_link_int \g_@@_pdf_object_int - \@@_postscript:x - { - mark - /_objdef { driver.obj \int_use:N \g_@@_pdf_link_int } - \g_@@_pdf_link_dict_tl \c_space_tl - driver.rect - /ANN ~ \l_@@_breaklink_pdfmark_tl - } - \@@_pdf_link_sf_restore: - \bool_gset_false:N \g_@@_pdf_link_bool - } -\cs_new_protected:Npn \@@_pdf_link_minima: - { - \hbox_set:Nn \l_@@_pdf_model_box { Gg } - \@@_postscript:x - { - /driver.linkdp.pad ~ - \dim_to_decimal:n - { - \dim_max:nn - { - \box_dp:N \l_@@_pdf_model_box - - \box_dp:N \l_@@_pdf_content_box - } - { 0pt } - } ~ - driver.pt.dvi ~ def - /driver.linkht.pad ~ - \dim_to_decimal:n - { - \dim_max:nn - { - \box_ht:N \l_@@_pdf_model_box - - \box_ht:N \l_@@_pdf_content_box - } - { 0pt } - } ~ - driver.pt.dvi ~ def - } - } -\cs_new_protected:Npn \@@_driver_link_outerbox:n #1 - { - \@@_postscript:x - { - /driver.outerbox - [ - \dim_to_decimal:n {#1} ~ - \dim_to_decimal:n { -\box_dp:N \l_@@_pdf_model_box } ~ -%<*initex> - \dim_to_decimal:n { #1 + \l_galley_text_width_dim } ~ -%</initex> -%<*package> - \dim_to_decimal:n { #1 + \textwidth } ~ -%</package> - \dim_to_decimal:n { \box_ht:N \l_@@_pdf_model_box } - ] - [ exch { driver.pt.dvi } forall ] def - /driver.baselineskip ~ - \dim_to_decimal:n { \tex_baselineskip:D } ~ dup ~ 0 ~ gt - { driver.pt.dvi ~ def } - { pop ~ pop } - ifelse - } - } -\cs_new_protected:Npn \@@_pdf_link_sf_save: - { - \int_gset:Nn \g_@@_pdf_link_sf_int - { - \mode_if_horizontal:TF - { \tex_spacefactor:D } - { 0 } - } - } -\cs_new_protected:Npn \@@_pdf_link_sf_restore: - { - \mode_if_horizontal:T - { - \int_compare:nNnT \g_@@_pdf_link_sf_int > { 0 } - { \int_set_eq:NN \tex_spacefactor:D \g_@@_pdf_link_sf_int } - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@makecol@hook} -% Hooks to allow link breaking: something will be needed in format mode -% at some stage. At present this code is disabled as there is an open -% question about the name of the hook: to be resolved at the \LaTeXe{} -% end. -% \begin{macrocode} -%<*package> -\use_none:n - { - \cs_if_exist:NT \@makecol@hook - { - \tl_put_right:Nn \@makecol@hook - { - \box_if_empty:NF \@cclv - { - \vbox_set:Nn \@cclv - { - \@@_postscript:n - { - driver.globaldict /driver.brokenlink.rect ~ known - { driver.bordertracking.continue } - if - } - \vbox_unpack_drop:N \@cclv - \@@_postscript:n - { driver.bordertracking.endpage } - } - } - } - \tl_set:Nn \l_@@_breaklink_pdfmark_tl { driver.pdfmark } - \cs_set_eq:NN \@@_breaklink_postscript:n \@@_postscript:n - \cs_set_eq:NN \@@_breaklink_usebox:N \hbox_unpack:N - } - } -%</package> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_link_last:} -% The same as annotations, but with a custom integer. -% \begin{macrocode} -\cs_new:Npn \driver_pdf_link_last: - { { driver.obj \int_use:N \g_@@_pdf_link_int } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_link_margin:n} -% Convert to big points and pass to PostScript. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_link_margin:n #1 - { - \@@_postscript:x - { - /driver.linkmargin { \dim_to_decimal:n {#1} ~ driver.pt.dvi } def - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_destination:nn, \driver_pdf_destination_rectangle:nn} -% Here, we need to turn the zoom into a scale. We also need to know where -% the current anchor point actually is: worked out in PostScript. For the -% rectangle version, we have a bit more PostScript: we need two points. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_destination:nn #1#2 - { - \@@_postscript:n { driver.dest.anchor } - \@@_pdfmark:x - { - /View - [ - \str_case:nnF {#2} - { - { xyz } { /XYZ ~ driver.dest.point ~ null } - { fit } { /Fit } - { fitb } { /FitB } - { fitbh } { /FitBH ~ driver.dest.y } - { fitbv } { /FitBV ~ driver.dest.x } - { fith } { /FitH ~ driver.dest.y } - { fitv } { /FitV ~ driver.dest.x } - } - { - /XYZ ~ driver.dest.point ~ \fp_eval:n { (#2) / 100 } - } - ] - /Dest ( \exp_not:n {#1} ) cvn - /DEST - } - } -\cs_new_protected:Npn \driver_pdf_destination_rectangle:nn #1#2 - { - \group_begin: - \hbox_set:Nn \l_@@_internal_box {#2} - \box_move_down:nn - { \box_dp:N \l_@@_internal_box } - { \hbox:n { \@@_postscript:n { driver.save.ll } } } - \box_use:N \l_@@_internal_box - \box_move_up:nn - { \box_ht:N \l_@@_internal_box } - { \hbox:n { \@@_postscript:n { driver.save.ur } } } - \@@_pdfmark:n - { - /View - [ - /FitR ~ - driver.llx ~ driver.lly ~ driver.dest2device ~ - driver.urx ~ driver.ury ~ driver.dest2device - ] - /Dest ( #1 ) cvn - /DEST - } - \group_end: - } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Structure} -% -% \begin{macro}{\driver_pdf_compresslevel:n} -% \begin{macro}{\driver_pdf_compress_objects:n} -% These are all no-ops. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_compresslevel:n #1 { } -\cs_new_protected:Npn \driver_pdf_compress_objects:n #1 { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% {\driver_pdf_version_major_gset:n, \driver_pdf_version_minor_gset:n} -% Data not available! -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_version_major_gset:n #1 { } -\cs_new_protected:Npn \driver_pdf_version_minor_gset:n #1 { } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\driver_pdf_version_major:, \driver_pdf_version_minor:} -% Data not available! -% \begin{macrocode} -\cs_new:Npn \driver_pdf_version_major: { -1 } -\cs_new:Npn \driver_pdf_version_minor: { -1 } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</dvips> -% \end{macrocode} -% -% \subsection{\texttt{pdfmode} driver} -% -% \begin{macrocode} -%<*pdfmode> -% \end{macrocode} -% -% \subsubsection{Annotations} -% -% \begin{macro}{\driver_pdf_annotation:nnnn} -% Simply pass the raw data through, just dealing with evaluation of dimensions. -% \begin{macrocode} -\cs_new_protected:Npx \driver_pdf_annotation:nnnn #1#2#3#4 - { - \cs_if_exist:NTF \tex_pdfextension:D - { \tex_pdfextension:D annot ~ } - { \tex_pdfannot:D } - width ~ \exp_not:N \dim_eval:n {#1} ~ - height ~ \exp_not:N \dim_eval:n {#2} ~ - depth ~ \exp_not:N \dim_eval:n {#3} ~ - {#4} - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\driver_pdf_annotation_last:} -% A tiny amount of extra data gets added here. -% \begin{macrocode} -\cs_new:Npx \driver_pdf_annotation_last: - { - \exp_not:N \tex_the:D - \cs_if_exist:NTF \tex_pdffeedback:D - { \exp_not:N \tex_pdffeedback:D annot ~ } - { \exp_not:N \tex_pdflastannot:D } - 0 ~ R - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% {\driver_pdf_link_begin_goto:nnw, \driver_pdf_link_begin_user:nnw} -% \begin{macro}{\@@_pdf_link_begin:nnnw} -% \begin{macro}{\driver_pdf_link_end:} -% Links are all created using the same internals. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_link_begin_goto:nnw #1#2 - { \@@_pdf_link_begin:nnnw {#1} { goto~name } {#2} } -\cs_new_protected:Npn \driver_pdf_link_begin_user:nnw #1#2 - { \@@_pdf_link_begin:nnnw {#1} { user } {#2} } -\cs_new_protected:Npx \@@_pdf_link_begin:nnnw #1#2#3 - { - \cs_if_exist:NTF \tex_pdfextension:D - { \tex_pdfextension:D startlink ~ } - { \tex_pdfstartlink:D } - attr {#1} - #2 {#3} - } -\cs_new_protected:Npx \driver_pdf_link_end: - { - \cs_if_exist:NTF \tex_pdfextension:D - { \tex_pdfextension:D endlink \scan_stop: } - { \tex_pdfendlink:D } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\driver_pdf_link_last:} -% Formatted for direct use. -% \begin{macrocode} -\cs_new:Npx \driver_pdf_link_last: - { - \exp_not:N \tex_the:D - \cs_if_exist:NTF \tex_pdffeedback:D - { \exp_not:N \tex_pdffeedback:D lastlink \scan_stop: } - { \exp_not:N \tex_pdflastlink:D } - ~ 0 ~ R - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_link_margin:n} -% A simple task: pass the data to the primitive. -% \begin{macrocode} -\cs_new_protected:Npx \driver_pdf_link_margin:n #1 - { - \cs_if_exist:NTF \tex_pdfvariable:D - { \exp_not:N \tex_pdfvariable:D linkmargin } - { \exp_not:N \tex_pdflinkmargin:D } - \exp_not:N \dim_eval:n {#1} \scan_stop: - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_destination:nn, \driver_pdf_destination_rectangle:nn} -% A simple task: pass the data to the primitive. The |\scan_stop:| deals -% with the danger of an unterminated keyword. The zoom given here is a -% percentage, but we need to pass it as \emph{per mille}. The rectangle -% version is also easy as everything is build in. -% \begin{macrocode} -\cs_new_protected:Npx \driver_pdf_destination:nn #1#2 - { - \cs_if_exist:NTF \tex_pdfextension:D - { \exp_not:N \tex_pdfextension:D dest ~ } - { \exp_not:N \tex_pdfdest:D } - name {#1} - \exp_not:N \str_case:nnF {#2} - { - { xyz } { xyz } - { fit } { fit } - { fitb } { fitb } - { fitbh } { fitbh } - { fitbv } { fitbv } - { fith } { fith } - { fitv } { fitv } - } - { xyz ~ zoom \exp_not:N \fp_eval:n { #2 * 10 } } - \scan_stop: - } -\cs_new_protected:Npx \driver_pdf_destination_rectangle:nn #1#2 - { - \group_begin: - \hbox_set:Nn \l_@@_internal_box {#2} - \cs_if_exist:NTF \tex_pdfextension:D - { \exp_not:N \tex_pdfextension:D dest ~ } - { \exp_not:N \tex_pdfdest:D } - name {#1} - fitr ~ - width \exp_not:N \box_wd:N \l_@@_internal_box - height \exp_not:N \box_ht:N \l_@@_internal_box - depth \exp_not:N \box_dp:N \l_@@_internal_box - \box_use:N \l_@@_internal_box - \group_end: - } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Catalogue entries} -% -% \begin{macro}{\driver_pdf_catalog_gput:nn, \driver_pdf_info_gput:nn} -% \begin{macrocode} -\cs_new_protected:Npx \driver_pdf_catalog_gput:nn #1#2 - { - \cs_if_exist:NTF \tex_pdfextension:D - { \tex_pdfextension:D catalog } - { \tex_pdfcatalog:D } - { / #1 ~ #2 } - } -\cs_new_protected:Npx \driver_pdf_info_gput:nn #1#2 - { - \cs_if_exist:NTF \tex_pdfextension:D - { \tex_pdfextension:D info } - { \tex_pdfinfo:D } - { / #1 ~ #2 } - } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Objects} -% -% \begin{variable}{\g_@@_pdf_object_prop} -% For tracking objects to allow finalisation. -% \begin{macrocode} -\prop_new:N \g_@@_pdf_object_prop -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\driver_pdf_object_new:nn} -% \begin{macro}[EXP]{\driver_pdf_object_ref:n} -% Declaring objects means reserving at the PDF level plus starting -% tracking. -% \begin{macrocode} -\group_begin: - \cs_set_protected:Npn \@@_tmp:w #1#2 - { - \cs_new_protected:Npx \driver_pdf_object_new:nn ##1##2 - { - #1 reserveobjnum ~ - \int_const:cn - { c_@@_pdf_object_ \exp_not:N \tl_to_str:n {##1} _int } - {#2} - \prop_gput:Nnn \exp_not:N \g_@@_pdf_object_prop {##1} {##2} - } - } - \cs_if_exist:NTF \tex_pdfextension:D - { - \@@_tmp:w - { \tex_pdfextension:D obj ~ } - { \exp_not:N \tex_pdffeedback:D lastobj } - } - { \@@_tmp:w { \tex_pdfobj:D } { \tex_pdflastobj:D } } -\group_end: -\cs_new:Npn \driver_pdf_object_ref:n #1 - { \int_use:c { c_@@_pdf_object_ \tl_to_str:n {#1} _int } ~ 0 ~ R } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\driver_pdf_object_write:nn} -% \begin{macro}[EXP]{\@@_exp_not_i:nn, \@@_exp_not_ii:nn} -% Writing the data needs a little information about the structure of the -% object. -% \begin{macrocode} -\group_begin: - \cs_set_protected:Npn \@@_tmp:w #1 - { - \cs_new_protected:Npn \driver_pdf_object_write:nn ##1##2 - { - \tex_immediate:D #1 useobjnum ~ - \int_use:c - { c_@@_pdf_object_ \tl_to_str:n {##1} _int } - \str_case_e:nn - { \prop_item:Nn \g_@@_pdf_object_prop {##1} } - { - { array } { { [ ~ \exp_not:n {##2} ~ ] } } - { dict } { { << ~ \exp_not:n {##2} ~ >> } } - { fstream } - { - stream ~ attr ~ { \@@_exp_not_i:nn ##2 } ~ - file ~ { \@@_exp_not_ii:nn ##2 } - } - { stream } - { - stream ~ attr ~ { \@@_exp_not_i:nn ##2 } ~ - { \@@_exp_not_ii:nn ##2 } - } - } - } - } - \cs_if_exist:NTF \tex_pdfextension:D - { \@@_tmp:w { \tex_pdfextension:D obj ~ } } - { \@@_tmp:w { \tex_pdfobj:D } } -\group_end: -\cs_new:Npn \@@_exp_not_i:nn #1#2 { \exp_not:n {#1} } -\cs_new:Npn \@@_exp_not_ii:nn #1#2 { \exp_not:n {#2} } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsubsection{Structure} -% -% \begin{macro}{\driver_pdf_compresslevel:n} -% \begin{macro}{\driver_pdf_compress_objects:n} -% \begin{macro}{\@@_pdf_objcompresslevel:n} -% Simply pass data to the engine. -% \begin{macrocode} -\cs_new_protected:Npx \driver_pdf_compresslevel:n #1 - { - \exp_not:N \tex_global:D - \cs_if_exist:NTF \tex_pdfcompresslevel:D - { \tex_pdfcompresslevel:D } - { \tex_pdfvariable:D compresslevel } - \exp_not:N \int_value:w \exp_not:N \int_eval:n {#1} \scan_stop: - } -\cs_new_protected:Npn \driver_pdf_compress_objects:n #1 - { - \str_if_eq:nnTF {#1} { true } - { \@@_pdf_objcompresslevel:n { 2 } } - { \@@_pdf_objcompresslevel:n { 0 } } - } -\cs_new_protected:Npx \@@_pdf_objcompresslevel:n #1 - { - \exp_not:N \tex_global:D - \cs_if_exist:NTF \tex_pdfobjcompresslevel:D - { \tex_pdfobjcompresslevel:D } - { \tex_pdfvariable:D objcompresslevel } - #1 \scan_stop: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% {\driver_pdf_version_major_gset:n, \driver_pdf_version_minor_gset:n} -% At present, we don't have a primitive for the major version in \pdfTeX{}, -% but we anticipate one \ldots -% \begin{macrocode} -\cs_new_protected:Npx \driver_pdf_version_major_gset:n #1 - { - \cs_if_exist:NTF \tex_pdfvariable:D - { - \int_compare:nNnT \tex_luatexversion:D > { 106 } - { - \exp_not:N \tex_global:D \tex_pdfvariable:D majorversion - \exp_not:N \int_eval:n {#1} \scan_stop: - } - } - { - \cs_if_exist:NT \tex_pdfmajorversion:D - { - \exp_not:N \tex_global:D \tex_pdfmajorversion:D - \exp_not:N \int_eval:n {#1} \scan_stop: - } - } - } -\cs_new_protected:Npx \driver_pdf_version_minor_gset:n #1 - { - \exp_not:N \tex_global:D - \cs_if_exist:NTF \tex_pdfminorversion:D - { \exp_not:N \tex_pdfminorversion:D } - { \tex_pdfvariable:D minorversion } - \exp_not:N \int_eval:n {#1} \scan_stop: - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\driver_pdf_version_major:, \driver_pdf_version_minor:} -% At present, we don't have a primitive for the major version! -% \begin{macrocode} -\cs_new:Npx \driver_pdf_version_major: - { - \cs_if_exist:NTF \tex_pdfvariable:D - { - \int_compare:nNnTF \tex_luatexversion:D > { 106 } - { \exp_not:N \tex_the:D \tex_pdfvariable:D majorversion } - { 1 } - } - { - \cs_if_exist:NTF \tex_pdfmajorversion:D - { \exp_not:N \tex_the:D \tex_pdfmajorversion:D } - { 1 } - } - } -\cs_new:Npx \driver_pdf_version_minor: - { - \exp_not:N \tex_the:D - \cs_if_exist:NTF \tex_pdfminorversion:D - { \exp_not:N \tex_pdfminorversion:D } - { \tex_pdfvariable:D minorversion } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</pdfmode> -% \end{macrocode} -% -% \subsection{\texttt{dvipdfmx} driver} -% -% \begin{macrocode} -%<*dvipdfmx|xdvipdfmx> -% \end{macrocode} -% -% \begin{macro}{\@@_pdf:n, \@@_pdf:x} -% A generic function for the driver PDF specials: used where we can. -% \begin{macrocode} -\cs_new_protected:Npx \@@_pdf:n #1 - { \@@_literal:n { pdf: #1 } } -\cs_generate_variant:Nn \@@_pdf:n { x } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Catalogue entries} -% -% \begin{macro}{\driver_pdf_catalog_gput:nn, \driver_pdf_info_gput:nn} -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_catalog_gput:nn #1#2 - { \@@_pdf:n { put ~ @catalog << /#1 ~ #2 >> } } -\cs_new_protected:Npn \driver_pdf_info_gput:nn #1#2 - { \@@_pdf:n { docinfo << /#1 ~ #2 >> } } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Objects} -% -% \begin{variable}{\g_@@_pdf_object_int, \g_@@_pdf_object_prop} -% For tracking objects to allow finalisation. -% \begin{macrocode} -\int_new:N \g_@@_pdf_object_int -\prop_new:N \g_@@_pdf_object_prop -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\driver_pdf_object_new:nn} -% \begin{macro}[EXP]{\driver_pdf_object_ref:n} -% Objects are tracked at the macro level, but we don't have to do anything -% at this stage. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_object_new:nn #1#2 - { - \int_gincr:N \g_@@_pdf_object_int - \int_const:cn - { g_@@_pdf_object_ \tl_to_str:n {#1} _int } - { \g_@@_pdf_object_int } - \prop_gput:Nnn \g_@@_pdf_object_prop {#1} {#2} - } -\cs_new:Npn \driver_pdf_object_ref:n #1 - { @driver.obj \int_use:c { g_@@_pdf_object_ \tl_to_str:n {#1} _int } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\driver_pdf_object_write:nn} -% \begin{macro}{\@@_pdf_object_write:nnn} -% \begin{macro} -% { -% \@@_pdf_object_write_array:nn , -% \@@_pdf_object_write_dict:nn , -% \@@_pdf_object_write_fstream:nn , -% \@@_pdf_object_write_stream:nn -% } -% \begin{macro}{\@@_pdf_object_write_stream:nnnn} -% This is where we choose the actual type. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_object_write:nn #1#2 - { - \exp_args:Nx \@@_pdf_object_write:nnn - { \prop_item:Nn \g_@@_pdf_object_prop {#1} } {#1} {#2} - } -\cs_new_protected:Npn \@@_pdf_object_write:nnn #1#2#3 - { \use:c { @@_pdf_object_write_ #1 :nn } {#2} {#3} } -\cs_new_protected:Npn \@@_pdf_object_write_array:nn #1#2 - { - \@@_pdf:x - { - obj ~ \driver_pdf_object_ref:n {#1} ~ - [ ~ \exp_not:n {#2} ~ ] - } - } -\cs_new_protected:Npn \@@_pdf_object_write_dict:nn #1#2 - { - \@@_pdf:x - { - obj ~ \driver_pdf_object_ref:n {#1} ~ - << ~ \exp_not:n {#2} ~ >> - } - } -\cs_new_protected:Npn \@@_pdf_object_write_fstream:nn #1#2 - { \@@_pdf_object_write_stream:nnnn { f } {#1} #2 } -\cs_new_protected:Npn \@@_pdf_object_write_stream:nn #1#2 - { \@@_pdf_object_write_stream:nnnn { } {#1} #2 } -\cs_new_protected:Npn \@@_pdf_object_write_stream:nnnn #1#2#3#4 - { - \@@_pdf:x - { - #1 stream ~ \driver_pdf_object_ref:n {#2} ~ - ( \exp_not:n {#4} ) ~ << \exp_not:n {#3} >> - - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \subsubsection{Annotations} -% -% \begin{variable}{\g_@@_landscape_bool} -% There is a bug in \texttt{(x)dvipdfmx} which means annotations do -% not rotate. As such, we need to know if landscape is active. -% \begin{macrocode} -\bool_new:N \g_@@_landscape_bool -%<*package> -\AtBeginDocument - { - \cs_if_exist:NT \landscape - { - \tl_put_right:Nn \landscape - { \bool_gset_true:N \g_@@_landscape_bool } - \tl_put_left:Nn \endlandscape - { \bool_gset_false:N \g_@@_landscape_bool } - } - } -%</package> -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\g_@@_pdf_annotation_int} -% Needed as objects which are not annotations could be created. -% \begin{macrocode} -\int_new:N \g_@@_pdf_annotation_int -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\driver_pdf_annotation:nnnn, \@@_pdf_annotation:nnnn} -% Simply pass the raw data through, just dealing with evaluation of dimensions. -% The only wrinkle is landscape: we have to adjust by hand. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_annotation:nnnn #1#2#3#4 - { - \bool_if:NTF \g_@@_landscape_bool - { - \box_move_up:nn {#2} - { - \vbox:n - { - \@@_pdf_annotation:nnnn - { #2 + #3 } {#1} { 0pt } {#4} - } - } - } - { \@@_pdf_annotation:nnnn {#1} {#2} {#3} {#4} } - } -\cs_new_protected:Npn \@@_pdf_annotation:nnnn #1#2#3#4 - { - \int_gincr:N \g_@@_pdf_object_int - \int_gset_eq:NN \g_@@_pdf_annotation_int \g_@@_pdf_object_int - \@@_pdf:x - { - ann ~ @driver.obj \int_use:N \g_@@_pdf_object_int \c_space_tl - width ~ \dim_eval:n {#1} ~ - height ~ \dim_eval:n {#2} ~ - depth ~ \dim_eval:n {#3} ~ - << #4 >> - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% {\driver_pdf_link_begin_goto:nnw, \driver_pdf_link_begin_user:nnw} -% \begin{macro}{\@@_pdf_link_begin:n} -% \begin{macro}{\driver_pdf_link_end:} -% All created using the same internals. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_link_begin_goto:nnw #1#2 - { \@@_pdf_link_begin:n { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> } } -\cs_new_protected:Npn \driver_pdf_link_begin_user:nnw #1#2 - { \@@_pdf_link_begin:n {#1#2} } -\cs_new_protected:Npn \@@_pdf_link_begin:n #1 - { - \@@_pdf:n - { - bann - << - /Type /Annot - #1 - >> - } - } -\cs_new_protected:Npn \driver_pdf_link_end: - { \@@_pdf:n { eann } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\driver_pdf_link_last:} -% Data not available. -% \begin{macrocode} -\cs_new:Npn \driver_pdf_link_last: { } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_link_margin:n} -% Pass to \texttt{dvipdfmx}. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_link_margin:n #1 - { \@@_literal:x { dvipdfmx:config~g~ \dim_eval:n {#1} } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\driver_pdf_destination:nn, \driver_pdf_destination_rectangle:nn} -% Here, we need to turn the zoom into a scale. The method for \texttt{FitR} -% is from Alexander Grahn: the idea is to avoid needing to do any calculations -% in \TeX{} by using the driver data for \texttt{@xpos} and \texttt{@ypos}. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_destination:nn #1#2 - { - \@@_pdf:x - { - dest ~ ( \exp_not:n {#1} ) - [ - @thispage - \str_case:nnF {#2} - { - { xyz } { /XYZ ~ @xpos ~ @ypos ~ null } - { fit } { /Fit } - { fitb } { /FitB } - { fitbh } { /FitBH } - { fitbv } { /FitBV ~ @xpos } - { fith } { /FitH ~ @ypos } - { fitv } { /FitV ~ @xpos } - } - { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } - ] - } - } -\cs_new_protected:Npn \driver_pdf_destination_rectangle:nn #1#2 - { - \group_begin: - \hbox_set:Nn \l_@@_internal_box {#2} - \box_move_down:nn { \box_dp:N \l_@@_internal_box } - { - \hbox:n - { - \@@_pdf:n { obj ~ @driver_#1_llx ~ @xpos } - \@@_pdf:n { obj ~ @driver_#1_lly ~ @ypos } - } - } - \box_use:N \l_@@_internal_box - \box_move_up:nn { \box_ht:N \l_@@_internal_box } - { - \hbox:n - { - \@@_pdf:n - { - dest ~ (#1) - [ - @thispage - /FitR ~ - @driver_#1_llx ~ @driver_#1_lly ~ - @xpos ~ @ypos - ] - } - } - } - \group_end: - } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Structure} -% -% \begin{macro}{\driver_pdf_compresslevel:n} -% \begin{macro}{\driver_pdf_compress_objects:n} -% Pass data to the driver: these are a one-shot. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_compresslevel:n #1 - { \@@_literal:x { dvipdfmx:config~z~ \int_eval:n {#1} } } -\cs_new_protected:Npn \driver_pdf_compress_objects:n #1 - { - \str_if_eq:nnF {#1} { true } - { \@@_literal:n { dvipdfmx:config~C~0x40 } } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% {\driver_pdf_version_major_gset:n, \driver_pdf_version_minor_gset:n} -% We start with the assumption that the default is active. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_version_major:n #1 - { - \cs_gset:Npx \driver_pdf_version_major: { \int_eval:n {#1} } - \@@_literal:x { pdf:majorversion \driver_pdf_version_major: } - } -\cs_new_protected:Npn \driver_pdf_version_minor:n #1 - { - \cs_gset:Npx \driver_pdf_version_minor: { \int_eval:n {#1} } - \@@_literal:x { pdf:minorversion \driver_pdf_version_minor: } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\driver_pdf_version_major:, \driver_pdf_version_minor:} -% We start with the assumption that the default is active. -% \begin{macrocode} -\cs_new:Npn \driver_pdf_version_major: { 1 } -\cs_new:Npn \driver_pdf_version_minor: { 5 } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</dvipdfmx|xdvipdfmx> -% \end{macrocode} -% -% \subsection{\texttt{dvisvgm} driver} -% -% \begin{macrocode} -%<*dvisvgm> -% \end{macrocode} -% -% \subsubsection{Catalogue entries} -% -% \begin{macro}{\driver_pdf_catalog_gput:nn, \driver_pdf_info_gput:nn} -% No-op. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_catalog_gput:nn #1#2 { } -\cs_new_protected:Npn \driver_pdf_info_gput:nn #1#2 { } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Objects} -% -% \begin{macro}{\driver_pdf_object_new:nn} -% \begin{macro}[EXP]{\driver_pdf_object_ref:n} -% \begin{macro}{\driver_pdf_object_write:nn} -% All no-ops here. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_object_new:nn #1#2 { } -\cs_new:Npn \driver_pdf_object_ref:n #1 { } -\cs_new_protected:Npn \driver_pdf_object_write:nn #1#2 { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \subsubsection{Structure} -% -% \begin{macro}{\driver_pdf_compresslevel:n} -% \begin{macro}{\driver_pdf_compress_objects:n} -% These are all no-ops. -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_compresslevel:n #1 { } -\cs_new_protected:Npn \driver_pdf_compress_objects:n #1 { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% {\driver_pdf_version_major_gset:n, \driver_pdf_version_minor_gset:n} -% Data not available! -% \begin{macrocode} -\cs_new_protected:Npn \driver_pdf_version_major_gset:n #1 { } -\cs_new_protected:Npn \driver_pdf_version_minor_gset:n #1 { } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\driver_pdf_version_major:, \driver_pdf_version_minor:} -% Data not available! -% \begin{macrocode} -\cs_new:Npn \driver_pdf_version_major: { -1 } -\cs_new:Npn \driver_pdf_version_minor: { -1 } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</dvisvgm> -% \end{macrocode} -% -% \begin{macrocode} -%</initex|package> -% \end{macrocode} -% -% \end{implementation} -% -% \PrintIndex |