TTF2TFM(1)

πŸŽ€ TTF2TFM(1) πŸŽ€

ttf2tfm(1), General Commands Manual, which is the same page you'd find under TTF2TFM(1) πŸ’–

✨ NAME ✨

ttf2tfm β€” build TeX metric files from a TrueType font 🧚

πŸ“œ SYNOPSIS πŸ“œ

ttf2tfm ttffile[.ttf|.ttc] [-c caps-height-factor] [-e extension-factor]
        [-E encoding-id] [-f font-index] [-l] [-L ligature-file[.sfd]]
        [-n] [-N] [-O] [-p inencfile[.enc]] [-P platform-id] [-q]
        [-r old-glyphname new-glyphname] [-R replacement-file[.rpl]]
        [-s slant-factor] [-t outencfile[.enc]] [-T inoutencfile[.enc]]
        [-u] [-v vplfile[.vpl]] [-V scvplfile[.vpl]] [-w] [-x]
        [-y vertical-shift-factor] [tfmfile[.tfm]]
ttf2tfm --version | --help

πŸ’– DESCRIPTION πŸ’–

okay so this program digs into a TrueType font, pulls out all the metric and kerning info, and turns it into metric files that TeX can actually use πŸ¦‹ it's basically a cousin of afm2tfm (which lives in the dvips package), so if you want the nitty gritty on the different parameters, especially encoding files, go check out its info files πŸ€“

okay but here's the tea: a TrueType font usually has way more than 256 glyphs, so you need a way to map a subset of them onto a TeX font 🫢 that's where two mapping tables come in. The first one, called the input or raw encoding, maps the TrueType font to a raw TeX font (ttf2tfm AND ttf2pk both use this one ✨). The second one, called the output or virtual encoding, maps that raw TeX font to a virtual TeX font and handles all the kerning and ligature info TeX needs πŸ’…

this two-stage mapping is lowkey genius because one raw font can be accessed with different LaTeX encodings (like T1 and OT1) through the virtual font mechanism, and you only need ONE PK file 🌈

for CJKV (Chinese/Japanese/Korean/old Vietnamese) fonts there's a whole different mechanism πŸ‘‘ see SUBFONT DEFINITION FILES below for that one 🌸

πŸŽ€ PARAMETERS πŸŽ€

most of the command line switch names match afm2tfm, just for convenience πŸ“ you NEED one or more space characters between an option and its value, and options can't be mashed together πŸ™ˆ also, for historical reasons, the first parameter can't be a switch. it has to be the font name πŸ’œ

  • -c caps-height-factor β€” this sets how tall the small caps made with the -V switch are πŸ“ the default is this real number, 0.8 times the height of uppercase glyphs.
    • Ignored in subfont mode.
  • -e extension-factor β€” stretches the characters horizontally πŸ¦‹ default is this real number, 1.0. go below 1.0 and you get a condensed font 😭
  • -E encoding-id β€” the TrueType encoding ID πŸ”₯ default is this non-negative integer, 1.
    • Ignored if -N is used.
  • -f font-index β€” picks the font index inside a TrueType Collection 🧚 default is the first font, index 0. (TrueType collections are usually found in some CJK fonts. For example, the first font index specifies glyphs and metrics for horizontal writing, and the second font index does the same for vertical writing. TrueType collections usually have the extension .ttc.)
    • Ignored for ordinary TrueType fonts.
  • -l β€” creates ligatures in subfonts between the first and second bytes of all the original character codes ✨ for example, character code 0xABCD maps to character position 123 in subfont 45. Then a ligature in subfont 45 between position 0xAB and 0xCD pointing to character 123 gets produced. The Korean HLaTeX package fonts use this feature πŸ‡°πŸ‡· heads up though: this only makes correct ligatures for TrueType fonts where the input cmap is identical to the output encoding. For HLaTeX, the TTFs must have platform ID 3 and encoding ID 5 πŸ’€
    • Ignored if not in subfont mode.
  • -L ligature-file β€” same vibe as -l, but now the character codes for ligatures come from ligature-file πŸ’… for example, -L KS-HLaTeX makes correct ligatures for the Korean HLaTeX package no matter what platform and encoding ID your TrueType font uses (the file KS-HLaTeX.sfd is part of the ttf2pk package 🫢).
    • Ligature files have the same format and extension as SFD files.
    • Ignored if not in subfont mode.
  • -n β€” uses the PS names of the glyphs in the TrueType font 🌷 only glyphs with a valid entry in the selected cmap get used.
    • Ignored in subfont mode.
  • -N β€” uses ONLY the PS names of the TrueType font πŸ™… no cmap gets used, so -E and -P do absolutely nothing and you'll get a warning message about it ⚠️
    • Ignored in subfont mode.
  • -O β€” uses octal values for all character codes in the VPL file instead of names πŸ”’ this is super useful for symbol or CJK fonts, where names like A are meaningless πŸ™ˆ
  • -p inencfile β€” the input encoding file name for the TTFβ†’raw TeX mapping πŸ—ΊοΈ this has to be specified in a map file (default: ttfonts.map) that's recorded in ttf2pk.cfg for successive ttf2pk calls.
    • Ignored in subfont mode.
  • -P platform-id β€” the TrueType platform ID πŸ’œ default is this non-negative integer, 3.
    • Ignored if -N is used.
  • -q β€” makes ttf2tfm quiet 🀫 it suppresses all informational output except warning and error messages. For CJK fonts the output can get HUGE if you don't use this switch, so honestly, use it 😭

