Как получить все символы шрифта с помощью CTFontCopyCharacterSet () в Swift? - PullRequest
1 голос
/ 27 июня 2019

Как получить все символы шрифта с CTFontCopyCharacterSet() в Swift? ... для macOS?

Проблема возникла при реализации подхода от OSX: CGGlyph к UniChar ответа в 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 не показывает релевантных методов.

enter image description here

И, по-видимому, Core Foundation> CFCharacterSet содержит методы для создания другого CFCharacterSet, но не то, что предоставляет массив | list | строку unichars для возможности создания сопоставленного словаря.


Примечание. Я ищу решение, не относящееся к iOS, как в Получите все доступные символы из шрифта , который использует UIFont.

Ответы [ 2 ]

1 голос
/ 27 июня 2019

CFCharacterSet является бесплатным по мосту с аналогом Cocoa Foundation NSCharacterSet и может быть подключен к соответствующему типу значения Swift CharacterSet:

let charset = CTFontCopyCharacterSet(ctFont) as CharacterSet

Тогда подход из NSArray из NSCharacterSet может быть использован для перечисления всех скалярных значений Unicode этого набора символов (включая точки, отличные от BMP, т.е. скалярные значения Unicode, превышающие U + FFFF).

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
}
1 голос
/ 27 июня 2019

Вы можете сделать что-то вроде этого.

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

Формат растрового изображения определен на странице ссылок для CFCharacterSetCreateWithBitmapRepresentation

...