如何不使用备用字体获取iPad字体中缺失的Glyph与CGPath?
解决字体缺失Glyph的CGPath获取问题(不使用备用字体)
部分字体(如AcademyEngravedLetPlain)本身未包含某些字符的Glyph,这是字体设计阶段的固有限制。要在不依赖备用字体的前提下获取对应路径,可尝试以下方案:
1. 先过滤字体支持的字符集
先确认字体实际支持的字符范围,避免对不支持的字符做无效查询:
let font = UIFont(name: "AcademyEngravedLetPlain", size: 30)! let ctFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil) // 获取字体支持的所有字符 if let supportedChars = CTFontCopySupportedCharacters(ctFont) as? [Unicode.Scalar] { let targetRange: ClosedRange<Unicode.Scalar> = "!" ... "~" let supportedTargetChars = targetRange.filter { supportedChars.contains($0) } // 仅处理字体支持的字符 for scalar in supportedTargetChars { let char = UniChar(scalar.value) var glyph: CGGlyph = 0 let gotGlyph = CTFontGetGlyphsForCharacters(ctFont, &char, &glyph, 1) if gotGlyph, let path = CTFontCreatePathForGlyph(ctFont, glyph, nil) { print("获取到\(scalar)的CGPath") } } }
2. 利用CoreText布局获取实际渲染的Glyph
部分字体通过内部替换规则(如连字、字形变体)提供Glyph,但直接调用CTFontGetGlyphsForCharacters可能无法捕获。可通过创建CTRun获取实际用于渲染的Glyph:
let font = UIFont(name: "AcademyEngravedLetPlain", size: 30)! let ctFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil) let text = String("!"..."~") // 目标字符范围对应的字符串 let attributes = [kCTFontAttributeName: ctFont] as CFDictionary let attributedString = NSAttributedString(string: text, attributes: attributes as [NSAttributedString.Key : Any]) let line = CTLineCreateWithAttributedString(attributedString) let runs = CTLineGetGlyphRuns(line) as! [CTRun] for run in runs { let glyphCount = CTRunGetGlyphCount(run) var glyphs = [CGGlyph](repeating: 0, count: glyphCount) CTRunGetGlyphs(run, CFRangeMake(0, glyphCount), &glyphs) for glyph in glyphs { if let path = CTFontCreatePathForGlyph(ctFont, glyph, nil) { print("获取到Glyph的CGPath") } } }
3. 手动生成缺失字符的路径(非字体原生)
如果字体确实没有对应字符的Glyph,又必须获取路径,可通过CoreGraphics手动绘制并提取路径:
func createPathForCharacter(_ char: Character, font: UIFont) -> CGPath? { let string = String(char) let attributes: [NSAttributedString.Key: Any] = [.font: font] let size = string.size(withAttributes: attributes) UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale) guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext() return nil } string.draw(at: .zero, withAttributes: attributes) // 提取上下文路径 context.beginPath() context.addRect(CGRect(origin: .zero, size: size)) context.clip() let path = context.path UIGraphicsEndImageContext() return path } // 使用示例 let font = UIFont(name: "AcademyEngravedLetPlain", size: 30)! let missingChar: Character = "@" // 示例缺失字符 if let path = createPathForCharacter(missingChar, font: font) { print("手动生成了\(missingChar)的CGPath") }
注意:该方法生成的路径基于系统渲染结果,并非字体原生Glyph路径,外观可能与字体风格存在差异。
内容的提问来源于stack exchange,提问作者Raj Kiran
相关产品推荐
相关产品推荐

