diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-06-10 11:48:52 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-06-10 11:48:52 +0000 |
commit | e6b03b9f097552829acd7c54ce222c5dc7eb2b65 (patch) | |
tree | 2a0c1c637f078118cd884d956e139048d8ab22f2 | |
parent | 7abe91c208ce7f0c1f6e6c4b13df4de7a664ffa5 (diff) | |
parent | 1bb4e61c3285f95e01f13d70354716c11c27ce39 (diff) | |
download | pango-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.h | 11 | ||||
-rw-r--r-- | pango/pango-attributes.c | 671 | ||||
-rw-r--r-- | pango/pango-context.c | 3 | ||||
-rw-r--r-- | pango/pango-layout.c | 6 | ||||
-rw-r--r-- | pango/pango-ot-info.c | 7 | ||||
-rw-r--r-- | pango/pango-tabs.c | 3 | ||||
-rw-r--r-- | pango/pangocairo-render.c | 2 | ||||
-rw-r--r-- | pango/pangofc-fontmap.c | 2 | ||||
-rw-r--r-- | tests/testattributes.c | 71 |
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); |