diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfmanagement.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfmanagement.dtx | 254 |
1 files changed, 227 insertions, 27 deletions
diff --git a/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfmanagement.dtx b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfmanagement.dtx index 0390980da5b..c3de57b74c5 100644 --- a/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfmanagement.dtx +++ b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdfmanagement.dtx @@ -61,7 +61,7 @@ % }^^A % } % -% \date{Version 0.95g, released 2021-07-21} +% \date{Version 0.95h, released 2021-07-31} % % \maketitle % \begin{documentation} @@ -137,9 +137,14 @@ % {\pdfmanagement_if_active:} % This conditional tests if the resource management code is active. % \end{function} -% -% \begin{function}[added = 2020-04-06] -% {\pdfmanagement_add:nnn,\pdfmanagement_add:nnx,\pdfmanagement_add:nxx} +% \begin{function}[added=2021-07-23] +% {\IfPDFManagementActiveTF} +% This is a LaTeX2e version of the conditional +% \end{function} + +% \begin{function}[added = 2020-04-06,updated=2021-07-23] +% {\pdfmanagement_add:nnn,\pdfmanagement_add:nnx,\pdfmanagement_add:nxx,\pdfmanagement_add:xxx, +% \PDFManagementAdd} % \begin{syntax} % \cs{pdfmanagement_add:nnn} \Arg{resource path} \Arg{name} \Arg{value} % \end{syntax} @@ -152,7 +157,8 @@ % keys used in PDF dictionaries (see the l3pdfdict module) the name is escaped % with \cs{str_convert_pdfname:n} when stored. % \Arg{value} should be a valid PDF value for this Name in the -% target dictionary. +% target dictionary. |\PDFManagementAdd| is a copy of |\pdfmanagement_add:xxx| +% and so expands all its arguments. % % % The code works with all major engines but not necessarily @@ -166,6 +172,10 @@ % backends. Some engines have to use labels and the aux-file to setup % the dictionaries and so need at least two compilations to put everything % in place. +% \item dvips doesn't support everything. It is for example not possible +% to add manually or through side effects +% a name tree like /AP or /JavaScript, pdfmark doesn't provide a handler +% here---at least I didn't find anything suitable. % \end{itemize} % \end{function} % @@ -549,6 +559,61 @@ % attach the file to the file panel. % \end{tabularx} % +% \paragraph{Catalog entries for name trees} +% +% \emph{Not supported in the dvips backend, pdfmark doesn't have an interface here}. +% +% In various places the PDF format allows to reference objects by name instead +% of by object reference. The relationship between a name and the object reference +% are store in so-called \emph{name trees}, which are stored in the +% Catalog/Names dictionary. The |/Dests| and the |/EmbeddedFiles| name trees are +% handled implicitly if destinations or files are added. Names to the other +% name trees can be added with |\pdfmanagement_add:nnn|, e.g. to add an value to +% the AP names (for appearance streams) use +% +% \begin{verbatim} +% \pdfmanagement_add:nnx { Catalog / Names / AP } {myAPname} {\pdf_object_ref_last:} +% \end{verbatim} +% +% Remarks: +% \begin{itemize} +% \item The name |myAPname| is processed through |\pdf_string_from_unicode:nnN{utf8/string}| +% and parentheses are added automatically. Ensure that the use of the name +% handles it in the same way. +% \item It is currently not possible to test if a name has already been used +% by another package or previous code, +% so use names where you can be confident that they are unique. +% (It would be possible to split up the first part and test, but it would slow +% down the compilation and I'm not sure if it is worth the trouble) +% \item The value is not preprocessed, it is up-to-you to ensure that it does the +% right thing. +% \item Currently the structure of the name tree is flat, it doesn't use +% Kids. But this can be changed if the need arise. +% \end{itemize} +% +% The following name trees can be filled with this method. Currently only the +% first three are activated. For the first, |EmbeddedFiles| there are two methods +% to add a value:\\ +% |\pdfmanagement_add:nnn{Catalog/Names/EmbeddedFiles}{name}{reference}| +% and +% |\pdfmanagement_add:nnn{Catalog/Names}{EmbeddedFiles}{reference}|. +% This is intended, the second methods creates a name on the fly (with the prefix l3ef) +% +% \medskip +% \noindent +% \begin{tabularx}{\linewidth}{ll>{\raggedright\arraybackslash}X} +% Catalog/Names/EmbeddedFiles & A name tree mapping name strings to file +% specifications for embedded file streams. The value should be a reference to a filespec +% dictionary\\ +% Catalog/Names/AP & A name tree mapping name strings to annotation appearance streams\\ +% Catalog/Names/JavaScript & A name tree mapping name strings to documentlevel ECMAScript actions\\ +% (inactive) Catalog/Names/Pages & A name tree mapping name strings to visible pages for use in interactive forms\\ +% (inactive) Catalog/Names/Templates & A name tree mapping name strings to invisible pages for use in interactive forms\\ +% (inactive) Catalog/Names/IDS & A name tree mapping digital identifiers to Web.Capture content sets\\ +% (inactive) Catalog/Names/URLS & A name tree mapping name strings to documentlevel ECMAScript actions\\ +% (inactive) Catalog/Names/Renditions & A name tree mapping name strings (which shall have Unicode encoding) to rendition objects +% (it is not quite clear yet, what unicode encoding means here. Perhaps this string will need special handling)\\ +% \end{tabularx} % \end{documentation} % % \begin{implementation} @@ -557,7 +622,7 @@ %<@@=pdfmanagement> %<*header> % -\ProvidesExplPackage{l3pdfmanagement}{2021-07-21}{0.95g} +\ProvidesExplPackage{l3pdfmanagement}{2021-07-31}{0.95h} {Management of core PDF dictionaries (LaTeX PDF management testphase bundle)} %</header> % \end{macrocode} @@ -576,6 +641,9 @@ \msg_new:nnn { pdfmanagement } { no-show } { It~is~not~possible~to~show~the~content~of~'#1'.} +\msg_new:nnn { pdfmanagement } { name-exist } + { The~name~'#1'~has~already~been~used~for~name~tree~'#2'.} + \msg_new:nnn { pdfmanagement } { show-dict } { The~PDF~resource~'#1'~ @@ -593,6 +661,16 @@ command~'#1'~ignored. } % \end{macrocode} +% +% \begin{variable}{\l_@@_tmpa_tl,\l_@@_tmpb_tl,\l_@@_tmpa_seq} +% Some temp variables +% \begin{macrocode} +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl +\seq_new:N \l_@@_tmpa_seq +% \end{macrocode} +% \end{variable} + % \begin{variable}{\g_@@_active_bool} % This boolean will control the activation of the management code. % It is used in the hooks, and in some backend files. @@ -612,6 +690,7 @@ \prg_set_eq_conditional:NNn \pdfmanagement_if_active: \@@_if_active: { p , T , F , TF } +\cs_set_eq:NN \IfPDFManagementActiveTF\pdfmanagement_if_active:TF % \end{macrocode} % We use a hook, to collect value added before the backend is ready. % \begin{macrocode} @@ -639,7 +718,8 @@ } } -\cs_generate_variant:Nn \pdfmanagement_add:nnn {nnx,nxx} +\cs_generate_variant:Nn \pdfmanagement_add:nnn {nnx,nxx,xxx} +\cs_set_eq:NN \PDFManagementAdd \pdfmanagement_add:xxx % \end{macrocode} % \subsection{Hooks -- shipout and end of run code} % Code is executed in three places: At shipout of every page, @@ -1006,6 +1086,7 @@ % \end{variable} % \begin{macro}{ \@@_catalog_XX_gput:n } % Various commands to handle subentries and special cases. +% At first we set up a few lists of the various types. % \begin{macrocode} \pdfdict_new:n { g__pdf_Core/Catalog} @@ -1059,8 +1140,24 @@ AcroForm/CO } - - +% \end{macrocode} +% Names trees in Catalog/Names. We prepare the full list +% but activate only AP and JavaScript for now. +% /EmbeddedFiles has special code and so is not in the name list. +% \begin{macrocode} +\clist_const:Nn \c_@@_Catalog_nametree_clist + { + AP, + JavaScript, +% Pages, +% Templates, +% IDS, +% URLS, +% Renditions + } +% \end{macrocode} +% now we create the handler. The entries in the seq-list store in a seq +% \begin{macrocode} \clist_map_inline:Nn \c_@@_Catalog_seq_clist { \seq_new:c { g_@@_/Catalog/#1_seq } % new name later @@ -1070,6 +1167,10 @@ } } +% \end{macrocode} +% OCProperties/D is special: it handles a default. This is done by adding to +% the left of the seq +% \begin{macrocode} \cs_new_protected:cpn { @@_handler/Catalog/OCProperties/D_gput:n } #1 { \seq_gput_left:cn @@ -1077,6 +1178,58 @@ { #1 } } % \end{macrocode} +% The name tree keys store in a property and check for duplicates. This is done +% with an auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_nametree_add_aux:nnn #1 #2 #3 + %#1 name tree, #2 sanitized name #3 value + { + \prop_get:coNTF + { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/Names/#1 }} + { #2 } + \l_@@_tmpb_tl + { + \msg_error:nnnn{pdfmanagement}{name-exist}{#2}{#1} + } + { + \prop_gput:con + { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/Names/#1 }} + { #2 } + { #3 } + } + } +% \end{macrocode} +% This is the standard handler for most names trees: +% \begin{macrocode} +\clist_map_inline:Nn \c_@@_Catalog_nametree_clist + { + \pdfdict_new:n { g__pdf_Core/Catalog/Names/#1} + \cs_new_protected:cpn { @@_handler/Catalog/Names/#1/?_gput:nn } ##1 ##2 + { + \pdf_string_from_unicode:nnN {utf8/string}{##1}\l_@@_tmpa_tl + \exp_args:Nno + \@@_nametree_add_aux:nnn {#1}{\l_@@_tmpa_tl}{##2} + } + } +% \end{macrocode} +% EmbeddedFiles is a bit special. For once there is special backend code +% needed by dvips. Beside this we also want the option to create the file name +% on the fly, so they are actually two access methods: +% |\pdfmanagement_add:nnn{Catalog/Names/EmbeddedFiles}{name}{reference}| +% and +% |\pdfmanagement_add:nnn{Catalog/Names}{EmbeddedFiles}{reference}| +% \begin{macrocode} +\pdfdict_new:n { g__pdf_Core/Catalog/Names/EmbeddedFiles} +\cs_new_protected:cpn { @@_handler/Catalog/Names/EmbeddedFiles/?_gput:nn } #1 #2 + { + \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_tl + \exp_args:Nno + \@@_nametree_add_aux:nnn + {EmbeddedFiles}{\l_@@_tmpa_tl}{#2} + \exp_args:No + \__pdf_backend_NamesEmbeddedFiles_add:nn {\l_@@_tmpa_tl}{#2} + } +% \end{macrocode} % \end{macro} % % \paragraph {Building the catalog: Push order} % \begin{macro}{\@@_Catalog_gpush:} @@ -1099,7 +1252,11 @@ { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog} } \__pdf_backend_catalog_gput:nn % output names tree: - \use:c { @@_/Catalog/Names/EmbeddedFiles_gpush: } + \use:c{ @@_/Catalog/Names_gpush:n } {EmbeddedFiles} + \clist_map_inline:Nn \c_@@_Catalog_nametree_clist + { + \use:c{ @@_/Catalog/Names_gpush:n } {##1} + } } % \end{macrocode} % \end{macro} @@ -1283,12 +1440,12 @@ { 0 } { \__pdf_backend_object_new:nn { @@/Catalog/OCProperties } { dict } - \seq_gpop_left:cN { g_@@_/Catalog/OCProperties/Configs_seq} \l_tmpa_tl + \seq_gpop_left:cN { g_@@_/Catalog/OCProperties/Configs_seq} \l_@@_tmpa_tl \exp_args:Nnx \__pdf_backend_object_write:nn {@@/Catalog/OCProperties} { /OCGs~[ \seq_use:cn { g_@@_/Catalog/OCProperties/OCGs_seq } {~} ] - /D~\l_tmpa_tl~ + /D~\l_@@_tmpa_tl~ \seq_if_empty:cF { g_@@_/Catalog/OCProperties/Configs_seq } { /Configs~ @@ -1382,6 +1539,30 @@ % \begin{NOTE}{UF} % TODO access function for the name in the name tree % \end{NOTE} +% \begin{variable}{\g_@@_EmbeddedFiles_int} +% We want to create names for files on the fly. For this we use an int. +% \begin{macrocode} +\int_new:N \g_@@_EmbeddedFiles_int +% \end{macrocode} +% \end{variable} +% \begin{macro}{\@@_EmbeddedFiles_name:} +% We use the prefix l3ef, and pad numbers below 9999. +% \begin{macrocode} +\cs_new:Npn \@@_EmbeddedFiles_name: + { + ( + l3ef + \int_compare:nNnT {\g_@@_EmbeddedFiles_int} < {10} + {0} + \int_compare:nNnT {\g_@@_EmbeddedFiles_int} < {100} + {0} + \int_compare:nNnT {\g_@@_EmbeddedFiles_int} < {1000} + {0} + \int_use:N \g_@@_EmbeddedFiles_int + ) + } +% \end{macrocode} +% \end{macro} % \begin{macro}{ Handler} % EmbeddedFiles is an array and needs a special handler to add values. % \begin{macrocode} @@ -1389,25 +1570,44 @@ \cs_new_protected:cpn { @@_handler/Catalog/Names/EmbeddedFiles_gput:n } #1 { - \__pdf_backend_NamesEmbeddedFiles_add:n { #1 } + \int_gincr:N \g_@@_EmbeddedFiles_int + \exp_args:Nnx + \prop_gput:cnn + { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/Names/EmbeddedFiles }} + { \@@_EmbeddedFiles_name: } + { #1 } + \exp_args:Nx + \__pdf_backend_NamesEmbeddedFiles_add:nn {\@@_EmbeddedFiles_name:} { #1 } } % \end{macrocode} % \end{macro} -% The entry should only be added if there are actually embedded files. -% This can be tested by checking the names_seq -% \begin{macro}{\@@_/Catalog/Names/EmbeddedFiles_gpush:} +% This pushes out the other names trees (but not with dvips). +% TODO: currently it simply write in the root of the name tree. +% That is the fastest. +% If they get longer we perhaps need to build something with Kids and Limits. +% \begin{macro}{\@@_/Catalog/Names/?_gpush:} % \begin{macrocode} -% -\cs_new_protected:cpn { @@_/Catalog/Names/EmbeddedFiles_gpush: } - { - \seq_if_empty:NF \g__pdf_backend_EmbeddedFiles_seq - { - \exp_args:Nx \__pdf_backend_NamesEmbeddedFiles_gpush:n - { - \seq_use:Nn \g__pdf_backend_EmbeddedFiles_seq {~} - } - } - } +\cs_new_protected:cpn { @@_/Catalog/Names_gpush:n } #1 %#1 name of name tree + { + \pdfdict_if_empty:nF { g__pdf_Core/Catalog/Names/#1 } + { + \seq_clear:N \l_@@_tmpa_seq + \prop_map_inline:cn + {\__kernel_pdfdict_name:n { g__pdf_Core/Catalog/Names/#1 }} + { \seq_put_right:Nn \l_@@_tmpa_seq {##1~##2}} + \seq_sort:Nn \l_@@_tmpa_seq + { + \str_compare:nNnTF {##1} > {##2} + { \sort_return_swapped: } + { \sort_return_same: } + } + \exp_args:Nnx \__pdf_backend_Names_gpush:nn + {#1} + { + \seq_use:Nn \l_@@_tmpa_seq {~} + } + } + } % \end{macrocode} % \end{macro} % \begin{macro}{@@_handler/Catalog/?_show:} |