summaryrefslogtreecommitdiff
path: root/gtk/gtkfontchooserwidget.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2015-07-22 15:04:34 +0200
committerBenjamin Otte <otte@redhat.com>2015-07-22 16:01:21 +0200
commit31191d5566847ab6278d736066b0fd49241db3a9 (patch)
treee02b4166933e9fa7e165c59cdf509ecb34b887ca /gtk/gtkfontchooserwidget.c
parent3fc5d09890e453dd85e94b78f4649abeb2fce53f (diff)
downloadgtk+-31191d5566847ab6278d736066b0fd49241db3a9.tar.gz
fontchooserwidget: Refactor code so we actually optimize
Previously, we would pango_font_describe() every time the code ran and we wouldn't ever hit the optimized quick exit. The code now is a lot more complex because the compute-actual-value-when-required-the-first-time approach is not supported out of the box in GtkTreeModel (or GValue).
Diffstat (limited to 'gtk/gtkfontchooserwidget.c')
-rw-r--r--gtk/gtkfontchooserwidget.c164
1 files changed, 105 insertions, 59 deletions
diff --git a/gtk/gtkfontchooserwidget.c b/gtk/gtkfontchooserwidget.c
index 317aef79d3..a30f8af144 100644
--- a/gtk/gtkfontchooserwidget.c
+++ b/gtk/gtkfontchooserwidget.c
@@ -145,9 +145,9 @@ static void gtk_font_chooser_widget_set_font (GtkFontChooserWidget *
const gchar *fontname);
static PangoFontDescription *gtk_font_chooser_widget_get_font_desc (GtkFontChooserWidget *fontchooser);
-static void gtk_font_chooser_widget_merge_font_desc(GtkFontChooserWidget *fontchooser,
- PangoFontDescription *font_desc,
- GtkTreeIter *iter);
+static void gtk_font_chooser_widget_merge_font_desc(GtkFontChooserWidget *fontchooser,
+ const PangoFontDescription *font_desc,
+ GtkTreeIter *iter);
static void gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser,
PangoFontDescription *font_desc);
@@ -179,6 +179,63 @@ G_DEFINE_TYPE_WITH_CODE (GtkFontChooserWidget, gtk_font_chooser_widget, GTK_TYPE
G_IMPLEMENT_INTERFACE (GTK_TYPE_FONT_CHOOSER,
gtk_font_chooser_widget_iface_init))
+typedef struct _GtkDelayedFontDescription GtkDelayedFontDescription;
+struct _GtkDelayedFontDescription {
+ PangoFontFace *face;
+ PangoFontDescription *desc;
+ guint ref_count;
+};
+
+static GtkDelayedFontDescription *
+gtk_delayed_font_description_new (PangoFontFace *face)
+{
+ GtkDelayedFontDescription *result;
+
+ result = g_slice_new0 (GtkDelayedFontDescription);
+
+ result->face = g_object_ref (face);
+ result->desc = NULL;
+ result->ref_count = 1;
+
+ return result;
+}
+
+static GtkDelayedFontDescription *
+gtk_delayed_font_description_ref (GtkDelayedFontDescription *desc)
+{
+ desc->ref_count++;
+
+ return desc;
+}
+
+static void
+gtk_delayed_font_description_unref (GtkDelayedFontDescription *desc)
+{
+ desc->ref_count--;
+
+ if (desc->ref_count > 0)
+ return;
+
+ g_object_unref (desc->face);
+ if (desc->desc)
+ pango_font_description_free (desc->desc);
+
+ g_slice_free (GtkDelayedFontDescription, desc);
+}
+
+static const PangoFontDescription *
+gtk_delayed_font_description_get (GtkDelayedFontDescription *desc)
+{
+ if (desc->desc == NULL)
+ desc->desc = pango_font_face_describe (desc->face);
+
+ return desc->desc;
+}
+
+#define GTK_TYPE_DELAYED_FONT_DESCRIPTION (gtk_delayed_font_description_get_type ())
+G_DEFINE_BOXED_TYPE (GtkDelayedFontDescription, gtk_delayed_font_description,
+ gtk_delayed_font_description_ref,
+ gtk_delayed_font_description_unref)
static void
gtk_font_chooser_widget_set_property (GObject *object,
guint prop_id,
@@ -379,39 +436,13 @@ row_activated_cb (GtkTreeView *view,
g_free (fontname);
}
-static PangoFontDescription *
-tree_model_get_font_description (GtkTreeModel *model,
- GtkTreeIter *iter)
-{
- PangoFontDescription *desc, *face_desc;
- PangoFontFace *face;
-
- gtk_tree_model_get (model, iter,
- FONT_DESC_COLUMN, &desc,
- -1);
- if (pango_font_description_get_set_fields (desc) != 0)
- return desc;
-
- gtk_tree_model_get (model, iter,
- FACE_COLUMN, &face,
- -1);
- face_desc = pango_font_face_describe (face);
- g_object_unref (face);
-
- pango_font_description_merge (desc, face_desc, TRUE);
-
- pango_font_description_free (face_desc);
-
- return desc;
-}
-
static void
cursor_changed_cb (GtkTreeView *treeview,
gpointer user_data)
{
GtkFontChooserWidget *fontchooser = user_data;
GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
- PangoFontDescription *desc;
+ GtkDelayedFontDescription *desc;
GtkTreeIter filter_iter, iter;
GtkTreePath *path = NULL;
@@ -431,9 +462,15 @@ cursor_changed_cb (GtkTreeView *treeview,
gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (priv->filter_model),
&iter,
&filter_iter);
- desc = tree_model_get_font_description (priv->model, &iter);
+ gtk_tree_model_get (priv->filter_model, &iter,
+ FONT_DESC_COLUMN, &desc,
+ -1);
- gtk_font_chooser_widget_merge_font_desc (fontchooser, desc, &iter);
+ gtk_font_chooser_widget_merge_font_desc (fontchooser,
+ gtk_delayed_font_description_get (desc),
+ &iter);
+
+ gtk_delayed_font_description_unref (desc);
}
static gboolean
@@ -515,6 +552,8 @@ gtk_font_chooser_widget_class_init (GtkFontChooserWidgetClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ g_type_ensure (GTK_TYPE_DELAYED_FONT_DESCRIPTION);
+
widget_class->screen_changed = gtk_font_chooser_widget_screen_changed;
widget_class->style_updated = gtk_font_chooser_widget_style_updated;
@@ -676,23 +715,23 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser,
for (j = 0; j < n_faces; j++)
{
- PangoFontDescription *empty_font_desc;
+ GtkDelayedFontDescription *desc;
const gchar *face_name;
face_name = pango_font_face_get_face_name (faces[j]);
family_and_face = g_strconcat (fam_name, " ", face_name, NULL);
- empty_font_desc = pango_font_description_new ();
+ desc = gtk_delayed_font_description_new (faces[j]);
gtk_list_store_insert_with_values (list_store, &iter, -1,
FAMILY_COLUMN, families[i],
FACE_COLUMN, faces[j],
- FONT_DESC_COLUMN, empty_font_desc,
+ FONT_DESC_COLUMN, desc,
PREVIEW_TITLE_COLUMN, family_and_face,
-1);
g_free (family_and_face);
- pango_font_description_free (empty_font_desc);
+ gtk_delayed_font_description_unref (desc);
}
g_free (faces);
@@ -830,22 +869,21 @@ gtk_font_chooser_widget_cell_data_func (GtkTreeViewColumn *column,
gpointer user_data)
{
GtkFontChooserWidget *fontchooser = user_data;
- PangoFontDescription *font_desc;
+ GtkDelayedFontDescription *desc;
PangoAttrList *attrs;
char *preview_title, *text;
gsize first_line_len;
- font_desc = tree_model_get_font_description (tree_model, iter);
-
gtk_tree_model_get (tree_model, iter,
PREVIEW_TITLE_COLUMN, &preview_title,
+ FONT_DESC_COLUMN, &desc,
-1);
text = g_strconcat (preview_title, "\n", fontchooser->priv->preview_text, NULL);
first_line_len = strlen (preview_title) + 1;
attrs = gtk_font_chooser_widget_get_preview_attributes (fontchooser,
- font_desc,
+ gtk_delayed_font_description_get (desc),
first_line_len);
g_object_set (cell,
@@ -853,7 +891,7 @@ gtk_font_chooser_widget_cell_data_func (GtkTreeViewColumn *column,
"text", text,
NULL);
- pango_font_description_free (font_desc);
+ gtk_delayed_font_description_unref (desc);
pango_attr_list_unref (attrs);
g_free (text);
g_free (preview_title);
@@ -928,26 +966,37 @@ gtk_font_chooser_widget_find_font (GtkFontChooserWidget *fontchooser,
valid;
valid = gtk_tree_model_iter_next (priv->model, iter))
{
- PangoFontDescription *desc;
+ GtkDelayedFontDescription *desc;
+ PangoFontDescription *merged;
PangoFontFamily *family;
gtk_tree_model_get (priv->model, iter,
FAMILY_COLUMN, &family,
+ FONT_DESC_COLUMN, &desc,
-1);
if (!my_pango_font_family_equal (pango_font_description_get_family (font_desc),
pango_font_family_get_name (family)))
- continue;
+ {
+ gtk_delayed_font_description_unref (desc);
+ g_object_unref (family);
+ continue;
+ }
- desc = tree_model_get_font_description (priv->model, iter);
+ merged = pango_font_description_copy_static (gtk_delayed_font_description_get (desc));
- pango_font_description_merge_static (desc, font_desc, FALSE);
- if (pango_font_description_equal (desc, font_desc)) {
- pango_font_description_free (desc);
- break;
- }
+ pango_font_description_merge_static (merged, font_desc, FALSE);
+ if (pango_font_description_equal (merged, font_desc))
+ {
+ gtk_delayed_font_description_unref (desc);
+ pango_font_description_free (merged);
+ g_object_unref (family);
+ break;
+ }
- pango_font_description_free (desc);
+ gtk_delayed_font_description_unref (desc);
+ pango_font_description_free (merged);
+ g_object_unref (family);
}
return valid;
@@ -1092,9 +1141,9 @@ gtk_font_chooser_widget_ensure_selection (GtkFontChooserWidget *fontchooser)
}
static void
-gtk_font_chooser_widget_merge_font_desc (GtkFontChooserWidget *fontchooser,
- PangoFontDescription *font_desc,
- GtkTreeIter *iter)
+gtk_font_chooser_widget_merge_font_desc (GtkFontChooserWidget *fontchooser,
+ const PangoFontDescription *font_desc,
+ GtkTreeIter *iter)
{
GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
PangoFontMask mask;
@@ -1107,10 +1156,7 @@ gtk_font_chooser_widget_merge_font_desc (GtkFontChooserWidget *fontchooser,
/* sucky test, because we can't restrict the comparison to
* only the parts that actually do get merged */
if (pango_font_description_equal (font_desc, priv->font_desc))
- {
- pango_font_description_free (font_desc);
- return;
- }
+ return;
pango_font_description_merge (priv->font_desc, font_desc, TRUE);
@@ -1140,8 +1186,6 @@ gtk_font_chooser_widget_merge_font_desc (GtkFontChooserWidget *fontchooser,
gtk_font_chooser_widget_update_preview_attributes (fontchooser);
- pango_font_description_free (font_desc); /* adopted */
-
g_object_notify (G_OBJECT (fontchooser), "font");
g_object_notify (G_OBJECT (fontchooser), "font-desc");
}
@@ -1171,6 +1215,8 @@ gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser,
{
gtk_font_chooser_widget_merge_font_desc (fontchooser, font_desc, &priv->font_iter);
}
+
+ pango_font_description_free (font_desc);
}
static const gchar*