summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx')
-rw-r--r--Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx931
1 files changed, 931 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx
new file mode 100644
index 00000000000..e20457368da
--- /dev/null
+++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx
@@ -0,0 +1,931 @@
+% \iffalse meta-comment
+%
+%% File: l3backend-graphics.dtx
+%
+% Copyright (C) 2019-2024 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
+%
+% https://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3backend 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 \pkg{l3backend-graphics} module\\ Backend graphics support^^A
+% }
+%
+% \author{^^A
+% The \LaTeX{} Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3backend-graphics} implementation}
+%
+% \begin{macrocode}
+%<*package>
+%<@@=graphics>
+% \end{macrocode}
+%
+% \begin{macro}{\@@_backend_loaded:n}
+% To deal with file load ordering. Plain users are on their own.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_loaded:n #1
+ {
+ \cs_if_exist:NTF \hook_gput_code:nnn
+ {
+ \hook_gput_code:nnn
+ { package / l3graphics / after }
+ { backend }
+ {#1}
+ }
+ {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{\texttt{dvips} backend}
+%
+% \begin{macrocode}
+%<*dvips>
+% \end{macrocode}
+%
+% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq}
+% \begin{macrocode}
+\@@_backend_loaded:n
+ { \seq_set_from_clist:Nn \l_graphics_search_ext_seq { .eps , .ps } }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_backend_getbb_eps:n, \@@_backend_getbb_ps:n}
+% Simply use the generic function.
+% \begin{macrocode}
+\@@_backend_loaded:n
+ {
+ \cs_new_eq:NN \@@_backend_getbb_eps:n \@@_read_bb:n
+ \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_read_bb:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_include_eps:n, \@@_backend_include_ps:n}
+% The special syntax is relatively clear here: remember we need PostScript
+% sizes here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_include_eps:n #1
+ {
+ \__kernel_backend_literal:e
+ {
+ PSfile = #1 \c_space_tl
+ llx = \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl
+ lly = \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl
+ urx = \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl
+ ury = \dim_to_decimal_in_bp:n \l_@@_ury_dim
+ }
+ }
+\cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_get_pagecount:n}
+% \begin{macrocode}
+\@@_backend_loaded:n
+ { \cs_new_eq:NN \@@_backend_get_pagecount:n \@@_get_pagecount:n }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</dvips>
+% \end{macrocode}
+%
+% \subsection{\LuaTeX{} and \pdfTeX{} backends}
+%
+% \begin{macrocode}
+%<*luatex|pdftex>
+% \end{macrocode}
+%
+% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq}
+% \begin{macrocode}
+\@@_backend_loaded:n
+ {
+ \seq_set_from_clist:Nn
+ \l_graphics_search_ext_seq
+ { .pdf , .eps , .ps , .png , .jpg , .jpeg }
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_attr_tl}
+% In PDF mode, additional attributes of an graphic (such as page number) are
+% needed both to obtain the bounding box and when inserting the graphic: this
+% occurs as the graphic 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_@@_attr_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+% {
+% \@@_backend_getbb_jpg:n ,
+% \@@_backend_getbb_jpeg:n ,
+% \@@_backend_getbb_pdf:n ,
+% \@@_backend_getbb_png:n
+% }
+% \begin{macro}
+% {
+% \@@_backend_getbb_auxi:n ,
+% \@@_backend_getbb_auxii:n ,
+% \@@_backend_getbb_auxiii:n
+% }
+% \begin{macro}[EXP]{\@@_backend_dequote:w}
+% Getting the bounding box here requires us to box up the graphic and
+% measure it. To deal with the difference in feature support in bitmap
+% and vector graphics 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 \@@_backend_getbb_jpg:n #1
+ {
+ \int_zero:N \l_@@_page_int
+ \tl_clear:N \l_@@_pagebox_tl
+ \tl_set:Ne \l_@@_attr_tl
+ {
+ \tl_if_empty:NF \l_@@_decodearray_str
+ { :D \l_@@_decodearray_str }
+ \bool_if:NT \l_@@_interpolate_bool
+ { :I }
+ \str_if_empty:NF \l_@@_pdf_str
+ { :X \l_@@_pdf_str }
+ }
+ \@@_backend_getbb_auxi:n {#1}
+ }
+\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n
+\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n
+\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1
+ {
+ \tl_clear:N \l_@@_decodearray_str
+ \bool_set_false:N \l_@@_interpolate_bool
+ \tl_set:Ne \l_@@_attr_tl
+ {
+ : \l_@@_pagebox_tl
+ \int_compare:nNnT \l_@@_page_int > 1
+ { :P \int_use:N \l_@@_page_int }
+ \str_if_empty:NF \l_@@_pdf_str
+ { :X \l_@@_pdf_str }
+ }
+ \@@_backend_getbb_auxi:n {#1}
+ }
+\cs_new_protected:Npn \@@_backend_getbb_auxi:n #1
+ {
+ \@@_bb_restore:eF { #1 \l_@@_attr_tl }
+ { \@@_backend_getbb_auxii:n {#1} }
+ }
+% \end{macrocode}
+% Measuring the graphic is done by boxing up: for PDF graphics 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. Quotes need to be \emph{removed} as \LuaTeX{}
+% does not like them here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_getbb_auxii:n #1
+ {
+ \exp_args:Ne \@@_backend_getbb_auxiii:n
+ { \@@_backend_dequote:w #1 " #1 " \s_@@_stop }
+ \int_const:cn { c_@@_ #1 \l_@@_attr_tl _int }
+ { \tex_the:D \tex_pdflastximage:D }
+ \@@_bb_save:e { #1 \l_@@_attr_tl }
+ }
+\cs_new_protected:Npn \@@_backend_getbb_auxiii:n #1
+ {
+ \tex_immediate:D \tex_pdfximage:D
+ \bool_lazy_any:nT
+ {
+ { \l_@@_interpolate_bool }
+ { ! \tl_if_empty_p:N \l_@@_decodearray_str }
+ { ! \str_if_empty_p:N \l_@@_pdf_str }
+ }
+ {
+ attr ~
+ {
+ \tl_if_empty:NF \l_@@_decodearray_str
+ { /Decode~[ \l_@@_decodearray_str ] }
+ \bool_if:NT \l_@@_interpolate_bool
+ { /Interpolate~true }
+ \l_@@_pdf_str
+ }
+ }
+ \int_compare:nNnT \l_@@_page_int > 0
+ { page ~ \int_use:N \l_@@_page_int }
+ \tl_if_empty:NF \l_@@_pagebox_tl
+ { \l_@@_pagebox_tl }
+ {#1}
+ \hbox_set:Nn \l_@@_internal_box
+ { \tex_pdfrefximage:D \tex_pdflastximage:D }
+ \dim_set:Nn \l_@@_urx_dim { \box_wd:N \l_@@_internal_box }
+ \dim_set:Nn \l_@@_ury_dim { \box_ht:N \l_@@_internal_box }
+ }
+\cs_new:Npn \@@_backend_dequote:w #1 " #2 " #3 \s_@@_stop {#2}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_backend_include_jpg:n ,
+% \@@_backend_include_jpeg:n ,
+% \@@_backend_include_pdf:n ,
+% \@@_backend_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 \@@_backend_include_jpg:n #1
+ {
+ \tex_pdfrefximage:D
+ \int_use:c { c_@@_ #1 \l_@@_attr_tl _int }
+ }
+\cs_new_eq:NN \@@_backend_include_jpeg:n \@@_backend_include_jpg:n
+\cs_new_eq:NN \@@_backend_include_pdf:n \@@_backend_include_jpg:n
+\cs_new_eq:NN \@@_backend_include_png:n \@@_backend_include_jpg:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_getbb_eps:n, \@@_backend_getbb_ps:n}
+% \begin{macro}{\@@_backend_getbb_eps:nm}
+% \begin{macro}{\@@_backend_include_eps:n, \@@_backend_include_ps:n}
+% \begin{variable}
+% {\l_@@_backend_dir_str, \l_@@_backend_name_str, \l_@@_backend_ext_str}
+% EPS graphics may be included in \LuaTeX{}/pdfTeX{} by conversion to
+% PDF: this requires restricted shell escape. Modelled on the \pkg{epstopdf}
+% \LaTeXe{} package, but simplified, conversion takes place here if we have
+% shell access.
+% \begin{macrocode}
+\sys_if_shell:T
+ {
+ \str_new:N \l_@@_backend_dir_str
+ \str_new:N \l_@@_backend_name_str
+ \str_new:N \l_@@_backend_ext_str
+ \cs_new_protected:Npn \@@_backend_getbb_eps:n #1
+ {
+ \file_parse_full_name:nNNN {#1}
+ \l_@@_backend_dir_str
+ \l_@@_backend_name_str
+ \l_@@_backend_ext_str
+ \exp_args:Ne \@@_backend_getbb_eps:nn
+ {
+ \exp_args:Ne \__kernel_file_name_quote:n
+ {
+ \l_@@_backend_name_str
+ - \str_tail:N \l_@@_backend_ext_str
+ -converted-to.pdf
+ }
+ }
+ {#1}
+ }
+ \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_backend_getbb_eps:n
+ \cs_new_protected:Npn \@@_backend_getbb_eps:nn #1#2
+ {
+ \file_compare_timestamp:nNnT {#2} > {#1}
+ {
+ \sys_shell_now:n
+ { repstopdf ~ #2 ~ #1 }
+ }
+ \tl_set:Nn \l_@@_final_name_str {#1}
+ \@@_backend_getbb_pdf:n {#1}
+ }
+ \cs_new_protected:Npn \@@_backend_include_eps:n #1
+ {
+ \file_parse_full_name:nNNN {#1}
+ \l_@@_backend_dir_str \l_@@_backend_name_str \l_@@_backend_ext_str
+ \exp_args:Ne \@@_backend_include_pdf:n
+ {
+ \exp_args:Ne \__kernel_file_name_quote:n
+ {
+ \l_@@_backend_name_str
+ - \str_tail:N \l_@@_backend_ext_str
+ -converted-to.pdf
+ }
+ }
+ }
+ \cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n
+ }
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_get_pagecount:n}
+% Simply load and store.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_get_pagecount:n #1
+ {
+ \tex_pdfximage:D {#1}
+ \int_const:cn { c_@@_ #1 _pages_int }
+ { \int_use:N \tex_pdflastximagepages:D }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</luatex|pdftex>
+% \end{macrocode}
+%
+% \subsection{\texttt{dvipdfmx} backend}
+%
+% \begin{macrocode}
+%<*dvipdfmx|xetex>
+% \end{macrocode}
+%
+% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq}
+% \begin{macrocode}
+\@@_backend_loaded:n
+ {
+ \seq_set_from_clist:Nn \l_graphics_search_ext_seq
+ { .pdf , .eps , .ps , .png , .jpg , .jpeg , .bmp }
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+% {
+% \@@_backend_getbb_eps:n , \@@_backend_getbb_ps:n ,
+% \@@_backend_getbb_jpg:n , \@@_backend_getbb_jpeg:n ,
+% \@@_backend_getbb_pdf:n , \@@_backend_getbb_png:n ,
+% \@@_backend_getbb_bmp:n
+% }
+% Simply use the generic functions: only for \texttt{dvipdfmx} in the
+% extraction cases.
+% \begin{macrocode}
+\@@_backend_loaded:n
+ {
+ \cs_new_eq:NN \@@_backend_getbb_eps:n \@@_read_bb:n
+ \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_read_bb:n
+ }
+%<*dvipdfmx>
+\cs_new_protected:Npn \@@_backend_getbb_jpg:n #1
+ {
+ \int_zero:N \l_@@_page_int
+ \tl_clear:N \l_@@_pagebox_tl
+ \@@_extract_bb:n {#1}
+ }
+\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n
+\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n
+\cs_new_eq:NN \@@_backend_getbb_bmp:n \@@_backend_getbb_jpg:n
+\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1
+ {
+ \tl_clear:N \l_@@_decodearray_str
+ \bool_set_false:N \l_@@_interpolate_bool
+ \@@_extract_bb:n {#1}
+ }
+%</dvipdfmx>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_track_int}
+% Used to track the object number associated with each graphic.
+% \begin{macrocode}
+\int_new:N \g_@@_track_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+% {
+% \@@_backend_include_eps:n , \@@_backend_include_ps:n ,
+% \@@_backend_include_jpg:n , \@@_backend_include_jpseg:n ,
+% \@@_backend_include_pdf:n , \@@_backend_include_png:n ,
+% \@@_backend_include_bmp:n ,
+% }
+% \begin{macro}{\@@_backend_include_auxi:nn}
+% \begin{macro}{\@@_backend_include_auxii:nnn, \@@_backend_include_auxii:enn}
+% \begin{macro}{\@@_backend_include_auxiii:nnn}
+% The special syntax depends on the file type. There is a difference in
+% how PDF graphics are best handled between |dvipdfmx| and \XeTeX{}: 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 \@@_backend_include_eps:n #1
+ {
+ \__kernel_backend_literal:e
+ {
+ PSfile = #1 \c_space_tl
+ llx = \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl
+ lly = \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl
+ urx = \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl
+ ury = \dim_to_decimal_in_bp:n \l_@@_ury_dim
+ }
+ }
+\cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n
+\cs_new_protected:Npn \@@_backend_include_jpg:n #1
+ { \@@_backend_include_auxi:nn {#1} { image } }
+\cs_new_eq:NN \@@_backend_include_jpeg:n \@@_backend_include_jpg:n
+\cs_new_eq:NN \@@_backend_include_png:n \@@_backend_include_jpg:n
+\cs_new_eq:NN \@@_backend_include_bmp:n \@@_backend_include_jpg:n
+%<*dvipdfmx>
+\cs_new_protected:Npn \@@_backend_include_pdf:n #1
+ { \@@_backend_include_auxi:nn {#1} { epdf } }
+%</dvipdfmx>
+% \end{macrocode}
+% Graphic 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 \@@_backend_include_auxi:nn #1#2
+ {
+ \@@_backend_include_auxii:enn
+ {
+ \tl_if_empty:NF \l_@@_pagebox_tl
+ { : \l_@@_pagebox_tl }
+ \int_compare:nNnT \l_@@_page_int > 1
+ { :P \int_use:N \l_@@_page_int }
+ \tl_if_empty:NF \l_@@_decodearray_str
+ { :D \l_@@_decodearray_str }
+ \bool_if:NT \l_@@_interpolate_bool
+ { :I }
+ }
+ {#1} {#2}
+ }
+\cs_new_protected:Npn \@@_backend_include_auxii:nnn #1#2#3
+ {
+ \int_if_exist:cTF { c_@@_ #2#1 _int }
+ {
+ \__kernel_backend_literal:e
+ { pdf:usexobj~@graphic \int_use:c { c_@@_ #2#1 _int } }
+ }
+ { \@@_backend_include_auxiii:nnn {#2} {#1} {#3} }
+ }
+\cs_generate_variant:Nn \@@_backend_include_auxii:nnn { e }
+% \end{macrocode}
+% Inclusion using the specials is relatively straight-forward, but there
+% is one wrinkle. To get the |pagebox| correct for PDF graphics 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 \@@_backend_include_auxiii:nnn #1#2#3
+ {
+ \int_gincr:N \g_@@_track_int
+ \int_const:cn { c_@@_ #1#2 _int } { \g_@@_track_int }
+ \__kernel_backend_literal:e
+ {
+ pdf:#3~
+ @graphic \int_use:c { c_@@_ #1#2 _int } ~
+ \int_compare:nNnT \l_@@_page_int > 1
+ { page ~ \int_use:N \l_@@_page_int \c_space_tl }
+ \tl_if_empty:NF \l_@@_pagebox_tl
+ {
+ pagebox ~ \l_@@_pagebox_tl \c_space_tl
+ bbox ~
+ \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl
+ \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl
+ \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl
+ \dim_to_decimal_in_bp:n \l_@@_ury_dim \c_space_tl
+ }
+ (#1)
+ \bool_lazy_or:nnT
+ { \l_@@_interpolate_bool }
+ { ! \tl_if_empty_p:N \l_@@_decodearray_str }
+ {
+ <<
+ \tl_if_empty:NF \l_@@_decodearray_str
+ { /Decode~[ \l_@@_decodearray_str ] }
+ \bool_if:NT \l_@@_interpolate_bool
+ { /Interpolate~true }
+ >>
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_get_pagecount:n}
+% \begin{macrocode}
+%<*dvipdfmx>
+\@@_backend_loaded:n
+ { \cs_new_eq:NN \@@_backend_get_pagecount:n \@@_get_pagecount:n }
+%</dvipdfmx>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</dvipdfmx|xetex>
+% \end{macrocode}
+%
+% \subsection{\XeTeX{} backend}
+%
+% \begin{macrocode}
+%<*xetex>
+% \end{macrocode}
+%
+% \begin{macro}
+% {
+% \@@_backend_getbb_jpg:n ,
+% \@@_backend_getbb_jpeg:n ,
+% \@@_backend_getbb_pdf:n ,
+% \@@_backend_getbb_png:n ,
+% \@@_backend_getbb_bmp:n
+% }
+% \begin{macro}{\@@_backend_getbb_auxi:nN}
+% \begin{macro}{\@@_backend_getbb_auxii:nnN, \@@_backend_getbb_auxii:VnN}
+% \begin{macro}{\@@_backend_getbb_auxiii:nNnn}
+% \begin{macro}{\@@_backend_getbb_auxiv:nnNnn, \@@_backend_getbb_auxiv:VnNnn}
+% \begin{macro}{\@@_backend_getbb_auxv:nNnn, \@@_backend_getbb_auxv:nNnn}
+% \begin{macro}[EXP]{\@@_backend_getbb_pagebox:w}
+% For \XeTeX{}, 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 \@@_backend_getbb_jpg:n #1
+ {
+ \int_zero:N \l_@@_page_int
+ \tl_clear:N \l_@@_pagebox_tl
+ \@@_backend_getbb_auxi:nN {#1} \tex_XeTeXpicfile:D
+ }
+\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n
+\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n
+\cs_new_eq:NN \@@_backend_getbb_bmp:n \@@_backend_getbb_jpg:n
+\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1
+ {
+ \tl_clear:N \l_@@_decodearray_str
+ \bool_set_false:N \l_@@_interpolate_bool
+ \@@_backend_getbb_auxi:nN {#1} \tex_XeTeXpdffile:D
+ }
+\cs_new_protected:Npn \@@_backend_getbb_auxi:nN #1#2
+ {
+ \int_compare:nNnTF \l_@@_page_int > 1
+ { \@@_backend_getbb_auxii:VnN \l_@@_page_int {#1} #2 }
+ { \@@_backend_getbb_auxiii:nNnn {#1} #2 { :P 1 } { page 1 } }
+ }
+\cs_new_protected:Npn \@@_backend_getbb_auxii:nnN #1#2#3
+ { \@@_backend_getbb_auxiii:nNnn {#2} #3 { :P #1 } { page #1 } }
+\cs_generate_variant:Nn \@@_backend_getbb_auxii:nnN { V }
+\cs_new_protected:Npn \@@_backend_getbb_auxiii:nNnn #1#2#3#4
+ {
+ \tl_if_empty:NTF \l_@@_pagebox_tl
+ { \@@_backend_getbb_auxiv:VnNnn \l_@@_pagebox_tl }
+ { \@@_backend_getbb_auxv:nNnn }
+ {#1} #2 {#3} {#4}
+ }
+\cs_new_protected:Npn \@@_backend_getbb_auxiv:nnNnn #1#2#3#4#5
+ {
+ \use:e
+ {
+ \@@_backend_getbb_auxv:nNnn {#2} #3 { : #1 #4 }
+ {
+ #5
+ \tl_if_blank:nF {#1}
+ { \c_space_tl \@@_backend_getbb_pagebox:w #1 }
+ }
+ }
+ }
+\cs_generate_variant:Nn \@@_backend_getbb_auxiv:nnNnn { V }
+\cs_new_protected:Npn \@@_backend_getbb_auxv:nNnn #1#2#3#4
+ {
+ \@@_bb_restore:nF {#1#3}
+ { \@@_backend_getbb_auxvi:nNnn {#1} #2 {#3} {#4} }
+ }
+\cs_new_protected:Npn \@@_backend_getbb_auxvi:nNnn #1#2#3#4
+ {
+ \hbox_set:Nn \l_@@_internal_box { #2 #1 ~ #4 }
+ \dim_set:Nn \l_@@_urx_dim { \box_wd:N \l_@@_internal_box }
+ \dim_set:Nn \l_@@_ury_dim { \box_ht:N \l_@@_internal_box }
+ \@@_bb_save:n {#1#3}
+ }
+\cs_new:Npn \@@_backend_getbb_pagebox:w #1 box {#1}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_include_pdf:n}
+% For PDF graphics, 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 graphic measurement part, although we know at this
+% stage that there must be some valid setting for \cs{l_@@_pagebox_tl}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_include_pdf:n #1
+ {
+ \tex_XeTeXpdffile:D #1 ~
+ \int_compare:nNnT \l_@@_page_int > 0
+ { page ~ \int_use:N \l_@@_page_int \c_space_tl }
+ \exp_after:wN \@@_backend_getbb_pagebox:w \l_@@_pagebox_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_get_pagecount:n}
+% Very little to do here other than cover the case of a non-PDF file.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_get_pagecount:n #1
+ {
+ \int_const:cn { c_@@_ #1 _pages_int }
+ {
+ \int_max:nn
+ { \int_use:N \tex_XeTeXpdfpagecount:D #1 ~ }
+ { 1 }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</xetex>
+% \end{macrocode}
+%
+% \subsection{\texttt{dvisvgm} backend}
+%
+% \begin{macrocode}
+%<*dvisvgm>
+% \end{macrocode}
+%
+% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq}
+% \begin{macrocode}
+\@@_backend_loaded:n
+ {
+ \seq_set_from_clist:Nn
+ \l_graphics_search_ext_seq
+ { .svg , .pdf , .eps , .ps , .png , .jpg , .jpeg }
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_backend_getbb_svg:n}
+% \begin{macro}{\@@_backend_getbb_svg_auxi:nNn}
+% \begin{macro}{\@@_backend_getbb_svg_auxii:w}
+% \begin{macro}
+% {
+% \@@_backend_getbb_svg_auxiii:Nw ,
+% \@@_backend_getbb_svg_auxiv:Nw ,
+% \@@_backend_getbb_svg_auxv:Nw
+% }
+% \begin{macro}{\@@_backend_getbb_svg_auxvi:Nn}
+% \begin{macro}{\@@_backend_getbb_svg_auxvii:w}
+% This is relatively similar to reading bounding boxes for |.eps| files. Life
+% is though made more tricky as we cannot pick a single line for the data. So
+% we have to loop until we collect up both height and width. To do that, we
+% can use a marker value. We also have to allow for the default units of the
+% lengths: they are big points and may be omitted.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_getbb_svg:n #1
+ {
+ \@@_bb_restore:nF {#1}
+ {
+ \ior_open:Nn \l_@@_internal_ior {#1}
+ \ior_if_eof:NTF \l_@@_internal_ior
+ { \msg_error:nnn { graphics } { graphic-not-found } {#1} }
+ {
+ \dim_zero:N \l_@@_llx_dim
+ \dim_zero:N \l_@@_lly_dim
+ \dim_set:Nn \l_@@_urx_dim { -\c_max_dim }
+ \dim_set:Nn \l_@@_ury_dim { -\c_max_dim }
+ \ior_str_map_inline:Nn \l_@@_internal_ior
+ {
+ \dim_compare:nNnT \l_@@_urx_dim = { -\c_max_dim }
+ {
+ \@@_backend_getbb_svg_auxi:nNn
+ { width } \l_@@_urx_dim {##1}
+ }
+ \dim_compare:nNnT \l_@@_ury_dim = { -\c_max_dim }
+ {
+ \@@_backend_getbb_svg_auxi:nNn
+ { height } \l_@@_ury_dim {##1}
+ }
+ \bool_lazy_and:nnF
+ { \dim_compare_p:nNn \l_@@_urx_dim = { -\c_max_dim } }
+ { \dim_compare_p:nNn \l_@@_ury_dim = { -\c_max_dim } }
+ { \ior_map_break: }
+ }
+ \@@_bb_save:n {#1}
+ }
+ \ior_close:N \l_@@_internal_ior
+ }
+ }
+\cs_new_protected:Npn \@@_backend_getbb_svg_auxi:nNn #1#2#3
+ {
+ \use:e
+ {
+ \cs_set_protected:Npn \@@_backend_getbb_svg_auxii:w
+ ##1 \tl_to_str:n {#1} = ##2 \tl_to_str:n {#1} = ##3
+ \s_@@_stop
+ }
+ {
+ \tl_if_blank:nF {##2}
+ {
+ \peek_remove_spaces:n
+ {
+ \peek_meaning:NTF ' % '
+ { \@@_backend_getbb_svg_auxiii:Nw #2 }
+ {
+ \peek_meaning:NTF " % "
+ { \@@_backend_getbb_svg_auxiv:Nw #2 }
+ { \@@_backend_getbb_svg_auxv:Nw #2 }
+ }
+ }
+ ##2 \s_@@_stop
+ }
+ }
+ \use:e
+ {
+ \@@_backend_getbb_svg_auxii:w #3
+ \tl_to_str:n {#1} = \tl_to_str:n {#1} =
+ \s_@@_stop
+ }
+ }
+\cs_new_protected:Npn \@@_backend_getbb_svg_auxii:w { }
+\cs_new_protected:Npn \@@_backend_getbb_svg_auxiii:Nw #1 ' #2 ' #3 \s_@@_stop
+ { \@@_backend_getbb_svg_auxvi:Nn #1 {#2} }
+\cs_new_protected:Npn \@@_backend_getbb_svg_auxiv:Nw #1 " #2 " #3 \s_@@_stop
+ { \@@_backend_getbb_svg_auxvi:Nn #1 {#2} }
+\cs_new_protected:Npn \@@_backend_getbb_svg_auxv:Nw #1 #2 ~ #3 \s_@@_stop
+ { \@@_backend_getbb_svg_auxvi:Nn #1 {#2} }
+\cs_new_protected:Npn \@@_backend_getbb_svg_auxvi:Nn #1#2
+ {
+ \tex_afterassignment:D \@@_backend_getbb_svg_auxvii:w
+ \l_@@_internal_dim #2 bp \scan_stop:
+ \dim_set_eq:NN #1 \l_@@_internal_dim
+ }
+\cs_new_protected:Npn \@@_backend_getbb_svg_auxvii:w #1 \scan_stop: { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_getbb_eps:n, \@@_backend_getbb_ps:n}
+% Simply use the generic function.
+% \begin{macrocode}
+\@@_backend_loaded:n
+ {
+ \cs_new_eq:NN \@@_backend_getbb_eps:n \@@_read_bb:n
+ \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_read_bb:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_getbb_png:n, \@@_backend_getbb_jpg:n, \@@_backend_getbb_jpeg:n}
+% These can be included by extracting the bounding box data.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_getbb_jpg:n #1
+ {
+ \int_zero:N \l_@@_page_int
+ \tl_clear:N \l_@@_pagebox_tl
+ \@@_extract_bb:n {#1}
+ }
+\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n
+\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_getbb_pdf:n}
+% Same as for \texttt{dvipdfmx}: use the generic function
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1
+ {
+ \tl_clear:N \l_@@_decodearray_str
+ \bool_set_false:N \l_@@_interpolate_bool
+ \@@_extract_bb:n {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_backend_include_eps:n ,
+% \@@_backend_include_ps:n ,
+% \@@_backend_include_pdf:n
+% }
+% \begin{macro}{\@@_backend_include:nn}
+% The special syntax is relatively clear here: remember we need PostScript
+% sizes here. (This is the same as the \texttt{dvips} code.)
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_include_eps:n #1
+ { \@@_backend_include:nn { PSfile } {#1} }
+\cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n
+\cs_new_protected:Npn \@@_backend_include_pdf:n #1
+ { \@@_backend_include:nn { pdffile } {#1} }
+\cs_new_protected:Npn \@@_backend_include:nn #1#2
+ {
+ \__kernel_backend_literal:e
+ {
+ #1 = #2 \c_space_tl
+ llx = \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl
+ lly = \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl
+ urx = \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl
+ ury = \dim_to_decimal_in_bp:n \l_@@_ury_dim
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_backend_include_svg:n ,
+% \@@_backend_include_png:n ,
+% \@@_backend_include_jpg:n ,
+% \@@_backend_include_jpeg:n
+% }
+% \begin{macro}{\@@_backend_include_dequote:w}
+% The backend here has built-in support for basic graphic inclusion (see
+% \texttt{dvisvgm.def} for a more complex approach, needed if clipping,
+% \emph{etc.}, is covered at the graphic backend level). We have to deal
+% with the fact that the image reference point is at the \emph{top}, so
+% there is a need for a vertical shift to put it in the right place.
+% The other 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 \@@_backend_include_svg:n #1
+ {
+ \box_move_up:nn { \l_@@_ury_dim }
+ {
+ \hbox:n
+ {
+ \__kernel_backend_literal:e
+ {
+ dvisvgm:img~
+ \dim_to_decimal:n { \l_@@_urx_dim } ~
+ \dim_to_decimal:n { \l_@@_ury_dim } ~
+ \@@_backend_include_dequote:w #1 " #1 " \s_@@_stop
+ }
+ }
+ }
+ }
+\cs_new_eq:NN \@@_backend_include_png:n \@@_backend_include_svg:n
+\cs_new_eq:NN \@@_backend_include_jpeg:n \@@_backend_include_svg:n
+\cs_new_eq:NN \@@_backend_include_jpg:n \@@_backend_include_svg:n
+\cs_new:Npn \@@_backend_include_dequote:w #1 " #2 " #3 \s_@@_stop
+ {#2}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_get_pagecount:n}
+% \begin{macrocode}
+\@@_backend_loaded:n
+ { \cs_new_eq:NN \@@_backend_get_pagecount:n \@@_get_pagecount:n }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</dvisvgm>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex