Satish B. SettyArchiveAbout

Merging multiple Noto fonts to single TTF font

This is a tutorial-style article on how to generate a big, single font file (.ttf) which combines multiple language fonts. The reason is that Google’s Noto Fonts are mostly distributed as separate files for each language or script. In this article, I’ll describe the steps to generate a single combined TTF for most Indian languages. The steps are specific to Debian, but you can adjust it for other distros or language families.

Note that there is a technical limitation that a single font file cannot contain more than 65,535 glyphs. So you cannot apply this technique for all the fonts, but it works well for Indic languages whose combined total glyph count is far less than that.

See below for Downloads.

What is your goal?

The goal is to generate a single font file containing all these scripts:

What do you need?

If you’re on Debian/Ubuntu:

apt install python3-nototools fonttools

If you can’t do the above, you can manually clone the nototools repository. You’re going to use the merge_fonts.py script.

Fonttools is only needed if you want to change the name of the final merged font.

How to do it?

First make a copy of merge_fonts.py since you don’t have permission to edit the one in /usr:

cp /usr/lib/python3/dist-packages/nototools/merge_fonts.py /tmp/merge_fonts.py

Edit that script and adjust the files variable to contain the list of all the fonts that you want to combine:

files = [
    # It's recommended to put NotoSans-Regular.ttf as the first element in the
    # list to maximize the amount of meta data retained in the final merged font.
    "NotoSans-Regular.ttf",
    "NotoSansDevanagari-Regular.ttf",
    "NotoSansBengali-Regular.ttf",
    "NotoSansGurmukhi-Regular.ttf",
    "NotoSansGujarati-Regular.ttf",
    "NotoSansOriya-Regular.ttf",
    "NotoSansTamil-Regular.ttf",
    "NotoSansTelugu-Regular.ttf",
    "NotoSansKannada-Regular.ttf",
    "NotoSansMalayalam-Regular.ttf",
    "NotoSansSinhala-Regular.ttf",
    "NotoSansBrahmi-Regular.ttf",
    "NotoSansKaithi-Regular.ttf",
    "NotoSansLepcha-Regular.ttf",
    "NotoSansLimbu-Regular.ttf",
    "NotoSansMeeteiMayek-Regular.ttf",
    "NotoSansOlChiki-Regular.ttf",
    "NotoSansSaurashtra-Regular.ttf",
 ]

I’ve chosen only the Regular font-weight as example, but you can choose Bold fonts as well.

The names of the files must match the ones you’ve downloaded in your font directory. You can download them from GitHub NotoFonts if you’ve not done so already. Or you can invoke apt:

apt install fonts-noto-core  # or fonts-noto-hinted in older distros

which fecthes pretty much all the important fonts (except CJK and Emojis) and places them in /usr/share/fonts/truetype/noto/.

And the magic happens:

cd /usr/lib/python3/dist-packages/nototools  # whichever dir contains merge_noto.py
PYTHONPATH='.' python3 /tmp/merge_fonts.py -d /usr/share/fonts/truetype/noto/ -o /tmp/NotoSansIndic.ttf
 WARNING:fontTools.fixedTools:Table version value is a float: 1.0000; fix to use hex instead: 0x00010000
 Merging 18 Fonts...
 18 fonts are merged. 0 fonts are skipped. Cost 558.813 s.
 Please check the result at /tmp/NotoSansIndic.ttf.

The conversion process will take some time (~10 min). The combined TTF is about 1.8 MB containing about 10,100 glyphs.

The script accepts two options: -d points to the directory containing .ttf files and -o is the output file name of the merged font. The script merge_fonts.py internally calls merge_noto.py; hence you adjust PYTHONPATH to include that dir. Both .py are originally in same directory anyway but you’ve modified only merge_fonts.py.

Renaming your font

The name and attributes of the merged font is inherited from whatever was the first in files list (see above). In your case, the merged font is still called “Noto Sans Regular” – it will cause confusion after installation because you might have another font with the same name already installed as part of fonts-noto-core package. So you’ve to change the name of the generated font.

Fonttools can be used for this purpose:

apt install fonttools

It installs a tool called ttx which creates a text file from a .ttf font:

ttx /tmp/NotoSansIndic.ttf

The text file has .ttx extension and you can open it in your $EDITOR. Do a simple Find-Replace. In my case, I replaced “Noto Sans” with “Noto Sans Indic”:

sed -i "s/Noto Sans/Noto Sans Indic/g" /tmp/NotoSansIndic.ttx
sed -i "s/NotoSans/NotoSansIndic/g" /tmp/NotoSansIndic.ttx

The ttx command is smart enough to do the reverse too: throw it a .ttx file and it will generate the corresponding .ttf:

ttx /tmp/NotoSansIndic.ttx
 Compiling "/tmp/NotoSansIndic.ttx" to "/tmp/NotoSansIndic#1.ttf"...

And that’s it! The font NotoSansIndic#1.ttf is ready to be installed.

Download

I scaled the above logic to combine more than 70 fonts! You can download the merged font (Noto Indosphere ttf) here – it contains all the Brahmic scripts, including historical ones – used in India, South Asia and South East Asia; plus Nastaliq (Persian/Urdu) script, Munda languages, LGC (Latin-Greek-Cyrillic) blocks, lots of symbols, maths notation and emojis too! There are 8825 Unicode code points spanning 29727 glyphs in just ~ 6 MB. You can think of it as a “Pan-Unicode font”.

NOTE:

  1. Use otfinfo to count the number of glyphs and code points.
  2. unitettc converts TTF to/from TTC (True Type Collection of ttfs).
  3. pyftmerge and pyftsubset are CLI tools part of fonttools package which, respectively, merge fonts and create subsets of fonts.