Skip to content

Instantly share code, notes, and snippets.

@oozoofrog
Last active July 10, 2016 12:43
Show Gist options
  • Save oozoofrog/a88989e77cf7866325bd3e38538fba98 to your computer and use it in GitHub Desktop.
Save oozoofrog/a88989e77cf7866325bd3e38538fba98 to your computer and use it in GitHub Desktop.
import UIKit
@IBDesignable
class CharacterView: UIView {
let pathLayer = CAShapeLayer()
override func didMoveToSuperview() {
if nil != superview {
if pathLayer.superlayer != self.layer {
self.layer.addSublayer(pathLayer)
pathLayer.path = self.path(forAttributedString: AttributedString(string: "Italic System", attributes: [NSFontAttributeName : UIFont.italicSystemFont(ofSize: 33)]))
pathLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1).cgColor
}
DispatchQueue.main.after(when: .now() + 1.0, execute: {
let morph = CABasicAnimation(keyPath: "path")
morph.duration = 1
morph.toValue = self.path(forAttributedString: AttributedString(string: "System", attributes: [NSFontAttributeName : UIFont.systemFont(ofSize: 33)]))
morph.fillMode = kCAFillModeForwards
morph.isRemovedOnCompletion = false
self.pathLayer.add(morph, forKey: "morph")
})
}
}
override func layoutSubviews() {
super.layoutSubviews()
self.pathLayer.frame = self.bounds
}
func path(forAttributedString attributedString: AttributedString) -> CGPath {
let line = CTLineCreateWithAttributedString(attributedString)
let array = CTLineGetGlyphRuns(line) as [AnyObject]
let paths = UIBezierPath()
for ao in array {
let run = ao as! CTRun
let runAttributes = CTRunGetAttributes(run) as NSDictionary
let runFont = runAttributes.object(forKey: NSFontAttributeName) as! CTFont
let glyphCount = CTRunGetGlyphCount(run)
for index in 0..<glyphCount {
var glyph = CGGlyph()
var point = CGPoint()
CTRunGetGlyphs(run, CFRangeMake(index, 1), &glyph)
CTRunGetPositions(run, CFRangeMake(index, 1), &point)
var transform = CGAffineTransform(translationX: point.x, y: point.y)
transform = transform.concat(CGAffineTransform(scaleX: 1, y: -1))
guard let path = CTFontCreatePathForGlyph(runFont, glyph, &transform) else {
continue
}
paths.append(UIBezierPath(cgPath: path))
}
}
paths.close()
return paths.cgPath
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment