howto change font in linux using fontconfig

Updated: Apr 22, 2023

To those who are not familier to fontconfig, it is the library which provides fonts to each program in your linux desktop (atleast in gnome3). It maintains the details about all the font files available in your linux box and provides best matched font when your program requests a specific type of font.

If you use only english in day-to-day activities, fontconfig dont come in your way, but its a nightmare if you are a multilingual user. Even if you are a multilingual user, fontconfig tries its best to make your life easy by matching the best font for your language automatically, but the pain starts if you don’t like what fontconfig provides and want to change the default font for your language to something which looks good in the editor.

I went through the pain and want to share what I did to fix. For me, fontconfig said TAMu_Kadambari is the best font for Tamil and gedit by default shows tamil fonts using TAMu_Kadambari. But, this font doesn’t look good in gedit. After much research, I’m able to change the default font for Tamil language from TAMu_Kadambari to TAMu_Kalyani using this xml file.

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!--save this file as ~/.config/fontconfig/fonts.conf-->
<fontconfig>
 <match>
  <test name="lang">
   <string>ta</string>
  </test>
  <edit name="family" mode="assign">
   <string>TAMu_Kalyani</string>
  </edit>
 </match>
</fontconfig>

Here, the <match> tag contains one test which checks if the provided language is Tamil (lang=ta). If it is, then edit the original request coming from the application and assign family name as TAMu_Kalyani (family=TAMu_Kalyani) so that fontconfig matching algorithm will match only TAMu_Kalyani.

Thats it, my gedit now picks TAMu_Kalyani and it looks good. More details about fontconfig is available here.

fontconfig uses patterns for its matching algorithm, and it goes like this

<families>-<point sizes>:<name1>=<values1>:<name2>=<values2>..

for example, here is how you can check which is the best matched font available in your system for language Tamil. Output also contains top 10 ranked fonts for tamil. The first preferred font is TAMu_Kalyani, because I have overridden in ~/.config/fontconfig/fonts.conf

[mohan@mohanlaptop0 ~]$ fc-match -s 'monospace-10:lang=ta' | head
TAMu_Kalyani.ttf: "TAMu_Kalyani" "Regular"
TSCu_Comic.ttf: "TSCu_Comic" "Normal"
DejaVuSans.ttf: "DejaVu Sans" "Book"
DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
DejaVuSerif.ttf: "DejaVu Serif" "Book"
Pothana2000.ttf: "Pothana2000" "Pothana2000"
MalOtf.ttf: "MalOtf" "Book"
TSCu_Paranar.ttf: "TSCu_Paranar" "Regular"
SyrCOMAdiabene.otf: "East Syriac Adiabene" "Regular"
SyrCOMKharput.otf: "Serto Kharput" "Regular"
[mohan@mohanlaptop0 ~]$

If I remove ~/.config/fontconfig/fonts.conf, it goes back to the original behaviour and provides TAMu_Kadambari as preferred font for Tamil

[mohan@mohanlaptop0 ~]$ fc-match -s 'monospace-10:lang=ta' | head
TAMu_Kadampari.ttf: "TAMu_Kadambri" "Regular"
TAMu_Kalyani.ttf: "TAMu_Kalyani" "Regular"
DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
DejaVuSansMono-Bold.ttf: "DejaVu Sans Mono" "Bold"
DejaVuSans.ttf: "DejaVu Sans" "Book"
DejaVuSerif.ttf: "DejaVu Serif" "Book"
Pothana2000.ttf: "Pothana2000" "Pothana2000"
MalOtf.ttf: "MalOtf" "Book"
TSCu_Comic.ttf: "TSCu_Comic" "Normal"
TSCu_Paranar.ttf: "TSCu_Paranar" "Regular"
[mohan@mohanlaptop0 ~]$

fontconfig configuration files are very versatile and one can do lot of things, but we need to first understand its patterns to do anything useful. Anyway, I hope this article provide good example for fc-match command-line tool and fontconfig patterns.