1

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

从OSX:CGGlyph to UniChar answer in Swift实施该方法时出现问题。

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显示没有相关方法。

在此处输入图像描述

并且Core Foundation > CFCharacterSet似乎具有创建另一个 CFCharacterSet 的方法,但没有提供能够创建映射字典的 unichars 数组|列表|字符串的方法。


注意:我正在寻找一种不特定于 iOS 的解决方案,如使用UIFont.

4

2 回答 2

2

你可以做这样的事情。

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

位图的格式在CFCharacterSetCreateWithBitmapRepresentation的参考页中定义

于 2019-06-27T05:27:17.270 回答
2

CFCharacterSet与 Cocoa Foundation 对应的免费桥接NSCharacterSet,并且可以桥接到相应的 Swift 值类型CharacterSet

let charset = CTFontCopyCharacterSet(ctFont) as CharacterSet

然后可以使用来自 NSCharacterSet 的 NSArray的方法来枚举该字符集的所有 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
}
于 2019-06-27T06:54:56.023 回答