Last active
February 21, 2023 12:06
-
-
Save odrobnik/2751fb3ce32792b8a85d to your computer and use it in GitHub Desktop.
Swift: create CGPath from attributed string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
What's location.x and location.y ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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 callCGPathAddPath
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.