#!/usr/bin/perl -w # # Syntax: replace_psfrag [-h] [-f] [-a] [-m method] [-k] latex_file[.tex] [...] # # Purpose: Extracts the figures from a latex file, processes them, and creates # the corresponding stand-alone eps or pdf files for each figure # (useful if you have used psfrag). # Only figures inside a \begin{figure}...\end{figure} environment # or inside a \begin{psfrags}...\end{psfrags} environment are # extracted. Furthermore, it is assumed that these environments # are not mixed or nested, and that all command (re)definitions # are done in the preamble. # The output is placed in files with names latex_file_fig_X.eps or # latex_file_fig_X.pdf, where X is the figure number. # If the -f flag is specified only pdf figures are created. # If the -a flag is specified both eps and pdf figures are created. # If the -k flag is specified, all intermediate files are kept. # The -m flag determines the method used to create an eps file # (see the help of dvi2epspdf for more information). # The -h flag shows the help info for this command. # # See also: dvi2epspdf, adjust_eps_bbox # # Notes: . This program requires the bash script dvi2epspdf # . This program is inspired by pdfrack # (http://www.enseeiht.fr/~boyer/Pdfrack/) # . Alternatively, you can use the pstool latex package. # Created: Aug 6, 2004 by Bart De Schutter # Last revised: Mar 14, 2009 by Bart De Schutter # # See http://www.deschutter.info/util/scripts.html for the latest version # of this script. # Status: public # Category: latex ############################################################################### # # Main program. # ############################################################################### use strict; use Inout; my ($dvi2epspdf_options, $keep_intermed, $cur_dir); $| = 1; # Set autoflush on. ($dvi2epspdf_options, $keep_intermed) = process_options (); chomp ($cur_dir = `pwd`); foreach my $latex_file (@ARGV) { chdir ($cur_dir); extract_and_create_figures ($latex_file, $dvi2epspdf_options, $keep_intermed, $cur_dir); } exit; ############################################################################### # # FUNCTION DEFINITIONS # ############################################################################### ############################################################################### # # ($dvi2epspdf_options, $keep_intermed) = process_options () # # Processes the options flags, if any. # # Inputs: none # # Outputs: $dvi2epspdf_options options to be passed to dvi2epspdf # $keep_intermed whether to keep intermediate files # # Global variables: @ARGV list of input arguments # ############################################################################### sub process_options { my ($option, $dvi2epspdf_options, $pdf_flag, $all_flag, $method); my ($keep_intermed, $command); ( $command = $0 ) =~ s/.*\///; $pdf_flag = 0; $all_flag = 0; $method = -1; $keep_intermed = 0; while ( ( $#ARGV >= 0 ) && ( $ARGV[0] =~ /^-(.*)/ ) ) { $option = $1; if ( $option eq "h" ) { system("sed '/^\$/q;/^#!/d;s/^# //;s/^#//' $0 >&2"); exit 1; } elsif ( $option eq "a" ) { $all_flag = 1; } elsif ( $option eq "f" ) { $pdf_flag = 1; } elsif ( $option =~ /^m(.*)/ ) { $method = $1; if ( $method eq "" ) { shift @ARGV; if ( $#ARGV >= 0 ) { $method = $ARGV[0]; } else { syntax_error ("Option m requires an extra argument."); } } if ( $method !~ /^[1-5]p?$/ ) { syntax_error ("The method argument should be a number between 1 ". "and 5, possibly followed by a p."); } } elsif ( $option eq "k" ) { $keep_intermed = 1; } else { syntax_error ("Unknown option $option in $command."); } shift @ARGV; } if ( $#ARGV < 0 ) { syntax_error ("$command requires at least 1 input argument."); } # If the all flag is set the pdf flag is redundant. $pdf_flag = 0 if ( $all_flag eq 1 ); # Construct options to be passed to dvi2epspdf $dvi2epspdf_options = ""; $dvi2epspdf_options .= " -m $method" if ( $method ne -1 ); $dvi2epspdf_options .= " -a" if ( $all_flag ); $dvi2epspdf_options .= " -f" if ( $pdf_flag ); $dvi2epspdf_options .= " -k" if ( $keep_intermed ); return ($dvi2epspdf_options, $keep_intermed); } ############################################################################### # # extract_and_create_figures ($latex_file, $dvi2epspdf_options, # $keep_intermed, $dest_dir) # # Extracts and creates figures for the given latex file. # # Inputs: $latex_file string # $dvi2epspdf_options options to be passed to dvi2epspdf # $keep_intermed whether to keep intermediate files # $dest_dir directory in which resulting eps or # pdf files should be created # # Outputs: none # ############################################################################### sub extract_and_create_figures { my ($latex_file, $dvi2epspdf_options, $keep_intermed, $dest_dir) = @_; my ($base_name, $extension, $preamble, @fig_blocks); my ($fig_block, $fig_no, $n_figs, $fig_base, $fig_latex_file); my ($latex209, $tmp_dir); ($base_name, $extension) = get_path_and_extension ($latex_file, 0); $latex_file .= ".tex" if ( $extension eq "" ); ($preamble, $latex209, $n_figs, @fig_blocks) = read_preamble_and_figures ($latex_file); $tmp_dir = create_tmp_dir ('replace_psfrag'); chdir ($tmp_dir); if ( $keep_intermed ) { print "\n\n"; print " Temporary files for $base_name are stored in\n $tmp_dir\n"; print "\n\n"; } for ( my $i = 1; $i <= $n_figs; $i++) { $fig_base = $base_name."_fig_${i}"; print ( ( $i > 1 ? "\n" : "")."Creating $fig_base ...\n"); $fig_latex_file = $fig_base.".tex"; create_figure_latex_file ($fig_latex_file, $preamble, $latex209, $fig_blocks[$i-1]); process_figure_latex_file ($fig_base, $dvi2epspdf_options, $cur_dir, $dest_dir); unlink <$fig_base.{tex,aux,dvi,log,lof,lot,toc}> if ( !$keep_intermed ); } rmdir $tmp_dir if ( !$keep_intermed ); } ############################################################################### # # read_preamble_and_figures ($latex_file) # # Reads the premable and figure/psfrags environment blocks of the given # latex file. # # Inputs: $latex_file string # # Outputs: $preamble preamble # $latex209 flag indicating whether or not latex209 is used # $n_figs number of figure/psfrags environment blocks # @fig_blocks stack with figure/psfrags environment blocks # ############################################################################### sub read_preamble_and_figures { my ($latex_file) = @_; my ($preamble, $begin_document_found, $line); my ($n_figs, @fig_blocks, $reading_fig_env, $fig_block, $latex209); $preamble = ""; @fig_blocks = (); $n_figs = 0; $latex209 = 0; open (LATEX_FILE, "<$latex_file") || die ("Cannot open $latex_file"); # # Read and store the preamble. # $begin_document_found = 0; while ( defined( $line = ) ) { chomp ($line); $latex209 = 1 if ( $line =~ /^\\documentstyle/ ); if ( $line =~ /^\s*\\begin{document}/ ) { $begin_document_found = 1; last; } if ( ( $line !~ /^\s*%/ ) && ( $line !~ /^\s*$/ ) ) { $preamble .= "$line\n"; } } if ( !$begin_document_found ) { error_exit ("No \\begin{document} found in $latex_file."); } # # Read and store the figures, i.e., each \begin{figure}...\end{figure} # or \begin{psfrags}...\end{psfrags} environment. # $reading_fig_env = 0; $fig_block = ""; while ( defined( $line = ) ) { chomp ($line); # Skip comment lines and empty lines. if ( ( $line !~ /^\s*%/ ) && ( $line !~ /^\s*$/ ) ) { if ( $reading_fig_env ) { # Check whether the last line of the environment is found. if ( $line =~ /^(.*\\end{(psfrags|figure)})/ ) { $fig_block .= $1."\n"; $reading_fig_env = 0; push (@fig_blocks, $fig_block); $n_figs++; $reading_fig_env = 0; $fig_block = ""; } else { $fig_block .= $line."\n"; } } else # not reading figure or psfrag environment { # Check whether a new figure environment is found. if ( $line =~ /^.*(\\begin{(psfrags|figure)}.*)$/ ) { $reading_fig_env = 1; $fig_block = $1."\n"; } } } } if ( $reading_fig_env ) { error_exit ("End of file reach while reading figure or psfrags ". "environment in $latex_file."); } close (LATEX_FILE); return ($preamble, $latex209, $n_figs, @fig_blocks); } ############################################################################### # # create_figure_latex_file ($fig_latex_file, $preamble, $latex209, $fig_block) # # Writes the latex file with name $fig_latex_file for the figure defined by # $fig_block. # # Inputs: $fig_base base name string # $preamble preamble # $latex209 flag indicating whether or not latex209 is used. # $fig_block figure or psfrags environment block # # Outputs: none # ############################################################################### sub create_figure_latex_file { my ($fig_latex_file, $preamble, $latex209, $fig_block) = @_; open (FIG_FILE, ">$fig_latex_file") || die ("Cannot open $fig_latex_file"); print FIG_FILE $preamble; # Make pagestyle and \caption (with possibly an optional argument) empty. print FIG_FILE "\\pagestyle{empty}\n"; if ( $latex209 ) { # Latex209 does not 'know' the syntax \renewcommand{cmd}[args][opt]{def} # So we remove the option argument, if any. We assume that the # optional argument does not contain any ] as internal character. print FIG_FILE "\\renewcommand{\\caption}[1]{}\n"; $fig_block =~ s/\\caption\s*\[.*?\]/\\caption/sg; } else { print FIG_FILE "\\renewcommand{\\caption}[2][]{}\n"; } print FIG_FILE "\\begin{document}\n"; print FIG_FILE $fig_block; print FIG_FILE "\\end{document}\n"; close (FIG_FILE); } ############################################################################### # # process_figure_latex_file ($fig_base, $dvi2epspdf_options) # # Latexes the latex file with name $fig_base.tex and transforms the resulting # dvi file into an eps and/or pdf file using the command dvi2epspdf with # options $dvi2epspdf_options. # # Inputs: $fig_base base name string for the latex figure file # $dvi2epspdf_options options to be passed to dvi2epspdf # $cur_dir current directory # $dest_dir directory in which resulting eps or # pdf files should be created # # Outputs: none # ############################################################################### sub process_figure_latex_file { my ($fig_base, $dvi2epspdf_options, $cur_dir, $dest_dir) = @_; my ($TEXINPUTS); $TEXINPUTS = "" if ( !defined ( $TEXINPUTS = $ENV{'TEXINPUTS'} ) ); system ("TEXINPUTS=$cur_dir:$TEXINPUTS ". "latex -interaction=batchmode $fig_base.tex") == 0 || error_exit ("Error latexing $fig_base.tex"); system ("TEXINPUTS=$cur_dir:$TEXINPUTS ". "dvi2epspdf $dvi2epspdf_options -t . -d $dest_dir $fig_base") == 0 || error_exit ("Error running dvi2epspdf on $fig_base.dvi"); }