From 96be5ed7ba5ce4406ca538c4b0d18edeec9d7aab Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Tue, 23 Feb 2021 22:38:24 +0000 Subject: pdfmanagement-testphase (23feb21) git-svn-id: svn://tug.org/texlive/trunk@57862 c570f23f-e606-0410-a88d-b1316a301751 --- .../latex/pdfmanagement-testphase/l3pdfannot.dtx | 583 +++++++++++++++++++++ 1 file changed, 583 insertions(+) create mode 100644 Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfannot.dtx (limited to 'Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfannot.dtx') diff --git a/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfannot.dtx b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfannot.dtx new file mode 100644 index 00000000000..94b7a89af87 --- /dev/null +++ b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfannot.dtx @@ -0,0 +1,583 @@ +% \iffalse meta-comment +% +%% File: l3pdfannot.dtx +% +% Copyright (C) 2021 The LaTeX 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 +% +% http://www.latex-project.org/lppl.txt +% +% This file is part of the "LaTeX PDF management testphase 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/pdfresources +% +% for those people who are interested. +% +%<*driver> +\RequirePackage{pdfmanagement-testphase} +\DeclareDocumentMetadata{pdfstandard=A-2b} +\makeatletter +\declare@file@substitution{doc.sty}{doc-v3beta.sty} +\makeatother +\documentclass[full]{l3doc} +\usepackage{array,booktabs,hyperxmp} +\hypersetup{pdfauthor=The LaTeX Project, + pdftitle=l3pdfannot (LaTeX PDF management testphase bundle)} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% \fi +% \providecommand\hook[1]{\texttt{#1}} +% \title{^^A +% The \pkg{l3pdfannot} module\\ Commands for PDF annotations ^^A +% \\ \LaTeX{} PDF management testphase bundle +% } +% +% \author{^^A +% The \LaTeX{} Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Version 0.95a, released 2021-02-21} +% +% \maketitle +% \begin{documentation} +% +% \section{\pkg{l3pdfannot} documentation} +% This module contains a number of commands to create PDF annotations. +% The commands are \emph{not} always simple wrappers around primitive commands. +% To allow external packages to configure links and other annotations, +% some of the commands have hooks and use shared attribute dictionaries. +% For these commands the hooks and dictionaries are selected depending on the \meta{type} +% of the annotation. Currently the module only supports some general commands +% and link annotations. Commands for other annotations like widgets will be added +% later. +% +% \subsection{General annotation commands} +% +% \begin{function}[added = 2019-09-05, updated = 2020-04-14] +% { \pdfannot_box:nnnn } +% \begin{syntax} +% \cs{pdfannot_box:nnnn} \Arg{width} \Arg{height} \Arg{depth} \Arg{annot spec} +% \end{syntax} +% This creates an \texttt{/Type/Annot} object with the given dimensions. +% It doesn't use hooks or dictionaries. +% \end{function} +% \begin{function}[added = 2020-03-30] +% { \pdfannot_box:nnnnn } +% \begin{syntax} +% \cs{pdfannot_box:nnnnn} \Arg{type} \Arg{width} \Arg{height} \Arg{depth} \Arg{annot spec} +% \end{syntax} +% This creates an \texttt{/Type/Annot} object with the given dimensions. +% \meta{type} should be currently one of |link/URI|, |link/GoToR|, +% |link/Launch|, |link/GoTo| or |link/Named| or +% |widget|, it will then insert the attribute dictionary of this type +% additionally to the manually given \meta{annot spec}. +% The attribute dictionaries can be filled with commands described below. +% Hooks are not used. +% \end{function} +% \begin{function}[added = 2019-09-05] +% { \pdfannot_box_ref_last: } +% \begin{syntax} +% \cs{pdfannot_box_ref_last:} +% \end{syntax} +% This retrieves the object reference of the last box annotation created. +% \end{function} +% \subsection{Link annotations} +% Link annotations are special cases of annotations. In the PDF they are identified +% by an |/Subtype/Link| entry in the dictionary. +% Link annotations are quite important as many documents contain links, +% both internal and external. They need a set of special commands for two reasons: +% +% At first the content of links are not only boxes. Links can contain line +% and page breaks (this is normally implemented by the primitive command by +% creating a set of annotations). +% +% At second link annotations are objects that need some +% \enquote{management} as more than one +% package wants to configure their look and behaviour. +% For example \pkg{hyperref}, \pkg{ocgx2} and the code for tagged PDF (currently +% in \pkg{tagpdf}) all want to add keys and values to the dictionaries of +% link annotation and code around links. +% So commands to create link annotations should offer suitable hooks. +% There are three standard places in a link where such hooks are needed: +% At the begin (for example for a structure command or color), +% in the \emph{attr spec} dictionary of the link (for example for the border), and +% at the end of the link (to close a structure or the color group). +% For the begin and end hooks of the LaTeX hook management are predefined and used. +% To add and remove values from the \emph{attr spec} dictionary special +% commands described below are provided. The link commands switch to horizontal mode +% as the commands of pdftex and luatex can't be used in vertical mode. +% +% \begin{variable}{\c_pdfannot_link_types_seq} +% There are currently five link types, \texttt{URI}, \texttt{GoToR}, +% \texttt{Launch}, \texttt{GoTo} or \texttt{Named}, and there are store in this +% constant. +% \end{variable} +% \begin{variable} +% { +% pdfannot/link/TYPE/before, +% pdfannot/link/TYPE/begin, +% pdfannot/link/TYPE/end, +% pdfannot/link/TYPE/after +% } +% These are the hooks used by the following commands. TYPE can be one of +% \texttt{URI}, \texttt{GoToR}, +% \texttt{Launch}, \texttt{GoTo} or \texttt{Named} +% \end{variable} +% \begin{variable} +% { +% link/TYPE +% } +% These is the name of the dictionary used by the following commands. TYPE can be one of +% \texttt{URI}, \texttt{GoToR}, +% \texttt{Launch}, \texttt{GoTo} or \texttt{Named}. The dictionary can be changed +% by the commands \cs{pdfannot_dict_put:nnn} and friends described below. +% \end{variable} +% \begin{function}[added = 2020-03-12, updated = 2020-12-06]{ \pdfannot_link:nnn } +% \begin{syntax} +% \cs{pdfannot_link:nnn} \Arg{type} \Arg{user action spec} \Arg{link text} +% \end{syntax} +% This creates a link around the \meta{link text} with the specified +% \meta{user action spec}\footnote{The wording follows the pdftex documentation}. +% \texttt{/Subtype/Link} is added automatically. +% \meta{type} should be one of \texttt{URI}, \texttt{GoToR}, +% \texttt{Launch}, \texttt{GoTo} or \texttt{Named}. The |GoTo| variant does +% \emph{not} complain if the destination name is not known like +% \cs{pdfannot_link_goto_begin:nw}. +% The attributes stored in the local dictionary +% \texttt{link/}\meta{type} are inserted as +% \emph{attr spec} and the code in the begin and end hook +% \texttt{pdfannot/link/\meta{type}/before} +% and \texttt{pdfannot/link/\meta{type}/after} +% is executed before and after the link (outside the link command) +% while \texttt{pdfannot/link/\meta{type}/begin} +% and \texttt{pdfannot/link/\meta{type}/end} are directly around the link +% text. None of the hooks introduce a group. +% \meta{type} should normally be identical to the value of the |/S| key +% in the action dictionary. +% As example +% \begin{verbatim} +% \pdfannot_dict_put:nnn +% {link/URI} { C } {[1~0~0]} %red border +% \pdfannot_link:nnn { URI } +% { +% /A +% << +% /Type/Action +% /S/URI +% /URI(https://www.latex-project.org) +% >> +% } +% { link text } +% \end{verbatim} +% +% +% \end{function} +% \begin{function}[updated = 2020-12-06]{ \pdfannot_link_begin:nnw, \pdfannot_link_end:n } +% \begin{syntax} +% \cs{pdfannot_link_begin:nnw} \Arg{type} \Arg{user action spec} \meta{content} +% \cs{pdfannot_link_end:n} \Arg{type} +% \end{syntax} +% This creates a link around the \meta{content} with the specified +% \meta{user action spec} (e.g. an /A dictionary with an URI) or +% \meta{destination} (a name as defined with the +% first argument of \cs{pdf_destination:nn}). +% \texttt{/Subtype/Link} is added automatically. +% In contrast to \cs{pdfannot_link:nnn} this function +% does not absorb the argument when finding the \meta{content}, and so can +% be used in circumstances where the \meta{content} may not be a simple +% argument. But beside this, it works similar and use the same hooks. +% As example +% \begin{verbatim} +% \pdfannot_link_begin:nnw { URI } +% { +% /A<< +% /Type/Action +% /S/URI +% /URI(https://www.latex-project.org) +% >> +% } +% link text +% \pdfannot_link_end:n { URI } +% \end{verbatim} +% \end{function} +% \begin{function}[updated = 2020-12-06]{ \pdfannot_link_goto_begin:nw, \pdfannot_link_goto_end: } +% \begin{syntax} +% \cs{pdfannot_link_goto_begin:nw} \Arg{destination} \meta{content} +% \cs{pdfannot_link_goto_end:} +% \end{syntax} +% This is a special, shorter version for links to internal destinations. It always +% uses the hooks and dictionary of the |GoTo| link type. \meta{destination} is a +% destination name. In difference to |\pdfannot_link:nnn { GoTo }| it will complain if +% \meta{destination} is an unknown destination and give the message +% +% |name{ZZZZ} has been referenced but does not exist, replaced by a fixed one| +% +% \end{function} +% \begin{function}[added = 2021-02-14]{ \pdfannot_link_ref_last: } +% This retrieves the object reference a link created previously with the commands +% above. This doesn't work currently with xelatex but a feature request has +% been made. see https://tug.org/pipermail/dvipdfmx/2020-December/000134.html +% \end{function} +% \begin{function}[added = 2021-02-14]{ \pdfannot_ref_last: } +% This retrieves the object reference a previously annotation +% created either with a link or a general box command. When the last was a link +% it won't work with xelatex. +% see https://tug.org/pipermail/dvipdfmx/2020-December/000134.html +% \end{function} +% \begin{NOTE}{UF} +% only annot link or also annot? +% \end{NOTE} +% \begin{function}[added = 2020-03-12]{ \pdfannot_link_margin:n } +% \begin{syntax} +% \cs{pdfannot_link_margin:n} \Arg{dimen} +% \end{syntax} +% This sets the dimension of the link margin. +% \end{function} +% \begin{function}[added = 2020-12-04]{ \pdfannot_dict_put:nnn } +% \begin{syntax} +% \cs{pdfannot_dict_put:nnn} \Arg{dictionary name} \Arg{key} \Arg{value} +% \end{syntax} +% This adds (locally) a key-value to the internal annot dictionaries used +% by the link commands above. +% \meta{dictionary name} should be currently one of \texttt{link/URI}, +% \texttt{link/URI},\texttt{link/GoToR}, \texttt{link/Launch}, +% \texttt{link/GoTo}, \texttt{link/Named}. +% \end{function} +% \begin{function}[added = 2020-12-04]{ \pdfannot_dict_remove:nn } +% \begin{syntax} +% \cs{pdfannot_dict_remove:nn} \Arg{dictionary name} \Arg{key} +% \end{syntax} +% This removes a key-value from the internal annot dictionary +% \meta{dictionary name} should be currently one of +% \texttt{link/URI}, \texttt{link/GoToR}, \texttt{link/Launch}, +% \texttt{link/GoTo}, \texttt{link/Named}. +% \end{function} +% \begin{function}[added = 2020-12-04]{ \pdfannot_dict_show:n } +% \begin{syntax} +% \cs{pdfannot_dict_show:n} \Arg{dictionary name} +% \end{syntax} +% This shows the content of the internal annot dictionary. +% \meta{dictionary name} should be currently one of \texttt{link/URI}, +% \texttt{link/URI}, \texttt{link/GoToR}, \texttt{link/Launch}, +% \texttt{link/GoTo}, \texttt{link/Named}. +% \end{function} +% +% \begin{variable}[added = 2020-12-28]{\l_pdfannot_F_bitset} +% This is a bitset variable, with the named index names suitable for the +% /F flag in an annotation. +% It can be used for example like this: +% \begin{verbatim} +% \pdfannot_dict_put:nnn {link/URI} {F} +% { \bitset_to_arabic:N \l_pdfannot_F_bitset } +% \bitset_set_true:Nn \l_pdfannot_F_bitset {Print} +% \end{verbatim} +% The known keys for the bitset are |Invisible|, |Hidden|, +% |Print|, |NoZoom|, |NoRotate|, |NoView|, |ReadOnly|, |Locked|, |ToggleNoView|, +% |LockedContents| which correspond to the names used in the PDF references. +% \end{variable} +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3pdfannot} implementation} +% +% \begin{macrocode} +%<@@=pdfannot> +%<*header> +\ProvidesExplPackage {l3pdfannot} {2021-02-22} {0.95a} + {PDF-annotations} +\RequirePackage{l3pdfdict} +% +% \end{macrocode} +% Annotations have a /F flag, we provide a public +% bitset for it. +% \begin{macrocode} +%<*package> +\RequirePackage{l3bitset} +\bitset_new:Nn \l_pdfannot_F_bitset + { + Invisible = 1, + Hidden = 2, + Print = 3, + NoZoom = 4, + NoRotate = 5, + NoView = 6, + ReadOnly = 7, + Locked = 8, + ToggleNoView = 9, + LockedContents = 10 + } +% \end{macrocode} +% \begin{NOTE}{UF} +% The code/naming tries to unify general annotations and the special type of +% link under a common name. +% regarding naming and relation of annotation commands see +% https://github.com/FrankMittelbach/AccessiblePDF/issues/73 +% \subsection{Annotations / backend} +% The backend commands are in l3backend: +% \cs{__pdf_backend_annotation:nnnn} and \cs{__pdf_backend_annotation_last:} +% \cs{__pdf_backend_link_begin_user:nnw}, etc +% \end{NOTE} +% +% \subsection{ General Annotations } +% \begin{variable} +% { \g_@@_use_lastlink_bool } +% The pdf engines have two different primitive commands to refer to the last created +% annotation: one for links, one for boxed annotation. We use a boolean to decide +% which one should be used, so that only one user command is needed. +% \begin{macrocode} +\bool_new:N \g_@@_use_lastlink_bool +% \end{macrocode} +% \end{variable} +% \begin{NOTE}{UF} +% type or not type? Syntax for type? +% should there be a version without type? +% \end{NOTE} + +% \begin{macrocode} +\cs_new_protected:Npn \pdfannot_box:nnnn #1 #2 #3 #4 + { + \__pdf_backend_annotation:nnnn {#1}{#2}{#3}{#4} + \bool_gset_false:N\g_@@_use_lastlink_bool + } + +\cs_new:Npn \pdfannot_box_ref_last: + { + \__pdf_backend_annotation_last: + } + +\cs_new_protected:Npn \pdfannot_box:nnnnn #1 #2 #3 #4 #5 + { + \exp_args:Nx + \__pdf_backend_annotation:nnnn {#2}{#3}{#4} + { + \pdfdict_if_exist:nT { l_@@/#1 } + { + \pdfdict_use:n { l_@@/#1} + } + #5 + } + \bool_gset_false:N\g_@@_use_lastlink_bool + } +% \end{macrocode} +% \subsection{Annotations, subtype Widget}\label{pdf:annot:widget} +% Currently no code is provided here. +% The local dictionary \texttt{l_@@/Widget} is a skeleton +% dictionary for this subtype. It currently contains as only entry +% the subtype setting (the /Type is added by the backend). +% \begin{macrocode} + \pdfdict_new:n { l_@@/widget } + \pdfdict_put:nnn { l_@@/widget }{ Subtype }{ /Widget } +% \end{macrocode} +% +% \subsection{Annotations, subtype Link}\label{sec:links} +% The code assumes that there will be different link types +% (currently URI, GoToR, Launch, GoTo, Named, hyperref uses the names +% url,file,run,link,menu) and that links of the same type share +% the \emph{attr spec} and also the same begin/end +% code. The list of link types need to stay restricted and well documented so that +% all packages know which types they have to handle. It is stored in a constant +% seq. +% \begin{NOTE}{UF} +% Perhaps a |cite| type will be useful at some time. -- Thinking more about it, +% a |cite| type is not sensible. hyperref supports it, but it doesn't fit in. +% Commands like cite, gls, acro, footnote and so on should locally change +% linkcolor and linkbordercolor. +% Probably we will need some commands to add an attribute to all link types +% at once. +% hyperref commands for the various type: +% url |\hyper@linkurl|, +% file |\hyper@linkfile|, +% run |\@hyper@launch run|, +% link |\hyper@link|, |\find@pdflink| +% menu |\Acrobatmenu| +% \end{NOTE} +% \begin{variable}[added = 2020-03-12]{ \c_pdfannot_link_types_seq } +% This constant sequence contains the list of currently supported link types +% for which hooks and dictionaries exist. +% \end{variable} +% +% \begin{variable} +% { +% link/TYPE, +% pdfannot/link/TYPE/before, +% pdfannot/link/TYPE/begin, +% pdfannot/link/TYPE/end, +% pdfannot/link/TYPE/after +% } +% These setup the dictionary and the hook pairs. +% \begin{macrocode} +\seq_const_from_clist:Nn \c_pdfannot_link_types_seq { URI , GoToR , Launch , GoTo, Named } +\seq_map_inline:Nn \c_pdfannot_link_types_seq + { + \pdfdict_new:n { l_@@/link/#1 } + \hook_new_pair:nn + {pdfannot/link/#1/before} + {pdfannot/link/#1/after} + \hook_new_pair:nn + {pdfannot/link/#1/begin} + {pdfannot/link/#1/end} + } +% \end{macrocode} +% \end{variable} +% \subsubsection{Annotations, subtype Link /management} +% +% \begin{macro}{\pdfannot_link:nnn,\pdfannot_link:nxn} +% \begin{macrocode} +\cs_new_protected:Nn \pdfannot_link:nnn %#1 type (URI, GoTo etc), + %#2 action spec, #3 link text + { + \hook_use:n { pdfannot/link/#1/before} + \mode_leave_vertical: + \exp_args:Nxx %xetex needs expansion + \__pdf_backend_link_begin_user:nnw + { + \pdfdict_if_exist:nT { l_@@/link/#1 } + { + \pdfdict_use:n { l_@@/link/#1} + } + } + { + /Subtype/Link + #2 %exp_not? + } + \bool_gset_true:N \g_@@_use_lastlink_bool + \hook_use:n { pdfannot/link/#1/begin} + #3 + \hook_use:n { pdfannot/link/#1/end} + \__pdf_backend_link_end: + \bool_gset_true:N \g_@@_use_lastlink_bool + \hook_use:n { pdfannot/link/#1/after} + } +\cs_generate_variant:Nn \pdfannot_link:nnn {nxn} +% \end{macrocode} +% \end{macro} +% \begin{macro}{ +% \pdfannot_link_begin:nnw, +% \pdfannot_link_begin:nxw, +% \pdfannot_link_end:n } +% \begin{macrocode} +\cs_new_protected:Npn \pdfannot_link_begin:nnw #1 #2 %#1 type, #2 action spec + { + \hook_use:n { pdfannot/link/#1/before} + \mode_leave_vertical: + \exp_args:Nxx %xetex needs expansion + \__pdf_backend_link_begin_user:nnw + { + \pdfdict_if_exist:nT { l_@@/link/#1 } + { + \pdfdict_use:n { l_@@/link/#1} + } + } + { #2 } + \bool_gset_true:N \g_@@_use_lastlink_bool + \hook_use:n { pdfannot/link/#1/begin} + } + +\cs_new_protected:Nn \pdfannot_link_end:n %#1 type, e.g. url + { + \hook_use:n { pdfannot/link/#1/end} + \__pdf_backend_link_end: + \bool_gset_true:N \g_@@_use_lastlink_bool + \hook_use:n { pdfannot/link/#1/after} + } +\cs_generate_variant:Nn \pdfannot_link_begin:nnw {nxw} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pdfannot_link_goto_begin:nw, \pdfannot_link_goto_end:} +% \begin{macrocode} +\cs_new_protected:Npn \pdfannot_link_goto_begin:nw #1 %#1 destination + { + \hook_use:n { pdfannot/link/GoTo/before} + \mode_leave_vertical: + \exp_args:Nxx %xetex needs expansion + \__pdf_backend_link_begin_goto:nnw + { + \pdfdict_use:n { l_@@/link/GoTo} + } + { #1 } + \bool_gset_true:N \g_@@_use_lastlink_bool + \hook_use:n { pdfannot/link/GoTo/begin} + } + +\cs_new_protected:Nn \pdfannot_link_goto_end: + { + \hook_use:n { pdfannot/link/GoTo/end} + \__pdf_backend_link_end: + \bool_gset_true:N \g_@@_use_lastlink_bool + \hook_use:n { pdfannot/link/GoTo/after} + } +% \end{macrocode} +% \end{macro} +% \begin{macro}[EXP]{\pdfannot_link_ref_last:, \pdfannot_ref_last:} +% \begin{macrocode} +\cs_new:Nn \pdfannot_link_ref_last: { \__pdf_backend_link_last: } +% \end{macrocode} +% \begin{macrocode} +\cs_new:Npn \pdfannot_ref_last: + { + \bool_if:NTF \g_@@_use_lastlink_bool + { + \__pdf_backend_link_last: + } + { + \__pdf_backend_annotation_last: + } + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{ \pdfannot_link_margin:n} +% \begin{macrocode} +\cs_new_protected:Npn \pdfannot_link_margin:n #1 + { + \__pdf_backend_link_margin:n { #1 } + } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \pdfannot_dict_put:nnn, +% \pdfannot_dict_put:nnx, +% \pdfannot_dict_remove:nn, +% \pdfannot_dict_show:n +% } +% \begin{macrocode} +\cs_new_protected:Npn \pdfannot_dict_put:nnn #1 #2 #3 + { + \pdfdict_put:nnn { l_@@/#1 } { #2 }{ #3 } + } +\cs_generate_variant:Nn \pdfannot_dict_put:nnn {nnx} +% \end{macrocode} +% \begin{macrocode} +\cs_new_protected:Npn \pdfannot_dict_remove:nn #1 #2 + { + \pdfdict_remove:nn { l_@@/#1 } { #2 } + } +% \end{macrocode} +% \begin{macrocode} +\cs_new_protected:Npn \pdfannot_dict_show:n #1 + { + \pdfdict_show:n { l_@@/#1 } + } +% +% \end{macrocode} +% \end{macro} +% \end{implementation} +% +% \PrintIndex -- cgit v1.2.3