summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx443
1 files changed, 427 insertions, 16 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
index d46578027d6..4a91ce531b4 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
@@ -41,7 +41,7 @@
% }^^A
% }
%
-% \date{Released 2018-08-23}
+% \date{Released 2018-09-24}
%
% \maketitle
%
@@ -458,6 +458,79 @@
% given.
% \end{function}
%
+% \section{PDF Features}
+%
+% A range of PDF features are exposed by \pdfTeX{} and \LuaTeX{} in direct PDF
+% output mode, and the vast majority of these are also controllable using
+% the \texttt{(x)dvipdfmx} driver (as DVI instructions are converted directly
+% to PDF). Some of these functions are also available for cases where PDFs
+% are generated by \texttt{dvips}: this depends on being able to pass
+% information through correctly.
+%
+% \subsection{PDF Objects}
+%
+% Objects are used to provide a range of data structures in a PDF. At the
+% driver level, different PDF object types are declared separately. Objects
+% are only \emph{written} to the PDF when referenced.
+%
+% \begin{function}{\driver_pdf_object_new:nn}
+% \begin{syntax}
+% \cs{driver_pdf_object_new:n} \Arg{name} \Arg{type}
+% \end{syntax}
+% Declares \meta{name} as a PDF object. The \texttt{type} should be one of
+% |array| or |dict|, |fstream| or |stream|.
+% \end{function}
+%
+% \begin{function}[EXP]{\driver_pdf_object_ref:n}
+% \begin{syntax}
+% \cs{driver_pdf_object_ref:n} \Arg{object}
+% \end{syntax}
+% Inserts the appropriate information to reference the \meta{object}
+% in for example page resource allocation.
+% \end{function}
+%
+% \begin{function}{\driver_pdf_object_write:nn}
+% \begin{syntax}
+% \cs{driver_pdf_object_write:nn} \Arg{name} \Arg{data}
+% \end{syntax}
+% Writes the \meta{data} as content of the \meta{object}. Depending on the
+% \meta{type} declared for the object, the format required for the
+% \meta{data} will vary
+% \begin{itemize}
+% \item[\texttt{array}] A space-separated list of values
+% \item[\texttt{dict}] Key--value pairs in the form
+% \texttt{/\meta{key} \meta{value}}
+% \item[\texttt{fstream}] Two brace groups: \meta{content} and
+% \meta{file name}
+% \item[\texttt{stream}] Two brace groups: \meta{content} and
+% \meta{additional attributes}
+% \end{itemize}
+% \end{function}
+%
+% \subsection{PDF structure}
+%
+% \begin{function}{\driver_pdf_compresslevel:n}
+% \begin{syntax}
+% \cs{driver_pdf_compresslevel:n} \Arg{level}
+% \end{syntax}
+% Sets the degree of compression used for PDF files: the \meta{level} should
+% be in the range $0$ to $9$ (higher is more compression). Typically, either
+% compression is disables ($0$) or maximised ($9$). When used with
+% \texttt{(x)dvipdfmx}, this setting may only be applied globally: it should
+% be set only once.
+% \end{function}
+%
+% \begin{function}{\driver_pdf_objects_enable:, \driver_pdf_objects_disable:}
+% \begin{syntax}
+% \cs{driver_pdf_objects_disable:}
+% \end{syntax}
+% Enables or disables the creation of PDF objects. These objects are used to
+% reduce the size of PDFs, and typically are enabled as standard. When used
+% with \texttt{(x)dvipdfmx}, object creation can be disabled but not
+% re-enabled, and this setting may only be applied globally: it should
+% be set only once.
+% \end{function}
+%
% \end{documentation}
%
% \begin{implementation}
@@ -481,23 +554,23 @@
%<*package>
\ProvidesExplFile
%<*dvipdfmx>
- {l3dvidpfmx.def}{2018-08-23}{}
+ {l3dvidpfmx.def}{2018-09-24}{}
{L3 Experimental driver: dvipdfmx}
%</dvipdfmx>
%<*dvips>
- {l3dvips.def}{2018-08-23}{}
+ {l3dvips.def}{2018-09-24}{}
{L3 Experimental driver: dvips}
%</dvips>
%<*dvisvgm>
- {l3dvisvgm.def}{2018-08-23}{}
+ {l3dvisvgm.def}{2018-09-24}{}
{L3 Experimental driver: dvisvgm}
%</dvisvgm>
%<*pdfmode>
- {l3pdfmode.def}{2018-08-23}{}
+ {l3pdfmode.def}{2018-09-24}{}
{L3 Experimental driver: PDF mode}
%</pdfmode>
%<*xdvipdfmx>
- {l3xdvidpfmx.def}{2018-08-23}{}
+ {l3xdvidpfmx.def}{2018-09-24}{}
{L3 Experimental driver: xdvipdfmx}
%</xdvipdfmx>
%</package>
@@ -605,7 +678,7 @@
{ rgb~ \fp_eval:n {#1} ~ \fp_eval:n {#2} ~ \fp_eval:n {#3} }
}
\cs_new_protected:Npn \driver_color_spot:nn #1#2
- { \@@_color_select:n { \c_space_tl #1 } }
+ { \@@_color_select:n { #1 } }
\cs_new_protected:Npn \@@_color_select:n #1
{
\@@_literal:n { color~push~ #1 }
@@ -904,7 +977,7 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Images}
+% \subsubsection{Images}
%
% \begin{macro}{\@@_image_getbb_eps:n}
% Simply use the generic function.
@@ -922,7 +995,7 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Drawing}
+% \subsubsection{Drawing}
%
% \begin{macro}{\@@_draw_literal:n, \@@_draw_literal:x}
% The same as literal PostScript: same arguments about positioning apply
@@ -1322,6 +1395,113 @@
% \end{macrocode}
% \end{macro}
%
+% \subsubsection{PDF Features}
+%
+% \begin{variable}{\g_@@_pdf_object_int, \g_@@_pdf_object_prop}
+% For tracking objects to allow finalisation.
+% \begin{macrocode}
+\int_new:N \g_@@_pdf_object_int
+\prop_new:N \g_@@_pdf_object_prop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\driver_pdf_object_new:nn}
+% \begin{macro}[EXP]{\driver_pdf_object_ref:n}
+% Tracking objects is similar to \texttt{dvipdfmx}.
+% \begin{macrocode}
+\cs_new_protected:Npn \driver_pdf_object_new:nn #1#2
+ {
+ \int_gincr:N \g_@@_pdf_object_int
+ \int_const:cn
+ { g_@@_pdf_object_ \tl_to_str:n {#1} _int }
+ { \g_@@_pdf_object_int }
+ \prop_gput:Nnn \g_@@_pdf_object_prop {#1} {#2}
+ }
+\cs_new:Npn \driver_pdf_object_ref:n #1
+ { { l3obj \int_use:c { g_@@_pdf_object_ \tl_to_str:n {#1} _int } } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\driver_pdf_object_write:nn}
+% \begin{macro}
+% {
+% \@@_pdf_object_write_array:nn ,
+% \@@_pdf_object_write_dict:nn ,
+% \@@_pdf_object_write_stream:nn
+% }
+% \begin{macro}{\@@_pdf_object_write_stream:nnn}
+% This is where we choose the actual type: some work to get things
+% right.
+% \begin{macrocode}
+\cs_new_protected:Npn \driver_pdf_object_write:nn #1#2
+ {
+ \@@_literal_postscript:x
+ {
+ mark ~ /_objdef ~ \driver_pdf_object_ref:n {#1} ~
+ /type
+ \str_case_e:nn
+ { \prop_item:Nn \g_@@_pdf_object_prop {#1} }
+ {
+ { array } { /array }
+ { dict } { /dict }
+ { fstream } { /stream }
+ { stream } { /stream }
+ }
+ /OBJ ~ pdfmark
+ }
+ \use:c
+ { @@_pdf_object_write_ \prop_item:Nn \g_@@_pdf_object_prop {#1} :nn }
+ {#1} {#2}
+ }
+\cs_new_protected:Npn \@@_pdf_object_write_array:nn #1#2
+ {
+ \@@_literal_postscript:x
+ {
+ mark ~ \driver_pdf_object_ref:n {#1} ~
+ [ ~ \exp_not:n {#2} ~ ] ~ /PUTINTERVAL ~ pdfmark
+ }
+ }
+\cs_new_protected:Npn \@@_pdf_object_write_dict:nn #1#2
+ {
+ \@@_literal_postscript:x
+ {
+ mark ~ \driver_pdf_object_ref:n {#1} ~
+ << ~ \exp_not:n {#2} ~ >> ~ /PUT ~ pdfmark
+ }
+ }
+\cs_new_protected:Npn \@@_pdf_object_write_stream:nn #1#2
+ {
+ \exp_args:Nx
+ \@@_pdf_object_write_stream:nnn
+ { \driver_pdf_object_ref:n {#1} }
+ #2
+ }
+\cs_new_protected:Npn \@@_pdf_object_write_stream:nnn #1#2#3
+ {
+ \@@_literal_postscript:n
+ {
+ [nobreak] ~
+ mark ~ #1 ~ ( #3 ) ~ /PUT ~ pdfmark ~
+ mark ~ #1 ~ << #2 >> ~ /PUT ~ pdfmark
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\driver_pdf_compresslevel:n}
+% \begin{macro}{\driver_pdf_objects_enable:, \driver_pdf_objects_disable:}
+% These are all no-ops.
+% \begin{macrocode}
+\cs_new_protected:Npn \driver_pdf_compresslevel:n #1 { }
+\cs_new_protected:Npn \driver_pdf_objects_enable: { }
+\cs_new_protected:Npn \driver_pdf_objects_disable: { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macrocode}
%</dvips>
% \end{macrocode}
@@ -1483,7 +1663,7 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Images}
+% \subsubsection{Images}
%
% \begin{variable}{\l_@@_image_attr_tl}
% In PDF mode, additional attributes of an image (such as page number) are
@@ -1594,6 +1774,117 @@
% \end{macrocode}
% \end{macro}
%
+% \subsubsection{PDF Objects}
+%
+% \begin{variable}{\g_@@_pdf_object_prop}
+% For tracking objects to allow finalisation.
+% \begin{macrocode}
+\prop_new:N \g_@@_pdf_object_prop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\driver_pdf_object_new:nn}
+% \begin{macro}[EXP]{\driver_pdf_object_ref:n}
+% Declaring objects means reserving at the PDF level plus starting
+% tracking.
+% \begin{macrocode}
+\group_begin:
+ \cs_set_protected:Npn \@@_tmp:w #1#2
+ {
+ \cs_new_protected:Npx \driver_pdf_object_new:nn ##1##2
+ {
+ #1 reserveobjnum ~
+ \int_const:cn
+ { g_@@_pdf_object_ \exp_not:N \tl_to_str:n {##1} _int }
+ {#2}
+ \prop_gput:Nnn \exp_not:N \g_@@_pdf_object_prop {##1} {##2}
+ }
+ }
+ \cs_if_exist:NTF \tex_pdfextension:D
+ {
+ \@@_tmp:w
+ { \tex_pdfextension:D obj ~ }
+ { \tex_pdffeedback:D lastobj \scan_stop: }
+ }
+ { \@@_tmp:w { \tex_pdfobj:D } { \tex_pdflastobj:D } }
+\group_end:
+\cs_new:Npn \driver_pdf_object_ref:n #1
+ { \int_use:c { g_@@_pdf_object_ \tl_to_str:n {#1} _int } ~ 0 ~ R }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\driver_pdf_object_write:nn}
+% \begin{macro}[EXP]{\@@_exp_not_i:nn, \@@_exp_not_ii:nn}
+% Writing the data needs a little information about the structure of the
+% object.
+% \begin{macrocode}
+\group_begin:
+ \cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new_protected:Npn \driver_pdf_object_write:nn ##1##2
+ {
+ \tex_immediate:D #1 useobjnum ~
+ \int_use:c
+ { g_@@_pdf_object_ \tl_to_str:n {##1} _int }
+ \str_case_e:nn
+ { \prop_item:Nn \g_@@_pdf_object_prop {##1} }
+ {
+ { array } { { [ ~ \exp_not:n {##2} ~ ] } }
+ { dict } { { << ~ \exp_not:n {##2} ~ >> } }
+ { fstream }
+ {
+ stream ~ attr ~ { \@@_exp_not_i:nn ##2 } ~
+ file ~ { \@@_exp_not_ii:nn ##2 }
+ }
+ { stream }
+ {
+ stream ~ attr ~ { \@@_exp_not_i:nn ##2 } ~
+ { \@@_exp_not_ii:nn ##2 }
+ }
+ }
+ }
+ }
+ \cs_if_exist:NTF \tex_pdfextension:D
+ { \@@_tmp:w { \tex_pdfextension:D obj ~ } }
+ { \@@_tmp:w { \tex_pdfobj:D } }
+\group_end:
+\cs_new:Npn \@@_exp_not_i:nn #1#2 { \exp_not:n {#1} }
+\cs_new:Npn \@@_exp_not_ii:nn #1#2 { \exp_not:n {#2} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{PDF Structure}
+%
+% \begin{macro}{\driver_pdf_compresslevel:n}
+% \begin{macro}{\driver_pdf_objects_enable:, \driver_pdf_objects_disable:}
+% \begin{macro}{\@@_pdf_objectlevel:n}
+% Simply pass data to the engine.
+% \begin{macrocode}
+\cs_new_protected:Npx \driver_pdf_compresslevel:n #1
+ {
+ \cs_if_exist:NTF \tex_pdfcompresslevel:D
+ { \tex_pdfcompresslevel:D }
+ { \tex_pdfvariable:D compresslevel }
+ \exp_not:N \int_value:w \exp_not:N \int_eval:n {#1} \scan_stop:
+ }
+\cs_new_protected:Npn \driver_pdf_objects_enable:
+ { \@@_pdf_objectlevel:n { 2 } }
+\cs_new_protected:Npn \driver_pdf_objects_disable:
+ { \@@_pdf_objectlevel:n { 0 } }
+\cs_new_protected:Npx \@@_pdf_objectlevel:n #1
+ {
+ \cs_if_exist:NTF \tex_pdfobjcompresslevel:D
+ { \tex_pdfobjcompresslevel:D }
+ { \tex_pdfvariable:D objcompresslevel }
+ #1 \scan_stop:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \begin{macrocode}
%</pdfmode>
% \end{macrocode}
@@ -1704,7 +1995,7 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Images}
+% \subsubsection{Images}
%
% \begin{macro}
% {
@@ -1840,6 +2131,104 @@
% \end{macro}
% \end{macro}
%
+% \subsubsection{PDF Objects}
+%
+% \begin{variable}{\g_@@_pdf_object_int, \g_@@_pdf_object_prop}
+% For tracking objects to allow finalisation.
+% \begin{macrocode}
+\int_new:N \g_@@_pdf_object_int
+\prop_new:N \g_@@_pdf_object_prop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\driver_pdf_object_new:nn}
+% \begin{macro}[EXP]{\driver_pdf_object_ref:n}
+% Objects are tracked at the macro level, but we don't have to do anything
+% at this stage.
+% \begin{macrocode}
+\cs_new_protected:Npn \driver_pdf_object_new:nn #1#2
+ {
+ \int_gincr:N \g_@@_pdf_object_int
+ \int_const:cn
+ { g_@@_pdf_object_ \tl_to_str:n {#1} _int }
+ { \g_@@_pdf_object_int }
+ \prop_gput:Nnn \g_@@_pdf_object_prop {#1} {#2}
+ }
+\cs_new:Npn \driver_pdf_object_ref:n #1
+ { @l3obj \int_use:c { g_@@_pdf_object_ \tl_to_str:n {#1} _int } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\driver_pdf_object_write:nn}
+% \begin{macro}{\@@_pdf_object_write:nnn}
+% \begin{macro}
+% {
+% \@@_pdf_object_write_array:nn ,
+% \@@_pdf_object_write_dict:nn ,
+% \@@_pdf_object_write_fstream:nn ,
+% \@@_pdf_object_write_stream:nn
+% }
+% \begin{macro}{\@@_pdf_object_write_stream:nnnn}
+% This is where we choose the actual type.
+% \begin{macrocode}
+\cs_new_protected:Npn \driver_pdf_object_write:nn #1#2
+ {
+ \exp_args:Nx \@@_pdf_object_write:nnn
+ { \prop_item:Nn \g_@@_pdf_object_prop {#1} } {#1} {#2}
+ }
+\cs_new_protected:Npn \@@_pdf_object_write:nnn #1#2#3
+ { \use:c { @@_pdf_object_write_ #1 :nn } {#2} {#3} }
+\cs_new_protected:Npn \@@_pdf_object_write_array:nn #1#2
+ {
+ \@@_literal:x
+ {
+ pdf:obj ~ \driver_pdf_object_ref:n {#1} ~
+ [ ~ \exp_not:n {#2} ~ ]
+ }
+ }
+\cs_new_protected:Npn \@@_pdf_object_write_dict:nn #1#2
+ {
+ \@@_literal:x
+ {
+ pdf:obj ~ \driver_pdf_object_ref:n {#1} ~
+ << ~ \exp_not:n {#2} ~ >>
+ }
+ }
+\cs_new_protected:Npn \@@_pdf_object_write_fstream:nn #1#2
+ { \@@_pdf_object_write_stream:nnnn { f } {#1} #2 }
+\cs_new_protected:Npn \@@_pdf_object_write_stream:nn #1#2
+ { \@@_pdf_object_write_stream:nnnn { } {#1} #2 }
+\cs_new_protected:Npn \@@_pdf_object_write_stream:nnnn #1#2#3#4
+ {
+ \@@_literal:x
+ {
+ pdf: #1 stream ~ \driver_pdf_object_ref:n {#2} ~
+ ( \exp_not:n {#4} ) ~ << \exp_not:n {#3} >>
+
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{PDF Structure}
+%
+% \begin{macro}{\driver_pdf_compresslevel:n}
+% \begin{macro}{\driver_pdf_objects_enable:, \driver_pdf_objects_disable:}
+% Pass data to the driver: these are a one-shot.
+% \begin{macrocode}
+\cs_new_protected:Npn \driver_pdf_compresslevel:n #1
+ { \@@_literal:x { dvipdfmx:config~z~ \int_eval:n {#1} } }
+\cs_new_protected:Npn \driver_pdf_objects_enable: { }
+\cs_new_protected:Npn \driver_pdf_objects_disable:
+ { \@@_literal:n { dvipdfmx:config~C~0x40 } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macrocode}
%</dvipdfmx|xdvipdfmx>
% \end{macrocode}
@@ -1850,7 +2239,7 @@
%<*xdvipdfmx>
% \end{macrocode}
%
-% \subsection{Images}
+% \subsubsection{Images}
%
% \begin{macro}
% {\@@_image_getbb_jpg:n, \@@_image_getbb_pdf:n, \@@_image_getbb_png:n}
@@ -1955,7 +2344,7 @@
%<*dvipdfmx|pdfmode|xdvipdfmx>
% \end{macrocode}
%
-% \subsection{Drawing}
+% \subsubsection{Drawing}
%
% \begin{macro}{\@@_draw_literal:n, \@@_draw_literal:x}
% Pass data through using a dedicated interface.
@@ -2416,7 +2805,7 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Driver-specific auxiliaries}
+% \subsubsection{Driver-specific auxiliaries}
%
% \begin{macro}{\@@_scope_begin:n, \@@_scope_begin:x}
% In SVG transformations, clips and so on are attached directly to scopes so
@@ -2556,7 +2945,7 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Images}
+% \subsubsection{Images}
%
% \begin{macro}{\@@_image_getbb_png:n, \@@_image_getbb_jpg:n}
% These can be included by extracting the bounding box data.
@@ -2592,7 +2981,29 @@
% \end{macro}
% \end{macro}
%
-% \subsection{Drawing}
+% \subsubsection{PDF Features}
+%
+% \begin{macro}{\driver_pdf_object_new:n}
+% \begin{macro}[EXP]{\driver_pdf_object_ref:n}
+% \begin{macro}{\driver_pdf_ojbect_write:nn}
+% \begin{macro}{\driver_pdf_compresslevel:n}
+% \begin{macro}{\driver_pdf_objects_enable:, \driver_pdf_objects_disable:}
+% These are all no-ops.
+% \begin{macrocode}
+\cs_new_protected:Npn \driver_pdf_object_new:n #1 { }
+\cs_new:Npn \driver_pdf_object_ref:n #1 { }
+\cs_new_protected:Npn \driver_pdf_object_write:nn #1#2 { }
+\cs_new_protected:Npn \driver_pdf_compresslevel:n #1 { }
+\cs_new_protected:Npn \driver_pdf_objects_enable: { }
+\cs_new_protected:Npn \driver_pdf_objects_disable: { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{Drawing}
%
% \begin{macro}{\@@_draw_literal:n, \@@_draw_literal:x}
% The same as the more general literal call.