summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-06-10 11:48:52 +0000
committerMatthias Clasen <mclasen@redhat.com>2020-06-10 11:48:52 +0000
commite6b03b9f097552829acd7c54ce222c5dc7eb2b65 (patch)
tree2a0c1c637f078118cd884d956e139048d8ab22f2
parent7abe91c208ce7f0c1f6e6c4b13df4de7a664ffa5 (diff)
parent1bb4e61c3285f95e01f13d70354716c11c27ce39 (diff)
downloadpango-e6b03b9f097552829acd7c54ce222c5dc7eb2b65.tar.gz
Merge branch 'wip/baedert/for-master' into 'master'
Wip/baedert/for master See merge request GNOME/pango!194
-rw-r--r--pango/pango-attributes-private.h11
-rw-r--r--pango/pango-attributes.c671
-rw-r--r--pango/pango-context.c3
-rw-r--r--pango/pango-layout.c6
-rw-r--r--pango/pango-ot-info.c7
-rw-r--r--pango/pango-tabs.c3
-rw-r--r--pango/pangocairo-render.c2
-rw-r--r--pango/pangofc-fontmap.c2
-rw-r--r--tests/testattributes.c71
9 files changed, 391 insertions, 385 deletions
diff --git a/pango/pango-attributes-private.h b/pango/pango-attributes-private.h
index b913cc2f..f7384fd0 100644
--- a/pango/pango-attributes-private.h
+++ b/pango/pango-attributes-private.h
@@ -22,8 +22,12 @@
struct _PangoAttrIterator
{
- GSList *next_attribute;
- GList *attribute_stack;
+ GPtrArray *attrs; /* From the list */
+ guint n_attrs; /* Copied from the list */
+
+ GPtrArray *attribute_stack;
+
+ guint attr_index;
guint start_index;
guint end_index;
};
@@ -31,8 +35,7 @@ struct _PangoAttrIterator
struct _PangoAttrList
{
guint ref_count;
- GSList *attributes;
- GSList *attributes_tail;
+ GPtrArray *attributes;
};
void _pango_attr_list_init (PangoAttrList *list);
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 97c7aeaf..239fc935 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1311,7 +1311,6 @@ _pango_attr_list_init (PangoAttrList *list)
{
list->ref_count = 1;
list->attributes = NULL;
- list->attributes_tail = NULL;
}
/**
@@ -1356,18 +1355,19 @@ pango_attr_list_ref (PangoAttrList *list)
void
_pango_attr_list_destroy (PangoAttrList *list)
{
- GSList *tmp_list;
+ guint i, p;
- tmp_list = list->attributes;
- while (tmp_list)
+ if (!list->attributes)
+ return;
+
+ for (i = 0, p = list->attributes->len; i < p; i++)
{
- PangoAttribute *attr = tmp_list->data;
- tmp_list = tmp_list->next;
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
attr->klass->destroy (attr);
}
- g_slist_free (list->attributes);
+ g_ptr_array_free (list->attributes, TRUE);
}
/**
@@ -1408,27 +1408,15 @@ PangoAttrList *
pango_attr_list_copy (PangoAttrList *list)
{
PangoAttrList *new;
- GSList *iter;
- GSList *new_attrs;
if (list == NULL)
return NULL;
new = pango_attr_list_new ();
+ if (!list->attributes || list->attributes->len == 0)
+ return new;
- iter = list->attributes;
- new_attrs = NULL;
- while (iter != NULL)
- {
- new_attrs = g_slist_prepend (new_attrs,
- pango_attribute_copy (iter->data));
-
- iter = g_slist_next (iter);
- }
-
- /* we're going to reverse the nodes, so head becomes tail */
- new->attributes_tail = new_attrs;
- new->attributes = g_slist_reverse (new_attrs);
+ new->attributes = g_ptr_array_copy (list->attributes, (GCopyFunc)pango_attribute_copy, NULL);
return new;
}
@@ -1438,47 +1426,42 @@ pango_attr_list_insert_internal (PangoAttrList *list,
PangoAttribute *attr,
gboolean before)
{
- GSList *tmp_list, *prev, *link;
- guint start_index = attr->start_index;
+ const guint start_index = attr->start_index;
+ PangoAttribute *last_attr;
- if (!list->attributes)
+ if (G_UNLIKELY (!list->attributes))
+ list->attributes = g_ptr_array_new ();
+
+ if (list->attributes->len == 0)
{
- list->attributes = g_slist_prepend (NULL, attr);
- list->attributes_tail = list->attributes;
+ g_ptr_array_add (list->attributes, attr);
+ return;
}
- else if (((PangoAttribute *)list->attributes_tail->data)->start_index < start_index ||
- (!before && ((PangoAttribute *)list->attributes_tail->data)->start_index == start_index))
+
+ g_assert (list->attributes->len > 0);
+
+ last_attr = g_ptr_array_index (list->attributes, list->attributes->len - 1);
+
+ if (last_attr->start_index < start_index ||
+ (!before && last_attr->start_index == start_index))
{
- list->attributes_tail = g_slist_append (list->attributes_tail, attr);
- list->attributes_tail = list->attributes_tail->next;
- g_assert (list->attributes_tail);
+ g_ptr_array_add (list->attributes, attr);
}
else
{
- prev = NULL;
- tmp_list = list->attributes;
- while (1)
- {
- PangoAttribute *tmp_attr = tmp_list->data;
-
- if (tmp_attr->start_index > start_index ||
- (before && tmp_attr->start_index == start_index))
- {
- link = g_slist_alloc ();
- link->next = tmp_list;
- link->data = attr;
-
- if (prev)
- prev->next = link;
- else
- list->attributes = link;
+ guint i, p;
- break;
- }
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *cur = g_ptr_array_index (list->attributes, i);
- prev = tmp_list;
- tmp_list = tmp_list->next;
- }
+ if (cur->start_index > start_index ||
+ (before && cur->start_index == start_index))
+ {
+ g_ptr_array_insert (list->attributes, i, attr);
+ break;
+ }
+ }
}
}
@@ -1533,7 +1516,7 @@ pango_attr_list_insert_before (PangoAttrList *list,
* and be merged with any adjoining attributes that are identical.
*
* This function is slower than pango_attr_list_insert() for
- * creating a attribute list in order (potentially much slower
+ * creating an attribute list in order (potentially much slower
* for large lists). However, pango_attr_list_insert() is not
* suitable for continually changing a set of attributes
* since it never removes or combines existing attributes.
@@ -1542,7 +1525,7 @@ void
pango_attr_list_change (PangoAttrList *list,
PangoAttribute *attr)
{
- GSList *tmp_list, *prev, *link;
+ guint i, p;
guint start_index = attr->start_index;
guint end_index = attr->end_index;
@@ -1554,177 +1537,119 @@ pango_attr_list_change (PangoAttrList *list,
return;
}
- tmp_list = list->attributes;
- prev = NULL;
- while (1)
+ if (!list->attributes || list->attributes->len == 0)
{
- PangoAttribute *tmp_attr;
-
- if (!tmp_list ||
- ((PangoAttribute *)tmp_list->data)->start_index > start_index)
- {
- /* We need to insert a new attribute
- */
- link = g_slist_alloc ();
- link->next = tmp_list;
- link->data = attr;
-
- if (prev)
- prev->next = link;
- else
- list->attributes = link;
+ pango_attr_list_insert (list, attr);
+ return;
+ }
- if (!tmp_list)
- list->attributes_tail = link;
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
- prev = link;
- tmp_list = prev->next;
- break;
- }
+ if (tmp_attr->start_index > start_index)
+ {
+ g_ptr_array_insert (list->attributes, i, attr);
+ break;
+ }
- tmp_attr = tmp_list->data;
+ if (tmp_attr->klass->type != attr->klass->type)
+ continue;
- if (tmp_attr->klass->type == attr->klass->type &&
- tmp_attr->end_index >= start_index)
- {
- /* We overlap with an existing attribute */
- if (pango_attribute_equal (tmp_attr, attr))
- {
- /* We can merge the new attribute with this attribute
- */
- if (tmp_attr->end_index >= end_index)
- {
- /* We are totally overlapping the previous attribute.
- * No action is needed.
- */
- pango_attribute_destroy (attr);
- return;
- }
- tmp_attr->end_index = end_index;
- pango_attribute_destroy (attr);
+ if (tmp_attr->end_index < start_index)
+ continue; /* This attr does not overlap with the new one */
- attr = tmp_attr;
+ g_assert (tmp_attr->end_index >= start_index);
+ g_assert (start_index < tmp_attr->end_index);
- prev = tmp_list;
- tmp_list = tmp_list->next;
+ if (pango_attribute_equal (tmp_attr, attr))
+ {
+ /* We can merge the new attribute with this attribute
+ */
+ if (tmp_attr->end_index >= end_index)
+ {
+ /* We are totally overlapping the previous attribute.
+ * No action is needed.
+ */
+ g_ptr_array_remove_index (list->attributes, i);
+ pango_attribute_destroy (attr);
+ return;
+ }
- break;
- }
- else
- {
- /* Split, truncate, or remove the old attribute
- */
- if (tmp_attr->end_index > attr->end_index)
- {
- PangoAttribute *end_attr = pango_attribute_copy (tmp_attr);
+ tmp_attr->end_index = end_index;
+ pango_attribute_destroy (attr);
- end_attr->start_index = attr->end_index;
- pango_attr_list_insert (list, end_attr);
- }
+ attr = tmp_attr;
+ break;
+ }
+ else
+ {
+ /* Split, truncate, or remove the old attribute
+ */
+ if (tmp_attr->end_index > attr->end_index)
+ {
+ PangoAttribute *end_attr = pango_attribute_copy (tmp_attr);
- if (tmp_attr->start_index == attr->start_index)
- {
- pango_attribute_destroy (tmp_attr);
- tmp_list->data = attr;
+ end_attr->start_index = attr->end_index;
+ pango_attr_list_insert (list, end_attr);
+ }
- prev = tmp_list;
- tmp_list = tmp_list->next;
- break;
- }
- else
- {
- tmp_attr->end_index = attr->start_index;
- }
- }
- }
- prev = tmp_list;
- tmp_list = tmp_list->next;
+ if (tmp_attr->start_index == attr->start_index)
+ {
+ pango_attribute_destroy (tmp_attr);
+ g_ptr_array_remove_index (list->attributes, i);
+ break;
+ }
+ else
+ {
+ tmp_attr->end_index = attr->start_index;
+ }
+ }
}
- /* At this point, prev points to the list node with attr in it,
- * tmp_list points to prev->next.
- */
-
- g_assert (prev->data == attr);
- g_assert (prev->next == tmp_list);
/* We now have the range inserted into the list one way or the
- * other. Fix up the remainder
- */
- while (tmp_list)
+ * other. Fix up the remainder */
+ /* Attention: No i = 0 here. */
+ for (i = i + 1, p = list->attributes->len; i < p; i++)
{
- PangoAttribute *tmp_attr = tmp_list->data;
+ PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
if (tmp_attr->start_index > end_index)
- break;
- else if (tmp_attr->klass->type == attr->klass->type)
- {
- if (tmp_attr->end_index <= attr->end_index ||
- pango_attribute_equal (tmp_attr, attr))
- {
- /* We can merge the new attribute with this attribute.
- */
- attr->end_index = MAX (end_index, tmp_attr->end_index);
-
- pango_attribute_destroy (tmp_attr);
- prev->next = tmp_list->next;
-
- if (!prev->next)
- list->attributes_tail = prev;
+ break;
- g_slist_free_1 (tmp_list);
- tmp_list = prev->next;
+ if (tmp_attr->klass->type != attr->klass->type)
+ continue;
- continue;
- }
- else
- {
- /* Trim the start of this attribute that it begins at the end
- * of the new attribute. This may involve moving
- * it in the list to maintain the required non-decreasing
- * order of start indices
- */
- GSList *tmp_list2;
- GSList *prev2;
-
- tmp_attr->start_index = attr->end_index;
-
- tmp_list2 = tmp_list->next;
- prev2 = tmp_list;
-
- while (tmp_list2)
- {
- PangoAttribute *tmp_attr2 = tmp_list2->data;
-
- if (tmp_attr2->start_index >= tmp_attr->start_index)
- break;
-
- prev2 = tmp_list2;
- tmp_list2 = tmp_list2->next;
- }
-
- /* Now remove and insert before tmp_list2. We'll
- * hit this attribute again later, but that's harmless.
- */
- if (prev2 != tmp_list)
- {
- GSList *old_next = tmp_list->next;
-
- prev->next = old_next;
- prev2->next = tmp_list;
- tmp_list->next = tmp_list2;
-
- if (!tmp_list->next)
- list->attributes_tail = tmp_list;
+ if (tmp_attr->end_index <= attr->end_index ||
+ pango_attribute_equal (tmp_attr, attr))
+ {
+ /* We can merge the new attribute with this attribute. */
+ attr->end_index = MAX (end_index, tmp_attr->end_index);
+ pango_attribute_destroy (tmp_attr);
+ g_ptr_array_remove_index (list->attributes, i);
+ i--;
+ p--;
+ continue;
+ }
+ else
+ {
+ /* Trim the start of this attribute that it begins at the end
+ * of the new attribute. This may involve moving
+ * it in the list to maintain the required non-decreasing
+ * order of start indices
+ */
+ int k, m;
- tmp_list = old_next;
+ tmp_attr->start_index = attr->end_index;
- continue;
- }
- }
- }
+ for (k = i + 1, m = list->attributes->len; k < m; k++)
+ {
+ PangoAttribute *tmp_attr2 = g_ptr_array_index (list->attributes, k);
- prev = tmp_list;
- tmp_list = tmp_list->next;
+ if (tmp_attr2->start_index >= tmp_attr->start_index)
+ break;
+ }
+ }
}
}
@@ -1760,52 +1685,41 @@ pango_attr_list_update (PangoAttrList *list,
int remove,
int add)
{
- GSList *l, *prev, *next;
+ guint i, p;
- prev = NULL;
- l = list->attributes;
- while (l)
+ for (i = 0, p = list->attributes->len; i < p; i++)
{
- PangoAttribute *attr = l->data;
- next = l->next;
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
if (attr->start_index >= pos &&
attr->end_index < pos + remove)
{
pango_attribute_destroy (attr);
- if (prev == NULL)
- list->attributes = next;
- else
- prev->next = next;
+ g_ptr_array_remove_index (list->attributes, i);
+ i--; /* Look at this index again */
+ p--;
+ continue;
+ }
- g_slist_free_1 (l);
+ if (attr->start_index >= pos &&
+ attr->start_index < pos + remove)
+ {
+ attr->start_index = pos + add;
}
- else
+ else if (attr->start_index >= pos + remove)
{
- prev = l;
-
- if (attr->start_index >= pos &&
- attr->start_index < pos + remove)
- {
- attr->start_index = pos + add;
- }
- else if (attr->start_index >= pos + remove)
- {
- attr->start_index += add - remove;
- }
-
- if (attr->end_index >= pos &&
- attr->end_index < pos + remove)
- {
- attr->end_index = pos;
- }
- else if (attr->end_index >= pos + remove)
- {
- attr->end_index += add - remove;
- }
+ attr->start_index += add - remove;
}
- l = next;
+ if (attr->end_index >= pos &&
+ attr->end_index < pos + remove)
+ {
+ attr->end_index = pos;
+ }
+ else if (attr->end_index >= pos + remove)
+ {
+ attr->end_index += add - remove;
+ }
}
}
@@ -1835,7 +1749,7 @@ pango_attr_list_splice (PangoAttrList *list,
gint pos,
gint len)
{
- GSList *tmp_list;
+ guint i, p;
guint upos, ulen;
g_return_if_fail (list != NULL);
@@ -1851,10 +1765,9 @@ pango_attr_list_splice (PangoAttrList *list,
*/
#define CLAMP_ADD(a,b) (((a) + (b) < (a)) ? G_MAXUINT : (a) + (b))
- tmp_list = list->attributes;
- while (tmp_list)
+ for (i = 0, p = list->attributes->len; i < p; i++)
{
- PangoAttribute *attr = tmp_list->data;
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);;
if (attr->start_index <= upos)
{
@@ -1870,15 +1783,15 @@ pango_attr_list_splice (PangoAttrList *list,
*/
attr->start_index = CLAMP_ADD (attr->start_index, ulen);
attr->end_index = CLAMP_ADD (attr->end_index, ulen);
- }
-
- tmp_list = tmp_list->next;
+ }
}
- tmp_list = other->attributes;
- while (tmp_list)
+ if (!other->attributes || other->attributes->len == 0)
+ return;
+
+ for (i = 0, p = other->attributes->len; i < p; i++)
{
- PangoAttribute *attr = pango_attribute_copy (tmp_list->data);
+ PangoAttribute *attr = pango_attribute_copy (g_ptr_array_index (other->attributes, i));
attr->start_index = CLAMP_ADD (attr->start_index, upos);
attr->end_index = CLAMP_ADD (attr->end_index, upos);
@@ -1886,8 +1799,6 @@ pango_attr_list_splice (PangoAttrList *list,
* pango_attr_list_change() will take care of deleting it.
*/
pango_attr_list_change (list, attr);
-
- tmp_list = tmp_list->next;
}
#undef CLAMP_ADD
}
@@ -1908,9 +1819,22 @@ pango_attr_list_splice (PangoAttrList *list,
GSList *
pango_attr_list_get_attributes (PangoAttrList *list)
{
+ GSList *result = NULL;
+ guint i, p;
+
g_return_val_if_fail (list != NULL, NULL);
- return g_slist_copy_deep (list->attributes, (GCopyFunc)pango_attribute_copy, NULL);
+ if (!list->attributes || list->attributes->len == 0)
+ return NULL;
+
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
+
+ result = g_slist_prepend (result, pango_attribute_copy (attr));
+ }
+
+ return g_slist_reverse (result);
}
/**
@@ -1930,9 +1854,7 @@ gboolean
pango_attr_list_equal (PangoAttrList *list,
PangoAttrList *other_list)
{
- GSList *attrs, *other_attrs;
- GSList *iter = NULL;
- guint attrs_length = 0;
+ GPtrArray *attrs, *other_attrs;
guint64 skip_bitmask = 0;
if (list == other_list)
@@ -1944,28 +1866,21 @@ pango_attr_list_equal (PangoAttrList *list,
attrs = list->attributes;
other_attrs = other_list->attributes;
- for (iter = attrs; iter != NULL; iter = iter->next)
+ if (attrs->len != other_attrs->len)
+ return FALSE;
+
+ for (guint i = 0; i < attrs->len; i++)
{
- PangoAttribute *attr = iter->data;
- GSList *other_iter = NULL;
+ PangoAttribute *attr = g_ptr_array_index (attrs, i);
gboolean attr_equal = FALSE;
- guint other_attr_index = 0;
-
- attrs_length++;
- for (other_iter = other_attrs;
- other_iter != NULL;
- other_iter = other_iter->next)
+ for (guint other_attr_index = 0; other_attr_index < other_attrs->len; other_attr_index++)
{
- PangoAttribute *other_attr = other_iter->data;
- guint64 other_attr_bitmask =
- other_attr_index < 64 ? 1 << other_attr_index : 0;
+ PangoAttribute *other_attr = g_ptr_array_index (other_attrs, other_attr_index);
+ guint64 other_attr_bitmask = other_attr_index < 64 ? 1 << other_attr_index : 0;
if ((skip_bitmask & other_attr_bitmask) != 0)
- {
- other_attr_index++;
- continue;
- }
+ continue;
if (attr->start_index == other_attr->start_index &&
attr->end_index == other_attr->end_index &&
@@ -1976,23 +1891,19 @@ pango_attr_list_equal (PangoAttrList *list,
break;
}
- other_attr_index++;
}
if (!attr_equal)
return FALSE;
}
- if (attrs_length != g_slist_length (other_attrs))
- return FALSE;
-
return TRUE;
}
gboolean
_pango_attr_list_has_attributes (const PangoAttrList *list)
{
- return list && (list->attributes != NULL);
+ return list && list->attributes != NULL && list->attributes->len > 0;
}
G_DEFINE_BOXED_TYPE (PangoAttrIterator,
@@ -2004,9 +1915,11 @@ void
_pango_attr_list_get_iterator (PangoAttrList *list,
PangoAttrIterator *iterator)
{
- iterator->next_attribute = list->attributes;
iterator->attribute_stack = NULL;
+ iterator->attrs = list->attributes;
+ iterator->n_attrs = iterator->attrs ? iterator->attrs->len : 0;
+ iterator->attr_index = 0;
iterator->start_index = 0;
iterator->end_index = 0;
@@ -2073,48 +1986,66 @@ pango_attr_iterator_range (PangoAttrIterator *iterator,
gboolean
pango_attr_iterator_next (PangoAttrIterator *iterator)
{
- GList *tmp_list;
+ guint i;
g_return_val_if_fail (iterator != NULL, FALSE);
- if (!iterator->next_attribute && !iterator->attribute_stack)
+ if (iterator->attr_index >= iterator->n_attrs &&
+ (!iterator->attribute_stack || iterator->attribute_stack->len == 0))
return FALSE;
iterator->start_index = iterator->end_index;
iterator->end_index = G_MAXUINT;
- tmp_list = iterator->attribute_stack;
- while (tmp_list)
+ if (iterator->attribute_stack)
{
- GList *next = tmp_list->next;
- PangoAttribute *attr = tmp_list->data;
-
- if (attr->end_index == iterator->start_index)
- {
- iterator->attribute_stack = g_list_remove_link (iterator->attribute_stack, tmp_list);
- g_list_free_1 (tmp_list);
- }
- else
- {
- iterator->end_index = MIN (iterator->end_index, attr->end_index);
- }
+ for (i = 0; i < iterator->attribute_stack->len; i++)
+ {
+ const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
- tmp_list = next;
+ if (attr->end_index == iterator->start_index)
+ {
+ g_ptr_array_remove_index (iterator->attribute_stack, i); /* Can't use index_fast :( */;
+ i--;
+ }
+ else
+ {
+ iterator->end_index = MIN (iterator->end_index, attr->end_index);
+ }
+ }
}
- while (iterator->next_attribute &&
- ((PangoAttribute *)iterator->next_attribute->data)->start_index == iterator->start_index)
+ while (1)
{
- if (((PangoAttribute *)iterator->next_attribute->data)->end_index > iterator->start_index)
- {
- iterator->attribute_stack = g_list_prepend (iterator->attribute_stack, iterator->next_attribute->data);
- iterator->end_index = MIN (iterator->end_index, ((PangoAttribute *)iterator->next_attribute->data)->end_index);
- }
- iterator->next_attribute = iterator->next_attribute->next;
+ PangoAttribute *attr;
+
+ if (iterator->attr_index >= iterator->n_attrs)
+ break;
+
+ attr = g_ptr_array_index (iterator->attrs, iterator->attr_index);
+
+ if (attr->start_index != iterator->start_index)
+ break;
+
+ if (attr->end_index > iterator->start_index)
+ {
+ if (G_UNLIKELY (!iterator->attribute_stack))
+ iterator->attribute_stack = g_ptr_array_new ();
+
+ g_ptr_array_add (iterator->attribute_stack, attr);
+
+ iterator->end_index = MIN (iterator->end_index, attr->end_index);
+ }
+
+ iterator->attr_index++; /* NEXT! */
}
- if (iterator->next_attribute)
- iterator->end_index = MIN (iterator->end_index, ((PangoAttribute *)iterator->next_attribute->data)->start_index);
+ if (iterator->attr_index < iterator->n_attrs)
+ {
+ PangoAttribute *attr = g_ptr_array_index (iterator->attrs, iterator->attr_index);
+
+ iterator->end_index = MIN (iterator->end_index, attr->start_index);
+ }
return TRUE;
}
@@ -2140,7 +2071,10 @@ pango_attr_iterator_copy (PangoAttrIterator *iterator)
*copy = *iterator;
- copy->attribute_stack = g_list_copy (iterator->attribute_stack);
+ if (iterator->attribute_stack)
+ copy->attribute_stack = g_ptr_array_copy (iterator->attribute_stack, NULL, NULL);
+ else
+ copy->attribute_stack = NULL;
return copy;
}
@@ -2148,7 +2082,8 @@ pango_attr_iterator_copy (PangoAttrIterator *iterator)
void
_pango_attr_iterator_destroy (PangoAttrIterator *iterator)
{
- g_list_free (iterator->attribute_stack);
+ if (iterator->attribute_stack)
+ g_ptr_array_free (iterator->attribute_stack, TRUE);
}
/**
@@ -2184,19 +2119,19 @@ PangoAttribute *
pango_attr_iterator_get (PangoAttrIterator *iterator,
PangoAttrType type)
{
- GList *tmp_list;
+ guint i;
g_return_val_if_fail (iterator != NULL, NULL);
- tmp_list = iterator->attribute_stack;
- while (tmp_list)
+ if (!iterator->attribute_stack)
+ return NULL;
+
+ for (i = 0; i < iterator->attribute_stack->len; i++)
{
- PangoAttribute *attr = tmp_list->data;
+ PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
if (attr->klass->type == type)
- return attr;
-
- tmp_list = tmp_list->next;
+ return attr;
}
return NULL;
@@ -2228,13 +2163,11 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator,
PangoLanguage **language,
GSList **extra_attrs)
{
- GList *tmp_list1;
- GSList *tmp_list2;
-
PangoFontMask mask = 0;
gboolean have_language = FALSE;
gdouble scale = 0;
gboolean have_scale = FALSE;
+ int i;
g_return_if_fail (iterator != NULL);
g_return_if_fail (desc != NULL);
@@ -2245,11 +2178,12 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator,
if (extra_attrs)
*extra_attrs = NULL;
- tmp_list1 = iterator->attribute_stack;
- while (tmp_list1)
+ if (!iterator->attribute_stack)
+ return;
+
+ for (i = iterator->attribute_stack->len - 1; i >= 0; i--)
{
- PangoAttribute *attr = tmp_list1->data;
- tmp_list1 = tmp_list1->next;
+ const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
switch ((int) attr->klass->type)
{
@@ -2333,22 +2267,24 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator,
{
gboolean found = FALSE;
- tmp_list2 = *extra_attrs;
/* Hack: special-case FONT_FEATURES. We don't want them to
* override each other, so we never merge them. This should
* be fixed when we implement attr-merging. */
if (attr->klass->type != PANGO_ATTR_FONT_FEATURES)
- while (tmp_list2)
- {
- PangoAttribute *old_attr = tmp_list2->data;
- if (attr->klass->type == old_attr->klass->type)
- {
- found = TRUE;
- break;
- }
-
- tmp_list2 = tmp_list2->next;
- }
+ {
+ GSList *tmp_list = *extra_attrs;
+ while (tmp_list)
+ {
+ PangoAttribute *old_attr = tmp_list->data;
+ if (attr->klass->type == old_attr->klass->type)
+ {
+ found = TRUE;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+ }
if (!found)
*extra_attrs = g_slist_prepend (*extra_attrs, pango_attribute_copy (attr));
@@ -2388,48 +2324,31 @@ pango_attr_list_filter (PangoAttrList *list,
{
PangoAttrList *new = NULL;
- GSList *tmp_list;
- GSList *prev;
+ guint i, p;
g_return_val_if_fail (list != NULL, NULL);
- tmp_list = list->attributes;
- prev = NULL;
- while (tmp_list)
+ if (!list->attributes || list->attributes->len == 0)
+ return NULL;
+
+ for (i = 0, p = list->attributes->len; i < p; i++)
{
- GSList *next = tmp_list->next;
- PangoAttribute *tmp_attr = tmp_list->data;
+ PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
if ((*func) (tmp_attr, data))
- {
- if (!tmp_list->next)
- list->attributes_tail = prev;
-
- if (prev)
- prev->next = tmp_list->next;
- else
- list->attributes = tmp_list->next;
-
- tmp_list->next = NULL;
-
- if (!new)
- {
- new = pango_attr_list_new ();
- new->attributes = new->attributes_tail = tmp_list;
- }
- else
- {
- new->attributes_tail->next = tmp_list;
- new->attributes_tail = tmp_list;
- }
-
- goto next_attr;
- }
+ {
+ g_ptr_array_remove_index (list->attributes, i);
+ i--; /* Need to look at this index again */
+ p--;
- prev = tmp_list;
+ if (G_UNLIKELY (!new))
+ {
+ new = pango_attr_list_new ();
+ new->attributes = g_ptr_array_new ();
+ }
- next_attr:
- tmp_list = next;
+ g_ptr_array_add (new->attributes, tmp_attr);
+ }
}
return new;
@@ -2453,22 +2372,26 @@ GSList *
pango_attr_iterator_get_attrs (PangoAttrIterator *iterator)
{
GSList *attrs = NULL;
- GList *tmp_list;
+ int i;
+
+ if (!iterator->attribute_stack ||
+ iterator->attribute_stack->len == 0)
+ return NULL;
- for (tmp_list = iterator->attribute_stack; tmp_list; tmp_list = tmp_list->next)
+ for (i = iterator->attribute_stack->len - 1; i >= 0; i--)
{
- PangoAttribute *attr = tmp_list->data;
+ PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
GSList *tmp_list2;
gboolean found = FALSE;
for (tmp_list2 = attrs; tmp_list2; tmp_list2 = tmp_list2->next)
{
PangoAttribute *old_attr = tmp_list2->data;
- if (attr->klass->type == old_attr->klass->type)
- {
- found = TRUE;
- break;
- }
+ if (attr->klass->type == old_attr->klass->type)
+ {
+ found = TRUE;
+ break;
+ }
}
if (!found)
diff --git a/pango/pango-context.c b/pango/pango-context.c
index a64eb79f..7772878f 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -1006,6 +1006,8 @@ itemize_state_init (ItemizeState *state,
state->item = NULL;
state->run_start = text + start_index;
+ state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED |
+ FONT_CHANGED | WIDTH_CHANGED | EMOJI_CHANGED;
/* First, apply the bidirectional algorithm to break
* the text into directional runs.
@@ -1079,7 +1081,6 @@ itemize_state_init (ItemizeState *state,
state->cache = NULL;
state->base_font = NULL;
- state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED | WIDTH_CHANGED | EMOJI_CHANGED;
}
static gboolean
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 6d4d94cb..3c138327 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -694,6 +694,10 @@ pango_layout_set_attributes (PangoLayout *layout,
!_pango_attr_list_has_attributes (attrs))
return;
+ if (layout->attrs &&
+ pango_attr_list_equal (layout->attrs, attrs))
+ return;
+
old_attrs = layout->attrs;
/* We always clear lines such that this function can be called
@@ -2090,6 +2094,8 @@ pango_layout_xy_to_index (PangoLayout *layout,
PangoRectangle line_logical;
int first_y, last_y;
+ g_assert (!ITER_IS_INVALID (&iter));
+
pango_layout_iter_get_line_extents (&iter, NULL, &line_logical);
pango_layout_iter_get_line_yrange (&iter, &first_y, &last_y);
diff --git a/pango/pango-ot-info.c b/pango/pango-ot-info.c
index f995c1d4..2b1b61f4 100644
--- a/pango/pango-ot-info.c
+++ b/pango/pango-ot-info.c
@@ -184,7 +184,7 @@ pango_ot_info_find_language (PangoOTInfo *info,
guint *required_feature_index)
{
gboolean ret;
- unsigned l_index;
+ guint l_index;
hb_tag_t tt = get_hb_table_type (table_type);
ret = hb_ot_layout_script_select_language (info->hb_face,
@@ -192,8 +192,9 @@ pango_ot_info_find_language (PangoOTInfo *info,
script_index,
1,
&language_tag,
- language_index);
- if (language_index) *language_index = l_index;
+ &l_index);
+ if (language_index)
+ *language_index = l_index;
hb_ot_layout_language_get_required_feature_index (info->hb_face, tt,
script_index,
diff --git a/pango/pango-tabs.c b/pango/pango-tabs.c
index 1ffa8356..56a34468 100644
--- a/pango/pango-tabs.c
+++ b/pango/pango-tabs.c
@@ -192,7 +192,8 @@ pango_tab_array_copy (PangoTabArray *src)
copy = pango_tab_array_new (src->size, src->positions_in_pixels);
- memcpy (copy->tabs, src->tabs, sizeof(PangoTab)*src->size);
+ if (copy->tabs)
+ memcpy (copy->tabs, src->tabs, sizeof(PangoTab) * src->size);
return copy;
}
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index e268ebd5..614a3a44 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -374,7 +374,7 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
PangoCairoFontHexBoxInfo *hbi;
gunichar ch;
gboolean invalid_input;
- char *p;
+ const char *p;
const char *name;
cairo_save (crenderer->cr);
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index b0c8365d..8aa27c1e 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -1468,7 +1468,7 @@ ensure_families (PangoFcFontMap *fcfontmap)
{
variable = FALSE;
#ifdef FC_VARIABLE
- res = FcPatternGetBool (fontset->fonts[i], FC_VARIABLE, 0, &variable);
+ variable = FcPatternGetBool (fontset->fonts[i], FC_VARIABLE, 0, &variable);
#endif
if (variable)
temp_family->variable = TRUE;
diff --git a/tests/testattributes.c b/tests/testattributes.c
index 6b5e849b..4eea97da 100644
--- a/tests/testattributes.c
+++ b/tests/testattributes.c
@@ -618,6 +618,76 @@ test_list_update (void)
pango_attr_list_unref (list);
}
+static void
+test_list_equal (void)
+{
+ PangoAttrList *list1, *list2;
+ PangoAttribute *attr;
+
+ list1 = pango_attr_list_new ();
+ list2 = pango_attr_list_new ();
+
+ attr = pango_attr_size_new (10 * PANGO_SCALE);
+ attr->start_index = 0;
+ attr->end_index = 7;
+ pango_attr_list_insert (list1, pango_attribute_copy (attr));
+ pango_attr_list_insert (list2, pango_attribute_copy (attr));
+ pango_attribute_destroy (attr);
+
+ g_assert_true (pango_attr_list_equal (list1, list2));
+
+ attr = pango_attr_stretch_new (PANGO_STRETCH_CONDENSED);
+ attr->start_index = 0;
+ attr->end_index = 1;
+ pango_attr_list_insert (list1, pango_attribute_copy (attr));
+ g_assert_true (!pango_attr_list_equal (list1, list2));
+
+ pango_attr_list_insert (list2, pango_attribute_copy (attr));
+ g_assert_true (pango_attr_list_equal (list1, list2));
+ pango_attribute_destroy (attr);
+
+ attr = pango_attr_size_new (30 * PANGO_SCALE);
+ /* Same range as the first attribute */
+ attr->start_index = 0;
+ attr->end_index = 7;
+ pango_attr_list_insert (list2, pango_attribute_copy (attr));
+ g_assert_true (!pango_attr_list_equal (list1, list2));
+ pango_attr_list_insert (list1, pango_attribute_copy (attr));
+ g_assert_true (pango_attr_list_equal (list1, list2));
+ pango_attribute_destroy (attr);
+
+ pango_attr_list_unref (list1);
+ pango_attr_list_unref (list2);
+
+
+ /* Same range but different order */
+ {
+ PangoAttrList *list1, *list2;
+ PangoAttribute *attr1, *attr2;
+
+ list1 = pango_attr_list_new ();
+ list2 = pango_attr_list_new ();
+
+ attr1 = pango_attr_size_new (10 * PANGO_SCALE);
+ attr2 = pango_attr_stretch_new (PANGO_STRETCH_CONDENSED);
+
+ pango_attr_list_insert (list1, pango_attribute_copy (attr1));
+ pango_attr_list_insert (list1, pango_attribute_copy (attr2));
+
+ pango_attr_list_insert (list2, pango_attribute_copy (attr2));
+ pango_attr_list_insert (list2, pango_attribute_copy (attr1));
+
+ pango_attribute_destroy (attr1);
+ pango_attribute_destroy (attr2);
+
+ g_assert_true (pango_attr_list_equal (list1, list2));
+ g_assert_true (pango_attr_list_equal (list2, list1));
+
+ pango_attr_list_unref (list1);
+ pango_attr_list_unref (list2);
+ }
+}
+
int
main (int argc, char *argv[])
{
@@ -630,6 +700,7 @@ main (int argc, char *argv[])
g_test_add_func ("/attributes/list/splice", test_list_splice);
g_test_add_func ("/attributes/list/filter", test_list_filter);
g_test_add_func ("/attributes/list/update", test_list_update);
+ g_test_add_func ("/attributes/list/equal", test_list_equal);
g_test_add_func ("/attributes/iter/basic", test_iter);
g_test_add_func ("/attributes/iter/get", test_iter_get);
g_test_add_func ("/attributes/iter/get_font", test_iter_get_font);