【问题标题】:Detect when a unicode character cannot be displayed correctly检测 unicode 字符何时无法正确显示
【发布时间】:2015-07-12 00:31:25
【问题描述】:

某些 unicode 字符在 iOS 上无法显示,但在 macOS 上可以正确显示。同样,iOS 可以显示的一些 unicode 字符在 watchOS 上也无法显示。这是因为这些平台上安装了不同的内置字体。

当一个字符无法显示时,它会显示为 ?在一个盒子里,像这样:

我还看到一些字符显示为外星人(不知道为什么会有所不同):

如果给定一个 unicode 字符的字符串,例如"ᄥ",有没有办法知道特定的 unicode 字符何时无法正确显示?

我需要一个适用于 iOS 和 watchOS 的解决方案。

【问题讨论】:

  • 也许使用CTFontGetGlyphsForCharacters(...)
  • 你能给我们这两个的代码点吗?
  • @ZoffDino 我手边没有外星人,但举个例子?,这个字符显示为?在 iOS 上:????
  • 我设置了????的unicode(U+1F0A1),显示为'`A1.在 Mobile Safari 中,您在浏览问题时看不到这一点。

标签: ios swift unicode watchkit


【解决方案1】:

您可以使用CTFontGetGlyphsForCharacters() 来确定字体是否具有特定代码点的字形(注意补充字符需要作为代理对进行检查):

CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica"), 12, NULL);
const UniChar code_point[] = { 0xD83C, 0xDCA1 };  // U+1F0A1
CGGlyph glyph[] = { 0, 0 };
bool has_glyph = CTFontGetGlyphsForCharacters(font, code_point, glyph, 2);

或者,在 Swift 中:

let font = CTFontCreateWithName("Helvetica", 12, nil)
var code_point: [UniChar] = [0xD83C, 0xDCA1]
var glyphs: [CGGlyph] = [0, 0]
let has_glyph = CTFontGetGlyphsForCharacters(font, &code_point, &glyph, 2)

如果要检查系统将尝试从中加载字形的完整备用字体集,则需要检查CTFontCopyDefaultCascadeListForLanguages() 返回的所有字体。查看answer to this question 了解有关如何创建后备字体列表的信息。

【讨论】:

  • has_glyph 为假,那么不可能显示正确?
  • 如果has_glyph == false,它将使用带有方框或问号的 Last Resort 字体呈现(如在原始问题中)。
  • 非常整洁!有没有一种更有效的方法来知道是否有任何字体可以显示给定的字形,而无需在从上述方法返回的所有字体上循环运行该代码?我想这对于大量字形来说会非常低效。
  • 这本质上是系统尝试正常渲染文本时所做的事情,因此性能应该不会太差。但是您可能希望缓存CTFont 对象,并且CTFontGetGlyphs... 可用于一次检查整个字符串(查找glyphs[i] != 0 而不是返回值)。
【解决方案2】:

与已知的未定义字符U+1FFF进行比较:

/// - Parameter font: a UIFont
/// - Returns: true if glyph exists
func glyphAvailable(forFont font:UIFont) -> Bool {
    if let refUnicodePng = Character("\u{1fff}").png(forFont: font),
        let myPng = self.png(forFont: font) {
        return refUnicodePng != myPng
    }
    return false
}

使用 png 位图:

/// - Parameter font: a UIFont
/// - Returns: an optional png representation
func png(forFont font: UIFont) -> Data? {
    let attributes = [NSAttributedStringKey.font: font]
    let charStr = "\(self)" as NSString
    let size = charStr.size(withAttributes: attributes)

    UIGraphicsBeginImageContext(size)
    charStr.draw(at: CGPoint(x: 0,y :0), withAttributes: attributes)

    var png:Data? = nil
    if let charImage = UIGraphicsGetImageFromCurrentImageContext() {
        png = UIImagePNGRepresentation(charImage)
    }

    UIGraphicsEndImageContext()
    return png
}

已回复here

【讨论】:

    猜你喜欢
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2012-08-08
    • 2014-02-14
    • 1970-01-01
    • 2011-12-06
    相关资源
    最近更新 更多