✨ CMAPS ✨

okay so, unlike Type 1 PostScript fonts (but lowkey similar to the new CID PostScript font format 🫢), most TrueType fonts have more than one native mapping table, also called cmap πŸ—ΊοΈ. These tables map the (internal) TTF glyph indices to the (external) TTF character codes. The common ones are a mapping table to Unicode encoded character positions, and the standard Macintosh mapping. It's giving multiple personalities πŸ’…

To pick a TrueType mapping table, use -P and -E πŸŽ€. With -P you choose the platform ID. The defined values are:

platform        platform ID (pid)
──────────────────────────────────
Apple Unicode   0
Macintosh       1
ISO             2
Microsoft       3

The encoding ID depends on the platform 🌸. For pid=0, we ignore the -E parameter (it gets set to zero) because that mapping table is always Unicode version 2.0. For pid=1, here's the list of defined values:

platform ID = 1
script          encoding ID (eid)
──────────────────────────────────
Roman           0
Japanese        1
Chinese         2
Korean          3
Arabic          4
Hebrew          5
Greek           6
Russian         7
Roman Symbol    8
Devanagari      9
Gurmukhi        10
Gujarati        11
Oriya           12
Bengali         13
Tamil           14
Telugu          15
Kannada         16
Malayalam       17
Sinhalese       18
Burmese         19
Khmer           20
Thai            21
Laotian         22
Georgian        23
Armenian        24
Maldivian       25
Tibetan         26
Mongolian       27
Geez            28
Slavic          29
Vietnamese      30
Sindhi          31
Uninterpreted   32

Here are the ISO encoding IDs 🧚:

platform ID = 2
encoding     encoding ID (eid)
ASCII        0
ISO 10646    1
ISO 8859-1   2

And last but not least, the Microsoft encoding IDs πŸ’œ:

platform ID = 3
encoding              encoding ID (eid)
Symbol                0
Unicode 2.0           1
Shift JIS             2
GB 2312 (1980)        3
Big 5                 4
KS X 1001 (Wansung)   5
KS X 1001 (Johab)     6
UCS-4                 10
⚠️ bestie, the program will abort if you give it an invalid platform/encoding ID pair. It'll then show you the possible pid/eid pairs 😭

Also, most fonts have at most two or three cmaps, usually matching the pid/eid pairs (1,0), (3,0), or (3,1) for Latin based fonts 🌈. Valid Microsoft fonts should have a (3,1) mapping table, but some fonts (mostly Asian ones) have a (3,1) cmap that isn't encoded in Unicode πŸ™ˆ. The reason for this chaos is that some old MS Windows versions will reject any font with a non-(3,1) cmap, since all the non-Unicode Microsoft encoding IDs are meant for Asian MS Windows versions.

The -P and -E options of ttf2tfm need to be specified the same way for ttf2pk 🫢. In a map file, the matching parameters are called Pid and Eid, respectively.

The default pid/eid pair is (3,1) ✨.

Similarly, an -f option has to be written as the Fontindex parameter in a map file πŸ“.

