How to get all characters of the font with CTFontCopyCharacterSet() in Swift?

前端 未结 2 1261
清歌不尽
清歌不尽 2021-01-27 00:51

How does one get all characters of the font with CTFontCopyCharacterSet() in Swift? ... for macOS?

The issue occured when implementing the approach from an

2条回答
  •  时光说笑
    2021-01-27 01:41

    CFCharacterSet is toll-free bridged with the Cocoa Foundation counterpart NSCharacterSet, and can be bridged to the corresponding Swift value type CharacterSet:

    let charset = CTFontCopyCharacterSet(ctFont) as CharacterSet
    

    Then the approach from NSArray from NSCharacterSet can be used to enumerate all Unicode scalar values of that character set (including non-BMP points, i.e. Unicode scalar values greater than U+FFFF).

    The CTFontGetGlyphsForCharacters() expects non-BMP characters as surrogate pair, i.e. as an array of UTF-16 code units.

    Putting it together, the function would look like this:

    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
    }
    

提交回复
热议问题