CTFontCreatePathForGlyph 创建的文本路径被翻转

Text path created by CTFontCreatePathForGlyph is flipped

我正在尝试实现在 CAShapeLayer 中绘制文本。为此,我需要从文本创建 UIBezierPath。基于 应该一切正常,但遗憾的是我找不到问题所在。

CTFontCreatePathForGlyph(runFont, glyph, nil)创建的路径从反面绘制了字母。

代码转换为Swift4

      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 但没有得到任何结果。

正如@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 中获取更新。

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

您还可以向 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)