summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx504
1 files changed, 504 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx
new file mode 100644
index 00000000000..ef2eea9f56d
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx
@@ -0,0 +1,504 @@
+% \iffalse meta-comment
+%
+%% File: l3drivers-image.dtx
+%
+% Copyright (C) 2011-2019 The LaTeX3 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
+%
+% https://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel 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/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full,kernel]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3drivers-image} package\\ Driver image support^^A
+% }
+%
+% \author{^^A
+% The \LaTeX3 Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2019-04-21}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3drivers-image} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+%<@@=driver>
+% \end{macrocode}
+%
+% \subsection{\texttt{dvips} driver}
+%
+% \begin{macrocode}
+%<*dvips>
+% \end{macrocode}
+%
+% \begin{macro}{\@@_image_getbb_eps:n}
+% Simply use the generic function.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_image_getbb_eps:n \image_read_bb:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_image_include_eps:n}
+% The special syntax is relatively clear here: remember we need PostScript
+% sizes here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_include_eps:n #1
+ { \@@_literal:n { PSfile = #1 } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</dvips>
+% \end{macrocode}
+%
+% \subsection{\texttt{pdfmode} driver}
+%
+% \begin{macrocode}
+%<*pdfmode>
+% \end{macrocode}
+%
+% \begin{variable}{\l_@@_image_attr_tl}
+% In PDF mode, additional attributes of an image (such as page number) are
+% needed both to obtain the bounding box and when inserting the image: this
+% occurs as the image dictionary approach means they are read as part of
+% the bounding box operation. As such, it is easier to track additional
+% attributes using a dedicated |tl| rather than build up the same data
+% twice.
+% \begin{macrocode}
+\tl_new:N \l_@@_image_attr_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+% {\@@_image_getbb_jpg:n, \@@_image_getbb_pdf:n, \@@_image_getbb_png:n}
+% \begin{macro}
+% {\@@_image_getbb_auxi:n, \@@_image_getbb_auxii:n}
+% Getting the bounding box here requires us to box up the image and
+% measure it. To deal with the difference in feature support in bitmap
+% and vector images but keeping the common parts, there is a little work
+% to do in terms of auxiliaries. The key here is to notice that we need
+% two forms of the attributes: a \enquote{short} set to allow us to
+% track for caching, and the full form to pass to the primitive.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_getbb_jpg:n #1
+ {
+ \int_zero:N \l_image_page_int
+ \tl_clear:N \l_image_pagebox_tl
+ \tl_set:Nx \l_@@_image_attr_tl
+ {
+ \tl_if_empty:NF \l_image_decode_tl
+ { :D \l_image_decodearray_tl }
+ \bool_if:NT \l_image_interpolate_bool
+ { :I }
+ }
+ \tl_clear:N \l_@@_image_attr_tl
+ \@@_image_getbb_auxi:n {#1}
+ }
+\cs_new_eq:NN \@@_image_getbb_png:n \@@_image_getbb_jpg:n
+\cs_new_protected:Npn \@@_image_getbb_pdf:n #1
+ {
+ \tl_clear:N \l_image_decode_tl
+ \bool_set_false:N \l_image_interpolate_bool
+ \tl_set:Nx \l_@@_image_attr_tl
+ {
+ : \l_image_pagebox_tl
+ \int_compare:nNnT \l_image_page_int > 1
+ { :P \int_use:N \l_image_page_int }
+ }
+ \@@_image_getbb_auxi:n {#1}
+ }
+\cs_new_protected:Npn \@@_image_getbb_auxi:n #1
+ {
+ \image_bb_restore:xF { #1 \l_@@_image_attr_tl }
+ { \@@_image_getbb_auxii:n {#1} }
+ }
+% \begin{macrocode}
+% Measuring the image is done by boxing up: for PDF images we could
+% use |\tex_pdfximagebbox:D|, but if doesn't work for other types.
+% As the box always starts at $(0,0)$ there is no need to worry about
+% the lower-left position.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_getbb_auxii:n #1
+ {
+ \tex_immediate:D \tex_pdfximage:D
+ \bool_lazy_or:nnT
+ { \l_image_interpolate_bool }
+ { ! \tl_if_empty_p:N \l_image_decodearray_tl }
+ {
+ attr ~
+ {
+ \tl_if_empty:NF \l_image_decode_tl
+ { /Decode~[ \l_image_decodearray_tl ] }
+ \bool_if:NT \l_image_interpolate_bool
+ { /Interpolate~true }
+ }
+ }
+ \int_compare:nNnT \l_image_page_int > 0
+ { page ~ \int_use:N \l_image_page_int }
+ \tl_if_empty:NF \l_image_pagebox_tl
+ { \l_image_pagebox_tl }
+ {#1}
+ \hbox_set:Nn \l_@@_tmp_box
+ { \tex_pdfrefximage:D \tex_pdflastximage:D }
+ \dim_set:Nn \l_image_urx_dim { \box_wd:N \l_@@_tmp_box }
+ \dim_set:Nn \l_image_ury_dim { \box_ht:N \l_@@_tmp_box }
+ \int_const:cn { c_@@_image_ #1 \l_@@_image_attr_tl _int }
+ { \tex_the:D \tex_pdflastximage:D }
+ \image_bb_save:x { #1 \l_@@_image_attr_tl }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {\@@_image_include_jpg:n, \@@_image_include_pdf:n, \@@_image_include_png:n}
+% Images are already loaded for the measurement part of the code, so
+% inclusion is straight-forward, with only any attributes to worry about. The
+% latter carry through from determination of the bounding box.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_include_jpg:n #1
+ {
+ \tex_pdfrefximage:D
+ \int_use:c { c_@@_image_ #1 \l_@@_image_attr_tl _int }
+ }
+\cs_new_eq:NN \@@_image_include_pdf:n \@@_image_include_jpg:n
+\cs_new_eq:NN \@@_image_include_png:n \@@_image_include_jpg:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</pdfmode>
+% \end{macrocode}
+%
+% \subsection{\texttt{dvipdfmx} driver}
+%
+% \begin{macrocode}
+%<*dvipdfmx|xdvipdfmx>
+% \end{macrocode}
+%
+% \begin{macro}
+% {
+% \@@_image_getbb_eps:n, \@@_image_getbb_jpg:n,
+% \@@_image_getbb_pdf:n, \@@_image_getbb_png:n
+% }
+% Simply use the generic functions: only for \texttt{dvipdfmx} in the
+% extraction cases.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_image_getbb_eps:n \image_read_bb:n
+%<*dvipdfmx>
+\cs_new_protected:Npn \@@_image_getbb_jpg:n #1
+ {
+ \int_zero:N \l_image_page_int
+ \tl_clear:N \l_image_pagebox_tl
+ \image_extract_bb:n {#1}
+ }
+\cs_new_eq:NN \@@_image_getbb_png:n \@@_image_getbb_jpg:n
+\cs_new_protected:Npn \@@_image_getbb_pdf:n #1
+ {
+ \tl_clear:N \l_image_decode_tl
+ \bool_set_false:N \l_image_interpolate_bool
+ \image_extract_bb:n {#1}
+ }
+%</dvipdfmx>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_image_int}
+% Used to track the object number associated with each image.
+% \begin{macrocode}
+\int_new:N \g_@@_image_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+% {
+% \@@_image_include_eps:n, \@@_image_include_jpg:n,
+% \@@_image_include_pdf:n, \@@_image_include_png:n
+% }
+% \begin{macro}{\@@_image_include_auxi:nn}
+% \begin{macro}{\@@_image_include_auxii:nnn, \@@_image_include_auxii:xnn}
+% \begin{macro}{\@@_image_include_auxiii:nn}
+% The special syntax depends on the file type. There is a difference in
+% how PDF images are best handled between |dvipdfmx| and |xdvipdfmx|: for
+% the latter it is better to use the primitive route. The relevant code for
+% that is included later in this file.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_include_eps:n #1
+ {
+ \@@_literal:n { PSfile = #1 }
+ }
+\cs_new_protected:Npn \@@_image_include_jpg:n #1
+ { \@@_image_include_auxi:nn {#1} { image } }
+\cs_new_eq:NN \@@_image_include_png:n \@@_image_include_jpg:n
+%<*dvipdfmx>
+\cs_new_protected:Npn \@@_image_include_pdf:n #1
+ { \@@_image_include_auxi:nn {#1} { epdf } }
+%</dvipdfmx>
+% \end{macrocode}
+% Image inclusion is set up to use the fact that each image is stored in
+% the PDF as an XObject. This means that we can include repeated images
+% only once and refer to them. To allow that, track the nature of each
+% image: much the same as for the direct PDF mode case.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_include_auxi:nn #1#2
+ {
+ \@@_image_include_auxii:xnn
+ {
+ \tl_if_empty:NF \l_image_pagebox_tl
+ { : \l_image_pagebox_tl }
+ \int_compare:nNnT \l_image_page_int > 1
+ { :P \int_use:N \l_image_page_int }
+ \tl_if_empty:NF \l_image_decode_tl
+ { :D \l_image_decodearray_tl }
+ \bool_if:NT \l_image_interpolate_bool
+ { :I }
+ }
+ {#1} {#2}
+ }
+\cs_new_protected:Npn \@@_image_include_auxii:nnn #1#2#3
+ {
+ \int_if_exist:cTF { c_@@_image_ #2#1 _int }
+ {
+ \@@_literal:x
+ { pdf:usexobj~@image \int_use:c { c_@@_image_ #2#1 _int } }
+ }
+ { \@@_image_include_auxiii:nn {#2} {#1} {#3} }
+ }
+\cs_generate_variant:Nn \@@_image_include_auxii:nnn { x }
+% \end{macrocode}
+% Inclusion using the specials is relatively straight-forward, but there
+% is one wrinkle. To get the |pagebox| correct for PDF images in all cases,
+% it is necessary to provide both that information and the |bbox| argument:
+% odd things happen otherwise!
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_include_auxiii:nnn #1#2#3
+ {
+ \int_gincr:N \g_@@_image_int
+ \int_const:cn { c_@@_image_ #1#2 _int } { \g_@@_image_int }
+ \@@_literal:x
+ {
+ pdf:#3~
+ @image \int_use:c { c_@@_image_ #1#2 _int }
+ \int_compare:nNnT \l_image_page_int > 1
+ { page ~ \int_use:N \l_image_page_int \c_space_tl }
+ \tl_if_empty:NF \l_image_pagebox_tl
+ {
+ pagebox ~ \l_image_pagebox_tl \c_space_tl
+ bbox ~
+ \dim_to_decimal_in_bp:n \l_image_llx_dim \c_space_tl
+ \dim_to_decimal_in_bp:n \l_image_lly_dim \c_space_tl
+ \dim_to_decimal_in_bp:n \l_image_urx_dim \c_space_tl
+ \dim_to_decimal_in_bp:n \l_image_ury_dim \c_space_tl
+ }
+ (#1)
+ \bool_lazy_or:nnT
+ { \l_image_interpolate_bool }
+ { ! \tl_if_empty_p:N \l_image_decodearray_tl }
+ {
+ <<
+ \tl_if_empty:NF \l_image_decode_tl
+ { /Decode~[ \l_image_decodearray_tl ] }
+ \bool_if:NT \l_image_interpolate_bool
+ { /Interpolate~true> }
+ >>
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</dvipdfmx|xdvipdfmx>
+% \end{macrocode}
+%
+% \subsection{\texttt{xdvipdfmx} driver}
+%
+% \begin{macrocode}
+%<*xdvipdfmx>
+% \end{macrocode}
+%
+% \subsubsection{Images}
+%
+% \begin{macro}
+% {\@@_image_getbb_jpg:n, \@@_image_getbb_pdf:n, \@@_image_getbb_png:n}
+% \begin{macro}{\@@_image_getbb_auxi:nN}
+% \begin{macro}{\@@_image_getbb_auxii:nnN, \@@_image_getbb_auxii:VnN}
+% \begin{macro}{\@@_image_getbb_auxiii:nNnn}
+% \begin{macro}{\@@_image_getbb_auxiv:nnNnn, \@@_image_getbb_auxiv:VnNnn}
+% \begin{macro}{\@@_image_getbb_auxv:nNnn, \@@_image_getbb_auxv:nNnn}
+% \begin{macro}[EXP]{\@@_image_getbb_pagebox:w}
+% For \texttt{xdvipdfmx}, there are two primitives that allow us to obtain
+% the bounding box without needing \texttt{extractbb}. The only complexity
+% is passing the various minor variations to a common core process. The
+% \XeTeX{} primitive omits the text |box| from the page box specification,
+% so there is also some \enquote{trimming} to do here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_getbb_jpg:n #1
+ {
+ \int_zero:N \l_image_page_int
+ \tl_clear:N \l_image_pagebox_tl
+ \@@_image_getbb_auxi:nN {#1} \tex_XeTeXpicfile:D
+ }
+\cs_new_eq:NN \@@_image_getbb_png:n \@@_image_getbb_jpg:n
+\cs_new_protected:Npn \@@_image_getbb_pdf:n #1
+ {
+ \tl_clear:N \l_image_decode_tl
+ \bool_set_false:N \l_image_interpolate_bool
+ \@@_image_getbb_auxi:nN {#1} \tex_XeTeXpdffile:D
+ }
+\cs_new_protected:Npn \@@_image_getbb_auxi:nN #1#2
+ {
+ \int_compare:nNnTF \l_image_page_int > 1
+ { \@@_image_getbb_auxii:VnN \l_image_page_int {#1} #2 }
+ { \@@_image_getbb_auxiii:nNnn {#1} #2 }
+ }
+\cs_new_protected:Npn \@@_image_getbb_auxii:nnN #1#2#3
+ { \@@_image_getbb_aux:nNnn {#2} #3 { :P #1 } { page #1 } }
+\cs_generate_variant:Nn \@@_image_getbb_auxii:nnN { V }
+\cs_new_protected:Npn \@@_image_getbb_auxiii:nNnn #1#2#3#4
+ {
+ \tl_if_empty:NTF \l_image_pagebox_tl
+ { \@@_image_getbb_auxiv:VnNnn \l_image_pagebox_tl }
+ { \@@_image_getbb_auxv:nNnn }
+ {#1} #2 {#3} {#4}
+ }
+\cs_new_protected:Npn \@@_image_getbb_auxiv:nnNnn #1#2#3#4#5
+ {
+ \use:x
+ {
+ \@@_image_getbb_auxv:nNnn {#2} #3 { : #1 #4 }
+ { #5 ~ \@@_image_getbb_pagebox:w #1 }
+ }
+ }
+\cs_generate_variant:Nn \@@_image_getbb_auxiv:nnNnn { V }
+\cs_new_protected:Npn \@@_image_getbb_auxv:nNnn #1#2#3#4
+ {
+ \image_bb_restore:nF {#1#3}
+ { \@@_image_getbb_auxvi:nNnn {#1} #2 {#3} {#4} }
+ }
+\cs_new_protected:Npn \@@_image_getbb_auxvi:nNnn #1#2#3#4
+ {
+ \hbox_set:Nn \l_@@_tmp_box { #2 #1 ~ #4 }
+ \dim_set:Nn \l_image_utx_dim { \box_wd:N \l_@@_tmp_box }
+ \dim_set:Nn \l_image_ury_dim { \box_ht:N \l_@@_tmp_box }
+ \image_bb_save:n {#1#3}
+ }
+\cs_new:Npn \@@_image_getbb_pagebox:w #1 box {#1}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_image_include_pdf:n}
+% For PDF images, properly supporting the |pagebox| concept in \XeTeX{}
+% is best done using the |\tex_XeTeXpdffile:D| primitive. The syntax here
+% is the same as for the image measurement part, although we know at this
+% stage that there must be some valid setting for \cs{l_image_pagebox_tl}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_include_pdf:n #1
+ {
+ \tex_XeTeXpdffile:D "#1" ~
+ \int_compare:nNnT \l_image_page_int > 0
+ { page~ \int_use:N \l_image_page_int }
+ \@@_image_getbb_auxiv:VnNnn \l_image_pagebox_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</xdvipdfmx>
+% \end{macrocode}
+%
+% \subsection{\texttt{dvisvgm} driver}
+%
+% \begin{macrocode}
+%<*dvisvgm>
+% \end{macrocode}
+%
+% \begin{macro}{\@@_image_getbb_png:n, \@@_image_getbb_jpg:n}
+% These can be included by extracting the bounding box data.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_image_getbb_png:n \image_extract_bb:n
+\cs_new_eq:NN \@@_image_getbb_jpg:n \image_extract_bb:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_image_include_png:n, \@@_image_include_jpg:n}
+% \begin{macro}{\@@_image_include_bitmap_quote:w}
+% The driver here has built-in support for basic image inclusion (see
+% \texttt{dvisvgm.def} for a more complex approach, needed if clipping,
+% \emph{etc.}, is covered at the image driver level). The only issue is
+% that |#1| must be quote-corrected. The \texttt{dvisvgm:img} operation
+% quotes the file name, but if it is already quoted (contains spaces)
+% then we have an issue: we simply strip off any quotes as a result.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_image_include_png:n #1
+ {
+ \@@_literal:x
+ {
+ dvisvgm:img~
+ \dim_to_decimal:n { \l_image_ury_dim } ~
+ \dim_to_decimal:n { \l_image_ury_dim } ~
+ \@@_image_include_bitmap_quote:w #1 " #1 " \q_stop
+ }
+ }
+\cs_new_eq:NN \@@_image_include_jpg:n \@@_image_include_png:n
+\cs_new:Npn \@@_image_include_bitmap_quote:w #1 " #2 " #3 \q_stop
+ { " #2 " }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</dvisvgm>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex