I am trying to achieve text drawn inside CAShapeLayer
. For this purpose I need to create UIBezierPath
from the text. Based on text path solution should all works fine, but sadly I can't find what is wrong.
The path created by CTFontCreatePathForGlyph(runFont, glyph, nil)
has drawn letter from the flipped side.
The code converted to Swift 4
func initializeTextLayer() {
let fontName: CFString = "Noteworthy-Light" as CFString
let letters = CGMutablePath()
let font = CTFontCreateWithName(fontName, 50, nil)
let attrString = NSAttributedString(string: "TEST", attributes: [kCTFontAttributeName as NSAttributedStringKey : font])
let line = CTLineCreateWithAttributedString(attrString)
let runArray = CTLineGetGlyphRuns(line)
for runIndex in 0..<CFArrayGetCount(runArray) {
let run : CTRun = unsafeBitCast(CFArrayGetValueAtIndex(runArray, runIndex), to: CTRun.self)
let dictRef : CFDictionary = CTRunGetAttributes(run)
let dict : NSDictionary = dictRef as NSDictionary
let runFont = dict[kCTFontAttributeName as String] as! CTFont
for runGlyphIndex in 0..<CTRunGetGlyphCount(run) {
let thisGlyphRange = CFRangeMake(runGlyphIndex, 1)
var glyph = CGGlyph()
var position = CGPoint.zero
CTRunGetGlyphs(run, thisGlyphRange, &glyph)
CTRunGetPositions(run, thisGlyphRange, &position)
let letter = CTFontCreatePathForGlyph(runFont, glyph, nil)
let t = CGAffineTransform(translationX: position.x, y: position.y)
if let letter = letter {
letters.addPath(letter, transform: t)
}
}
}
let path = UIBezierPath()
path.move(to: CGPoint.zero)
path.append(UIBezierPath(cgPath: letters))
let pathLayer = CAShapeLayer()
pathLayer.path = path.cgPath
self.layer.addSublayer(pathLayer)
}
Any ideas what can I do to mirror it ? I found something mirror path but it didn't get any results.
As @Grimxn said: I have to do scale and translation.
In super view of custom layer inside draw(in rect: CGRect)
added following lines of code.
func updateTextLayerPath() {
if let pth = popupLayer.textLayerPath {
UIColor.red.setStroke()
// glyph path is inverted, so flip vertically
let flipY = CGAffineTransform(scaleX: 1, y: -1.0)
// glyph path may be offset on the x coord, and by the height (because it's flipped)
let translate = CGAffineTransform(translationX: -pth.bounds.origin.x, y: pth.bounds.size.height + pth.bounds.origin.y)
// apply the transforms
pth.apply(flipY)
pth.apply(translate)
// stroke the path
pth.stroke()
}
}
textLayerPath
is a stored property in custom CAShapeLayer
which gets updates inside layoutSubviews
of the super view.
Hope it will be helpful for everyone else who is going to face this problem.