summaryrefslogtreecommitdiff
path: root/src/cairo-pdf-surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-pdf-surface.c')
-rw-r--r--src/cairo-pdf-surface.c441
1 files changed, 315 insertions, 126 deletions
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 2b1bf72e4..459f90a8f 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -471,7 +471,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
surface->surface_bounded = TRUE;
_cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
- _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
+ _cairo_array_init (&surface->pages, sizeof (cairo_pdf_page_info_t));
_cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
_cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
@@ -482,7 +482,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
_cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
_cairo_array_init (&surface->doc_surfaces, sizeof (cairo_pdf_source_surface_t));
_cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t));
- _cairo_array_init (&surface->page_heights, sizeof (double));
surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
if (unlikely (surface->all_surfaces == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -495,6 +494,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
goto BAIL1;
}
+ surface->duplicate_surface_number = 0;
+
_cairo_pdf_group_resources_init (&surface->resources);
surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
@@ -565,8 +566,11 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
surface->thumbnail_height = 0;
surface->thumbnail_image = NULL;
- if (getenv ("CAIRO_DEBUG_PDF") != NULL)
+ surface->debug = FALSE;
+ if (getenv ("CAIRO_DEBUG_PDF") != NULL) {
+ surface->debug = TRUE;
surface->compress_streams = FALSE;
+ }
surface->paginated_surface = _cairo_paginated_surface_create (
&surface->base,
@@ -1457,6 +1461,9 @@ _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
if (a->interpolate != b->interpolate)
return FALSE;
+ if (a->region_id != b->region_id)
+ return FALSE;
+
if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length)
return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0);
@@ -1472,6 +1479,9 @@ _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
} else {
key->base.hash = key->id;
}
+ key->base.hash = _cairo_hash_bytes (key->base.hash,
+ &key->region_id,
+ sizeof(key->region_id));
}
static cairo_bool_t
@@ -1601,6 +1611,11 @@ _get_source_surface_extents (cairo_surface_t *source,
* @surface: [in] the pdf surface
* @source_surface: [in] A #cairo_surface_t to use as the source surface
* @source_pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
+ * @region_id: [in] Surfaces containing tags set this to the recording
+ * surface region id. When tags are used in a XObject, PDF requires a
+ * separate object for each use (section 14.7.4.2) @region_id is used
+ * as a key to ensure a separate object is emitted for each use. Set
+ * to 0 for surfaces without tags.
* @op: [in] the operator used to composite this source
* @filter: [in] filter type of the source pattern
* @stencil_mask: [in] if true, the surface will be written to the PDF as an /ImageMask
@@ -1628,6 +1643,7 @@ static cairo_int_status_t
_cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
cairo_surface_t *source_surface,
const cairo_pattern_t *source_pattern,
+ int region_id,
cairo_operator_t op,
cairo_filter_t filter,
cairo_bool_t stencil_mask,
@@ -1653,6 +1669,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
cairo_rectangle_int_t op_extents;
double x, y;
cairo_bool_t subsurface;
+ cairo_bool_t emit_image;
switch (filter) {
default:
@@ -1700,10 +1717,21 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
*source_extents = op_extents;
surface_key.id = source_surface->unique_id;
- surface_key.interpolate = interpolate;
+
+ /* Recording surfaces do not use interpolate. Ensure it is always
+ * false for recording surfaces. This is because pdf-interchange
+ * needs to lookup recording surfaces in the hash table using
+ * interpolate = FALSE in the key since it does not know the
+ * interpolate value passed to this function.
+ */
+ emit_image = source_surface->type != CAIRO_SURFACE_TYPE_RECORDING;
+ surface_key.interpolate = emit_image ? interpolate : FALSE;
+
cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID,
(const unsigned char **) &surface_key.unique_id,
&surface_key.unique_id_length);
+
+ surface_key.region_id = region_id;
_cairo_pdf_source_surface_init_key (&surface_key);
surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
if (surface_entry) {
@@ -1746,9 +1774,12 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
if (pdf_source)
*pdf_source = surface_entry;
+
surface_entry->id = surface_key.id;
+ surface_entry->region_id = region_id;
surface_entry->operator = op;
- surface_entry->interpolate = interpolate;
+ surface_entry->interpolate = emit_image ? interpolate : FALSE;
+ surface_entry->emit_image = emit_image;
surface_entry->stencil_mask = stencil_mask;
surface_entry->smask = smask;
surface_entry->need_transp_group = need_transp_group;
@@ -1810,11 +1841,6 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
goto fail3;
}
- /* Test if surface will be emitted as image or recording */
- status = _cairo_pdf_surface_emit_surface (surface, &src_surface, TRUE, &surface_entry->emit_image);
- if (unlikely (status))
- goto fail3;
-
if (surface_entry->bounded) {
status = _cairo_array_append (&surface->page_surfaces, &src_surface);
if (unlikely (status))
@@ -1858,6 +1884,7 @@ static cairo_int_status_t
_cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
const cairo_pattern_t *pattern,
cairo_operator_t op,
+ cairo_analysis_source_t source_type,
const cairo_rectangle_int_t *extents,
cairo_bool_t is_shading,
cairo_pdf_resource_t *pattern_res,
@@ -1865,6 +1892,7 @@ _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
{
cairo_pdf_pattern_t pdf_pattern;
cairo_int_status_t status;
+ int region_id = 0;
pdf_pattern.is_shading = is_shading;
pdf_pattern.operator = op;
@@ -1923,6 +1951,17 @@ _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
* Y-axis. */
pdf_pattern.inverted_y_axis = pdf_pattern.gstate_res.id ? TRUE : surface->in_xobject;
+ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+ if (_cairo_pdf_interchange_struct_tree_requires_recording_surface (surface,
+ surface_pattern,
+ source_type))
+ {
+ region_id = surface_pattern->region_array_id;
+ }
+ }
+ pdf_pattern.region_id = region_id;
+
status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
if (unlikely (status)) {
cairo_pattern_destroy (pdf_pattern.pattern);
@@ -1954,6 +1993,7 @@ _cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t *surface,
return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
pattern,
op,
+ CAIRO_ANALYSIS_SOURCE_NONE,
extents,
TRUE,
shading_res,
@@ -1964,6 +2004,7 @@ static cairo_int_status_t
_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
const cairo_pattern_t *pattern,
cairo_operator_t op,
+ cairo_analysis_source_t source_type,
const cairo_rectangle_int_t *extents,
cairo_pdf_resource_t *pattern_res,
cairo_pdf_resource_t *gstate_res)
@@ -1971,6 +2012,7 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
pattern,
op,
+ source_type,
extents,
FALSE,
pattern_res,
@@ -2242,6 +2284,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
surface->group_stream.mem_stream = NULL;
surface->group_stream.stream = NULL;
+ surface->reset_gs_required = FALSE;
return status;
}
@@ -2249,7 +2292,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
static cairo_int_status_t
_cairo_pdf_surface_open_object_stream (cairo_pdf_surface_t *surface)
{
- if (surface->pdf_version < CAIRO_PDF_VERSION_1_5) {
+ if (surface->debug || surface->pdf_version < CAIRO_PDF_VERSION_1_5) {
/* Object streams not supported. All objects will be written
* directly to the file. */
assert (surface->pdf_stream.active == FALSE);
@@ -2305,7 +2348,9 @@ _cairo_pdf_surface_object_end (cairo_pdf_surface_t *surface)
}
}
-static int _cairo_xref_stream_object_compare (const void *a, const void *b)
+static int
+_cairo_xref_stream_object_compare (const void *a,
+ const void *b)
{
const cairo_xref_stream_object_t *a_obj = a;
const cairo_xref_stream_object_t *b_obj = b;
@@ -2427,7 +2472,8 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
const cairo_box_double_t *bbox,
cairo_pdf_resource_t *resource,
cairo_bool_t is_form,
- cairo_bool_t is_group)
+ cairo_bool_t is_group,
+ int struct_parents)
{
cairo_int_status_t status;
@@ -2441,41 +2487,56 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
if (is_form) {
assert (bbox != NULL);
+ cairo_output_stream_t *mem_stream = _cairo_memory_stream_create ();
if (is_group) {
- status =
- _cairo_pdf_surface_open_stream (surface,
- resource,
- surface->compress_streams,
- " /Type /XObject\n"
- " /Subtype /Form\n"
- " /BBox [ %f %f %f %f ]\n"
- " /Group <<\n"
- " /Type /Group\n"
- " /S /Transparency\n"
- " /I true\n"
- " /CS /DeviceRGB\n"
- " >>\n"
- " /Resources %d 0 R\n",
- bbox->p1.x,
- bbox->p1.y,
- bbox->p2.x,
- bbox->p2.y,
- surface->content_resources.id);
+ _cairo_output_stream_printf (mem_stream,
+ " /Type /XObject\n"
+ " /Subtype /Form\n"
+ " /BBox [ %f %f %f %f ]\n"
+ " /Group <<\n"
+ " /Type /Group\n"
+ " /S /Transparency\n"
+ " /I true\n"
+ " /CS /DeviceRGB\n"
+ " >>\n"
+ " /Resources %d 0 R\n",
+ bbox->p1.x,
+ bbox->p1.y,
+ bbox->p2.x,
+ bbox->p2.y,
+ surface->content_resources.id);
} else {
- status =
- _cairo_pdf_surface_open_stream (surface,
- resource,
- surface->compress_streams,
- " /Type /XObject\n"
- " /Subtype /Form\n"
- " /BBox [ %f %f %f %f ]\n"
- " /Resources %d 0 R\n",
- bbox->p1.x,
- bbox->p1.y,
- bbox->p2.x,
- bbox->p2.y,
- surface->content_resources.id);
+ _cairo_output_stream_printf (mem_stream,
+ " /Type /XObject\n"
+ " /Subtype /Form\n"
+ " /BBox [ %f %f %f %f ]\n"
+ " /Resources %d 0 R\n",
+ bbox->p1.x,
+ bbox->p1.y,
+ bbox->p2.x,
+ bbox->p2.y,
+ surface->content_resources.id);
+ }
+ if (struct_parents >= 0) {
+ _cairo_output_stream_printf (mem_stream,
+ " /StructParents %d\n", struct_parents);
}
+
+ unsigned char *data;
+ unsigned long length;
+ status = _cairo_memory_stream_destroy (mem_stream, &data, &length);
+ if (unlikely (status))
+ return status;
+
+ char *str = _cairo_strndup ((const char*)data, length); /* Add NULL terminator */
+
+ status =
+ _cairo_pdf_surface_open_stream (surface,
+ resource,
+ surface->compress_streams,
+ str);
+ free (str);
+ free (data);
} else {
status =
_cairo_pdf_surface_open_stream (surface,
@@ -2550,6 +2611,73 @@ _cairo_pdf_color_glyph_pluck (void *entry, void *closure)
free (glyph_entry);
}
+static cairo_int_status_t
+_cairo_pdf_surface_write_page_dicts (cairo_pdf_surface_t *surface)
+{
+ cairo_int_status_t status;
+ cairo_pdf_page_info_t *page_info;
+ int num_annots;
+ cairo_pdf_resource_t res;
+
+ for (unsigned i = 0; i < _cairo_array_num_elements (&surface->pages); i++) {
+ page_info = _cairo_array_index (&surface->pages, i);
+
+ status = _cairo_pdf_surface_object_begin (surface, page_info->page_res);
+ if (unlikely (status))
+ return status;
+
+ _cairo_output_stream_printf (surface->object_stream.stream,
+ "<< /Type /Page %% %d\n"
+ " /Parent %d 0 R\n"
+ " /MediaBox [ 0 0 %f %f ]\n"
+ " /Contents %d 0 R\n"
+ " /Group <<\n"
+ " /Type /Group\n"
+ " /S /Transparency\n"
+ " /I true\n"
+ " /CS /DeviceRGB\n"
+ " >>\n"
+ " /Resources %d 0 R\n",
+ i + 1,
+ surface->pages_resource.id,
+ page_info->width,
+ page_info->height,
+ page_info->content.id,
+ page_info->resources.id);
+
+ if (page_info->struct_parents >= 0) {
+ _cairo_output_stream_printf (surface->object_stream.stream,
+ " /StructParents %d\n",
+ page_info->struct_parents);
+ }
+
+ num_annots = _cairo_array_num_elements (&page_info->annots);
+ if (num_annots > 0) {
+ _cairo_output_stream_printf (surface->object_stream.stream,
+ " /Annots [ ");
+ for (int j = 0; j < num_annots; j++) {
+ _cairo_array_copy_element (&page_info->annots, j, &res);
+ _cairo_output_stream_printf (surface->object_stream.stream,
+ "%d 0 R ",
+ res.id);
+ }
+ _cairo_output_stream_printf (surface->object_stream.stream, "]\n");
+ }
+
+ if (page_info->thumbnail.id) {
+ _cairo_output_stream_printf (surface->object_stream.stream,
+ " /Thumb %d 0 R\n",
+ page_info->thumbnail.id);
+ }
+
+ _cairo_output_stream_printf (surface->object_stream.stream,
+ ">>\n");
+ _cairo_pdf_surface_object_end (surface);
+ }
+
+ return status;
+}
+
static cairo_status_t
_cairo_pdf_surface_finish (void *abstract_surface)
{
@@ -2594,6 +2722,10 @@ _cairo_pdf_surface_finish (void *abstract_surface)
if (unlikely (status))
return status;
+ status = _cairo_pdf_surface_write_page_dicts (surface);
+ if (unlikely (status))
+ return status;
+
catalog = _cairo_pdf_surface_new_object (surface);
if (catalog.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2606,7 +2738,7 @@ _cairo_pdf_surface_finish (void *abstract_surface)
if (unlikely (status))
return status;
- if (surface->pdf_version >= CAIRO_PDF_VERSION_1_5)
+ if (!surface->debug && surface->pdf_version >= CAIRO_PDF_VERSION_1_5)
{
xref_res = _cairo_pdf_surface_new_object (surface);
status = _cairo_pdf_surface_write_xref_stream (surface,
@@ -2669,6 +2801,11 @@ _cairo_pdf_surface_finish (void *abstract_surface)
_cairo_pdf_group_resources_fini (&surface->resources);
_cairo_array_fini (&surface->objects);
+ size = _cairo_array_num_elements (&surface->pages);
+ for (i = 0; i < size; i++) {
+ cairo_pdf_page_info_t *page_info = _cairo_array_index (&surface->pages, i);
+ _cairo_array_fini (&page_info->annots);
+ }
_cairo_array_fini (&surface->pages);
_cairo_array_fini (&surface->rgb_linear_functions);
_cairo_array_fini (&surface->alpha_linear_functions);
@@ -2705,7 +2842,6 @@ _cairo_pdf_surface_finish (void *abstract_surface)
return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING);
}
_cairo_array_fini (&surface->jbig2_global);
- _cairo_array_fini (&surface->page_heights);
size = _cairo_array_num_elements (&surface->page_labels);
for (i = 0; i < size; i++) {
@@ -2725,7 +2861,7 @@ static cairo_int_status_t
_cairo_pdf_surface_start_page (void *abstract_surface)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_pdf_resource_t page;
+ cairo_pdf_page_info_t page_info;
cairo_int_status_t status;
/* Document header */
@@ -2758,11 +2894,19 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
_cairo_pdf_group_resources_clear (&surface->resources);
surface->in_xobject = FALSE;
- page = _cairo_pdf_surface_new_object (surface);
- if (page.id == 0)
+ page_info.page_res = _cairo_pdf_surface_new_object (surface);
+ if (page_info.page_res.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- status = _cairo_array_append (&surface->pages, &page);
+ page_info.width = surface->width;
+ page_info.height = surface->height;
+ page_info.content.id = 0;
+ page_info.resources.id = 0;
+ page_info.thumbnail.id = 0;
+ page_info.struct_parents = -1;
+ _cairo_array_init (&page_info.annots, sizeof (cairo_pdf_resource_t));
+
+ status = _cairo_array_append (&surface->pages, &page_info);
if (unlikely (status))
return status;
@@ -2777,13 +2921,17 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
cairo_pdf_surface_t *surface = abstract_surface;
cairo_box_double_t bbox;
+ status = _cairo_pdf_interchange_end_page_content (surface);
+ if (unlikely (status))
+ return status;
+
surface->has_fallback_images = has_fallbacks;
surface->in_xobject = has_fallbacks;
bbox.p1.x = 0;
bbox.p1.y = 0;
bbox.p2.x = surface->width;
bbox.p2.y = surface->height;
- status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks, has_fallbacks);
+ status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks, has_fallbacks, -1);
if (unlikely (status))
return status;
@@ -2883,6 +3031,7 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa
status = _cairo_pdf_surface_add_source_surface (surface,
pad_image,
NULL,
+ -1 , /* node_surface_index */
CAIRO_OPERATOR_OVER, /* not used for images */
source->filter,
FALSE, /* stencil mask */
@@ -3722,6 +3871,7 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
cairo_bool_t is_subsurface;
cairo_bool_t transparency_group;
cairo_recording_surface_t *recording;
+ int struct_parents = -1;
assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE);
@@ -3780,11 +3930,20 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
_cairo_recording_surface_has_only_bilevel_alpha (recording) &&
_cairo_recording_surface_has_only_op_over (recording));
+ status = _cairo_pdf_interchange_emit_recording_surface_begin (surface,
+ pdf_source->surface,
+ pdf_source->hash_entry->region_id,
+ pdf_source->hash_entry->surface_res,
+ &struct_parents);
+ if (unlikely (status))
+ goto err;
+
status = _cairo_pdf_surface_open_content_stream (surface,
&bbox,
&pdf_source->hash_entry->surface_res,
TRUE,
- transparency_group);
+ transparency_group,
+ struct_parents);
if (unlikely (status))
goto err;
@@ -3823,6 +3982,10 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
surface->paginated_mode = old_paginated_mode;
surface->surface_extents = old_surface_extents;
surface->surface_bounded = old_surface_bounded;
+ surface->reset_gs_required = FALSE;
+
+ if (pdf_source->hash_entry->region_id > 0)
+ status = _cairo_pdf_interchange_emit_recording_surface_end (surface, pdf_source->surface);
err:
cairo_surface_destroy (free_me);
@@ -3964,6 +4127,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_add_source_surface (surface,
NULL,
pattern,
+ pdf_pattern->region_id,
pdf_pattern->operator,
pattern->filter,
FALSE, /* stencil mask */
@@ -5108,6 +5272,7 @@ static cairo_int_status_t
_cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
+ cairo_analysis_source_t source_type,
const cairo_rectangle_int_t *extents,
double alpha,
cairo_pdf_resource_t *smask_res,
@@ -5119,6 +5284,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
double x_offset;
double y_offset;
cairo_pdf_source_surface_entry_t *pdf_source;
+ int region_id = 0;
if (source->extend == CAIRO_EXTEND_PAD &&
!(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
@@ -5132,9 +5298,19 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
&y_offset,
NULL);
} else {
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
+ if (_cairo_pdf_interchange_struct_tree_requires_recording_surface (surface,
+ surface_pattern,
+ source_type))
+ {
+ region_id = surface_pattern->region_array_id;
+ }
+ }
status = _cairo_pdf_surface_add_source_surface (surface,
NULL,
source,
+ region_id,
op,
source->filter,
stencil_mask,
@@ -5269,6 +5445,7 @@ static cairo_int_status_t
_cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
+ cairo_analysis_source_t source_type,
const cairo_rectangle_int_t *extents,
double alpha,
cairo_bool_t mask)
@@ -5279,6 +5456,7 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
return _cairo_pdf_surface_paint_surface_pattern (surface,
op,
source,
+ source_type,
extents,
alpha,
NULL,
@@ -5474,10 +5652,6 @@ _cairo_pdf_surface_show_page (void *abstract_surface)
cairo_pdf_surface_t *surface = abstract_surface;
cairo_int_status_t status;
- status = _cairo_array_append (&surface->page_heights, &surface->height);
- if (unlikely (status))
- return status;
-
status = _cairo_array_append (&surface->page_labels, &surface->current_page_label);
if (unlikely (status))
return status;
@@ -5530,7 +5704,7 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface,
static cairo_int_status_t
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
{
- cairo_pdf_resource_t page;
+ cairo_pdf_page_info_t *page_info;
int num_pages, i;
cairo_int_status_t status;
@@ -5544,8 +5718,8 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
num_pages = _cairo_array_num_elements (&surface->pages);
for (i = 0; i < num_pages; i++) {
- _cairo_array_copy_element (&surface->pages, i, &page);
- _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", page.id);
+ page_info = _cairo_array_index (&surface->pages, i);
+ _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", page_info->page_res.id);
}
_cairo_output_stream_printf (surface->object_stream.stream, "]\n");
@@ -6605,7 +6779,7 @@ cairo_pdf_surface_emit_color_glyph (cairo_pdf_surface_t *surface,
goto cleanup;
status = _cairo_recording_surface_replay_and_create_regions (glyph_surface, regions_id,
- NULL, analysis, TRUE);
+ NULL, analysis, TRUE, FALSE);
if (status)
goto cleanup;
@@ -6667,6 +6841,7 @@ cairo_pdf_surface_emit_color_glyph (cairo_pdf_surface_t *surface,
_cairo_pdf_surface_paint_surface_pattern (surface,
CAIRO_OPERATOR_OVER,
&surface_pattern.base,
+ CAIRO_ANALYSIS_SOURCE_NONE,
&extents,
1.0, /* alpha */
NULL, /* smask_res */
@@ -6738,6 +6913,7 @@ cairo_pdf_surface_emit_color_glyph_image (cairo_pdf_surface_t *surface,
_cairo_pdf_surface_paint_surface_pattern (surface,
CAIRO_OPERATOR_OVER,
image_pattern,
+ CAIRO_ANALYSIS_SOURCE_NONE,
&extents,
1.0, /* alpha */
NULL, /* smask_res */
@@ -7267,6 +7443,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_paint_pattern (surface,
CAIRO_OPERATOR_OVER,
group->mask,
+ CAIRO_ANALYSIS_MASK_MASK,
&group->extents,
1.0, /* alpha */
FALSE); /* mask */
@@ -7279,6 +7456,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask,
CAIRO_OPERATOR_OVER,
+ CAIRO_ANALYSIS_MASK_MASK,
NULL,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -7344,6 +7522,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_paint_pattern (surface,
CAIRO_OPERATOR_OVER,
group->source,
+ CAIRO_ANALYSIS_MASK_MASK,
&group->extents,
1.0, /* alpha */
FALSE); /* mask */
@@ -7356,6 +7535,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source,
CAIRO_OPERATOR_OVER,
+ CAIRO_ANALYSIS_MASK_MASK,
NULL,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -7593,10 +7773,12 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
static cairo_int_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
{
- cairo_pdf_resource_t knockout, res, thumbnail_res;
- cairo_pdf_resource_t *page;
+ cairo_pdf_resource_t knockout, res;
cairo_int_status_t status;
- unsigned int i, len, page_num, num_annots;
+ unsigned int i, len;
+ cairo_pdf_page_info_t *page_info;
+
+ page_info = _cairo_array_last_element (&surface->pages);
status = _cairo_pdf_surface_open_object_stream (surface);
if (unlikely (status))
@@ -7642,7 +7824,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
return status;
_cairo_pdf_group_resources_clear (&surface->resources);
- status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE, FALSE);
+ status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE, FALSE, -1);
if (unlikely (status))
return status;
@@ -7658,70 +7840,18 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
return status;
}
- thumbnail_res.id = 0;
if (surface->thumbnail_image) {
cairo_pdf_source_surface_entry_t entry;
memset (&entry, 0, sizeof (entry));
- thumbnail_res = _cairo_pdf_surface_new_object (surface);
- entry.surface_res = thumbnail_res;
+ page_info->thumbnail = _cairo_pdf_surface_new_object (surface);
+ entry.surface_res = page_info->thumbnail;
_cairo_pdf_surface_emit_image (surface, surface->thumbnail_image, &entry);
}
- page_num = _cairo_array_num_elements (&surface->pages);
- page = _cairo_array_index (&surface->pages, page_num - 1);
-
- status = _cairo_pdf_surface_object_begin (surface, *page);
- if (unlikely (status))
- return status;
-
- _cairo_output_stream_printf (surface->object_stream.stream,
- "<< /Type /Page %% %d\n"
- " /Parent %d 0 R\n"
- " /MediaBox [ 0 0 %f %f ]\n"
- " /Contents %d 0 R\n"
- " /Group <<\n"
- " /Type /Group\n"
- " /S /Transparency\n"
- " /I true\n"
- " /CS /DeviceRGB\n"
- " >>\n"
- " /Resources %d 0 R\n",
- page_num,
- surface->pages_resource.id,
- surface->width,
- surface->height,
- surface->content.id,
- surface->content_resources.id);
-
- if (surface->page_parent_tree >= 0) {
- _cairo_output_stream_printf (surface->object_stream.stream,
- " /StructParents %d\n",
- surface->page_parent_tree);
- }
-
- num_annots = _cairo_array_num_elements (&surface->page_annots);
- if (num_annots > 0) {
- _cairo_output_stream_printf (surface->object_stream.stream,
- " /Annots [ ");
- for (i = 0; i < num_annots; i++) {
- _cairo_array_copy_element (&surface->page_annots, i, &res);
- _cairo_output_stream_printf (surface->object_stream.stream,
- "%d 0 R ",
- res.id);
- }
- _cairo_output_stream_printf (surface->object_stream.stream, "]\n");
- }
-
- if (thumbnail_res.id) {
- _cairo_output_stream_printf (surface->object_stream.stream,
- " /Thumb %d 0 R\n",
- thumbnail_res.id);
- }
-
- _cairo_output_stream_printf (surface->object_stream.stream,
- ">>\n");
- _cairo_pdf_surface_object_end (surface);
+ page_info->content = surface->content;
+ page_info->resources = surface->content_resources;
+ page_info->struct_parents = surface->page_parent_tree;
status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface, FALSE);
if (unlikely (status))
@@ -7968,7 +8098,7 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
bbox.p1.y = 0;
bbox.p2.x = surface->width;
bbox.p2.y = surface->height;
- status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE);
+ status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE, -1);
if (unlikely (status))
return status;
@@ -8115,6 +8245,7 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_add_source_surface (surface,
NULL,
mask,
+ -1, /* node_surface_index */
op,
source->filter,
FALSE, /* stencil mask */
@@ -8135,7 +8266,9 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface,
return status;
_cairo_output_stream_printf (surface->output, "q\n");
- status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source, extents,
+ status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source,
+ CAIRO_ANALYSIS_SOURCE_NONE,
+ extents,
1.0, /* alpha */
need_smask ? &pdf_source->surface_res : NULL,
FALSE);
@@ -8200,7 +8333,9 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
return status;
_cairo_output_stream_printf (surface->output, "q\n");
- status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, extents, 1.0, NULL, TRUE);
+ status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask,
+ CAIRO_ANALYSIS_SOURCE_NONE,
+ extents, 1.0, NULL, TRUE);
if (unlikely (status))
return status;
@@ -8282,6 +8417,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
status = _cairo_pdf_surface_paint_pattern (surface,
op,
source,
+ CAIRO_ANALYSIS_SOURCE_PAINT,
&extents.bounded,
1.0, /* alpha */
FALSE); /* mask */
@@ -8296,6 +8432,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
+ CAIRO_ANALYSIS_SOURCE_PAINT,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -8467,6 +8604,7 @@ _cairo_pdf_surface_mask (void *abstract_surface,
status = _cairo_pdf_surface_paint_pattern (surface,
op,
source,
+ CAIRO_ANALYSIS_SOURCE_MASK,
&extents.bounded,
alpha,
FALSE); /* mask */
@@ -8596,6 +8734,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
+ CAIRO_ANALYSIS_SOURCE_STROKE,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -8754,6 +8893,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
status = _cairo_pdf_surface_paint_pattern (surface,
op,
source,
+ CAIRO_ANALYSIS_SOURCE_FILL,
&extents.bounded,
1.0, /* alpha */
FALSE); /* mask */
@@ -8768,6 +8908,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
+ CAIRO_ANALYSIS_SOURCE_FILL,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -8947,6 +9088,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
fill_op,
+ CAIRO_ANALYSIS_SOURCE_FILL,
&extents.bounded,
&fill_pattern_res,
&gstate_res);
@@ -8960,6 +9102,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
status = _cairo_pdf_surface_add_pdf_pattern (surface,
stroke_source,
stroke_op,
+ CAIRO_ANALYSIS_SOURCE_STROKE,
&extents.bounded,
&stroke_pattern_res,
&gstate_res);
@@ -9038,6 +9181,10 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
if (unlikely (status))
return status;
+ status = _cairo_pdf_interchange_add_content (surface);
+ if (unlikely (status))
+ return status;
+
status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
if (unlikely (status))
return status;
@@ -9063,6 +9210,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
+ CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -9191,9 +9339,10 @@ _cairo_pdf_surface_tag (void *abstract_surface,
cairo_bool_t begin,
const char *tag_name,
const char *attributes)
+
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_int_status_t status = 0;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
if (begin)
status = _cairo_pdf_interchange_tag_begin (surface, tag_name, attributes);
@@ -9203,6 +9352,16 @@ _cairo_pdf_surface_tag (void *abstract_surface,
return status;
}
+static cairo_int_status_t
+_cairo_pdf_surface_command_id (void *abstract_surface,
+ unsigned int recording_id,
+ unsigned int command_id)
+{
+ cairo_pdf_surface_t *surface = abstract_surface;
+
+ return _cairo_pdf_interchange_command_id (surface, recording_id, command_id);
+}
+
/* The Type 3 font subset support will the embed the
* CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE image if vector operations
* are not supported. The only case we don't currently handle is if a
@@ -9266,6 +9425,33 @@ _cairo_pdf_surface_supports_color_glyph (void *abstract_surface
}
static cairo_int_status_t
+_cairo_pdf_surface_analyze_recording_surface(void *abstract_surface,
+ const cairo_surface_pattern_t *recording_surface_pattern,
+ unsigned int region_id,
+ cairo_analysis_source_t source_type,
+ cairo_bool_t begin)
+{
+ cairo_pdf_surface_t *surface = abstract_surface;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
+
+ if (begin) {
+ status = _cairo_pdf_interchange_recording_source_surface_begin (
+ surface,
+ recording_surface_pattern,
+ region_id,
+ source_type);
+ } else {
+ status = _cairo_pdf_interchange_recording_source_surface_end (
+ surface,
+ recording_surface_pattern,
+ region_id,
+ source_type);
+ }
+
+ return status;
+}
+
+static cairo_int_status_t
_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
cairo_paginated_mode_t paginated_mode)
{
@@ -9273,6 +9459,7 @@ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
cairo_int_status_t status;
surface->paginated_mode = paginated_mode;
+
status = _cairo_pdf_interchange_begin_page_content (surface);
if (unlikely (status))
return status;
@@ -9324,6 +9511,8 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_get_supported_mime_types,
_cairo_pdf_surface_tag,
_cairo_pdf_surface_supports_color_glyph,
+ _cairo_pdf_surface_analyze_recording_surface,
+ _cairo_pdf_surface_command_id,
};
static const cairo_paginated_surface_backend_t