summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3experimental/l3graphics.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3experimental/l3graphics.dtx')
-rw-r--r--macros/latex/contrib/l3experimental/l3graphics.dtx546
1 files changed, 296 insertions, 250 deletions
diff --git a/macros/latex/contrib/l3experimental/l3graphics.dtx b/macros/latex/contrib/l3experimental/l3graphics.dtx
index 8b97a562ed..cf4a70983d 100644
--- a/macros/latex/contrib/l3experimental/l3graphics.dtx
+++ b/macros/latex/contrib/l3experimental/l3graphics.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Released 2022-02-05}
+% \date{Released 2022-04-10}
%
% \maketitle
%
@@ -54,140 +54,60 @@
%
% \section{\pkg{l3graphics} documentation}
%
-% \subsection{Driver functions}
+% \subsection{Graphics keys}
%
% Inclusion of graphic files requires a range of low-level data be passed to
-% the driver layer. These functions are primarily aimed at supporting this
-% work.
+% the backend. This is set up using a small number of key--value settings,
+% which are stored in the |graphics| tree.
%
-% \begin{variable}{\l_graphics_decodearray_tl}
+% \begin{variable}{decodearray}
% Array to decode color in bitmap graphic: when non-empty, this should
% be in the form of one, two or three pairs of real numbers in the range
% $[0,1]$, separated by spaces.
% \end{variable}
%
-% \begin{variable}{\l_graphics_interpolate_bool}
-% Indicates whether interpolation should be applied to bitmap graphic files.
+% \begin{variable}{draft}
+% Switch to enable draft mode: graphics are read but not included when this is
+% true.
+% \end{variable}
+%
+% \begin{variable}{interpolate}
+% Switch which indicates whether interpolation should be applied to bitmap
+% graphic files.
% \end{variable}
%
-% \begin{variable}{\l_graphics_page_int}
+% \begin{variable}{page}
% The page to extract from a multi-page graphic file: used for |.pdf| files
% which may contain multiple pages.
% \end{variable}
%
-% \begin{variable}{\l_graphics_pagebox_tl}
+% \begin{variable}{pagebox}
% The nature of the page box setting used to determine the bounding box of
% material: used for |.pdf| files which feature multiple page box
-% specifications.
+% specifications. A choice from |art|, |bleed|, |crop|, |media|, |trim|.
+% The standard setting is |crop|.
% \end{variable}
%
-% \begin{variable}{\l_graphics_draft_bool}
+% \begin{variable}{draft}
% Switch to enable draft mode: graphics are read but not included when this is
% true.
% \end{variable}
%
-% \begin{variable}
-% {\l_graphics_llx_dim, \l_graphics_lly_dim, \l_graphics_urx_dim, \l_graphics_ury_dim}
-% Dimensions which return the points $(\meta{llx},\meta{lly})$ and
-% $(\meta{urx},\meta{ury})$ for the graphic. For many graphics only the resulting
-% height and width are significant, but this is driver-dependent.
-% \end{variable}
-%
-% \begin{variable}{\l_graphics_name_bool}
-% The name of a graphics file being loaded: usually the same as the
-% input file name, but may be altered by some drivers.
+% \begin{variable}{type}
+% The type of graphic file beign included: if this key is not set, the
+% \emph{type} is determined from the file extension.
% \end{variable}
%
-% \begin{function}
-% {
-% \graphics_bb_save:n, \graphics_bb_save:x,
-% \graphics_bb_restore:nF, \graphics_bb_restore:xF
-% }
-% \begin{syntax}
-% \cs{graphics_bb_save:n} \Arg{graphic}
-% \cs{graphics_bb_restore:nF} \Arg{graphic} \Arg{false code}
-% \end{syntax}
-% This pair of functions are used to cache the bounding box of an \meta{graphic}
-% so that extraction/reading is only required once. The \texttt{save}
-% function stores the values from \cs{l_graphics_llx_dim},
-% \cs{l_graphics_lly_dim}, \cs{l_graphics_urx_dim} and
-% \cs{l_graphics_ury_dim} as constants. The \texttt{restore} function will then
-% look up values for the bounding box of an \meta{graphic} and set the four
-% dimensions appropriately. For any one \meta{graphic} the bounding box will
-% be constant, so the \texttt{save} function should only be called once. Thus
-% a typical use case is
-% \begin{verbatim}
-% \graphics_bb_restore:nF { <name> }
-% {
-% % Code to read the bb
-% \graphics_bb_save:n { <name> }
-% }
-% \end{verbatim}
-% \emph{i.e.}~every use of a bounding box will attempt to restore saved data,
-% and saving will only take place where that is not possible.
-%
-% Note that the \meta{graphic} may not be a simple file name: a multi-page PDF,
-% for example, will need to have the bounding box cached for each page used.
-% \end{function}
+% \subsection{Including graphics}
%
-% \begin{function}{\graphics_extract_bb:n}
+% \begin{function}{\graphics_include:nn, \graphics_include:nV}
% \begin{syntax}
-% \cs{graphics_extract_bb:n} \Arg{file}
+% \cs{graphics_include:nn} \Arg{keys} \Arg{file}
% \end{syntax}
-% Extracts bounding box data for the graphic \meta{file} using the |extractbb|
-% utility, and stores the bounding box of the graphic file in
-% \cs{l_graphics_llx_dim}, \cs{l_graphics_lly_dim}, \cs{l_graphics_urx_dim} and
-% \cs{l_graphics_ury_dim}.
-%
-% The \meta{file} name should be fully-qualified and sanitized: no search
-% or other manipulation is carried out at this level. No check is made on
-% the file \emph{type} at this stage: it is assumed that the driver code
-% using this function has made such a check. File types such as |.pdf| and
-% |.jpg| are appropriate for parsing using this function.
-%
-% When \cs{l_graphics_page_int} is positive the appropriate page will be
-% queried from the graphic file.
-%
-% Note that this function requires pipe shell calls to be enabled: this is
-% generally true but may require the option |--enable-pipes| to be enabled
-% when running the \TeX{} job.
-% \end{function}
-%
-% \begin{function}{\graphics_read_bb:n}
-% \begin{syntax}
-% \cs{graphics_read_bb:n} \Arg{file}
-% \end{syntax}
-% Parses the graphic \meta{file} to find a PostScript-style bounding box
-% line of the form
-% \begin{verbatim}
-% %%BoundingBox: llx lly urx urx
-% \end{verbatim}
-% where \meta{llx}, \meta{lly}, \meta{urx} and \meta{ury} are the corners
-% of the bounding box expressed in PostScript (\enquote{big}) points. The
-% values are stored in \cs{l_graphics_llx_dim}, \cs{l_graphics_lly_dim},
-% \cs{l_graphics_urx_dim} and \cs{l_graphics_ury_dim}.
-%
-% The \meta{file} name should be fully-qualified and sanitized: no search
-% or other manipulation is carried out at this level. No check is made on
-% the file \emph{type} at this stage: it is assumed that the driver code
-% using this function has made such a check. File types such as |.eps| and
-% |.bb|/|.xbb| are appropriate for parsing using this function.
-% \end{function}
-%
-% \begin{function}{\graphics_include:n, \graphics_include:nn}
-% \begin{syntax}
-% \cs{graphics_include:n} \Arg{file}
-% \cs{graphics_include:nn} \Arg{file} \Arg{type}
-% \end{syntax}
-% Horizontal-mode commands which include the \meta{file} as an graphic
-% at the current location. The file \meta{type} is given explicitly in
-% the two-argument version, or is inferred from the file extension extracted
-% in the single-argument form. The exact graphic types supported depend upon
-% the driver in use.
-%
-% Where the \meta{file} is not found and the \meta{type} is \emph{not}
-% given, a search for possible graphic files is undertaken using the extensions
-% stored in \cs{l_graphics_search_ext_seq}.
+% Horizontal-mode command which includes the \meta{file} as an graphic
+% at the current location. The file \meta{type} may be given as one of the
+% \meta{keys}, or will otherwise be determined from file extension. The
+% \meta{keys} is used to pass settings as detailed above.
% \end{function}
%
% \begin{variable}{\l_graphics_ext_type_prop}
@@ -200,11 +120,6 @@
% \end{verbatim}
% \end{variable}
%
-% \begin{variable}{\l_graphics_search_ext_seq}
-% Extensions to use for graphic searching when the given \meta{file} name is not
-% found by \cs{graphics_include:n}.
-% \end{variable}
-%
% \begin{variable}{\l_graphics_search_path_seq}
% Each entry is the path to a directory which should be searched when
% seeking an graphic file. Each path can be relative or absolute, and should
@@ -213,6 +128,36 @@
% variable content. Spaces need not be quoted.
% \end{variable}
%
+% \subsection{Utility functions}
+%
+% \begin{function}[noTF]{\graphics_get_full_name:nN}
+% \begin{syntax}
+% \cs{graphics_get_full_name:nN} \Arg{file} \meta{tl~var}
+% \cs{graphics_get_full_name:nNTF} \Arg{file} \meta{tl~var} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Searches for \meta{file} first as given and then using the extensions
+% listed in \cs{l_graphics_search_ext_seq}. The search path used will be
+% the entries of \cs{l_graphics_search_path_seq}. If found, the full file
+% name including any path and extension will be returned in the
+% \meta{tl~var}. In the non-branching version, the \meta{tl var} will be
+% set to \cs{q_no_value} in the case that the graphics is not found.
+% \end{function}
+%
+% \begin{variable}{\l_graphics_search_ext_seq}
+% Extensions to use for graphic searching when the given \meta{file} name is not
+% found by \cs{graphics_get_full_name:nN}.
+% \end{variable}
+%
+% \begin{function}{\graphics_get_pagecount:nN}
+% \begin{syntax}
+% \cs{graphics_get_pagecount:nn} \Arg{file} \meta{tl~var}
+% \end{syntax}
+% Reads the graphics \meta{file} and extracts the number of pages, which
+% are stored in the \meta{tl~var}.
+% \end{function}
+%
+% \subsection{Showing and logging included graphics}
+%
% \begin{function}{\graphics_show_list:, \graphics_log_list:}
% \begin{syntax}
% \cs{graphics_show_list:}
@@ -240,15 +185,15 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3graphics}{2022-02-05}{}
+\ProvidesExplPackage{l3graphics}{2022-04-10}{}
{L3 Experimental graphics inclusion support}
% \end{macrocode}
%
-% \begin{variable}{\l_@@_tmp_ior, \l_@@_tmp_tl}
+% \begin{variable}{\l_@@_internal_ior, \l_@@_internal_tl}
% Scratch space.
% \begin{macrocode}
-\ior_new:N \l_@@_tmp_ior
-\tl_new:N \l_@@_tmp_tl
+\ior_new:N \l_@@_internal_ior
+\tl_new:N \l_@@_internal_tl
% \end{macrocode}
% \end{variable}
%
@@ -259,24 +204,47 @@
% \end{macrocode}
% \end{variable}
%
-% \subsection{Image feature support}
+% \subsection{Graphics keys}
%
% \begin{macro}
% {
-% \l_graphics_decodearray_tl ,
-% \l_graphics_interpolate_bool,
-% \l_graphics_page_int ,
-% \l_graphics_pagebox_tl
+% \l_@@_decodearray_str ,
+% \l__@@_draft_bool ,
+% \l_@@_interpolate_bool ,
+% \l_@@_page_int ,
+% \l_@@_pagebox_tl ,
+% \l_@@_type_str
% }
% Keys which control features of graphics. The standard value of |pagebox|
-% set up here should match the default for the drivers themselves: in
-% the absence of any other setting the |cropbox| should be used.
+% set up here should match the default for the backends themselves: in
+% the absence of any other setting the |crop| should be used. Note that
+% the variable \cs{l_@@_pagebox_str} can be empty internally, as backends
+% which do not support |pagebox| are set up to clear it entirely. The
+% store for |pagebox| is a |tl| as that makes extracting the data
+% easier for some backends.
% \begin{macrocode}
-\tl_new:N \l_graphics_decodearray_tl
-\tl_new:N \l_graphics_pagebox_tl
-\bool_new:N \l_graphics_interpolate_bool
-\tl_set:Nn \l_graphics_pagebox_tl { cropbox }
-\int_new:N \l_graphics_page_int
+\tl_new:N \l_@@_pagebox_tl
+\keys_define:nn { graphics }
+ {
+ decodearray .str_set:N =
+ \l_@@_decodearray_str ,
+ draft .bool_set:N =
+ \l_@@_draft_bool ,
+ interpolate .bool_set:N =
+ \l_@@_interpolate_bool ,
+ pagebox .choices:nn =
+ { art , bleed , crop , media , trim }
+ {
+ \tl_set:Nx \l_@@_pagebox_tl
+ { \tl_use:N \l_keys_choice_tl box }
+ } ,
+ pagebox .initial:n =
+ crop ,
+ page .int_set:N =
+ \l_@@_page_int ,
+ type . str_set:N =
+ \l_@@_type_str
+ }
% \end{macrocode}
% \end{macro}
%
@@ -284,60 +252,60 @@
%
% \begin{variable}
% {
-% \l_graphics_llx_dim , \l_graphics_lly_dim,
-% \l_graphics_urx_dim , \l_graphics_ury_dim
+% \l_@@_llx_dim , \l_@@_lly_dim,
+% \l_@@_urx_dim , \l_@@_ury_dim
% }
% Storage for the return of bounding box.
% \begin{macrocode}
-\dim_new:N \l_graphics_llx_dim
-\dim_new:N \l_graphics_lly_dim
-\dim_new:N \l_graphics_urx_dim
-\dim_new:N \l_graphics_ury_dim
+\dim_new:N \l_@@_llx_dim
+\dim_new:N \l_@@_lly_dim
+\dim_new:N \l_@@_urx_dim
+\dim_new:N \l_@@_ury_dim
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\graphics_bb_save:n, \graphics_bb_save:x}
-% \begin{macro}{\graphics_bb_restore:nF, \graphics_bb_restore:xF}
+% \begin{macro}{\@@_bb_save:n, \@@_bb_save:x}
+% \begin{macro}{\@@_bb_restore:nF, \@@_bb_restore:xF}
% Caching graphic bounding boxes is sensible, and these functions are needed both
% here and for drive-specific work. So they are made available as documented
% functions. To save on registers, the \enquote{origin} is only saved if it is
% not at zero.
% \begin{macrocode}
-\cs_new_protected:Npn \graphics_bb_save:n #1
+\cs_new_protected:Npn \@@_bb_save:n #1
{
\dim_if_exist:cTF { c_@@_ #1 _urx_dim }
{ \msg_error:nnn { graphic } { bb-already-cached } {#1} }
{
- \dim_compare:nNnF \l_graphics_llx_dim = { 0pt }
- { \dim_const:cn { c_@@_ #1 _llx_dim } { \l_graphics_llx_dim } }
- \dim_compare:nNnF \l_graphics_lly_dim = { 0pt }
- { \dim_const:cn { c_@@_ #1 _lly_dim } { \l_graphics_lly_dim } }
- \dim_const:cn { c_@@_ #1 _urx_dim } { \l_graphics_urx_dim }
- \dim_const:cn { c_@@_ #1 _ury_dim } { \l_graphics_ury_dim }
+ \dim_compare:nNnF \l_@@_llx_dim = { 0pt }
+ { \dim_const:cn { c_@@_ #1 _llx_dim } { \l_@@_llx_dim } }
+ \dim_compare:nNnF \l_@@_lly_dim = { 0pt }
+ { \dim_const:cn { c_@@_ #1 _lly_dim } { \l_@@_lly_dim } }
+ \dim_const:cn { c_@@_ #1 _urx_dim } { \l_@@_urx_dim }
+ \dim_const:cn { c_@@_ #1 _ury_dim } { \l_@@_ury_dim }
}
}
-\cs_generate_variant:Nn \graphics_bb_save:n { x }
-\cs_new_protected:Npn \graphics_bb_restore:nF #1#2
+\cs_generate_variant:Nn \@@_bb_save:n { x }
+\cs_new_protected:Npn \@@_bb_restore:nF #1#2
{
\dim_if_exist:cTF { c_@@_ #1 _urx_dim }
{
- \dim_set_eq:Nc \l_graphics_urx_dim { c_@@_ #1 _urx_dim }
- \dim_set_eq:Nc \l_graphics_ury_dim { c_@@_ #1 _ury_dim }
+ \dim_set_eq:Nc \l_@@_urx_dim { c_@@_ #1 _urx_dim }
+ \dim_set_eq:Nc \l_@@_ury_dim { c_@@_ #1 _ury_dim }
\dim_if_exist:cTF { c_@@_ #1 _llx_dim }
- { \dim_set_eq:Nc \l_graphics_llx_dim { c_@@_ #1 _llx_dim } }
- { \dim_zero:N \l_graphics_llx_dim }
+ { \dim_set_eq:Nc \l_@@_llx_dim { c_@@_ #1 _llx_dim } }
+ { \dim_zero:N \l_@@_llx_dim }
\dim_if_exist:cTF { c_@@_ #1 _lly_dim }
- { \dim_set_eq:Nc \l_graphics_lly_dim { c_@@_ #1 _lly_dim } }
- { \dim_zero:N \l_graphics_lly_dim }
+ { \dim_set_eq:Nc \l_@@_lly_dim { c_@@_ #1 _lly_dim } }
+ { \dim_zero:N \l_@@_lly_dim }
}
{#2}
}
-\cs_generate_variant:Nn \graphics_bb_restore:nF { x }
+\cs_generate_variant:Nn \@@_bb_restore:nF { x }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\graphics_extract_bb:n, \graphics_read_bb:n}
+% \begin{macro}{\@@_extract_bb:n, \@@_read_bb:n}
% \begin{macro}{\@@_extract_bb_auix:nn, \@@_extract_bb_auix:Vn}
% \begin{macro}{\@@_extract_bb_auxii:nnn}
% \begin{macro}{\@@_extract_bb_auxiii:nnnn, \@@_extract_bb_auxiii:Vnnn}
@@ -357,10 +325,10 @@
% box has to be calculated by |extractbb|, with just the initial phase
% different.
% \begin{macrocode}
-\cs_new_protected:Npn \graphics_extract_bb:n #1
+\cs_new_protected:Npn \@@_extract_bb:n #1
{
- \int_compare:nNnTF \l_graphics_page_int > 0
- { \@@_extract_bb_auxi:Vn \l_graphics_page_int {#1} }
+ \int_compare:nNnTF \l_@@_page_int > 0
+ { \@@_extract_bb_auxi:Vn \l_@@_page_int {#1} }
{ \@@_extract_bb_auxii:nnn {#1} { } { } }
}
\cs_new_protected:Npn \@@_extract_bb_auxi:nn #1#2
@@ -368,9 +336,9 @@
\cs_generate_variant:Nn \@@_extract_bb_auxi:nn { Vn }
\cs_new_protected:Npn \@@_extract_bb_auxii:nnn #1#2#3
{
- \tl_if_empty:NTF \l_graphics_pagebox_tl
+ \tl_if_empty:NTF \l_@@_pagebox_tl
{ \@@_extract_bb_auxiv:nnn }
- { \@@_extract_bb_auxiii:Vnnn \l_graphics_pagebox_tl }
+ { \@@_extract_bb_auxiii:Vnnn \l_@@_pagebox_tl }
{#1} {#2} {#3}
}
\cs_new_protected:Npn \@@_extract_bb_auxiii:nnnn #1#2#3#4
@@ -379,13 +347,13 @@
\cs_new_protected:Npn \@@_extract_bb_auxiv:nnn #1#2#3
{
\@@_read_bb_auxi:nnnn {#1} {#2}
- { \ior_shell_open:Nn \l_@@_tmp_ior { extractbb~#3-O~#1 } }
+ { \ior_shell_open:Nn \l_@@_internal_ior { extractbb~#3-O~#1 } }
{ pipe-failed }
}
-\cs_new_protected:Npn \graphics_read_bb:n #1
+\cs_new_protected:Npn \@@_read_bb:n #1
{
\@@_read_bb_auxi:nnnn {#1} { }
- { \ior_open:Nn \l_@@_tmp_ior {#1} }
+ { \ior_open:Nn \l_@@_internal_ior {#1} }
{ graphic-not-found }
}
% \end{macrocode}
@@ -401,31 +369,23 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_read_bb_auxi:nnnn #1#2#3#4
{
- \graphics_bb_restore:nF {#1#2}
+ \@@_bb_restore:nF {#1#2}
{ \@@_read_bb_auxii:nnnn {#3} {#4} {#1} {#2} }
}
\cs_new_protected:Npx \@@_read_bb_auxii:nnnn #1#2#3#4
{
#1
- \exp_not:N \ior_if_eof:NTF \exp_not:N \l_@@_tmp_ior
+ \exp_not:N \ior_if_eof:NTF \exp_not:N \l_@@_internal_ior
{ \msg_error:nnn { graphics } {#2} {#3} }
{
- \ior_str_map_inline:Nn \exp_not:N \l_@@_tmp_ior
+ \ior_str_map_inline:Nn \exp_not:N \l_@@_internal_ior
{
\exp_not:N \@@_read_bb_auxiii:w
##1 ~ \c_colon_str \s_@@_stop
}
+ \@@_bb_save:n {#3#4}
}
- \exp_not:n
- {
- \ior_close:N \l_@@_tmp_ior
- \dim_compare:nNnF \l_graphics_llx_dim = { 0pt }
- { \dim_const:cn { c_@@_ #3#4 _llx_dim } { \l_graphics_llx_dim } }
- \dim_compare:nNnF \l_graphics_lly_dim = { 0pt }
- { \dim_const:cn { c_@@_ #3#4 _lly_dim } { \l_graphics_lly_dim } }
- \dim_const:cn { c_@@_ #3#4 _urx_dim } { \l_graphics_urx_dim }
- \dim_const:cn { c_@@_ #3#4 _ury_dim } { \l_graphics_ury_dim }
- }
+ \ior_close:N \exp_not:N \l_@@_internal_ior
}
\use:x
{
@@ -450,13 +410,13 @@
{
\str_if_eq:nnF {#2} { atend }
{
- \tl_set_rescan:Nnx \l_@@_tmp_tl
+ \tl_set_rescan:Nnx \l_@@_internal_tl
{
\char_set_catcode_space:n { 9 }
\char_set_catcode_space:n { 32 }
}
{ \use:n #1 }
- \exp_after:wN \@@_read_bb_auxv:w \l_@@_tmp_tl \s_@@_stop
+ \exp_after:wN \@@_read_bb_auxv:w \l_@@_internal_tl \s_@@_stop
}
}
% \end{macrocode}
@@ -465,10 +425,10 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_read_bb_auxv:w #1~#2~#3~#4~#5 \s_@@_stop
{
- \dim_set:Nn \l_graphics_llx_dim { #1 bp }
- \dim_set:Nn \l_graphics_lly_dim { #2 bp }
- \dim_set:Nn \l_graphics_urx_dim { #3 bp }
- \dim_set:Nn \l_graphics_ury_dim { #4 bp }
+ \dim_set:Nn \l_@@_llx_dim { #1 bp }
+ \dim_set:Nn \l_@@_lly_dim { #2 bp }
+ \dim_set:Nn \l_@@_urx_dim { #3 bp }
+ \dim_set:Nn \l_@@_ury_dim { #4 bp }
\ior_map_break:
}
% \end{macrocode}
@@ -480,17 +440,13 @@
% \end{macro}
% \end{macro}
%
-% \begin{variable}{\l_graphics_draft_bool}
-% Relevant to including graphics but not to reading them.
-% \begin{macrocode}
-\bool_new:N \l_graphics_draft_bool
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_graphics_name_tl, \l_@@_name_tl}
+% \begin{variable}{\l_@@_final_name_str, \l_@@_full_name_str}
+% The full name is as you'd expect the name including path and extension.
+% The final name here reflects any conversions carried out by the backend,
+% for example if an |.eps| is converted to |.pdf|.
% \begin{macrocode}
-\tl_new:N \l_graphics_name_tl
-\tl_new:N \l_@@_name_tl
+\str_new:N \l_@@_final_name_str
+\str_new:N \l_@@_full_name_str
% \end{macrocode}
% \end{variable}
%
@@ -515,7 +471,7 @@
% \end{variable}
%
% \begin{variable}{\l_graphics_search_ext_seq}
-% Used to specify fall-back extensions: actually set on a per-driver basis.
+% Used to specify fall-back extensions: actually set on a per-backend basis.
% \begin{macrocode}
\seq_new:N \l_graphics_search_ext_seq
% \end{macrocode}
@@ -536,66 +492,49 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\graphics_include:n}
+% \begin{macro}{\graphics_include:nn, \graphics_include:nV}
% \begin{macro}{\@@_include_search:n}
% \begin{macro}{\@@_include:}
-% \begin{macro}{\graphics_include:nn}
% \begin{macro}
% {
-% \@@_include_auxi:n, \@@_include_auxii:n,
+% \@@_include_auxi:n, \@@_include_auxi:e, \@@_include_auxii:n,
% \@@_include_auxiii:n, \@@_include_auxiv:n
% }
% Actually including an graphic is relatively straight-forward: most of the
-% work is done by the driver. We only have to deal with making sure the
+% work is done by the backend. We only have to deal with making sure the
% box has no apparent depth. Where the first given name is not found, we
% search based on extension only if the \meta{type} was not given. The one
% wrinkle is that we may have found a \texttt{.tex} file matching the file
% name stem: that's not what we want, so we have to filter out.
% \begin{macrocode}
-\cs_new_protected:Npn \graphics_include:n #1
+\cs_new_protected:Npn \graphics_include:nn #1#2
{
\group_begin:
+ \keys_set:nn { graphics } {#1}
\seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
- \file_get_full_name:nNTF {#1} \l_@@_name_tl
+ \file_get_full_name:nNTF {#2} \l_@@_full_name_str
{
- \str_if_eq:eeTF { \l_@@_name_tl } { #1 .tex }
- { \@@_include_search:n {#1} }
+ \str_if_eq:eeTF { \l_@@_full_name_str } { #2 .tex }
+ { \msg_error:nnn { graphics } { graphic-not-found } {#2} }
{ \@@_include: }
}
- { \@@_include_search:n {#1} }
+ { \msg_error:nnn { graphics } { graphic-not-found } {#2} }
\group_end:
}
-\cs_new_protected:Npn \@@_include_search:n #1
- {
- \seq_map_inline:Nn \l_graphics_search_ext_seq
- {
- \file_get_full_name:nNT { #1 . ##1 } \l_@@_name_tl
- { \seq_map_break:n { \use_i:nnn \@@_include: } }
- }
- \use:n
- { \msg_error:nnn { graphics } { graphic-not-found } {#1} }
- }
+\cs_generate_variant:Nn \graphics_include:nn { nV }
\cs_new_protected:Npn \@@_include:
{
- \file_parse_full_name:VNNN \l_@@_name_tl
- \l_@@_dir_str \l_@@_name_str \l_@@_ext_str
- \exp_args:Ne \@@_include_auxi:n
+ \str_if_empty:NTF \l_@@_type_str
{
- \exp_args:Ne \str_tail:n
- { \str_foldcase:V \l_@@_ext_str }
- }
- }
-\cs_new_protected:Npn \graphics_include:nn #1#2
- {
- \group_begin:
- \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
- \file_get_full_name:nNTF {#1} \l_@@_name_tl
- {
- \exp_args:Ne \@@_include_auxi:n
- { \str_foldcase:n {#1} }
- }
- { \msg_error:nnn { graphics } { graphic-not-found } {#1} }
- \group_end:
+ \file_parse_full_name:VNNN \l_@@_full_name_str
+ \l_@@_dir_str \l_@@_name_str \l_@@_ext_str
+ \@@_include_auxi:e
+ {
+ \exp_args:Ne \str_tail:n
+ { \str_foldcase:V \l_@@_ext_str }
+ }
+ }
+ { \@@_include_auxi:e { \l_@@_type_str } }
}
\cs_new_protected:Npn \@@_include_auxi:n #1
{
@@ -603,20 +542,21 @@
{ \tl_set:Nn \l_@@_internal_tl {#1} }
\exp_args:NV \@@_include_auxii:n \l_@@_internal_tl
}
+\cs_generate_variant:Nn \@@_include_auxi:n { e }
\cs_new_protected:Npn \@@_include_auxii:n #1
{
\mode_leave_vertical:
\cs_if_exist:cTF { @@_backend_include_ #1 :n }
{
- \tl_set_eq:NN \l_graphics_name_tl \l_@@_name_tl
+ \tl_set_eq:NN \l_@@_final_name_str \l_@@_full_name_str
+ \str_set:Nx \l_@@_full_name_str
+ { \exp_args:NV \__kernel_file_name_quote:n \l_@@_full_name_str }
\exp_args:NnV \use:c { @@_backend_getbb_ #1 :n }
- \l_@@_name_tl
- \seq_gput_right:NV \g_@@_record_seq \l_graphics_name_tl
-%<*package>
+ \l_@@_full_name_str
+ \seq_gput_right:NV \g_@@_record_seq \l_@@_final_name_str
\clist_if_exist:NT \@filelist
- { \exp_args:NV \@addtofilelist \l_graphics_name_tl }
-%</package>
- \bool_if:NTF \l_graphics_draft_bool
+ { \exp_args:NV \@addtofilelist \l_@@_final_name_str }
+ \bool_if:NTF \l_@@_draft_bool
{ \@@_include_auxiii:n }
{ \@@_include_auxiv:n }
{#1}
@@ -625,23 +565,21 @@
}
\cs_new_protected:Npn \@@_include_auxiii:n #1
{
- \hbox_to_wd:nn { \l_graphics_urx_dim - \l_graphics_llx_dim }
+ \hbox_to_wd:nn { \l_@@_urx_dim - \l_@@_llx_dim }
{
\tex_vrule:D
\tex_hss:D
\vbox_to_ht:nn
- { \l_graphics_ury_dim - \l_graphics_lly_dim }
+ { \l_@@_ury_dim - \l_@@_lly_dim }
{
\tex_hrule:D width
- \dim_eval:n { \l_graphics_urx_dim - \l_graphics_llx_dim }
+ \dim_eval:n { \l_@@_urx_dim - \l_@@_llx_dim }
\tex_vss:D
\hbox_to_wd:nn
- { \l_graphics_urx_dim - \l_graphics_llx_dim }
+ { \l_@@_urx_dim - \l_@@_llx_dim }
{
-%<*package>
\ttfamily
-%</package>
- \tex_hss:D \l_@@_name_tl \tex_hss:D
+ \tex_hss:D \l_@@_full_name_str \tex_hss:D
}
\tex_vss:D
\tex_hrule:D
@@ -655,13 +593,13 @@
\hbox_set:Nn \l_@@_internal_box
{
\exp_args:NnV \use:c { @@_backend_include_ #1 :n }
- \l_@@_name_tl
+ \l_@@_full_name_str
}
\box_set_dp:Nn \l_@@_internal_box { 0pt }
\box_set_ht:Nn \l_@@_internal_box
- { \l_graphics_ury_dim - \l_graphics_lly_dim }
+ { \l_@@_ury_dim - \l_@@_lly_dim }
\box_set_wd:Nn \l_@@_internal_box
- { \l_graphics_urx_dim - \l_graphics_llx_dim }
+ { \l_@@_urx_dim - \l_@@_llx_dim }
\box_use_drop:N \l_@@_internal_box
}
% \end{macrocode}
@@ -669,7 +607,6 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\graphics_show_list:, \graphics_log_list:, \@@_list:N}
% \begin{macro}[EXP]{\@@_list_aux:n}
@@ -680,7 +617,7 @@
\cs_new_protected:Npn \@@_list:N #1
{
\seq_remove_duplicates:N \g_@@_record_seq
- #1 { LaTeX/kernel } { file-list }
+ #1 { kernel } { file-list }
{ \seq_map_function:NN \g_@@_record_seq \@@_list_aux:n }
{ } { } { }
}
@@ -689,14 +626,123 @@
% \end{macro}
% \end{macro}
%
+% \subsection{Utility functions}
+%
+% \begin{macro}{\graphics_get_full_name:nN}
+% \begin{macro}[TF]{\graphics_get_full_name:nN}
+% \begin{macro}{\@@_get_full_name:n}
+% A simple search.
+% \begin{macrocode}
+\cs_new_protected:Npn \graphics_get_full_name:nN #1#2
+ {
+ \graphics_get_full_name:nNF {#1} #2
+ { \tl_set:Nn #2 { \q_no_value } }
+ }
+\prg_new_protected_conditional:Npnn \graphics_get_full_name:nN #1#2
+ { T , F , TF }
+ {
+ \group_begin:
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#1} \l_@@_full_name_str
+ {
+ \str_if_eq:eeT { \l_@@_full_name_str } { #1 .tex }
+ { \@@_get_full_name:n {#1} }
+ }
+ { \@@_get_full_name:n {#1} }
+ \exp_args:NNNV \group_end:
+ \tl_set:Nn #2 \l_@@_full_name_str
+ \tl_if_empty:NTF #2
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+\cs_new_protected:Npn \@@_get_full_name:n #1
+ {
+ \str_clear:N \l_@@_full_name_str
+ \seq_map_inline:Nn \l_graphics_search_ext_seq
+ {
+ \file_get_full_name:nNT { #1 ##1 } \l_@@_full_name_str
+ { \seq_map_break:n { \use_none:nn } }
+ }
+ \use:n
+ { \str_clear:N \l_@@_full_name_str }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\graphics_get_pagecount:nN}
+% \begin{macro}{\@@_get_pagecount:n}
+% \begin{macro}{\@@_get_pagecount:nw}
+% A generic function to read the number of pages in a graphic file. This is
+% used by all of the backend where there is not a dedicated primitive. The
+% plan is essentially the same as reading the bounding box. To avoid multiple
+% calls, the value is cached either here or in the backend.
+% \begin{macrocode}
+\cs_new_protected:Npn \graphics_get_pagecount:nN #1#2
+ {
+ \group_begin:
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#1} \l_@@_full_name_str
+ {
+ \int_if_exist:cF { c_@@_ \l_@@_full_name_str _pages_int }
+ {
+ \exp_args:NV \@@_backend_get_pagecount:n
+ \l_@@_full_name_str
+ }
+ \tl_set:Nv #2 { c_@@_ \l_@@_full_name_str _pages_int }
+ }
+ {
+ \tl_set:Nn #2 { 0 }
+ \msg_error:nnn { graphics } { graphic-not-found } {#1}
+ }
+ \exp_args:NNNV \group_end:
+ \tl_set:Nn #2 #2
+ }
+\cs_new_protected:Npx \@@_get_pagecount:n #1
+ {
+ \ior_shell_open:Nn \exp_not:N \l_@@_internal_ior
+ { extractbb~-O~#1 }
+ \exp_not:N \ior_if_eof:NTF \exp_not:N \l_@@_internal_ior
+ { \msg_error:nnn { graphics } { pipe-failed } }
+ {
+ \ior_str_map_inline:Nn \exp_not:N \l_@@_internal_ior
+ {
+ \exp_not:N \@@_get_pagecount:nw {#1}
+ ##1 ~ \c_colon_str \c_colon_str \s_@@_stop
+ }
+ \exp_not:N \int_if_exist:cF { c_@@_ #1 _pages_int }
+ { \int_const:cn { c_@@_ #1 _pages_int } { 1 } }
+ }
+ \ior_close:N \exp_not:N \l_@@_internal_ior
+ }
+\use:x
+ {
+ \cs_new_protected:Npn \exp_not:N \@@_get_pagecount:nw
+ ##1##2 \c_colon_str ##3 \c_colon_str ##4 \s_@@_stop
+ {
+ \exp_not:N \str_if_eq:nnT
+ { \c_percent_str \c_percent_str Pages }
+ {##2}
+ {
+ \int_const:cn { c_@@_ ##1 _pages_int } {##3}
+ \exp_not:N \ior_map_break:
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Messages}
%
% \begin{macrocode}
\msg_new:nnnn { graphics } { graphic-not-found }
{ Image~file~'#1'~not~found. }
{
- LaTeX~tried~to~open~graphic~file~'#1',
- ~but~the~file~could~not~be~read.
+ LaTeX~tried~to~open~graphic~file~'#1',~
+ but~the~file~could~not~be~read.
}
\msg_new:nnnn { graphics } { pipe-failed }
{ Cannot~run~piped~system~commands. }