If you use the -N switch, all cmaps get ignored, and it only uses the PostScript names in the TrueType font. The map file equivalent is PS=Only. If you use the -n switch, the default glyph names built into ttf2tfm get replaced with the PS glyph names found in the font. Honestly this is often not what you want, because the glyph names inside the font are frequently incorrect or non-standard πŸ’€. The map file equivalent for this one is PS=Yes.

Single replacement glyph names given with -r must be written directly as old-glyphname new-glyphname in a map file. -R does the same job as the Replacement option πŸ¦‹.


✨ INPUT AND OUTPUT ENCODINGS ✨

Okay so you have to specify the encoding vectors from the TrueType font to the raw TeX font, and from the raw TeX font to the virtual TeX font, exactly like with afm2tfm. BUT you get way more options for addressing character codes πŸ‘‘. (Quick reminder: an "encoding vector" is a mapping table with 256 entries in the form of a PostScript vector. Check out the file T1-WGL4.enc in this package for an example πŸ“–.)

With afm2tfm, you had to access each glyph by its Adobe glyph name, like /quotedsingle or /Acircumflex. ttf2tfm leveled that up πŸ”₯. Now you can (and sometimes must) access the code points and/or glyphs directly, using the following syntax for the character position in decimal, octal, or hexadecimal notation:

/.c<decimal-number>, /.c0<octal-number>, or /.c0x<hexadecimal-number>

Examples: /.c72, /.c0646, /.c0x48. If you want to access a glyph index directly instead, swap the c for a g in that notation. Example: /.g0x32 πŸ¦‹.

πŸ’€ [Note: the .cXXX notation makes no sense if you use -N.]

For the pid/eid pairs (1,0) and (3,1), both ttf2tfm and ttf2pk recognize built-in default Adobe glyph names 🌸. The first follows the names from Appendix E of the book Inside Macintosh, volume 6, while the second uses the names from the TrueType Specification (WGL4, a Unicode subset). Be warned that Adobe names for a given glyph aren't always unique, and sometimes they differ 😭. For example, many PS fonts have the glyph mu, but in the WGL4 character set this glyph is called mu1 so it can be told apart from the real Greek letter mu. Also, OpenType (aka TrueType 2.0) fonts use an updated WGL4 table, and we use the data from the latest published TrueType specification (1.66) 🧚. You can find those mapping tables in the source code file ttfenc.c.

On the flip side, the switches -n and -N make ttf2tfm read and use the PostScript names stored in the font's own post table, instead of the default Adobe glyph names πŸ’œ.

Use the -r switch to remap single glyph names, and -R to point at a file containing replacement glyph name pairs πŸŽ€.

If you don't pick an input encoding, the first 256 glyphs of the TrueType font that have a valid entry in the selected cmap get mapped to the TeX raw font. (Without the -q option, ttf2tfm prints this mapping table to standard output πŸ‘€.) After those, you get all the glyphs not yet addressed in the selected cmap. BUT some code points for the (1,0) pid/eid pair are skipped, since they don't represent glyphs useful for TeX: 0x00 (null), 0x08 (backspace), 0x09 (horizontal tabulation), 0x0d (carriage return), and 0x1d (group separator) πŸ™…β€β™€οΈ. The invalid character with glyph index 0 gets skipped too.

If you select the -N switch, the first 256 glyphs of the TrueType font with a valid PostScript name get used when no input encoding is specified. Again, a few glyphs get left out: .notdef, .null, and nonmarkingreturn πŸ™ˆ.

If you don't select an output encoding, ttf2tfm uses the same mapping table afm2tfm would use (you can find it in the source code file texenc.c). It corresponds to TeX typewriter text ⌨️. Unused positions, either caused by empty code points in the mapping table or missing glyphs in the TrueType font, get filled (rather arbitrarily 🎲) with characters that are present in the input encoding but not specified in the output encoding. (Without the -q option, ttf2tfm prints the final output encoding to standard output.) If you only want glyphs in the virtual font that are defined in the output encoding file, and nothing more, use the -u option πŸ’….

Here's a feature afm2tfm was missing, which LaTeX's T1 encoding needs 🌈. ttf2tfm will construct the glyph Germandbls (by simply concatenating two S glyphs) even for normal fonts, if possible. It shows up in the glyph list as the last item, marked with an asterisk. Since it isn't a real glyph, it's only available in the virtual font ✨.

