% Author : C. Pierquet % licence : Released under the LaTeX Project Public License v1.3c or later, see http://www.latex-project.org/lppl.txt \NeedsTeXFormat{LaTeX2e} \ProvidesExplPackage{inlinegraphicx}{2026-06-27}{0.20b}{Insert inline graphicx with LaTeX3} %====HISTORY % v 0.20b Placeholder if file not found % v 0.20a Bugfix with gset + l3 improvements % v 0.2.0 LaTeX3 conversion % v 0.1.1 Alt options for includegraphics % v 0.1.0 Initial version %====PACKAGE \RequirePackage { graphicx } %====MESSAGES \msg_new:nnn { inlinegraphicx } { file-not-found } { Image~'#1'~not~found~;~inserting~a~dummy~image~instead. } %====VARIABLES (toutes \l_ = locales au groupe de la macro) \dim_new:N \l_totheight_inlinegraphicx_dim \dim_new:N \l_depth_inlinegraphicx_dim \dim_new:N \l_raisebox_inlinegraphicx_dim \dim_new:N \l_height_inlinegraphicx_dim \dim_new:N \l_dummyinner_inlinegraphicx_dim \dim_new:N \l_dummydiag_inlinegraphicx_dim \dim_new:N \l_dummyht_inlinegraphicx_dim \dim_new:N \l_dummydp_inlinegraphicx_dim \dim_new:N \l_dummyraise_inlinegraphicx_dim \fp_new:N \l_scale_inlinegraphicx_fp \fp_new:N \l_invscale_inlinegraphicx_fp \tl_new:N \l_strut_inlinegraphicx_tl \tl_new:N \l_dummy_inlinegraphicx_tl \clist_new:N \l_extensions_inlinegraphicx_clist \clist_new:N \l_searchpath_inlinegraphicx_clist \bool_new:N \l_inlinegraphicx_exists_bool %====KEYS \keys_define:nn { inlinegraphics } { scale .fp_set:N = \l_scale_inlinegraphicx_fp, scale .initial:n = { 1.0 }, scale .default:n = { 1.0 }, strut .tl_set:N = \l_strut_inlinegraphicx_tl, strut .initial:n = { qH }, strut .default:n = { qH }, dummy .tl_set:N = \l_dummy_inlinegraphicx_tl, dummy .initial:n = { }, extensions .clist_set:N = \l_extensions_inlinegraphicx_clist, extensions .initial:n = { .pdf, .png, .jpg, .jpeg, .eps }, searchpath .clist_set:N = \l_searchpath_inlinegraphicx_clist, searchpath .initial:n = { }, } %====FONCTIONS INTERNES \cs_new_protected:Npn \inlinegraphicx_check_exist:n #1 { \bool_set_false:N \l_inlinegraphicx_exists_bool \file_if_exist:nT { #1 } { \bool_set_true:N \l_inlinegraphicx_exists_bool } \bool_if:NF \l_inlinegraphicx_exists_bool { \clist_map_inline:Nn \l_extensions_inlinegraphicx_clist { \file_if_exist:nT { #1 ##1 } { \bool_set_true:N \l_inlinegraphicx_exists_bool \clist_map_break: } } } \bool_if:NF \l_inlinegraphicx_exists_bool { \clist_map_inline:Nn \l_searchpath_inlinegraphicx_clist { \file_if_exist:nT { ##1 #1 } { \bool_set_true:N \l_inlinegraphicx_exists_bool \clist_map_break: } \clist_map_inline:Nn \l_extensions_inlinegraphicx_clist { \file_if_exist:nT { ##1 #1 ####1 } { \bool_set_true:N \l_inlinegraphicx_exists_bool \clist_map_break: } } \bool_if:NT \l_inlinegraphicx_exists_bool { \clist_map_break: } } } \bool_if:NF \l_inlinegraphicx_exists_bool { \msg_warning:nnn { inlinegraphicx } { file-not-found } { #1 } } } \cs_new_protected:Npn \inlinegraphicx_dummybox: { \dim_set:Nn \l_dummyinner_inlinegraphicx_dim { \l_height_inlinegraphicx_dim - 1.2pt } \dim_set:Nn \l_dummydiag_inlinegraphicx_dim { \fp_eval:n { 1.41421356 * \l_dummyinner_inlinegraphicx_dim } pt } \fboxsep 0pt \fboxrule 0.6pt \hbox_set:Nn \l_tmpb_box { \fbox { \makebox [ \dim_use:N \l_dummyinner_inlinegraphicx_dim ] [ c ] { \makebox [ 0pt ] [ c ] { \rotatebox [ origin = c ] { 45 } { \rule { \dim_use:N \l_dummydiag_inlinegraphicx_dim } { 0.5pt } } } \makebox [ 0pt ] [ c ] { \rotatebox [ origin = c ] { -45 } { \rule { \dim_use:N \l_dummydiag_inlinegraphicx_dim } { 0.5pt } } } } } } % --- on mesure la boîte obtenue puis on la recentre verticalement % sur la hauteur cible, et on force ses dimensions finales. \dim_set:Nn \l_dummyht_inlinegraphicx_dim { \box_ht:N \l_tmpb_box } \dim_set:Nn \l_dummydp_inlinegraphicx_dim { \box_dp:N \l_tmpb_box } \dim_set:Nn \l_dummyraise_inlinegraphicx_dim { 0.5 \l_height_inlinegraphicx_dim - 0.5 \l_dummyht_inlinegraphicx_dim + 0.5 \l_dummydp_inlinegraphicx_dim } \hbox_set:Nn \l_tmpb_box { \raisebox { \dim_use:N \l_dummyraise_inlinegraphicx_dim } { \box_use:N \l_tmpb_box } } \box_set_ht:Nn \l_tmpb_box { \l_height_inlinegraphicx_dim } \box_set_dp:Nn \l_tmpb_box { 0pt } \box_use:N \l_tmpb_box } \cs_new_protected:Npn \inlinegraphicx_insert:nn #1 #2 { \bool_if:NTF \l_inlinegraphicx_exists_bool { \includegraphics [ height = { \dim_use:N \l_height_inlinegraphicx_dim } , #1 ] { #2 } } { \tl_if_empty:NTF \l_dummy_inlinegraphicx_tl { \inlinegraphicx_dummybox: } { \includegraphics [ height = { \dim_use:N \l_height_inlinegraphicx_dim } , #1 ] { \l_dummy_inlinegraphicx_tl } } } } %====MAIN MACRO \NewDocumentCommand \inlinegraphics { s O { } D < > { } m } { \group_begin: \keys_set:nn { inlinegraphics } { scale = { 1.0 } , strut = { qH } , dummy = { } , extensions = { .pdf, .png, .jpg, .jpeg, .eps } , searchpath = { } , } \keys_set:nn { inlinegraphics } { #2 } \inlinegraphicx_check_exist:n { #4 } % --- \bool_if:NTF #1 { % --- Mode étoilé : hauteur = hauteur de la capitale du strut \hbox_set:Nn \l_tmpa_box { \tl_use:N \l_strut_inlinegraphicx_tl } \dim_set:Nn \l_totheight_inlinegraphicx_dim { \box_ht:N \l_tmpa_box } \dim_set:Nn \l_height_inlinegraphicx_dim { \fp_eval:n { \l_scale_inlinegraphicx_fp * \l_totheight_inlinegraphicx_dim } pt } \inlinegraphicx_insert:nn { #3 } { #4 } } { % --- Mode normal : hauteur totale (ht+dp) du strut avec alignement vertical \hbox_set:Nn \l_tmpa_box { \tl_use:N \l_strut_inlinegraphicx_tl } \dim_set:Nn \l_totheight_inlinegraphicx_dim { \box_dp:N \l_tmpa_box + \box_ht:N \l_tmpa_box } \dim_set:Nn \l_depth_inlinegraphicx_dim { \box_dp:N \l_tmpa_box } \dim_set:Nn \l_height_inlinegraphicx_dim { \fp_eval:n { \l_scale_inlinegraphicx_fp * \l_totheight_inlinegraphicx_dim } pt } \fp_set:Nn \l_invscale_inlinegraphicx_fp { 0.5 * ( 1.0 - \l_scale_inlinegraphicx_fp ) } \dim_set:Nn \l_raisebox_inlinegraphicx_dim { \l_depth_inlinegraphicx_dim - \fp_eval:n { \l_invscale_inlinegraphicx_fp * \l_totheight_inlinegraphicx_dim } pt } \raisebox { - \dim_use:N \l_raisebox_inlinegraphicx_dim } { \inlinegraphicx_insert:nn { #3 } { #4 } } } \group_end: } %====SIMPLE WRAPPER \NewDocumentCommand \safeincludegraphics { O { } m } { \group_begin: \inlinegraphicx_check_exist:n { #2 } \bool_if:NTF \l_inlinegraphicx_exists_bool { \includegraphics [ #1 ] { #2 } } { \includegraphics [ #1 ] { example-image.pdf } } \group_end: } \endinput