summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2017-08-26 16:32:48 +0930
committerAdrian Johnson <ajohnson@redneon.com>2017-08-26 16:32:48 +0930
commit12b875aef374636d1693a631524dd3b622277415 (patch)
tree6f12588130603a9ff432742c29727e9065bc6796
parentdf37baf7895ef9acc71f3627b22e7368c8af3ea1 (diff)
downloadcairo-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.c177
-rw-r--r--src/cairo-pdf-surface-private.h2
-rw-r--r--src/cairo-pdf-surface.c17
-rw-r--r--src/cairo-pdf.h2
-rw-r--r--test/pdf-tagged-text.c12
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'");