how to convert a swift String to an array of CGGly

2019-05-11 00:36发布

问题:

This snippet can be used for drawing CGGlyphs with a CGContext.

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

But how do I obtain the CGGlyphs from a swift string which contains emoji symbols like flags or accented characters?

let string = "swift: \u{1F496} \u{65}\u{301} \u{E9}\u{20DD} \u{1F1FA}\u{1F1F8}"

Neither of these approaches shows the special characters, even though they are correctly printed to the console. Note that this first approach returns NSGlyph but CGGlyph's are required for drawing.

    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
    }

or this second approach which requires casting to 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
    }

Some of the characters are drawn as empty boxes with either approach. Kinda stuck here, hoping you can help.

edit:

Using CTFontDrawGlyphs renders the glyphs correctly, but setting the font, size and text matrix directly before calling CGContextShowGlyphsAtPositions draws nothing. I find that rather odd.

回答1:

If you generate glyphs yourself, you also need to perform font substitution yourself. When you use Core Text or TextKit to lay out and draw the text, they perform font substitution for you. For example:

let richText = NSAttributedString(string: "Hello