mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
text: Store the markup attributes separately
Previously when the markup property is set it would generate an attribute list from the markup and then merge it with the attributes from the attribute property and store it as the effective attributes. The markup attributes and the marked up text would then be forgotten. This breaks if the application then later changes the attributes property because it would try to regenerate the effective attributes from the markup text but the stored text no longer contains any markup. If the original markup text happened to contain entities like '<' they would end up causing parse errors because they would be converted to the actual symbols. To fix this the attributes from the markup are now stored independently from the effective attributes. The effective attributes are now regenerated if either set of attributes changes right before a layout is created. http://bugzilla.openedhand.com/show_bug.cgi?id=1940
This commit is contained in:
parent
32b456fc8c
commit
59105341bc
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user