Raj Kiran
Raj Kiran

Reputation: 161

Get Glyphs of a character without using fallback font

I'm trying to get CGPath from glyphs for all the fonts available on my iPad, in a few cases the Glyphs are not available for fonts such as "AcademyEngravedLetPlain" which looks like below:

enter image description here

My code:

    let attributes = text.attributes(at: 0, effectiveRange: nil)
    let font = attributes[.font] as! UIFont
    //or you can use let font = UIFont(name: "AcademyEngravedLetPlain", size: 30)!

    let unicodeScalarRange: ClosedRange<Unicode.Scalar> = "!" ... "~"
    let unicodeScalarValueRange: ClosedRange<UInt32> = unicodeScalarRange.lowerBound.value ... unicodeScalarRange.upperBound.value
    let unicodeScalarArray: [Unicode.Scalar] = unicodeScalarValueRange.compactMap(Unicode.Scalar.init)

    var a: [UniChar] = unicodeScalarValueRange.map(UniChar.init)
    var glyphs = [CGGlyph](repeatElement(0, count: a.count))
    let gotGlyphs = CTFontGetGlyphsForCharacters(font, &a, &glyphs, a.count)
    if gotGlyphs{
        for g in glyphs {
            if let cgpath = CTFontCreatePathForGlyph(font, g, nil) {
                print("cgpath available")
            }
        }
    }else{
        print("Could not get glyphs for font characters!!! No cgpath")
    }

How do I get the missing glyphs/paths of the fonts, I don't want to use the fallback font. what can be the solution?

Upvotes: 2

Views: 499

Answers (1)

Rob Napier
Rob Napier

Reputation: 299663

Fonts do not generally have glyphs for every possible character. Some of these characters have glyphs in this font and some do not. The return value of CTFontGetGlyphsForCharacters is only true if every requested character has a glyph. If any of them are missing, it stores 0 in the glyph array at that index, and returns false.

If you change your loop to the following, you can get a list of what's missing for this font:

for (c, g) in zip(unicodeScalarArray, glyphs) {
    if g == 0 {
        print("cgpath NOT available for: \(c)")
    }
    else if let cgpath = CTFontCreatePathForGlyph(font, g, nil) {
        // print("cgpath available for: \(c)")
    }
}

=>

cgpath NOT available for: #
cgpath NOT available for: +
cgpath NOT available for: <
cgpath NOT available for: =
cgpath NOT available for: >
cgpath NOT available for: @
cgpath NOT available for: ^
cgpath NOT available for: {
cgpath NOT available for: |
cgpath NOT available for: }
cgpath NOT available for: ~

Upvotes: 1

Related Questions