Some unicode characters cannot be displayed on iOS but are displayed correctly on macOS. Similarly, some unicode characters that iOS can display cannot be displayed on watch
Compare against the known, undefined character U+1FFF
:
/// - Parameter font: a UIFont
/// - Returns: true if glyph exists
func glyphAvailable(forFont font:UIFont) -> Bool {
if let refUnicodePng = Character("\u{1fff}").png(forFont: font),
let myPng = self.png(forFont: font) {
return refUnicodePng != myPng
}
return false
}
using a png bitmap:
/// - Parameter font: a UIFont
/// - Returns: an optional png representation
func png(forFont font: UIFont) -> Data? {
let attributes = [NSAttributedStringKey.font: font]
let charStr = "\(self)" as NSString
let size = charStr.size(withAttributes: attributes)
UIGraphicsBeginImageContext(size)
charStr.draw(at: CGPoint(x: 0,y :0), withAttributes: attributes)
var png:Data? = nil
if let charImage = UIGraphicsGetImageFromCurrentImageContext() {
png = UIImagePNGRepresentation(charImage)
}
UIGraphicsEndImageContext()
return png
}
Answered here.
You can use CTFontGetGlyphsForCharacters()
to determine if a font has a glyph for a particular code point (note that supplementary characters need to be checked as surrogate pairs):
CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica"), 12, NULL);
const UniChar code_point[] = { 0xD83C, 0xDCA1 }; // U+1F0A1
CGGlyph glyph[] = { 0, 0 };
bool has_glyph = CTFontGetGlyphsForCharacters(font, code_point, glyph, 2);
Or, in Swift:
let font = CTFontCreateWithName("Helvetica", 12, nil)
var code_point: [UniChar] = [0xD83C, 0xDCA1]
var glyphs: [CGGlyph] = [0, 0]
let has_glyph = CTFontGetGlyphsForCharacters(font, &code_point, &glyph, 2)
If you want to check the complete set of fallback fonts that the system will try to load a glyph from, you will need to check all of the fonts returned by CTFontCopyDefaultCascadeListForLanguages()
. Check the answer to this question for information on how the fallback font list is created.