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* diff --git a/gtk/ui/gtkfontchooserwidget.ui b/gtk/ui/gtkfontchooserwidget.ui index 429dd2b648..98b6b0edb1 100644 --- a/gtk/ui/gtkfontchooserwidget.ui +++ b/gtk/ui/gtkfontchooserwidget.ui @@ -8,7 +8,7 @@ - +