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:
- Latin, Greek, Cyrillic and others contained in NotoSans-Regular.ttf
- Devanagari (used for Sanskrit, Hindi, Marathi, Nepali, etc.)
- Bengali (used for Bengali and Assamese)
- Gurmukhi (used for Punjabi)
- Oriya (used for Odia)
- Meetei Mayek
- Ol Chiki
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
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
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
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
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
hence you adjust
PYTHONPATH to include that dir. Both .py are originally in same directory anyway
but you’ve modified only
Renaming your font
The name and attributes of the merged font is inherited from whatever was the first in
(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:
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
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.
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”.
otfinfoto count the number of glyphs and code points.
unitettcconverts TTF to/from TTC (True Type Collection of ttfs).
pyftsubsetare CLI tools part of fonttools package which, respectively, merge fonts and create subsets of fonts.