diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2017-08-26 16:32:48 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2017-08-26 16:32:48 +0930 |
commit | 12b875aef374636d1693a631524dd3b622277415 (patch) | |
tree | 6f12588130603a9ff432742c29727e9065bc6796 | |
parent | df37baf7895ef9acc71f3627b22e7368c8af3ea1 (diff) | |
download | cairo-12b875aef374636d1693a631524dd3b622277415.tar.gz |
pdf: use link attributes instead of dest name for cairo_pdf_surface_add_outline
In PDF outline targets are specified the same way as link targets so
there is no need to restrict the target to dest names.
-rw-r--r-- | src/cairo-pdf-interchange.c | 177 | ||||
-rw-r--r-- | src/cairo-pdf-surface-private.h | 2 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 17 | ||||
-rw-r--r-- | src/cairo-pdf.h | 2 | ||||
-rw-r--r-- | test/pdf-tagged-text.c | 12 |
5 files changed, 116 insertions, 94 deletions
diff --git a/src/cairo-pdf-interchange.c b/src/cairo-pdf-interchange.c index 1521fc25a..460f483e6 100644 --- a/src/cairo-pdf-interchange.c +++ b/src/cairo-pdf-interchange.c @@ -230,6 +230,87 @@ cairo_pdf_interchange_write_node_object (cairo_pdf_surface_t *surface } static cairo_int_status_t +cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface, + cairo_link_attrs_t *link_attrs) +{ + cairo_int_status_t status; + double height; + char *dest = NULL; + + if (link_attrs->dest) { + status = _cairo_utf8_to_pdf_string (link_attrs->dest, &dest); + if (unlikely (status)) + return status; + } + + if (link_attrs->link_type == TAG_LINK_DEST) { + + if (link_attrs->dest) { + _cairo_output_stream_printf (surface->output, + " /Dest %s\n", + dest); + } else { + cairo_pdf_resource_t res; + int page = link_attrs->page; + + if (page < 1 || page > (int)_cairo_array_num_elements (&surface->pages)) + return CAIRO_INT_STATUS_TAG_ERROR; + + _cairo_array_copy_element (&surface->page_heights, page - 1, &height); + _cairo_array_copy_element (&surface->pages, page - 1, &res); + if (link_attrs->has_pos) { + _cairo_output_stream_printf (surface->output, + " /Dest [%d 0 R /XYZ %f %f 0]\n", + res.id, + link_attrs->pos.x, + height - link_attrs->pos.y); + } else { + _cairo_output_stream_printf (surface->output, + " /Dest [%d 0 R /XYZ null null 0]\n", + res.id); + } + } + } else if (link_attrs->link_type == TAG_LINK_URI) { + _cairo_output_stream_printf (surface->output, + " /A <<\n" + " /Type /Action\n" + " /S /URI\n" + " /URI (%s)\n" + " >>\n", + link_attrs->uri); + } else if (link_attrs->link_type == TAG_LINK_FILE) { + _cairo_output_stream_printf (surface->output, + " /A <<\n" + " /Type /Action\n" + " /S /GoToR\n" + " /F (%s)\n", + link_attrs->file); + if (link_attrs->dest) { + _cairo_output_stream_printf (surface->output, + " /D %s\n", + dest); + } else { + if (link_attrs->has_pos) { + _cairo_output_stream_printf (surface->output, + " /D [%d %f %f 0]\n", + link_attrs->page, + link_attrs->pos.x, + link_attrs->pos.y); + } else { + _cairo_output_stream_printf (surface->output, + " /D [%d null null 0]\n", + link_attrs->page); + } + } + _cairo_output_stream_printf (surface->output, + " >>\n"); + } + free (dest); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, cairo_pdf_struct_tree_node_t *node) { @@ -237,7 +318,6 @@ cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_pdf_interchange_t *ic = &surface->interchange; int sp; - char *dest = NULL; int i, num_rects; double height; @@ -299,73 +379,9 @@ cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, " ]\n"); } - if (node->annot.link_attrs.dest) { - status = _cairo_utf8_to_pdf_string (node->annot.link_attrs.dest, &dest); - if (unlikely (status)) - return status; - } - - if (node->annot.link_attrs.link_type == TAG_LINK_DEST) { - if (node->annot.link_attrs.dest) { - _cairo_output_stream_printf (surface->output, - " /Dest %s\n", - dest); - } else { - cairo_pdf_resource_t res; - int page = node->annot.link_attrs.page; - - if (page < 1 || page > (int)_cairo_array_num_elements (&surface->pages)) - return CAIRO_INT_STATUS_TAG_ERROR; - - _cairo_array_copy_element (&surface->page_heights, page - 1, &height); - _cairo_array_copy_element (&surface->pages, page - 1, &res); - if (node->annot.link_attrs.has_pos) { - _cairo_output_stream_printf (surface->output, - " /Dest [%d 0 R /XYZ %f %f 0]\n", - res.id, - node->annot.link_attrs.pos.x, - height - node->annot.link_attrs.pos.y); - } else { - _cairo_output_stream_printf (surface->output, - " /Dest [%d 0 R /XYZ null null 0]\n", - res.id); - } - } - } else if (node->annot.link_attrs.link_type == TAG_LINK_URI) { - _cairo_output_stream_printf (surface->output, - " /A <<\n" - " /Type /Action\n" - " /S /URI\n" - " /URI (%s)\n" - " >>\n", - node->annot.link_attrs.uri); - } else if (node->annot.link_attrs.link_type == TAG_LINK_FILE) { - _cairo_output_stream_printf (surface->output, - " /A <<\n" - " /Type /Action\n" - " /S /GoToR\n" - " /F (%s)\n", - node->annot.link_attrs.file); - if (node->annot.link_attrs.dest) { - _cairo_output_stream_printf (surface->output, - " /D %s\n", - dest); - } else { - if (node->annot.link_attrs.has_pos) { - _cairo_output_stream_printf (surface->output, - " /D [%d %f %f 0]\n", - node->annot.link_attrs.page, - node->annot.link_attrs.pos.x, - node->annot.link_attrs.pos.y); - } else { - _cairo_output_stream_printf (surface->output, - " /D [%d null null 0]\n", - node->annot.link_attrs.page); - } - } - _cairo_output_stream_printf (surface->output, - " >>\n"); - } + status = cairo_pdf_interchange_write_link_action (surface, &node->annot.link_attrs); + if (unlikely (status)) + return status; _cairo_output_stream_printf (surface->output, " /BS << /W 0 >>" @@ -373,8 +389,6 @@ cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, "endobj\n"); status = _cairo_output_stream_get_status (surface->output); - - free (dest); } return status; @@ -520,7 +534,6 @@ cairo_pdf_interchange_write_outline (cairo_pdf_surface_t *surface) cairo_pdf_interchange_t *ic = &surface->interchange; cairo_int_status_t status; char *name = NULL; - char *dest = NULL; num_elems = _cairo_array_num_elements (&ic->outline); if (num_elems < 2) @@ -549,10 +562,6 @@ cairo_pdf_interchange_write_outline (cairo_pdf_surface_t *surface) if (unlikely (status)) return status; - status = _cairo_utf8_to_pdf_string (outline->dest, &dest); - if (unlikely (status)) - return status; - _cairo_output_stream_printf (surface->output, "%d 0 obj\n" "<< /Title %s\n" @@ -594,12 +603,13 @@ cairo_pdf_interchange_write_outline (cairo_pdf_surface_t *surface) flags); } + status = cairo_pdf_interchange_write_link_action (surface, &outline->link_attrs); + if (unlikely (status)) + return status; + _cairo_output_stream_printf (surface->output, - " /Dest %s\n" ">>\n" - "endobj\n", - dest); - free (dest); + "endobj\n"); } return status; @@ -1313,7 +1323,7 @@ cairo_int_status_t _cairo_pdf_interchange_add_outline (cairo_pdf_surface_t *surface, int parent_id, const char *name, - const char *dest, + const char *link_attribs, cairo_pdf_outline_flags_t flags, int *id) { @@ -1329,12 +1339,17 @@ _cairo_pdf_interchange_add_outline (cairo_pdf_surface_t *surface, if (unlikely (outline == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_tag_parse_link_attributes (link_attribs, &outline->link_attrs); + if (unlikely (status)) { + free (outline); + return status; + } + outline->res = _cairo_pdf_surface_new_object (surface); if (outline->res.id == 0) return _cairo_error (CAIRO_STATUS_NO_MEMORY); outline->name = strdup (name); - outline->dest = strdup (dest); outline->flags = flags; outline->count = 0; diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h index be721af24..09262e0d3 100644 --- a/src/cairo-pdf-surface-private.h +++ b/src/cairo-pdf-surface-private.h @@ -194,7 +194,7 @@ typedef struct _cairo_pdf_named_dest { typedef struct _cairo_pdf_outline_entry { char *name; - char *dest; + cairo_link_attrs_t link_attrs; cairo_pdf_outline_flags_t flags; cairo_pdf_resource_t res; struct _cairo_pdf_outline_entry *parent; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index f1ae9eec4..c258b7381 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -739,14 +739,15 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface, * @surface: a PDF #cairo_surface_t * @parent_id: the id of the parent item or %CAIRO_PDF_OUTLINE_ROOT if this is a top level item. * @utf8: the name of the outline - * @dest: the name of the destination + * @link_attribs: the link attributes specifying where this outline links to * @flags: outline item flags * - * Add an item to the document outline hierarchy with the name @utf8 that links to the - * destinaton @dest. Destinations are created using - * cairo_tag_begin()/cairo_tag_end() with the - * %CAIRO_TAG_DEST. The item will be a child of the item with id @parent_id. Use %CAIRO_PDF_OUTLINE_ROOT - * as the parent id of top level items. + * Add an item to the document outline hierarchy with the name @utf8 + * that links to the location specified by @link_attribs. Link + * attributes have the same keys and values as the [Link Tag][link], + * excluding the "rect" attribute. The item will be a child of the + * item with id @parent_id. Use %CAIRO_PDF_OUTLINE_ROOT as the parent + * id of top level items. * * Return value: the id for the added item. * @@ -756,7 +757,7 @@ int cairo_pdf_surface_add_outline (cairo_surface_t *surface, int parent_id, const char *utf8, - const char *dest, + const char *link_attribs, cairo_pdf_outline_flags_t flags) { cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */ @@ -769,7 +770,7 @@ cairo_pdf_surface_add_outline (cairo_surface_t *surface, status = _cairo_pdf_interchange_add_outline (pdf_surface, parent_id, utf8, - dest, + link_attribs, flags, &id); if (status) diff --git a/src/cairo-pdf.h b/src/cairo-pdf.h index 040c0ed35..5be0b3f1b 100644 --- a/src/cairo-pdf.h +++ b/src/cairo-pdf.h @@ -110,7 +110,7 @@ cairo_public int cairo_pdf_surface_add_outline (cairo_surface_t *surface, int parent_id, const char *utf8, - const char *dest, + const char *link_attribs, cairo_pdf_outline_flags_t flags); /** diff --git a/test/pdf-tagged-text.c b/test/pdf-tagged-text.c index f79789429..afadd6b87 100644 --- a/test/pdf-tagged-text.c +++ b/test/pdf-tagged-text.c @@ -229,9 +229,11 @@ draw_section (cairo_surface_t *surface, cairo_t *cr, const struct section *secti { int flags, i; char buf[100]; + char buf2[100]; cairo_tag_begin (cr, "Sect", NULL); sprintf(buf, "name='%s'", section->heading); + sprintf(buf2, "dest='%s'", section->heading); cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); if (section->level == 0) { cairo_show_page (cr); @@ -248,7 +250,7 @@ draw_section (cairo_surface_t *surface, cairo_t *cr, const struct section *secti outline_parents[0] = cairo_pdf_surface_add_outline (surface, CAIRO_PDF_OUTLINE_ROOT, section->heading, - section->heading, + buf2, flags); } else { if (section->level == 1) { @@ -280,7 +282,7 @@ draw_section (cairo_surface_t *surface, cairo_t *cr, const struct section *secti outline_parents[section->level] = cairo_pdf_surface_add_outline (surface, outline_parents[section->level - 1], section->heading, - section->heading, + buf2, flags); } @@ -327,6 +329,10 @@ create_document (cairo_surface_t *surface, cairo_t *cr) cairo_tag_begin (cr, "Document", NULL); draw_cover (surface, cr); + cairo_pdf_surface_add_outline (surface, + CAIRO_PDF_OUTLINE_ROOT, + "Cover", "page=1", + CAIRO_PDF_OUTLINE_FLAG_BOLD); cairo_show_page (cr); page_num = 0; @@ -335,7 +341,7 @@ create_document (cairo_surface_t *surface, cairo_t *cr) cairo_pdf_surface_add_outline (surface, CAIRO_PDF_OUTLINE_ROOT, - "Contents", "TOC", + "Contents", "dest='TOC'", CAIRO_PDF_OUTLINE_FLAG_BOLD); cairo_tag_begin (cr, CAIRO_TAG_DEST, "name='TOC'"); |