diff options
Diffstat (limited to 'src/cairo-pdf-surface.c')
-rw-r--r-- | src/cairo-pdf-surface.c | 441 |
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 |