diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3drivers-image.dtx | 504 |
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 |