diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c index 9925d903d..4cf56b5ba 100644 --- a/clutter/clutter-text.c +++ b/clutter/clutter-text.c @@ -112,8 +112,18 @@ struct _ClutterTextPrivate LayoutCache cached_layouts[N_CACHED_LAYOUTS]; guint cache_age; + /* These are the attributes set by the attributes property */ PangoAttrList *attrs; + /* These are the attributes derived from the text when the + use-markup property is set */ + PangoAttrList *markup_attrs; + /* This is the combination of the above two lists. It is set to NULL + whenever either of them changes and then regenerated by merging + the two lists whenever a layout is needed */ PangoAttrList *effective_attrs; + /* These are the attributes for the preedit string. These are merged + with the effective attributes into a temporary list before + creating a layout */ PangoAttrList *preedit_attrs; guint alignment : 2; @@ -287,6 +297,52 @@ clutter_text_get_display_text (ClutterText *self) } } +static void +clutter_text_ensure_effective_attributes (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + + /* If we already have the effective attributes then we don't need to + do anything */ + if (priv->effective_attrs == NULL) + { + if (priv->attrs) + { + /* If there are no markup attributes then we can just use + these attributes directly */ + if (priv->markup_attrs == NULL) + priv->effective_attrs = pango_attr_list_ref (priv->attrs); + else + { + /* Otherwise we need to merge the two lists */ + PangoAttrIterator *iter; + GSList *attributes, *l; + + priv->effective_attrs = pango_attr_list_copy (priv->markup_attrs); + + iter = pango_attr_list_get_iterator (priv->attrs); + do + { + attributes = pango_attr_iterator_get_attrs (iter); + + for (l = attributes; l != NULL; l = l->next) + { + PangoAttribute *attr = l->data; + + pango_attr_list_insert (priv->effective_attrs, attr); + } + + g_slist_free (attributes); + } + while (pango_attr_iterator_next (iter)); + } + } + else if (priv->markup_attrs) + /* We can just use the markup attributes directly */ + priv->effective_attrs = pango_attr_list_ref (priv->markup_attrs); + } +} + static PangoLayout * clutter_text_create_layout_no_cache (ClutterText *text, gfloat allocation_width, @@ -333,8 +389,15 @@ clutter_text_create_layout_no_cache (ClutterText *text, else pango_layout_set_text (layout, contents, contents_len); - if (!priv->editable && priv->effective_attrs) - pango_layout_set_attributes (layout, priv->effective_attrs); + if (!priv->editable) + { + /* This will merge the markup attributes and the attributes + property if needed */ + clutter_text_ensure_effective_attributes (text); + + if (priv->effective_attrs) + pango_layout_set_attributes (layout, priv->effective_attrs); + } pango_layout_set_alignment (layout, priv->alignment); pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode); @@ -749,39 +812,6 @@ clutter_text_delete_selection (ClutterText *self) return TRUE; } -static void -clutter_text_merge_attributes (ClutterText *self) -{ - ClutterTextPrivate *priv = self->priv; - PangoAttrIterator *iter; - GSList *attributes, *l; - - if (!priv->attrs) - return; - - if (!priv->effective_attrs) - { - priv->effective_attrs = pango_attr_list_ref (priv->attrs); - return; - } - - iter = pango_attr_list_get_iterator (priv->attrs); - do - { - attributes = pango_attr_iterator_get_attrs (iter); - - for (l = attributes; l != NULL; l = l->next) - { - PangoAttribute *attr = l->data; - - pango_attr_list_insert (priv->effective_attrs, attr); - } - - g_slist_free (attributes); - } - while (pango_attr_iterator_next (iter)); -} - static inline void clutter_text_set_text_internal (ClutterText *self, const gchar *text) @@ -885,15 +915,18 @@ clutter_text_set_markup_internal (ClutterText *self, g_free (text); } - if (attrs) + /* Store the new markup attributes */ + if (priv->markup_attrs) + pango_attr_list_unref (priv->markup_attrs); + priv->markup_attrs = attrs; + + /* Clear the effective attributes so they will be regenerated when a + layout is created */ + if (priv->effective_attrs) { - if (priv->effective_attrs) - pango_attr_list_unref (priv->effective_attrs); - - priv->effective_attrs = attrs; + pango_attr_list_unref (priv->effective_attrs); + priv->effective_attrs = NULL; } - - clutter_text_merge_attributes (self); } static void @@ -1146,6 +1179,8 @@ clutter_text_finalize (GObject *gobject) if (priv->attrs) pango_attr_list_unref (priv->attrs); + if (priv->markup_attrs) + pango_attr_list_unref (priv->markup_attrs); if (priv->effective_attrs) pango_attr_list_unref (priv->effective_attrs); if (priv->preedit_attrs) @@ -3858,18 +3893,13 @@ clutter_text_set_attributes (ClutterText *self, priv->attrs = attrs; - if (!priv->use_markup) + /* Clear the effective attributes so they will be regenerated when a + layout is created */ + if (priv->effective_attrs) { - if (attrs) - pango_attr_list_ref (attrs); - - if (priv->effective_attrs) - pango_attr_list_unref (priv->effective_attrs); - - priv->effective_attrs = attrs; + pango_attr_list_unref (priv->effective_attrs); + priv->effective_attrs = NULL; } - else - clutter_text_set_markup_internal (self, priv->text); clutter_text_dirty_cache (self);