-
-
Save odrobnik/2751fb3ce32792b8a85d to your computer and use it in GitHub Desktop.
func appendToPath(path: CGMutablePath) | |
{ | |
let textPath = CGPathCreateMutable() | |
let attributedString = NSAttributedString(string: string) | |
let line = CTLineCreateWithAttributedString(attributedString) | |
// direct cast to typed array fails for some reason | |
let runs = (CTLineGetGlyphRuns(line) as [AnyObject]) as! [CTRun] | |
for run in runs | |
{ | |
let attributes: NSDictionary = CTRunGetAttributes(run) | |
let font = attributes[kCTFontAttributeName as String] as! CTFont | |
let count = CTRunGetGlyphCount(run) | |
for index in 0..<count | |
{ | |
let range = CFRangeMake(index, 1) | |
var glyph = CGGlyph() | |
CTRunGetGlyphs(run, range, &glyph) | |
var position = CGPoint() | |
CTRunGetPositions(run, range, &position) | |
let letterPath = CTFontCreatePathForGlyph(font, glyph, nil) | |
var transform = CGAffineTransformMake(1, 0, 0, -1, position.x, position.y) | |
CGPathAddPath(textPath, &transform, letterPath) | |
} | |
} | |
var transform = CGAffineTransformMakeTranslation(location.x, location.y) | |
CGPathAddPath(path, &transform, textPath) | |
} |
Can you please elaborate on how this is supposed to be used? Is it supposed to added to an extension on NSAttributedString? (If so, the use of "CGAffineTransformMakeTranslation(location.x, location.y)" generates an error (as location is not a property of NSAttributedString.) Thanks.
@manmal, those changes won't work. As @odrobnik points out, his conversions are required (in Swift 2.3 at any rate).
However, checks ARE needed. It turn out that non-drawing glyphs such as spaces will cause CTFontCreatePathForGlyph
to return NULL. You need to check for this, and only call CGPathAddPath
if the path was successfully created. Otherwise, crash.
e.g. feeding the string "This string will crash" to the method on iOS 9 will indeed cause it to crash, because of the spaces.
The quick-help documentation on this is in error, or at least misleading. But the header file says this about the returned value:
"A retained CGPath reference containing the glyph outlines or NULL if there is no such glyph or it has no outline"
i.e. it's entirely possibly for NULL to be returned for some glyphs.
What's location.x and location.y ?
I'd change
let runs = CTLineGetGlyphRuns(line) as! Array<CTRun>
to
guard let runs = CTLineGetGlyphRuns(line) as? [CTRun] else { return }
and
to
The rest looks great for me 👍