[gtk+/gtk-3-22] Redo emoji data slightly
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-3-22] Redo emoji data slightly
- Date: Tue, 15 Aug 2017 10:41:43 +0000 (UTC)
commit c56545f7211664ccccb27a5771835465260ebea7
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Aug 13 15:16:11 2017 -0400
Redo emoji data slightly
No longer store variation sequences explicitly. Instead, put a 0
in the sequence where the modifiers will be inserted. This is more
compact, and it allows us to put variations directly into the
recent section. Update the type of the recent-emoji setting to
match these changes.
gtk/emoji/convert-emoji.c | 222 +++++++++++++------------
gtk/emoji/emoji.data | Bin 53562 -> 36967 bytes
gtk/gtkemojichooser.c | 138 +++++++++-------
gtk/org.gtk.Settings.EmojiChooser.gschema.xml | 7 +-
4 files changed, 200 insertions(+), 167 deletions(-)
---
diff --git a/gtk/emoji/convert-emoji.c b/gtk/emoji/convert-emoji.c
index 7850ccc..3474259 100644
--- a/gtk/emoji/convert-emoji.c
+++ b/gtk/emoji/convert-emoji.c
@@ -22,28 +22,31 @@
#include <string.h>
gboolean
-parse_code (GVariantBuilder *b, const char *code)
+parse_code (GVariantBuilder *b,
+ const char *code)
{
- g_auto(GStrv) strv = NULL;
- int j;
- guint32 u1;
-
- strv = g_strsplit (code, " ", -1);
- for (j = 0; strv[j]; j++) {
- guint32 u;
- char *end;
-
- u = (guint32) g_ascii_strtoull (strv[j], &end, 16);
- if (*end != '\0') {
- g_error ("failed to parse code: %s\n", strv[j]);
- return FALSE;
- }
- //if (u != 0xfe0f || strv[j+1] != 0)
- g_variant_builder_add (b, "u", u);
- u1 = u;
+ g_auto(GStrv) strv = NULL;
+ int j;
+
+ strv = g_strsplit (code, " ", -1);
+ for (j = 0; strv[j]; j++)
+ {
+ guint32 u;
+ char *end;
+
+ u = (guint32) g_ascii_strtoull (strv[j], &end, 16);
+ if (*end != '\0')
+ {
+ g_error ("failed to parse code: %s\n", strv[j]);
+ return FALSE;
}
+ if (0x1f3fb <= u && u <= 0x1f3ff)
+ g_variant_builder_add (b, "u", 0);
+ else
+ g_variant_builder_add (b, "u", u);
+ }
- return TRUE;
+ return TRUE;
}
static const char *blacklist[] = {
@@ -78,97 +81,102 @@ static const char *blacklist[] = {
int
main (int argc, char *argv[])
{
- JsonParser *parser;
- JsonNode *root;
- JsonArray *array;
- GError *error = NULL;
- guint length, i;
- GVariantBuilder builder;
- GVariant *v;
- GString *s;
- GBytes *bytes;
-
- if (argc != 3) {
- g_print ("Usage: emoji-convert INPUT OUTPUT\n");
- return 1;
+ JsonParser *parser;
+ JsonNode *root;
+ JsonArray *array;
+ GError *error = NULL;
+ guint length, i;
+ GVariantBuilder builder;
+ GVariant *v;
+ GString *s;
+ GBytes *bytes;
+
+ if (argc != 3)
+ {
+ g_print ("Usage: emoji-convert INPUT OUTPUT\n");
+ return 1;
+ }
+
+ parser = json_parser_new ();
+
+ if (!json_parser_load_from_file (parser, argv[1], &error))
+ {
+ g_error ("%s", error->message);
+ return 1;
+ }
+
+ root = json_parser_get_root (parser);
+ array = json_node_get_array (root);
+ length = json_array_get_length (array);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aus)"));
+ i = 0;
+ while (i < length)
+ {
+ JsonNode *node = json_array_get_element (array, i);
+ JsonObject *obj = json_node_get_object (node);
+ GVariantBuilder b1;
+ const char *name;
+ char *code;
+ int j;
+ gboolean skip;
+ gboolean has_variations;
+
+ i++;
+
+ g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
+
+ name = json_object_get_string_member (obj, "name");
+ code = g_strdup (json_object_get_string_member (obj, "code"));
+
+ if (strcmp (name, "world map") == 0)
+ continue;
+
+ skip = FALSE;
+ for (j = 0; blacklist[j]; j++)
+ {
+ if (strstr (name, blacklist[j]) != 0)
+ skip = TRUE;
}
-
- parser = json_parser_new ();
-
- if (!json_parser_load_from_file (parser, argv[1], &error)) {
- g_error ("%s", error->message);
- return 1;
+ if (skip)
+ continue;
+
+ has_variations = FALSE;
+ while (i < length)
+ {
+ JsonNode *node2 = json_array_get_element (array, i);
+ JsonObject *obj2 = json_node_get_object (node2);
+ const char *name2;
+ const char *code2;
+
+ name2 = json_object_get_string_member (obj2, "name");
+ code2 = json_object_get_string_member (obj2, "code");
+
+ if (!strstr (name2, "skin tone") || !g_str_has_prefix (name2, name))
+ break;
+
+ if (!has_variations)
+ {
+ has_variations = TRUE;
+ g_free (code);
+ code = g_strdup (code2);
+ }
+ i++;
}
- root = json_parser_get_root (parser);
- array = json_node_get_array (root);
- length = json_array_get_length (array);
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ausaau)"));
- i = 0;
- while (i < length) {
- JsonNode *node = json_array_get_element (array, i);
- JsonObject *obj = json_node_get_object (node);
- GVariantBuilder b1, b2;
- const char *name;
- const char *code;
- int j;
- gboolean skip;
-
- i++;
-
- g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
- g_variant_builder_init (&b2, G_VARIANT_TYPE ("aau"));
-
- name = json_object_get_string_member (obj, "name");
- code = json_object_get_string_member (obj, "code");
-
- if (strcmp (name, "world map") == 0)
- continue;
-
- skip = FALSE;
- for (j = 0; blacklist[j]; j++) {
- if (strstr (name, blacklist[j]) != 0) {
- skip = TRUE;
- break;
- }
- }
- if (skip)
- continue;
-
- if (!parse_code (&b1, code))
- return 1;
-
- while (i < length) {
- JsonNode *node2 = json_array_get_element (array, i);
- JsonObject *obj2 = json_node_get_object (node2);
- const char *name2;
- const char *code2;
- GVariantBuilder b22;
-
- name2 = json_object_get_string_member (obj2, "name");
- code2 = json_object_get_string_member (obj2, "code");
-
- if (!strstr (name2, "skin tone") || !g_str_has_prefix (name2, name))
- break;
-
- g_variant_builder_init (&b22, G_VARIANT_TYPE ("au"));
- if (!parse_code (&b22, code2))
- return 1;
-
- g_variant_builder_add (&b2, "au", &b22);
- i++;
- }
-
- g_variant_builder_add (&builder, "(ausaau)", &b1, name, &b2);
- }
+ if (!parse_code (&b1, code))
+ return 1;
- v = g_variant_builder_end (&builder);
- bytes = g_variant_get_data_as_bytes (v);
- if (!g_file_set_contents (argv[2], g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes),
&error)) {
- g_error ("%s", error->message);
- return 1;
- }
+ g_variant_builder_add (&builder, "(aus)", &b1, name);
+ }
+
+ v = g_variant_builder_end (&builder);
+ bytes = g_variant_get_data_as_bytes (v);
+ if (!g_file_set_contents (argv[2], g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &error))
+ {
+ g_error ("%s", error->message);
+ return 1;
+ }
- return 0;
+ return 0;
}
diff --git a/gtk/emoji/emoji.data b/gtk/emoji/emoji.data
index 61d1af0..12db9d4 100644
Binary files a/gtk/emoji/emoji.data and b/gtk/emoji/emoji.data differ
diff --git a/gtk/gtkemojichooser.c b/gtk/gtkemojichooser.c
index 1da725d..1bd5318 100644
--- a/gtk/gtkemojichooser.c
+++ b/gtk/gtkemojichooser.c
@@ -137,36 +137,55 @@ scroll_to_section (GtkButton *button,
static void
add_emoji (GtkWidget *box,
gboolean prepend,
- GVariantIter *iter,
- GVariant *data);
+ GVariant *item,
+ gunichar modifier);
#define MAX_RECENT (7*3)
static void
+populate_recent_section (GtkEmojiChooser *chooser)
+{
+ GVariant *variant;
+ GVariant *item;
+ GVariantIter iter;
+
+ variant = g_settings_get_value (chooser->settings, "recent-emoji");
+ g_variant_iter_init (&iter, variant);
+ while ((item = g_variant_iter_next_value (&iter)))
+ {
+ GVariant *emoji_data;
+ gunichar modifier;
+
+ emoji_data = g_variant_get_child_value (item, 0);
+ g_variant_get_child (item, 1, "u", &modifier);
+ add_emoji (chooser->recent.box, FALSE, emoji_data, modifier);
+ g_variant_unref (emoji_data);
+ g_variant_unref (item);
+ }
+ g_variant_unref (variant);
+}
+
+static void
add_recent_item (GtkEmojiChooser *chooser,
- GVariant *item)
+ GVariant *item,
+ gunichar modifier)
{
GList *children, *l;
- GVariantIter *codes;
- const char *name;
int i;
GVariantBuilder builder;
g_variant_ref (item);
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ausaau)"));
- g_variant_builder_add_value (&builder, item);
-
- g_variant_get_child (item, 1, "&s", &name);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a((aus)u)"));
+ g_variant_builder_add (&builder, "(@(aus)u)", item, modifier);
children = gtk_container_get_children (GTK_CONTAINER (chooser->recent.box));
for (l = children, i = 1; l; l = l->next, i++)
{
GVariant *item2 = g_object_get_data (G_OBJECT (l->data), "emoji-data");
- const char *name2;
+ gunichar modifier2 = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (l->data), "modifier"));
- g_variant_get_child (item2, 1, "&s", &name2);
- if (strcmp (name, name2) == 0)
+ if (modifier == modifier2 && g_variant_equal (item, item2))
{
gtk_widget_destroy (GTK_WIDGET (l->data));
i--;
@@ -178,13 +197,11 @@ add_recent_item (GtkEmojiChooser *chooser,
continue;
}
- g_variant_builder_add_value (&builder, item2);
+ g_variant_builder_add (&builder, "(@(aus)u)", item2, modifier2);
}
g_list_free (children);
- g_variant_get_child (item, 0, "au", &codes);
- add_emoji (chooser->recent.box, TRUE, codes, item);
- g_variant_iter_free (codes);
+ add_emoji (chooser->recent.box, TRUE, item, modifier);
g_settings_set_value (chooser->settings, "recent-emoji", g_variant_builder_end (&builder));
@@ -201,6 +218,7 @@ emoji_activated (GtkFlowBox *box,
GtkWidget *ebox;
GtkWidget *label;
GVariant *item;
+ gunichar modifier;
gtk_popover_popdown (GTK_POPOVER (chooser));
@@ -209,7 +227,8 @@ emoji_activated (GtkFlowBox *box,
text = g_strdup (gtk_label_get_label (GTK_LABEL (label)));
item = (GVariant*) g_object_get_data (G_OBJECT (child), "emoji-data");
- add_recent_item (chooser, item);
+ modifier = (gunichar) GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (child), "modifier"));
+ add_recent_item (chooser, item, modifier);
g_signal_emit (data, signals[EMOJI_PICKED], 0, text);
g_free (text);
@@ -227,8 +246,10 @@ long_pressed_cb (GtkGesture *gesture,
GtkWidget *box;
GVariant *emoji_data;
GtkWidget *parent_popover;
- GVariantIter *iter;
- GVariantIter *codes;
+ GVariant *codes;
+ int i;
+ gboolean has_variations;
+ gunichar modifier;
box = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
child = GTK_WIDGET (gtk_flow_box_get_child_at_pos (GTK_FLOW_BOX (box), x, y));
@@ -239,12 +260,21 @@ long_pressed_cb (GtkGesture *gesture,
if (!emoji_data)
return;
- g_variant_get_child (emoji_data, 2, "aau", &iter);
- if (g_variant_iter_n_children (iter) == 0)
+ has_variations = FALSE;
+ codes = g_variant_get_child_value (emoji_data, 0);
+ for (i = 0; i < g_variant_n_children (codes); i++)
{
- g_variant_iter_free (iter);
- return;
+ gunichar code;
+ g_variant_get_child (codes, i, "u", &code);
+ if (code == 0)
+ {
+ has_variations = TRUE;
+ break;
+ }
}
+ g_variant_unref (codes);
+ if (!has_variations)
+ return;
parent_popover = gtk_widget_get_ancestor (child, GTK_TYPE_POPOVER);
popover = gtk_popover_new (child);
@@ -261,13 +291,11 @@ long_pressed_cb (GtkGesture *gesture,
g_signal_connect (box, "child-activated", G_CALLBACK (emoji_activated), parent_popover);
- g_variant_get_child (emoji_data, 0, "au", &codes);
- add_emoji (box, FALSE, codes, emoji_data);
- g_variant_iter_free (codes);
- while (g_variant_iter_next (iter, "au", &codes))
+ add_emoji (box, FALSE, emoji_data, 0);
+ for (modifier = 0x1f3fb; modifier <= 0x1f3ff; modifier++)
{
- add_emoji (box, FALSE, codes, emoji_data);
- g_variant_iter_free (codes);
+ add_emoji (box, FALSE, emoji_data, modifier);
+ g_variant_unref (codes);
}
gtk_widget_show_all (view);
@@ -288,20 +316,30 @@ update_hover (GtkWidget *widget,
static void
add_emoji (GtkWidget *box,
gboolean prepend,
- GVariantIter *iter,
- GVariant *data)
+ GVariant *item,
+ gunichar modifier)
{
GtkWidget *child;
GtkWidget *ebox;
GtkWidget *label;
PangoAttrList *attrs;
+ GVariant *codes;
char text[64];
char *p = text;
- gunichar code;
+ int i;
- while (g_variant_iter_next (iter, "u", &code))
- p += g_unichar_to_utf8 (code, p);
- p[0] = 0;
+ codes = g_variant_get_child_value (item, 0);
+ for (i = 0; i < g_variant_n_children (codes); i++)
+ {
+ gunichar code;
+
+ g_variant_get_child (codes, i, "u", &code);
+ if (code == 0)
+ code = modifier;
+ if (code != 0)
+ p += g_unichar_to_utf8 (code, p);
+ }
+ p[0] = 0;
label = gtk_label_new (text);
attrs = pango_attr_list_new ();
@@ -312,8 +350,10 @@ add_emoji (GtkWidget *box,
child = gtk_flow_box_child_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (child), "emoji");
g_object_set_data_full (G_OBJECT (child), "emoji-data",
- g_variant_ref (data),
+ g_variant_ref (item),
(GDestroyNotify)g_variant_unref);
+ if (modifier != 0)
+ g_object_set_data (G_OBJECT (child), "modifier", GUINT_TO_POINTER (modifier));
ebox = gtk_event_box_new ();
gtk_widget_add_events (ebox, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
@@ -334,16 +374,14 @@ populate_emoji_chooser (GtkEmojiChooser *chooser)
GtkWidget *box;
bytes = g_resources_lookup_data ("/org/gtk/libgtk/emoji/emoji.data", 0, NULL);
- chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(ausaau)"), bytes, TRUE));
+ chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(aus)"), bytes, TRUE));
g_variant_iter_init (&iter, chooser->data);
box = chooser->people.box;
while ((item = g_variant_iter_next_value (&iter)))
{
- GVariantIter *codes;
const char *name;
- g_variant_get_child (item, 0, "au", &codes);
g_variant_get_child (item, 1, "&s", &name);
if (strcmp (name, chooser->body.first) == 0)
@@ -363,8 +401,7 @@ populate_emoji_chooser (GtkEmojiChooser *chooser)
else if (strcmp (name, chooser->flags.first) == 0)
box = chooser->flags.box;
- add_emoji (box, FALSE, codes, item);
- g_variant_iter_free (codes);
+ add_emoji (box, FALSE, item, 0);
}
}
@@ -514,9 +551,8 @@ static void
gtk_emoji_chooser_init (GtkEmojiChooser *chooser)
{
GtkAdjustment *adj;
- GVariant *variant;
- GVariantIter iter;
- GVariant *item;
+
+ chooser->settings = g_settings_new ("org.gtk.Settings.EmojiChooser");
gtk_widget_init_template (GTK_WIDGET (chooser));
@@ -544,19 +580,7 @@ gtk_emoji_chooser_init (GtkEmojiChooser *chooser)
setup_section (chooser, &chooser->flags, "chequered flag", 0x1f3f4);
populate_emoji_chooser (chooser);
-
- chooser->settings = g_settings_new ("org.gtk.Settings.EmojiChooser");
- variant = g_settings_get_value (chooser->settings, "recent-emoji");
- g_variant_iter_init (&iter, variant);
- while ((item = g_variant_iter_next_value (&iter)))
- {
- GVariantIter *codes;
-
- g_variant_get_child (item, 0, "au", &codes);
- add_emoji (chooser->recent.box, FALSE, codes, item);
- g_variant_iter_free (codes);
- }
- g_variant_unref (variant);
+ populate_recent_section (chooser);
}
static void
diff --git a/gtk/org.gtk.Settings.EmojiChooser.gschema.xml b/gtk/org.gtk.Settings.EmojiChooser.gschema.xml
index d720275..7105cb2 100644
--- a/gtk/org.gtk.Settings.EmojiChooser.gschema.xml
+++ b/gtk/org.gtk.Settings.EmojiChooser.gschema.xml
@@ -2,13 +2,14 @@
<schemalist>
<schema id='org.gtk.Settings.EmojiChooser' path='/org/gtk/settings/emoji-chooser/'>
- <key name='recent-emoji' type='a(ausaau)'>
+ <key name='recent-emoji' type='a((aus)u)'>
<default>[]</default>
<summary>Recently used Emoji</summary>
<description>
An array of Emoji definitions to show in the Emoji chooser. Each Emoji is
- specified as an array of codepoints, a name, and an optional array of
- nested Emoji.
+ specified as an array of codepoints and a name. The extra integer after this
+ pair is the code of the Fitzpatrick modifier to use in place of a 0 in the
+ codepoint array.
</description>
</key>
</schema>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]