翻转CTFontCreatePathForGlyph创建的文本路径

时间:2018-06-12 08:47:26

标签: swift uibezierpath

我正在尝试在CAShapeLayer内创建文字。为此,我需要从文本中创建UIBezierPath。基于text path solution应该都可行,但遗憾的是我无法找到错误。

CTFontCreatePathForGlyph(runFont, glyph, nil)创建的路径已从翻转的一侧绘制了字母。

enter image description here

代码转换为 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)
    }

任何想法我能做些什么来反映它?我发现了一些mirror path,但它没有得到任何结果。

2 个答案:

答案 0 :(得分:1)

正如@Grimxn所说:我必须进行规模和翻译。

draw(in rect: CGRect)内的自定义图层的超级视图中添加了以下代码行。

 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是自定义CAShapeLayer中的存储属性,可在超级视图的layoutSubviews内获取更新。

希望它对将要面对这个问题的其他人有所帮助。

答案 1 :(得分:0)

您还可以提供对CTFontCreatePathForGlyph方法的转换以翻转返回的路径。

// Mirror the glyph about the x-axis so it not upside down
var flipVertically = CGAffineTransform(scaleX: 1, y: -1)
let cgPath = CTFontCreatePathForGlyph(font, glyph, &flipVertically)