You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用备用字体获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 22:01:16