Commit 54b593ec authored by Matthias Clasen's avatar Matthias Clasen

Fix attr iterators with overlapping attributes

This broke when PangoAttrIterator was changed to
use an array for the stack of current attributes, in
dec6c086. We were not always walking the array
in the right order. The first attribute to check is
at the *end* of the array.

This showed up as misrendering in epsilon_0 example
in gtk3-demo's text view markup demo.

Test included.
parent 51b2b223
Pipeline #214604 passed with stages
in 2 minutes and 28 seconds
......@@ -2003,7 +2003,7 @@ pango_attr_iterator_range (PangoAttrIterator *iterator,
gboolean
pango_attr_iterator_next (PangoAttrIterator *iterator)
{
guint i;
int i;
g_return_val_if_fail (iterator != NULL, FALSE);
......@@ -2016,19 +2016,14 @@ pango_attr_iterator_next (PangoAttrIterator *iterator)
if (iterator->attribute_stack)
{
for (i = 0; i < iterator->attribute_stack->len; i++)
for (i = iterator->attribute_stack->len - 1; i>= 0; i--)
{
const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
if (attr->end_index == iterator->start_index)
{
g_ptr_array_remove_index (iterator->attribute_stack, i); /* Can't use index_fast :( */;
i--;
}
g_ptr_array_remove_index (iterator->attribute_stack, i); /* Can't use index_fast :( */
else
{
iterator->end_index = MIN (iterator->end_index, attr->end_index);
}
iterator->end_index = MIN (iterator->end_index, attr->end_index);
}
}
......@@ -2136,14 +2131,14 @@ PangoAttribute *
pango_attr_iterator_get (PangoAttrIterator *iterator,
PangoAttrType type)
{
guint i;
int i;
g_return_val_if_fail (iterator != NULL, NULL);
if (!iterator->attribute_stack)
return NULL;
for (i = 0; i < iterator->attribute_stack->len; i++)
for (i = iterator->attribute_stack->len - 1; i>= 0; i--)
{
PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
......
......@@ -944,6 +944,94 @@ test_merge2 (void)
pango_attr_list_unref (list);
}
/* This only prints rise, size and scale, which are the
* only relevant attributes in the test that uses this
* function.
*/
static void
print_tags_for_attributes (PangoAttrIterator *iter,
GString *s)
{
PangoAttribute *attr;
attr = pango_attr_iterator_get (iter, PANGO_ATTR_RISE);
if (attr)
g_string_append_printf (s, "[%d, %d]rise=%d\n",
attr->start_index, attr->end_index,
((PangoAttrInt*)attr)->value);
attr = pango_attr_iterator_get (iter, PANGO_ATTR_SIZE);
if (attr)
g_string_append_printf (s, "[%d, %d]size=%d\n",
attr->start_index, attr->end_index,
((PangoAttrInt*)attr)->value);
attr = pango_attr_iterator_get (iter, PANGO_ATTR_SCALE);
if (attr)
g_string_append_printf (s, "[%d, %d]scale=%f\n",
attr->start_index, attr->end_index,
((PangoAttrFloat*)attr)->value);
}
static void
test_iter_epsilon_zero (void)
{
const char *markup = "𝜀<span rise=\"-6000\" size=\"x-small\" font_desc=\"italic\">0</span> = 𝜔<span rise=\"8000\" size=\"smaller\">𝜔<span rise=\"14000\" size=\"smaller\">𝜔<span rise=\"20000\">.<span rise=\"23000\">.<span rise=\"26000\">.</span></span></span></span></span>";
PangoAttrList *attributes;
PangoAttrIterator *attr;
char *text;
GError *error = NULL;
GString *s;
s = g_string_new ("");
pango_parse_markup (markup, -1, 0, &attributes, &text, NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (text, ==, "𝜀0 = 𝜔𝜔𝜔...");
attr = pango_attr_list_get_iterator (attributes);
do
{
int start, end;
pango_attr_iterator_range (attr, &start, &end);
g_string_append_printf (s, "range: [%d, %d]\n", start, end);
print_tags_for_attributes (attr, s);
}
while (pango_attr_iterator_next (attr));
g_assert_cmpstr (s->str, ==,
"range: [0, 4]\n"
"range: [4, 5]\n"
"[4, 5]rise=-6000\n"
"[4, 5]scale=0.694444\n"
"range: [5, 12]\n"
"range: [12, 16]\n"
"[12, 23]rise=8000\n"
"[12, 23]scale=0.833333\n"
"range: [16, 20]\n"
"[16, 23]rise=14000\n"
"[16, 23]scale=0.694444\n"
"range: [20, 21]\n"
"[20, 23]rise=20000\n"
"[16, 23]scale=0.694444\n"
"range: [21, 22]\n"
"[21, 23]rise=23000\n"
"[16, 23]scale=0.694444\n"
"range: [22, 23]\n"
"[22, 23]rise=26000\n"
"[16, 23]scale=0.694444\n"
"range: [23, 2147483647]\n");
g_free (text);
pango_attr_list_unref (attributes);
pango_attr_iterator_destroy (attr);
g_string_free (s, TRUE);
}
int
main (int argc, char *argv[])
{
......@@ -966,6 +1054,7 @@ main (int argc, char *argv[])
g_test_add_func ("/attributes/iter/get", test_iter_get);
g_test_add_func ("/attributes/iter/get_font", test_iter_get_font);
g_test_add_func ("/attributes/iter/get_attrs", test_iter_get_attrs);
g_test_add_func ("/attributes/iter/epsilon_zero", test_iter_epsilon_zero);
return g_test_run ();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment