From: Adrian Johnson <ajohnson@redneon.com>
authorAdrian Johnson <ajohnson@redneon.com>
Fri, 21 Sep 2012 15:19:01 +1200
changeset 108468 74493ca34d5ec9afe6680e9dbdc4c3d027857376
parent 108467 1b9a99a17afbd93f63df8c57918e813a1aa2e4c5
child 108469 93b39d0f7d175aac17861bb33a5ac7b2119534b1
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
bugs691061
milestone18.0a1
From: Adrian Johnson <ajohnson@redneon.com> Bug 691061 - Don't use patterns with padded images. r=jmuizelaar
gfx/cairo/cairo/src/cairo-pdf-surface.c
--- a/gfx/cairo/cairo/src/cairo-pdf-surface.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c
@@ -1759,16 +1759,101 @@ static cairo_int_status_t
 }
 
 static cairo_bool_t
 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
 {
     return TRUE;
 }
 
+static cairo_status_t
+_cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t          *surface,
+					     cairo_surface_pattern_t      *source,
+					     const cairo_rectangle_int_t  *extents,
+					     cairo_pdf_resource_t         *surface_res,
+					     int                          *width,
+					     int                          *height,
+					     int                          *origin_x,
+					     int                          *origin_y)
+{
+    cairo_image_surface_t *image;
+    cairo_surface_t *pad_image;
+    void *image_extra;
+    cairo_int_status_t status;
+    int x = 0;
+    int y = 0;
+    int w, h;
+    cairo_rectangle_int_t extents2;
+    cairo_box_t box;
+    cairo_rectangle_int_t rect;
+    cairo_surface_pattern_t pad_pattern;
+
+    status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra);
+    if (unlikely (status))
+        return status;
+
+    pad_image = &image->base;
+
+    /* get the operation extents in pattern space */
+    _cairo_box_from_rectangle (&box, extents);
+    _cairo_matrix_transform_bounding_box_fixed (&source->base.matrix, &box, NULL);
+    _cairo_box_round_to_rectangle (&box, &rect);
+
+    /* Check if image needs padding to fill extents */
+    w = image->width;
+    h = image->height;
+    if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
+	_cairo_fixed_integer_ceil(box.p1.y) < 0 ||
+	_cairo_fixed_integer_floor(box.p2.y) > w ||
+	_cairo_fixed_integer_floor(box.p2.y) > h)
+    {
+	x = -rect.x;
+	y = -rect.y;
+	pad_image = _cairo_image_surface_create_with_content (source->surface->content,
+							      rect.width,
+							      rect.height);
+	if (pad_image->status) {
+	    status = pad_image->status;
+	    goto BAIL;
+	}
+
+	_cairo_pattern_init_for_surface (&pad_pattern, &image->base);
+	cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
+	pad_pattern.base.extend = CAIRO_EXTEND_PAD;
+	status = _cairo_surface_paint (pad_image,
+				       CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
+				       NULL);
+        _cairo_pattern_fini (&pad_pattern.base);
+        if (unlikely (status))
+            goto BAIL;
+    }
+
+    status = _cairo_pdf_surface_add_source_surface (surface,
+						    pad_image,
+						    source->base.filter,
+						    surface_res,
+						    &w,
+						    &h);
+    if (unlikely (status))
+        goto BAIL;
+
+    *width = ((cairo_image_surface_t *)pad_image)->width;
+    *height = ((cairo_image_surface_t *)pad_image)->height;
+    *origin_x = x;
+    *origin_y = y;
+
+BAIL:
+    if (pad_image != &image->base)
+        cairo_surface_destroy (pad_image);
+
+    _cairo_surface_release_source_image (source->surface, image, image_extra);
+
+    return status;
+}
+
 /* Emit alpha channel from the image into the given data, providing
  * an id that can be used to reference the resulting SMask object.
  *
  * In the case that the alpha channel happens to be all opaque, then
  * no SMask object will be emitted and *id_ret will be set to 0.
  */
 static cairo_status_t
 _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
