diff options
-rw-r--r-- | Build/source/texk/texlive/ChangeLog | 2 | ||||
-rw-r--r-- | Build/source/texk/texlive/Makefile.in | 1 | ||||
-rw-r--r-- | Build/source/texk/texlive/linked_scripts/pkfix-helper | 1219 | ||||
-rw-r--r-- | Build/source/texk/texlive/linked_scripts/purifyeps | 511 | ||||
-rw-r--r-- | Master/texmf-dist/doc/support/pkfix-helper/README | 65 | ||||
-rw-r--r-- | Master/texmf-dist/doc/support/pkfix-helper/encoding-samples.pdf | bin | 0 -> 315660 bytes | |||
-rwxr-xr-x | Master/texmf-dist/scripts/pkfix-helper/pkfix-helper | 1219 | ||||
-rw-r--r-- | Master/texmf/doc/man/man1/pkfix-helper.1 | 483 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 2 | ||||
-rwxr-xr-x | Master/tlpkg/libexec/ctan2tds | 4 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-binextra.tlpsrc | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/pkfix-helper.tlpsrc | 2 | ||||
-rw-r--r-- | TODO | 6 |
13 files changed, 3510 insertions, 5 deletions
diff --git a/Build/source/texk/texlive/ChangeLog b/Build/source/texk/texlive/ChangeLog index 11c36669b7e..3f26131f6c3 100644 --- a/Build/source/texk/texlive/ChangeLog +++ b/Build/source/texk/texlive/ChangeLog @@ -1,6 +1,6 @@ 2009-03-23 Karl Berry <karl@tug.org> - * Makefile.in (LINKED_SCRIPTS): add purifyeps. + * Makefile.in (LINKED_SCRIPTS): add purifyeps, pkfix-helper. 2009-03-10 Karl Berry <karl@tug.org> diff --git a/Build/source/texk/texlive/Makefile.in b/Build/source/texk/texlive/Makefile.in index c59f90f3b68..b78489da846 100644 --- a/Build/source/texk/texlive/Makefile.in +++ b/Build/source/texk/texlive/Makefile.in @@ -35,6 +35,7 @@ LINKED_SCRIPTS = \ texmf-dist/scripts/ppower4/ppower4.texlua \ texmf-dist/scripts/pdfcrop/pdfcrop.pl \ texmf-dist/scripts/perltex/perltex.pl \ + texmf-dist/scripts/pkfix-helper/pkfix-helper \ texmf-dist/scripts/ppower4/pdfthumb.texlua \ texmf-dist/scripts/ppower4/ppower4.texlua \ texmf-dist/scripts/pst-pdf/ps4pdf \ diff --git a/Build/source/texk/texlive/linked_scripts/pkfix-helper b/Build/source/texk/texlive/linked_scripts/pkfix-helper new file mode 100644 index 00000000000..f1a2f1cb694 --- /dev/null +++ b/Build/source/texk/texlive/linked_scripts/pkfix-helper @@ -0,0 +1,1219 @@ +#! /usr/bin/env perl + +############################################# +# Help pkfix decipher fonts in a PostScript # +# file produced by an ancient dvips # +# # +# By Scott Pakin <scott+pkfh@pakin.org> # +############################################# + +use File::Spec; +use File::Temp qw (tempfile); +use File::Basename; +use Getopt::Long; +use Pod::Usage; +use warnings; +use strict; + +# Define some global variables. +my $progname = basename $0; # Name of this program +our $VERSION = "1.0"; # Version number of this program +my %name2chars; # Map from a font name to a character list +my $GS = $ENV{"GS"} || "gs"; # Name of the Ghostscript interpreter +my $TFTOPL = $ENV{"TFTOPL"} || "tftopl"; # Name of the TFM to PL converter +my $dpi = 300; # Number of dots per inch used to generate bitmapped characters +my @tfmlist; # List of TFM files to use +my %fontmatch; # Map from a font name to its best match +my $xinc = 36; # Width of font name in PostScript points +my $yinc = 24; # Height of font in PostScript points +my $init_yinc = 36; # Space after title +my %tfmfontwidth; # Map from font name to character number to character width +my %tfm2size; # Map from font name to design size +my ($dvips_xscale, $dvips_yscale); # Scaling factors from Dvips's PostScript CTM +my $discard_output = $^O eq "MSWin32" ? "> NUL:" : "> /dev/null 2>&1"; # Command suffix to discard all output + +# Define the global variables that the user can modify from the command line. +my $wanthelp = 0; # 1=user wants to see the program's documentation +my $wantversion = 0; # 1=user wants to see the program's version number +my $verbose = 1; # 0=quiet; 1=verbose output; 2=more verbose output +my @forced_fonts; # Font mappings the user asserts are correct +my @exclude_res; # Regexps for fonts to exclude +my @extra_tfms; # Extra TFM files to use +my $sample_file_ps; # Name of a PostScript file of font samples to write +my $sample_file_tex; # Name of a TeX file of font samples to write +my $single_font_use = 0; # 1=one use per font; 0=allow repetitions + +########################################################################### + +# Given the base name of a .tfm file, process the file and return the +# font's design size and a mapping from character number to character +# width. +sub tfm2widths ($) +{ + my $tfmname = $_[0]; # Name of the TFM file + my $designsize; # Design size of the font + my %num2width; # Resultant mapping + my $plname; # Name of PL file; some tftopl programs can't write to stdout. + my $plfile; # Filehandle corresponding to $plname + + ($plfile, $plname) = tempfile (DIR => File::Spec->tmpdir(), SUFFIX => ".pl"); + close $plfile; + if (!system "$TFTOPL $tfmname $plname $discard_output") { + print STDERR " Processing $tfmname ... " if $verbose >= 2; + open (PLFILE, "<$plname") || die "${progname}: Unable to open $tfmname ($!)\n"; + my $charnum; # Current character number + while (my $oneline = <PLFILE>) { + # Store the current character width. + $oneline =~ /\(CHARWD R (\S+)\)/ && do { + $num2width{$charnum} = $1 * $designsize; + next; + }; + + # Store the current character number. + $oneline =~ /\(CHARACTER (\S) (\S+)/ && do { + if ($1 eq "O") { + # Octal character number + $charnum = oct $2; + } + elsif ($1 eq "C") { + # ASCII character number + $charnum = ord $2; + } + else { + die "${progname}: Unknown TFM character type \"$1\"\n"; + } + next; + }; + + # Store the font design size. + $oneline =~ /\(DESIGNSIZE R (\S+)\)/ && do { + $designsize = $1 + 0.0; + next; + }; + } + close PLFILE; + print STDERR "done.\n" if $verbose >= 2; + } + else { + print STDERR " Discarding $tfmname (not found).\n" if $verbose >= 3; + } + unlink $plname; + return [$designsize, %num2width]; +} + + +# Given two character maps, one for a document font and one for a TFM +# file, return the optimal scale factor for the TFM file to best match +# the document font. +sub optimal_scale ($$) +{ + my %docmap = %{$_[0]}; # Map for a document font + my %tfmmap = %{$_[1]}; # Map for a TFM font + my $doc_dot_tfm = 0.0; # Sum of $docmap{$c}*$tfmmap{$c} for all $c + my $tfm_dot_tfm = 0.0; # Sum of $tfmmap{$c}**2 for all $c + + while (my ($char, $docwidth) = each %docmap) { + my $tfmwidth = $tfmmap{$char}; + return undef if !defined $tfmwidth; # Match is impossible. + $doc_dot_tfm += $docwidth * $tfmwidth; + $tfm_dot_tfm += $tfmwidth**2; + } + return $doc_dot_tfm / $tfm_dot_tfm; +} + + +# Compare two character maps and return their mismatch (smaller is +# better). The third, optional, argument is a scale factor for the +# TFM file. +sub compare_maps ($$;$) +{ + my %docmap = %{$_[0]}; # Map for a document font + my %tfmmap = %{$_[1]}; # Map for a TFM font + my $scale = $_[2] || 1.0; # Scale for each TFM width + my $sqdiff = 0; # Sum of squares of differences + + while (my ($char, $docwidth) = each %docmap) { + my $tfmwidth = $tfmmap{$char}; + return 10**9 if !defined $tfmwidth; # Match is impossible. + $sqdiff += ($docwidth - $tfmwidth*$scale) ** 2; + } + return $sqdiff; +} + + +# Given a Type 3 font definition, surround it with DVIPSBitmapFont comments. +sub write_comments ($$) +{ + my ($fontname, $fontdef) = @_; + my $tfm = $fontmatch{$fontname}->{"tfm"}; + my $scale = $fontmatch{$fontname}->{"scale"}; + my $origsize = $tfm2size{$tfm}; + my $begincomment = sprintf '%%DVIPSBitmapFont: %s %s %.5g %d', + $fontname, $tfm, $origsize*$scale, 1+$#{$name2chars{$fontname}}; + my $endcomment = '%EndDVIPSBitmapFont'; + return "\n" . $begincomment . "\n" . $fontdef . "\n" . $endcomment . "\n"; +} + + +# Escape an array of characters for PostScript's benefit. +sub psify (@) +{ + my @ps_chars; + foreach my $onechar (@_) { + my $charnum = ord $onechar; + if ($onechar =~ /[\\()]/) { + push @ps_chars, "\\" . $onechar; + } + elsif ($charnum >= 32 && $charnum <= 126) { + push @ps_chars, $onechar; + } + else { + push @ps_chars, sprintf "\\%03o", $charnum; + } + } + return @ps_chars; +} + + +# Escape an array of characters for TeX's benefit. +sub texify (@) +{ + my @texchars; + foreach my $onechar (@_) { + if ($onechar =~ m|[\000-\037\\{}\177-\377]|) { + push @texchars, sprintf '\char"%02X{}', ord $onechar; + } + else { + push @texchars, $onechar; + } + } + return join "", @texchars; +} + + +# Parse a font specification into a hash of information. +sub parse_font_spec ($) +{ + my $spec = $_[0]; + my $parse_error = "${progname}: Unable to parse font specification \"$spec\"\n"; + + if ($spec =~ /^\s*([-\w]+)(.*)$/o) { + my $tfm = $1; # Name of tfm file (e.g., "cmr10") + my $scale_info = $2; # Concatenation of scale type and scale factor + my $scale_type; # "X"=multiply, "@"=assign + my $scale_amount; # How much to scale the TFM file, "*"=automatic + + if ($scale_info =~ /^\s*$/o) { + # Empty + $scale_type = 'X'; + $scale_amount = 1.0; + } + elsif ($scale_info =~ /^\s*\@\s*([\d.]+)\s*X\s*$/io) { + # "@ <number> X" + $scale_type = 'X'; + $scale_amount = $1 + 0.0; + } + elsif ($scale_info =~ /^\s*\@\s*([\d.]+)\s*(pt|bp)\s*$/io) { + # "@ <number> pt" or "@ <number> bp" + $scale_type = '@'; + $scale_amount = $1; + $scale_amount *= 72.0/72.27 if $2 eq "bp"; # Convert to TeX points + } + elsif ($scale_info =~ /^\s*\@\s*\*\s*$/o) { + # "@ *" + $scale_type = 'X'; + $scale_amount = "*" + } + else { + die $parse_error; + } + return {"tfm" => $tfm, + "scale_type" => $scale_type, + "scale" => $scale_amount}; + } + die $parse_error; +} + + +# Return all of the unique items in a given list. +sub unique_items (@) +{ + my %item_hash; + foreach my $item (@_) { + $item_hash{$item} = 1; + } + return keys %item_hash; +} + +########################################################################### + +# Parse the command line. +Getopt::Long::Configure ("bundling"); +GetOptions ("h|help" => \$wanthelp, + "v|verbose+" => \$verbose, + "V|version" => \$wantversion, + "q|quiet" => sub {$verbose=0}, + "f|force=s" => \@forced_fonts, + "i|include=s" => \@extra_tfms, + "x|exclude=s" => \@exclude_res, + "t|tex=s" => \$sample_file_tex, + "p|ps=s" => \$sample_file_ps, + "1|no-repeats" => \$single_font_use) || pod2usage(2); +if ($wantversion) { + print "pkfix-helper $VERSION\n"; + exit 0; +} +if ($wanthelp) { + pod2usage (-verbose => $verbose, + -exitval => "NOEXIT"); + print "Report bugs to scott+pkfh\@pakin.org.\n" if $verbose == 1; + exit 0; +} +my $infilename = $#ARGV>=0 ? $ARGV[0] : "-"; +my $outfilename = $#ARGV>=1 ? $ARGV[1] : "-"; + +# Convert any user-specified TFMs to the appropriate internal format. +foreach my $tfm (@extra_tfms) { + my $font_spec = parse_font_spec $tfm; + push @tfmlist, $font_spec; +} + +# Parse the list of forced font mappings. +foreach my $mapstr (@forced_fonts) { + $mapstr =~ /^(\w+)\s*=\s*(.*)$/ || die "${progname}: Unable to parse font specification \"$mapstr\"\n"; + $fontmatch{$1} = parse_font_spec $2; +} + +# Construct a list of (possibly nonexistent) TFM files to try. These +# should be in order of decreasing likelihood. Each entry in the list +# is of the form {full name, scale factor}. +@exclude_res = ('^\s*$') if $#exclude_res == -1; +foreach my $size_scale ([10, 1.0], + [12, 1.0], + [10, 1.1], + [17, 1.0], + [ 9, 1.0], + [ 8, 1.0], + [ 7, 1.0], + [ 6, 1.0], + [ 5, 1.0], + [10, 1.2], + # The following are common cmbx12 section headings. + [12, 14.40/12], + [12, 17.28/12], + [12, 20.74/12], + [12, 24.88/12]) { + my ($pointsize, $scale) = @$size_scale; + FONTLOOP: + foreach my $basefont (qw (cmr cmb cmtt cmbsy cmbx cmbxsl cmbxti + cmcsc cmex cmitt cmmi cmmib cmsl cmsltt + cmss cmssbx cmssi cmsy cmti lasy lasyb + msam msbm cmssdc cmtcsc)) { + my $friendly_name = sprintf "%s%d \@ %.5gX", $basefont, $pointsize, $scale; + foreach my $regexp (@exclude_res) { + next FONTLOOP if $friendly_name =~ $regexp; + } + push @tfmlist, {"tfm" => $basefont . $pointsize, + "scale_type" => "X", + "scale" => $scale}; + } +} + +# Read the entire input file. +$| = 1; +if ($verbose) { + printf STDERR "Reading %s ... ", $infilename eq "-" ? "standard input" : $infilename; +} +my $entirefile; +{ + local $/ = undef; + open (INFILE, "<$infilename") || die "open(\"$infilename\"): $!\n"; + binmode INFILE; + $entirefile = <INFILE>; + close INFILE; +} +print STDERR "done.\n" if $verbose; + +# Construct a mapping from each document font name to a list of valid +# characters in that font. +while ($entirefile =~ m|/(\S+)\s+\d+\s+\d+\s+df(.*?>[^<>]*?[DI])\s+E|gs) { + my $fontname = $1; # Name of current font (e.g., "Fa") + my $fontbody = $2; # List of character definitions as hexadecimal strings + my $charnum = 0; # Current character number + my @charlist = (); # List of valid characters in PostScript-friendly format + + while ($fontbody =~ /<[0-9A-F\s]+>(.*?[DI])/gs) { + # Put the current character number in $charnum then append the + # corresponding character to @charlist. + my @chardef = split " ", $1; + if ($chardef[$#chardef] eq "I") { + $charnum++; + } + else { + $charnum = $chardef[$#chardef-1]; + } + push @charlist, chr $charnum; + } + $name2chars{$fontname} = \@charlist; +} +my @sortedfontnames = sort {$#{$name2chars{$b}} <=> $#{$name2chars{$a}} + || $a cmp $b} keys %name2chars; +if ($verbose) { + printf STDERR "Number of Type 3 fonts encountered: %d\n", 1+$#sortedfontnames; + if ($verbose >= 2) { + foreach my $fontname (@sortedfontnames) { + printf STDERR " %s -- %3d character(s)\n", $fontname, 1+$#{$name2chars{$fontname}}; + } + } +} +die "${progname}: No Type 3 fonts were encountered in the input file\n" if $#sortedfontnames==-1; + +# Determine the number of dots per inch used to generate the bitmaps. +if ($entirefile =~ /dpi=(\d+)/i + || $entirefile =~ /Resolution (\d+)dpi/i) { + $dpi = $1 + 0; + printf STDERR "Bitmapped fonts are typeset at $dpi DPI.\n" if $verbose; +} +else { + warn "${progname}: Could not determine the target printer resolution; assuming $dpi DPI\n"; +} + +# Insert some helper code after the first ProcSet. +my $output_width_ps = $entirefile; # PostScript code to output character widths +my $showfontnamecode = <<"SHOWFONTNAME"; +\%\%BeginProcSet: $progname.pro +TeXDict begin + +% char0 char1 PRINT-WIDTH - +% +% Output the name of the current font (font-name-string), its character +% number (char0), and the character's width in PostScript points. + +/print-width { + pop + (FONT: ) print font-name-string print + ( CHAR: ) print 8 string cvs print + ( XPOS: ) print currentpoint pop 80 string cvs print + (\\n) print +} bind def + +% font-name sample-string PRINT-CHAR-WIDTHS - +% +% Store the name of font-name in the string font-name-string. Then, select +% font-name and, for each character of test-string, call print-width +% to output its width. + +/print-char-widths { + /sample-string exch def + /font-name exch def + font-name 8 string cvs /font-name-string exch def + font-name cvx exec {print-width} sample-string kshow +} bind def + +end +\%\%EndProcSet +SHOWFONTNAME + ;#' +if ($output_width_ps !~ s/\%\%EndProcSet/$&\n$showfontnamecode/s) { + print STDERR 'No %%EndProcSet comment was found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject prologue code\n" if $output_width_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop/\n$showfontnamecode\n$&/s; +} + +# Define some code to display the width of every valid character in +# every bitmapped font. Fonts are displayed in decreasing order of +# the number of characters used. +my $displaycode = "\%\%Page: 1 1\nTeXDict begin\n1 0 bop\n"; +foreach my $fontnum (0 .. $#sortedfontnames) { + # Duplicate the last character of the sample string so kshow can + # process the final character delta. + my $fontname = $sortedfontnames[$fontnum]; + my @charlist = psify @{$name2chars{$fontname}}; + my $samplestring = join("", @charlist) . $charlist[$#charlist]; + + # Typeset the string starting at horizontal offset 0. + $displaycode .= sprintf "0 0 moveto\n"; + $displaycode .= "/$fontname ($samplestring) print-char-widths\n"; +} + +# Dvips scales the page. Determine the scaling it uses. +$displaycode .= <<'ENDDISPLAYCODE'; +(CURRENTMATRIX: ) print +matrix currentmatrix == +(\n) print +eop +end +ENDDISPLAYCODE + ; + +# Replace the bulk of the PostScript file with the display code. +if ($output_width_ps !~ s/\%\%Page:.*(\%\%Trailer)/$displaycode$1/s) { + print STDERR 'No %%Page and/or %%Trailer comments were found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject display code\n" if $output_width_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop.*eop\s+end/\n$displaycode\n/s; +} + +# Output the modified PostScript code to a temporary file, run +# Ghostscript on the temporary file, and process Ghostscript's output. +my ($psfile, $psfilename) = tempfile ("pkfix-helper-XXXXXX", + DIR => File::Spec->tmpdir(), + SUFFIX => ".ps"); +binmode $psfile; +print $psfile $output_width_ps; +close $psfile; +undef $output_width_ps; +my %fontwidth; # Map from font name to character number to character width +my @previnfo = ("", 0.0); # Previous font name and final character position +my $gscmd = "$GS -q -dNOPAUSE -dBATCH -dNODISPLAY $psfilename"; +print STDERR "Finding character widths ... " if $verbose >= 1; +print STDERR "\n Invoking: $gscmd\n" if $verbose >= 2; +print STDERR "done.\n" if $verbose >= 1; +open (GSCMD, "$gscmd|") || die "${progname}: failed to fork ($!)\n"; +while (my $oneline = <GSCMD>) { + if ($oneline =~ /FONT: (\S+)\s*CHAR: (\d+)\s*XPOS: (\S+)/o) { + my ($fontname, $charnum, $xpos) = ($1, $2, $3); + my $width = $xpos + 0.0; + $width -= $previnfo[1] if $fontname eq $previnfo[0]; + $fontwidth{$fontname}->{$charnum} = $width * 72.27 / $dpi; + @previnfo = ($fontname, $xpos); + } + elsif ($oneline =~ /CURRENTMATRIX: \[\s*([-\d.]+)\s+[-\d.]+\s+[-\d.]+\s+([-\d.]+)\s+[-\d.]+\s+[-\d.]+\s*\]/o) { + $dvips_xscale = $1 * 1.0; + $dvips_yscale = $2 * -1.0; + } +} +close GSCMD || die "${progname}: failed to run $GS ($!)\n"; +unlink $psfilename; +die "${progname}: No character-width information was found\n" if !%fontwidth; + +# Read each TFM file and store its design size and character widths. +print STDERR "Reading TFM files ... " if $verbose; +print STDERR "\n" if $verbose >= 2; +foreach my $tfm (sort {$a cmp $b} + unique_items map {$_->{"tfm"}} (@tfmlist, values %fontmatch)) { + my ($designsize, %num2widths) = @{tfm2widths $tfm}; + if (%num2widths) { + $tfmfontwidth{$tfm} = \%num2widths; + $tfm2size{$tfm} = $designsize * 1.0; + } +} + +# Remove nonexistent fonts from @tfmlist and replace all absolute +# ("@") scaling with relative ("X") scaling. +my @goodtfmlist; +foreach my $tfminfo (@tfmlist) { + my $tfm = $tfminfo->{"tfm"}; + next if !defined ($tfmfontwidth{$tfm}); + $tfminfo->{"designsize"} = $tfm2size{$tfm}; + if ($tfminfo->{"scale_type"} eq "@") { + # Convert absolute to relative sizes. + $tfminfo->{"scale_type"} = "X"; + $tfminfo->{"scale"} /= $tfminfo->{"designsize"}; + } + push @goodtfmlist, $tfminfo; +} +@tfmlist = @goodtfmlist; +undef @goodtfmlist; + +# Do the same for all user-specified font mappings. +while (my ($fontname, $tfminfo) = each %fontmatch) { + my $tfm = $tfminfo->{"tfm"}; + if (!defined ($tfmfontwidth{$tfm})) { + print STDERR "failed.\n" if $verbose; + die "${progname}: Unable to process user-specified TFM file \"$tfm\"\n"; + } + $tfminfo->{"designsize"} = $tfm2size{$tfm}; + if ($tfminfo->{"scale_type"} eq "@") { + # Convert absolute to relative sizes. + $tfminfo->{"scale_type"} = "X"; + $tfminfo->{"scale"} /= $tfminfo->{"designsize"}; + } +} + +# Report the number of fonts in our repertoire. +my $numtfms = keys %tfm2size; +my $numfonts = 1 + $#tfmlist; +print STDERR "done ($numtfms TFMs in $numfonts scaling variations).\n" if $verbose; +die "${progname}: No TFM files were processed successfully\n" if !$numtfms; + +# Compare every document font (ordered by decreasing number of +# characters utilized) to every TFM file (in increasing order of +# obscurity). +print STDERR "Matching fonts:\n" if $verbose; +foreach my $fontname (@sortedfontnames) { + my @besttfms; # Best matching TFM file(s), sizes, and scales + my $bestmatch = 10**9; # Best matching value + + # Determine the list of eligible fonts to compare against. + my @eligible_tfms; + foreach my $tfminfo ($fontmatch{$fontname} || @tfmlist) { + if ($tfminfo->{"scale"} eq "*") { + # Replace "*" with the best scaling factor we can find. + my $newscale = optimal_scale $fontwidth{$fontname}, $tfmfontwidth{$tfminfo->{"tfm"}}; + if (defined $newscale) { + # Replace the "*" with the optimal multiplier. + my %newtfminfo = %$tfminfo; + $newtfminfo{"scale"} = $newscale; + push @eligible_tfms, \%newtfminfo; + } + else { + # Fonts are incomparable. + my $tfm = $tfminfo->{"tfm"}; + print STDERR " Not scaling $tfm; ${fontname}'s character set is not a subset of ${tfm}'s.\n" if $verbose >= 2; + } + } + else { + # The desired scaling factor is specified explicitly. + push @eligible_tfms, $tfminfo; + } + } + die "${progname}: No fonts are eligible to match $fontname\n" if !@eligible_tfms; + + # Try each TFM file in increasing order of obscurity. + print STDERR " Processing $fontname ... " if $verbose == 1; + foreach my $tfminfo (@eligible_tfms) { + my $tfm = $tfminfo->{"tfm"}; + my $scale = $tfminfo->{"scale"}; + printf STDERR " Comparing %s and %s \@ %.5gX ... ", $fontname, $tfm, $scale if $verbose >= 2; + my $match = compare_maps $fontwidth{$fontname}, $tfmfontwidth{$tfm}, $scale; + if ($bestmatch > $match) { + # We found a closer match than what we had before. + $bestmatch = $match; + @besttfms = ($tfminfo); + } + elsif ($bestmatch == $match) { + # We found an equal match to what we had before. + push @besttfms, $tfminfo; + } + printf STDERR "done (mismatch=%.5f).\n", $match if $verbose >= 2; + } + + # Select the first of the best matches. + $fontmatch{$fontname} = $besttfms[0]; + my $besttfminfo = $fontmatch{$fontname}; + my $besttfm = $besttfminfo->{"tfm"}; + my $bestscale = $besttfminfo->{"scale"}; + if ($verbose >= 2) { + if ($#besttfms == 0) { + # Single winner + printf STDERR " Best match for %s is %s \@ %.5gX with mismatch=%.5f.\n\n", + $fontname, $besttfm, $bestscale, $bestmatch; + } + else { + # Tie for first place + printf STDERR " Best match for %s is %s \@ %.5gX (tied among %s) with mismatch=%.5f.\n\n", + $fontname, $besttfm, $bestscale, + join("/", map {sprintf "%s\@%.5gX", $_->{"tfm"}, $_->{"scale"}} @besttfms), + $bestmatch; + } + } + elsif ($verbose == 1) { + printf STDERR "done (%s \@ %.5gX, mismatch=%.5f).\n", $besttfm, $bestscale, $bestmatch; + } + warn "${progname}: Best match for $fontname is rather poor\n" if $bestmatch>=1.0; + + # Optionally remove the font from @goodtfmlist. + if ($single_font_use) { + @tfmlist = grep {$_->{"tfm"} ne $besttfm + || $_->{"scale"} != $bestscale} @tfmlist; + } +} + +# Insert %DVIPSBitmapFont comments around every Type 3 font definition. +my $commented_ps = $entirefile; +my $infilename_ps = $infilename; # PostScript version of $infilename +$infilename_ps =~ s/[()\\]/\\$1/g; +$commented_ps =~ s|^\%(End)?DVIPSBitmapFont.*$||gm; # Remove existing comments (if any) +$commented_ps =~ s|/(\S+)\s+\d+\s+\d+\s+df.*?>[^<]*?[DI]\s+E|write_comments($1, $&)|gse; +if ($commented_ps !~ /\%\%EndProlog/) { + # pkfix fails silently if it doesn't see an %%EndProlog. + print STDERR "No %%EndProlog comment was found. Adding one.\n" if $verbose >= 3; + $commented_ps =~ s|TeXDict begin\s+\d+\s+\d+\s+bop|\%\%EndProlog\n$&|s; +} + +# Help pkfix handle ancient versions of dvips by artificially making +# dvips look newer. +$commented_ps =~ s|(\%\%Creator: dvips\S*) \S+|$1 5.62|; # pkfix rejects dvips <= 5.58 +if ($commented_ps =~ s|(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\@start|$1 $2 $3 $4 $5 ($infilename_ps) \@start|gx) { + # pkfix expects *six* arguments to @start, not five as in old + # versions of dvips. + $commented_ps =~ s|/\@start\s*\{|$& pop |; +} +if ($commented_ps !~ /^%DVIPSParameters:.*dpi=([\dx]+)/) { + # Tell pkfix what resolution to use. + my $dvips_params = "\%DVIPSParameters: dpi=$dpi"; + if ($commented_ps !~ s|^\%\%EndComments.*$|$&\n$dvips_params|m) { + # Comments must have been stripped. + $commented_ps =~ s|\n|\n$dvips_params\n|; + } +} + +# Write the modified PostScript code to the specified file. +open (OUTFILE, ">$outfilename") || die "${progname}: Unable to open $outfilename ($!)\n"; +print OUTFILE $commented_ps; +close OUTFILE; +undef $commented_ps; + +# If the user requested a PostScript font sample, produce that. +if (defined $sample_file_ps) { + # Insert some helper code at an appropriate place in the file. + my $sample_ps = $entirefile; + my $showfontnamecode = <<"SHOWFONTNAME"; +\%\%BeginProcSet: $progname.pro +TeXDict begin + +% font-name sample-string PRINT-FONT-SAMPLE - +% +% Store the name of font-name in the string font-name-string. Then, +% output font-name-string in Times Bold in case the user wants to view +% the font samples. Next, select font-name and output the sample +% string. Finally, move the cursor to the next line in preparation for +% the next invocation of print-font-sample. +/print-font-sample { + /sample-string exch def + /font-name exch def + font-name 8 string cvs /font-name-string exch def + gsave + /Times-Bold 12 selectfont + font-name-string show (:) show + grestore + gsave + 36 0 rmoveto + font-name cvx exec + currentfont bitmap-font-transform makefont setfont + sample-string show + grestore + 0 -24 rmoveto +} def + +end +\%\%EndProcSet +SHOWFONTNAME + ; + if ($sample_ps !~ s/\%\%EndProcSet/$&\n$showfontnamecode/) { + print STDERR 'No %%EndProcSet comment was found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject prologue code\n" if $sample_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop/\n$showfontnamecode\n$&/s; + } + + # Generate code to output a sample of each font in turn. + my $displaycode = <<"PAGEHEADER"; +\%\%Page: 1 1 +TeXDict begin +1 0 bop + +\% Define a transformation matrix for dvips bitmapped fonts. We _could_ +\% do this dynamically but there seems to be a bug in GhostView (v3.6.1) +\% or GhostScript (ESP v7.07.1) that causes the page layout to change +\% with rescaling. To avoid problems we simply hardwire the scaling +\% factor. +/bitmap-font-transform [$dvips_xscale 0.0 0.0 $dvips_yscale 0 0] def + +\% Display a page title. +0 0 moveto +initmatrix +gsave + /Helvetica 18 selectfont + (Fonts used by $infilename_ps) show +grestore +0 -$init_yinc rmoveto + +\% Display samples of each document font in decreasing order of the number +\% of characters utilized from the font. +PAGEHEADER +; + foreach my $fontnum (0 .. $#sortedfontnames) { + my $fontname = $sortedfontnames[$fontnum]; + my $samplestring = join("", psify @{$name2chars{$fontname}}); + $displaycode .= "/$fontname ($samplestring) print-font-sample\n"; + } + $displaycode .= "eop\nend\n"; + if ($sample_ps !~ s/\%\%Page:.*(\%\%Trailer)/$displaycode$1/s) { + print STDERR 'No %%Page and/or %%Trailer comments were found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject display code\n" if $sample_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop.*eop\s+end/\n$displaycode\n/s; + } + + # Write the PostScript file. + open (SAMPLE_PS, ">$sample_file_ps") || die "${progname}: Unable to open $sample_file_ps ($!)\n"; + binmode SAMPLE_PS; + print SAMPLE_PS $sample_ps; + close SAMPLE_PS; + undef $sample_ps; +} + +# If the user requested a TeX font sample, produce that. +if (defined $sample_file_tex) { + my $oneline; # One line to write to the TeX file. + + open (SAMPLE_TEX, ">$sample_file_tex") || die "${progname}: Unable to open $sample_file_tex ($!)\n"; + select (SAMPLE_TEX); + $| = 1; + select (STDOUT); + format SAMPLE_TEX = +% ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~ +$oneline +. + $oneline = <<"TEX_HEADER"; +This file was generated by $0. DO NOT EDIT. Edit $progname instead. +Note that this is a Plain TeX document. Compile it with tex, *not* +latex. +TEX_HEADER + ; + write SAMPLE_TEX; + print SAMPLE_TEX <<'TEX_BOILERPLATE'; + +% Make printable all special characters between +% \makeprintable...\endmakeprintable except for "\", "{", and "}". +\def\makeprintable{% + \begingroup + \def\do##1{\catcode`##1=12}% + \dospecials + \catcode`\\=0\relax + \catcode`\{=1\relax + \catcode`\}=2\relax +} +\let\endmakeprintable=\endgroup + +% Put a piece of text at specific PostScript coordinates. +\newdimen\xofs +\newdimen\yofs +\def\put(#1,#2)#{% + \leavevmode + \begingroup + \makeprintable + \xofs=#1bp + \yofs=#2bp + \afterassignment\puthelper + \toks0=% +} +\def\puthelper{% + \lower\yofs + \rlap{\hskip\xofs\the\toks0}% + \endmakeprintable + \endgroup +} + +% We use Times Bold at 12 point for font names. +\font\timesbXII=ptmb at 12bp + +% Don't add extra space to paragraphs. +\parindent=0pt +\parskip=0pt + +% Output the document's title. +\font\somefont=phvr at 18bp +TEX_BOILERPLATE + ; + # Output the document's title. + my $infilename_tex = texify split "", $infilename; + print SAMPLE_TEX '\put(0, 0){\somefont New fonts to use for ', "$infilename_tex}\n"; + + # Output samples of each font in turn. + print SAMPLE_TEX "\n\% Output font samples.\n"; + foreach my $fontnum (0 .. $#sortedfontnames) { + my $fontname = $sortedfontnames[$fontnum]; + my $samplestring = texify @{$name2chars{$fontname}}; + my $yoffset = $fontnum*$yinc + $init_yinc; + printf SAMPLE_TEX "\\put(0, %d){\\timesbXII %s:}%%\n", $yoffset, $fontname; + my $tfm = $fontmatch{$fontname}->{"tfm"}; + my $scale = $fontmatch{$fontname}->{"scale"}; + my $size = $tfm2size{$tfm}; + printf SAMPLE_TEX "\\font\\somefont=%s%s\\somefont\n", + $tfm, $scale==1.0 ? "" : sprintf(" at %.5gbp", $scale*$size); + printf SAMPLE_TEX "\\put(%d, %d){%s}%%\n", $xinc, $yoffset, $samplestring; + } + + # Complete the TeX file. + print SAMPLE_TEX "\n\\bye\n"; + close SAMPLE_TEX; +} + +########################################################################### + +__END__ + +=head1 NAME + +pkfix-helper - preprocess dvips-produced PostScript documents before passing them to pkfix + + +=head1 SYNOPSIS + +pkfix-helper +[B<--help>] +[B<--verbose>] +[B<--force>=I<name>=I<fontspec>] +[B<--ps>=I<filename.ps>] +[B<--tex>=I<filename.tex>] +[B<--include>=I<fontspec>] +[B<--exclude>=I<regexp>] +[B<--quiet>] +[B<--no-repeats>] +[I<input.ps> [I<output.ps>]] + + +=head1 DESCRIPTION + +=head2 Motivation + +PostScript documents created with old versions of B<dvips> almost +invariably utilize bitmapped (PostScript S<Type 3>) fonts. The +problem with bitmapped fonts is that they target a specific device +resolution; a PostScript file produced using S<300 DPI> fonts will +look grainy on a S<600 DPI> printer. Even worse, I<all> bitmapped +fonts look grainy when zoomed in on screen. The solution is to use +vector (PostScript S<Type 1>) fonts, which are resolution-independent +and appear crisp at any size or scale. + +While it is no longer difficult to configure B<dvips> to use vector +fonts, it is not always possible to rerun B<dvips> on an old F<.dvi> +file. The F<.dvi> file and document source may have been lost; or, +the source may no longer compile because packages it depends upon may +no longer be available. + +Heiko Oberdiek's B<pkfix> script replaces bitmapped fonts in +B<dvips>-produced PostScript files with the corresponding vector +fonts. It works by parsing the PostScript comments with which +B<dvips> surrounds bitmapped-font definitions. For example, a font +definition beginning with the comment C<%DVIPSBitmapFont: Fi cmss10 11 +28> and ending with a matching C<%EndDVIPSBitmapFont> is known to +define font C<Fi> as C<cmss10> (Computer Modern Sans Serif at a design +size of S<10 points>) scaled to S<C<11> points>. Only the C<28> +characters actually used by the document are defined. B<pkfix> then +replaces the font definition with one that defines C<Fi> using the +same set of characters but taken from the F<cmss10.pfb> vector font +file. + +Unfortunately, B<pkfix> works only with versions of B<dvips> newer +than v5.58 S<(ca. 1996)>. Naturally, the older a PostScript document, +the less likely its sources still exist and can still be recompiled. +Older versions of B<dvips> lack C<%DVIPSBitmapFont> comments and +various other PostScript comments on which B<pkfix> relies. Without +PostScript comments to guide it, B<pkfix> is unable to determine which +vector fonts correspond with which bitmapped fonts. + +=head2 Overview + +The B<pkfix-helper> script is a preprocessor for B<pkfix> that +attempts to determine the association between each document-font name +S<(e.g., C<Fi>)> in a PostScript file and the original font S<(e.g., +C<cmss10>)> and fonts size (e.g., S<C<11> points>). It then +fabricates the PostScript comments that B<pkfix> expects to see so +that B<pkfix> can do its job. + +B<pkfix-helper> works by comparing every document font against every +F<.tfm> font file it knows about (assuming that each such font has a +corresponding F<.pfb> vector version) and selecting the best matching +F<.tfm> file for every document font. B<pkfix-helper> has access only +to the widths of characters and only to those characters actually used +in the document. Also, the program recognizes only a limited set of +the most popular F<.tfm> files and scaling factors. Consequently, the +comparison is imperfect and B<pkfix-helper> may attribute an incorrect +font to a given name. Fonts comprising only one or two characters +actually used in a document are particularly problematic for +B<pkfix-helper> because many fonts may be near-enough matches to fool +the problem. + +B<pkfix-helper> is designed so that a user can guide the +font-selection process by manually designating matching fonts. With a +modicum of diligence and patience a user can correct any mismatched +fonts and help the program provide proper input to B<pkfix>. + + +=head1 OPTIONS + +B<pkfix-helper> accepts on the command line the filename of a +PostScript document to process (with the default being the standard +input device) and the filename of a modified PostScript document to +create (with the default being the standard output device). The +program also accepts the following command-line options: + +=head2 Frequently Used Options + +=over 4 + +=item B<-h>, B<--help> + +Display usage information and exit. The B<--verbose> and B<--quiet> +options can be used to increase and decrease the amount of information +presented. + +=item B<-v>, B<--verbose> + +Increase the amount of status information that B<pkfix-helper> +displays as it runs. Additional instances of B<--verbose> on the +command line further increase the program's verbosity. By default, +only major operations are displayed. A single B<--verbose> +additionally displays information about individual font comparisons. +A second B<--verbose> additionally displays details about some of the +program's internal operations. + +=item B<-f> I<name>=I<fontspec>, B<--force>=I<name>=I<fontspec> + +Force B<pkfix-helper> to associate a specific font with a given font +name appearing the document. I<name> is a two-character B<dvips> font +name such as C<Fa>. I<fontspec> is a font specification such as +S<C<cmsy10 @ 1.1X>>. The B<--force> option can be specified +repeatedly on the command line. + +=item B<-p> I<filename.ps>, B<--ps>=I<filename.ps> + +Create a PostScript file called I<filename.ps> that shows the B<dvips> +name and a font sample of every font used by the input document. + +=item B<-t> I<filename.tex>, B<--tex>=I<filename.tex> + +Create a Plain TeX file called I<filename.tex> that shows the B<dvips> +name and a font sample of every font that B<pkfix-helper> used in the +output document. + +=back + +=head2 Infrequently Used Options + +=over 4 + +=item B<-i> I<fontspec>, B<--include>=I<fontspec> + +Add I<fontspec> to the list of font specifications against which +B<pkfix-helper> compares I<every> document font. (In contrast, +B<--force> designates a font specification to use only for a +I<specific> document font.) The B<--include> option can be specified +repeatedly on the command line. + +=item B<-x> I<regexp>, B<--exclude>=I<regexp> + +Remove all font specifications matching regular expression I<regexp> +from B<pkfix-helper>'s list of known fonts. The B<--exclude> option +can be specified repeatedly on the command line. + +=item B<-q>, B<--quiet> + +Instruct B<pkfix-helper> to produce no output during its run except +for fatal error messages. + +=item B<-1>, B<--no-repeats> + +Prevent B<pkfix-helper> from associating the same I<fontspec> with +more than one B<dvips> font name. + +=back + + +=head1 DIAGNOSTICS + +=over 4 + +=item C<Best match for I<name> is rather poor> + +The best font B<pkfix-helper> found for B<dvips> font name I<name> has +a mismatch value greater than or equal S<to 1.0>. (The mismatch value +is the sum of the squares of the difference between the character +widths of a document font and a potential replacement font.) Use the +B<--force> option to designate an alternative replacement font or +scaling amount. + +=back + + +=head1 EXAMPLES + +For the purpose of the following examples, assume that F<oldfile.ps> +is the name of a PostScript file produced by an old version of +B<dvips> and utilizing at least one bitmapped font. It's always worth +verifying that B<pkfix> can't convert the file on its own: + + % pkfix oldfile.ps newfile.ps + PKFIX 1.3, 2005/02/25 - Copyright (c) 2001, 2005 by Heiko Oberdiek. + ==> no fonts converted + +(Alternatively B<pkfix> may issue an error message such as C<!!! +Error: Parse error (@start parameters)!>.) Only when B<pkfix> can't +replace bitmapped fonts with vector fonts is B<pkfix-helper> needed. +In its simplest form, B<pkfix-helper> takes the name of an input file +(F<oldfile.ps> in this example) and the name of an output file +(F<pkfix-oldfile.ps>), which will have the same contents as the input +file but serve as suitable input for B<pkfix>: + + % pkfix-helper oldfile.ps pkfix-oldfile.ps + Reading netpipe.ps ... done. + Number of Type 3 fonts encountered: 10 + Bitmapped fonts are typeset at 600 DPI. + Finding character widths ... done. + Reading TFM files ... done (103 TFMs in 193 scaling variations). + Matching fonts: + Processing Fi ... done (cmr10 @ 1X, mismatch=0.11683). + Processing Fa ... done (cmti10 @ 1X, mismatch=0.08892). + Processing Fb ... done (cmr8 @ 1X, mismatch=0.07133). + Processing Ff ... done (cmbx12 @ 1.2X, mismatch=0.02948). + Processing Fh ... done (cmtt10 @ 1X, mismatch=0.06895). + Processing Fd ... done (cmmi10 @ 1X, mismatch=0.03966). + Processing Fj ... done (cmbx12 @ 1X, mismatch=0.03972). + Processing Fe ... done (cmbx10 @ 1X, mismatch=0.00762). + Processing Fg ... done (cmsy10 @ 1X, mismatch=0.00875). + Processing Fc ... done (cmr6 @ 1X, mismatch=0.00284). + + % pkfix pkfix-oldfile.ps newfile.ps + PKFIX 1.3, 2005/02/25 - Copyright (c) 2001, 2005 by Heiko Oberdiek. + *** Font conversion: `cmti10' -> `CMTI10'. + *** Font conversion: `cmr8' -> `CMR8'. + *** Font conversion: `cmr6' -> `CMR6'. + *** Font conversion: `cmmi10' -> `CMMI10'. + *** Font conversion: `cmbx10' -> `CMBX10'. + *** Font conversion: `cmbx12' -> `CMBX12'. + *** Font conversion: `cmsy10' -> `CMSY10'. + *** Font conversion: `cmtt10' -> `CMTT10'. + *** Font conversion: `cmr10' -> `CMR10'. + *** Font conversion: `cmbx12' -> `CMBX12'. + *** Merging font `CMBX12' (2). + ==> 10 converted fonts. + ==> 1 merged font. + +Although B<pkfix-helper> tries to automate as much as possible the +font-detection process, some fonts will invariably be incorrectly +identified. The program outputs a warning message if it I<knows> a +match is bad but the lack of a warning message does not necessarily +indicate that B<pkfix-helper> did a good job. It is therefore +strongly recommended that the user produce "before" and "after" font +sheets: + + % pkfix-helper -q oldfile.ps pkfix-oldfile.ps \ + --ps=oldfonts.ps --tex=newfonts.tex + + % tex newfonts.tex + This is TeX, Version 3.14159 (Web2C 7.4.5) + (./newfonts.tex [1] ) + Output written on newfonts.dvi (1 page, 1292 bytes). + Transcript written on newfonts.log. + + % dvips newfonts.dvi -o newfonts.ps + This is dvips(k) 5.92b Copyright 2002 Radical Eye Software (www.radicaleye.com) + ' TeX output 2006.06.11:1636' -> newfonts.ps + <texc.pro><8r.enc><texps.pro>. <cmr6.pfb><cmsy10.pfb><cmbx10.pfb><cmbx12.pfb> + <cmmi10.pfb><cmtt10.pfb><cmr8.pfb><cmti10.pfb><cmr10.pfb>[1] + +After running the preceding commands, F<oldfonts.ps> shows samples of +the fonts in F<oldfile.ps> and F<newfonts.ps> shows samples of the +replacement fonts that B<pkfix-helper> used to produce +F<pkfix-oldfile.ps>. Print F<oldfonts.ps> and <newfonts.ps> and +compare them carefully for incorrect fonts and sizes. + +Suppose that the choice of C<cmbx12 @ 1.2X> for font C<Ff> looks +wrong; say the characters look taller in F<oldfonts.ps> than in +F<newfonts.ps>. This is where the trial-and-error stage begins. +Let's hypothesize that C<cmb12> is a better match than C<cmbx12> but +we don't know how much to scale the font. Fortunately, +B<pkfix-helper> allows C<*> to be used as a scaling factor to tell the +program to automatically detect an optimal scaling factor, even if +doing so means choosing a highly nonstandard font size: + + % pkfix-helper oldfile.ps pkfix-oldfile.ps --force="Ff=cmb12 @ *" + Reading netpipe.ps ... done. + Number of Type 3 fonts encountered: 10 + Bitmapped fonts are typeset at 600 DPI. + Finding character widths ... done. + Reading TFM files ... failed. + pkfix-helper: Unable to process user-specified TFM file "cmb12" + +Oops, it looks like we don't have a F<cmb12.tfm> file on our system. +Let's try scaling up F<cmb10.tfm> instead: + + % pkfix-helper oldfile.ps pkfix-oldfile.ps --force="Ff=cmb10 @ *" + Reading netpipe.ps ... done. + Number of Type 3 fonts encountered: 10 + Bitmapped fonts are typeset at 600 DPI. + Finding character widths ... done. + Reading TFM files ... done (103 TFMs in 193 scaling variations). + Matching fonts: + Processing Fi ... done (cmr10 @ 1X, mismatch=0.11683). + Processing Fa ... done (cmti10 @ 1X, mismatch=0.08892). + Processing Fb ... done (cmr8 @ 1X, mismatch=0.07133). + Processing Ff ... done (cmb10 @ 1.5708X, mismatch=0.00035). + Processing Fh ... done (cmtt10 @ 1X, mismatch=0.06895). + Processing Fd ... done (cmmi10 @ 1X, mismatch=0.03966). + Processing Fj ... done (cmbx12 @ 1X, mismatch=0.03972). + Processing Fe ... done (cmbx10 @ 1X, mismatch=0.00762). + Processing Fg ... done (cmsy10 @ 1X, mismatch=0.00875). + Processing Fc ... done (cmr6 @ 1X, mismatch=0.00284). + +The match has definitely improved, although S<15.708 pt.> is certainly +an odd size for a font. Then again, many documents I<do> use +nonstandard sizes so this may in fact be correct. The best way to +verify is once again to produce, print, and compare a pair of font +samples and iterate until all of the fonts look correct. Use one +instance of B<--force> for each font you want to alter. + + +=head1 ENVIRONMENT + +B<pkfix-helper> honors the following environment variables: + +=over 8 + +=item GS + +The name of the Ghostscript interpreter (default: F<gs>) + +=item TFTOPL + +The name of a utility for converting F<.tfm> files to F<.pl> files +(default: F<tftopl>) + +=back + + +=head1 BUGS + +Even when B<pkfix-helper> finds a perfect match S<(i.e., the> correct +font in the correct size) the mismatch value is still typically +nonzero. The same error is probably what causes B<pkfix-helper> +sometimes to consider the wrong font as being a better match than the +correct font. Suggestions for fixing these bugs are welcome. + + +=head1 RESTRICTIONS + +B<pkfix-helper> works only with PostScript files produced by B<dvips>, +not with arbitrary PostScript files. The program has not been tested +with output from versions of B<dvips> older than v5.490 S<(ca. 1992)>; +output from older versions may or may not work. Only bitmapped fonts +loaded by B<dvips> can be analyzed, not bitmapped fonts loaded by +embedded graphics. + +B<pkfix-helper> works by comparing character widths, not the actual +glyphs. Consequently, it is misled by sets of fonts with similar +character widths (at least for those characters used by a given +document). As an extreme example, all Computer Modern Teletype fonts +of a given design size (e.g., C<cmtt10>, C<cmsltt10>, and C<cmitt10>) +use exactly the same widths for all characters. Human assistance is +generally needed to guide B<pkfix-helper>'s font-matching procedures. + + +=head1 NOTES + +Files produced using the B<--tex> option are Plain TeX files and +therefore must be compiled with F<tex> (or a variation such F<etex>, +F<pdftex>, F<pdfetex>, etc.), I<not> with F<latex>. + + +=head1 SEE ALSO + +pkfix(1), dvips(1), tex(1), gs(1) + +PostScript Language Reference, Third Edition. +Published by Addison-Wesley, ISBN 0-201-37922-8, +L<http://www.adobe.com/products/postscript/pdfs/PLRM.pdf>. + + +=head1 AUTHOR + +Scott Pakin, I<scott+pkfh@pakin.org> + + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2006, Scott Pakin + +This file may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.3c of this license +or (at your option) any later version. The latest version of this +license is in L<http://www.latex-project.org/lppl.txt> and version +1.3c or later is part of all distributions of LaTeX version 2006/05/20 +or later. diff --git a/Build/source/texk/texlive/linked_scripts/purifyeps b/Build/source/texk/texlive/linked_scripts/purifyeps new file mode 100644 index 00000000000..d1916891e3c --- /dev/null +++ b/Build/source/texk/texlive/linked_scripts/purifyeps @@ -0,0 +1,511 @@ +#! /usr/bin/env perl + +################################################################ +# Convert an ordinary Encapsulated PostScript file (.eps) into # +# one that works with both LaTeX+dvips and pdfLaTeX # +# # +# By Scott Pakin <scott+peps@pakin.org> # +################################################################ + +our $VERSION = "1.0a"; +require 5.006_001; +use English; +use Getopt::Long; +use FindBin qw($Script); +use File::Basename; +use File::Temp qw(tempfile); +use File::Spec; +use Pod::Usage; +use Pod::Man; +use Cwd qw(cwd chdir); +use POSIX; +use warnings; +use strict; + +# Global variables +my $fontmap = "mpost.fmp"; # pstoedit-style font map file +my %TeX_to_PS; # Hash table representing the contents of the above +my $infile = "-"; # Input file (default: stdin) +my $outfile = "-"; # Output file (default: stdout) +my $tempbase; # Base name of temporary files + +######################################################################## + +# At the end of the program's execution, delete all of our temporary files. +END { + if (defined $tempbase) { + foreach my $tempfile ($tempbase, <$tempbase.*>) { + unlink $tempfile; + } + } +} + + +# Extract the first word from the given array. A word is either a +# single token or a quoted set of space-separated tokens. Return the +# first word followed by the remaining tokens. +sub extractName (@) +{ + my @tokens = @_; + my $firstWord; + + # Ensure we have a token to extract. + return (undef, @tokens) if $#tokens==-1; + + # Extract the first word from the token list. + $firstWord = shift @tokens; + if (substr ($firstWord, 0, 1) eq '"') { + while (substr ($firstWord, length($firstWord)-1, 1) ne '"') { + return (undef, @tokens) if $#tokens==-1; + $firstWord .= " " . shift @tokens; + } + $firstWord = substr ($firstWord, 1, length($firstWord)-2); + } + + # Return the word plus the remaining tokens. + return ($firstWord, @tokens); +} + + +# Execute a shell command, and die if it fails. +sub executeCommand ($) +{ + my $command = $_[0]; + if (system "$command 1>&2") { + die "${Script}: The following command failed with exit code @{[int($?/256)]}:\n $command\n"; + } +} + + +# Generate -- and optionally clean up -- a man page. +sub createManPage ($$$) +{ + my $manfile = $_[0]; # Name of file to produce + my $wantPS = $_[1]; # 1=produce PostScript, 0=produce troff + my $section = $_[2]; # Manual section that purifyeps belongs to + + # Produce a (*roff) man page. + my $parser = Pod::Man->new (center => "", + release => "v$VERSION", + section => $section); + $parser->parse_from_file ($PROGRAM_NAME, $manfile); + + # Touch up the man page, and use groff to write + # the result back to disk as a PostScript file. + return unless $wantPS; + open (MANFILE, "<$manfile") or die "${Script}: $! ($manfile)\n"; + my @manlines = <MANFILE>; + close MANFILE; + open (MANFILE, "|groff -man > $manfile") or die "${Script}: $! ($manfile)\n"; + foreach (@manlines) { + s/LaTeX/L\\h'-0.36m'\\v'-0.15'\\s-2A\\s+2\\v'0.15'\\h'-0.15m'TeX/g; + s/TeX/T\\h'-0.1667m'\\v'0.20'E\\v'-0.20'\\h'-0.125m'X/g; + s/\\\*\(--/--/g; + print MANFILE $_; + } + close MANFILE; +} + +######################################################################## + +# Initialize our base temporary filename. +(undef, $tempbase) = tempfile ($Script . "-XXXXXXXX", DIR => File::Spec->tmpdir()); + +# Process the command line. +my ($wanthelp, $wantman, $wantps, $wantversion); +my $versionmsg = "purifyeps version $VERSION + +Copyright (C) 2009 Scott Pakin + +This program may be distributed and/or modified under the conditions +of the LaTeX Project Public License, either version 1.3c of this +license or (at your option) any later version. + +The latest version of this license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3c or later is part of all distributions of LaTeX +version 2006/05/20 or later. +"; +my $man_section = 1; # Section number of man page +GetOptions ("fontmap=s" => \$fontmap, + "make-man:s" => \$wantman, + "make-ps-man:s" => \$wantps, + "section=s" => \$man_section, + "V|version" => \$wantversion, + "help" => \$wanthelp) || pod2usage(2); +do {print $versionmsg; exit 1} if $wantversion; +pod2usage(1) if $wanthelp; +if (defined $wantman) { + # Create a troff manual page. + my $filename = ($wantman eq "" ? + basename ($PROGRAM_NAME, ".pl") . ".$man_section" : + $wantman); + createManPage ($filename, 0, $man_section); + print STDERR "Wrote $filename\n"; + exit 0; +} +if (defined $wantps) { + # Create a PostScript manual page. + my $filename = ($wantps eq "" ? + basename ($PROGRAM_NAME, ".pl") . ".ps" : + $wantps); + createManPage ($filename, 1, $man_section); + print STDERR "Wrote $filename\n"; + exit 0; +} +$infile = shift @ARGV if $#ARGV!=-1; +$outfile = shift @ARGV if $#ARGV!=-1; +pod2usage(2) if $#ARGV!=-1; # Too many arguments. + +# Read the font map file into a hash table. +open (FONTMAP, "<$fontmap") || die "${Script}: $! ($fontmap)\n"; +FONTMAP_LINE: + while (<FONTMAP>) { + # Clean up the line. + chomp; + s/\%.*//; + my $origLine = $_; + next if /^\s*$/; + my @tokens = split " "; + + # Extract the PostScript name, which may be quoted and contain spaces. + my $PSname; + ($PSname, @tokens) = extractName @tokens; + if (!defined $PSname) { + warn "${fontmap}:$NR: warning: incorrect format -- ignoring line\n"; + next FONTMAP_LINE; + } + + # Extract the TeX name, which may also be quoted and contain spaces. + my $TeXname; + ($TeXname, @tokens) = extractName @tokens; + if (!defined $TeXname) { + warn "${fontmap}:$NR: warning: incorrect format -- ignoring line\n"; + next FONTMAP_LINE; + } + + # That should be the end of the line. + if ($#tokens != -1) { + warn "${fontmap}:$NR: warning: incorrect format -- ignoring line\n"; + next FONTMAP_LINE; + } + + # Store the mapping in a hash table. + # HEURISTIC: If the mapping is not unique, map the TeX + # name to the *shortest* PostScript name. + if (!defined $TeX_to_PS{$TeXname} || + length $PSname < length $TeX_to_PS{$TeXname}) { + $TeX_to_PS{$TeXname} = $PSname; + } + } +close FONTMAP; + +# Utilize pstoedit to convert from EPS to MetaPost. +my $mpfile = $tempbase . ".mp"; +executeCommand "pstoedit -ssp -f mpost -fontmap \"$fontmap\" \"$infile\" \"$mpfile\""; + +# Utilize mpost to convert from MetaPost to MPS (stylized EPS). +my $old_cwd = cwd(); +chdir (File::Spec->tmpdir()); # mpost always writes to the current directory. +executeCommand "echo X | mpost $mpfile"; +chdir $old_cwd; + +# Post-process the MPS file into the output file. +my $mpsfile = $tempbase . ".1"; +my @purified_eps; +my $outfile_clean = ($outfile eq "-") ? "stdout" : $outfile; +open (MPSFILE, "<$mpsfile") || die "${Script}: $! ($mpsfile)\n"; +while (<MPSFILE>) { + # Process blank lines. + chomp; + my @tokens = split " "; + if ($#tokens == -1) { + push @purified_eps, "$_\n"; + next; + } + + # Convert the list of document fonts. + if ($tokens[0] eq "%%DocumentFonts:") { + my $outputLine = shift @tokens; + foreach my $TeXname (@tokens) { + my $PSname = $TeX_to_PS{$TeXname}; + if (!defined $PSname) { + warn "${outfile_clean}:$NR: warning: TeX font \"$TeXname\" does not appear in $fontmap\n"; + $outputLine .= " $TeXname"; + } + else { + $outputLine .= " $PSname"; + } + } + push @purified_eps, "$outputLine\n"; + next; + } + + # Convert the font name definitions. + if ($#tokens == 2 && + $tokens[0] eq $tokens[1] && + $tokens[2] eq "def") { + push @purified_eps, sprintf " %s /%s def\n", $tokens[0], $TeX_to_PS{substr($tokens[1],1)}; + next; + } + + # By default, output the line as is. + push @purified_eps, "$_\n"; +} +close MPSFILE; + +# Write the output file. +open (OUTFILE, ">$outfile") || die "${Script}: $! ($outfile_clean)\n"; +print OUTFILE @purified_eps; +close OUTFILE; + +# Finish up. +print STDERR "\nFile seems to have been purified successfully.\n"; +exit 0; + +########################################################################### + +__END__ + + +=head1 NAME + +purifyeps - make an Encapsulated PostScript file work with both dvips and +pdflatex + + +=head1 SYNOPSIS + +purifyeps +B<--help> + +purifyeps +B<--version> + +purifyeps +[B<--fontmap>=I<.fmp file>] +[I<.eps input file> [I<.eps output file>]] + +purifyeps +B<--make-man> [=I<filename>] [B<--section>=I<section>] + +purifyeps +B<--make-ps-man> [=I<filename>] [B<--section>=I<section>] + + +=head1 DESCRIPTION + +While B<pdflatex> has a number of nice features, its primary +shortcoming relative to standard B<latex>+B<dvips> is that it is +unable to read ordinary Encapsulated PostScript (EPS) files, the most +common graphics format in the LaTeX world. B<pdflatex> can read only +the following types of graphics files: + +=over 4 + +=item PDF + +Most people who use B<pdflatex> convert their documents to PDF using a +utility such as B<epstopdf>. This works well and preserves the vector +nature of the original EPS. Unfortunately, B<dvips> does not read +PDF, so two versions of the graphic must be maintained if the document +is to be processed with both B<latex>+B<dvips> and B<pdflatex>. + +=item PNG + +PNG is a bitmap format and therefore scales poorly. Also, B<dvips> +does not read PNG, so two versions of the graphic must be maintained +if the document is to be processed with both B<latex>+B<dvips> and +B<pdflatex>. + +=item JPEG + +JPEG is a bitmap format and therefore scales poorly. Also, B<dvips> +does not read JPEG, so two versions of the graphic must be maintained +if the document is to be processed with both B<latex>+B<dvips> and +B<pdflatex>. + +=item MPS + +This is probably the least-used B<pdflatex>-compatible graphics +format. MPS is actually a stylized version of EPS that MetaPost +outputs. Like PDF, MPS is a vector format and remains as such when +imported into a B<pdflatex> document. Also like PDF, B<dvips> does +not read MPS, so two versions of the graphic must be maintained if the +document is to be processed with both B<latex>+B<dvips> and +B<pdflatex>. + +=back + +The insight behind B<purifyeps> is that there are only a few, small +differences between MPS and EPS and that a file can be converted into +a format that matches both the MPS and EPS specifications +simultaneously. B<purifyeps> inputs an EPS file, uses B<pstoedit>'s +C<mpost> filter to convert the file to MetaPost (F<.mp>), runs +B<mpost> on the file to convert it to MPS, and finally performs some +touchups on the result to convert the file back to EPS, while +preserving its ability to be parsed by B<pdflatex>. + + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Display L<"Usage"> and L<"Options"> from the B<purifyeps> documentation. + +=item B<-V>, B<--version> + +Display the B<purifyeps> version number, copyright, and license. + +=item B<--fontmap>=I<.fmp file> + +Specify the name of a file that tells B<purifyeps> how to map from TeX +font names to PostScript font names. [Default: F<mpost.fmp>] + +=item B<--make-man> [=I<filename>]] [B<--section>=I<section>] + +Automatically create a Unix man page for B<purifyeps>. I<section> +specifies the section [default: C<1> (User Commands)]. I<filename> +defaults to F<purifyeps.1> or an analogous filename if I<section> is +specified. + +=item B<--make-ps-man> [=I<filename>]] [B<--section>=I<section>] + +Automatically create a PostScript version of the B<purifyeps> +documentation. The documentation is formatted like a Unix man page. +I<section> specifies the section [default: C<1> (User Commands)]. +I<filename> defaults to F<purifyeps.ps>. + +=back + +In normal operation (i.e., when not run with C<--help>, C<--make-man>, +or C<--make-ps-man>), B<purifyeps> takes the name of an input file and +output file. The same filename can safely be used for both files. If +the output filename is omitted, output will go to the standard output +device. If the input filename is omitted, B<purifyeps> will read from +the standard input device. + + +=head1 EXAMPLES + +Create a PostScript version of the B<purifyeps> documentation, but +call it F<happydoc.ps> instead of the default, F<purifyeps.ps>: + + purifyeps --make-ps-man=happydoc.ps + +Create a Unix man page for B<purifyeps> (in the usual roff format), +but indicate that it belongs in section C<LOCAL> instead of the +default of section C<1>: + + purifyeps --make-man --section=LOCAL + +Purify F<sample.eps> (F<mpost.fmp> is in the current directory): + + purifyeps sample.eps sample.eps + +Purify F<sample.eps> (F<mpost.fmp> is in a different location): + + purifyeps --fontmap=/usr/share/pstoedit/mpost.fmp sample.eps sample.eps + +Rename the purified version while purifying: + + purifyeps sample.eps sample-pure.eps + +Do the same, but in a Unix pipeline: + + cat sample.eps | purifyeps > sample-pure.eps + +When you run B<purifyeps>, you should see the output from both +B<pstoedit> and B<mpost>, followed by a success message from +B<purifyeps>: + + % cat sample.eps | purifyeps > sample-pure.eps + pstoedit: version 3.30 / DLL interface 107 (build Mar 14 2002) : + Copyright (C) 1993 - 2001 Wolfgang Glunz + Interpreter finished. Return status 0 + This is MetaPost, Version 0.641 (Web2C 7.3.1) + (/tmp/purifyeps-jdeGPkh9.mp [1] ) + 1 output file written: purifyeps-jdeGPkh9.1 + Transcript written on purifyeps-jdeGPkh9.log. + + File seems to have been purified successfully. + + +=head1 FILES + +=over 4 + +=item F<mpost.fmp> + +File containing mappings between TeX and PostScript font names. See +L<"NOTES"> for a description of this file's contents. + +=back + + +=head1 BUGS + +Error reporting could definitely stand to be improved. Error messages +produced by B<pstoedit> and B<mpost> are sometimes silently ignored. +Also, errors sometimes cause B<purifyeps> to leave temporary files +(F<purifyeps->I<#####>) lying around. + +B<purifyeps> is subject to all of the limitations that affect +B<pstoedit> and especially the C<mpost> backend to B<pstoedit>. As a +result, B<purifyeps> ignores certain PostScript constructs, such as +nonuniformly scaled text. + + +=head1 NOTES + +B<purifyeps> needs a file that tells it how to map from TeX font names +to PostScript font names. This file must contain two, space-separated +columns. The first lists a PostScript font name, and the second lists +the TeX equivalent. Blank lines and lines that start with C<%> are +ignored. The following is a sample F<.fmp> file: + + % This is a sample font map for purifyeps. + Times-Bold ptmb + Times-Italic ptmri + Times-Roman ptmr + Helvetica phvr + Helvetica-Bold phvb + Helvetica-Oblique phvro + Courier pcrr + Courier-Bold pcrb + Courier-Oblique pcrro + +Note that this is exactly the same format that B<pstoedit> uses. By +default, B<purifyeps> looks in the current directory for a font map +called F<mpost.fmp>. The C<--fontmap> command-line option tells +B<purifyeps> to use a different font map, which will typically be the +F<mpost.fmp> file that comes with B<pstoedit>. + +Once you create purified EPS files with B<purifyeps>, you need to +instruct B<pdflatex> to use them. The pdfLaTeX configuration of the +C<graphics> and C<graphicx> packages (F<pdftex.def>) normally ignores +F<.eps> files. Putting the following LaTeX code in your document's +preamble tells B<pdflatex> that all F<.eps> files are in MPS format: + + % Tell pdfLaTeX that all .eps files were produced by MetaPost. + \usepackage{graphicx} % or graphics + \usepackage{ifpdf} + \ifpdf + \DeclareGraphicsRule{.eps}{mps}{*}{} + \makeatletter + \g@addto@macro\Gin@extensions{,.eps} + \makeatother + \fi + +=head1 SEE ALSO + +dvips(1), epstopdf(1), latex(1), mpost(1), pdflatex(1), pstoedit(1) + + +=head1 AUTHOR + +Scott Pakin, I<scott+peps@pakin.org> diff --git a/Master/texmf-dist/doc/support/pkfix-helper/README b/Master/texmf-dist/doc/support/pkfix-helper/README new file mode 100644 index 00000000000..aeb7888089d --- /dev/null +++ b/Master/texmf-dist/doc/support/pkfix-helper/README @@ -0,0 +1,65 @@ + +---------------------------------------+ + | PKFIX-HELPER | + | | + | Help pkfix process PostScript files | + | produced by ancient versions of dvips | + | | + | Scott Pakin, scott+pkfh@pakin.org | + +---------------------------------------+ + + +Description +=========== + +pkfix is a useful utility for replacing resolution-dependent bitmapped +fonts in a dvips-produced PostScript file with the corresponding +resolution-independent vector fonts. Unfortunately, pkfix needs to +parse certain PostScript comments that appear only in files produced +by dvips versions later than 5.58 (ca. 1996); it fails to work on +PostScript files produced by older versions of dvips. + +pkfix-helper is a program that attempts to insert newer-dvips comments +into an older-dvips PostScript file, thereby making the file suitable +for processing by pkfix. pkfix-helper can sometimes process documents +fully autonomously but does require the user to verify and, if needed, +correct its decisions. + + +Installation +============ + +pkfix-helper has essentially the same requirements as pkfix. To run +it, you will need: + + * Perl (http://www.cpan.org/) + * Ghostscript (http://www.cs.wisc.edu/~ghost/) + * tftopl (comes with most TeX distributions) + +Simply copy pkfix-helper to somewhere in your search path (e.g., +/usr/local/bin/) and you should be good to go. You may also want to +install and/or print the documentation (pkfix-helper.pdf and +encoding-samples.pdf) and install the Unix man page (pkfix-helper.1). +At a minimum, you should *read* the documentation; pkfix-helper usage +is neither completely automatic nor completely intuitive. + +As the pkfix README states, "I have only tested with a few test files +on a Linux machine with teTeX." The same is true for pkfix-helper. +In particular, I don't know what needs to be done to get pkfix-helper +to work under Windows. If you're a Windows user, you're on your own. +Sorry. Maybe try Cygwin (http://www.cygwin.com/)? + + +Copyright and license +===================== + +Copyright (C) 2006, Scott Pakin + +This file may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.3c of this license +or (at your option) any later version. The latest version of this +license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3c or later is part of all distributions of LaTeX +version 2006/05/20 or later. diff --git a/Master/texmf-dist/doc/support/pkfix-helper/encoding-samples.pdf b/Master/texmf-dist/doc/support/pkfix-helper/encoding-samples.pdf Binary files differnew file mode 100644 index 00000000000..c3362003e11 --- /dev/null +++ b/Master/texmf-dist/doc/support/pkfix-helper/encoding-samples.pdf diff --git a/Master/texmf-dist/scripts/pkfix-helper/pkfix-helper b/Master/texmf-dist/scripts/pkfix-helper/pkfix-helper new file mode 100755 index 00000000000..f1a2f1cb694 --- /dev/null +++ b/Master/texmf-dist/scripts/pkfix-helper/pkfix-helper @@ -0,0 +1,1219 @@ +#! /usr/bin/env perl + +############################################# +# Help pkfix decipher fonts in a PostScript # +# file produced by an ancient dvips # +# # +# By Scott Pakin <scott+pkfh@pakin.org> # +############################################# + +use File::Spec; +use File::Temp qw (tempfile); +use File::Basename; +use Getopt::Long; +use Pod::Usage; +use warnings; +use strict; + +# Define some global variables. +my $progname = basename $0; # Name of this program +our $VERSION = "1.0"; # Version number of this program +my %name2chars; # Map from a font name to a character list +my $GS = $ENV{"GS"} || "gs"; # Name of the Ghostscript interpreter +my $TFTOPL = $ENV{"TFTOPL"} || "tftopl"; # Name of the TFM to PL converter +my $dpi = 300; # Number of dots per inch used to generate bitmapped characters +my @tfmlist; # List of TFM files to use +my %fontmatch; # Map from a font name to its best match +my $xinc = 36; # Width of font name in PostScript points +my $yinc = 24; # Height of font in PostScript points +my $init_yinc = 36; # Space after title +my %tfmfontwidth; # Map from font name to character number to character width +my %tfm2size; # Map from font name to design size +my ($dvips_xscale, $dvips_yscale); # Scaling factors from Dvips's PostScript CTM +my $discard_output = $^O eq "MSWin32" ? "> NUL:" : "> /dev/null 2>&1"; # Command suffix to discard all output + +# Define the global variables that the user can modify from the command line. +my $wanthelp = 0; # 1=user wants to see the program's documentation +my $wantversion = 0; # 1=user wants to see the program's version number +my $verbose = 1; # 0=quiet; 1=verbose output; 2=more verbose output +my @forced_fonts; # Font mappings the user asserts are correct +my @exclude_res; # Regexps for fonts to exclude +my @extra_tfms; # Extra TFM files to use +my $sample_file_ps; # Name of a PostScript file of font samples to write +my $sample_file_tex; # Name of a TeX file of font samples to write +my $single_font_use = 0; # 1=one use per font; 0=allow repetitions + +########################################################################### + +# Given the base name of a .tfm file, process the file and return the +# font's design size and a mapping from character number to character +# width. +sub tfm2widths ($) +{ + my $tfmname = $_[0]; # Name of the TFM file + my $designsize; # Design size of the font + my %num2width; # Resultant mapping + my $plname; # Name of PL file; some tftopl programs can't write to stdout. + my $plfile; # Filehandle corresponding to $plname + + ($plfile, $plname) = tempfile (DIR => File::Spec->tmpdir(), SUFFIX => ".pl"); + close $plfile; + if (!system "$TFTOPL $tfmname $plname $discard_output") { + print STDERR " Processing $tfmname ... " if $verbose >= 2; + open (PLFILE, "<$plname") || die "${progname}: Unable to open $tfmname ($!)\n"; + my $charnum; # Current character number + while (my $oneline = <PLFILE>) { + # Store the current character width. + $oneline =~ /\(CHARWD R (\S+)\)/ && do { + $num2width{$charnum} = $1 * $designsize; + next; + }; + + # Store the current character number. + $oneline =~ /\(CHARACTER (\S) (\S+)/ && do { + if ($1 eq "O") { + # Octal character number + $charnum = oct $2; + } + elsif ($1 eq "C") { + # ASCII character number + $charnum = ord $2; + } + else { + die "${progname}: Unknown TFM character type \"$1\"\n"; + } + next; + }; + + # Store the font design size. + $oneline =~ /\(DESIGNSIZE R (\S+)\)/ && do { + $designsize = $1 + 0.0; + next; + }; + } + close PLFILE; + print STDERR "done.\n" if $verbose >= 2; + } + else { + print STDERR " Discarding $tfmname (not found).\n" if $verbose >= 3; + } + unlink $plname; + return [$designsize, %num2width]; +} + + +# Given two character maps, one for a document font and one for a TFM +# file, return the optimal scale factor for the TFM file to best match +# the document font. +sub optimal_scale ($$) +{ + my %docmap = %{$_[0]}; # Map for a document font + my %tfmmap = %{$_[1]}; # Map for a TFM font + my $doc_dot_tfm = 0.0; # Sum of $docmap{$c}*$tfmmap{$c} for all $c + my $tfm_dot_tfm = 0.0; # Sum of $tfmmap{$c}**2 for all $c + + while (my ($char, $docwidth) = each %docmap) { + my $tfmwidth = $tfmmap{$char}; + return undef if !defined $tfmwidth; # Match is impossible. + $doc_dot_tfm += $docwidth * $tfmwidth; + $tfm_dot_tfm += $tfmwidth**2; + } + return $doc_dot_tfm / $tfm_dot_tfm; +} + + +# Compare two character maps and return their mismatch (smaller is +# better). The third, optional, argument is a scale factor for the +# TFM file. +sub compare_maps ($$;$) +{ + my %docmap = %{$_[0]}; # Map for a document font + my %tfmmap = %{$_[1]}; # Map for a TFM font + my $scale = $_[2] || 1.0; # Scale for each TFM width + my $sqdiff = 0; # Sum of squares of differences + + while (my ($char, $docwidth) = each %docmap) { + my $tfmwidth = $tfmmap{$char}; + return 10**9 if !defined $tfmwidth; # Match is impossible. + $sqdiff += ($docwidth - $tfmwidth*$scale) ** 2; + } + return $sqdiff; +} + + +# Given a Type 3 font definition, surround it with DVIPSBitmapFont comments. +sub write_comments ($$) +{ + my ($fontname, $fontdef) = @_; + my $tfm = $fontmatch{$fontname}->{"tfm"}; + my $scale = $fontmatch{$fontname}->{"scale"}; + my $origsize = $tfm2size{$tfm}; + my $begincomment = sprintf '%%DVIPSBitmapFont: %s %s %.5g %d', + $fontname, $tfm, $origsize*$scale, 1+$#{$name2chars{$fontname}}; + my $endcomment = '%EndDVIPSBitmapFont'; + return "\n" . $begincomment . "\n" . $fontdef . "\n" . $endcomment . "\n"; +} + + +# Escape an array of characters for PostScript's benefit. +sub psify (@) +{ + my @ps_chars; + foreach my $onechar (@_) { + my $charnum = ord $onechar; + if ($onechar =~ /[\\()]/) { + push @ps_chars, "\\" . $onechar; + } + elsif ($charnum >= 32 && $charnum <= 126) { + push @ps_chars, $onechar; + } + else { + push @ps_chars, sprintf "\\%03o", $charnum; + } + } + return @ps_chars; +} + + +# Escape an array of characters for TeX's benefit. +sub texify (@) +{ + my @texchars; + foreach my $onechar (@_) { + if ($onechar =~ m|[\000-\037\\{}\177-\377]|) { + push @texchars, sprintf '\char"%02X{}', ord $onechar; + } + else { + push @texchars, $onechar; + } + } + return join "", @texchars; +} + + +# Parse a font specification into a hash of information. +sub parse_font_spec ($) +{ + my $spec = $_[0]; + my $parse_error = "${progname}: Unable to parse font specification \"$spec\"\n"; + + if ($spec =~ /^\s*([-\w]+)(.*)$/o) { + my $tfm = $1; # Name of tfm file (e.g., "cmr10") + my $scale_info = $2; # Concatenation of scale type and scale factor + my $scale_type; # "X"=multiply, "@"=assign + my $scale_amount; # How much to scale the TFM file, "*"=automatic + + if ($scale_info =~ /^\s*$/o) { + # Empty + $scale_type = 'X'; + $scale_amount = 1.0; + } + elsif ($scale_info =~ /^\s*\@\s*([\d.]+)\s*X\s*$/io) { + # "@ <number> X" + $scale_type = 'X'; + $scale_amount = $1 + 0.0; + } + elsif ($scale_info =~ /^\s*\@\s*([\d.]+)\s*(pt|bp)\s*$/io) { + # "@ <number> pt" or "@ <number> bp" + $scale_type = '@'; + $scale_amount = $1; + $scale_amount *= 72.0/72.27 if $2 eq "bp"; # Convert to TeX points + } + elsif ($scale_info =~ /^\s*\@\s*\*\s*$/o) { + # "@ *" + $scale_type = 'X'; + $scale_amount = "*" + } + else { + die $parse_error; + } + return {"tfm" => $tfm, + "scale_type" => $scale_type, + "scale" => $scale_amount}; + } + die $parse_error; +} + + +# Return all of the unique items in a given list. +sub unique_items (@) +{ + my %item_hash; + foreach my $item (@_) { + $item_hash{$item} = 1; + } + return keys %item_hash; +} + +########################################################################### + +# Parse the command line. +Getopt::Long::Configure ("bundling"); +GetOptions ("h|help" => \$wanthelp, + "v|verbose+" => \$verbose, + "V|version" => \$wantversion, + "q|quiet" => sub {$verbose=0}, + "f|force=s" => \@forced_fonts, + "i|include=s" => \@extra_tfms, + "x|exclude=s" => \@exclude_res, + "t|tex=s" => \$sample_file_tex, + "p|ps=s" => \$sample_file_ps, + "1|no-repeats" => \$single_font_use) || pod2usage(2); +if ($wantversion) { + print "pkfix-helper $VERSION\n"; + exit 0; +} +if ($wanthelp) { + pod2usage (-verbose => $verbose, + -exitval => "NOEXIT"); + print "Report bugs to scott+pkfh\@pakin.org.\n" if $verbose == 1; + exit 0; +} +my $infilename = $#ARGV>=0 ? $ARGV[0] : "-"; +my $outfilename = $#ARGV>=1 ? $ARGV[1] : "-"; + +# Convert any user-specified TFMs to the appropriate internal format. +foreach my $tfm (@extra_tfms) { + my $font_spec = parse_font_spec $tfm; + push @tfmlist, $font_spec; +} + +# Parse the list of forced font mappings. +foreach my $mapstr (@forced_fonts) { + $mapstr =~ /^(\w+)\s*=\s*(.*)$/ || die "${progname}: Unable to parse font specification \"$mapstr\"\n"; + $fontmatch{$1} = parse_font_spec $2; +} + +# Construct a list of (possibly nonexistent) TFM files to try. These +# should be in order of decreasing likelihood. Each entry in the list +# is of the form {full name, scale factor}. +@exclude_res = ('^\s*$') if $#exclude_res == -1; +foreach my $size_scale ([10, 1.0], + [12, 1.0], + [10, 1.1], + [17, 1.0], + [ 9, 1.0], + [ 8, 1.0], + [ 7, 1.0], + [ 6, 1.0], + [ 5, 1.0], + [10, 1.2], + # The following are common cmbx12 section headings. + [12, 14.40/12], + [12, 17.28/12], + [12, 20.74/12], + [12, 24.88/12]) { + my ($pointsize, $scale) = @$size_scale; + FONTLOOP: + foreach my $basefont (qw (cmr cmb cmtt cmbsy cmbx cmbxsl cmbxti + cmcsc cmex cmitt cmmi cmmib cmsl cmsltt + cmss cmssbx cmssi cmsy cmti lasy lasyb + msam msbm cmssdc cmtcsc)) { + my $friendly_name = sprintf "%s%d \@ %.5gX", $basefont, $pointsize, $scale; + foreach my $regexp (@exclude_res) { + next FONTLOOP if $friendly_name =~ $regexp; + } + push @tfmlist, {"tfm" => $basefont . $pointsize, + "scale_type" => "X", + "scale" => $scale}; + } +} + +# Read the entire input file. +$| = 1; +if ($verbose) { + printf STDERR "Reading %s ... ", $infilename eq "-" ? "standard input" : $infilename; +} +my $entirefile; +{ + local $/ = undef; + open (INFILE, "<$infilename") || die "open(\"$infilename\"): $!\n"; + binmode INFILE; + $entirefile = <INFILE>; + close INFILE; +} +print STDERR "done.\n" if $verbose; + +# Construct a mapping from each document font name to a list of valid +# characters in that font. +while ($entirefile =~ m|/(\S+)\s+\d+\s+\d+\s+df(.*?>[^<>]*?[DI])\s+E|gs) { + my $fontname = $1; # Name of current font (e.g., "Fa") + my $fontbody = $2; # List of character definitions as hexadecimal strings + my $charnum = 0; # Current character number + my @charlist = (); # List of valid characters in PostScript-friendly format + + while ($fontbody =~ /<[0-9A-F\s]+>(.*?[DI])/gs) { + # Put the current character number in $charnum then append the + # corresponding character to @charlist. + my @chardef = split " ", $1; + if ($chardef[$#chardef] eq "I") { + $charnum++; + } + else { + $charnum = $chardef[$#chardef-1]; + } + push @charlist, chr $charnum; + } + $name2chars{$fontname} = \@charlist; +} +my @sortedfontnames = sort {$#{$name2chars{$b}} <=> $#{$name2chars{$a}} + || $a cmp $b} keys %name2chars; +if ($verbose) { + printf STDERR "Number of Type 3 fonts encountered: %d\n", 1+$#sortedfontnames; + if ($verbose >= 2) { + foreach my $fontname (@sortedfontnames) { + printf STDERR " %s -- %3d character(s)\n", $fontname, 1+$#{$name2chars{$fontname}}; + } + } +} +die "${progname}: No Type 3 fonts were encountered in the input file\n" if $#sortedfontnames==-1; + +# Determine the number of dots per inch used to generate the bitmaps. +if ($entirefile =~ /dpi=(\d+)/i + || $entirefile =~ /Resolution (\d+)dpi/i) { + $dpi = $1 + 0; + printf STDERR "Bitmapped fonts are typeset at $dpi DPI.\n" if $verbose; +} +else { + warn "${progname}: Could not determine the target printer resolution; assuming $dpi DPI\n"; +} + +# Insert some helper code after the first ProcSet. +my $output_width_ps = $entirefile; # PostScript code to output character widths +my $showfontnamecode = <<"SHOWFONTNAME"; +\%\%BeginProcSet: $progname.pro +TeXDict begin + +% char0 char1 PRINT-WIDTH - +% +% Output the name of the current font (font-name-string), its character +% number (char0), and the character's width in PostScript points. + +/print-width { + pop + (FONT: ) print font-name-string print + ( CHAR: ) print 8 string cvs print + ( XPOS: ) print currentpoint pop 80 string cvs print + (\\n) print +} bind def + +% font-name sample-string PRINT-CHAR-WIDTHS - +% +% Store the name of font-name in the string font-name-string. Then, select +% font-name and, for each character of test-string, call print-width +% to output its width. + +/print-char-widths { + /sample-string exch def + /font-name exch def + font-name 8 string cvs /font-name-string exch def + font-name cvx exec {print-width} sample-string kshow +} bind def + +end +\%\%EndProcSet +SHOWFONTNAME + ;#' +if ($output_width_ps !~ s/\%\%EndProcSet/$&\n$showfontnamecode/s) { + print STDERR 'No %%EndProcSet comment was found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject prologue code\n" if $output_width_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop/\n$showfontnamecode\n$&/s; +} + +# Define some code to display the width of every valid character in +# every bitmapped font. Fonts are displayed in decreasing order of +# the number of characters used. +my $displaycode = "\%\%Page: 1 1\nTeXDict begin\n1 0 bop\n"; +foreach my $fontnum (0 .. $#sortedfontnames) { + # Duplicate the last character of the sample string so kshow can + # process the final character delta. + my $fontname = $sortedfontnames[$fontnum]; + my @charlist = psify @{$name2chars{$fontname}}; + my $samplestring = join("", @charlist) . $charlist[$#charlist]; + + # Typeset the string starting at horizontal offset 0. + $displaycode .= sprintf "0 0 moveto\n"; + $displaycode .= "/$fontname ($samplestring) print-char-widths\n"; +} + +# Dvips scales the page. Determine the scaling it uses. +$displaycode .= <<'ENDDISPLAYCODE'; +(CURRENTMATRIX: ) print +matrix currentmatrix == +(\n) print +eop +end +ENDDISPLAYCODE + ; + +# Replace the bulk of the PostScript file with the display code. +if ($output_width_ps !~ s/\%\%Page:.*(\%\%Trailer)/$displaycode$1/s) { + print STDERR 'No %%Page and/or %%Trailer comments were found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject display code\n" if $output_width_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop.*eop\s+end/\n$displaycode\n/s; +} + +# Output the modified PostScript code to a temporary file, run +# Ghostscript on the temporary file, and process Ghostscript's output. +my ($psfile, $psfilename) = tempfile ("pkfix-helper-XXXXXX", + DIR => File::Spec->tmpdir(), + SUFFIX => ".ps"); +binmode $psfile; +print $psfile $output_width_ps; +close $psfile; +undef $output_width_ps; +my %fontwidth; # Map from font name to character number to character width +my @previnfo = ("", 0.0); # Previous font name and final character position +my $gscmd = "$GS -q -dNOPAUSE -dBATCH -dNODISPLAY $psfilename"; +print STDERR "Finding character widths ... " if $verbose >= 1; +print STDERR "\n Invoking: $gscmd\n" if $verbose >= 2; +print STDERR "done.\n" if $verbose >= 1; +open (GSCMD, "$gscmd|") || die "${progname}: failed to fork ($!)\n"; +while (my $oneline = <GSCMD>) { + if ($oneline =~ /FONT: (\S+)\s*CHAR: (\d+)\s*XPOS: (\S+)/o) { + my ($fontname, $charnum, $xpos) = ($1, $2, $3); + my $width = $xpos + 0.0; + $width -= $previnfo[1] if $fontname eq $previnfo[0]; + $fontwidth{$fontname}->{$charnum} = $width * 72.27 / $dpi; + @previnfo = ($fontname, $xpos); + } + elsif ($oneline =~ /CURRENTMATRIX: \[\s*([-\d.]+)\s+[-\d.]+\s+[-\d.]+\s+([-\d.]+)\s+[-\d.]+\s+[-\d.]+\s*\]/o) { + $dvips_xscale = $1 * 1.0; + $dvips_yscale = $2 * -1.0; + } +} +close GSCMD || die "${progname}: failed to run $GS ($!)\n"; +unlink $psfilename; +die "${progname}: No character-width information was found\n" if !%fontwidth; + +# Read each TFM file and store its design size and character widths. +print STDERR "Reading TFM files ... " if $verbose; +print STDERR "\n" if $verbose >= 2; +foreach my $tfm (sort {$a cmp $b} + unique_items map {$_->{"tfm"}} (@tfmlist, values %fontmatch)) { + my ($designsize, %num2widths) = @{tfm2widths $tfm}; + if (%num2widths) { + $tfmfontwidth{$tfm} = \%num2widths; + $tfm2size{$tfm} = $designsize * 1.0; + } +} + +# Remove nonexistent fonts from @tfmlist and replace all absolute +# ("@") scaling with relative ("X") scaling. +my @goodtfmlist; +foreach my $tfminfo (@tfmlist) { + my $tfm = $tfminfo->{"tfm"}; + next if !defined ($tfmfontwidth{$tfm}); + $tfminfo->{"designsize"} = $tfm2size{$tfm}; + if ($tfminfo->{"scale_type"} eq "@") { + # Convert absolute to relative sizes. + $tfminfo->{"scale_type"} = "X"; + $tfminfo->{"scale"} /= $tfminfo->{"designsize"}; + } + push @goodtfmlist, $tfminfo; +} +@tfmlist = @goodtfmlist; +undef @goodtfmlist; + +# Do the same for all user-specified font mappings. +while (my ($fontname, $tfminfo) = each %fontmatch) { + my $tfm = $tfminfo->{"tfm"}; + if (!defined ($tfmfontwidth{$tfm})) { + print STDERR "failed.\n" if $verbose; + die "${progname}: Unable to process user-specified TFM file \"$tfm\"\n"; + } + $tfminfo->{"designsize"} = $tfm2size{$tfm}; + if ($tfminfo->{"scale_type"} eq "@") { + # Convert absolute to relative sizes. + $tfminfo->{"scale_type"} = "X"; + $tfminfo->{"scale"} /= $tfminfo->{"designsize"}; + } +} + +# Report the number of fonts in our repertoire. +my $numtfms = keys %tfm2size; +my $numfonts = 1 + $#tfmlist; +print STDERR "done ($numtfms TFMs in $numfonts scaling variations).\n" if $verbose; +die "${progname}: No TFM files were processed successfully\n" if !$numtfms; + +# Compare every document font (ordered by decreasing number of +# characters utilized) to every TFM file (in increasing order of +# obscurity). +print STDERR "Matching fonts:\n" if $verbose; +foreach my $fontname (@sortedfontnames) { + my @besttfms; # Best matching TFM file(s), sizes, and scales + my $bestmatch = 10**9; # Best matching value + + # Determine the list of eligible fonts to compare against. + my @eligible_tfms; + foreach my $tfminfo ($fontmatch{$fontname} || @tfmlist) { + if ($tfminfo->{"scale"} eq "*") { + # Replace "*" with the best scaling factor we can find. + my $newscale = optimal_scale $fontwidth{$fontname}, $tfmfontwidth{$tfminfo->{"tfm"}}; + if (defined $newscale) { + # Replace the "*" with the optimal multiplier. + my %newtfminfo = %$tfminfo; + $newtfminfo{"scale"} = $newscale; + push @eligible_tfms, \%newtfminfo; + } + else { + # Fonts are incomparable. + my $tfm = $tfminfo->{"tfm"}; + print STDERR " Not scaling $tfm; ${fontname}'s character set is not a subset of ${tfm}'s.\n" if $verbose >= 2; + } + } + else { + # The desired scaling factor is specified explicitly. + push @eligible_tfms, $tfminfo; + } + } + die "${progname}: No fonts are eligible to match $fontname\n" if !@eligible_tfms; + + # Try each TFM file in increasing order of obscurity. + print STDERR " Processing $fontname ... " if $verbose == 1; + foreach my $tfminfo (@eligible_tfms) { + my $tfm = $tfminfo->{"tfm"}; + my $scale = $tfminfo->{"scale"}; + printf STDERR " Comparing %s and %s \@ %.5gX ... ", $fontname, $tfm, $scale if $verbose >= 2; + my $match = compare_maps $fontwidth{$fontname}, $tfmfontwidth{$tfm}, $scale; + if ($bestmatch > $match) { + # We found a closer match than what we had before. + $bestmatch = $match; + @besttfms = ($tfminfo); + } + elsif ($bestmatch == $match) { + # We found an equal match to what we had before. + push @besttfms, $tfminfo; + } + printf STDERR "done (mismatch=%.5f).\n", $match if $verbose >= 2; + } + + # Select the first of the best matches. + $fontmatch{$fontname} = $besttfms[0]; + my $besttfminfo = $fontmatch{$fontname}; + my $besttfm = $besttfminfo->{"tfm"}; + my $bestscale = $besttfminfo->{"scale"}; + if ($verbose >= 2) { + if ($#besttfms == 0) { + # Single winner + printf STDERR " Best match for %s is %s \@ %.5gX with mismatch=%.5f.\n\n", + $fontname, $besttfm, $bestscale, $bestmatch; + } + else { + # Tie for first place + printf STDERR " Best match for %s is %s \@ %.5gX (tied among %s) with mismatch=%.5f.\n\n", + $fontname, $besttfm, $bestscale, + join("/", map {sprintf "%s\@%.5gX", $_->{"tfm"}, $_->{"scale"}} @besttfms), + $bestmatch; + } + } + elsif ($verbose == 1) { + printf STDERR "done (%s \@ %.5gX, mismatch=%.5f).\n", $besttfm, $bestscale, $bestmatch; + } + warn "${progname}: Best match for $fontname is rather poor\n" if $bestmatch>=1.0; + + # Optionally remove the font from @goodtfmlist. + if ($single_font_use) { + @tfmlist = grep {$_->{"tfm"} ne $besttfm + || $_->{"scale"} != $bestscale} @tfmlist; + } +} + +# Insert %DVIPSBitmapFont comments around every Type 3 font definition. +my $commented_ps = $entirefile; +my $infilename_ps = $infilename; # PostScript version of $infilename +$infilename_ps =~ s/[()\\]/\\$1/g; +$commented_ps =~ s|^\%(End)?DVIPSBitmapFont.*$||gm; # Remove existing comments (if any) +$commented_ps =~ s|/(\S+)\s+\d+\s+\d+\s+df.*?>[^<]*?[DI]\s+E|write_comments($1, $&)|gse; +if ($commented_ps !~ /\%\%EndProlog/) { + # pkfix fails silently if it doesn't see an %%EndProlog. + print STDERR "No %%EndProlog comment was found. Adding one.\n" if $verbose >= 3; + $commented_ps =~ s|TeXDict begin\s+\d+\s+\d+\s+bop|\%\%EndProlog\n$&|s; +} + +# Help pkfix handle ancient versions of dvips by artificially making +# dvips look newer. +$commented_ps =~ s|(\%\%Creator: dvips\S*) \S+|$1 5.62|; # pkfix rejects dvips <= 5.58 +if ($commented_ps =~ s|(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\@start|$1 $2 $3 $4 $5 ($infilename_ps) \@start|gx) { + # pkfix expects *six* arguments to @start, not five as in old + # versions of dvips. + $commented_ps =~ s|/\@start\s*\{|$& pop |; +} +if ($commented_ps !~ /^%DVIPSParameters:.*dpi=([\dx]+)/) { + # Tell pkfix what resolution to use. + my $dvips_params = "\%DVIPSParameters: dpi=$dpi"; + if ($commented_ps !~ s|^\%\%EndComments.*$|$&\n$dvips_params|m) { + # Comments must have been stripped. + $commented_ps =~ s|\n|\n$dvips_params\n|; + } +} + +# Write the modified PostScript code to the specified file. +open (OUTFILE, ">$outfilename") || die "${progname}: Unable to open $outfilename ($!)\n"; +print OUTFILE $commented_ps; +close OUTFILE; +undef $commented_ps; + +# If the user requested a PostScript font sample, produce that. +if (defined $sample_file_ps) { + # Insert some helper code at an appropriate place in the file. + my $sample_ps = $entirefile; + my $showfontnamecode = <<"SHOWFONTNAME"; +\%\%BeginProcSet: $progname.pro +TeXDict begin + +% font-name sample-string PRINT-FONT-SAMPLE - +% +% Store the name of font-name in the string font-name-string. Then, +% output font-name-string in Times Bold in case the user wants to view +% the font samples. Next, select font-name and output the sample +% string. Finally, move the cursor to the next line in preparation for +% the next invocation of print-font-sample. +/print-font-sample { + /sample-string exch def + /font-name exch def + font-name 8 string cvs /font-name-string exch def + gsave + /Times-Bold 12 selectfont + font-name-string show (:) show + grestore + gsave + 36 0 rmoveto + font-name cvx exec + currentfont bitmap-font-transform makefont setfont + sample-string show + grestore + 0 -24 rmoveto +} def + +end +\%\%EndProcSet +SHOWFONTNAME + ; + if ($sample_ps !~ s/\%\%EndProcSet/$&\n$showfontnamecode/) { + print STDERR 'No %%EndProcSet comment was found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject prologue code\n" if $sample_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop/\n$showfontnamecode\n$&/s; + } + + # Generate code to output a sample of each font in turn. + my $displaycode = <<"PAGEHEADER"; +\%\%Page: 1 1 +TeXDict begin +1 0 bop + +\% Define a transformation matrix for dvips bitmapped fonts. We _could_ +\% do this dynamically but there seems to be a bug in GhostView (v3.6.1) +\% or GhostScript (ESP v7.07.1) that causes the page layout to change +\% with rescaling. To avoid problems we simply hardwire the scaling +\% factor. +/bitmap-font-transform [$dvips_xscale 0.0 0.0 $dvips_yscale 0 0] def + +\% Display a page title. +0 0 moveto +initmatrix +gsave + /Helvetica 18 selectfont + (Fonts used by $infilename_ps) show +grestore +0 -$init_yinc rmoveto + +\% Display samples of each document font in decreasing order of the number +\% of characters utilized from the font. +PAGEHEADER +; + foreach my $fontnum (0 .. $#sortedfontnames) { + my $fontname = $sortedfontnames[$fontnum]; + my $samplestring = join("", psify @{$name2chars{$fontname}}); + $displaycode .= "/$fontname ($samplestring) print-font-sample\n"; + } + $displaycode .= "eop\nend\n"; + if ($sample_ps !~ s/\%\%Page:.*(\%\%Trailer)/$displaycode$1/s) { + print STDERR 'No %%Page and/or %%Trailer comments were found. We have to guess where to inject PostScript code.', "\n" if $verbose >= 3; + die "${progname}: Unable to inject display code\n" if $sample_ps !~ s/TeXDict begin\s+\d+\s+\d+\s+bop.*eop\s+end/\n$displaycode\n/s; + } + + # Write the PostScript file. + open (SAMPLE_PS, ">$sample_file_ps") || die "${progname}: Unable to open $sample_file_ps ($!)\n"; + binmode SAMPLE_PS; + print SAMPLE_PS $sample_ps; + close SAMPLE_PS; + undef $sample_ps; +} + +# If the user requested a TeX font sample, produce that. +if (defined $sample_file_tex) { + my $oneline; # One line to write to the TeX file. + + open (SAMPLE_TEX, ">$sample_file_tex") || die "${progname}: Unable to open $sample_file_tex ($!)\n"; + select (SAMPLE_TEX); + $| = 1; + select (STDOUT); + format SAMPLE_TEX = +% ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~ +$oneline +. + $oneline = <<"TEX_HEADER"; +This file was generated by $0. DO NOT EDIT. Edit $progname instead. +Note that this is a Plain TeX document. Compile it with tex, *not* +latex. +TEX_HEADER + ; + write SAMPLE_TEX; + print SAMPLE_TEX <<'TEX_BOILERPLATE'; + +% Make printable all special characters between +% \makeprintable...\endmakeprintable except for "\", "{", and "}". +\def\makeprintable{% + \begingroup + \def\do##1{\catcode`##1=12}% + \dospecials + \catcode`\\=0\relax + \catcode`\{=1\relax + \catcode`\}=2\relax +} +\let\endmakeprintable=\endgroup + +% Put a piece of text at specific PostScript coordinates. +\newdimen\xofs +\newdimen\yofs +\def\put(#1,#2)#{% + \leavevmode + \begingroup + \makeprintable + \xofs=#1bp + \yofs=#2bp + \afterassignment\puthelper + \toks0=% +} +\def\puthelper{% + \lower\yofs + \rlap{\hskip\xofs\the\toks0}% + \endmakeprintable + \endgroup +} + +% We use Times Bold at 12 point for font names. +\font\timesbXII=ptmb at 12bp + +% Don't add extra space to paragraphs. +\parindent=0pt +\parskip=0pt + +% Output the document's title. +\font\somefont=phvr at 18bp +TEX_BOILERPLATE + ; + # Output the document's title. + my $infilename_tex = texify split "", $infilename; + print SAMPLE_TEX '\put(0, 0){\somefont New fonts to use for ', "$infilename_tex}\n"; + + # Output samples of each font in turn. + print SAMPLE_TEX "\n\% Output font samples.\n"; + foreach my $fontnum (0 .. $#sortedfontnames) { + my $fontname = $sortedfontnames[$fontnum]; + my $samplestring = texify @{$name2chars{$fontname}}; + my $yoffset = $fontnum*$yinc + $init_yinc; + printf SAMPLE_TEX "\\put(0, %d){\\timesbXII %s:}%%\n", $yoffset, $fontname; + my $tfm = $fontmatch{$fontname}->{"tfm"}; + my $scale = $fontmatch{$fontname}->{"scale"}; + my $size = $tfm2size{$tfm}; + printf SAMPLE_TEX "\\font\\somefont=%s%s\\somefont\n", + $tfm, $scale==1.0 ? "" : sprintf(" at %.5gbp", $scale*$size); + printf SAMPLE_TEX "\\put(%d, %d){%s}%%\n", $xinc, $yoffset, $samplestring; + } + + # Complete the TeX file. + print SAMPLE_TEX "\n\\bye\n"; + close SAMPLE_TEX; +} + +########################################################################### + +__END__ + +=head1 NAME + +pkfix-helper - preprocess dvips-produced PostScript documents before passing them to pkfix + + +=head1 SYNOPSIS + +pkfix-helper +[B<--help>] +[B<--verbose>] +[B<--force>=I<name>=I<fontspec>] +[B<--ps>=I<filename.ps>] +[B<--tex>=I<filename.tex>] +[B<--include>=I<fontspec>] +[B<--exclude>=I<regexp>] +[B<--quiet>] +[B<--no-repeats>] +[I<input.ps> [I<output.ps>]] + + +=head1 DESCRIPTION + +=head2 Motivation + +PostScript documents created with old versions of B<dvips> almost +invariably utilize bitmapped (PostScript S<Type 3>) fonts. The +problem with bitmapped fonts is that they target a specific device +resolution; a PostScript file produced using S<300 DPI> fonts will +look grainy on a S<600 DPI> printer. Even worse, I<all> bitmapped +fonts look grainy when zoomed in on screen. The solution is to use +vector (PostScript S<Type 1>) fonts, which are resolution-independent +and appear crisp at any size or scale. + +While it is no longer difficult to configure B<dvips> to use vector +fonts, it is not always possible to rerun B<dvips> on an old F<.dvi> +file. The F<.dvi> file and document source may have been lost; or, +the source may no longer compile because packages it depends upon may +no longer be available. + +Heiko Oberdiek's B<pkfix> script replaces bitmapped fonts in +B<dvips>-produced PostScript files with the corresponding vector +fonts. It works by parsing the PostScript comments with which +B<dvips> surrounds bitmapped-font definitions. For example, a font +definition beginning with the comment C<%DVIPSBitmapFont: Fi cmss10 11 +28> and ending with a matching C<%EndDVIPSBitmapFont> is known to +define font C<Fi> as C<cmss10> (Computer Modern Sans Serif at a design +size of S<10 points>) scaled to S<C<11> points>. Only the C<28> +characters actually used by the document are defined. B<pkfix> then +replaces the font definition with one that defines C<Fi> using the +same set of characters but taken from the F<cmss10.pfb> vector font +file. + +Unfortunately, B<pkfix> works only with versions of B<dvips> newer +than v5.58 S<(ca. 1996)>. Naturally, the older a PostScript document, +the less likely its sources still exist and can still be recompiled. +Older versions of B<dvips> lack C<%DVIPSBitmapFont> comments and +various other PostScript comments on which B<pkfix> relies. Without +PostScript comments to guide it, B<pkfix> is unable to determine which +vector fonts correspond with which bitmapped fonts. + +=head2 Overview + +The B<pkfix-helper> script is a preprocessor for B<pkfix> that +attempts to determine the association between each document-font name +S<(e.g., C<Fi>)> in a PostScript file and the original font S<(e.g., +C<cmss10>)> and fonts size (e.g., S<C<11> points>). It then +fabricates the PostScript comments that B<pkfix> expects to see so +that B<pkfix> can do its job. + +B<pkfix-helper> works by comparing every document font against every +F<.tfm> font file it knows about (assuming that each such font has a +corresponding F<.pfb> vector version) and selecting the best matching +F<.tfm> file for every document font. B<pkfix-helper> has access only +to the widths of characters and only to those characters actually used +in the document. Also, the program recognizes only a limited set of +the most popular F<.tfm> files and scaling factors. Consequently, the +comparison is imperfect and B<pkfix-helper> may attribute an incorrect +font to a given name. Fonts comprising only one or two characters +actually used in a document are particularly problematic for +B<pkfix-helper> because many fonts may be near-enough matches to fool +the problem. + +B<pkfix-helper> is designed so that a user can guide the +font-selection process by manually designating matching fonts. With a +modicum of diligence and patience a user can correct any mismatched +fonts and help the program provide proper input to B<pkfix>. + + +=head1 OPTIONS + +B<pkfix-helper> accepts on the command line the filename of a +PostScript document to process (with the default being the standard +input device) and the filename of a modified PostScript document to +create (with the default being the standard output device). The +program also accepts the following command-line options: + +=head2 Frequently Used Options + +=over 4 + +=item B<-h>, B<--help> + +Display usage information and exit. The B<--verbose> and B<--quiet> +options can be used to increase and decrease the amount of information +presented. + +=item B<-v>, B<--verbose> + +Increase the amount of status information that B<pkfix-helper> +displays as it runs. Additional instances of B<--verbose> on the +command line further increase the program's verbosity. By default, +only major operations are displayed. A single B<--verbose> +additionally displays information about individual font comparisons. +A second B<--verbose> additionally displays details about some of the +program's internal operations. + +=item B<-f> I<name>=I<fontspec>, B<--force>=I<name>=I<fontspec> + +Force B<pkfix-helper> to associate a specific font with a given font +name appearing the document. I<name> is a two-character B<dvips> font +name such as C<Fa>. I<fontspec> is a font specification such as +S<C<cmsy10 @ 1.1X>>. The B<--force> option can be specified +repeatedly on the command line. + +=item B<-p> I<filename.ps>, B<--ps>=I<filename.ps> + +Create a PostScript file called I<filename.ps> that shows the B<dvips> +name and a font sample of every font used by the input document. + +=item B<-t> I<filename.tex>, B<--tex>=I<filename.tex> + +Create a Plain TeX file called I<filename.tex> that shows the B<dvips> +name and a font sample of every font that B<pkfix-helper> used in the +output document. + +=back + +=head2 Infrequently Used Options + +=over 4 + +=item B<-i> I<fontspec>, B<--include>=I<fontspec> + +Add I<fontspec> to the list of font specifications against which +B<pkfix-helper> compares I<every> document font. (In contrast, +B<--force> designates a font specification to use only for a +I<specific> document font.) The B<--include> option can be specified +repeatedly on the command line. + +=item B<-x> I<regexp>, B<--exclude>=I<regexp> + +Remove all font specifications matching regular expression I<regexp> +from B<pkfix-helper>'s list of known fonts. The B<--exclude> option +can be specified repeatedly on the command line. + +=item B<-q>, B<--quiet> + +Instruct B<pkfix-helper> to produce no output during its run except +for fatal error messages. + +=item B<-1>, B<--no-repeats> + +Prevent B<pkfix-helper> from associating the same I<fontspec> with +more than one B<dvips> font name. + +=back + + +=head1 DIAGNOSTICS + +=over 4 + +=item C<Best match for I<name> is rather poor> + +The best font B<pkfix-helper> found for B<dvips> font name I<name> has +a mismatch value greater than or equal S<to 1.0>. (The mismatch value +is the sum of the squares of the difference between the character +widths of a document font and a potential replacement font.) Use the +B<--force> option to designate an alternative replacement font or +scaling amount. + +=back + + +=head1 EXAMPLES + +For the purpose of the following examples, assume that F<oldfile.ps> +is the name of a PostScript file produced by an old version of +B<dvips> and utilizing at least one bitmapped font. It's always worth +verifying that B<pkfix> can't convert the file on its own: + + % pkfix oldfile.ps newfile.ps + PKFIX 1.3, 2005/02/25 - Copyright (c) 2001, 2005 by Heiko Oberdiek. + ==> no fonts converted + +(Alternatively B<pkfix> may issue an error message such as C<!!! +Error: Parse error (@start parameters)!>.) Only when B<pkfix> can't +replace bitmapped fonts with vector fonts is B<pkfix-helper> needed. +In its simplest form, B<pkfix-helper> takes the name of an input file +(F<oldfile.ps> in this example) and the name of an output file +(F<pkfix-oldfile.ps>), which will have the same contents as the input +file but serve as suitable input for B<pkfix>: + + % pkfix-helper oldfile.ps pkfix-oldfile.ps + Reading netpipe.ps ... done. + Number of Type 3 fonts encountered: 10 + Bitmapped fonts are typeset at 600 DPI. + Finding character widths ... done. + Reading TFM files ... done (103 TFMs in 193 scaling variations). + Matching fonts: + Processing Fi ... done (cmr10 @ 1X, mismatch=0.11683). + Processing Fa ... done (cmti10 @ 1X, mismatch=0.08892). + Processing Fb ... done (cmr8 @ 1X, mismatch=0.07133). + Processing Ff ... done (cmbx12 @ 1.2X, mismatch=0.02948). + Processing Fh ... done (cmtt10 @ 1X, mismatch=0.06895). + Processing Fd ... done (cmmi10 @ 1X, mismatch=0.03966). + Processing Fj ... done (cmbx12 @ 1X, mismatch=0.03972). + Processing Fe ... done (cmbx10 @ 1X, mismatch=0.00762). + Processing Fg ... done (cmsy10 @ 1X, mismatch=0.00875). + Processing Fc ... done (cmr6 @ 1X, mismatch=0.00284). + + % pkfix pkfix-oldfile.ps newfile.ps + PKFIX 1.3, 2005/02/25 - Copyright (c) 2001, 2005 by Heiko Oberdiek. + *** Font conversion: `cmti10' -> `CMTI10'. + *** Font conversion: `cmr8' -> `CMR8'. + *** Font conversion: `cmr6' -> `CMR6'. + *** Font conversion: `cmmi10' -> `CMMI10'. + *** Font conversion: `cmbx10' -> `CMBX10'. + *** Font conversion: `cmbx12' -> `CMBX12'. + *** Font conversion: `cmsy10' -> `CMSY10'. + *** Font conversion: `cmtt10' -> `CMTT10'. + *** Font conversion: `cmr10' -> `CMR10'. + *** Font conversion: `cmbx12' -> `CMBX12'. + *** Merging font `CMBX12' (2). + ==> 10 converted fonts. + ==> 1 merged font. + +Although B<pkfix-helper> tries to automate as much as possible the +font-detection process, some fonts will invariably be incorrectly +identified. The program outputs a warning message if it I<knows> a +match is bad but the lack of a warning message does not necessarily +indicate that B<pkfix-helper> did a good job. It is therefore +strongly recommended that the user produce "before" and "after" font +sheets: + + % pkfix-helper -q oldfile.ps pkfix-oldfile.ps \ + --ps=oldfonts.ps --tex=newfonts.tex + + % tex newfonts.tex + This is TeX, Version 3.14159 (Web2C 7.4.5) + (./newfonts.tex [1] ) + Output written on newfonts.dvi (1 page, 1292 bytes). + Transcript written on newfonts.log. + + % dvips newfonts.dvi -o newfonts.ps + This is dvips(k) 5.92b Copyright 2002 Radical Eye Software (www.radicaleye.com) + ' TeX output 2006.06.11:1636' -> newfonts.ps + <texc.pro><8r.enc><texps.pro>. <cmr6.pfb><cmsy10.pfb><cmbx10.pfb><cmbx12.pfb> + <cmmi10.pfb><cmtt10.pfb><cmr8.pfb><cmti10.pfb><cmr10.pfb>[1] + +After running the preceding commands, F<oldfonts.ps> shows samples of +the fonts in F<oldfile.ps> and F<newfonts.ps> shows samples of the +replacement fonts that B<pkfix-helper> used to produce +F<pkfix-oldfile.ps>. Print F<oldfonts.ps> and <newfonts.ps> and +compare them carefully for incorrect fonts and sizes. + +Suppose that the choice of C<cmbx12 @ 1.2X> for font C<Ff> looks +wrong; say the characters look taller in F<oldfonts.ps> than in +F<newfonts.ps>. This is where the trial-and-error stage begins. +Let's hypothesize that C<cmb12> is a better match than C<cmbx12> but +we don't know how much to scale the font. Fortunately, +B<pkfix-helper> allows C<*> to be used as a scaling factor to tell the +program to automatically detect an optimal scaling factor, even if +doing so means choosing a highly nonstandard font size: + + % pkfix-helper oldfile.ps pkfix-oldfile.ps --force="Ff=cmb12 @ *" + Reading netpipe.ps ... done. + Number of Type 3 fonts encountered: 10 + Bitmapped fonts are typeset at 600 DPI. + Finding character widths ... done. + Reading TFM files ... failed. + pkfix-helper: Unable to process user-specified TFM file "cmb12" + +Oops, it looks like we don't have a F<cmb12.tfm> file on our system. +Let's try scaling up F<cmb10.tfm> instead: + + % pkfix-helper oldfile.ps pkfix-oldfile.ps --force="Ff=cmb10 @ *" + Reading netpipe.ps ... done. + Number of Type 3 fonts encountered: 10 + Bitmapped fonts are typeset at 600 DPI. + Finding character widths ... done. + Reading TFM files ... done (103 TFMs in 193 scaling variations). + Matching fonts: + Processing Fi ... done (cmr10 @ 1X, mismatch=0.11683). + Processing Fa ... done (cmti10 @ 1X, mismatch=0.08892). + Processing Fb ... done (cmr8 @ 1X, mismatch=0.07133). + Processing Ff ... done (cmb10 @ 1.5708X, mismatch=0.00035). + Processing Fh ... done (cmtt10 @ 1X, mismatch=0.06895). + Processing Fd ... done (cmmi10 @ 1X, mismatch=0.03966). + Processing Fj ... done (cmbx12 @ 1X, mismatch=0.03972). + Processing Fe ... done (cmbx10 @ 1X, mismatch=0.00762). + Processing Fg ... done (cmsy10 @ 1X, mismatch=0.00875). + Processing Fc ... done (cmr6 @ 1X, mismatch=0.00284). + +The match has definitely improved, although S<15.708 pt.> is certainly +an odd size for a font. Then again, many documents I<do> use +nonstandard sizes so this may in fact be correct. The best way to +verify is once again to produce, print, and compare a pair of font +samples and iterate until all of the fonts look correct. Use one +instance of B<--force> for each font you want to alter. + + +=head1 ENVIRONMENT + +B<pkfix-helper> honors the following environment variables: + +=over 8 + +=item GS + +The name of the Ghostscript interpreter (default: F<gs>) + +=item TFTOPL + +The name of a utility for converting F<.tfm> files to F<.pl> files +(default: F<tftopl>) + +=back + + +=head1 BUGS + +Even when B<pkfix-helper> finds a perfect match S<(i.e., the> correct +font in the correct size) the mismatch value is still typically +nonzero. The same error is probably what causes B<pkfix-helper> +sometimes to consider the wrong font as being a better match than the +correct font. Suggestions for fixing these bugs are welcome. + + +=head1 RESTRICTIONS + +B<pkfix-helper> works only with PostScript files produced by B<dvips>, +not with arbitrary PostScript files. The program has not been tested +with output from versions of B<dvips> older than v5.490 S<(ca. 1992)>; +output from older versions may or may not work. Only bitmapped fonts +loaded by B<dvips> can be analyzed, not bitmapped fonts loaded by +embedded graphics. + +B<pkfix-helper> works by comparing character widths, not the actual +glyphs. Consequently, it is misled by sets of fonts with similar +character widths (at least for those characters used by a given +document). As an extreme example, all Computer Modern Teletype fonts +of a given design size (e.g., C<cmtt10>, C<cmsltt10>, and C<cmitt10>) +use exactly the same widths for all characters. Human assistance is +generally needed to guide B<pkfix-helper>'s font-matching procedures. + + +=head1 NOTES + +Files produced using the B<--tex> option are Plain TeX files and +therefore must be compiled with F<tex> (or a variation such F<etex>, +F<pdftex>, F<pdfetex>, etc.), I<not> with F<latex>. + + +=head1 SEE ALSO + +pkfix(1), dvips(1), tex(1), gs(1) + +PostScript Language Reference, Third Edition. +Published by Addison-Wesley, ISBN 0-201-37922-8, +L<http://www.adobe.com/products/postscript/pdfs/PLRM.pdf>. + + +=head1 AUTHOR + +Scott Pakin, I<scott+pkfh@pakin.org> + + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2006, Scott Pakin + +This file may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.3c of this license +or (at your option) any later version. The latest version of this +license is in L<http://www.latex-project.org/lppl.txt> and version +1.3c or later is part of all distributions of LaTeX version 2006/05/20 +or later. diff --git a/Master/texmf/doc/man/man1/pkfix-helper.1 b/Master/texmf/doc/man/man1/pkfix-helper.1 new file mode 100644 index 00000000000..f4c0eea458c --- /dev/null +++ b/Master/texmf/doc/man/man1/pkfix-helper.1 @@ -0,0 +1,483 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "PKFIX-HELPER 1" +.TH PKFIX-HELPER 1 "2006-06-18" "v1.0" " " +.SH "NAME" +pkfix\-helper \- preprocess dvips\-produced PostScript documents before passing them to pkfix +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +pkfix-helper +[\fB\-\-help\fR] +[\fB\-\-verbose\fR] +[\fB\-\-force\fR=\fIname\fR=\fIfontspec\fR] +[\fB\-\-ps\fR=\fIfilename.ps\fR] +[\fB\-\-tex\fR=\fIfilename.tex\fR] +[\fB\-\-include\fR=\fIfontspec\fR] +[\fB\-\-exclude\fR=\fIregexp\fR] +[\fB\-\-quiet\fR] +[\fB\-\-no\-repeats\fR] +[\fIinput.ps\fR [\fIoutput.ps\fR]] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.Sh "Motivation" +.IX Subsection "Motivation" +PostScript documents created with old versions of \fBdvips\fR almost +invariably utilize bitmapped (PostScript Type\ 3) fonts. The +problem with bitmapped fonts is that they target a specific device +resolution; a PostScript file produced using 300\ \s-1DPI\s0 fonts will +look grainy on a 600\ \s-1DPI\s0 printer. Even worse, \fIall\fR bitmapped +fonts look grainy when zoomed in on screen. The solution is to use +vector (PostScript Type\ 1) fonts, which are resolution-independent +and appear crisp at any size or scale. +.PP +While it is no longer difficult to configure \fBdvips\fR to use vector +fonts, it is not always possible to rerun \fBdvips\fR on an old \fI.dvi\fR +file. The \fI.dvi\fR file and document source may have been lost; or, +the source may no longer compile because packages it depends upon may +no longer be available. +.PP +Heiko Oberdiek's \fBpkfix\fR script replaces bitmapped fonts in +\&\fBdvips\fR\-produced PostScript files with the corresponding vector +fonts. It works by parsing the PostScript comments with which +\&\fBdvips\fR surrounds bitmapped-font definitions. For example, a font +definition beginning with the comment \f(CW\*(C`%DVIPSBitmapFont: Fi cmss10 11 +28\*(C'\fR and ending with a matching \f(CW%EndDVIPSBitmapFont\fR is known to +define font \f(CW\*(C`Fi\*(C'\fR as \f(CW\*(C`cmss10\*(C'\fR (Computer Modern Sans Serif at a design +size of 10\ points) scaled to \f(CW11\fR\ points. Only the \f(CW28\fR +characters actually used by the document are defined. \fBpkfix\fR then +replaces the font definition with one that defines \f(CW\*(C`Fi\*(C'\fR using the +same set of characters but taken from the \fIcmss10.pfb\fR vector font +file. +.PP +Unfortunately, \fBpkfix\fR works only with versions of \fBdvips\fR newer +than v5.58 (ca.\ 1996). Naturally, the older a PostScript document, +the less likely its sources still exist and can still be recompiled. +Older versions of \fBdvips\fR lack \f(CW%DVIPSBitmapFont\fR comments and +various other PostScript comments on which \fBpkfix\fR relies. Without +PostScript comments to guide it, \fBpkfix\fR is unable to determine which +vector fonts correspond with which bitmapped fonts. +.Sh "Overview" +.IX Subsection "Overview" +The \fBpkfix-helper\fR script is a preprocessor for \fBpkfix\fR that +attempts to determine the association between each document-font name +(e.g.,\ \f(CW\*(C`Fi\*(C'\fR) in a PostScript file and the original font (e.g.,\ \f(CW\*(C`cmss10\*(C'\fR) and fonts size (e.g., \f(CW11\fR\ points). It then +fabricates the PostScript comments that \fBpkfix\fR expects to see so +that \fBpkfix\fR can do its job. +.PP +\&\fBpkfix-helper\fR works by comparing every document font against every +\&\fI.tfm\fR font file it knows about (assuming that each such font has a +corresponding \fI.pfb\fR vector version) and selecting the best matching +\&\fI.tfm\fR file for every document font. \fBpkfix-helper\fR has access only +to the widths of characters and only to those characters actually used +in the document. Also, the program recognizes only a limited set of +the most popular \fI.tfm\fR files and scaling factors. Consequently, the +comparison is imperfect and \fBpkfix-helper\fR may attribute an incorrect +font to a given name. Fonts comprising only one or two characters +actually used in a document are particularly problematic for +\&\fBpkfix-helper\fR because many fonts may be near-enough matches to fool +the problem. +.PP +\&\fBpkfix-helper\fR is designed so that a user can guide the +font-selection process by manually designating matching fonts. With a +modicum of diligence and patience a user can correct any mismatched +fonts and help the program provide proper input to \fBpkfix\fR. +.SH "OPTIONS" +.IX Header "OPTIONS" +\&\fBpkfix-helper\fR accepts on the command line the filename of a +PostScript document to process (with the default being the standard +input device) and the filename of a modified PostScript document to +create (with the default being the standard output device). The +program also accepts the following command-line options: +.Sh "Frequently Used Options" +.IX Subsection "Frequently Used Options" +.IP "\fB\-h\fR, \fB\-\-help\fR" 4 +.IX Item "-h, --help" +Display usage information and exit. The \fB\-\-verbose\fR and \fB\-\-quiet\fR +options can be used to increase and decrease the amount of information +presented. +.IP "\fB\-v\fR, \fB\-\-verbose\fR" 4 +.IX Item "-v, --verbose" +Increase the amount of status information that \fBpkfix-helper\fR +displays as it runs. Additional instances of \fB\-\-verbose\fR on the +command line further increase the program's verbosity. By default, +only major operations are displayed. A single \fB\-\-verbose\fR +additionally displays information about individual font comparisons. +A second \fB\-\-verbose\fR additionally displays details about some of the +program's internal operations. +.IP "\fB\-f\fR \fIname\fR=\fIfontspec\fR, \fB\-\-force\fR=\fIname\fR=\fIfontspec\fR" 4 +.IX Item "-f name=fontspec, --force=name=fontspec" +Force \fBpkfix-helper\fR to associate a specific font with a given font +name appearing the document. \fIname\fR is a two-character \fBdvips\fR font +name such as \f(CW\*(C`Fa\*(C'\fR. \fIfontspec\fR is a font specification such as +\&\f(CW\*(C`cmsy10\ @\ 1.1X\*(C'\fR. The \fB\-\-force\fR option can be specified +repeatedly on the command line. +.IP "\fB\-p\fR \fIfilename.ps\fR, \fB\-\-ps\fR=\fIfilename.ps\fR" 4 +.IX Item "-p filename.ps, --ps=filename.ps" +Create a PostScript file called \fIfilename.ps\fR that shows the \fBdvips\fR +name and a font sample of every font used by the input document. +.IP "\fB\-t\fR \fIfilename.tex\fR, \fB\-\-tex\fR=\fIfilename.tex\fR" 4 +.IX Item "-t filename.tex, --tex=filename.tex" +Create a Plain TeX file called \fIfilename.tex\fR that shows the \fBdvips\fR +name and a font sample of every font that \fBpkfix-helper\fR used in the +output document. +.Sh "Infrequently Used Options" +.IX Subsection "Infrequently Used Options" +.IP "\fB\-i\fR \fIfontspec\fR, \fB\-\-include\fR=\fIfontspec\fR" 4 +.IX Item "-i fontspec, --include=fontspec" +Add \fIfontspec\fR to the list of font specifications against which +\&\fBpkfix-helper\fR compares \fIevery\fR document font. (In contrast, +\&\fB\-\-force\fR designates a font specification to use only for a +\&\fIspecific\fR document font.) The \fB\-\-include\fR option can be specified +repeatedly on the command line. +.IP "\fB\-x\fR \fIregexp\fR, \fB\-\-exclude\fR=\fIregexp\fR" 4 +.IX Item "-x regexp, --exclude=regexp" +Remove all font specifications matching regular expression \fIregexp\fR +from \fBpkfix-helper\fR's list of known fonts. The \fB\-\-exclude\fR option +can be specified repeatedly on the command line. +.IP "\fB\-q\fR, \fB\-\-quiet\fR" 4 +.IX Item "-q, --quiet" +Instruct \fBpkfix-helper\fR to produce no output during its run except +for fatal error messages. +.IP "\fB\-1\fR, \fB\-\-no\-repeats\fR" 4 +.IX Item "-1, --no-repeats" +Prevent \fBpkfix-helper\fR from associating the same \fIfontspec\fR with +more than one \fBdvips\fR font name. +.SH "DIAGNOSTICS" +.IX Header "DIAGNOSTICS" +.ie n .IP """Best match for \f(CIname\f(CW is rather poor""" 4 +.el .IP "\f(CWBest match for \f(CIname\f(CW is rather poor\fR" 4 +.IX Item "Best match for name is rather poor" +The best font \fBpkfix-helper\fR found for \fBdvips\fR font name \fIname\fR has +a mismatch value greater than or equal to\ 1.0. (The mismatch value +is the sum of the squares of the difference between the character +widths of a document font and a potential replacement font.) Use the +\&\fB\-\-force\fR option to designate an alternative replacement font or +scaling amount. +.SH "EXAMPLES" +.IX Header "EXAMPLES" +For the purpose of the following examples, assume that \fIoldfile.ps\fR +is the name of a PostScript file produced by an old version of +\&\fBdvips\fR and utilizing at least one bitmapped font. It's always worth +verifying that \fBpkfix\fR can't convert the file on its own: +.PP +.Vb 3 +\& % pkfix oldfile.ps newfile.ps +\& PKFIX 1.3, 2005/02/25 \- Copyright (c) 2001, 2005 by Heiko Oberdiek. +\& ==> no fonts converted +.Ve +.PP +(Alternatively \fBpkfix\fR may issue an error message such as \f(CW\*(C`!!! +Error: Parse error (@start parameters)!\*(C'\fR.) Only when \fBpkfix\fR can't +replace bitmapped fonts with vector fonts is \fBpkfix-helper\fR needed. +In its simplest form, \fBpkfix-helper\fR takes the name of an input file +(\fIoldfile.ps\fR in this example) and the name of an output file +(\fIpkfix\-oldfile.ps\fR), which will have the same contents as the input +file but serve as suitable input for \fBpkfix\fR: +.PP +.Vb 17 +\& % pkfix\-helper oldfile.ps pkfix\-oldfile.ps +\& Reading netpipe.ps ... done. +\& Number of Type 3 fonts encountered: 10 +\& Bitmapped fonts are typeset at 600 DPI. +\& Finding character widths ... done. +\& Reading TFM files ... done (103 TFMs in 193 scaling variations). +\& Matching fonts: +\& Processing Fi ... done (cmr10 @ 1X, mismatch=0.11683). +\& Processing Fa ... done (cmti10 @ 1X, mismatch=0.08892). +\& Processing Fb ... done (cmr8 @ 1X, mismatch=0.07133). +\& Processing Ff ... done (cmbx12 @ 1.2X, mismatch=0.02948). +\& Processing Fh ... done (cmtt10 @ 1X, mismatch=0.06895). +\& Processing Fd ... done (cmmi10 @ 1X, mismatch=0.03966). +\& Processing Fj ... done (cmbx12 @ 1X, mismatch=0.03972). +\& Processing Fe ... done (cmbx10 @ 1X, mismatch=0.00762). +\& Processing Fg ... done (cmsy10 @ 1X, mismatch=0.00875). +\& Processing Fc ... done (cmr6 @ 1X, mismatch=0.00284). +.Ve +.PP +.Vb 15 +\& % pkfix pkfix\-oldfile.ps newfile.ps +\& PKFIX 1.3, 2005/02/25 \- Copyright (c) 2001, 2005 by Heiko Oberdiek. +\& *** Font conversion: `cmti10' \-> `CMTI10'. +\& *** Font conversion: `cmr8' \-> `CMR8'. +\& *** Font conversion: `cmr6' \-> `CMR6'. +\& *** Font conversion: `cmmi10' \-> `CMMI10'. +\& *** Font conversion: `cmbx10' \-> `CMBX10'. +\& *** Font conversion: `cmbx12' \-> `CMBX12'. +\& *** Font conversion: `cmsy10' \-> `CMSY10'. +\& *** Font conversion: `cmtt10' \-> `CMTT10'. +\& *** Font conversion: `cmr10' \-> `CMR10'. +\& *** Font conversion: `cmbx12' \-> `CMBX12'. +\& *** Merging font `CMBX12' (2). +\& ==> 10 converted fonts. +\& ==> 1 merged font. +.Ve +.PP +Although \fBpkfix-helper\fR tries to automate as much as possible the +font-detection process, some fonts will invariably be incorrectly +identified. The program outputs a warning message if it \fIknows\fR a +match is bad but the lack of a warning message does not necessarily +indicate that \fBpkfix-helper\fR did a good job. It is therefore +strongly recommended that the user produce \*(L"before\*(R" and \*(L"after\*(R" font +sheets: +.PP +.Vb 2 +\& % pkfix\-helper \-q oldfile.ps pkfix\-oldfile.ps \e +\& \-\-ps=oldfonts.ps \-\-tex=newfonts.tex +.Ve +.PP +.Vb 5 +\& % tex newfonts.tex +\& This is TeX, Version 3.14159 (Web2C 7.4.5) +\& (./newfonts.tex [1] ) +\& Output written on newfonts.dvi (1 page, 1292 bytes). +\& Transcript written on newfonts.log. +.Ve +.PP +.Vb 5 +\& % dvips newfonts.dvi \-o newfonts.ps +\& This is dvips(k) 5.92b Copyright 2002 Radical Eye Software (www.radicaleye.com) +\& ' TeX output 2006.06.11:1636' \-> newfonts.ps +\& <texc.pro><8r.enc><texps.pro>. <cmr6.pfb><cmsy10.pfb><cmbx10.pfb><cmbx12.pfb> +\& <cmmi10.pfb><cmtt10.pfb><cmr8.pfb><cmti10.pfb><cmr10.pfb>[1] +.Ve +.PP +After running the preceding commands, \fIoldfonts.ps\fR shows samples of +the fonts in \fIoldfile.ps\fR and \fInewfonts.ps\fR shows samples of the +replacement fonts that \fBpkfix-helper\fR used to produce +\&\fIpkfix\-oldfile.ps\fR. Print \fIoldfonts.ps\fR and <newfonts.ps> and +compare them carefully for incorrect fonts and sizes. +.PP +Suppose that the choice of \f(CW\*(C`cmbx12 @ 1.2X\*(C'\fR for font \f(CW\*(C`Ff\*(C'\fR looks +wrong; say the characters look taller in \fIoldfonts.ps\fR than in +\&\fInewfonts.ps\fR. This is where the trial-and-error stage begins. +Let's hypothesize that \f(CW\*(C`cmb12\*(C'\fR is a better match than \f(CW\*(C`cmbx12\*(C'\fR but +we don't know how much to scale the font. Fortunately, +\&\fBpkfix-helper\fR allows \f(CW\*(C`*\*(C'\fR to be used as a scaling factor to tell the +program to automatically detect an optimal scaling factor, even if +doing so means choosing a highly nonstandard font size: +.PP +.Vb 7 +\& % pkfix\-helper oldfile.ps pkfix\-oldfile.ps \-\-force="Ff=cmb12 @ *" +\& Reading netpipe.ps ... done. +\& Number of Type 3 fonts encountered: 10 +\& Bitmapped fonts are typeset at 600 DPI. +\& Finding character widths ... done. +\& Reading TFM files ... failed. +\& pkfix\-helper: Unable to process user\-specified TFM file "cmb12" +.Ve +.PP +Oops, it looks like we don't have a \fIcmb12.tfm\fR file on our system. +Let's try scaling up \fIcmb10.tfm\fR instead: +.PP +.Vb 17 +\& % pkfix\-helper oldfile.ps pkfix\-oldfile.ps \-\-force="Ff=cmb10 @ *" +\& Reading netpipe.ps ... done. +\& Number of Type 3 fonts encountered: 10 +\& Bitmapped fonts are typeset at 600 DPI. +\& Finding character widths ... done. +\& Reading TFM files ... done (103 TFMs in 193 scaling variations). +\& Matching fonts: +\& Processing Fi ... done (cmr10 @ 1X, mismatch=0.11683). +\& Processing Fa ... done (cmti10 @ 1X, mismatch=0.08892). +\& Processing Fb ... done (cmr8 @ 1X, mismatch=0.07133). +\& Processing Ff ... done (cmb10 @ 1.5708X, mismatch=0.00035). +\& Processing Fh ... done (cmtt10 @ 1X, mismatch=0.06895). +\& Processing Fd ... done (cmmi10 @ 1X, mismatch=0.03966). +\& Processing Fj ... done (cmbx12 @ 1X, mismatch=0.03972). +\& Processing Fe ... done (cmbx10 @ 1X, mismatch=0.00762). +\& Processing Fg ... done (cmsy10 @ 1X, mismatch=0.00875). +\& Processing Fc ... done (cmr6 @ 1X, mismatch=0.00284). +.Ve +.PP +The match has definitely improved, although 15.708\ pt. is certainly +an odd size for a font. Then again, many documents \fIdo\fR use +nonstandard sizes so this may in fact be correct. The best way to +verify is once again to produce, print, and compare a pair of font +samples and iterate until all of the fonts look correct. Use one +instance of \fB\-\-force\fR for each font you want to alter. +.SH "ENVIRONMENT" +.IX Header "ENVIRONMENT" +\&\fBpkfix-helper\fR honors the following environment variables: +.IP "\s-1GS\s0" 8 +.IX Item "GS" +The name of the Ghostscript interpreter (default: \fIgs\fR) +.IP "\s-1TFTOPL\s0" 8 +.IX Item "TFTOPL" +The name of a utility for converting \fI.tfm\fR files to \fI.pl\fR files +(default: \fItftopl\fR) +.SH "BUGS" +.IX Header "BUGS" +Even when \fBpkfix-helper\fR finds a perfect match (i.e.,\ the correct +font in the correct size) the mismatch value is still typically +nonzero. The same error is probably what causes \fBpkfix-helper\fR +sometimes to consider the wrong font as being a better match than the +correct font. Suggestions for fixing these bugs are welcome. +.SH "RESTRICTIONS" +.IX Header "RESTRICTIONS" +\&\fBpkfix-helper\fR works only with PostScript files produced by \fBdvips\fR, +not with arbitrary PostScript files. The program has not been tested +with output from versions of \fBdvips\fR older than v5.490 (ca.\ 1992); +output from older versions may or may not work. Only bitmapped fonts +loaded by \fBdvips\fR can be analyzed, not bitmapped fonts loaded by +embedded graphics. +.PP +\&\fBpkfix-helper\fR works by comparing character widths, not the actual +glyphs. Consequently, it is misled by sets of fonts with similar +character widths (at least for those characters used by a given +document). As an extreme example, all Computer Modern Teletype fonts +of a given design size (e.g., \f(CW\*(C`cmtt10\*(C'\fR, \f(CW\*(C`cmsltt10\*(C'\fR, and \f(CW\*(C`cmitt10\*(C'\fR) +use exactly the same widths for all characters. Human assistance is +generally needed to guide \fBpkfix-helper\fR's font-matching procedures. +.SH "NOTES" +.IX Header "NOTES" +Files produced using the \fB\-\-tex\fR option are Plain TeX files and +therefore must be compiled with \fItex\fR (or a variation such \fIetex\fR, +\&\fIpdftex\fR, \fIpdfetex\fR, etc.), \fInot\fR with \fIlatex\fR. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fIpkfix\fR\|(1), \fIdvips\fR\|(1), \fItex\fR\|(1), \fIgs\fR\|(1) +.PP +PostScript Language Reference, Third Edition. +Published by Addison\-Wesley, \s-1ISBN\s0 0\-201\-37922\-8, +<http://www.adobe.com/products/postscript/pdfs/PLRM.pdf>. +.SH "AUTHOR" +.IX Header "AUTHOR" +Scott Pakin, \fIscott+pkfh@pakin.org\fR +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2006, Scott Pakin +.PP +This file may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.3c of this license +or (at your option) any later version. The latest version of this +license is in <http://www.latex\-project.org/lppl.txt> and version +1.3c or later is part of all distributions of LaTeX version 2006/05/20 +or later. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 2424fc6633a..55c0fee5c3e 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -174,7 +174,7 @@ my @WorkingTLP = qw( permute petiteannonce pgf pgf-soroban pgfopts pgfplots phaistos philex philosophersimprint phonetic pict2e pictex pictex2 pigpen - pinlabel pittetd pkfix placeins plari plates play + pinlabel pittetd pkfix pkfix-helper placeins plari plates play plnfss pmgraph poemscol polski polyglossia polynom polynomial polytable powerdot ppr-prv pracjourn preprint diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index ea20e7532b3..483f93844d4 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -1034,6 +1034,7 @@ $standardtex='\.(cfg|sty|clo|ldf|cls|def|fd|cmap|4ht)$'; 'phonetic', 'fonts', 'pictex', 'generic', 'pkfix', 'support', + 'pkfix-helper','support', 'plnfss', 'plain', 'psfrag-italian', 'italian', 'pst-cox', 'generic', @@ -1411,6 +1412,7 @@ $standardxmt='\.xmt'; 'pdfcrop' => '\.pl$', 'perltex' => '\.pl$', 'pkfix' => '\.pl$', + 'pkfix-helper' => 'pkfix-helper$', 'pst2pdf' => '\.pl$', 'purifyeps' => 'purifyeps$', 'texcount' => '\.pl$', @@ -1420,6 +1422,7 @@ $standardxmt='\.xmt'; # packages which have man pages to install. Assume section 1 for now. %specialmans = ( + 'pkfix-helper' => 'pkfix-helper.1', 'purifyeps' => 'purifyeps.1', ); @@ -1445,6 +1448,7 @@ $standardclean = '\.head|\.tmp|\.dvi|\.log|\.out|\.aux|\.toc|\.lof|\.lot' 'lshort-spanish'=>'lshort-a5book.pdf', # a4 is enough 'mathexam' => 'sample.tex~', 'notes2bib' => "$standardclean|jawltxdoc.sty", # temp file for doc + 'pkfix-helper' => 'pkfix-helper.pdf', 'purifyeps' => 'purifyeps.pdf', 'rsc' => $standardclean . '|jawltxdoc.sty', # temp file for doc 'wsuipa' => $standardclean . '|.*pk$', # premade pk files diff --git a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc index e6aa5df81dc..93a3463617e 100644 --- a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc @@ -33,6 +33,7 @@ depend latexmk depend mkind-english depend mkjobtexmf depend pdfcrop +depend pkfix-helper depend purifyeps depend synctex depend texcount diff --git a/Master/tlpkg/tlpsrc/pkfix-helper.tlpsrc b/Master/tlpkg/tlpsrc/pkfix-helper.tlpsrc new file mode 100644 index 00000000000..d05842bbfaa --- /dev/null +++ b/Master/tlpkg/tlpsrc/pkfix-helper.tlpsrc @@ -0,0 +1,2 @@ +name pkfix-helper +category Package @@ -32,7 +32,7 @@ Public domain. TODO: not done already. - kpsewhich default to "TeX system documentation" for *.pdf, *.html. - add epspdf to doc/info/dir (should not be in bin-kpathsea, either). -- enable binpattern in {texloganalyser,purifyeps}.tlpsrc. +- enable/write binpattern in {texloganalyser,purifyeps,pkfix-helper}.tlpsrc. - add luatex-plain.mem generation per elie. - review comments in context.tlpsrc. - move pkfix (and other scripts?) to texmf-dist, get symlinks right. @@ -40,8 +40,8 @@ Public domain. TODO: - remove bin-* prefixes from package names where possible. - merge collection-ttfutils and collection-psutils into collection-fontbin. better name? -- move purifyeps, pdfcrop, bin-pdftools, others? from binextra to a - collection-pdftools? some other name? +- move pkfix-helper, purifyeps, pdfcrop, bin-pdftools, others? from + binextra to a collection-pdftools? some other name? 1. Package updates ================== |