How to customize Malayalam fonts in Linux

Now a days GNU/Linux distributions like Ubuntu, Debian, Fedora etc comes with pre-configured fonts for Malayalam. For Sans-serif family, it is Meera and  for serif, it is Rachana. If you like to change these fonts, there is no easy way to do with configuration tools in Gnome or KDE. They provide a general font selector for the whole desktop, but not for a given language.

The advantage of setting these preference at system level is, you don’t need to choose this fonts at application level then. For example, you don’t need to set them for firefox, chrome etc. All will follow the system preferences. We will use fontconfig for this

First, create a file named ~/.config/fontconfig/conf.d/50-my-malayalam.conf. If the folders for this file does not exist, just create them. To this file, add the following content.

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<!-- Malayalam (ml) -->
<match target="font">
        <test name="lang" compare="contains">
                <string>ml</string>
        </test>
        <alias>
                <family>sans-serif</family>
                <prefer>
                        <family>Manjari</family>
                </prefer>
        </alias>
</match>

<match target="font">
        <test name="lang" compare="contains">
                <string>ml</string>
        </test>
        <alias>
                <family>serif</family>
                <prefer>
                        <family>Rachana</family>
                </prefer>
        </alias>
</match>

<!-- Malayalam (ml) ends -->

</fontconfig>

Save the file and you are done. You can check if the default font for Malayalam changed or not using the following command

$ LANG=ml_IN fc-match

It should list Manjari. The above code we added to the file is not complicated. You can see that we are setting the sans-serif font preference for ml(Malayalam) language as Manjari. Also serif font preference as Rachana. You are free to change the fonts to whatever you prefer.

Note that you may want to close and open your applications to get this preference applied.

You may choose one of the fonts available at smc.org.in/fonts, download and install and use the above configuration with it.

Fontconfig language matching

I had to spend a few hours to debug a problem about fontconfig not identifiying a font for a language. Following the tradition of sharing the knowledge you acquired in hard way, let me note it down here for search engines.

The font that I am designing now has 3 style variants, thin, regular and bold. All has same family name. So if you set this family for whatever purpose, depending on context, thin, regular or bold versions will be picked up. Regular is expected by default. Also when you pick the font from font selectors, you would expect, regular being selected by default.

The problem I was facing is, instead of Regular, Bold was getting selected as default. In font selectors, Bold was listed first.

In GNU/Linux systems, this font matching and selection is done by fontconfig. I started with fc-match

$ fc-match MyFont
MyFontBold.otf: "MyFont" "Bold"

So that confirms the problem. After fiddling with os/2 properties , asking in fontconfig mailing list, and reading fontconfig documentation, I found that the lang property fontconfig calculates from Regular variant of font does not include ‘en’

$ fc-list MyFont : family : style : lang 
MyFont:style=Bold:lang=aa|ay|bi|br|ch|en|es|eu|fj|fur|gd|gl|gv|ho|ia|id|ie|io|it|mg|ml|nl|nr|nso|oc|om|pt|rm|so|sq|ss|st|sw|tl|tn|ts|uz|vo|xh|yap|zu|an|fil|ht|jv|kj|kwm|li|ms|ng|pap-an|pap-aw|rn|r
w|sc|sg|sn|su|za 
MyFont:style=Regular:lang=aa|ay|bi|br|ch|da|de|es|et|eu|fi|fj|fo|fur|fy|gl|ho|ia|id|ie|io|is|it|ki|lb|mg|ml|nb|nds|nl|nn|no|nr|nso|ny|om|rm|sma|smj|so|ss|st|sv|sw|tl|tn|ts|uz|vo|vot|xh|yap|zu|an|f
il|ht|jv|kj|kwm|li|ms|na|ng|pap-an|pap-aw|rn|rw|sc|sg|sn|su|za

I tried to find how fontconfig calculates the languages supported by a font. The minimum set of code points to be included in a font so that fontconfig declare that it supports a given language is defined in the fontconfig library. You can find them in source code. For example, mandatory code points(glyphs that match to it) to be present for English is defined in en.orth file. I cross checked each code points and one was indeed missing from my regular font variant, but bold version had everything. When I added it, all started working normally.

Later fontconfig developer Akira TAGOH told me that I can also use fc-validate to check the language coverage

$ fc-validate --lang=en MyFont.otf
MyFont.otf:0 Missing 1 glyph(s) to satisfy the coverage for en language

And after adding the missing glyph

$ fc-validate --lang=en MyFont.otf
MyFont.otf:0 Satisfy the coverage for en language

And now fc-match list Regular as default style

$ fc-match MyFont
MyFont.otf: "MyFont" "Regular"