From d5cb45013bf10d97657cea105683bf5ccb21c2d7 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 9 Nov 2017 20:52:36 +1030 Subject: [PATCH] pdf: fix mime-unique-id jpeg attached to recording test - Restructure the emit_surface code so that mime types are checked first. - Add a test parameter to emit_surface to test if the surface will be emitted as an image or recording instead checking the surface type as the attached mime may override this. - Mark surface as not clear when mime is attached to avoid optimizing away "clear" surfaces that have mime attached. - Include entire surface in analysis if mime attached (also fixes bug with calculating the extents CONTENT_COLOR surfaces) --- src/cairo-analysis-surface.c | 172 +++++++++++++++------------- src/cairo-pdf-surface.c | 211 ++++++++++++++++++++++++----------- src/cairo-surface.c | 42 +++++++ src/cairoint.h | 3 + test/mime-unique-id.c | 4 +- 5 files changed, 287 insertions(+), 145 deletions(-) diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c index a968f4015..c07e068f9 100644 --- a/src/cairo-analysis-surface.c +++ b/src/cairo-analysis-surface.c @@ -137,81 +137,6 @@ detach_proxy (cairo_surface_t *proxy) cairo_surface_destroy (proxy); } -static cairo_int_status_t -_analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, - const cairo_pattern_t *pattern, - cairo_rectangle_int_t *extents) -{ - const cairo_surface_pattern_t *surface_pattern; - cairo_analysis_surface_t *tmp; - cairo_surface_t *source, *proxy; - cairo_matrix_t p2d; - cairo_status_t status, analysis_status; - cairo_bool_t surface_is_unbounded; - cairo_bool_t unused; - - assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); - surface_pattern = (const cairo_surface_pattern_t *) pattern; - assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING); - source = surface_pattern->surface; - - proxy = _cairo_surface_has_snapshot (source, &proxy_backend); - if (proxy != NULL) { - /* nothing untoward found so far */ - return CAIRO_STATUS_SUCCESS; - } - - tmp = (cairo_analysis_surface_t *) - _cairo_analysis_surface_create (surface->target); - if (unlikely (tmp->base.status)) - return tmp->base.status; - proxy = attach_proxy (source, &tmp->base); - - p2d = pattern->matrix; - status = cairo_matrix_invert (&p2d); - assert (status == CAIRO_STATUS_SUCCESS); - _cairo_analysis_surface_set_ctm (&tmp->base, &p2d); - - source = _cairo_surface_get_source (source, NULL); - surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT - || pattern->extend == CAIRO_EXTEND_REFLECT); - status = _cairo_recording_surface_replay_and_create_regions (source, - &pattern->matrix, - &tmp->base, - surface_is_unbounded); - if (tmp->has_supported) { - surface->has_supported = TRUE; - unused = cairo_region_union (&surface->supported_region, &tmp->supported_region); - } - - if (tmp->has_unsupported) { - surface->has_unsupported = TRUE; - unused = cairo_region_union (&surface->fallback_region, &tmp->fallback_region); - } - - analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS; - - if (pattern->extend != CAIRO_EXTEND_NONE) { - _cairo_unbounded_rectangle_init (extents); - } else if (source->content & CAIRO_CONTENT_ALPHA) { - status = cairo_matrix_invert (&tmp->ctm); - _cairo_matrix_transform_bounding_box_fixed (&tmp->ctm, - &tmp->page_bbox, NULL); - _cairo_box_round_to_rectangle (&tmp->page_bbox, extents); - } else { - /* black background fills entire extents */ - _cairo_surface_get_extents (source, extents); - } - - detach_proxy (proxy); - cairo_surface_destroy (&tmp->base); - - if (unlikely (status)) - return status; - - return analysis_status; -} - static cairo_int_status_t _add_operation (cairo_analysis_surface_t *surface, cairo_rectangle_int_t *rect, @@ -329,6 +254,103 @@ _add_operation (cairo_analysis_surface_t *surface, return status; } +static cairo_int_status_t +_analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, + const cairo_pattern_t *pattern, + cairo_rectangle_int_t *extents) +{ + const cairo_surface_pattern_t *surface_pattern; + cairo_analysis_surface_t *tmp; + cairo_surface_t *source, *proxy; + cairo_matrix_t p2d; + cairo_int_status_t status, analysis_status; + cairo_bool_t surface_is_unbounded; + cairo_bool_t unused; + + assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); + surface_pattern = (const cairo_surface_pattern_t *) pattern; + assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING); + source = surface_pattern->surface; + + proxy = _cairo_surface_has_snapshot (source, &proxy_backend); + if (proxy != NULL) { + /* nothing untoward found so far */ + return CAIRO_STATUS_SUCCESS; + } + + tmp = (cairo_analysis_surface_t *) + _cairo_analysis_surface_create (surface->target); + if (unlikely (tmp->base.status)) { + status =tmp->base.status; + goto cleanup1; + } + proxy = attach_proxy (source, &tmp->base); + + p2d = pattern->matrix; + status = cairo_matrix_invert (&p2d); + assert (status == CAIRO_INT_STATUS_SUCCESS); + _cairo_analysis_surface_set_ctm (&tmp->base, &p2d); + + + source = _cairo_surface_get_source (source, NULL); + surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT + || pattern->extend == CAIRO_EXTEND_REFLECT); + status = _cairo_recording_surface_replay_and_create_regions (source, + &pattern->matrix, + &tmp->base, + surface_is_unbounded); + if (unlikely (status)) + goto cleanup2; + + /* black background or mime data fills entire extents */ + if (!(source->content & CAIRO_CONTENT_ALPHA) || _cairo_surface_has_mime_image (source)) { + cairo_rectangle_int_t rect; + + if (_cairo_surface_get_extents (source, &rect)) { + cairo_box_t bbox; + + _cairo_box_from_rectangle (&bbox, &rect); + _cairo_matrix_transform_bounding_box_fixed (&p2d, &bbox, NULL); + _cairo_box_round_to_rectangle (&bbox, &rect); + status = _add_operation (tmp, &rect, CAIRO_INT_STATUS_SUCCESS); + if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) + status = CAIRO_INT_STATUS_SUCCESS; + if (unlikely (status)) + goto cleanup2; + } + } + + if (tmp->has_supported) { + surface->has_supported = TRUE; + unused = cairo_region_union (&surface->supported_region, &tmp->supported_region); + } + + if (tmp->has_unsupported) { + surface->has_unsupported = TRUE; + unused = cairo_region_union (&surface->fallback_region, &tmp->fallback_region); + } + + analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS; + if (pattern->extend != CAIRO_EXTEND_NONE) { + _cairo_unbounded_rectangle_init (extents); + } else { + status = cairo_matrix_invert (&tmp->ctm); + _cairo_matrix_transform_bounding_box_fixed (&tmp->ctm, + &tmp->page_bbox, NULL); + _cairo_box_round_to_rectangle (&tmp->page_bbox, extents); + } + + cleanup2: + detach_proxy (proxy); + cleanup1: + cairo_surface_destroy (&tmp->base); + + if (unlikely (status)) + return status; + + return analysis_status; +} + static cairo_status_t _cairo_analysis_surface_finish (void *abstract_surface) { diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index aaec50457..07f9c308d 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -267,6 +267,12 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface); +static cairo_int_status_t +_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface, + cairo_pdf_source_surface_t *source, + cairo_bool_t test, + cairo_bool_t *is_image); + static cairo_int_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface); @@ -1646,6 +1652,11 @@ _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)) @@ -2890,7 +2901,8 @@ _cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface, cairo_surface_t *source, - cairo_pdf_source_surface_entry_t *surface_entry) + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { cairo_int_status_t status; const unsigned char *mime_data; @@ -2913,6 +2925,10 @@ _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface, if (status) return status; + /* At this point we know emitting jbig2 will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, &global_id, &global_id_length); if (global_id && global_id_length > 0) { @@ -2998,7 +3014,8 @@ _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface, cairo_surface_t *source, - cairo_pdf_source_surface_entry_t *surface_entry) + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { cairo_int_status_t status; const unsigned char *mime_data; @@ -3029,6 +3046,10 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface, else smask_buf[0] = 0; + /* At this point we know emitting jpx will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + if (surface_entry->stencil_mask) { status = _cairo_pdf_surface_open_stream (surface, &surface_entry->surface_res, @@ -3073,7 +3094,8 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface, cairo_surface_t *source, - cairo_pdf_source_surface_entry_t *surface_entry) + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { cairo_int_status_t status; const unsigned char *mime_data; @@ -3113,6 +3135,10 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; } + /* At this point we know emitting jpeg will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + if (surface_entry->smask_res.id) snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id); else @@ -3168,7 +3194,8 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_ccitt_image (cairo_pdf_surface_t *surface, cairo_surface_t *source, - cairo_pdf_source_surface_entry_t *surface_entry) + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { cairo_status_t status; const unsigned char *ccitt_data; @@ -3203,6 +3230,10 @@ _cairo_pdf_surface_emit_ccitt_image (cairo_pdf_surface_t *surface, free (params); + /* At this point we know emitting jbig2 will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + p = buf; *p = 0; end = buf + sizeof(buf) - 1; @@ -3272,54 +3303,6 @@ _cairo_pdf_surface_emit_ccitt_image (cairo_pdf_surface_t *surface, return status; } -static cairo_int_status_t -_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface, - cairo_pdf_source_surface_t *source) -{ - cairo_image_surface_t *image; - void *image_extra; - cairo_int_status_t status; - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - status = _cairo_pdf_surface_emit_jbig2_image (surface, source->surface, source->hash_entry); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_pdf_surface_emit_jpx_image (surface, source->surface, source->hash_entry); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_pdf_surface_emit_jpeg_image (surface, source->surface, source->hash_entry); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_pdf_surface_emit_ccitt_image (surface, source->surface, source->hash_entry); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra); - } else { - status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source->raster_pattern, - &image, &image_extra); - } - if (unlikely (status)) - return status; - - status = _cairo_pdf_surface_emit_image (surface, - image, - source->hash_entry); - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) - _cairo_surface_release_source_image (source->surface, image, image_extra); - else - _cairo_pdf_surface_release_source_image_from_pattern (surface, source->raster_pattern, - image, image_extra); - - return status; -} - static cairo_int_status_t _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, cairo_pdf_source_surface_t *pdf_source) @@ -3441,15 +3424,107 @@ err: return status; } +/** + * _cairo_pdf_surface_emit_surface: + * @surface: [in] the pdf surface + * @source: [in] #cairo_pdf_source_surface_t containing the surface to write + * @test: [in] if true, test what type of surface will be emitted. + * @is_image: [out] if @test is true, returns TRUE if the surface will be emitted + * as an Image XObject. + * + * If @test is FALSE, emit @src_surface as an XObject. + * If @test is TRUE, don't emit anything. Set @is_image based on the output that would be emitted. + **/ static cairo_int_status_t _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface, - cairo_pdf_source_surface_t *src_surface) + cairo_pdf_source_surface_t *source, + cairo_bool_t test, + cairo_bool_t *is_image) { - if (src_surface->type == CAIRO_PATTERN_TYPE_SURFACE && - src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING) - return _cairo_pdf_surface_emit_recording_surface (surface, src_surface); + cairo_image_surface_t *image; + void *image_extra; + cairo_int_status_t status; - return _cairo_pdf_surface_emit_image_surface (surface, src_surface); + /* Try all the supported mime types and recording type, falling through + * each option if unsupported */ + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + status = _cairo_pdf_surface_emit_jbig2_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + status = _cairo_pdf_surface_emit_jpx_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + status = _cairo_pdf_surface_emit_jpeg_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + status = _cairo_pdf_surface_emit_ccitt_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + if (source->surface->type == CAIRO_SURFACE_TYPE_RECORDING) { + if (test) { + *is_image = FALSE; + return CAIRO_INT_STATUS_SUCCESS; + } else { + return _cairo_pdf_surface_emit_recording_surface (surface, source); + } + } + } + + /* The only option left is to emit as an image surface */ + + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra); + } else { + status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, + source->raster_pattern, + &image, + &image_extra); + } + if (unlikely (status)) + return status; + + if (test) { + *is_image = TRUE; + } else { + status = _cairo_pdf_surface_emit_image (surface, + image, + source->hash_entry); + } + + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + _cairo_surface_release_source_image (source->surface, image, image_extra); + } else { + _cairo_pdf_surface_release_source_image_from_pattern (surface, + source->raster_pattern, + image, + image_extra); + } + + return status; } static cairo_int_status_t @@ -3596,8 +3671,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &mat); cairo_matrix_translate (&pdf_p2d, x_offset, y_offset); - if (((cairo_surface_pattern_t *)pattern)->surface->type != CAIRO_SURFACE_TYPE_RECORDING) - { + if (pdf_source->emit_image) { cairo_matrix_translate (&pdf_p2d, 0.0, pdf_source->extents.height); cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); } @@ -3625,18 +3699,18 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, if (unlikely (status)) return status; - if (((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) { - snprintf(draw_surface, - sizeof (draw_surface), - "/x%d Do", - pdf_source->surface_res.id); - } else { + if (pdf_source->emit_image) { snprintf(draw_surface, sizeof (draw_surface), "q %d 0 0 %d 0 0 cm /x%d Do Q", pdf_source->extents.width, pdf_source->extents.height, pdf_source->surface_res.id); + } else { + snprintf(draw_surface, + sizeof (draw_surface), + "/x%d Do", + pdf_source->surface_res.id); } if (extend == CAIRO_EXTEND_REFLECT) { @@ -6729,6 +6803,7 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface cairo_pdf_source_surface_t src_surface; unsigned int pattern_index, group_index, surface_index, doc_surface_index; cairo_int_status_t status; + cairo_bool_t is_image; /* Writing out PDF_MASK groups will cause additional smask groups * to be appended to surface->smask_groups. Additional patterns @@ -6762,7 +6837,7 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) { _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface); - status = _cairo_pdf_surface_emit_surface (surface, &src_surface); + status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE, &is_image); if (unlikely (status)) return status; } @@ -6770,7 +6845,7 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface if (finish) { for (; doc_surface_index < _cairo_array_num_elements (&surface->doc_surfaces); doc_surface_index++) { _cairo_array_copy_element (&surface->doc_surfaces, doc_surface_index, &src_surface); - status = _cairo_pdf_surface_emit_surface (surface, &src_surface); + status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE, &is_image); if (unlikely (status)) return status; } @@ -6915,7 +6990,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) static cairo_int_status_t _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface, - cairo_surface_pattern_t *pattern) + cairo_surface_pattern_t *pattern) { cairo_image_surface_t *image; void *image_extra; diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 6e69faba8..e04c478fb 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -1224,6 +1224,44 @@ _cairo_mime_data_destroy (void *ptr) free (mime_data); } + +static const char *_cairo_surface_image_mime_types[] = { + CAIRO_MIME_TYPE_JPEG, + CAIRO_MIME_TYPE_PNG, + CAIRO_MIME_TYPE_JP2, + CAIRO_MIME_TYPE_JBIG2, + CAIRO_MIME_TYPE_CCITT_FAX, +}; + +cairo_bool_t +_cairo_surface_has_mime_image (cairo_surface_t *surface) +{ + cairo_user_data_slot_t *slots; + int i, j, num_slots; + + /* Prevent reads of the array during teardown */ + if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)) + return FALSE; + + /* The number of mime-types attached to a surface is usually small, + * typically zero. Therefore it is quicker to do a strcmp() against + * each key than it is to intern the string (i.e. compute a hash, + * search the hash table, and do a final strcmp). + */ + num_slots = surface->mime_data.num_elements; + slots = _cairo_array_index (&surface->mime_data, 0); + for (i = 0; i < num_slots; i++) { + if (slots[i].key != NULL) { + for (j = 0; j < ARRAY_LENGTH (_cairo_surface_image_mime_types); j++) { + if (strcmp ((char *) slots[i].key, _cairo_surface_image_mime_types[j]) == 0) + return TRUE; + } + } + } + + return FALSE; +} + /** * CAIRO_MIME_TYPE_CCITT_FAX: * @@ -1405,6 +1443,8 @@ cairo_surface_set_mime_data (cairo_surface_t *surface, return _cairo_surface_set_error (surface, status); } + surface->is_clear = FALSE; + return CAIRO_STATUS_SUCCESS; } slim_hidden_def (cairo_surface_set_mime_data); @@ -1479,6 +1519,8 @@ _cairo_surface_copy_mime_data (cairo_surface_t *dst, _cairo_mime_data_reference, NULL); + dst->is_clear = FALSE; + return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairoint.h b/src/cairoint.h index 6f8303c3c..c44242a6c 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1336,6 +1336,9 @@ _cairo_stroke_style_dash_approximate (const cairo_stroke_style_t *style, /* cairo-surface.c */ +cairo_private cairo_bool_t +_cairo_surface_has_mime_image (cairo_surface_t *surface); + cairo_private cairo_status_t _cairo_surface_copy_mime_data (cairo_surface_t *dst, cairo_surface_t *src); diff --git a/test/mime-unique-id.c b/test/mime-unique-id.c index 78957fc51..1d7babe09 100755 --- a/test/mime-unique-id.c +++ b/test/mime-unique-id.c @@ -72,7 +72,7 @@ * file size due to changes to the PS/PDF surfaces while being small * enough to catch any attempt to embed the surface more than * once. The compressed size of each surface embedded in PDF is: - * - image: 111,952 + * - image: 108,774 * - jpeg: 11,400 * - recording: 17,518 * @@ -81,7 +81,7 @@ */ #define PS2_EXPECTED_SIZE 315362 #define PS3_EXPECTED_SIZE 315362 -#define PDF_EXPECTED_SIZE 142968 +#define PDF_EXPECTED_SIZE 347182 #define SIZE_TOLERANCE 5000 static const char *png_filename = "romedalen.png";