PKFIX-HELPER(1)

πŸ’– pkfix-helper(1) πŸ’–

okay so bestie, welcome to the manual page for pkfix-helper β€” it lives in section 1 of the manual, and it's literally the pre-flight glow-up your crusty old PostScript files have been begging for. grab a boba, we're doing this πŸ§‹βœ¨


🌸 NAME 🌸

pkfix-helper β€” preprocess dvips-produced PostScript documents before passing them to pkfix

like. that's the whole vibe. it's the opening act, pkfix is the headliner 🎀


✨ SYNOPSIS ✨

pkfix-helper [--help] [--verbose] [--force=name=fontspec]
[--ps=filename.ps] [--tex=filename.tex] [--cache=filename]
[--include=fontspec] [--exclude=regexp] [--keep=fontspec] [--quiet]
[--no-repeats] [--spp=number] [input.ps [output.ps]]

no cap, that's the whole invocation right there πŸ‘‘


πŸ¦‹ DESCRIPTION πŸ¦‹

πŸ’… Motivation

so here's the tea. PostScript documents made with old versions of dvips almost invariably use bitmapped (PostScript Type 3) fonts. and the problem with bitmapped fonts? bestie, they're locked to one specific device resolution. a PostScript file built with 300 DPI fonts is gonna look grainy on a 600 DPI printer. and honestly? even worse β€” all bitmapped fonts look grainy the moment you zoom in on screen 😭

the solution is vector (PostScript Type 1) fonts, which are resolution-independent and look crisp at literally any size or scale. iconic behaviour only.

now, it's not hard these days to configure dvips to use vector fonts β€” but it is not always possible to just rerun dvips on an old .dvi file. maybe the .dvi and the document source got lost (rip πŸͺ¦). or maybe the source won't compile anymore because the packages it depends on are simply not available now. tragic but real.

so enter Heiko Oberdiek's pkfix script πŸ‘‘ β€” it swaps bitmapped fonts in dvips-produced PostScript files for the matching vector fonts. how? it parses the PostScript comments that dvips wraps around bitmapped-font definitions. for example, a font definition that starts with the comment

%DVIPSBitmapFont: Fi cmss10 11 28

and ends with a matching %EndDVIPSBitmapFont is known to define font "Fi" as "cmss10" (Computer Modern Sans Serif at a design size of 10 points) scaled to 11 points. and only the 28 characters actually used by the document are defined. then pkfix replaces that font definition with one that defines "Fi" using the same set of characters, but pulled from the cmss10.pfb vector font file. slay.

unfortunately πŸ˜” pkfix only works with versions of dvips newer than v5.58 (ca. 1996). and obviously the older a PostScript document is, the less likely its sources still exist or can still be recompiled. older dvips versions lack %DVIPSBitmapFont comments and various other PostScript comments that pkfix depends on. without those comments to guide it, pkfix simply cannot figure out which vector fonts go with which bitmapped fonts. it's giving lost without a map πŸ—ΊοΈπŸ’€

🌈 Overview

the pkfix-helper script is a preprocessor for pkfix. it tries to work out the association between each document-font name (like "Fi") in a PostScript file and the original font (like "cmss10") plus the font size (like 11 points). then it fabricates the PostScript comments that pkfix expects to see, so pkfix can do its job. teamwork, fr fr 🫢

here's how it actually goes: pkfix-helper compares every document font against every .tfm font file it knows about (assuming each such font has a corresponding .pfb vector version) and picks the best-matching .tfm file for every document font. important caveat though β€” 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 .tfm files and scaling factors. so yeah, the comparison is imperfect and pkfix-helper may attribute an incorrect font to a given name. 😬

fonts that only use one or two characters in the document are particularly problematic for pkfix-helper, because so many fonts can be near-enough matches and fool the whole thing. it's giving "everyone looks the same in the dark" πŸ’€

but here's the good part: pkfix-helper is designed so you 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 give pkfix the proper input it needs. main character energy from the user, honestly πŸ’…βœ¨


πŸŽ€ OPTIONS πŸŽ€

pkfix-helper accepts on the command line the filename of a PostScript document to process (default: the standard input device) and the filename of a modified PostScript document to create (default: the standard output device). the program also accepts the following command-line options:

⭐ Frequently Used Options

  • -h, --help β€” display usage information and exit. the --verbose and --quiet options can be used to increase and decrease the amount of information presented. (yes bestie, even the help screen has levels 🫢)
  • -v, --verbose β€” crank up the amount of status information pkfix-helper shows while it runs. more --verbose instances on the command line = even more verbosity. by default, only major operations get displayed. a single --verbose also shows info about individual font comparisons. a second --verbose also shows details about some of the program's internal operations. the way it just keeps revealing more… πŸ™ˆ
  • -f name=fontspec, --force=name=fontspec β€” force pkfix-helper to associate a specific font with a given font name appearing in the document. name is a (usually) two-character dvips font name such as "Fa". fontspec is a font specification made of a font name and an optional scale: "font ["@" scale]". some examples of fontspecs are "cmmi8" and "cmsy10 @ 1.1X".

