forked from AuroraMiddleware/gtk
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).
This commit is contained in:
parent
3fc5d09890
commit
31191d5566
@ -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*
|
||||
|
@ -8,7 +8,7 @@
|
||||
<!-- column-name face -->
|
||||
<column type="PangoFontFace"/>
|
||||
<!-- column-name description -->
|
||||
<column type="PangoFontDescription"/>
|
||||
<column type="GtkDelayedFontDescription"/>
|
||||
<!-- column-name preview-title -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
|
Loading…
Reference in New Issue
Block a user