%% LaTeX2e file `pstool.sty' %% generated by the `filecontents' environment %% from source `pstool' on 2010/03/24. %% \ProvidesPackage{pstool}[2009/07/17 v1.3 Wrapper for processing PostScript/psfrag figures] % External packages \RequirePackage{% catchfile,color,ifpdf,ifplatform, graphicx,pdftexcmds,psfrag,suffix,xkeyval} % Allocations \newif\if@pstool@pdfcrop@ \newif\if@pstool@verbose@ \newwrite\pstool@out % These are cute \providecommand\OnlyIfFileExists[2]{\IfFileExists{#1}{#2}{}} \providecommand\NotIfFileExists[2]{\IfFileExists{#1}{}{#2}} % \subsection{Package options} \define@choicekey*{pstool.sty}{crop} [\@tempa\@tempb]{preview,pdfcrop}{% \ifcase\@tempb\relax \@pstool@pdfcrop@false \or \@pstool@pdfcrop@true \or \fi } \define@choicekey*{pstool.sty}{process} [\@tempa\pstool@process@choice]{all,none,auto}{} \ExecuteOptionsX{process=auto} \define@choicekey*{pstool.sty}{mode} [\@tempa\@tempb]{errorstop,nonstop,batch}{% \ifnum\@tempb=2\relax \@pstool@verbose@false \else \@pstool@verbose@true \fi \edef\pstool@mode{\@tempa mode}% } \ExecuteOptionsX{mode=batch} \DeclareOptionX{cleanup}{\def\pstool@rm@files{#1}} \ExecuteOptionsX{cleanup={.tex,.dvi,.ps,.pdf,.log,.aux}} \DeclareOptionX{suffix}{\def\pstool@suffix{#1}} \ExecuteOptionsX{suffix={-pstool}} % There is an implicit |\space| after the bitmap options. \define@choicekey*{pstool.sty}{bitmap} [\@tempa\@tempb]{auto,lossless,lossy}{% \ifcase\@tempb \let\pstool@bitmap@opts\@empty \or \def\pstool@bitmap@opts{% "-dAutoFilterColorImages=false" "-dAutoFilterGrayImages=false" "-dColorImageFilter=/FlateEncode" "-dGrayImageFilter=/FlateEncode" % space } \or \def\pstool@bitmap@opts{% "-dAutoFilterColorImages=false" "-dAutoFilterGrayImages=false" "-dColorImageFilter=/DCTEncode" "-dGrayImageFilter=/DCTEncode" % space } \fi } \ExecuteOptionsX{bitmap=lossless} % \HideAllDefining % \Define*{latex-options} % \Define*{dvips-options} % \Define*{ps2pdf-options} % \Define*{pdfcrop-options} \DeclareOptionX{latex-options}{\def\pstool@latex@opts{#1}} \DeclareOptionX{dvips-options}{\def\pstool@dvips@opts{#1}} \DeclareOptionX{ps2pdf-options}{\def\pstool@pspdf@opts{#1}} \DeclareOptionX{pdfcrop-options}{\def\pstool@pdfcrop@opts{#1}} % \ResumeAllDefining \ExecuteOptionsX{ latex-options={}, dvips-options={}, ps2pdf-options={"-dPDFSETTINGS=/prepress"}, pdfcrop-options={} } \ifpdf \ifshellescape\else \ExecuteOptionsX{process=none} \PackageWarning{pstool}{^^J\space\space% Package option [process=none] activated^^J\space\space because -shell-escape is not enabled.^^J% This warning occurred} \fi \fi \ProcessOptionsX % A command to set \pkg{pstool} options after the package is loaded. \newcommand\pstoolsetup{% \setkeys{pstool.sty}% } % \section{Macros} % Used to echo information to the console output. % Can't use |\typeout| because it's asynchronous with % any |\immediate\write18| processes (for some reason). \def\pstool@echo#1{% \if@pstool@verbose@ \pstool@echo@verbose{#1}% \fi } \def\pstool@echo@verbose#1{% \immediate\write18{echo "#1"}% } \let\pstool@includegraphics\includegraphics % Command line abstractions between platforms: \edef\pstool@cmdsep{\ifwindows\string&\else\string;\fi\space} \edef\pstool@rm@cmd{\ifwindows del \else rm -- \fi} % Delete a file if it exists:\\ % |#1|: path\\ % |#2|: filename \newcommand\pstool@rm[2]{% \OnlyIfFileExists{#1#2}{% \immediate\write18{% cd "#1"\pstool@cmdsep\pstool@rm@cmd "#2" }% }% } % Generic function to execute a command on the shell and pass its exit status back into \LaTeX. Any number of \cmd\pstool@exe\ statements can be made consecutively followed by \cmd\pstool@endprocess, which also takes an argument. If \emph{any} of the shell calls failed, then the execution immediately skips to the end and expands \cmd\pstool@error\ instead of the argument to \cmd\pstool@endprocess. % % |#1|: `name' of process\\ % |#2|: relative path where to execute the command\\ % |#3|: the command itself \newcommand\pstool@exe[3]{% \pstool@echo{^^J=== pstool: #1 ===}% \pstool@shellexecute{#2}{#3}% \pstool@retrievestatus{#2}% \ifnum\pstool@status > \z@ \PackageWarning{pstool}{Execution failed during process:^^J\space\space#3^^JThis warning occurred}% \expandafter\pstool@abort \fi } % Edit this definition to print something else when graphic processing fails. \def\pstool@error{% \fbox{% \parbox{0.8\linewidth}{% \color{red}\raggedright\ttfamily\scshape\small An error occured processing graphic \upshape`\pstool@path\pstool@filestub'% }% }% } \def\pstool@abort#1\pstool@endprocess{\pstool@error\@gobble} \let\pstool@endprocess\@firstofone % It is necessary while executing commands on the shell to write the exit status to a temporary file to test for failures in processing. (If all versions of |pdflatex| supported input pipes, things might be different.) \def\pstool@shellexecute#1#2{% \immediate\write18{% cd "#1" \pstool@cmdsep #2 \pstool@cmdsep \ifwindows call echo \string^\@percentchar ERRORLEVEL\string^\@percentchar \else echo \detokenize{$?} \fi > \pstool@statusfile}% % That's the execution; now we need to flush the write buffer to the status file. This ensures the file is written to disk properly (allowing it to be read by \cmd\CatchFileEdef). Not necessary on Windows, whose file writing is evidently more crude/immediate. \ifwindows\else \immediate\write18{% touch #1\pstool@statusfile}% \fi } \def\pstool@statusfile{pstool-statusfile.txt} % Read the exit status from the temporary file and delete it.\\ % |#1| is the path\\ % Status is recorded in \cmd\pstool@status. \def\pstool@retrievestatus#1{% \CatchFileEdef{\pstool@status}{#1\pstool@statusfile}{}% \pstool@rm{#1}{\pstool@statusfile}% \ifx\pstool@status\pstool@statusfail \PackageWarning{pstool}{% Status of process unable to be determined:^^J #1^^J% Trying to proceed... }% \def\pstool@status{0}% \fi } \def\pstool@statusfail{\par }% what results when \TeX\ reads an empty file % \subsection{File age detection} \def\pstool@IfnewerEPS{% \ifnum\pdf@strcmp{\pdf@filemoddate{\pstool@path\pstool@filestub.pdf}} {\pdf@filemoddate{\pstool@path\pstool@filestub.eps}} < \z@ \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % Grab filename and filepath. Always need a relative path to a filename even if it's in the same directory. \def\pstool@getpaths#1{% \filename@parse{#1}% \ifx\filename@area\@empty \def\pstool@path{./}% \else \let\pstool@path\filename@area \fi \let\pstool@filestub\filename@base } % \section{Command parsing} % User input is \cmd\pstool\ (with optional |*| or |!| suffix) which turns into one of the following three macros depending on the mode. \newcommand\pstool@alwaysprocess[3][]{% \pstool@getpaths{#2}% \pstool@process{#1}{#3}% } \ifpdf \newcommand\pstool@neverprocess[3][]{% \pstool@includegraphics{#2}% } \else \newcommand\pstool@neverprocess[3][]{% \begingroup \setkeys*{pstool.sty}{#1}% #3% \expandafter\pstool@includegraphics\expandafter[\XKV@rm]{#2}% \endgroup } \fi % For regular operation, which processes the figure only if % the command is starred, or the PDF doesn't exist. \newcommand\pstool@maybeprocess[3][]{% \pstool@getpaths{#2}% \IfFileExists{#2.pdf}{% \pstool@IfnewerEPS{% needs info from |\pstool@getpaths| \pstool@process{#1}{#3}% }{% \pstool@includegraphics{#2}% }% }{% \pstool@process{#1}{#3}% }% } % \section{User commands} % Finally, define \cmd\pstool\ as appropriate for the mode: (|all|, |none|, |auto|, respectively) \ifpdf \newcommand\pstool{% \ifcase\pstool@process@choice\relax \expandafter \pstool@alwaysprocess \or \expandafter \pstool@neverprocess \or \expandafter \pstool@maybeprocess \fi } \WithSuffix\def\pstool!{% \ifcase\pstool@process@choice\relax \expandafter \pstool@alwaysprocess \or \expandafter \pstool@neverprocess \or \expandafter \pstool@neverprocess \fi } \WithSuffix\def\pstool*{% \ifcase\pstool@process@choice\relax \expandafter \pstool@alwaysprocess \or \expandafter \pstool@neverprocess \or \expandafter \pstool@alwaysprocess \fi } \else \let\pstool\pstool@neverprocess \WithSuffix\def\pstool!{\pstool@neverprocess} \WithSuffix\def\pstool*{\pstool@neverprocess} \fi % \section{The figure processing} % \cmd\pstool@filestub\ is the filename of the figure stripped of its path (if any) \def\pstool@jobname{\pstool@filestub\pstool@suffix} % And this is the main macro. \newcommand\pstool@process[2]{% \begingroup \setkeys*{pstool.sty}{#1}% \pstool@echo@verbose{% ^^J^^J=== pstool: begin processing ===}% \pstool@write@processfile{#1} {\pstool@path\pstool@filestub}{#2}% \pstool@exe{auxiliary process: \pstool@filestub\space} {./}{latex -shell-escape -output-format=dvi -output-directory="\pstool@path" -interaction=\pstool@mode\space \pstool@latex@opts\space "\pstool@jobname.tex"}% % Execute |dvips| in quiet mode if |latex| is not run in (non/error)stop mode: \pstool@exe{dvips}{\pstool@path}{% dvips \if@pstool@verbose@\else -q \fi -Ppdf \pstool@dvips@opts\space "\pstool@jobname.dvi"}% \if@pstool@pdfcrop@ \pstool@exe{ps2pdf}{\pstool@path}{% ps2pdf \pstool@bitmap@opts \pstool@pspdf@opts \space "\pstool@jobname.ps" "\pstool@jobname.pdf"}% \pstool@exe{pdfcrop}{\pstool@path}{% pdfcrop \pstool@pdfcrop@opts\space "\pstool@jobname.pdf" "\pstool@filestub.pdf"}% \else \pstool@exe{ps2pdf}{\pstool@path}{% ps2pdf \pstool@bitmap@opts \pstool@pspdf@opts \space "\pstool@jobname.ps" "\pstool@filestub.pdf"}% \fi \pstool@endprocess{% \pstool@cleanup \pstool@includegraphics{% \pstool@path\pstool@filestub}% }% \pstool@echo@verbose{^^J=== pstool: end processing ===^^J}% \endgroup } % The file that is written for processing is set up to read the preamble of the original document and set the graphic on an empty page (cropping to size is done either here with \pkg{preview} or later with \pkg{pdfcrop}). \def\pstool@write@processfile#1#2#3{% \immediate\openout\pstool@out #2\pstool@suffix.tex\relax \immediate\write\pstool@out{% % Input the main document; redefine the document environment so only the preamble is read: \unexpanded{% \pdfoutput=0^^J% force DVI mode if not already \let\origdocument\document^^J% \let\EndPreamble\endinput^^J% \def\document{\endgroup\endinput}^^J% }% \noexpand\input{\jobname}^^J% % % Now the preamble of the process file: (restoring document's original meaning; empty \cmd\pagestyle\ removes the page number) \if@pstool@pdfcrop@\else \noexpand\usepackage[active,tightpage]{preview}^^J% \fi \unexpanded{% \let\document\origdocument^^J% \pagestyle{empty}^^J% }% % % And the document body to place the graphic on a page of its own: \unexpanded{% \begin{document}^^J% \centering\null\vfill^^J% }% \if@pstool@pdfcrop@\else \noexpand\begin{preview}^^J% \fi \unexpanded{#3^^J}% this is the "psfrag" material \noexpand\includegraphics [\unexpanded\expandafter{\XKV@rm}] {\pstool@filestub}^^J% \if@pstool@pdfcrop@\else \noexpand\end{preview}^^J% \fi \unexpanded{\vfill\end{document}}^^J% }% \immediate\closeout\pstool@out } \def\pstool@cleanup{% \@for\@ii:=\pstool@rm@files\do{% \pstool@rm{\pstool@path}{\pstool@jobname\@ii}% }% } \providecommand\EndPreamble{} % \section{User commands} % % These all support the suffixes |*| and |!|, so each user command is defined as a wrapper to \cmd\pstool. % for EPS figures with psfrag: \newcommand\psfragfig[2][]{\pstool@psfragfig{#1}{#2}{}} \WithSuffix\newcommand\psfragfig*[2][]{% \pstool@psfragfig{#1}{#2}{*}% } \WithSuffix\newcommand\psfragfig![2][]{% \pstool@psfragfig{#1}{#2}{!}% } % Parse optional \ \newcommand\pstool@psfragfig[3]{% \@ifnextchar\bgroup{% \pstool@@psfragfig{#1}{#2}{#3}% }{% \pstool@@psfragfig{#1}{#2}{#3}{}% }% } % Search for both \ and \|-psfrag| inputs. % % |#1|: possible graphicx options\\ % |#2|: graphic name (possibly with path)\\ % |#3|: |\pstool| suffix (i.e., |!| or |*| or \)\\ % |#4|: possible \pkg{psfrag} (or other) macros \newcommand\pstool@@psfragfig[4]{% % Find the .eps file to use. \IfFileExists{#2-psfrag.eps}{% \edef\pstool@eps{#2-psfrag}% \OnlyIfFileExists{#2.eps}{% \PackageWarning{pstool}{Graphic "#2.eps" exists but "#2-psfrag.eps" is being used}% }% }{% \IfFileExists{#2.eps}{% \edef\pstool@eps{#2}% }{% \PackageError{pstool}{% No graphic "#2.eps" or "#2-psfrag.eps" found% }{% Check the path and whether the file exists.% }% }% }% % Find the .tex file to use. \IfFileExists{#2-psfrag.tex}{% \edef\pstool@tex{#2-psfrag.tex}% \OnlyIfFileExists{#2.tex}{% \PackageWarning{pstool}{% File "#2.tex" exists that may contain macros for "\pstool@eps.eps"^^J% But file "#2-psfrag.tex" is being used instead.% }% }% }{% \IfFileExists{#2.tex}{% \edef\pstool@tex{#2.tex}% }{% \let\pstool@tex\@empty \PackageWarning{pstool}{% No file "#2.tex" or "#2-psfrag.tex" can be found that may contain macros for "\pstool@eps.eps"% }% }% }% \ifx\pstool@tex\@empty \pstool#3[#1]{\pstool@eps}{#4}% \else \expandafter\pstool@@@psfragfig \expandafter{\pstool@tex}{#3[#1]}{#4}% \fi } % Break out the separate function in order to expand |\pstool@tex| before writing it. \newcommand\pstool@@@psfragfig[3]{% \pstool#2{\pstool@eps}{% \csname @input\endcsname{#1}% #3% }% } % That's it.