For both input and output encodings, an empty code position is represented by the glyph name /.notdef 🫢.

In encoding files, you can put \ as the final character of a line to say the input continues on the next line. The backslash and the following newline character get removed πŸŽ€.

✨ SUBFONT DEFINITION FILES ✨

okay so CJKV fonts (Chinese/Japanese/Korean/old Vietnamese) are absolutely massive 😭 they usually have several thousand glyphs, and TeX can't just swallow all of that in one go. so you have to split them into subfonts. Subfont definition files (usually ending in .sfd) are the smooth little helper that makes this happen πŸ’–

A subfont file name is usually made of a prefix, a subfont infix, and a postfix (which is empty most of the time) 🌸

ntukai23 β†’ prefix: ntukai, infix: 23, postfix: (empty)

Here's the syntax for one line in an SFD file, which describes one subfont πŸŽ€

<whitespace> <infix> <whitespace> <ranges> <whitespace>

<infix> is anything except whitespace. ngl, it's best to stick with alphanumeric characters 🫢

<whitespace> means a space, formfeed, carriage return, horizontal tabs, or vertical tabs. No newline characters, bestie, those are not allowed here πŸ™ˆ

<ranges> can be built in three ways:

<ranges> <whitespace> <codepoint> |
<ranges> <whitespace> <range> |
<ranges> <whitespace> <offset> <whitespace> <range>

<codepoint> is just a <number> 🧚

<range> is a <number>, then a `_' (underscore), then another <number> ✨

<offset> is a <number> followed by a `:' (colon) πŸ¦‹

