Merge branch 'fix-emoji-pres' into 'main'

emoji: Fix presentation selector handling

See merge request GNOME/gtk!6986
This commit is contained in:
Matthias Clasen 2024-03-07 00:23:41 +00:00
commit cc17577763
28 changed files with 53 additions and 17 deletions

Binary file not shown.

View File

@ -24,9 +24,14 @@
/* The format of the generated data is: a(aussasasu).
* Each member of the array has the following fields:
* au - sequence of unicode codepoints. If the
* sequence contains a 0, it marks the point
* where skin tone modifiers should be inserted
* au - sequence of unicode codepoints, including the emoji presentation
* selector (FE0F) where necessary. skin tone variations are represented
* with either the first tone code point (1F3FB) or 0. the choice indicates
* the handling of the generic sequence (i.e., no tone), which may have a
* default text presentation and thus require the emoji presentation
* selector (unlike sequences with a tone, which are always presented as
* emojis). 0 indicates the text case, that is, replace this code point
* with FE0F, while 1F3FB indicates this code point should be omitted.
* s - name in english, e.g. "man worker"
* s - name in locale
* as - keywords in english, e.g. "man", "worker"
@ -48,7 +53,8 @@
gboolean
parse_code (GVariantBuilder *b,
const char *code)
const char *code,
gboolean needs_presentation_selector)
{
g_auto(GStrv) strv = NULL;
int j;
@ -66,11 +72,31 @@ parse_code (GVariantBuilder *b,
return FALSE;
}
if (0x1f3fb <= u && u <= 0x1f3ff)
g_variant_builder_add (b, "u", 0);
{
if (needs_presentation_selector)
{
if (strv[j+1])
{
g_error ("unexpected inner skin tone in default-text generic sequence: %s\n", code);
return FALSE;
}
g_variant_builder_add (b, "u", 0);
needs_presentation_selector = FALSE;
}
else
{
g_variant_builder_add (b, "u", 0x1f3fb);
}
}
else
g_variant_builder_add (b, "u", u);
{
g_variant_builder_add (b, "u", u);
}
}
if (needs_presentation_selector)
g_variant_builder_add (b, "u", 0xfe0f);
return TRUE;
}
@ -120,7 +146,6 @@ main (int argc, char *argv[])
array_en = json_node_get_array (root_en);
length_en = json_array_get_length (array_en);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aussasasu)"));
for (i = 0; i < length; i++)
{
@ -133,13 +158,21 @@ main (int argc, char *argv[])
const char *name;
const char *name_en;
char *code;
const char *text;
gboolean needs_presentation_selector;
if (!json_object_has_member (obj, "group"))
continue;
if (!json_object_has_member (obj_en, "group"))
continue;
group = json_object_get_int_member (obj, "group");
name = json_object_get_string_member (obj, "label");
name_en = json_object_get_string_member (obj_en, "label");
if (g_str_has_suffix (name_en, "skin tone"))
continue;
if (json_object_has_member (obj, "skins") && json_object_has_member (obj_en, "skins"))
{
JsonArray *a2 = json_object_get_array_member (obj, "skins");
@ -151,9 +184,12 @@ main (int argc, char *argv[])
{
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
}
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
if (!parse_code (&b1, code))
text = json_object_get_string_member (obj, "text");
needs_presentation_selector = *text != '\0' && json_object_get_int_member (obj, "type") == 0;
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
if (!parse_code (&b1, code, needs_presentation_selector))
return 1;
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as"));

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -449,7 +449,7 @@ static gboolean
has_variations (GVariant *emoji_data)
{
GVariant *codes;
int i;
gsize i;
gboolean has_variations;
has_variations = FALSE;
@ -458,7 +458,7 @@ has_variations (GVariant *emoji_data)
{
gunichar code;
g_variant_get_child (codes, i, "u", &code);
if (code == 0)
if (code == 0 || code == 0x1f3fb)
{
has_variations = TRUE;
break;
@ -571,15 +571,14 @@ add_emoji (GtkWidget *box,
{
g_variant_get_child (codes, i, "u", &code);
if (code == 0)
code = modifier != 0 ? modifier : 0xfe0f;
if (code == 0x1f3fb)
code = modifier;
if (code != 0)
p += g_unichar_to_utf8 (code, p);
}
g_variant_unref (codes);
if (code != 0xFE0F && code != 0xFE0E)
p += g_unichar_to_utf8 (0xFE0F, p); /* Append a variation selector, if there isn't one already */
p[0] = 0;
label = gtk_label_new (text);

View File

@ -409,7 +409,7 @@ has_variations (GVariant *emoji_data)
{
gunichar code;
g_variant_get_child (codes, i, "u", &code);
if (code == 0)
if (code == 0 || code == 0x1f3fb)
{
has_variations = TRUE;
break;
@ -438,12 +438,13 @@ get_text (GVariant *emoji_data,
g_variant_get_child (codes, i, "u", &code);
if (code == 0)
code = modifier != 0 ? modifier : 0xfe0f;
if (code == 0x1f3fb)
code = modifier;
if (code != 0)
p += g_unichar_to_utf8 (code, p);
}
g_variant_unref (codes);
p += g_unichar_to_utf8 (0xFE0F, p); /* U+FE0F is the Emoji variation selector */
p[0] = 0;
}

View File

@ -9,7 +9,7 @@
An array of Emoji definitions to show in the Emoji chooser. Each Emoji is
specified as an array of codepoints, name and keywords. The extra
integer after this pair is the code of the Fitzpatrick modifier to use in
place of a 0 in the codepoint array.
place of a modifier placeholder (0 or 0x1F3FB) in the codepoint array.
</description>
</key>
</schema>