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-Vswitch 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
-Nis used.
- Ignored if
-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 code0xABCDmaps to character position 123 in subfont 45. Then a ligature in subfont 45 between position0xABand0xCDpointing 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-HLaTeXmakes 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-Eand-Pdo 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 likeAare 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 inttf2pk.cfgfor successive ttf2pk calls.- Ignored in subfont mode.
-P platform-idβ the TrueType platform ID π default is this non-negative integer, 3.- Ignored if
-Nis used.
- Ignored if
-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.cXXXnotation 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 anEncodingorReplacementparameter 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:
.ttfand.ttcβTTFONTSttf2pk.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 πͺ
.ttfand.ttcβTTFONTSttf2pk.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 π ππ©·
π¦ where this page comes from
- arch rolling: texlive-doc 2026.1-1 Β· GPL
- debian bookworm: texlive-binaries 2022.20220321.62855-5.1+deb12u2
- debian trixie: texlive-binaries 2024.20240313.70630+ds-6 Β· TeX-Live
- epel 10: texlive-ttfutils 13:20240311-10.el10_3 Β· LPPL-1.3c
- epel 9: texlive-ttfutils 9:20200406-38.el9 Β· LPPL
- fedora 43: texlive-ttfutils 11:svn66186-93.fc43 Β· LPPL-1.3c
- fedora 43: texlive-ttfutils 11:svn66186-95.fc43.1 Β· LPPL-1.3c
- fedora 44: texlive-ttfutils 12:svn77830-105.fc44 Β· LPPL-1.3c
- fedora 44: texlive-ttfutils 12:svn77830-111.fc44 Β· LPPL-1.3c
- opensuse-leap 16.0: texlive-ttfutils-doc 2025.221.svn73908-160000.3.1 Β· LPPL-1.0
- ubuntu jammy: texlive-binaries 2021.20210626.59705-1build1
- ubuntu jammy: texlive-binaries 2021.20210626.59705-1ubuntu0.3
- ubuntu noble: texlive-binaries 2023.20230311.66589-9build3 Β· TeX-Live
- ubuntu questing: texlive-binaries 2024.20240313.70630+ds-6ubuntu2 Β· TeX-Live
- ubuntu resolute: texlive-binaries 2025.20250727.75242+ds-5build1 Β· TeX-Live
- ubuntu stonking: texlive-binaries 2026.20260303.78225+ds-5ubuntu1 Β· TeX-Live
- π girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms