如何在Swift中使用CTFontCopyCharacterSet()获取字体的所有字符?

时间:2019-06-27 00:02:39

标签: swift core-text

在Swift中,如何使用CTFontCopyCharacterSet()获取字体的所有字符? ...对于macOS?

在Swift中通过OSX: CGGlyph to UniChar答案实现方法时,就会发生此问题。

func createUnicodeFontMap() {
    // Get all characters of the font with CTFontCopyCharacterSet().
    let cfCharacterSet: CFCharacterSet = CTFontCopyCharacterSet(ctFont)

    //    
    let cfCharacterSetStr = "\(cfCharacterSet)"
    print("CFCharacterSet: \(cfCharacterSet)")  

    // Map all Unicode characters to corresponding glyphs
    var unichars = [UniChar](…NYI…) // NYI: lacking unichars for CFCharacterSet
    var glyphs = [CGGlyph](repeating: 0, count: unichars.count)
    guard CTFontGetGlyphsForCharacters(
        ctFont, // font: CTFont
        &unichars, // characters: UnsafePointer<UniChar>
        &glyphs, // UnsafeMutablePointer<CGGlyph>
        unichars.count // count: CFIndex
        )
        else {
            return
    }

    // For each Unicode character and its glyph, 
    // store the mapping glyph -> Unicode in a dictionary.
    // ... NYI
}

使用CFCharacterSet来检索实际字符的方法已难以捉摸。 cfCharacterSet实例的自动补全功能不会显示任何相关方法。

enter image description here

然后出现Core Foundation > CFCharacterSet的方法具有创建另一个CFCharacterSet的方法,但是不提供提供单字符数组| list以便创建映射字典的方法。


注意:我正在寻找一个不特定于iOS的解决方案,例如使用UIFont的{​​{3}}。

2 个答案:

答案 0 :(得分:1)

您可以执行以下操作。

let cs = CTFontCopyCharacterSet(font) as NSCharacterSet
let bitmapRepresentation = cs.bitmapRepresentation

参考页中为CFCharacterSetCreateWithBitmapRepresentation

定义了位图的格式

答案 1 :(得分:1)

CFCharacterSet与Cocoa Foundation的同行NSCharacterSet之间是免费的桥接,并且可以桥接到相应的Swift值类型CharacterSet

let charset = CTFontCopyCharacterSet(ctFont) as CharacterSet

然后可以使用NSArray from NSCharacterSet中的方法来枚举该字符集的所有Unicode标量值(包括非BMP点,即大于U + FFFF的Unicode标量值)。

CTFontGetGlyphsForCharacters()期望将非BMP字符作为代理对,即作为UTF-16代码单元的数组。

将其放在一起,该函数将如下所示:

func createUnicodeFontMap(ctFont: CTFont) ->  [CGGlyph : UnicodeScalar] {

    let charset = CTFontCopyCharacterSet(ctFont) as CharacterSet

    var glyphToUnicode = [CGGlyph : UnicodeScalar]() // Start with empty map.

    // Enumerate all Unicode scalar values from the character set:
    for plane: UInt8 in 0...16 where charset.hasMember(inPlane: plane) {
        for unicode in UTF32Char(plane) << 16 ..< UTF32Char(plane + 1) << 16 {
            if let uniChar = UnicodeScalar(unicode), charset.contains(uniChar) {

                // Get glyph for this `uniChar` ...
                let utf16 = Array(uniChar.utf16)
                var glyphs = [CGGlyph](repeating: 0, count: utf16.count)
                if CTFontGetGlyphsForCharacters(ctFont, utf16, &glyphs, utf16.count) {
                    // ... and add it to the map.
                    glyphToUnicode[glyphs[0]] = uniChar
                }
            }
        }
    }

    return glyphToUnicode
}