@@ -2114,116 +2199,16 @@ static cairo_status_t
 
 BAIL:
     _cairo_surface_release_source_image (source, image, image_extra);
 
     return status;
 }
 
 static cairo_status_t
-_cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t     *surface,
-					      cairo_pdf_pattern_t     *pdf_pattern,
-					      cairo_pdf_resource_t    *resource,
-					      int                     *width,
-					      int                     *height,
-					      int                     *origin_x,
-					      int                     *origin_y)
-{
-    cairo_image_surface_t *image;
-    cairo_surface_t *pad_image;
-    void *image_extra;
-    cairo_status_t status;
-    cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
-    int x = 0;
-    int y = 0;
-    cairo_bool_t interpolate;
-
-    status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
-    if (unlikely (status))
-        return status;
-
-    pad_image = &image->base;
-    if (pattern->base.extend == CAIRO_EXTEND_PAD) {
-        cairo_box_t box;
-        cairo_rectangle_int_t rect;
-        cairo_surface_pattern_t pad_pattern;
-
-        /* get the operation extents in pattern space */
-        _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
-        _cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
-        _cairo_box_round_to_rectangle (&box, &rect);
-        x = -rect.x;
-        y = -rect.y;
-
-        pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
-                                                              rect.width,
-                                                              rect.height);
-        if (pad_image->status) {
-            status = pad_image->status;
-            goto BAIL;
-        }
-
-        _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
-        cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
-        pad_pattern.base.extend = CAIRO_EXTEND_PAD;
-        status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
-                                           &pad_pattern.base,
-                                           NULL,
-                                           pad_image,
-                                           0, 0,
-                                           0, 0,
-                                           0, 0,
-                                           rect.width,
-                                           rect.height,
-					   NULL);
-        _cairo_pattern_fini (&pad_pattern.base);
-        if (unlikely (status))
-            goto BAIL;
-    }
-
-    switch (pdf_pattern->pattern->filter) {
-    case CAIRO_FILTER_GOOD:
-    case CAIRO_FILTER_BEST:
-    case CAIRO_FILTER_BILINEAR:
-	interpolate = TRUE;
-	break;
-    case CAIRO_FILTER_FAST:
-    case CAIRO_FILTER_NEAREST:
-    case CAIRO_FILTER_GAUSSIAN:
-	interpolate = FALSE;
-	break;
-    }
-
-    *resource = _cairo_pdf_surface_new_object (surface);
-    if (resource->id == 0) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto BAIL;
-    }
-
-    status = _cairo_pdf_surface_emit_image (surface, (cairo_image_surface_t *)pad_image,
-                                            resource, interpolate);
-    if (unlikely (status))
-        goto BAIL;
-
-    *width = ((cairo_image_surface_t *)pad_image)->width;
-    *height = ((cairo_image_surface_t *)pad_image)->height;
-    *origin_x = x;
-    *origin_y = y;
-
-BAIL:
-    if (pad_image != &image->base)
-        cairo_surface_destroy (pad_image);
-
-    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
-
-    return status;
-}
-
-
-static cairo_status_t
 _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t  *surface,
 					   cairo_surface_t      *recording_surface,
 					   cairo_pdf_resource_t  resource)
 {
     double old_width, old_height;
     cairo_paginated_mode_t old_paginated_mode;
     cairo_rectangle_int_t recording_extents;
     cairo_bool_t is_bounded;
@@ -2377,23 +2362,24 @@ static cairo_status_t
     int origin_x = 0; /* squelch bogus compiler warning */
     int origin_y = 0; /* squelch bogus compiler warning */
     int bbox_x, bbox_y;
     char draw_surface[200];
 
     if (pattern->base.extend == CAIRO_EXTEND_PAD &&
 	pattern->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
     {
-	status = _cairo_pdf_surface_emit_padded_image_surface (surface,
-							       pdf_pattern,
-							       &pattern_resource,
-							       &pattern_width,
-							       &pattern_height,
-							       &origin_x,
-							       &origin_y);
+	status = _cairo_pdf_surface_add_padded_image_surface (surface,
+							      pattern,
+							      &pdf_pattern->extents,
+							      &pattern_resource,
+							      &pattern_width,
+							      &pattern_height,
+							      &origin_x,
+							      &origin_y);
     }
     else
     {
 	status = _cairo_pdf_surface_add_source_surface (surface,
 							pattern->surface,
 							pdf_pattern->pattern->filter,
 							&pattern_resource,
 							&pattern_width,
@@ -3351,40 +3337,57 @@ static cairo_status_t
 					  old_width,
 					  old_height);
 
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t     *surface,
-					  cairo_surface_pattern_t *source)
+					  cairo_surface_pattern_t *source,
+					  const cairo_rectangle_int_t  *extents)
 {
     cairo_pdf_resource_t surface_res;
     int width, height;
     cairo_matrix_t cairo_p2d, pdf_p2d;
     cairo_status_t status;
     int alpha;
-
-    status = _cairo_pdf_surface_add_source_surface (surface,
-						    source->surface,
-						    source->base.filter,
-						    &surface_res,
-						    &width,
-						    &height);
+    int origin_x = 0;
+    int origin_y = 0;
+
+    if (source->base.extend == CAIRO_EXTEND_PAD &&
+	source->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
+    {
+	status = _cairo_pdf_surface_add_padded_image_surface (surface,
+							      source,
+							      extents,
+							      &surface_res,
+							      &width,
+							      &height,
+							      &origin_x,
+							      &origin_y);
+    } else {
+	status = _cairo_pdf_surface_add_source_surface (surface,
+							source->surface,
+							source->base.filter,
+							&surface_res,
+							&width,
+						 	&height);
+    }
     if (unlikely (status))
 	return status;
 
     cairo_p2d = source->base.matrix;
     status = cairo_matrix_invert (&cairo_p2d);
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
     assert (status == CAIRO_STATUS_SUCCESS);
 
     pdf_p2d = surface->cairo_to_pdf;
     cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
+    cairo_matrix_translate (&pdf_p2d, -origin_x, -origin_y);
     cairo_matrix_translate (&pdf_p2d, 0.0, height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
     if (source->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
 	cairo_matrix_scale (&pdf_p2d, width, height);
 
     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
     if (unlikely (status))
 	return status;
@@ -5453,17 +5456,18 @@ static cairo_int_status_t
     if (unlikely (status))
 	return status;
 
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
 	source->extend == CAIRO_EXTEND_NONE)
     {
 	_cairo_output_stream_printf (surface->output, "q\n");
 	status = _cairo_pdf_surface_paint_surface_pattern (surface,
-							   (cairo_surface_pattern_t *) source);
+							   (cairo_surface_pattern_t *) source,
+							   &extents.bounded);
 	if (unlikely (status))
 	    return status;
 
 	_cairo_output_stream_printf (surface->output, "Q\n");
 	return _cairo_output_stream_get_status (surface->output);
     }
 
     pattern_res.id = 0;
@@ -5824,31 +5828,33 @@ static cairo_int_status_t
     if (unlikely (status))
 	return status;
 
     status = _cairo_pdf_surface_select_operator (surface, op);
     if (unlikely (status))
 	return status;
 
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
-	source->extend == CAIRO_EXTEND_NONE)
+	(source->extend == CAIRO_EXTEND_NONE ||
+	 source->extend == CAIRO_EXTEND_PAD))
     {
 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 	if (unlikely (status))
 	    return status;
 
 	_cairo_output_stream_printf (surface->output, "q\n");
 	status =  _cairo_pdf_operators_clip (&surface->pdf_operators,
 					     path,
 					     fill_rule);
 	if (unlikely (status))
 	    return status;
 
 	status = _cairo_pdf_surface_paint_surface_pattern (surface,
-							   (cairo_surface_pattern_t *) source);
+							   (cairo_surface_pattern_t *) source,
+							   &extents.bounded);
 	if (unlikely (status))
 	    return status;
 
 	_cairo_output_stream_printf (surface->output, "Q\n");
 	return _cairo_output_stream_get_status (surface->output);
     }
 
     pattern_res.id = 0;