summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx')
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx254
1 files changed, 227 insertions, 27 deletions
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx
index 0390980da5..c3de57b74c 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx
+++ b/macros/latex/contrib/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:}