【问题标题】:Font.canDisplay always returns true on macFont.canDisplay 在 Mac 上总是返回 true
【发布时间】:2013-06-05 04:13:41
【问题描述】:

我编写了一个简单的代码来检查在给定的自定义字体文件(.ttf 或 .otf)中是否有可用的字形,为此我正在使用:

Font.canDisplay()

当我在 Windows 上测试我的代码时它工作正常,但在 mac 上它总是返回 true,即使该字形不可用,我猜字体替换选项在 mac 中默认为打开,有什么建议如何关闭它?

Environment:

VM Version 1.6.0_26
Mac OS X 10.7.2

字体文件(truetype):http://www.fontsc.com/font/depth-charge(您可以在此网站上查看字符映射,字形在 CAP 中不可用)

【问题讨论】:

    标签: java fonts awt glyph truetype


    【解决方案1】:

    更新: Oracle 接受了我的错误报告: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8223834

    您将在下面找到可能的解决方法:

    这似乎是 Mac OS 实现 Font2D 类的一个错误。

    我能够使用反射解决该问题。这是在 Mac 上产生正确结果的代码。它在 Kotlin 中,但如果需要,应该可以直接将其转换为 Java。

    // Mac OS workaround for incorrectly implemented canDisplayUpTo method
    fun Font.macCanDisplayUpTo(str: String): Int {
        val getFontMethod = Font::class.java.getDeclaredMethod("getFont2D")
        getFontMethod.isAccessible = true
        val font2d = getFontMethod.invoke(this)
        val getMapperMethod = font2d.javaClass.getDeclaredMethod("getMapper")
        getMapperMethod.isAccessible = true
        val mapper = getMapperMethod.invoke(font2d)
        val charToGlyphMethod = mapper.javaClass.getDeclaredMethod("charToGlyph", Char::class.java)
    
        val len = str.length
        var i = 0
        while (i < len) {
            val c = str[i]
            val glyph = charToGlyphMethod.invoke(mapper, c) as Int
            if (glyph >= 0) {
                i++
                continue
            }
            if (!Character.isHighSurrogate(c)
                    || (charToGlyphMethod.invoke(mapper, str.codePointAt(i)) as Int) < 0) {
                return i
            }
            i += 2
        }
        return -1
    }
    

    如果您使用的是 Java 9 或更高版本,则需要将这些命令参数传递给 VM 以使代码正常工作:

    --add-opens java.desktop/java.awt=your.module.name
    --add-opens java.desktop/sun.font=your.module.name
    

    此代码在 Windows 上不起作用(会产生不正确的结果)。它仅适用于 MacOS。

    【讨论】:

      【解决方案2】:

      .

      Font font = Font.createFont(int fontFormat, File fontFile)
      /(int fontFormat, InputStream fontStream)
      
      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
      ge.registerFont(font);
      
      if (font.canDisplay()/canDisplayUpTo()){
          //your code with font.....    
      }
      

      【讨论】:

      • 我尝试在 GE 中注册字体,但仍然没有运气
        有趣的是 font.getNumGlyphs() 返回正确的字形计数。
      • font.canDisplay(65)/font.canDisplay('A') 和 font.canDisplay(97)/font.canDisplay('a') 都返回 true :(
      猜你喜欢
      • 2013-08-06
      • 2017-05-10
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多