TLDR: CTFont / CTFontRef / CTGlyph недостаточно - необходимо задействовать CTLine и CTRun;и даже тогда это имеет смысл только в том случае, если у вас есть доступ к исходному отображению String-> Glyph.
Я вернусь к этому на несколько лет позже, если другие в конечном итоге зададут этот вопрос.Как заметил Аластер, нет никакого способа для общего сопоставления глифов с символами.Простые примеры - есть несколько символов Юникода для «пробела», часто сопоставляемых одному и тому же символу.То же самое часто бывает верно для «микро» и греческого «му».
Однако иногда (часто?) Бывает, что у вас есть исходная строка, и вам действительно нужно знать, как она была отображена.глифам.Другими словами - у меня есть моя строка, и у меня есть полученные глифы - для каждого индекса глифа, каков индекс символа в строке, в которую он вносит свой вклад.Я написал этот пример, чтобы продемонстрировать способ сделать это.(Помимо: извлеченный урок - Swift становится немного грубым при работе с некоторыми API Core Foundation)
import CoreText
import AppKit
func main(argc: Int, argv: [String])
{
var stringAttributes: [String: AnyObject] = [:]
var fontName = "Zapfino"
var fUseLigatures = false
var fontNameIndex = 0
if argc > 1
{
if argv[1] == "/lig"
{
fUseLigatures = true;
if (argc > 2) { fontNameIndex = 3 }
}
else { fontNameIndex = 2 }
}
if fontNameIndex > 0 { fontName = argv[fontNameIndex] }
if let font = NSFont(name:fontName, size:24.0)
{ stringAttributes[NSFontAttributeName] = font }
stringAttributes[NSLigatureAttributeName] = fUseLigatures ? 2 : 0
let string = NSAttributedString(
string:"This is \(fontName)!",
attributes: stringAttributes)
let line = CTLineCreateWithAttributedString(string) // CTLine
let runs = CTLineGetGlyphRuns(line) // CTRun[]
let nsRuns:Array<AnyObject> = runs as Array<AnyObject>
assert(nsRuns.count == 1)
let run = nsRuns[0] as! CTRun
let glyphCount = CTRunGetGlyphCount(run)
println("String: \(string.string)")
println("\tStrLen: \(count(string.string)), Count Of Glyphs: \(glyphCount)");
let clusters = UnsafeMutablePointer<CFIndex>.alloc(glyphCount)
CTRunGetStringIndices(run, CFRange(location:0, length:glyphCount), clusters)
for var idx = 0; idx < glyphCount; idx++
{
let idxString = clusters[idx];
println("Glyph @ \(idx) maps to String @ \(idxString)")
}
}
main(Process.arguments.count, Process.arguments)
Если вы запустите это без параметров, а затем с помощью / lig в командной строке вы получите следующий вывод:
String: This is Zapfino!
StrLen: 16, Count Of Glyphs: 16
Glyph @ 0 maps to String @ 0
Glyph @ 1 maps to String @ 1
Glyph @ 2 maps to String @ 2
Glyph @ 3 maps to String @ 3
Glyph @ 4 maps to String @ 4
Glyph @ 5 maps to String @ 5
Glyph @ 6 maps to String @ 6
Glyph @ 7 maps to String @ 7
Glyph @ 8 maps to String @ 8
Glyph @ 9 maps to String @ 9
Glyph @ 10 maps to String @ 10
Glyph @ 11 maps to String @ 11
Glyph @ 12 maps to String @ 12
Glyph @ 13 maps to String @ 13
Glyph @ 14 maps to String @ 14
Glyph @ 15 maps to String @ 15
joes-mac: Tue Apr 14, 10:26:00
~/Source/FontGlyph/./main /lig
String: This is Zapfino!
StrLen: 16, Count Of Glyphs: 7
Glyph @ 0 maps to String @ 0
Glyph @ 1 maps to String @ 2
Glyph @ 2 maps to String @ 4
Glyph @ 3 maps to String @ 5
Glyph @ 4 maps to String @ 7
Glyph @ 5 maps to String @ 8
Glyph @ 6 maps to String @ 15
Я добавил опцию Ligature, чтобы помочь визуализировать, что глифы и символы довольно легко могут не быть 1 к 1. Вот визуальное представление двух строк: ![enter image description here](https://i.stack.imgur.com/USoEg.png)