From 87dfd0c16f4fa798c1f72612a2e070fca8547ad2 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 22 Oct 2017 08:45:45 +1030 Subject: [PATCH] Allow mime image to be different size to cairo image Previously it was assumed the mime image size is the same as the cairo image surface size. When using the 1 bpp formats (CCITT, JBIG2), creating a cairo image of the same size will have very large memory requirements and in some case may exceed the pixman image size limits. In these cases it is useful to allow the mime image to have a different resolution to the cairo image and in the PDF/PS output scale the mime image to be the same physical size as the cairo image. In PDF, this is easy as all PDF images are scaled to 1x1 unit and the CTM is used to scale the image to the required size. The PS surface has been changed to also scale images to 1x1 and use the CTM to get the required size. --- src/cairo-pdf-surface.c | 124 ---------------------------------------- src/cairo-ps-surface.c | 29 ++++++++-- 2 files changed, 24 insertions(+), 129 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index cb887119f..fa40bc304 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1402,97 +1402,6 @@ _cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t } } -static cairo_int_status_t -_get_jbig2_image_info (cairo_surface_t *source, - cairo_image_info_t *info) -{ - const unsigned char *mime_data; - unsigned long mime_data_length; - - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2, - &mime_data, &mime_data_length); - if (mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_image_info_get_jbig2_info (info, mime_data, mime_data_length); -} - -static cairo_int_status_t -_get_jpx_image_info (cairo_surface_t *source, - cairo_image_info_t *info) -{ - const unsigned char *mime_data; - unsigned long mime_data_length; - - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2, - &mime_data, &mime_data_length); - if (mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_image_info_get_jpx_info (info, mime_data, mime_data_length); -} - -static cairo_int_status_t -_get_jpeg_image_info (cairo_surface_t *source, - cairo_image_info_t *info) -{ - const unsigned char *mime_data; - unsigned long mime_data_length; - - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG, - &mime_data, &mime_data_length); - if (mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_image_info_get_jpeg_info (info, mime_data, mime_data_length); -} - -static cairo_int_status_t -_get_ccitt_image_info (cairo_surface_t *source, - int *width, - int *height) -{ - cairo_status_t status; - const unsigned char *ccitt_data; - unsigned long ccitt_data_len; - const unsigned char *ccitt_params_string; - unsigned long ccitt_params_string_len; - char *params; - cairo_ccitt_params_t ccitt_params; - - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX, - &ccitt_data, &ccitt_data_len); - if (unlikely (source->status)) - return source->status; - if (ccitt_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, - &ccitt_params_string, &ccitt_params_string_len); - if (unlikely (source->status)) - return source->status; - if (ccitt_params_string == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* ensure params_string is null terminated */ - params = malloc (ccitt_params_string_len + 1); - memcpy (params, ccitt_params_string, ccitt_params_string_len); - params[ccitt_params_string_len] = 0; - status = _cairo_tag_parse_ccitt_params (params, &ccitt_params); - if (unlikely(status)) - return source->status; - - free (params); - - if (ccitt_params.columns <= 0 || ccitt_params.rows <= 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - *width = ccitt_params.columns; - *height = ccitt_params.rows; - - return CAIRO_STATUS_SUCCESS; -} - static cairo_int_status_t _get_source_surface_extents (cairo_surface_t *source, cairo_rectangle_int_t *extents, @@ -1500,8 +1409,6 @@ _get_source_surface_extents (cairo_surface_t *source, cairo_bool_t *subsurface) { cairo_int_status_t status; - cairo_image_info_t info; - int width, height; *bounded = TRUE; *subsurface = FALSE; @@ -1534,37 +1441,6 @@ _get_source_surface_extents (cairo_surface_t *source, return CAIRO_STATUS_SUCCESS; } - extents->x = 0; - extents->y = 0; - - status = _get_jbig2_image_info (source, &info); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - extents->width = info.width; - extents->height = info.height; - return status; - } - - status = _get_jpx_image_info (source, &info); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - extents->width = info.width; - extents->height = info.height; - return status; - } - - status = _get_jpeg_image_info (source, &info); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - extents->width = info.width; - extents->height = info.height; - return status; - } - - status = _get_ccitt_image_info (source, &width, &height); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - extents->width = width; - extents->height = height; - return status; - } - if (! _cairo_surface_get_extents (source, extents)) return CAIRO_INT_STATUS_UNSUPPORTED; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 62b19e4af..905ee2c84 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -2754,7 +2754,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ] def\n" " end\n" " /MaskDict 8 dict def\n" " MaskDict begin\n" @@ -2764,14 +2764,18 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, " /Interpolate %s def\n" " /BitsPerComponent 1 def\n" " /Decode [ 1 0 ] def\n" - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ] def\n" " end\n" "end\n" "image\n", + ps_image->width, + -ps_image->height, ps_image->height, ps_image->width, ps_image->height, interpolate, + ps_image->width, + -ps_image->height, ps_image->height); } else { if (!stencil_mask) { @@ -2808,9 +2812,11 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ] def\n" "end\n" "%s%s\n", + ps_image->width, + -ps_image->height, ps_image->height, surface->use_string_datasource ? "" : "cairo_", stencil_mask ? "imagemask" : "image"); @@ -2936,9 +2942,11 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ] def\n" "end\n" "%simage\n", + info.width, + -info.height, info.height, surface->use_string_datasource ? "" : "cairo_"); @@ -3077,9 +3085,11 @@ _cairo_ps_surface_emit_ccitt_image (cairo_ps_surface_t *surface, " >> /CCITTFaxDecode filter\n"); _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ]\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ]\n" ">>\n" "%s%s\n", + ccitt_params.columns, + -ccitt_params.rows, ccitt_params.rows, surface->use_string_datasource ? "" : "cairo_", stencil_mask ? "imagemask" : "image"); @@ -3407,6 +3417,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, { cairo_matrix_translate (&ps_p2d, 0.0, src_surface_extents.height); cairo_matrix_scale (&ps_p2d, 1.0, -1.0); + cairo_matrix_scale (&ps_p2d, src_surface_extents.width, src_surface_extents.height); } if (! _cairo_matrix_is_identity (&ps_p2d)) { @@ -3545,6 +3556,14 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, pattern_extents.x, pattern_extents.y, pattern_extents.width, pattern_extents.height); + + if (((cairo_surface_pattern_t *)pattern)->surface->type != CAIRO_SURFACE_TYPE_RECORDING) + { + _cairo_output_stream_printf (surface->stream, + "[ %d 0 0 %d 0 0 ] concat\n", + pattern_extents.width, pattern_extents.height); + } + old_use_string_datasource = surface->use_string_datasource; surface->use_string_datasource = TRUE; if (op == CAIRO_OPERATOR_SOURCE) {