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/l3pdffile.dtx | 746 +++++++++++++++++++++ 1 file changed, 746 insertions(+) create mode 100644 Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdffile.dtx (limited to 'Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdffile.dtx') diff --git a/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdffile.dtx b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdffile.dtx new file mode 100644 index 00000000000..c1a2a25591d --- /dev/null +++ b/Master/texmf-dist/source/latex/pdfmanagement-testphase/l3pdffile.dtx @@ -0,0 +1,746 @@ +% \iffalse meta-comment +% +%% File: l3pdffile.dtx +% +% Copyright (C) 2018-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 package 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=l3pdffile (LaTeX PDF management testphase bundle)} + +\providecommand\potentialclash{\noindent\llap{\dbend\ }} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% \fi +% +% \title{^^A +% The \pkg{l3pdffile} module\\ Embedding and referencing files in a PDF ^^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-22} +% +% \maketitle +% \begin{documentation} +% +% \section{\pkg{l3pdffile} documentation} +% \subsection{Introduction} +% \subsubsection{Background} +% External files can be referenced from a PDF in three ways: +% \begin{enumerate} +% \item through an annotation of type Link, +% \item by referencing a local file in the file system, +% \item by embedding the file directly into the PDF +% \end{enumerate} +% Case 1 (Links) are created with the \cs{pdfannot} commands. +% This module handles the two other cases. Actually from the view +% of the PDF format they are quite similar: Case 2 is case 3 without the stream +% object and without the /EF entry in the /FileSpec dictionary (this points to the +% stream object of the file). Not embedding the file makes the PDF smaller. But it is +% also less portable: the files can only be found if they are in the right location +% relative to the PDF. The normal case is to embed the file. +% +% The tasks to embed and reference such a file are +% \begin{enumerate} +% \item Embed the file in a stream. +% \item Create a FileSpec dictionary which references the stream object in the /EF +% dictionary: +% \begin{verbatim} +% << +% /Type /Filespec +% /F (l3pdffile.dtx) +% /UF (l3pdffile.dtx) +% /AFRelationship /Source +% /EF <> %case 3, embedded file +% >> +% \end{verbatim} +% The file names in the /UF and /F value don't need to be identical to the +% name of file on the disc. It is quite possible to embed a \texttt{zzz.tex} +% and name it \texttt{blub.tex}. The second name is then what the user will see +% in the attachment list or in the properties of an annotation. +% +%\item Reference the FileSpec dictionary so that the user can access the file. +% This can be done in various way: +% \begin{enumerate} +% \item With an annotation (/Subtype/FileAttachment). This is done by +% \pkg{attachfile}, \pkg{attachfile2} and \pkg{intopdf}. +% Typical entries of such an annotation are: +% +% \medskip +% \begin{tabular}{lll} +% key & value type & notes\\\hline +% /FS & object reference &(FileSpec dictionary)\\ +% /Name & name & /Graph, /PushPin, /Paperclip, /Tag\\ +% /Contents & text string & optional but recommended\\ +% /F & integer & Flags\\ +% /AP & dictionary & Appearance (required if rectangle >0) \\ +% /AS & name\\ +% \end{tabular} +% +% The |/AP| takes precedence over Border and similar keys. +% \item Through an entry in the |/EmbeddedFiles| name tree. +% This is what \pkg{embedfiles} does. +% \begin{verbatim} +% 20 0 obj %Document Name tree +% <> +% endobj +% 21 0 obj %Embedded Files Name dictionary +% <> +% endobj +% \end{verbatim} +% The strings (keys) in the |/Names| dictionary must be sorted lexically. +% But they don't have to be the file name or anything related to +% the file name. The resource management code uses l3emb0001, l3emb0002~\ldots, +% which allows up to 9999 files. +% The key can be needed to identify the start file in a collection, +% so their relation to the files are stored in a property list. +% +% \item Through the |/AF| key in various objects (pdf 2.0). +% The value is normally an array of object +% references, but it can also be a name which is mapped to an array in /Properties: +% \begin{verbatim} +% /AF /NamedAF BDC +% /Properties <> +% } +% {example-image.eps} +% } +% \tl_set:Nx \l_my_fileobj_tl {\pdf_object_ref_last:} +% \end{verbatim} +% +% \begin{itemize} +% \item The |/Params| dictionary is not always required, but the commands of +% these module will prefill them as shown in the examples. A |/CreationDate| entry +% has to be added explicitly as there is no sensible way +% to retrieve this automatically. +% \item The mimetype (in the |/Subtype|) should be properly escaped. +% This module contains a property list with maps a number of file extensions +% to mimetypes and the commands try to detect and fill the mimetype automatically. +% \item The dictionary can contain additional keys (|/Filter|, |/DecodeParms|), +% see the pdf reference. +% \end{itemize} +% +% \subsubsection{Task 2: Creating the \texttt{/FileSpec} dictionary} +% The |/FileSpec| dictionary is a simple dictionary object, and can also +% be created in various ways. If it refers to an embedded file it should +% reference it in the |/EF| key. +% +% \subsubsection{Task 3: Referencing the \texttt{/FileSpec} dictionary} +% +% Using the dictionary reference in annotations and |/AF| keys is unproblematic. +% +% \potentialclash +% But to add it to the |/EmbeddedFiles| name tree so that it appears in the +% attachment panel requires special care: +% This name tree is a global resource and uncoordinated access can lead to +% clashes and files that are not visible or inaccessible. +% The access here is managed by the \pkg{l3pdfmanagement} module:\\[\smallskipamount]% +% |\pdfmanagement_add:nnx{Catalog/Names}{EmbeddedFiles}{|\meta{objref}|}| +% +% \subsection{Commands and tools of these module} +% \begin{function}{file, file/Params, file/streamParams,file/FileSpec} +% The module predefines and uses a number of local dictionaries for the +% components of the stream and the |/FileSpec| object. These dictionaries are +% then used by the \cs{pdffile_embed_XX}. +% The content of these dictionaries can be changed by users with the commands +% from the \pkg{l3pdfdict} module, but it should be done only locally +% to avoid side effects on uses by other packages/commands. + +% The preset values are of these dictionaries are shown in table~\ref{tab:filedict}. +% \end{function} +% \begin{table} +% \caption{Preset values in the file dictionaries\label{tab:filedict}} +% \begin{tabular}{lll} +% dictionary & key & value \\\hline +% l\_pdffile & Type & /EmbeddedFile\\ +% l\_pdffile/Params& Size & |\file_size:n{\l_pdffile_source_name_str}|\\ +% l\_pdffile/Params& ModDate & |(\file_timestamp:n {\l_pdffile_source_name_str})|\\ +% l\_pdffile/Params& CheckSum & |(\file_mdfive_hash:n{\l_pdffile_source_name_str})|\\ +% l\_pdffile/streamParams& & a /ModDate entry with year/month/date (used with \cs{pdffile_embed_stream:nnn})\\ +% l\_pdffile/FileSpec & Type & /FileSpec\\ +% l\_pdffile/FileSpec & AFRelationship &Unspecified +% \end{tabular} +% \end{table} +% \begin{function}{\pdffile_embed_file:nnn} +% \begin{syntax} +% \cs{pdffile_embed_file:nnn} \Arg{source filename} \Arg{target filename} \Arg{object name } +% \end{syntax} +% This commands embeds the file \meta{source filename} in the PDF, +% and creates a |/FileSpec| dictionary object named \meta{object name}. +% The object name must be unique. +% The command uses the content of the local +% dictionaries |l_pdffile|, |l_pdffile/Params| and |l_pdffile/FileSpec| +% to setup the dictionary entries of the stream object and the +% |/FileSpec| dictionary. The |/F| and |/UF| entry are filled +% with \meta{target filename}. +% +% It is an error if both \meta{target filename} and \meta{source filename} +% are empty. +% +% If \meta{target filename} is empty \meta{source filename} is used instead. +% +% If \meta{source filename} is empty, only a |/FileSpec| dictionary is +% created. +% +% If the |l_pdffile| dictionary doesn't contain a +% Subtype entry with the mimetype, the command tries to guess it +% from the file extension of \meta{source filename}. Unknown file extensions can be +% added (or known extension be changed) by adding to or changing the value in +% the property \cs{g_pdffile_mimetypes_prop}, see below. +% +% When using \texttt{dvips} and \texttt{pstopdf} the actual embedding is +% done by \texttt{pstopdf}. \texttt{pstopdf} will embed files +% only if used with the option \texttt{-dNOSAFER} and will not be able +% to use files which are found with \texttt{kpathsea}. +% +% \meta{target filename} doesn't need to be a file name with an extension, +% but it is recommended as security settings in the pdf +% viewer can restrict access to known file types. +% \end{function} +% +% \begin{NOTE}{UF} +% we should perhaps also consider the chunk method see pdfbase and +% https://chat.stackexchange.com/transcript/message/54181193#54181193 +% \end{NOTE} +% +% \begin{function}{\pdffile_embed_stream:nnn} +% \begin{syntax} +% \cs{pdffile_embed_stream:nnn} \Arg{content} \Arg{target filename} \Arg{object name } +% \end{syntax} +% This commands embeds the \meta{content} in the PDF in a stream objects and +% creates a |/FileSpec| dictionary object named \meta{object name}. +% \meta{content} is wrapped in a \cs{exp_not:n}. +% The object name must be unique. The command uses the content of the local +% dictionaries |l_pdffile|, |l_pdffile/streamParams| and |l_pdffile/FileSpec| +% to setup the dictionary entries of the stream object and the /FileSpec dictionary. +% The /F and /UF entry are filled with \meta{target filename}. +% If \meta{target filename} is empty the fix name \texttt{stream.txt} +% is used instead. +% +% If the |l_pdffile| dictionary doesn't contain a +% Subtype entry with the mimetype, the command tries to guess it +% from the file extension of \meta{target filename}. +% +% \meta{target filename} doesn't need to be a file name with an extension, +% but it is recommended as security settings in the pdf +% viewer can restrict access to known file types. +% +% The stream should not be too long, at least PS imposes a size limit for strings. +% \end{function} +% +% \begin{variable}{\g_pdffile_mimetypes_prop} +% This property contains a list of extensions and their mimetypes. +% Values can be added or changed with the standard commands: +% +% |\prop_gput:Nnn \g_pdffile_mimetypes_prop {.abc}{text/plain}| +% +% The extension should start with a period, the mimetype should be given +% as plain text (it will be escaped internally). Extensions with two periods +% are not supported. +% \end{variable} +% +% \begin{variable}{\l_pdffile_source_name_str} +% This variable is set at the begin of \cs{pdffile_embed_file:nnn}. It can be +% (and is) used in the file dictionaries, see table~\ref{tab:filedict} for examples. +% \end{variable} +% +% \begin{variable} {\g_pdffile_embed_prop} +% This property holds a list of embedded files. It is used by the following +% show command. The keys are the object names, the argument holds a key word, +% the source file name and the target file name. +% \end{variable} +% +% \begin{function}{\pdffile_embed_show:} +% This shows the embedded files with their source and target name. +% \end{function} +% +% \subsection{Example} +% \begin{verbatim} +% \group_begin: +% %set the relationship: +% \pdfdict_put:nnn {l_pdffile/FileSpec} {AFRelationship}{/Source} +% %set the description key. The text must first be converted: +% \pdf_string_from_unicode:nnN {utf16/string} +% {this~is~an~odd~description~with~öäü} +% \l_tmpa_str +% \pdfdict_put:nnx {l_pdffile/FileSpec} {Desc}{\l_tmpa_str} +% %embeds testinput.txt and calls it grüße.txt +% \pdffile_embed_file:nnn {testinput.txt}{grüße.txt}{file:example1} +% %reference it in the panel +% \pdfmanagement_add:nnx +% {Catalog/Names} +% {EmbeddedFiles} +% {\pdf_object_ref:n{file:example1}} +% \group_end: +% \end{verbatim} +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3pdffile} implementation} +% +% \begin{macrocode} +%<*header> +\ProvidesExplPackage {l3pdffile} {2021-02-22} {0.95a} + {embedding and referencing files in PDF---LaTeX PDF management testphase bundle} +\RequirePackage{l3pdftools} %temporarly!! +% +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +%<@@=pdffile> +\cs_new_protected:Npn \@@_filename_convert_to_print:nN #1 #2 + {\pdf_string_from_unicode:nnN {utf16/hex}{#1}{#2}} +% \end{macrocode} +% \subsection{Messages} +% \begin{macrocode} +\msg_new:nnn { pdffile } { file-not-found } + { + File~'\tl_to_str:n{#1}'~not~found + } + +\msg_new:nnn { pdffile } { mimetype-missing } + { + Mime~type~not~set~for~file~'\tl_to_str:n{#1}' + } + +\msg_new:nnn { pdffile } { target-name-missing } + { + a~target~name~for~the~/FileSpec~dictionary~is~missing. + } + +\msg_new:nnn { pdffile } { object-exists } + { + object~name~'#1'~is~already~used. + } + +\msg_new:nnn { pdffile } { show-files } + { + The~following~files~have~been~embedded\\ + #1 + } +% \end{macrocode} +% \begin{variable} +% { +% \l_@@_tmpa_tl, +% \l_@@_tmpb_tl, +% \l_@@_tmpa_str, +% \l_@@_tmpb_str, +% \l_@@_ext_str, +% \l_@@_automimetype_tl, +% \l_@@_embed_ref_tl +% } +% temporary variables: generic, for extension, subtype, to store the ref. +% \end{variable} +% \begin{macrocode} +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl +\str_new:N \l_@@_tmpa_str +\str_new:N \l_@@_tmpb_str +\str_new:N \l_@@_ext_str +\tl_new:N \l_@@_automimetype_tl +\tl_new:N \l_@@_embed_ref_tl +% \end{macrocode} +% \begin{variable} {\g_pdffile_mimetypes_prop} +% This variable holds common mimetypes. The key is an extension with (one) period, +% the value the description, e.g. \texttt{text/csv}. +% \end{variable} +% \begin{macrocode} +\prop_new:N \g_pdffile_mimetypes_prop +\prop_set_from_keyval:Nn \g_pdffile_mimetypes_prop + { + ,.csv = text/csv + ,.html= text/html + ,.dtx = text/plain %or application/x-tex, not in iana.org list + ,.eps = application/postscript + ,.jpg = image/jpeg + ,.mp4 = video/mp4 + ,.pdf = application/pdf + ,.png = image/png + ,.tex = text/plain %or application/x-tex, not in iana.org list + ,.txt = text/plain + ,.sty = text/plain + } +% \end{macrocode} +% \begin{variable} +% { +% \l_pdffile_source_name_str +% } +% \cs{l_pdffile_source_name_str} will be set at the begin of the command and +% contains the full file name and can be used e.g. with \cs{file_timestamp:n}. +% \end{variable} +% \begin{macrocode} +\str_new:N \l_pdffile_source_name_str +% \end{macrocode} +% Here we define and setup the local dictionaries. +% We add a ModDate to ensure that there is an entry if +% associated files are used. +% \begin{macrocode} +\pdfdict_new:n { l_pdffile } +\pdfdict_put:nnn { l_pdffile }{Type}{/EmbeddedFile} +\pdfdict_new:n { l_pdffile/Params } +\pdfdict_put:nnn { l_pdffile/Params } + {ModDate} { (\file_timestamp:n { \l_pdffile_source_name_str }) } +\pdfdict_put:nnn { l_pdffile/Params } + {Size} { \file_size:n { \l_pdffile_source_name_str } } +\pdfdict_put:nnn { l_pdffile/Params } + {CheckSum} { (\file_mdfive_hash:n { \l_pdffile_source_name_str }) } +\pdfdict_new:n { l_pdffile/streamParams } +\pdfdict_put:nnn { l_pdffile/streamParams } + {ModDate} { + ( + D:\int_use:N\c_sys_year_int + \int_compare:nNnT{\c_sys_month_int}<{10}{0} + \int_use:N\c_sys_month_int + \int_compare:nNnT{\c_sys_day_int}<{10}{0} + \int_use:N\c_sys_day_int + ) + } +\pdfdict_new:n { l_pdffile/FileSpec } +\pdfdict_put:nnn { l_pdffile/FileSpec } + {Type} { /FileSpec } +\pdfdict_put:nnn { l_pdffile/FileSpec } + {AFRelationship} { /Unspecified } + +% \end{macrocode} +% \begin{variable}{\g_pdffile_embed_prop} +% we record here the relation\\% +% \meta{object name} $\Rightarrow$ +% \Arg{file/stream or empty}\Arg{sourcename}\Arg{targetname} +% +% \begin{macrocode} +\prop_new:N \g_pdffile_embed_prop +% \end{macrocode} +% \end{variable} +% \begin{macro}{\pdffile_embed_show:} +% \begin{macrocode} +\cs_new_protected:Npn \pdffile_embed_show: + { + \msg_show:nnx + {pdffile}{show-files} + { + \prop_map_function:NN {\g_pdffile_embed_prop} \msg_show_item:nn + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pdffile_embed_file:nnn, \pdffile_embed_stream:nnn} +% At first a command to set the mimetype. It either uses the current value +% in the file dictionary, or tries to guess it from the extension. +% \begin{macro}{\@@_mimetype_set:nN,\@@_mimetype_set:VN} +% \begin{macro}{\@@_fstream_write:nN, \@@_fstream_write:VN} +% \begin{macro}{\@@_stream_write:nN, \@@_stream_write:VN} +% \begin{macrocode} +%#1 file name, +%#2 tl to return the (printed) value for the guessed mimetype +\cs_new_protected:Npn \@@_mimetype_set:nN #1 #2 + { + \file_parse_full_name:nNNN + {#1} + \l_@@_tmpa_str %unused + \l_@@_tmpb_str %unused + \l_@@_ext_str + %check if Subtype has been set + \pdfdict_get:nnN { l_pdffile}{Subtype}\l_@@_tmpa_tl + %if not look up in the prop: + \quark_if_no_value:NT \l_@@_tmpa_tl + { + \prop_get:NVNTF + \g_pdffile_mimetypes_prop + \l_@@_ext_str + \l_@@_tmpb_tl + { + \tl_set:Nx #2 {/Subtype~\pdf_name_from_unicode_e:V \l_@@_tmpb_tl} + } + { + \msg_warning:nnx { pdffile }{ mimetype-missing} {#1} + \tl_clear:N #2 + } + } + } + +\cs_generate_variant:Nn \@@_mimetype_set:nN {VN} + +%#1 file name, +%#2 tl, should be empty or contain /Subtype /mimetype +% e.g. result from \@@_mimetype_set:NN +\cs_new_protected:Npn \@@_fstream_write:nN #1 #2 + { + \pdf_object_unnamed_write:nx { fstream } + { + { + #2 + \pdfdict_use:n { l_pdffile} + \pdfdict_if_empty:nF { l_pdffile/Params} + { + /Params + << + \pdfdict_use:n { l_pdffile/Params} + >> + } + } + { #1 } + } + \tl_clear:N \l_@@_automimetype_tl + } + +\cs_generate_variant:Nn \@@_fstream_write:nN {VN} + +%#1 file content +%#2 tl, should be empty or contain /Subtype /mimtype +% e.g. result from \@@_mimetype_set:NN +\cs_new_protected:Npn \@@_stream_write:nN #1 #2 + { + \pdf_object_unnamed_write:nx { stream } + { + { + #2 + \pdfdict_use:n { l_pdffile} + \pdfdict_if_empty:nF { l_pdffile/streamParams} + { + /Params + << + \pdfdict_use:n { l_pdffile/streamParams} + >> + } + } + { \exp_not:n { #1 } } + } + \tl_clear:N \l_@@_automimetype_tl + } + +\cs_generate_variant:Nn \@@_stream_write:nN {VN} + +%#1 symbolic name of dict object +%#2 target file name, +%#3 object ref of the file stream. +\cs_new_protected:Npn \@@_filespec_write:nnn #1 #2 #3 + { + \tl_if_blank:nT { #2 } + { + \msg_error:nn {pdffile}{target-name-missing} + } + { + \pdf_object_new:nn { #1 } {dict} + \group_begin: + \@@_filename_convert_to_print:nN { #2 } \l_@@_tmpa_str + \pdfdict_put:nnx {l_pdffile/FileSpec}{F} { \l_@@_tmpa_str } + \pdfdict_put:nnx {l_pdffile/FileSpec}{UF}{ \l_@@_tmpa_str } + \pdf_object_write:nx { #1 } + { + \pdfdict_use:n { l_pdffile/FileSpec} + \tl_if_empty:nF { #3 } + { + /EF <> + } + } + \group_end: + } + } + + +%#1 {source filename} +%#2 {target filename} +%#3 { filespec object name } (will internally get a prefix!) +\cs_new_protected:Npn \pdffile_embed_file:nnn #1 #2 #3 + { % if #1 empty => only filespec + % if #2 empty => = #1 + \pdf_object_if_exist:nTF { #3 } + { + \msg_error:nnn { pdffile }{ object-exists } { #3 } + } + { + \tl_if_blank:nTF { #1 } + { + \tl_set:Nn \l_@@_embed_ref_tl {} + } + { + \file_get_full_name:nNTF {#1} \l_pdffile_source_name_str + { + \@@_mimetype_set:VN + \l_pdffile_source_name_str + \l_@@_automimetype_tl + \@@_fstream_write:VN + \l_pdffile_source_name_str + \l_@@_automimetype_tl + \tl_set:Nx \l_@@_embed_ref_tl { \pdf_object_ref_last: } + } + { + \msg_error:nnn { pdffile }{ file-not-found }{ #1 } + } + + } + \prop_gput:Nnx + \g_pdffile_embed_prop + { #3 } + { + { \tl_if_blank:nTF { #1 } {filespec}{file} } + {\l_pdffile_source_name_str} + { + \tl_if_blank:nTF { #2 } + { \l_pdffile_source_name_str } + { \tl_to_str:n{#2}} + } + } + \tl_if_blank:nTF { #2 } + { + \exp_args:Nnnx + \@@_filespec_write:nnn + %#1 dict, #2 target file name, #3 object ref + { #3 } + { #1 } + {\l_@@_embed_ref_tl} + } + { + \exp_args:Nnnx + \@@_filespec_write:nnn + %#1 dict, #2 target file name, #3 object ref + { #3 } + { #2 } + {\l_@@_embed_ref_tl} + } + } + } + + +%#1{stream content} +%#2{target filename} +%#3{file object name } +\cs_new_protected:Npn \pdffile_embed_stream:nnn #1 #2 #3 + { + % if #2 empty => error + \pdf_object_if_exist:nTF { #3 } + { + \msg_error:nnn { pdffile }{ object-exists } { #3 } + } + { + \prop_gput:Nnx + \g_pdffile_embed_prop + { #3 } + {{stream}{}{\tl_if_blank:nTF {#2}{stream.txt}{\exp_not:n{#2}}}} + \tl_if_blank:nTF {#2} + { \@@_mimetype_set:nN {stream.txt}\l_@@_automimetype_tl} + { \@@_mimetype_set:nN { #2 } \l_@@_automimetype_tl } + \@@_stream_write:nN + { #1 } + \l_@@_automimetype_tl + \tl_set:Nx \l_@@_embed_ref_tl { \pdf_object_ref_last: } + \exp_args:Nnxx + \@@_filespec_write:nnn + %#1 dict, #2 target file name, #3 object ref + { #3 } + { \tl_if_blank:nTF {#2}{stream.txt}{\exp_not:n{#2}} } + {\l_@@_embed_ref_tl} + } + } + + +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex -- cgit v1.2.3