diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2016-10-01 22:44:22 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2016-10-01 22:44:22 +0930 |
commit | 26b3f83ff652a284b79557ec1555b398c566a7eb (patch) | |
tree | 8a5aff3112e7853293a401f0f3ea023230b3e6c3 /src/cairo-pdf-interchange.c | |
parent | 5bfadd5530623d3b12fadf8cd22f95cec4132b65 (diff) | |
download | cairo-26b3f83ff652a284b79557ec1555b398c566a7eb.tar.gz |
pdf: page label API
Diffstat (limited to 'src/cairo-pdf-interchange.c')
-rw-r--r-- | src/cairo-pdf-interchange.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/cairo-pdf-interchange.c b/src/cairo-pdf-interchange.c index a84f0ccfa..622f3b3f3 100644 --- a/src/cairo-pdf-interchange.c +++ b/src/cairo-pdf-interchange.c @@ -599,6 +599,117 @@ cairo_pdf_interchange_write_outline (cairo_pdf_surface_t *surface) return status; } +/* + * Split a page label into a text prefix and numeric suffix. Leading '0's are + * included in the prefix. eg + * "3" => NULL, 3 + * "cover" => "cover", 0 + * "A-2" => "A-", 2 + * "A-002" => "A-00", 2 + */ +static char * +split_label (const char* label, int *num) +{ + int len, i; + + *num = 0; + len = strlen (label); + if (len == 0) + return NULL; + + i = len; + while (i > 0 && _cairo_isdigit (label[i-1])) + i--; + + while (i < len && label[i] == '0') + i++; + + if (i < len) + sscanf (label + i, "%d", num); + + if (i > 0) + return strndup (label, i); + + return NULL; +} + +/* strcmp that handles NULL arguments */ +static cairo_bool_t +strcmp_null (const char *s1, const char *s2) +{ + if (s1 && s2) + return strcmp (s1, s2) == 0; + + if (!s1 && !s2) + return TRUE; + + return FALSE; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_page_labels (cairo_pdf_surface_t *surface) +{ + int num_elems, i; + char *label; + char *prefix; + char *prev_prefix; + int num, prev_num; + cairo_int_status_t status; + + num_elems = _cairo_array_num_elements (&surface->page_labels); + if (num_elems > 0) { + surface->page_labels_res = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Nums [\n", + surface->page_labels_res.id); + prefix = NULL; + prev_prefix = NULL; + num = 0; + prev_num = 0; + for (i = 0; i < num_elems; i++) { + _cairo_array_copy_element (&surface->page_labels, i, &label); + if (label) { + prefix = split_label (label, &num); + } else { + prefix = NULL; + num = i + 1; + } + + if (!strcmp_null (prefix, prev_prefix) || num != prev_num + 1) { + _cairo_output_stream_printf (surface->output, " %d << ", i); + + if (num) + _cairo_output_stream_printf (surface->output, "/S /D /St %d ", num); + + if (prefix) { + char *s; + status = _cairo_utf8_to_pdf_string (prefix, &s); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->output, "/P %s ", s); + free (s); + } + + _cairo_output_stream_printf (surface->output, ">>\n"); + } + free (prev_prefix); + prev_prefix = prefix; + prefix = NULL; + prev_num = num; + } + free (prefix); + free (prev_prefix); + _cairo_output_stream_printf (surface->output, + " ]\n" + ">>\n" + "endobj\n"); + } + + return CAIRO_STATUS_SUCCESS; +} + static void _collect_dest (void *entry, void *closure) { @@ -1077,6 +1188,10 @@ _cairo_pdf_interchange_write_document_objects (cairo_pdf_surface_t *surface) if (unlikely (status)) return status; + status = cairo_pdf_interchange_write_page_labels (surface); + if (unlikely (status)) + return status; + status = cairo_pdf_interchange_write_names_dict (surface); if (unlikely (status)) return status; |