mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 11:08:12 +02:00
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.
This commit is contained in:
parent
df37baf789
commit
12b875aef3
5 changed files with 116 additions and 94 deletions
|
|
@ -229,6 +229,87 @@ cairo_pdf_interchange_write_node_object (cairo_pdf_surface_t *surface
|
|||
return _cairo_output_stream_get_status (surface->output);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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'");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue