diff --git a/src/cairo-pdf-interchange.c b/src/cairo-pdf-interchange.c index 6bda9e8b8..0e910fd22 100644 --- a/src/cairo-pdf-interchange.c +++ b/src/cairo-pdf-interchange.c @@ -1991,14 +1991,22 @@ _cairo_pdf_interchange_command_id (cairo_pdf_surface_t *surface, if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER && ic->current_render_node) { /* TODO If the group does not have tags we don't need to close the current tag. */ if (command_list_is_group (surface, command_id)) { + /* A "Do /xnnn" can not be inside a tag (since the + * XObject may also contain tags). Close the tag. + */ if (ic->marked_content_open) { status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); ic->marked_content_open = FALSE; } - if (command_list_has_content (surface, command_id, NULL)) { + /* If there is any more content after this and we are + * inside a tag (current node is not the root node), + * ensure that the next command will open the tag. + */ + if (command_list_has_content (surface, command_id, NULL) && ic->current_render_node->parent) { ic->render_next_command_has_content = TRUE; } } else if (ic->render_next_command_has_content) { + /* After a "Do /xnnn" operation, if there is more content, open the tag. */ add_mcid_to_node (surface, ic->current_render_node, ic->command_id, &mcid); status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, ic->current_render_node->name, mcid); diff --git a/test/pdf-structure.c b/test/pdf-structure.c index ee4efe511..3ade6de8c 100644 --- a/test/pdf-structure.c +++ b/test/pdf-structure.c @@ -177,6 +177,54 @@ test_group (cairo_t *cr) cairo_tag_end (cr, "Document"); } +/* https://bugzilla.mozilla.org/show_bug.cgi?id=1896173 + * This particular combination of tags and groups resulted in a crash. + */ +static void +test_group2 (cairo_t *cr) +{ + cairo_tag_begin (cr, "H", ""); + text (cr, "Heading"); + cairo_tag_end (cr, "H"); + + cairo_push_group (cr); + + cairo_tag_begin (cr, "P", ""); + text (cr, "Para1"); + cairo_tag_end (cr, "P"); + + cairo_pop_group_to_source (cr); + cairo_paint (cr); + + cairo_set_source_rgb (cr, 0, 0, 0); + text (cr, "text"); +} + +/* Check that the fix for test_group2() works when there is a top level tag. */ +static void +test_group3 (cairo_t *cr) +{ + cairo_tag_begin (cr, "Document", NULL); + + cairo_tag_begin (cr, "H", ""); + text (cr, "Heading"); + cairo_tag_end (cr, "H"); + + cairo_push_group (cr); + + cairo_tag_begin (cr, "P", ""); + text (cr, "Para1"); + cairo_tag_end (cr, "P"); + + cairo_pop_group_to_source (cr); + cairo_paint (cr); + + cairo_set_source_rgb (cr, 0, 0, 0); + text (cr, "text"); + + cairo_tag_end (cr, "Document"); +} + static void test_group_ref (cairo_t *cr) { @@ -434,6 +482,8 @@ static const struct pdf_structure_test pdf_structure_tests[] = { { "simple", test_simple }, { "simple-ref", test_simple_ref }, { "group", test_group }, + { "group2", test_group2 }, + { "group3", test_group3 }, { "group-ref", test_group_ref }, { "repeated-group", test_repeated_group }, { "multipage-simple", test_multipage_simple },