From ed3fc98f72b1f7b54f9dcda6d989afecb9d0b7ed Mon Sep 17 00:00:00 2001 From: Rob Napier Date: Thu, 2 Jan 2020 17:12:35 -0500 Subject: [PATCH] Use CTFontDrawGlyphs rather than CTRunDraw --- PathText/Sources/PathText/GlyphRun.swift | 27 ++++++++++++------- .../Tests/PathTextTests/PathTextTests.swift | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/PathText/Sources/PathText/GlyphRun.swift b/PathText/Sources/PathText/GlyphRun.swift index e258cd4..e092df0 100644 --- a/PathText/Sources/PathText/GlyphRun.swift +++ b/PathText/Sources/PathText/GlyphRun.swift @@ -17,8 +17,10 @@ private extension Sequence { } struct GlyphLocation { - var glyphRange: CFRange - var anchor: CGFloat // Center location + var glyph: CGGlyph + var position: CGPoint + var width: CGFloat + var anchor: CGFloat { position.x + width / 2 } } struct GlyphRun { @@ -34,6 +36,10 @@ struct GlyphRun { let baseTextMatrix = context.textMatrix defer { context.textMatrix = baseTextMatrix } + // FIXME: Apply other attributes + let attributes = CTRunGetAttributes(run) as! [CFString : Any] + let font = attributes[kCTFontAttributeName] as! CTFont + for (location, tangent) in zip(locations, tangents) { context.saveGState() defer { context.restoreGState() } @@ -41,14 +47,12 @@ struct GlyphRun { let tangentPoint = tangent.point let angle = tangent.angle - // FIXME: Apply other attributes - context.translateBy(x: tangentPoint.x, y: tangentPoint.y) context.rotate(by: angle) - context.textMatrix = baseTextMatrix.translatedBy(x: -location.anchor, y: 0) - - CTRunDraw(run, context, location.glyphRange) + var glyph = location.glyph + var point = CGPoint(x: -location.width / 2, y: location.position.y) + CTFontDrawGlyphs(font, &glyph, &point, 1, context) } } } @@ -90,10 +94,13 @@ struct PathTextLayoutManager { CGFloat(CTRunGetTypographicBounds(run, CFRange(location: $0, length: 1), nil, nil, nil)) } - let anchors = zip(positions, widths).map { $0.x + $1 / 2 } + let glyphs = Array(unsafeUninitializedCapacity: glyphCount) { (buffer, initialized) in + CTRunGetGlyphs(run, CFRange(), buffer.baseAddress!) + initialized = glyphCount + } - let locations = anchors.enumerated() - .map { GlyphLocation(glyphRange: CFRange(location: $0, length: 1), anchor: $1) } + let locations = zip(glyphs, zip(positions, widths)) + .map { GlyphLocation(glyph: $0, position: $1.0, width: $1.1) } .sorted { $0.anchor < $1.anchor } return GlyphRun(run: run, locations: locations) diff --git a/PathText/Tests/PathTextTests/PathTextTests.swift b/PathText/Tests/PathTextTests/PathTextTests.swift index dce5f57..0594f25 100644 --- a/PathText/Tests/PathTextTests/PathTextTests.swift +++ b/PathText/Tests/PathTextTests/PathTextTests.swift @@ -52,7 +52,7 @@ final class PathTextTests: XCTestCase { var generator = TangentGenerator(path: path) let tangents = [0, 100, 200, 300, 400, 500, 600].compactMap{ generator.getTangent(at: $0) } - print(tangents) + AssertPathTangentsEqual(tangents, [ PathTangent(t: 0, point: P0, angle: -0.674), PathTangent(t: 0.124, point: CGPoint(x: 137, y: 451), angle: -0.310),