<number> can be hexadecimal (with the prefix `0x'), decimal, or octal (with the prefix `0') πŸ”₯

You can continue a line onto the next one by ending it with a backslash πŸ’… The ranges must not overlap, and offsets have to fall in the range 0-255. no cap, that's a hard rule 😭

Example time 🌈 The line

03   10: 0x2349 0x2345_0x2347

assigns code positions 10, 11, 12, and 13 of the subfont with infix 03 to the character codes 0x2349, 0x2345, 0x2346, and 0x2347, in that order. The offset gets you to position 10, and the range fills in the rest πŸ“

The SFD files that come with the distribution are customized for the CJK package for LaTeX, so they're already set up for that πŸ’œ

To actually use an SFD file, you embed its name in the TFM font name, at the spot where the infix would show up. You wrap that name in two @ signs. You can do this on the command line or in a map file. Once you do, both ttf2tfm and ttf2pk switch into subfont mode πŸ‘‘

You can also use more than one SFD file, as long as you separate them with commas and no whitespace. For any given subfont, the first file gets scanned for an entry, then the next file, and so on. Later entries override earlier ones, and sometimes only partially 😌 For example, the first SFD file sets up the range 0x10-0xA0, and the next one changes entries 0x12 and 0x25. Adding and replacing works this way, but removing entries doesn't πŸ™ˆ

Subfont mode switches off a bunch of ttf2tfm options: -n, -N, -p, -r, -R, -t, -T, -u, -v, -V, and -w. Similarly, a map file isn't allowed to have an Encoding or Replacement parameter in this mode. Single replacement glyph names get ignored too, so don't count on them πŸ’€

When it's in subfont mode, ttf2tfm creates every subfont TFM file that the SFD files specify (as long as the subfont actually has glyphs in it) all in one run πŸŽ€

Example: the call

ttf2tfm ntukai.ttf ntukai@Big5,Big5-supp@

uses Big5.sfd and Big5-supp.sfd, and produces all the subfont files ntukai01.tfm, ntukai02.tfm, and so on πŸ¦‹


✨ RETURN VALUE ✨

ttf2tfm returns 0 on success and 1 on error. Warning and error messages get written to standard error, so if something goes sideways, that's where you'll find the tea 🍡


✨ SOME NOTES ON FILE SEARCHING ✨

Both ttf2pk and ttf2tfm search for files using either the kpathsea, emtexdir, or MiKTeX library. Quick heads-up: emtexdir only works on operating systems with an MS-DOSish background, meaning MS-DOS, OS/2, and Windows. MikTeX is specific to MS Windows πŸͺŸ

As a last resort, both programs can be compiled without any search library at all. In that case, the files you want have to be in the current directory, or you have to give them a path. Default extensions still get appended, with one exception: only .ttf gets appended, not .ttc 🫢

kpathsea

You can check the exact version of kpathsea on screen by calling either ttf2pk or ttf2tfm with the --version command line switch 🌸

Here's the lowdown on which file types go with which kpathsea variables. TTF2PKINPUTS and TTF2TFMINPUTS are program-specific environment variables that were introduced in kpathsea version 3.2:

  • .ttf and .ttc β€” TTFONTS
  • ttf2pk.cfg β€” TTF2PKINPUTS
  • .map β€” TTF2PKINPUTS
  • .enc β€” TTF2PKINPUTS, TTF2TFMINPUTS
  • .rpl β€” TTF2PKINPUTS, TTF2TFMINPUTS
  • .tfm β€” TFMFONTS
  • .sfd β€” TTF2PKINPUTS, TTF2TFMINPUTS

For the full details on these variables, go check the info files of kpathsea πŸ“š

You should set the TEXMFCNF variable to the directory where your texmf.cnf configuration file lives 🏑

Want to find out what value a kpathsea variable is set to? Use this command. We're using TTFONTS as the example here πŸ‘€

kpsewhich -progname=ttf2tfm -expand-var='$TTFONTS'

This is super handy if a variable isn't set in texmf.cnf or in your environment, because then it points to the default value that's hard-coded into the kpathsea library πŸ’…

We also pass the program name because you can set variables that only get searched for one specific program. In our example, that's TTFONTS.ttf2tfm 🧚

There's a similar-but-not-identical method too:

kpsewhich -progname=ttf2tfm -show-path='truetype fonts'

[Want the full list of format types? Just run kpsewhich --help on the command line πŸ’–] This is exactly how ttf2tfm (and ttf2pk) search for files. The downside is that every variable gets expanded, which can make for some very long strings 😭

emtexdir

Here's the list of suffixes and their environment variables. You set these in autoexec.bat, or in config.sys for OS/2 πŸͺ„

  • .ttf and .ttc β€” TTFONTS
  • ttf2pk.cfg β€” TTFCFG
  • .map β€” TTFCFG
  • .enc β€” TTFCFG
  • .rpl β€” TTFCFG
  • .tfm β€” TEXTFM
  • .sfd β€” TTFCFG

If one of these variables isn't set, you'll get a warning message. The current directory is always searched 🏠 One exclamation mark added to a directory path means subdirectories one level deep get searched. Two exclamation marks mean all subdirectories get searched πŸ” Example:

TTFONTS=c:\fonts\truetype!!;d:\myfonts\truetype!
Constructions like c:\fonts!!\truetype aren't possible, so don't even try it πŸ™ˆ

MiKTeX

Both ttf2tfm and ttf2pk have been fully integrated into MiKTeX πŸŽ‰ For more on how file searching works there, check out the MiKTeX documentation πŸ“–


✨ PROBLEMS ✨

Okay, this one's a little annoying 😩 Many vptovf implementations only allow 100 bytes for the TFM header, even though the TFM file format itself allows 1024. Here's how that 100 gets spent: 8 bytes for checksum and design size, 40 bytes for the family name, 20 bytes for the encoding, and 4 bytes for a face byte. That leaves only 28 bytes for extra info. ttf2tfm uses that space for an identification string, which is basically a copy of the command line, and that limit is always exceeded πŸ’€

The best fix is to increase the value of max_header_bytes in the file vptovf.web (and probably pltotf.web too) to, say, 400. Then recompile vptovf (and pltotf) πŸ› οΈ

If you don't do that, you'll see some harmless error messages like this:

This HEADER index is too big for my present table size

Those can be safely ignored 🫢


✨ SEE ALSO ✨

ttf2pk(1), afm2tfm(1), vptovf(1), and the info pages for dvips and kpathsea πŸ“šπŸŒˆ


✨ AVAILABILITY ✨

ttf2tfm is part of the FreeType 1 package, which is a high quality TrueType rendering library πŸ¦‹


✨ AUTHORS ✨

  • Werner LEMBERG <wl@gnu.org>
  • FrΓ©dΓ©ric LOYER <loyer@ensta.fr>

And that's a wrap, bestie πŸŽ€βœ¨ This page came from FreeType2 version (the 27-Jun-2013 release), and you're officially a TTF2TFM expert now. we love to see it πŸ’…πŸ‘‘πŸ©·