自定义字体为Android中的某些字母组合提供了错误的字形

时间:2017-03-29 09:18:03

标签: java android fonts

我在Android项目中使用自定义字体。出于某种原因,当文本包含字母IJ时,它会给我以下字形:

enter image description here

这似乎是位于字体的PUA区域的\uE2C5处的字形。

字体中存在单独的IJ字形,如果我将文字设置为I J,我可以将其显示出来。

enter image description here

它不是OpenType字体(我不认为Android甚至支持自定义字体中的OpenType渲染),所以不应该发生这样的事情。这是怎么回事?

使用以下简单项目可以重现该问题:

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");
    }
}

可以从here下载该字体。将它放在项目的assets文件夹中。

3 个答案:

答案 0 :(得分:7)

我真的不能说你看到你所看到的东西的原因,但“IJ”的字母组合似乎有特殊待遇的历史。来自Typographic ligature上的维基百科页面。

  然而,荷兰语is更加含糊不清。根据所使用的标准,它可以被认为是有向图,结扎线或字母本身,它的大写和小写形式通常作为单个字形提供,在几种专业字体(例如Zapfino)中具有独特的结扎。在荷兰流行的Sans serif大写字母IJ字形通常使用类似U的结扎,左手中风。

同样来自Wikipedia

  

字形替换和组成

     

对于符合Unicode标准的文本处理和显示软件,某些兼容性字符是完全可有可无的。其中包括:

     

连字       拉丁文脚本中的“ffi”等连字通常被编码为传统字符集中的单独字符。 Unicode的连字方法是将它们视为富文本,如果启用,则通过字形替换来处理。

鉴于此,我的猜测是你使用的字体利用了这种用法来做自己的事情。

<强>更新 使用setFontFeatureSettings()可以禁用字形的显示,如下面的代码所示。不幸的是,这仅适用于API 21+。有一点需要注意,您可能会注意到其他副作用。

对于21以下的API,您可以使用字体编辑程序(如FontForge)并删除U + E2C5处的字形。我做了这个,它确实消除了字形。只要您认为可以识别可能导致字形的所有字母组合,这可能是最好的方法。

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");
    }
}

答案 1 :(得分:3)

我不确定问题的确切原因,我认为这也可能是字体问题。

但作为一种解决方法,您可以应用小字母间距,这将显示预期的字母。

textView1.setText("IJ");

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

结果:

enter image description here

答案 2 :(得分:1)

这个问题似乎有三种解决方案:

1。以编程方式禁用连字

您可以使用setFontFeatureSettings(建议here)或setLetterSpacing(建议here)以编程方式禁用连字。这两种方法的一个缺点是它们只能从API 21获得。

2。编辑字体

之外的连字

您可以使用字体编辑软件修复或删除字体中的连字错误。有关如何在FontForge中执行此操作,请参阅this Q&A。这里的潜在问题是字体版权所有者可能不允许第三方编辑其字体。

3。使用不同的字体

通常可以使用不同的字体,在这种情况下也是如此。在问题中具有问题TrueType字体的同一公司也具有该字体的OpenType版本。 OpenType版本似乎没有绑定错误。但缺点是它的尺寸明显更大,这将使应用下载量更大。

备注

  • 我以前认为Android 6.0之前没有连字渲染。但是,TrueType字体显然支持一些基本的连接,并且这些连接在6.0之前的Android版本中呈现。
  • 来自FontForge的以下图像显示了问题中引用的有问题字体中定义的所有连字。 enter image description here