I want to find out if a certain unicode character has a glyph representation even if by a cascading font. For example, let's say I am using UIFont.systemFont(withSize:18)
and a string \u{1CDA}
and would like to find out if this font will display the graphical representation of this character, and not a default question mark representation (ie there's no graphical representation, even by the supporting cascade fonts).
Determine if unicode character has a glyph in UIFont
1.9k views Asked by andrewz At
3
There are 3 answers
2
On
This is heavily based on the answer by @andrewz, so most credit to them! I found some issues with certain emojis giving false negatives (including ✋) so I've got some modifications, including passing the emoji in as a String
:
(note: I've got Font
instead of UIFont
as I'm using this on both iOS and macOS so have a typealias to switch between the two font classes, you can just prefix it with NS
or UI
for your platform of choice!)
extension Font {
func canRender(emoji: String) -> Bool {
var code_points = Array(emoji.utf16)
var glyphs: [CGGlyph] = Array(repeating: 0, count: code_points.count)
return CTFontGetGlyphsForCharacters(self as CTFont, &code_points, &glyphs, glyphs.count)
}
}
class Glypher {
private let font: Font
private var support: [CTFont] = []
init(for font: Font, languages: [String] = ["en"]) {
self.font = font
let languages = languages as CFArray
let result = CTFontCopyDefaultCascadeListForLanguages(font as CTFont, languages)
let array = result as! Array<CTFontDescriptor>
for descriptor in array {
support.append(CTFontCreateWithFontDescriptor(descriptor, 18, nil))
}
}
func isRenderable(emoji: String) -> Bool {
return font.canRender(emoji: emoji) || renderSupported(emoji: emoji)
}
func renderSupported(emoji: String) -> Bool {
var code_points = Array(emoji.utf16)
var glyphs: [CGGlyph] = Array(repeating: 0, count: code_points.count)
for font in support where CTFontGetGlyphsForCharacters(font as CTFont, &code_points, &glyphs, glyphs.count) {
return true
}
return false
}
}
0
On
This may work too, it doesn't check the glyph, but it checks the character set
import CoreText
func isSupported(unicode: UnicodeScalar, font: UIFont) -> Bool {
let coreFont: CTFont = font
let characterSet: CharacterSet = CTFontCopyCharacterSet(coreFont) as CharacterSet
return characterSet.contains(unicode)
}
Example test:
let testString = "R"
let font = UIFont.boldSystemFont(ofSize: 10.0)
print("\(isSupported(unicode: testString.unicodeScalars.first!, font: font))")
This works for me. Swift 3, XCode 8.6 version: