% #!rm -f tigerpsdfmt4* && ptex2pdf -l -u -ot '-shell-escape' -od '-v' test-gin-rule-psd % #!rm -f tigerpsdfmt4* && xelatex -shell-escape test-gin-rule-psd % #!rm -f tigerpsdfmt4* && pdflatex -shell-escape test-gin-rule-psd %#!rm -f tigerpsdfmt4* && lualatex -shell-escape test-gin-rule-psd %% %% This is file 'graphicxpsd.sty'. %% %% Copyright (c) 2017-2026 Munehiro Yamamoto %% %% This package is licensed under the terms of the MIT License. %% \RequirePackage{expl3} \ProvidesExplPackage {graphicxpsd} {2026/03/01} {2.0} {Adobe~Photoshop~Data~format~(PSD)~support~for~graphicx~package~with~sips/magick} %% ------------------------------------------------------------------- %% declare package messages %% ------------------------------------------------------------------- \msg_new:nnn { graphicxpsd } { no-graphicx } { Please~load~'graphicxpsd'~package~after~loading~'graphicx'~package. } \msg_new:nnn { graphicxpsd } { no-driver } { Please~choose~a~specific~dviware~driver~from~the~following~list~ and~set~the~one~as~a~documentclass~option.\msg_line_context: \newline Available~dviware~drivers:~dvipdfmx,~xetex,~luatex,~pdftex } %% ------------------------------------------------------------------- %% declare variables %% ------------------------------------------------------------------- \bool_new:N \l__gfxpsd_imagemagick_bool \bool_new:N \l__gfxpsd_cache_bool \tl_new:N \l__gfxpsd_psdtopdf_tl \tl_new:N \l__gfxpsd_driver_type_tl %% default value for psdtopdf command \tl_set:Nn \l__gfxpsd_psdtopdf_tl { sips } %% ------------------------------------------------------------------- %% define and process options (Key-Value) %% ------------------------------------------------------------------- \keys_define:nn { graphicxpsd } { %% support major graphicx drivers dvipdfmx .code:n = { \tl_set:Nn \l__gfxpsd_driver_type_tl { dvipdfmx } }, xetex .code:n = { \tl_set:Nn \l__gfxpsd_driver_type_tl { dvipdfmx } }, luatex .code:n = { \tl_set:Nn \l__gfxpsd_driver_type_tl { pdftex } }, pdftex .code:n = { \tl_set:Nn \l__gfxpsd_driver_type_tl { pdftex } }, %% support two psd-to-pdf commands: %% sips (Darwin/macOS), magick/convert (ImageMagick), %% graphicsmagick (GraphicsMagick) sips .code:n = { \bool_set_false:N \l__gfxpsd_imagemagick_bool \tl_set:Nn \l__gfxpsd_psdtopdf_tl { sips } }, imagemagick .code:n = { \bool_set_true:N \l__gfxpsd_imagemagick_bool \tl_set:Nn \l__gfxpsd_psdtopdf_tl { magick } }, magick .code:n = { \bool_set_true:N \l__gfxpsd_imagemagick_bool \tl_set:Nn \l__gfxpsd_psdtopdf_tl { magick } }, convert .code:n = { \bool_set_true:N \l__gfxpsd_imagemagick_bool \tl_set:Nn \l__gfxpsd_psdtopdf_tl { convert } }, graphicsmagick .code:n = { \bool_set_true:N \l__gfxpsd_imagemagick_bool \tl_set:Nn \l__gfxpsd_psdtopdf_tl { gm~convert } %% use ~ to represent a space safely }, %% image cache flag (maintaining True/False compatibility) cache .bool_set:N = \l__gfxpsd_cache_bool, cache .default:n = false, cache / True .code:n = { \bool_set_true:N \l__gfxpsd_cache_bool }, cache / False .code:n = { \bool_set_false:N \l__gfxpsd_cache_bool }, } \ProcessKeyOptions [ graphicxpsd ] %% ------------------------------------------------------------------- %% check graphicx loading and map base extensions %% ------------------------------------------------------------------- \cs_if_exist:NF \Ginclude@pdf { \msg_fatal:nn { graphicxpsd } { no-graphicx } } %% support the extension .ai \cs_set:cpn { Gin@rule@.ai } #1 { {pdf}{.ai}{#1} } \cs_set:cpn { Gin@rule@.AI } #1 { {pdf}{.AI}{#1} } %% support the extension .psd (psdtopdf) according to driver \str_case:VnF \l__gfxpsd_driver_type_tl { { dvipdfmx } { \cs_set:cpn { Gin@rule@.PSD } #1 { {psdtopdf}{.xbb}{#1} } \cs_set:cpn { Gin@rule@.psd } #1 { {psdtopdf}{.xbb}{#1} } } { pdftex } { \cs_set:cpn { Gin@rule@.PSD } #1 { {psdtopdf}{.pdf}{#1} } \cs_set:cpn { Gin@rule@.psd } #1 { {psdtopdf}{.pdf}{#1} } } } { %% fallback: attempt automatic detection using l3sys if no driver is specified \sys_if_output_pdf:TF { \cs_set:cpn { Gin@rule@.PSD } #1 { {psdtopdf}{.pdf}{#1} } \cs_set:cpn { Gin@rule@.psd } #1 { {psdtopdf}{.pdf}{#1} } } { \sys_if_output_dvi:TF { \cs_set:cpn { Gin@rule@.PSD } #1 { {psdtopdf}{.xbb}{#1} } \cs_set:cpn { Gin@rule@.psd } #1 { {psdtopdf}{.xbb}{#1} } } { \msg_error:nn { graphicxpsd } { no-driver } } } } %% then, include .psd file as converted PDF \cs_set_eq:NN \Ginclude@psdtopdf \Ginclude@pdf %% ------------------------------------------------------------------- %% file reading and conversion hook definitions %% ------------------------------------------------------------------- %% create a clone of \Gread@pdf \cs_set_eq:NN \__gfxpsd_clone_Gread_pdf:n \Gread@pdf %% internal macro to execute PDF conversion \cs_new_protected:Nn \__gfxpsd_convert_psd_to_pdf: { \iow_term:e { converting:~ \Gin@base\Gin@ext \c_space_tl ->~ \Gin@base 4gfxpsd.pdf } \bool_if:NTF \l__gfxpsd_imagemagick_bool { \sys_shell_now:e { \l__gfxpsd_psdtopdf_tl \c_space_tl \Gin@base\Gin@ext \c_space_tl \Gin@base 4gfxpsd.pdf } } { \sys_shell_now:e { sips~ -s~ format~ pdf~ \Gin@base\Gin@ext \c_space_tl --out~ \Gin@base 4gfxpsd.pdf } } } %% read .psd file \cs_set_protected:Npn \Gread@psdtopdf #1 { \bool_if:NTF \l__gfxpsd_cache_bool { \file_if_exist:nTF { \Gin@base 4gfxpsd.pdf } { \iow_term:e { including~cached~image:~ \Gin@base 4gfxpsd.pdf } } { \iow_term:e { not~found:~ \Gin@base 4gfxpsd.pdf } \__gfxpsd_convert_psd_to_pdf: } } { \__gfxpsd_convert_psd_to_pdf: } %% renamed inside: foo.psd -> foo4gfxpsd.pdf \cs_set_eq:NN \__gfxpsd_clone_Gin_base: \Gin@base \cs_set:Npn \Gin@base { \__gfxpsd_clone_Gin_base: 4gfxpsd } \cs_set:Npn \Gin@ext { .pdf } \__gfxpsd_clone_Gread_pdf:n { #1 } } \endinput %% %% End of file `graphicxpsd.sty'.