我想找出某个 unicode 字符是否具有字形表示,即使使用级联字体也是如此。 例如,假设我正在使用UIFont.systemFont(withSize:18)
和字符串u{1CDA}
,并且想知道此字体是否将显示此字符的图形表示形式,而不是默认的问号表示形式(即没有图形表示形式,即使通过支持的级联字体也是如此)。
这对我有用。 Swift 3,XCode 8.6版本:
import UIKit
import CoreText
extension Font {
public func hasGlyph(utf32 character:UInt32) -> Bool {
var code_point: [UniChar] = [
UniChar.init(truncatingBitPattern: character),
UniChar.init(truncatingBitPattern: character >> 16)
]
var glyphs: [CGGlyph] = [0,0]
let result = CTFontGetGlyphsForCharacters(self as CTFont, &code_point, &glyphs, glyphs.count)
return result
}
}
public class Glypher {
let font:UIFont
var support:[CTFont] = []
public init(for font:UIFont, 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))
}
}
public func isGlyph(_ point:UInt32) -> Bool {
return font.hasGlyph(utf32:point) || isGlyphSupported(point)
}
public func isGlyphSupported(_ point:UInt32) -> Bool {
for font in support {
var code_point: [UniChar] = [
UniChar.init(truncatingBitPattern: point),
UniChar.init(truncatingBitPattern: point >> 16)
]
var glyphs: [CGGlyph] = [0, 0]
let result = CTFontGetGlyphsForCharacters(font as CTFont, &code_point, &glyphs, glyphs.count)
if result {
return true
}
}
return false
}
}
let glypher = Glypher(for:UIFont.systemFont(ofSize:18))
if glypher.isGlyph(0x1CDA) {
print("bingo!")
}
这可能也有效,它不检查字形,但它检查字符集
import CoreText
func isSupported(unicode: UnicodeScalar, font: UIFont) -> Bool {
let coreFont: CTFont = font
let characterSet: CharacterSet = CTFontCopyCharacterSet(coreFont) as CharacterSet
return characterSet.contains(unicode)
}
示例测试:
let testString = "R"
let font = UIFont.boldSystemFont(ofSize: 10.0)
print("(isSupported(unicode: testString.unicodeScalars.first!, font: font))")
这在很大程度上是基于@andrewz的答案,所以大部分功劳都归功于他们!我发现某些表情符号给出假阴性(包括)存在一些问题,所以我进行了一些修改,包括✋将表情符号作为String
传递:
(注意:我有Font
而不是UIFont
,因为我在iOS和macOS上都使用它,所以有一个typealias可以在两个字体类之间切换,你可以用NS
或UI
作为前缀,适合你选择的平台!
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
}
}