[libadwaita/wip/exalm/avatar: 527/527] avatar: Fix initial extraction
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/avatar: 527/527] avatar: Fix initial extraction
- Date: Mon, 7 Feb 2022 08:44:52 +0000 (UTC)
commit e3b93248ab35a4051176a1103e500c81f67a6c36
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Mon Feb 7 13:44:45 2022 +0500
avatar: Fix initial extraction
Rewrite it using Pango - correctly handle clusters, word boundaries and
hopefully RTL.
The returned string can be empty now if there are no actual words there,
so account for that everywhere.
src/adw-avatar.c | 115 +++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 91 insertions(+), 24 deletions(-)
---
diff --git a/src/adw-avatar.c b/src/adw-avatar.c
index 6e706502..d12715fc 100644
--- a/src/adw-avatar.c
+++ b/src/adw-avatar.c
@@ -80,33 +80,100 @@ enum {
static GParamSpec *props[PROP_LAST_PROP];
static char *
-extract_initials_from_text (const char *text)
+extract_initials_from_text (AdwAvatar *self,
+ const char *text)
{
+ char *normalized = g_utf8_normalize (text, -1, G_NORMALIZE_DEFAULT_COMPOSE);
+ char *upper = g_utf8_strup (normalized, -1);
+ PangoContext *ctx = gtk_widget_get_pango_context (GTK_WIDGET (self->label));
+ PangoLayout *layout = pango_layout_new (ctx);
+ const PangoLogAttr *attrs = NULL;
GString *initials;
- char *p = g_utf8_strup (text, -1);
- char *normalized = g_utf8_normalize (g_strstrip (p), -1, G_NORMALIZE_DEFAULT_COMPOSE);
- gunichar unichar;
- char *q = NULL;
+ PangoLayoutIter *iter, *first_word = NULL, *last_word = NULL;
+ int i, n_attrs, from, to;
- g_clear_pointer (&p, g_free);
+ pango_layout_set_text (layout, upper, -1);
+ pango_layout_set_single_paragraph_mode (layout, TRUE);
+ iter = pango_layout_get_iter (layout);
+ attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
- if (normalized == NULL)
- return NULL;
+ for (i = 0; i < n_attrs; i++) {
+ PangoDirection direction_before, direction_after;
+ PangoLayoutIter *iter2;
+
+ if (!attrs[i].is_word_start) {
+ pango_layout_iter_next_char (iter);
+
+ continue;
+ }
+
+ iter2 = pango_layout_iter_copy (iter);
+ from = pango_layout_iter_get_index (iter2);
+ pango_layout_iter_next_char (iter2);
+ to = pango_layout_iter_get_index (iter2);
+ pango_layout_iter_free (iter2);
+
+ if (from == to) {
+ pango_layout_iter_next_char (iter);
+
+ continue;
+ }
+
+ direction_before = pango_layout_get_direction (layout, from);
+ direction_after = pango_layout_get_direction (layout, to);
+
+ if (direction_before != direction_after) {
+ pango_layout_iter_next_char (iter);
+
+ continue;
+ }
+
+ if (!first_word)
+ first_word = pango_layout_iter_copy (iter);
+
+ if (last_word)
+ pango_layout_iter_free (last_word);
+
+ last_word = pango_layout_iter_copy (iter);
+
+ pango_layout_iter_next_char (iter);
+ }
+
+ if (!first_word) {
+ g_free (normalized);
+ g_free (upper);
+
+ return g_strdup ("");
+ }
initials = g_string_new ("");
- unichar = g_utf8_get_char (normalized);
- g_string_append_unichar (initials, unichar);
+ from = pango_layout_iter_get_index (first_word);
+ pango_layout_iter_next_cluster (first_word);
+ to = pango_layout_iter_get_index (first_word);
+
+ if (pango_layout_get_direction (layout, from) == PANGO_DIRECTION_RTL)
+ g_string_prepend_len (initials, upper + to, from - to);
+ else
+ g_string_append_len (initials, upper + from, to - from);
- q = g_utf8_strrchr (normalized, -1, ' ');
- if (q != NULL && g_utf8_next_char (q) != NULL) {
- q = g_utf8_next_char (q);
+ if (from != pango_layout_iter_get_index (last_word)) {
+ from = pango_layout_iter_get_index (last_word);
+ pango_layout_iter_next_cluster (last_word);
+ to = pango_layout_iter_get_index (last_word);
- unichar = g_utf8_get_char (q);
- g_string_append_unichar (initials, unichar);
+ if (pango_layout_get_direction (layout, from) == PANGO_DIRECTION_RTL)
+ g_string_prepend_len (initials, upper + to, from - to);
+ else
+ g_string_append_len (initials, upper + from, to - from);
}
+ pango_layout_iter_free (iter);
+ pango_layout_iter_free (first_word);
+ pango_layout_iter_free (last_word);
+ g_object_unref (layout);
g_free (normalized);
+ g_free (upper);
return g_string_free (initials, FALSE);
}
@@ -115,7 +182,8 @@ static void
update_visibility (AdwAvatar *self)
{
gboolean has_custom_image = gtk_image_get_paintable (self->custom_image) != NULL;
- gboolean has_initials = self->show_initials && self->text && strlen (self->text);
+ const char *initials = gtk_label_get_label (self->label);
+ gboolean has_initials = self->show_initials && initials && initials[0];
gtk_widget_set_visible (GTK_WIDGET (self->label), !has_custom_image && has_initials);
gtk_widget_set_visible (GTK_WIDGET (self->icon), !has_custom_image && !has_initials);
@@ -153,17 +221,19 @@ update_initials (AdwAvatar *self)
{
char *initials;
- if (gtk_image_get_paintable (self->custom_image) != NULL ||
- !self->show_initials ||
- self->text == NULL ||
- strlen (self->text) == 0)
+ if (self->custom_image_source || !self->show_initials) {
+ update_visibility (self);
+
return;
+ }
- initials = extract_initials_from_text (self->text);
+ initials = extract_initials_from_text (self, self->text);
gtk_label_set_label (self->label, initials);
g_free (initials);
+
+ update_visibility (self);
}
static void
@@ -427,7 +497,6 @@ adw_avatar_init (AdwAvatar *self)
update_initials (self);
update_font_size (self);
update_icon (self);
- update_visibility (self);
g_signal_connect (self, "notify::root", G_CALLBACK (update_font_size), NULL);
}
@@ -546,7 +615,6 @@ adw_avatar_set_text (AdwAvatar *self,
update_initials (self);
update_font_size (self);
- update_visibility (self);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TEXT]);
}
@@ -591,7 +659,6 @@ adw_avatar_set_show_initials (AdwAvatar *self,
update_initials (self);
update_font_size (self);
- update_visibility (self);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SHOW_INITIALS]);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]