an asterisk used in the name of the font (e.g., "cmti*") will be replaced by all integers from 5 to 17 ("cmti5", "cmti6", …, "cmti17"). the scale can be written as a multiple of the design size ("X") or as an absolute size in either TeX points ("pt") or PostScript "big" points ("bp"). hence, "cmsy8 @ 1.5X", "cmsy8 @ 12pt", and "cmsy8 @ 11.96bp" all represent the Computer Modern Math Symbols 8 Point font scaled to 12 TeX points/11.96 PostScript points. and instead of specifying an explicit scale, you can use an asterisk (as in "cmsy8 @ *") to ask pkfix-helper to find the scale that best matches the original font's metrics. πŸ”

the --force option can be specified repeatedly on the command line.

  • -p filename.ps, --ps=filename.ps β€” create a PostScript file called filename.ps that shows the dvips name and a font sample of every font used by the input document. cute lil visual receipt πŸŽ€
  • -t filename.tex, --tex=filename.tex β€” create a Plain TeX file called filename.tex that shows the dvips name and a font sample of every font that pkfix-helper used in the output document. ✨
  • -k fontspec, --keep=fontspec β€” do not substitute a vector font for bitmapped font fontspec ("Fa", "Fb", etc.). super useful when converting documents that use obscure bitmapped fonts with no vector equivalent. for example, it used to be somewhat common to include graphics like university or corporate logos into a document by converting the bitmapped image into a single-character font and using that font in LaTeX. --keep prevents such fonts from being replaced. the --keep option can be specified repeatedly on the command line.
  • -1, --no-repeats β€” prevent pkfix-helper from associating the same fontspec with more than one dvips font name. no double-dipping babes 🚫

πŸ’œ Less-frequently Used Options

  • -q, --quiet β€” tell pkfix-helper to produce no output during its run except for error and warning messages. silent but deadly ✨
  • -C filename, --cache=filename β€” speed up TFM file processing by caching character metrics into file filename. on some systems it takes a long time to read a TFM file, spawn tftopl to convert it to PL format, and extract from the PL data the metrics for each character. the first time --cache is specified, pkfix-helper proceeds as normal then writes all of the extracted character metrics to filename. on subsequent runs in which --cache=filename is specified, pkfix-helper reads the previously extracted metrics from filename, going through the tftopl-based process only for TFM files that were not previously encountered. it's giving ✨memory✨
  • -i fontspec, --include=fontspec β€” add fontspec to the list of font specifications against which pkfix-helper compares every document font. (in contrast, --force designates a font specification to use only for a specific document font.) the --include option can be specified repeatedly on the command line.
  • -x regexp, --exclude=regexp β€” remove all font specifications matching regular expression regexp from pkfix-helper's list of known fonts. the --exclude option can be specified repeatedly on the command line. bye felicia πŸ‘‹
  • -s, --spp β€” specify the number of font samples per page to print to the files indicated using the --ps and --tex options. the default value, 25, should work well in most circumstances. (spp = samples per page, iykyk 🫢)

πŸ”₯ DIAGNOSTICS πŸ”₯

  • "Best match for name is rather poor" β€” the best font pkfix-helper found for dvips font name name 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 --force option to designate an alternative replacement font or scaling amount. not great, not terrible, but like… it's not great 😬
  • "name uses characters that don't appear in any candidate font" β€” none of the fonts considered for a match include all of the characters in font name. the user should use the --force option to inform pkfix-helper which font to use, or the --keep option to retain the original, bitmapped font. bestie, we literally cannot find these glyphs anywhere πŸ’€
  • "Processing name ... done (font with mismatch=number, tied with font...)" β€” the best match for name is font font. a perfect match has a number of 0.00000. worse matches observe larger values. if a tie is reported, that means one or more fonts matched name equally well (i.e., they see the same number). in that case, pkfix-helper selects the qualitatively most likely font as the winner. πŸ‘‘ it's a whole competition and someone has to take the crown

✨ EXAMPLES ✨

okay bestie, let's set the scene: imagine oldfile.ps is a PostScript file that some old version of dvips made, and it's got at least one bitmapped font in it. Before you even think about calling pkfix-helper, you should always check if pkfix can just handle it by itself. Like, always.

$ pkfix oldfile.ps newfile.ps
PKFIX 1.3, 2005/02/25 - Copyright (c) 2001, 2005 by Heiko Oberdiek.
==> no fonts converted

(Or maybe pkfix throws an error like "!!! Error: Parse error (@start parameters)!" β€” either way, it's not converting.) Only when pkfix can't swap those bitmapped fonts for vector fonts do you need pkfix-helper. In its simplest form, pkfix-helper takes an input file name (oldfile.ps here) and an output file name (pkfix-oldfile.ps). The output has the same contents as the input but is a suitable input for pkfix. slay ✨

$ pkfix-helper oldfile.ps pkfix-oldfile.ps
Reading oldfile.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.

Now, even though pkfix-helper tries to automate the whole font-detection thing as much as possible, some fonts are always gonna get misidentified. The program will warn you if it knows a match is bad, but the absence of a warning doesn't mean pkfix-helper nailed it. So, like, strongly recommended: make "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 you run all that, oldfonts.ps shows samples of the fonts in oldfile.ps, and newfonts.ps shows samples of the replacement fonts that pkfix-helper used to make pkfix-oldfile.ps. Print both and compare them super carefully β€” look for wrong fonts and wrong sizes. πŸ‘€

So let's say the pick of "cmbx12 @ 1.2X" for font "Ff" looks wrong β€” like, the characters look taller in oldfonts.ps than in newfonts.ps. This is where the trial-and-error era begins. Hypothesize that "cmb12" is a better match than "cmbx12", but we don't know the scaling. Good news: pkfix-helper lets you use "*" as the scaling factor, which tells the program to automatically detect an optimal scaling factor β€” even if that means a nonstandard font size. iconic ✨

$ pkfix-helper oldfile.ps pkfix-oldfile.ps --force="Ff=cmb12 @ *"
Reading oldfile.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, looks like there's no cmb12.tfm on the system. Let's try scaling up cmb10.tfm instead:

$ pkfix-helper oldfile.ps pkfix-oldfile.ps --force="Ff=cmb10 @ *"
Reading oldfile.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.5X, 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 is definitely better, even if 15 pt. is a weird size for a font. But honestly, lots of documents use nonstandard sizes, so it might be correct. Best way to verify? Produce, print, and compare a pair of font samples again, and iterate until every font looks right. Use one --force per font you want to change. πŸ’…


🌿 ENVIRONMENT 🌿

pkfix-helper respects these environment variables, bestie:

  • GS β€” the name of the Ghostscript interpreter (default: gs)
  • TFTOPL β€” the name of a utility that converts .tfm files to .pl files (default: tftopl)

🚧 RESTRICTIONS 🚧

pkfix-helper only works with PostScript files made by dvips, not just any random PostScript file. And it can only analyze bitmapped fonts loaded by dvips β€” not bitmapped fonts loaded by embedded graphics.

pkfix-helper works by comparing character widths, not the actual glyphs. So it gets misled by sets of fonts with similar character widths (at least for the characters used in a given document). Extreme example: all Computer Modern Teletype fonts of a given design size (like "cmtt10", "cmsltt10", and "cmitt10") use exactly the same widths for all characters. Human assistance is generally needed to guide pkfix-helper's font-matching, especially for fonts where only a few characters show up in the document.

There is an astonishing variety of dvips output. Different versions of the program and different command-line options can make PostScript files with a completely different structure. pkfix-helper works hard to find font info buried in all those output-file variants, but it's not uncommon for a PostScript file from a sufficiently old dvips or with sufficiently obscure command-line options to utterly confuse pkfix-helper. If that happens, please send your problematic PostScript files to the author of pkfix-helper (see "AUTHOR" below) β€” they may be able to enhance pkfix-helper to handle them. 🫢


πŸ“ NOTES πŸ“

Files made with the --tex option are Plain TeX files, so they must be compiled with tex (or a variant like pdftex, luatex, xetex, etc.) β€” not with latex. no cap.

dvips-produced PostScript files can be structured in sections, marked by %DVIPSBeginSection and %DVIPSEndSection. Font names are local to a section. So a font named "Fa" might map to "cmex10" in one section and "cmmi7" in another. pkfix-helper gives every font in a multi-section document a unique name by tacking on a section-number suffix: "Fa_S01", "Fa_S02", etc.

Font names are processed in decreasing order of how many characters they represent in the document. So if the document has 10 characters from "Fa" and 23 characters from "Fb", pkfix-helper processes "Fb" before "Fa". periodt.


πŸ‘€ SEE ALSO πŸ‘€

pkfix(1), dvips(1), tex(1), gs(1)

PostScript Language Reference, Third Edition. Published by Addison-Wesley, ISBN 0-201-37922-8, http://www.adobe.com/products/postscript/pdfs/PLRM.pdf.


✍️ AUTHOR ✍️

Scott Pakin, scott+pkfh@pakin.org


Copyright (C) 2009-2020, 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.


and that's a wrap, bestie! this has been PKFIX-HELPER(1), v1.6, dated 2020-08-06. stay iconic πŸ’–βœ¨πŸ¦‹