From 754f431642e9082611f36d7aec96378875b5620a Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sat, 11 May 2024 15:03:17 +0930 Subject: Allow links to specify 'dest' and 'uri' - If a link has both 'dest' and 'uri', the 'dest' will be used if it exists, otherwise it will fallback to using the 'uri'. - Ensure that a missing 'dest' does not result in an error. Instead a warning is printed if CAIRO_DEBUG_TAG is set, and a link to the current location is embedded in the PDF. ie the link does nothing. Cairo needs to embed a link even if no destination is available because when links are embedded at the end of the document, the content stream already contains link tags. - Remove cairo_pdf_interchange_write_forward_links. This code was originally used prior to !463 when cairo wrote the links at the end of each page. Now the links are written at the end of the document so there are no longer any forward links with an unknown destination, unless the destination does not exist. - When 'internal' is not used, use the 'dest' name to reference the link. Ensure non ASCII names are correctly encoded. --- test/pdf-tagged-text.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/pdf-tagged-text.c b/test/pdf-tagged-text.c index 3883d418e..094b1c8b0 100644 --- a/test/pdf-tagged-text.c +++ b/test/pdf-tagged-text.c @@ -113,6 +113,8 @@ static const char *roman_numerals[] = { #define MAX_PARAGRAPH_LINES 20 +static const char *utf8_destination = "l\xc3\xa4nk"; + static int paragraph_num_lines; static char *paragraph_text[MAX_PARAGRAPH_LINES]; static double paragraph_height; @@ -329,20 +331,20 @@ draw_cover (cairo_surface_t *surface, cairo_t *cr) cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cr, 16); - cairo_move_to (cr, PAGE_WIDTH/3, PAGE_HEIGHT/3); + cairo_move_to (cr, PAGE_WIDTH/3, 0.15*PAGE_HEIGHT); cairo_tag_begin (cr, "Span", NULL); cairo_show_text (cr, "PDF Features Test"); cairo_tag_end (cr, "Span"); /* Test URL link using "rect" attribute. The entire rectangle surrounding the URL should be a clickable link. */ - cairo_move_to (cr, PAGE_WIDTH/3, 2*PAGE_HEIGHT/3); + cairo_move_to (cr, PAGE_WIDTH/3, 0.2*PAGE_HEIGHT); cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, TEXT_SIZE); cairo_set_source_rgb (cr, 0, 0, 1); cairo_show_text (cr, cairo_url); cairo_text_extents (cr, cairo_url, &text_extents); url_box.x = PAGE_WIDTH/3 - url_box_margin; - url_box.y = 2*PAGE_HEIGHT/3 - url_box_margin; + url_box.y = 0.2*PAGE_HEIGHT - url_box_margin; url_box.width = text_extents.width + 2*url_box_margin; url_box.height = -text_extents.height + 2*url_box_margin; cairo_rectangle(cr, url_box.x, url_box.y, url_box.width, url_box.height); @@ -355,28 +357,52 @@ draw_cover (cairo_surface_t *surface, cairo_t *cr) /* Create link to not yet emmited page number */ cairo_tag_begin (cr, CAIRO_TAG_LINK, "page=5"); - cairo_move_to (cr, PAGE_WIDTH/3, 4*PAGE_HEIGHT/5); + cairo_move_to (cr, PAGE_WIDTH/3, 0.25*PAGE_HEIGHT); cairo_show_text (cr, "link to page 5"); cairo_tag_end (cr, CAIRO_TAG_LINK); /* Create link to not yet emmited destination */ cairo_tag_begin (cr, CAIRO_TAG_LINK, "dest='Section 3.3'"); - cairo_move_to (cr, PAGE_WIDTH/3, 4.2*PAGE_HEIGHT/5); + cairo_move_to (cr, PAGE_WIDTH/3, 0.3*PAGE_HEIGHT); cairo_show_text (cr, "link to page section 3.3"); cairo_tag_end (cr, CAIRO_TAG_LINK); /* Create link to external file */ + cairo_move_to (cr, PAGE_WIDTH/3, 0.35*PAGE_HEIGHT); cairo_tag_begin (cr, CAIRO_TAG_LINK, "file='foo.pdf' page=1"); - cairo_move_to (cr, PAGE_WIDTH/3, 4.4*PAGE_HEIGHT/5); cairo_show_text (cr, "link file 'foo.pdf'"); cairo_tag_end (cr, CAIRO_TAG_LINK); + /* Create link to missing dest */ + cairo_move_to (cr, PAGE_WIDTH/3, 0.4*PAGE_HEIGHT); + cairo_tag_begin (cr, CAIRO_TAG_LINK, "dest='I don\\'t exist'"); + cairo_show_text (cr, "link to missing dest"); + cairo_tag_end (cr, CAIRO_TAG_LINK); + + /* Create link to missing dest with URI fallback*/ + cairo_move_to (cr, PAGE_WIDTH/3, 0.45*PAGE_HEIGHT); + xasprintf(&attrib, "dest='I also don\\'t exist' uri='%s'", cairo_url); + cairo_tag_begin (cr, CAIRO_TAG_LINK, attrib); + cairo_show_text (cr, "link to missing dest with uri fallback"); + cairo_tag_end (cr, CAIRO_TAG_LINK); + free (attrib); + + /* Create link to utf8 dest */ + cairo_move_to (cr, PAGE_WIDTH/3, 0.5*PAGE_HEIGHT); + xasprintf(&attrib, "dest='%s'", utf8_destination); + cairo_tag_begin (cr, CAIRO_TAG_LINK, attrib); + cairo_show_text (cr, "link to utf8 dest"); + cairo_tag_end (cr, CAIRO_TAG_LINK); + free (attrib); + draw_page_num (surface, cr, "cover", 0); } static void create_document (cairo_surface_t *surface, cairo_t *cr) { + char *attrib; + layout_paragraph (cr); cairo_pdf_surface_set_thumbnail_size (surface, PAGE_WIDTH/10, PAGE_HEIGHT/10); @@ -491,6 +517,14 @@ create_document (cairo_surface_t *surface, cairo_t *cr) cairo_show_text (cr, "link to page 3"); cairo_tag_end (cr, CAIRO_TAG_LINK); + /* Create utf8 dest */ + cairo_move_to (cr, PAGE_WIDTH/3, 4*PAGE_HEIGHT/5); + xasprintf(&attrib, "name='%s'", utf8_destination); + cairo_tag_begin (cr, CAIRO_TAG_DEST, attrib); + cairo_show_text (cr, utf8_destination); + cairo_tag_end (cr, CAIRO_TAG_DEST); + free (attrib); + cairo_tag_end (cr, "Document"); } -- cgit v1.2.3