11
votes

I'm using a custom font in my Android project. For some reason when the text includes the letters IJ together, it gives me the following glyph:

enter image description here

This appears to be the glyph located at \uE2C5 of the PUA region of the font.

The individual I and J glyphs both exist in the font and I can get them to appear if I set the text to I J.

enter image description here

It's not an OpenType font (I don't think Android even supports OpenType rendering in custom fonts), so there shouldn't be anything like this happening. What is going on here?

The problem is reproducible with the following simple project:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = (TextView) findViewById(R.id.textview);
        Typeface tf = Typeface.createFromAsset(this.getAssets(), "MenksoftHawang.ttf");
        textView.setTypeface(tf);

        textView.setText("IJ");
    }
}

The font can be downloaded from here. Put it in the assets folder in the project.

3

3 Answers

9
votes

I can't really speak to the reason that you are seeing what you are seeing, but the letter combination of "IJ" seems to have a history of special treatment. From the Wikipedia page on Typographic ligature.

Dutch ij, however, is somewhat more ambiguous. Depending on the standard used, it can be considered a digraph, a ligature or a letter in itself, and its upper case and lower case forms are often available as a single glyph with a distinctive ligature in several professional fonts (e.g. Zapfino). Sans serif uppercase IJ glyphs, popular in the Netherlands, typically use a ligature resembling a U with a broken left-hand stroke.

Also from Wikipedia:

Glyph substitution and composition

Some compatibility characters are completely dispensable for text processing and display software that conforms to the Unicode standard. These include:

Ligatures Ligatures such as ‘ffi’ in the Latin script were often encoded as a separate character in legacy character sets. Unicode’s approach to ligatures is to treat them as rich text and, if turned on, handled through glyph substitution.

Given this, my guess is that the font you are using has taken advantage of this type of usage to do its own thing.

Update Using setFontFeatureSettings() works to disable the display of the glyph as shown in the following code. Unfortunately, this is only available in API 21+. There is a caveat that there may be other side effects that you may be become aware of.

For APIs below 21, you can use a font editing program such as FontForge and delete the glyph at U+E2C5. I have done this and it does eliminate the glyph. This may be the best way to go as long as you think that you can identify all letter combinations that can result in a glyph.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String features = "\"liga\"=0";

        TextView textView = (TextView) findViewById(R.id.textview);
        Typeface tf = Typeface.createFromAsset(this.getAssets(), "MenksoftHawang" +
                ".ttf");
        textView.setTypeface(tf);
        textView.setFontFeatureSettings(features);

        textView.setText("IJ ij");
    }
}
4
votes

I'm not sure about exact cause of the issue, I assume it might be also a font issue.

But as a workaround you can apply tiny letter spacing, which will show letters as expected.

textView1.setText("IJ");

textView2.setLetterSpacing(0.04f);
textView2.setText("IJ");

Result:

enter image description here

3
votes

There appears to be three solutions to this problem:

1. Programmatically disable the ligatures

You can disable the ligatures programmatically with setFontFeatureSettings (as suggested here) or setLetterSpacing (as suggested here). One disadvantage of both of these methods is that they are only available from API 21.

2. Edit the ligatures out of the font

You can use font editing software to fix or delete the ligature errors in the font. See this Q&A for how to do it in FontForge. A potential problem here is that the font copyright owners may not allow third parties to edit their fonts.

3. Use a different font

Different fonts are often available and that is true in this case. The same company that had the problematic TrueType font in the question also has an OpenType version of that font. The OpenType version does not seem to have the ligature errors. A disadvantage, though, is that it is significantly larger in size, which will make that app download size larger.

Notes

  • I had previously thought that there was no ligature rendering prior to Android 6.0. However, TrueType fonts do apparently support some basic ligatures and those are rendered in versions of Android prior to 6.0.
  • The following image from FontForge shows all the ligatures defined in the problematic font referenced in the question. enter image description here