mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-20 21:00:10 +01:00
Add cairo_pdf_surface_set_custom_metadata()
This commit is contained in:
parent
2dec76ddfe
commit
0ce4c0fc29
6 changed files with 159 additions and 0 deletions
|
|
@ -82,6 +82,7 @@ cairo_pdf_version_to_string
|
||||||
cairo_pdf_surface_set_size
|
cairo_pdf_surface_set_size
|
||||||
cairo_pdf_surface_add_outline
|
cairo_pdf_surface_add_outline
|
||||||
cairo_pdf_surface_set_metadata
|
cairo_pdf_surface_set_metadata
|
||||||
|
cairo_pdf_surface_set_custom_metadata
|
||||||
cairo_pdf_surface_set_page_label
|
cairo_pdf_surface_set_page_label
|
||||||
cairo_pdf_surface_set_thumbnail_size
|
cairo_pdf_surface_set_thumbnail_size
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
|
||||||
|
|
@ -1169,6 +1169,9 @@ cairo_pdf_interchange_write_docinfo (cairo_pdf_surface_t *surface)
|
||||||
{
|
{
|
||||||
cairo_pdf_interchange_t *ic = &surface->interchange;
|
cairo_pdf_interchange_t *ic = &surface->interchange;
|
||||||
cairo_int_status_t status;
|
cairo_int_status_t status;
|
||||||
|
unsigned int i, num_elems;
|
||||||
|
struct metadata *data;
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
surface->docinfo_res = _cairo_pdf_surface_new_object (surface);
|
surface->docinfo_res = _cairo_pdf_surface_new_object (surface);
|
||||||
if (surface->docinfo_res.id == 0)
|
if (surface->docinfo_res.id == 0)
|
||||||
|
|
@ -1203,6 +1206,26 @@ cairo_pdf_interchange_write_docinfo (cairo_pdf_surface_t *surface)
|
||||||
if (ic->docinfo.mod_date)
|
if (ic->docinfo.mod_date)
|
||||||
_cairo_output_stream_printf (surface->object_stream.stream, " /ModDate %s\n", ic->docinfo.mod_date);
|
_cairo_output_stream_printf (surface->object_stream.stream, " /ModDate %s\n", ic->docinfo.mod_date);
|
||||||
|
|
||||||
|
num_elems = _cairo_array_num_elements (&ic->custom_metadata);
|
||||||
|
for (i = 0; i < num_elems; i++) {
|
||||||
|
data = _cairo_array_index (&ic->custom_metadata, i);
|
||||||
|
if (data->value) {
|
||||||
|
_cairo_output_stream_printf (surface->object_stream.stream, " /");
|
||||||
|
/* The name can be any utf8 string. Use hex codes as
|
||||||
|
* specified in section 7.3.5 of PDF reference
|
||||||
|
*/
|
||||||
|
p = (unsigned char *)data->name;
|
||||||
|
while (*p) {
|
||||||
|
if (*p < 0x21 || *p > 0x7e || *p == '#' || *p == '/')
|
||||||
|
_cairo_output_stream_printf (surface->object_stream.stream, "#%02x", *p);
|
||||||
|
else
|
||||||
|
_cairo_output_stream_printf (surface->object_stream.stream, "%c", *p);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
_cairo_output_stream_printf (surface->object_stream.stream, " %s\n", data->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->object_stream.stream,
|
_cairo_output_stream_printf (surface->object_stream.stream,
|
||||||
">>\n");
|
">>\n");
|
||||||
_cairo_pdf_surface_object_end (surface);
|
_cairo_pdf_surface_object_end (surface);
|
||||||
|
|
@ -1624,6 +1647,7 @@ _cairo_pdf_interchange_init (cairo_pdf_surface_t *surface)
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
memset (&ic->docinfo, 0, sizeof (ic->docinfo));
|
memset (&ic->docinfo, 0, sizeof (ic->docinfo));
|
||||||
|
_cairo_array_init (&ic->custom_metadata, sizeof(struct metadata));
|
||||||
_cairo_pdf_interchange_set_create_date (surface);
|
_cairo_pdf_interchange_set_create_date (surface);
|
||||||
status = _cairo_array_append (&ic->outline, &outline_root);
|
status = _cairo_array_append (&ic->outline, &outline_root);
|
||||||
|
|
||||||
|
|
@ -1654,6 +1678,8 @@ void
|
||||||
_cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface)
|
_cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface)
|
||||||
{
|
{
|
||||||
cairo_pdf_interchange_t *ic = &surface->interchange;
|
cairo_pdf_interchange_t *ic = &surface->interchange;
|
||||||
|
unsigned int i, num_elems;
|
||||||
|
struct metadata *data;
|
||||||
|
|
||||||
_cairo_tag_stack_fini (&ic->analysis_tag_stack);
|
_cairo_tag_stack_fini (&ic->analysis_tag_stack);
|
||||||
_cairo_tag_stack_fini (&ic->render_tag_stack);
|
_cairo_tag_stack_fini (&ic->render_tag_stack);
|
||||||
|
|
@ -1674,6 +1700,14 @@ _cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface)
|
||||||
free (ic->docinfo.creator);
|
free (ic->docinfo.creator);
|
||||||
free (ic->docinfo.create_date);
|
free (ic->docinfo.create_date);
|
||||||
free (ic->docinfo.mod_date);
|
free (ic->docinfo.mod_date);
|
||||||
|
|
||||||
|
num_elems = _cairo_array_num_elements (&ic->custom_metadata);
|
||||||
|
for (i = 0; i < num_elems; i++) {
|
||||||
|
data = _cairo_array_index (&ic->custom_metadata, i);
|
||||||
|
free (data->name);
|
||||||
|
free (data->value);
|
||||||
|
}
|
||||||
|
_cairo_array_fini (&ic->custom_metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_int_status_t
|
cairo_int_status_t
|
||||||
|
|
@ -1868,3 +1902,69 @@ _cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface,
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *reserved_metadata_names[] = {
|
||||||
|
"",
|
||||||
|
"Title",
|
||||||
|
"Author",
|
||||||
|
"Subject",
|
||||||
|
"Keywords",
|
||||||
|
"Creator",
|
||||||
|
"Producer",
|
||||||
|
"CreationDate",
|
||||||
|
"ModDate",
|
||||||
|
"Trapped",
|
||||||
|
};
|
||||||
|
|
||||||
|
cairo_int_status_t
|
||||||
|
_cairo_pdf_interchange_set_custom_metadata (cairo_pdf_surface_t *surface,
|
||||||
|
const char *name,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
cairo_pdf_interchange_t *ic = &surface->interchange;
|
||||||
|
struct metadata *data;
|
||||||
|
struct metadata new_data;
|
||||||
|
int i, num_elems;
|
||||||
|
cairo_int_status_t status;
|
||||||
|
char *s = NULL;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
return CAIRO_STATUS_NULL_POINTER;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_LENGTH (reserved_metadata_names); i++) {
|
||||||
|
if (strcmp(name, reserved_metadata_names[i]) == 0)
|
||||||
|
return CAIRO_STATUS_INVALID_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First check if we already have an entry for this name. If so,
|
||||||
|
* update the value. A NULL value means the entry has been removed
|
||||||
|
* and will not be emitted. */
|
||||||
|
num_elems = _cairo_array_num_elements (&ic->custom_metadata);
|
||||||
|
for (i = 0; i < num_elems; i++) {
|
||||||
|
data = _cairo_array_index (&ic->custom_metadata, i);
|
||||||
|
if (strcmp(name, data->name) == 0) {
|
||||||
|
free (data->value);
|
||||||
|
data->value = NULL;
|
||||||
|
if (value && strlen(value)) {
|
||||||
|
status = _cairo_utf8_to_pdf_string (value, &s);
|
||||||
|
if (unlikely (status))
|
||||||
|
return status;
|
||||||
|
data->value = s;
|
||||||
|
}
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new entry */
|
||||||
|
status = CAIRO_STATUS_SUCCESS;
|
||||||
|
if (value && strlen(value)) {
|
||||||
|
new_data.name = strdup (name);
|
||||||
|
status = _cairo_utf8_to_pdf_string (value, &s);
|
||||||
|
if (unlikely (status))
|
||||||
|
return status;
|
||||||
|
new_data.value = s;
|
||||||
|
status = _cairo_array_append (&ic->custom_metadata, &new_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,11 @@ struct docinfo {
|
||||||
char *mod_date;
|
char *mod_date;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct metadata {
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _cairo_pdf_interchange {
|
typedef struct _cairo_pdf_interchange {
|
||||||
cairo_tag_stack_t analysis_tag_stack;
|
cairo_tag_stack_t analysis_tag_stack;
|
||||||
cairo_tag_stack_t render_tag_stack;
|
cairo_tag_stack_t render_tag_stack;
|
||||||
|
|
@ -248,6 +253,7 @@ typedef struct _cairo_pdf_interchange {
|
||||||
int annot_page;
|
int annot_page;
|
||||||
cairo_array_t outline; /* array of pointers to cairo_pdf_outline_entry_t; */
|
cairo_array_t outline; /* array of pointers to cairo_pdf_outline_entry_t; */
|
||||||
struct docinfo docinfo;
|
struct docinfo docinfo;
|
||||||
|
cairo_array_t custom_metadata; /* array of struct metadata */
|
||||||
|
|
||||||
} cairo_pdf_interchange_t;
|
} cairo_pdf_interchange_t;
|
||||||
|
|
||||||
|
|
@ -420,4 +426,9 @@ _cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface,
|
||||||
cairo_pdf_metadata_t metadata,
|
cairo_pdf_metadata_t metadata,
|
||||||
const char *utf8);
|
const char *utf8);
|
||||||
|
|
||||||
|
cairo_private cairo_int_status_t
|
||||||
|
_cairo_pdf_interchange_set_custom_metadata (cairo_pdf_surface_t *surface,
|
||||||
|
const char *name,
|
||||||
|
const char *value);
|
||||||
|
|
||||||
#endif /* CAIRO_PDF_SURFACE_PRIVATE_H */
|
#endif /* CAIRO_PDF_SURFACE_PRIVATE_H */
|
||||||
|
|
|
||||||
|
|
@ -907,6 +907,42 @@ cairo_pdf_surface_set_metadata (cairo_surface_t *surface,
|
||||||
status = _cairo_surface_set_error (surface, status);
|
status = _cairo_surface_set_error (surface, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cairo_pdf_surface_set_custom_metadata:
|
||||||
|
* @surface: a PDF #cairo_surface_t
|
||||||
|
* @name: The name of the custom metadata item to set (utf8).
|
||||||
|
* @value: The value of the metadata (utf8).
|
||||||
|
*
|
||||||
|
* Set custom document metadata. @name may be any string except for
|
||||||
|
* the following names reserved by PDF: "Title", "Author", "Subject",
|
||||||
|
* "Keywords", "Creator", "Producer", "CreationDate", "ModDate",
|
||||||
|
* "Trapped".
|
||||||
|
*
|
||||||
|
* If @value is NULL or an empty string, the @name metadata will not be set.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* <informalexample><programlisting>
|
||||||
|
* cairo_pdf_surface_set_custom_metadata (surface, "ISBN", "978-0123456789");
|
||||||
|
* </programlisting></informalexample>
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
cairo_pdf_surface_set_custom_metadata (cairo_surface_t *surface,
|
||||||
|
const char *name,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
|
if (! _extract_pdf_surface (surface, &pdf_surface))
|
||||||
|
return;
|
||||||
|
|
||||||
|
status = _cairo_pdf_interchange_set_custom_metadata (pdf_surface, name, value);
|
||||||
|
if (status)
|
||||||
|
status = _cairo_surface_set_error (surface, status);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_pdf_surface_set_page_label:
|
* cairo_pdf_surface_set_page_label:
|
||||||
* @surface: a PDF #cairo_surface_t
|
* @surface: a PDF #cairo_surface_t
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,11 @@ cairo_pdf_surface_set_metadata (cairo_surface_t *surface,
|
||||||
cairo_pdf_metadata_t metadata,
|
cairo_pdf_metadata_t metadata,
|
||||||
const char *utf8);
|
const char *utf8);
|
||||||
|
|
||||||
|
cairo_public void
|
||||||
|
cairo_pdf_surface_set_custom_metadata (cairo_surface_t *surface,
|
||||||
|
const char *name,
|
||||||
|
const char *value);
|
||||||
|
|
||||||
cairo_public void
|
cairo_public void
|
||||||
cairo_pdf_surface_set_page_label (cairo_surface_t *surface,
|
cairo_pdf_surface_set_page_label (cairo_surface_t *surface,
|
||||||
const char *utf8);
|
const char *utf8);
|
||||||
|
|
|
||||||
|
|
@ -377,6 +377,12 @@ create_document (cairo_surface_t *surface, cairo_t *cr)
|
||||||
cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_CREATE_DATE, "2016-01-01T12:34:56+10:30");
|
cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_CREATE_DATE, "2016-01-01T12:34:56+10:30");
|
||||||
cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_MOD_DATE, "2016-06-21T05:43:21Z");
|
cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_MOD_DATE, "2016-06-21T05:43:21Z");
|
||||||
|
|
||||||
|
cairo_pdf_surface_set_custom_metadata (surface, "DocumentNumber", "12345");
|
||||||
|
/* Include some non ASCII characters */
|
||||||
|
cairo_pdf_surface_set_custom_metadata (surface, "Document Name", "\xc2\xab""cairo test\xc2\xbb");
|
||||||
|
/* Test unsetting custom metadata. "DocumentNumber" should not be emitted. */
|
||||||
|
cairo_pdf_surface_set_custom_metadata (surface, "DocumentNumber", "");
|
||||||
|
|
||||||
cairo_tag_begin (cr, "Document", NULL);
|
cairo_tag_begin (cr, "Document", NULL);
|
||||||
|
|
||||||
draw_cover (surface, cr);
|
draw_cover (surface, cr);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue