Virtual Fonts -- a Tutorial Thomas A. Schmitz February 9, 2005 Lots of information on virtual fonts can be found on the web and in books (e.g., Knuth's very own ``Virtual Fonts: More Fun for Grand Wizards,'' available on CTAN [CTAN.info.virtual-fonts.knuth]). However, there doesn't seem to be a step-by-step tutorial for non-wizards like myself. I experimented a bit with virtual fonts during the last couple of days. It took me a while to understand the basics, so I thought that other people might find it useful to hear about this and avoid some common mistakes. Most of what I write is fairly trivial, but maybe someone can make good use of it. 1. Basic Facts about Virtual Fonts Virtual fonts can do two immensely useful things. They can remap characters within the same font. If you have a font foo with files foo.pfb and foo.tfm, you can have a virtual font foobar that will be identical to foo but print an ``A'' whenever you have a ``B'' in your \TeX-file. This may sound absurd at first, but there are cases where this is useful. Some fonts offer alternative forms for letters. With the help of a virtual font, you can remap the characters and thus switch to these alternative forms without changing your \TeX-source. The second use for virtual fonts, however, is much more common: Given a font foo, you can create a virtual font foobar that will use some characters from a second font, say bar. This is often used to include old-style numerals or additional ligatures that are not provided by the normal font. 2. Copying the font-files So let's begin. We assume that you will be using two postscript-fonts, foo and bar. Usually, for each of these fonts, you will have two files foo.tfm (bar.tfm) and foo.pfb (bar.pfb) and nothing else, so we need to create a vf-file from scratch. I didn't find it mentioned anywhere that this is not only possible, but even fairly easy. We assume that you will be performing these operations on the command line in a working directory like /tmp. So the first step would be to copy foo.tfm to this directory: cd /tmp cp PATH_TO_foo.tfm . (Watch the trailing period, it's necessary! 3. Create a Human-Oriented Property-List The file foo.tfm is a binary in a format that \TeX can read. If we want to edit it, we will have to convert it to a human-oriented property list (with extension .pl). We will be using tools that come with any complete \TeX-installation. On the command-line, do this: tftopl foo foo (yes, that's right: you have to type foo twice) 4. Open the Property-List You now have a new file foo.pl which contains all the information about the font that \TeX needs. Open it in your favorite text editor. If you're editing it in a non-UNIX environment like Windows or Mac OS X, make sure that your editor is set to use UNIX line-endings (all kinds of nasty things can happen when UNIX apps like \TeX encounter non-UNIX line-endings). The first couple of lines will read like this: (FAMILY TEX-FOO) (FACE F MRR) (CODINGSCHEME FONTSPECIFIC + TEX TEXT) (DESIGNSIZE R 10.0) (COMMENT DESIGNSIZE IS IN POINTS) (COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE) (FONTDIMEN (SLANT R 0.0) (SPACE R 0.252) (STRETCH R 0.2) (SHRINK R 0.1) (XHEIGHT R 0.459) (QUAD R 1.0) (EXTRASPACE R 0.111) ) (LIGTABLE etc. If there is a line (CHECKSUM O ...), delete it (it will be regenerated later). 5. Editing the Property-List In order to generate a virtual font, you need to modify this file. First, you will have to tell \TeX which fonts this virtual font will be referring to. Let's say they're foo.tfm and bar.tfm (needless to say, both have to be installed and functional in your \TeX-installation). In a first step, we will create a virtual font that will remap some characters within foo. So just before the line starting with (LIGTABLE, add this: (MAPFONT D 0 (FONTNAME foo) (FONTDSIZE R 10.0) ) The FONTDSIZE of foo could be found in the first lines (DESIGNSIZE R 10.0), so all you have to do is copy this information. 6. Remapping a Character If you scroll down in this file, the LIGTABLE (containing information about ligatures and kerning) will end with two lines (STOP) ) After this, the section with information about all the defined characters in the font will follow, probably starting something like this: (CHARACTER O 0 (CHARWD R 0.674) (CHARHT R 0.726) ) \TeX only cares about the dimensions of every character and puts an empty box with these dimensions into the .dvi-file. It is only when this .dvi is interpreted by a postscript- or pdf-driver that the actual character (the ``glyph'') is put into this box. So let us assume you want to have a virtual font that will always print ``A'' when you have ``B'' in your source. Scroll further down until you reach the section with the capital letters: (CHARACTER C A (CHARWD R 0.747) (CHARHT R 0.747) ) (CHARACTER C B (CHARWD R 0.739) (CHARHT R 0.726) ) \TeX will be using the box described here, so you want the box for ``B'' to be of the same size as the box for ``A.'' Hence, the first thing you need to do is copy the dimensions of ``A'' into ``B.'' So the section should look like this: (CHARACTER C A (CHARWD R 0.747) (CHARHT R 0.747) ) (CHARACTER C B (CHARWD R 0.747) (CHARHT R 0.747) ) Next (and this is the magic of virtual fonts) you will tell \TeX that it should remap ``B'' to ``A.'' Just before the closing parenthesis of CHARACTER B, you will insert a new section. Now ``B'' will look like this: (CHARACTER C B (CHARWD R 0.747) (CHARHT R 0.747) (MAP (SETCHAR C A) ) ) One of the things that can be a bit confusing about these property lists is the fact that (apart from the numbers and the 26 letters of the alphabet) characters are referred to by ``octal numbers.'' If you want to know what character corresponds to what octal number, you can have a look at the tables created by testing the font (section 9). 7. Saving the File That's it! You have modified the font description; now you need to generate the binary files for \TeX to use. The next step is extremely important: SAVE THE FILE TO A DIFFERENT NAME! So in our case, let's say we call the new virtual font foobar (the name doesn't matter; the extension has to be .vpl); so save to foobar.vpl 8. Generating the Binaries Back to the command line. We now run a little program that will convert your foobar.vpl into two new files: foobar.tfm and foobar.vf. vptovf foobar.vpl This will not only do the conversion, it will also check whether you .vpl-file is in good order. It is very picky about the right indentation level and parentheses, and it will tell you exactly in which line there is a problem. So if you get errors, just go back and edit foobar.vpl again. vptovf may also tell you that it had to ``round some units,'' that's OK. 9. Installing the New Font So now you should have foobar.vf and foobar.tfm. Copy both files into the right places. I would suggest you create your own texmf-branch in your home directory, under ~/texmf or ~/Library/texmf (depending on your local setup as defined in texmf.cnf). So the files should go here: cp foobar.tfm ~/texmf/fonts/tfm/ cp foobar.vf ~/texmf/fonts/vf/ (you will have to create these directories if they don't exist yet). Since this virtual font will only be seen by \TeX, you don't need to fiddle with any map file; for the postscript- or pdf-driver, only font foo will exist, which was already functional. Before you embark on a long journey with this new virtual font (say your 1200-page thesis that is due in two weeks), I would suggest you test it in a nice quiet little directory on your box. cd to this directory and then do this: cd ~ pdfetex testfont pdfetex will respond to this command like so: This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.3) \write18 enabled. entering extended mode (/usr/local/teTeX/share/texmf.tetex/tex/plain/base/testfont.tex Name of the font to test = You type foobar pdfetex will respond: Now type a test command (\help for help):) * you type: \table pdfetex will open a new line with another asterisk, and you type \end If all goes well, a file testfont.pdf will be created, with a table showing that font foobar does not have a letter ``B,'' but twice the letter ``A''---which is just what we wanted. If your \TeX-installation includes \CONTEXT, a macro package for \TeX (see http://tug.org/pracjourn/2005-1/asknelly/), you can also create a very nice colorized table. Create a file test.tex with this content: \starttext \showfont[foobar] \stoptext Then, run this file through \CONTEXT: texexec --nonstopmode --pdf test.tex You'll get a table with all the glyphs; every cell will indicate the decimal, hexadecimal, and octal value of the glyph (very handy for editing property lists). 10. Adding a Second Font Now let's assume you want to include further stuff, like old-style numerals or ligatures from font bar. We go back to our working directory and delete the old file foobar.vpl. Don't worry, we'll create it again: rm foobar.vpl vftovp foobar foobar foobar The reason we do this is that vftovp will automagically include one important piece of information: every character description will now look like this: (CHARACTER C A (CHARWD R 0.747) (CHARHT R 0.747) (MAP (SETCHAR C A) ) ) That's already not bad, but if we want to mix glyphs from two fonts, we will have to say which font to use at every instance. So in your editor, you should perform a ``find and replace'' that will find every instance of (MAP and replace it with (MAP (SELECTFONT D 0) In emacs, it is possible to include the line break in the replace pattern, I don't know if (and how) other editors can handle it. Now add the information about the second font, just as described in section 5: (MAPFONT D 1 (FONTNAME bar) (FONTDSIZE R 10.0) ) If you want to know the DSIZE of bar, just convert bar.tfm into bar.pl, open this file and look into the first lines (we'll need bar.pl anyway). Or, if you want to be fancy, you could even do this: tftopl `kpsewhich bar.tfm` | grep DESIGNSIZE (watch the ``backticks,'' those are single opening quotes!). (CHARACTER C 0 (CHARWD R 0.514) (CHARHT R 0.628) (CHARDP R 0.1) (MAP (SELECTFONT D 0) (SETCHAR C 0) ) ) 11. Including Glyphs from a Second Font Now look for the section containing the numerals. It should start like this: (CHARACTER C 0 (CHARWD R 0.514) (CHARHT R 0.628) (CHARDP R 0.1) (MAP (SELECTFONT D 0) (SETCHAR C 0) ) ) Again, the first thing you should do is copy the dimensions of CHARACTER C 0 from bar.pl to foo.pl. Then replace (SELECTFONT D 0) with (SELECTFONT D 1), and everything should work: After you have done this for all the numerals, generated the tfm/vf pair (section 8) and copied these files to the right directories (section 9), \TeX will look at the tfm/vf pair, and will take the numerals from font bar, everything else from font foo. Again, test to see if this works as expected. 12. Post-Install After you have edited your virtual font, you can discard the .vpl-file. If you ever want to edit your font again, you can recreate it by copying both the .vf and the .tfm into the same directory and running vftovp foobar foobar foobar Have great fun and feel like a grand wizard! 13. Further Reading http://www.cl.cam.ac.uk/users/rf/pstex/index.htm http://homepage.mac.com/bkerstetter/tex/fonttutorial-current.html http://zoonek.free.fr/LaTeX/Fontes/fontes.html (in French)