如何将swift String转换为CGGlyph数组

use*_*972 3 string typesetting glyph swift

此片段可用于使用CGContext绘制CGGlyphs.

    //drawing
    let coreGraphicsFont = CTFontCopyGraphicsFont(coreTextFont, nil)
    CGContextSetFont(context, coreGraphicsFont);
    CGContextSetFontSize(context, CTFontGetSize(coreTextFont))
    CGContextSetFillColorWithColor(context, Color.blueColor().CGColor)          
    CGContextShowGlyphsAtPositions(context, glyphs, positions, length)
Run Code Online (Sandbox Code Playgroud)

但是如何从包含标志符号或重音字符等表情符号的快速字符串中获取CGGlyphs?

let string = "swift: \u{1F496} \u{65}\u{301} \u{E9}\u{20DD} \u{1F1FA}\u{1F1F8}"
Run Code Online (Sandbox Code Playgroud)

这些方法都没有显示特殊字符,即使它们已正确打印到控制台.请注意,第一种方法返回NSGlyph,但绘制时需要CGGlyph.

    var progress = CGPointZero
    for character in string.characters
    {
        let glyph = font.glyphWithName(String(character))
        glyphs.append(CGGlyph(glyph))
        let advancement = font.advancementForGlyph(glyph)
        positions.append(progress)
        progress.x += advancement.width
    }
Run Code Online (Sandbox Code Playgroud)

或者这第二种方法需要转换为NSString:

    var buffer = Array<unichar>(count: length, repeatedValue: 0)
    let range = NSRange(location: 0, length: length)
    (string as NSString).getCharacters(&buffer, range: range)

    glyphs = Array<CGGlyph>(count: length, repeatedValue: 0)
    CTFontGetGlyphsForCharacters(coreTextFont, &buffer, &glyphs, length)

    //glyph positions
    advances = Array<CGSize>(count: length, repeatedValue: CGSize.zero)
    CTFontGetAdvancesForGlyphs(ctFont, CTFontOrientation.Default, glyphs, &advances, length)
    positions = []
    var progress = CGPointZero
    for advance in advances
    {
        positions.append(progress)
        progress.x += advance.width
    }
Run Code Online (Sandbox Code Playgroud)

使用任一种方法将一些字符绘制为空框.有点卡在这里,希望你能帮忙.

编辑:

使用CTFontDrawGlyphs正确渲染字形,但在调用CGContextShowGlyphsAtPositions之前直接设置字体,大小和文本矩阵.我发现这很奇怪.

rob*_*off 5

如果您自己生成字形,则还需要自己执行字体替换.当您使用Core Text或TextKit布局和绘制文本时,它们会为您执行字体替换.例如:

let richText = NSAttributedString(string: "Hello?")
let line = CTLineCreateWithAttributedString(richText)
print(line)
Run Code Online (Sandbox Code Playgroud)

输出:

<CTLine: 0x7fa349505f00>{run count = 3, string range = (0, 8), width = 55.3457, A/D/L = 15/4.6875/0, glyph count = 7, runs = (

<CTRun: 0x7fa34969f600>{string range = (0, 5), string = "Hello", attributes = <CFBasicHash 0x7fa3496902d0 [0x10e85a7b0]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0x1153bb720 [0x10e85a7b0]>{contents = "NSFont"} = <CTFont: 0x7fa3496182f0>{name = Helvetica, size = 12.000000, matrix = 0x0, descriptor = <CTFontDescriptor: 0x7fa34968f860>{attributes = <CFBasicHash 0x7fa34968f8b0 [0x10e85a7b0]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0x1153c16c0 [0x10e85a7b0]>{contents = "NSFontNameAttribute"} = <CFString 0x1153b4700 [0x10e85a7b0]>{contents = "Helvetica"}
}
>}}
}
}


<CTRun: 0x7fa3496cde40>{string range = (5, 2), string = "\U0001F600", attributes = <CFBasicHash 0x7fa34b11a150 [0x10e85a7b0]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0x1153bb720 [0x10e85a7b0]>{contents = "NSFont"} = <CTFont: 0x7fa3496c3eb0>{name = AppleColorEmoji, size = 12.000000, matrix = 0x0, descriptor = <CTFontDescriptor: 0x7fa3496a3c30>{attributes = <CFBasicHash 0x7fa3496a3420 [0x10e85a7b0]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0x1153c16c0 [0x10e85a7b0]>{contents = "NSFontNameAttribute"} = <CFString 0x11cf63bb0 [0x10e85a7b0]>{contents = "AppleColorEmoji"}
}
>}}
}
}


<CTRun: 0x7fa3496cf3e0>{string range = (7, 1), string = "\u2192", attributes = <CFBasicHash 0x7fa34b10ed00 [0x10e85a7b0]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0x1153bb720 [0x10e85a7b0]>{contents = "NSFont"} = <CTFont: 0x7fa3496cf2c0>{name = PingFangSC-Regular, size = 12.000000, matrix = 0x0, descriptor = <CTFontDescriptor: 0x7fa3496a45a0>{attributes = <CFBasicHash 0x7fa3496a5660 [0x10e85a7b0]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0x1153c16c0 [0x10e85a7b0]>{contents = "NSFontNameAttribute"} = <CFString 0x11cf63230 [0x10e85a7b0]>{contents = "PingFangSC-Regular"}
}
>}}
}
}

)
}
Run Code Online (Sandbox Code Playgroud)

我们在这里可以看到Core Text认识到默认字体(Helvetica)没有表情符号或箭头的字形,因此它将该行分为三个运行,每个运行都有所需的字体.

核心文本编程指南这样说:

大多数情况下,您应该只使用CTLine对象来获取此信息,因为一种字体可能不会对整个字符串进行编码.此外,简单的字符到字形映射将无法获得复杂脚本的正确外观.如果您尝试显示字体的特定Unicode字符,则此简单字形映射可能是适当的.

最好的办法是用来CTLineCreateWithAttributedString生成字形并选择字体.然后,如果你想调整字形的位置,CTLineGetGlyphRuns用来从线上运行,然后向运行询问字形,字体和你需要的任何其他内容.

如果你想自己处理字体替换,我想你会想要研究"字体级联".