diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2021-08-18 19:41:26 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2021-08-22 13:43:34 +0930 |
commit | 0ce4c0fc29230a15c12e66571dba2dbfa428285c (patch) | |
tree | 96ee813d5a8a25d7d563f92efaba22aad74e3966 /src/cairo-pdf-interchange.c | |
parent | 2dec76ddfe9499b5a6efc1ccc8e52536a314543b (diff) | |
download | cairo-0ce4c0fc29230a15c12e66571dba2dbfa428285c.tar.gz |
Add cairo_pdf_surface_set_custom_metadata()
Diffstat (limited to 'src/cairo-pdf-interchange.c')
-rw-r--r-- | src/cairo-pdf-interchange.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/cairo-pdf-interchange.c b/src/cairo-pdf-interchange.c index 921952afb..38bec977f 100644 --- a/src/cairo-pdf-interchange.c +++ b/src/cairo-pdf-interchange.c @@ -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; +} |