summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2022-01-13 21:05:04 +0000
committerKarl Berry <karl@freefriends.org>2022-01-13 21:05:04 +0000
commit031d7dac6f41c0c635cb8e8fa08cf794a1cc80c1 (patch)
tree16758e614639acf9cd63d4db4f4a618ffe99e853 /Master/texmf-dist/source/latex/pdfmanagement-testphase/l3backend-testphase.dtx
parentd34f367554fea0310b29e2b530b4b1939e21b92b (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.dtx362
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>