mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-01 15:20:14 +01:00
Merge branch 'dest-and-uri' into 'master'
Allow links to specify 'dest' and 'uri' See merge request cairo/cairo!547
This commit is contained in:
commit
c75997a4ea
8 changed files with 135 additions and 137 deletions
|
|
@ -768,13 +768,11 @@ static cairo_int_status_t
|
|||
cairo_pdf_interchange_write_dest (cairo_pdf_surface_t *surface,
|
||||
cairo_link_attrs_t *link_attrs)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_pdf_interchange_t *ic = &surface->interchange;
|
||||
cairo_pdf_forward_link_t *link;
|
||||
cairo_pdf_resource_t link_res;
|
||||
|
||||
/* If the dest is known, emit an explicit dest */
|
||||
if (link_attrs->dest) {
|
||||
if (link_attrs->link_type == TAG_LINK_DEST_AND_URI || link_attrs->link_type == TAG_LINK_DEST) {
|
||||
cairo_pdf_named_dest_t key;
|
||||
cairo_pdf_named_dest_t *named_dest;
|
||||
|
||||
|
|
@ -797,53 +795,56 @@ cairo_pdf_interchange_write_dest (cairo_pdf_surface_t *surface,
|
|||
if (named_dest->attrs.y_valid)
|
||||
y = named_dest->attrs.y;
|
||||
|
||||
_cairo_output_stream_printf (surface->object_stream.stream, " /Dest ");
|
||||
status = cairo_pdf_interchange_write_explicit_dest (surface,
|
||||
named_dest->page,
|
||||
TRUE,
|
||||
x, y);
|
||||
if (named_dest->attrs.internal) {
|
||||
_cairo_output_stream_printf (surface->object_stream.stream, " /Dest ");
|
||||
status = cairo_pdf_interchange_write_explicit_dest (surface,
|
||||
named_dest->page,
|
||||
TRUE,
|
||||
x, y);
|
||||
} else {
|
||||
char *name = NULL;
|
||||
|
||||
status = _cairo_utf8_to_pdf_string (named_dest->attrs.name, &name);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->object_stream.stream, " /Dest %s\n",
|
||||
name);
|
||||
free (name);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the page is known, emit an explicit dest */
|
||||
if (!link_attrs->dest) {
|
||||
if (link_attrs->page < 1)
|
||||
return _cairo_tag_error ("Link attribute: \"page=%d\" page must be >= 1", link_attrs->page);
|
||||
|
||||
if (link_attrs->page <= (int)_cairo_array_num_elements (&surface->pages)) {
|
||||
_cairo_output_stream_printf (surface->object_stream.stream, " /Dest ");
|
||||
return cairo_pdf_interchange_write_explicit_dest (surface,
|
||||
link_attrs->page,
|
||||
link_attrs->has_pos,
|
||||
link_attrs->pos.x,
|
||||
link_attrs->pos.y);
|
||||
/* name does not exist */
|
||||
if (link_attrs->link_type == TAG_LINK_DEST_AND_URI) {
|
||||
/* Don't emit anything. The caller will fallback to emitting a URI destination. */
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
/* Mising destination. Emit a "do nothing" dest that points to the same page and position. */
|
||||
_cairo_tag_warning ("Link to dest=\"%s\" not found", link_attrs->dest);
|
||||
_cairo_output_stream_printf (surface->object_stream.stream, " /Dest ");
|
||||
status = cairo_pdf_interchange_write_explicit_dest (surface,
|
||||
link_attrs->link_page,
|
||||
FALSE,
|
||||
0, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Link refers to a future or unknown page. Use an indirect object
|
||||
* and write the link at the end of the document */
|
||||
/* link_attrs->link_type == TAG_LINK_PAGE */
|
||||
|
||||
link = _cairo_malloc (sizeof (cairo_pdf_forward_link_t));
|
||||
if (unlikely (link == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
if (link_attrs->page < 1)
|
||||
return _cairo_tag_error ("Link attribute: \"page=%d\" page must be >= 1", link_attrs->page);
|
||||
|
||||
link_res = _cairo_pdf_surface_new_object (surface);
|
||||
if (link_res.id == 0)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
if (link_attrs->page > (int)_cairo_array_num_elements (&surface->pages))
|
||||
return _cairo_tag_error ("Link attribute: \"page=%d\" page exceeds page count (%d)",
|
||||
link_attrs->page, _cairo_array_num_elements (&surface->pages));
|
||||
|
||||
_cairo_output_stream_printf (surface->object_stream.stream,
|
||||
" /Dest %d 0 R\n",
|
||||
link_res.id);
|
||||
|
||||
link->res = link_res;
|
||||
link->dest = link_attrs->dest ? strdup (link_attrs->dest) : NULL;
|
||||
link->page = link_attrs->page;
|
||||
link->has_pos = link_attrs->has_pos;
|
||||
link->pos = link_attrs->pos;
|
||||
status = _cairo_array_append (&surface->forward_links, link);
|
||||
|
||||
return status;
|
||||
_cairo_output_stream_printf (surface->object_stream.stream, " /Dest ");
|
||||
return cairo_pdf_interchange_write_explicit_dest (surface,
|
||||
link_attrs->page,
|
||||
link_attrs->has_pos,
|
||||
link_attrs->pos.x,
|
||||
link_attrs->pos.y);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -918,12 +919,20 @@ cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface,
|
|||
cairo_int_status_t status;
|
||||
char *dest = NULL;
|
||||
|
||||
if (link_attrs->link_type == TAG_LINK_DEST) {
|
||||
if (link_attrs->link_type == TAG_LINK_DEST_AND_URI ||
|
||||
link_attrs->link_type == TAG_LINK_DEST ||
|
||||
link_attrs->link_type == TAG_LINK_PAGE)
|
||||
{
|
||||
status = cairo_pdf_interchange_write_dest (surface, link_attrs);
|
||||
if (unlikely (status))
|
||||
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return status;
|
||||
|
||||
} else if (link_attrs->link_type == TAG_LINK_URI) {
|
||||
/* CAIRO_INT_STATUS_NOTHING_TO_DO means that the link type is TAG_LINK_DEST_AND_URI
|
||||
* and the DEST is missing. Fall through to writing a URI link below.
|
||||
*/
|
||||
}
|
||||
|
||||
if (link_attrs->link_type == TAG_LINK_URI || link_attrs->link_type == TAG_LINK_DEST_AND_URI) {
|
||||
status = _cairo_utf8_to_pdf_string (link_attrs->uri, &dest);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
|
@ -1460,67 +1469,6 @@ strcmp_null (const char *s1, const char *s2)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
cairo_pdf_interchange_write_forward_links (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
int num_elems, i;
|
||||
cairo_pdf_forward_link_t *link;
|
||||
cairo_int_status_t status;
|
||||
cairo_pdf_named_dest_t key;
|
||||
cairo_pdf_named_dest_t *named_dest;
|
||||
cairo_pdf_interchange_t *ic = &surface->interchange;
|
||||
|
||||
num_elems = _cairo_array_num_elements (&surface->forward_links);
|
||||
for (i = 0; i < num_elems; i++) {
|
||||
link = _cairo_array_index (&surface->forward_links, i);
|
||||
if (link->page > (int)_cairo_array_num_elements (&surface->pages))
|
||||
return _cairo_tag_error ("Link attribute: \"page=%d\" page exceeds page count (%d)",
|
||||
link->page, _cairo_array_num_elements (&surface->pages));
|
||||
|
||||
|
||||
status = _cairo_pdf_surface_object_begin (surface, link->res);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (link->dest) {
|
||||
key.attrs.name = link->dest;
|
||||
init_named_dest_key (&key);
|
||||
named_dest = _cairo_hash_table_lookup (ic->named_dests, &key.base);
|
||||
if (named_dest) {
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
|
||||
if (named_dest->extents.valid) {
|
||||
x = named_dest->extents.extents.x;
|
||||
y = named_dest->extents.extents.y;
|
||||
}
|
||||
|
||||
if (named_dest->attrs.x_valid)
|
||||
x = named_dest->attrs.x;
|
||||
|
||||
if (named_dest->attrs.y_valid)
|
||||
y = named_dest->attrs.y;
|
||||
|
||||
status = cairo_pdf_interchange_write_explicit_dest (surface,
|
||||
named_dest->page,
|
||||
TRUE,
|
||||
x, y);
|
||||
} else {
|
||||
return _cairo_tag_error ("Link to dest=\"%s\" not found", link->dest);
|
||||
}
|
||||
} else {
|
||||
cairo_pdf_interchange_write_explicit_dest (surface,
|
||||
link->page,
|
||||
link->has_pos,
|
||||
link->pos.x,
|
||||
link->pos.y);
|
||||
}
|
||||
_cairo_pdf_surface_object_end (surface);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
cairo_pdf_interchange_write_page_labels (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
|
|
@ -1658,6 +1606,7 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface)
|
|||
cairo_pdf_named_dest_t *dest = ic->sorted_dests[i];
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
char *name = NULL;
|
||||
|
||||
if (dest->attrs.internal)
|
||||
continue;
|
||||
|
|
@ -1673,13 +1622,19 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface)
|
|||
if (dest->attrs.y_valid)
|
||||
y = dest->attrs.y;
|
||||
|
||||
status = _cairo_utf8_to_pdf_string (dest->attrs.name, &name);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
page_info = _cairo_array_index (&surface->pages, dest->page - 1);
|
||||
_cairo_output_stream_printf (surface->object_stream.stream,
|
||||
" (%s) [%d 0 R /XYZ %f %f 0]\n",
|
||||
dest->attrs.name,
|
||||
" %s [%d 0 R /XYZ %f %f 0]\n",
|
||||
name,
|
||||
page_info->page_res.id,
|
||||
x,
|
||||
page_info->height - y);
|
||||
free (name);
|
||||
|
||||
}
|
||||
_cairo_output_stream_printf (surface->object_stream.stream,
|
||||
" ]\n"
|
||||
|
|
@ -2419,10 +2374,6 @@ _cairo_pdf_interchange_write_document_objects (cairo_pdf_surface_t *surface)
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cairo_pdf_interchange_write_forward_links (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cairo_pdf_interchange_write_names_dict (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -266,14 +266,6 @@ typedef struct _cairo_pdf_outline_entry {
|
|||
int count;
|
||||
} cairo_pdf_outline_entry_t;
|
||||
|
||||
typedef struct _cairo_pdf_forward_link {
|
||||
cairo_pdf_resource_t res;
|
||||
char *dest;
|
||||
int page;
|
||||
cairo_bool_t has_pos;
|
||||
cairo_point_double_t pos;
|
||||
} cairo_pdf_forward_link_t;
|
||||
|
||||
struct docinfo {
|
||||
char *title;
|
||||
char *author;
|
||||
|
|
@ -468,7 +460,6 @@ struct _cairo_pdf_surface {
|
|||
cairo_pdf_interchange_t interchange;
|
||||
int page_parent_tree; /* -1 if not used */
|
||||
cairo_array_t page_annots;
|
||||
cairo_array_t forward_links;
|
||||
cairo_bool_t tagged;
|
||||
char *current_page_label;
|
||||
cairo_array_t page_labels;
|
||||
|
|
|
|||
|
|
@ -555,7 +555,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
|
||||
surface->page_parent_tree = -1;
|
||||
_cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t));
|
||||
_cairo_array_init (&surface->forward_links, sizeof (cairo_pdf_forward_link_t));
|
||||
surface->tagged = FALSE;
|
||||
surface->current_page_label = NULL;
|
||||
_cairo_array_init (&surface->page_labels, sizeof (char *));
|
||||
|
|
@ -2824,7 +2823,6 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
_cairo_array_fini (&surface->fonts);
|
||||
_cairo_array_fini (&surface->knockout_group);
|
||||
_cairo_array_fini (&surface->page_annots);
|
||||
_cairo_array_fini (&surface->forward_links);
|
||||
|
||||
_cairo_hash_table_foreach (surface->color_glyphs,
|
||||
_cairo_pdf_color_glyph_pluck,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ typedef enum {
|
|||
TAG_LINK_DEST,
|
||||
TAG_LINK_URI,
|
||||
TAG_LINK_FILE,
|
||||
TAG_LINK_PAGE,
|
||||
TAG_LINK_DEST_AND_URI,
|
||||
} cairo_tag_link_type_t;
|
||||
|
||||
typedef struct _cairo_content_attrs {
|
||||
|
|
|
|||
|
|
@ -655,25 +655,30 @@ _cairo_tag_parse_link_attributes (const char *attributes, cairo_link_attrs_t *li
|
|||
}
|
||||
}
|
||||
|
||||
if (link_attrs->uri) {
|
||||
link_attrs->link_type = TAG_LINK_URI;
|
||||
if (link_attrs->dest || link_attrs->page || link_attrs->has_pos || link_attrs->file)
|
||||
invalid_combination = TRUE;
|
||||
|
||||
} else if (link_attrs->file) {
|
||||
if (link_attrs->file) {
|
||||
link_attrs->link_type = TAG_LINK_FILE;
|
||||
if (link_attrs->uri)
|
||||
invalid_combination = TRUE;
|
||||
else if (link_attrs->dest && (link_attrs->page || link_attrs->has_pos))
|
||||
invalid_combination = TRUE;
|
||||
|
||||
} else if (link_attrs->uri && link_attrs->dest) {
|
||||
link_attrs->link_type = TAG_LINK_DEST_AND_URI;
|
||||
if (link_attrs->page || link_attrs->has_pos || link_attrs->file)
|
||||
invalid_combination = TRUE;
|
||||
|
||||
} else if (link_attrs->uri) {
|
||||
link_attrs->link_type = TAG_LINK_URI;
|
||||
if (link_attrs->dest || link_attrs->page || link_attrs->has_pos || link_attrs->file)
|
||||
invalid_combination = TRUE;
|
||||
|
||||
} else if (link_attrs->dest) {
|
||||
link_attrs->link_type = TAG_LINK_DEST;
|
||||
if (link_attrs->uri || link_attrs->page || link_attrs->has_pos)
|
||||
invalid_combination = TRUE;
|
||||
|
||||
} else if (link_attrs->page) {
|
||||
link_attrs->link_type = TAG_LINK_DEST;
|
||||
link_attrs->link_type = TAG_LINK_PAGE;
|
||||
if (link_attrs->uri || link_attrs->dest)
|
||||
invalid_combination = TRUE;
|
||||
|
||||
|
|
|
|||
|
|
@ -116,4 +116,7 @@ _cairo_tag_get_type (const char *name);
|
|||
cairo_private cairo_status_t
|
||||
_cairo_tag_error (const char *fmt, ...) CAIRO_PRINTF_FORMAT (1, 2);
|
||||
|
||||
cairo_private void
|
||||
_cairo_tag_warning (const char *fmt, ...) CAIRO_PRINTF_FORMAT (1, 2);
|
||||
|
||||
#endif /* CAIRO_TAG_STACK_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -331,3 +331,17 @@ _cairo_tag_error (const char *fmt, ...)
|
|||
}
|
||||
return _cairo_error (CAIRO_STATUS_TAG_ERROR);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_tag_warning (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (getenv ("CAIRO_DEBUG_TAG") != NULL) {
|
||||
printf ("TAG WARNING: ");
|
||||
va_start (ap, fmt);
|
||||
vprintf (fmt, ap);
|
||||
va_end (ap);
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue