diff options
author | Karl Berry <karl@freefriends.org> | 2022-01-13 21:05:04 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-01-13 21:05:04 +0000 |
commit | 031d7dac6f41c0c635cb8e8fa08cf794a1cc80c1 (patch) | |
tree | 16758e614639acf9cd63d4db4f4a618ffe99e853 /Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx | |
parent | d34f367554fea0310b29e2b530b4b1939e21b92b (diff) |
pdfmanagement-testphase (13jan22)
git-svn-id: svn://tug.org/texlive/trunk@61599 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx | 362 |
1 files changed, 355 insertions, 7 deletions
diff --git a/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx index 7c902d8b92f..54f2e089dfd 100644 --- a/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx +++ b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx @@ -45,7 +45,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % @@ -56,27 +56,27 @@ % \begin{macrocode} %<drivers>\ProvidesExplFile %<*dvipdfmx> - {l3backend-testphase-dvipdfmx.def}{2021-08-28}{} + {l3backend-testphase-dvipdfmx.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvipdfmx} %</dvipdfmx> %<*dvips> - {l3backend-testphase-dvips.def}{2021-08-28}{} + {l3backend-testphase-dvips.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvips} %</dvips> %<*dvisvgm> - {l3backend-testphase-dvisvgm.def}{2021-08-28}{} + {l3backend-testphase-dvisvgm.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvisvgm} %</dvisvgm> %<*luatex> - {l3backend-testphase-luatex.def}{2021-08-28}{} + {l3backend-testphase-luatex.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (LuaTeX)} %</luatex> %<*pdftex> - {l3backend-testphase-pdftex.def}{2021-08-28}{} + {l3backend-testphase-pdftex.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (pdfTeX)} %</pdftex> %<*xdvipdfmx> - {l3backend-testphase-xetex.def}{2021-08-28}{} + {l3backend-testphase-xetex.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: XeTeX} %</xdvipdfmx> % \end{macrocode} @@ -1600,6 +1600,354 @@ % \end{macrocode} % \end{macro} % \end{macro} +% \subsection{Structure Destinations} +% Standard destinations consist of a reference to a page in the pdf and instructions +% how to display it---typically they will put a specific location in the left top corner +% of the viewer and so give the impression that a link jumped to the word in this place. +% But in reality they are not connected to the content. +% +% Starting with pdf~2.0 destinations can in a tagged PDF also point to a structure, to a /StructElem object. +% GoTo links can then additionally to the \texttt{/D} key pointing to a +% page destination also point to such a structure destination with an \texttt{/SD} key. +% Programs that e.g. convert such a PDF to html can then create better links. +% (According to the reference, PDF-viewer should prefer the structure destination +% over the page destination, but as far as it is known this isn't done yet.) +% +% Currently structure destinations and GoTo links making use of it could natively only +% be created with the dvipdfmx backend. With pdftex and lualatex it was only possible to create +% a restricted type which used only the \enquote{Fit} mode. Starting with +% \TeX{}live 2022 (earlier in miktex) both engine will knew new keywords which allow +% to create structure destination easily. +% +% The following backend code prepares the use of structure destinations. The general idea is +% that if structure destinations are used, they should be used always. So we define +% alternative commands which can be activated by mapping them to the standard backend commands. +% +% \begin{macro}{\l_pdf_current_structure_destination_tl} +% +% This commands holds the name of the structure object to use in the next command +% which creates a destination. The code which activates structure destinations +% must also ensure that it has a sensible, expandable content. \pkg{tagpdf} for example +% will define it as +% \begin{verbatim} +% \tl_set:Nn \l_pdf_current_structure_destination_tl { __tag/struct/\g__tag_struct_stack_current_tl } +% \end{verbatim} +% \begin{macrocode} +%<*drivers> +\tl_new:N \l_pdf_current_structure_destination_tl +%</drivers> +% \end{macrocode} +% \end{macro} +% +% We will define alternatives for three backend commands: +% \begin{verbatim} +% \__pdf_backend_destination:nn -> \__pdf_backend_structure_destination:nn +% \__pdf_backend_destination:nnnn -> \__pdf_backend_structure_destination:nnnn +% \__pdf_backend_link_begin_goto:nnw -> \__pdf_backend_link_begin_structure_goto:nnw +% \end{verbatim} +% +% Activating means mapping them onto the original commands. Be aware that not +% all engines and compilation routes support structure destinations, for them +% the command will be a no-op. +% +% \begin{macro}{\pdf_activate_structure_destination:} +% \begin{macrocode} +%<*drivers> +\cs_new_protected:Npn \pdf_activate_structure_destination: + { + \cs_gset_eq:NN \@@_backend_destination:nn \@@_backend_structure_destination:nn + \cs_gset_eq:NN \@@_backend_destination:nnnn \@@_backend_structure_destination:nnnn + \cs_gset_eq:NN \@@_backend_link_begin_goto:nnw \@@_backend_link_begin_structure_goto:nnw + } +%</drivers> +% \end{macrocode} +% \end{macro} +% Now the driver dependant parts. +% By default the new commands are simply copies of the original commands. +% We adapt them then for the engines and engine version which provide support +% for structure destinations. +% +% \begin{macrocode} +%<*drivers> +\cs_set_eq:NN \@@_backend_structure_destination:nn \@@_backend_destination:nn +\cs_set_eq:NN \@@_backend_structure_destination:nnnn \@@_backend_destination:nnnn +\cs_set_eq:NN \@@_backend_link_begin_structure_goto:nnw \@@_backend_link_begin_goto:nnw +%</drivers> +% \end{macrocode} +% \begin{macro}{\@@_backend_structure_destination:nn} +% This command is the backend command to create a destination. +% It should in parallel create also a structure destination. +% At first xetex/dvipdfmx. +% The structure destination is an array, so we use obj for it +% so that we can reference it: +% \begin{macrocode} +%<*xdvipdfmx|dvipdfmx> +\cs_set_protected:Npn \@@_backend_structure_destination:nn #1#2 + { + \@@_backend: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 } + { fitr } { /Fit } + } + { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } + ] + } +% \end{macrocode} +% We test if the structure object exist. The object of the structure destination +% gets the name \texttt{@pdf.Sdest.\meta{destname}}, where \meta{destname} is the +% name of the standard destination so that we can reference it in the GoTo links. +% \begin{macrocode} + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \@@_backend:x + { + obj ~ @pdf.SDest.\exp_not:n{#1} + [ + \exp_args:Ne \pdf_object_ref:n { \l_pdf_current_structure_destination_tl } + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ @xpos ~ @ypos ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH } + { fitbv } { /FitBV ~ @xpos } + { fith } { /FitH ~ @ypos } + { fitv } { /FitV ~ @xpos } + { fitr } { /Fit } + } + { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } + ] + } + } + } +% \end{macrocode} +% The second destination command is for the boxed destination. Here we need to define +% an new auxiliary command: +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_structure_destination_aux:nnnn #1#2#3#4 + { + \vbox_to_zero:n + { + \__kernel_kern:n {#4} + \hbox:n + { + \@@_backend:n { obj ~ @pdf_ #2 _llx ~ @xpos } + \@@_backend:n { obj ~ @pdf_ #2 _lly ~ @ypos } + } + \tex_vss:D + } + \__kernel_kern:n {#1} + \vbox_to_zero:n + { + \__kernel_kern:n { -#3 } + \hbox:n + { + \@@_backend:n + { + dest ~ (#2) + [ + @thispage + /FitR ~ + @pdf_ #2 _llx ~ @pdf_ #2 _lly ~ + @xpos ~ @ypos + ] + } +% \end{macrocode} +% Here we add the structure destination to the same box +% \begin{macrocode} + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \@@_backend:x + { + obj ~ @pdf.SDest.\exp_not:n{#2} + [ + \exp_args:Ne \pdf_object_ref:n { \l_pdf_current_structure_destination_tl } + /FitR ~ + @pdf_ #2 _llx ~ @pdf_ #2 _lly ~ + @xpos ~ @ypos + ] + } + } + } + \tex_vss:D + } + \__kernel_kern:n { -#1 } + } +% \end{macrocode} +% And now we redefine the destination command: +% \begin{macrocode} +\cs_set_protected:Npn \@@_backend_structure_destination:nnnn #1#2#3#4 + { + \exp_args:Ne \@@_backend_structure_destination_aux:nnnn + { \dim_eval:n {#2} } {#1} {#3} {#4} + } +% \end{macrocode} +% At last the goto link. +% \begin{macrocode} +\cs_set_protected:Npn \@@_backend_link_begin_structure_goto:nnw #1#2 + { + \@@_backend_link_begin:n { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) /SD~@pdf.SDest.#2 >> } + } +%</xdvipdfmx|dvipdfmx> +% \end{macrocode} +% \end{macro} +% Now pdftex. We only redefine for version 1.40 revision 24 or later. +% \begin{macrocode} +%<*pdftex> +\bool_lazy_and:nnT + { \int_compare_p:nNn {\tex_pdftexversion:D } > {139} } + { \int_compare_p:nNn {\tex_pdftexrevision:D } > {23} } + { + \cs_set_protected:Npn \@@_backend_structure_destination:nn #1#2 + { + \tex_pdfdest:D + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfdest:D + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 + { + \tex_pdfdest:D + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfdest:D + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_link_begin_structure_goto:nnw #1#2 + { + \@@_backend_link_begin:nnnw {#1} { goto~struct~name~{#2}~name } {#2} + } + } +%</pdftex> +% \end{macrocode} +% luatex is quite similar to pdftex. Mostly the test for the version is different +% \begin{macrocode} +%<*luatex> + \int_compare:nNnT {\directlua{tex.print(status.list()["development_id"])} } > {7468} + { + \cs_set_protected:Npn \@@_backend_structure_destination:nn #1#2 + { + \tex_pdfextension:D dest + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfextension:D dest + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 + { + \tex_pdfextension:D dest + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfextension:D dest + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_link_begin_structure_goto:nnw #1#2 + { + \@@_backend_link_begin:nnnw {#1} { goto~struct~name~{#2}~name } {#2} + } + } +%</luatex> +% \end{macrocode} % \subsection{lua code for lualatex} % \begin{macrocode} %<*lua> |