如何支持多个代码点表情符号?

发布于 2025-01-24 23:39:01 字数 84 浏览 7 评论 0 原文

对于上下文,我正在尝试创建一个从字符串代码点到表情符号的映射,并且需要知道系统是否支持表情符号:

("1F9AE") -> "
              

For context, I'm trying to create a mapping from string code points to emojis and need to know if the system supports the emoji:

("1F9AE") -> "????"
("1FAE0") -> "????" (iOS 15.4+) / nil (if below 15.4, since it would show as "????")
("1F415-200D-1F9BA") -> "????‍????"
("1F415-1F9BA") -> nil (since it would normally be "????????", which isn't a single emoji)

I've gotten this to work with the single code point case with:

func emoji(for codepoint: String) -> String? {
    guard let int = Int(codepoint, radix: 16),
        let scalar = UnicodeScalar(int),
        scalar.properties.isEmoji
    else { return nil }
    return String(scalar)
}

However, I can't figure out what the corresponding check for isEmoji with multiple code points would be.

// assume I had to make these scalars via a `String`
let scalars = [UnicodeScalar(0x1F415)!, UnicodeScalar(0x200D)!, UnicodeScalar(0x1F9BA)!]
let scalarView = String.UnicodeScalarView(scalars)
// How can I check that this `UnicodeScalarView` is for single, supported emoji, since I can't check `isEmoji`?
print(String(scalarView))

For example, "1FAE0-1F3FD" should be nil, since it's not a single emoji ("????????"). However, in future versions, the melting face might work with skin variation, in which case it should return that single valid emoji.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

也只是曾经 2025-01-31 23:39:01

根据表情符号14.0's isemoji 返回 true 的序列中至少有一个代码点,并且该序列将形成一个单个字形。

因此,您应该首先从Unicode标量中制作一个字符串:

let scalars = [UnicodeScalar(0x1F415)!, UnicodeScalar(0x200D)!, UnicodeScalar(0x1F9BA)!]
let scalarView = String.UnicodeScalarView(scalars)
let string = String(scalarView)

然后,您可以检查它是否是表情符号:

CTLineGetGlyphCount(CTLineCreateWithAttributedString(
    NSAttributedString(string: string)
)) == 1 && 
string.unicodeScalars.contains { $0.properties.isEmoji }

或者,因为您只想检查表情符号是否可以正确显示,您可以使用 ctfontgetglyphsforcharacters 查看苹果颜色表情符号是否支持角色。

let font = UIFont(name: "AppleColorEmoji", size: 20)! as CTFont
var text = Array(string.utf16)
var glyphs = Array(repeating: 0 as CGGlyph, count: text.count)
let isEmoji = CTFontGetGlyphsForCharacters(font, &text, &glyphs, text.count) && 
    CTLineGetGlyphCount(CTLineCreateWithAttributedString(
        NSAttributedString(string: string)
    )) == 1

请注意,这两种方法都会返回误报(如将其报告为表情符号的非emojis),但不会返回虚假负面因素。

According to Emoji 14.0's data files, an emoji is either a basic emoji, a keycap sequence, a flag, a modifier sequence, or a ZWJ sequence. In each of those cases, there will be at least one code point in the sequence for which isEmoji returns true, and the sequence will form a single glyph.

So, you should make a string out of the unicode scalars first:

let scalars = [UnicodeScalar(0x1F415)!, UnicodeScalar(0x200D)!, UnicodeScalar(0x1F9BA)!]
let scalarView = String.UnicodeScalarView(scalars)
let string = String(scalarView)

Then, you can check if it is a emoji like this:

CTLineGetGlyphCount(CTLineCreateWithAttributedString(
    NSAttributedString(string: string)
)) == 1 && 
string.unicodeScalars.contains { $0.properties.isEmoji }

Alternatively, since you just want to check if the emoji can be displayed properly, you can use CTFontGetGlyphsForCharacters to see if Apple Color Emoji supports the characters.

let font = UIFont(name: "AppleColorEmoji", size: 20)! as CTFont
var text = Array(string.utf16)
var glyphs = Array(repeating: 0 as CGGlyph, count: text.count)
let isEmoji = CTFontGetGlyphsForCharacters(font, &text, &glyphs, text.count) && 
    CTLineGetGlyphCount(CTLineCreateWithAttributedString(
        NSAttributedString(string: string)
    )) == 1

Note that both of these methods will return false positives (non-emojis like ASCII letters being reported as emojis), but will not return false negatives.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文