mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-20 14: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_add_outline
|
||||
cairo_pdf_surface_set_metadata
|
||||
cairo_pdf_surface_set_custom_metadata
|
||||
cairo_pdf_surface_set_page_label
|
||||
cairo_pdf_surface_set_thumbnail_size
|
||||
</SECTION>
|
||||
|
|
|
|||
|
|
@ -1169,6 +1169,9 @@ cairo_pdf_interchange_write_docinfo (cairo_pdf_surface_t *surface)
|
|||
{
|
||||
cairo_pdf_interchange_t *ic = &surface->interchange;
|
||||
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);
|
||||
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)
|
||||
_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,
|
||||
">>\n");
|
||||
_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);
|
||||
|
||||
memset (&ic->docinfo, 0, sizeof (ic->docinfo));
|
||||
_cairo_array_init (&ic->custom_metadata, sizeof(struct metadata));
|
||||
_cairo_pdf_interchange_set_create_date (surface);
|
||||
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_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->render_tag_stack);
|
||||
|
|
@ -1674,6 +1700,14 @@ _cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface)
|
|||
free (ic->docinfo.creator);
|
||||
free (ic->docinfo.create_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
|
||||
|
|
@ -1868,3 +1902,69 @@ _cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface,
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
struct metadata {
|
||||
char *name;
|
||||
char *value;
|
||||
};
|
||||
|
||||
typedef struct _cairo_pdf_interchange {
|
||||
cairo_tag_stack_t analysis_tag_stack;
|
||||
cairo_tag_stack_t render_tag_stack;
|
||||
|
|
@ -248,6 +253,7 @@ typedef struct _cairo_pdf_interchange {
|
|||
int annot_page;
|
||||
cairo_array_t outline; /* array of pointers to cairo_pdf_outline_entry_t; */
|
||||
struct docinfo docinfo;
|
||||
cairo_array_t custom_metadata; /* array of struct metadata */
|
||||
|
||||
} cairo_pdf_interchange_t;
|
||||
|
||||
|
|
@ -420,4 +426,9 @@ _cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface,
|
|||
cairo_pdf_metadata_t metadata,
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -907,6 +907,42 @@ cairo_pdf_surface_set_metadata (cairo_surface_t *surface,
|
|||
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:
|
||||
* @surface: a PDF #cairo_surface_t
|
||||
|
|
|
|||
|
|
@ -143,6 +143,11 @@ cairo_pdf_surface_set_metadata (cairo_surface_t *surface,
|
|||
cairo_pdf_metadata_t metadata,
|
||||
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_pdf_surface_set_page_label (cairo_surface_t *surface,
|
||||
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_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);
|
||||
|
||||
draw_cover (surface, cr);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue