[cairo-commit] 8 commits - src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h src/cairo-ps-surface.c src/cairo-truetype-subset.c src/cairo-type1-subset.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Tue Dec 6 02:20:58 PST 2011


 src/cairo-pdf-surface-private.h |    2 
 src/cairo-pdf-surface.c         |  554 +++++++++++++++++++++++++++-------------
 src/cairo-ps-surface.c          |   85 ++++--
 src/cairo-truetype-subset.c     |    2 
 src/cairo-type1-subset.c        |    8 
 5 files changed, 449 insertions(+), 202 deletions(-)

New commits:
commit a8cbb007844b04937b36cc387d5ad29b5fc70119
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:47:14 2011 +1030

    pdf: avoid using pdf patterns to paint/fill translucent linear/radial gradients

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 5d3e3af..d7108d1 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3238,11 +3238,27 @@ _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t      *surface,
 
 static cairo_status_t
 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
+					   cairo_pdf_pattern_t  *pdf_pattern,
 					   cairo_pdf_resource_t  gstate_resource,
 					   cairo_pdf_resource_t  gradient_mask)
 {
     cairo_pdf_resource_t smask_resource;
     cairo_status_t status;
+    char buf[100];
+
+    if (pdf_pattern->is_shading) {
+	snprintf(buf, sizeof(buf),
+		 "         /Shading\n"
+		 "            << /sh%d %d 0 R >>\n",
+		 gradient_mask.id,
+		 gradient_mask.id);
+    } else {
+	snprintf(buf, sizeof(buf),
+		 "         /Pattern\n"
+		 "            << /p%d %d 0 R >>\n",
+		 gradient_mask.id,
+		 gradient_mask.id);
+    }
 
     status = _cairo_pdf_surface_open_stream (surface,
 					     NULL,
@@ -3255,8 +3271,7 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
 					     "      << /ExtGState\n"
 					     "            << /a0 << /ca 1 /CA 1 >>"
 					     "      >>\n"
-					     "         /Pattern\n"
-					     "            << /p%d %d 0 R >>\n"
+					     "%s"
 					     "      >>\n"
 					     "   /Group\n"
 					     "      << /Type /Group\n"
@@ -3265,24 +3280,29 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
 					     "      >>\n",
 					     surface->width,
 					     surface->height,
-					     gradient_mask.id,
-					     gradient_mask.id);
+					     buf);
     if (unlikely (status))
 	return status;
 
-    _cairo_output_stream_printf (surface->output,
-                                 "q\n"
-                                 "/a0 gs\n"
-                                 "/Pattern cs /p%d scn\n"
-                                 "0 0 %f %f re\n"
-                                 "f\n"
-                                 "Q\n",
-                                 gradient_mask.id,
-                                 surface->width,
-                                 surface->height);
-
-     status = _cairo_pdf_surface_close_stream (surface);
-     if (unlikely (status))
+    if (pdf_pattern->is_shading) {
+	_cairo_output_stream_printf (surface->output,
+				     "/a0 gs /sh%d sh\n",
+				     gradient_mask.id);
+    } else {
+	_cairo_output_stream_printf (surface->output,
+				     "q\n"
+				     "/a0 gs\n"
+				     "/Pattern cs /p%d scn\n"
+				     "0 0 %f %f re\n"
+				     "f\n"
+				     "Q\n",
+				     gradient_mask.id,
+				     surface->width,
+				     surface->height);
+    }
+
+    status = _cairo_pdf_surface_close_stream (surface);
+    if (unlikely (status))
 	return status;
 
     smask_resource = _cairo_pdf_surface_new_object (surface);
@@ -3522,11 +3542,8 @@ _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t    *surface,
 					    &pat_to_pdf, &start, &end, domain,
 					    "/DeviceGray", alpha_function);
 
-        status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
-        if (unlikely (status))
-            return status;
-
 	status = cairo_pdf_surface_emit_transparency_group (surface,
+							    pdf_pattern,
 						            pdf_pattern->gstate_res,
 							    mask_resource);
 	if (unlikely (status))
@@ -3671,6 +3688,7 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t    *surface,
 				     res.id);
 
 	status = cairo_pdf_surface_emit_transparency_group (surface,
+							    pdf_pattern,
 						            pdf_pattern->gstate_res,
 							    mask_resource);
 	if (unlikely (status))
@@ -3825,8 +3843,6 @@ _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t         *surface,
     if (unlikely (status))
 	return status;
 
-    assert (gstate_res.id == 0);
-
     pat_to_pdf = source->matrix;
     status = cairo_matrix_invert (&pat_to_pdf);
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
@@ -3845,19 +3861,29 @@ _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t         *surface,
 				     pat_to_pdf.x0, pat_to_pdf.y0);
     }
 
-    status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
-    if (unlikely (status))
-	return status;
-
     status = _cairo_pdf_surface_add_shading (surface, shading_res);
     if (unlikely (status))
 	return status;
 
+    if (gstate_res.id != 0) {
+	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+	if (unlikely (status))
+	    return status;
 
-    _cairo_output_stream_printf (surface->output,
-				 "/a%d gs /sh%d sh\n",
-				 alpha,
-				 shading_res.id);
+	_cairo_output_stream_printf (surface->output,
+				     "/s%d gs /sh%d sh\n",
+				     gstate_res.id,
+				     shading_res.id);
+    } else {
+	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+	if (unlikely (status))
+	    return status;
+
+	_cairo_output_stream_printf (surface->output,
+				     "/a%d gs /sh%d sh\n",
+				     alpha,
+				     shading_res.id);
+    }
 
     return status;
 }
@@ -3891,8 +3917,6 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t          *surface,
 static cairo_bool_t
 _can_paint_pattern (const cairo_pattern_t *pattern)
 {
-    double min_alpha;
-
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
 	return FALSE;
@@ -3903,8 +3927,7 @@ _can_paint_pattern (const cairo_pattern_t *pattern)
 
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
-	_cairo_pattern_alpha_range (pattern, &min_alpha, NULL);
-	return CAIRO_ALPHA_IS_OPAQUE (min_alpha);
+	return TRUE;
 
     case CAIRO_PATTERN_TYPE_MESH:
 	return FALSE;
commit 79f430e7ada4384390dc03caab2af0ffc1603885
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:46:49 2011 +1030

    pdf: avoid using pdf patterns to paint/fill opaque linear/radial gradients
    
    Patterns are slower and use more memory to print. For painting and
    filling we can use the shading operator to draw gradients.

diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 08620e6..1e174fe 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -60,6 +60,7 @@ typedef struct _cairo_pdf_group_resources {
     cairo_array_t alphas;
     cairo_array_t smasks;
     cairo_array_t patterns;
+    cairo_array_t shadings;
     cairo_array_t xobjects;
     cairo_array_t fonts;
 } cairo_pdf_group_resources_t;
@@ -89,6 +90,7 @@ typedef struct _cairo_pdf_pattern {
     cairo_pattern_t *pattern;
     cairo_pdf_resource_t pattern_res;
     cairo_pdf_resource_t gstate_res;
+    cairo_bool_t is_shading;
 } cairo_pdf_pattern_t;
 
 typedef enum _cairo_pdf_operation {
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index f61638c..5d3e3af 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -715,6 +715,7 @@ _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
     _cairo_array_init (&res->alphas, sizeof (double));
     _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&res->shadings, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
 }
@@ -725,6 +726,7 @@ _cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
     _cairo_array_fini (&res->alphas);
     _cairo_array_fini (&res->smasks);
     _cairo_array_fini (&res->patterns);
+    _cairo_array_fini (&res->shadings);
     _cairo_array_fini (&res->xobjects);
     _cairo_array_fini (&res->fonts);
 }
@@ -740,6 +742,7 @@ _cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
     _cairo_array_truncate (&res->alphas, 0);
     _cairo_array_truncate (&res->smasks, 0);
     _cairo_array_truncate (&res->patterns, 0);
+    _cairo_array_truncate (&res->shadings, 0);
     _cairo_array_truncate (&res->xobjects, 0);
     _cairo_array_truncate (&res->fonts, 0);
 }
@@ -796,6 +799,14 @@ _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t  *surface,
 }
 
 static cairo_status_t
+_cairo_pdf_surface_add_shading (cairo_pdf_surface_t  *surface,
+				cairo_pdf_resource_t  shading)
+{
+    return _cairo_array_append (&(surface->resources.shadings), &shading);
+}
+
+
+static cairo_status_t
 _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t  *surface,
 				cairo_pdf_resource_t  xobject)
 {
@@ -908,7 +919,7 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t         *surface,
 {
     int num_alphas, num_smasks, num_resources, i;
     double alpha;
-    cairo_pdf_resource_t *smask, *pattern, *xobject;
+    cairo_pdf_resource_t *smask, *pattern, *shading, *xobject;
     cairo_pdf_font_t *font;
 
     _cairo_output_stream_printf (surface->output, "<<\n");
@@ -960,6 +971,21 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t         *surface,
 				     " >>\n");
     }
 
+    num_resources = _cairo_array_num_elements (&res->shadings);
+    if (num_resources > 0) {
+	_cairo_output_stream_printf (surface->output,
+				     "   /Shading <<");
+	for (i = 0; i < num_resources; i++) {
+	    shading = _cairo_array_index (&res->shadings, i);
+	    _cairo_output_stream_printf (surface->output,
+					 " /sh%d %d 0 R",
+					 shading->id, shading->id);
+	}
+
+	_cairo_output_stream_printf (surface->output,
+				     " >>\n");
+    }
+
     num_resources = _cairo_array_num_elements (&res->xobjects);
     if (num_resources > 0) {
 	_cairo_output_stream_printf (surface->output,
@@ -1282,15 +1308,18 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
 }
 
 static cairo_status_t
-_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
-				    const cairo_pattern_t	*pattern,
-				    const cairo_rectangle_int_t	*extents,
-				    cairo_pdf_resource_t	*pattern_res,
-				    cairo_pdf_resource_t	*gstate_res)
+_cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t	   *surface,
+					       const cairo_pattern_t	   *pattern,
+					       const cairo_rectangle_int_t *extents,
+					       cairo_bool_t                 is_shading,
+					       cairo_pdf_resource_t	   *pattern_res,
+					       cairo_pdf_resource_t	   *gstate_res)
 {
     cairo_pdf_pattern_t pdf_pattern;
     cairo_status_t status;
 
+    pdf_pattern.is_shading = is_shading;
+
     /* Solid colors are emitted into the content stream */
     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
 	pattern_res->id = 0;
@@ -1363,6 +1392,36 @@ _get_bbox_from_extents (double                       surface_height,
 }
 
 static cairo_status_t
+_cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t		*surface,
+				    const cairo_pattern_t	*pattern,
+				    const cairo_rectangle_int_t	*extents,
+				    cairo_pdf_resource_t	*shading_res,
+				    cairo_pdf_resource_t	*gstate_res)
+{
+    return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
+							  pattern,
+							  extents,
+							  TRUE,
+							  shading_res,
+							  gstate_res);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
+				    const cairo_pattern_t	*pattern,
+				    const cairo_rectangle_int_t	*extents,
+				    cairo_pdf_resource_t	*pattern_res,
+				    cairo_pdf_resource_t	*gstate_res)
+{
+    return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
+							  pattern,
+							  extents,
+							  FALSE,
+							  pattern_res,
+							  gstate_res);
+}
+
+static cairo_status_t
 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
 				cairo_pdf_resource_t    *resource,
 				cairo_bool_t             compressed,
@@ -3270,15 +3329,19 @@ _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t        *surface,
 				    cairo_pdf_resource_t        color_function)
 {
     _cairo_output_stream_printf (surface->output,
-                                 "%d 0 obj\n"
-                                 "<< /Type /Pattern\n"
-                                 "   /PatternType 2\n"
-                                 "   /Matrix [ %f %f %f %f %f %f ]\n"
-                                 "   /Shading\n",
-				 pattern_resource.id,
-                                 pat_to_pdf->xx, pat_to_pdf->yx,
-                                 pat_to_pdf->xy, pat_to_pdf->yy,
-                                 pat_to_pdf->x0, pat_to_pdf->y0);
+                                 "%d 0 obj\n",
+				 pattern_resource.id);
+
+    if (!pdf_pattern->is_shading) {
+	_cairo_output_stream_printf (surface->output,
+				     "<< /Type /Pattern\n"
+				     "   /PatternType 2\n"
+				     "   /Matrix [ %f %f %f %f %f %f ]\n"
+				     "   /Shading\n",
+				     pat_to_pdf->xx, pat_to_pdf->yx,
+				     pat_to_pdf->xy, pat_to_pdf->yy,
+				     pat_to_pdf->x0, pat_to_pdf->y0);
+    }
 
     if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
 	_cairo_output_stream_printf (surface->output,
@@ -3314,10 +3377,14 @@ _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t        *surface,
 
     _cairo_output_stream_printf (surface->output,
 				 "         /Function %d 0 R\n"
-                                 "      >>\n"
-                                 ">>\n"
-                                 "endobj\n",
+                                 "      >>\n",
 				 color_function.id);
+
+    if (!pdf_pattern->is_shading) {
+	_cairo_output_stream_printf (surface->output,
+				     ">>\n"
+				     "endobj\n");
+    }
 }
 
 static cairo_status_t
@@ -3741,6 +3808,114 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t          *surface,
 }
 
 static cairo_status_t
+_cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t         *surface,
+				   const cairo_pattern_t       *source,
+				   const cairo_rectangle_int_t *extents)
+{
+    cairo_pdf_resource_t shading_res, gstate_res;
+    cairo_matrix_t pat_to_pdf;
+    cairo_status_t status;
+    int alpha;
+
+    status = _cairo_pdf_surface_add_pdf_shading (surface, source,
+						 extents,
+						 &shading_res, &gstate_res);
+    if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
+	return CAIRO_STATUS_SUCCESS;
+    if (unlikely (status))
+	return status;
+
+    assert (gstate_res.id == 0);
+
+    pat_to_pdf = source->matrix;
+    status = cairo_matrix_invert (&pat_to_pdf);
+    /* cairo_pattern_set_matrix ensures the matrix is invertible */
+    assert (status == CAIRO_STATUS_SUCCESS);
+    cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
+
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (unlikely (status))
+	return status;
+
+    if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
+	_cairo_output_stream_printf (surface->output,
+				     "%f %f %f %f %f %f cm\n",
+				     pat_to_pdf.xx, pat_to_pdf.yx,
+				     pat_to_pdf.xy, pat_to_pdf.yy,
+				     pat_to_pdf.x0, pat_to_pdf.y0);
+    }
+
+    status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_pdf_surface_add_shading (surface, shading_res);
+    if (unlikely (status))
+	return status;
+
+
+    _cairo_output_stream_printf (surface->output,
+				 "/a%d gs /sh%d sh\n",
+				 alpha,
+				 shading_res.id);
+
+    return status;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t          *surface,
+				  const cairo_pattern_t        *source,
+				  const cairo_rectangle_int_t  *extents,
+				  cairo_bool_t                  mask)
+{
+    switch (source->type) {
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	return _cairo_pdf_surface_paint_surface_pattern (surface,
+							 (cairo_surface_pattern_t *)source,
+							 extents,
+							 mask);
+    case CAIRO_PATTERN_TYPE_LINEAR:
+    case CAIRO_PATTERN_TYPE_RADIAL:
+    case CAIRO_PATTERN_TYPE_MESH:
+	return _cairo_pdf_surface_paint_gradient (surface,
+						  source,
+						  extents);
+
+    case CAIRO_PATTERN_TYPE_SOLID:
+    default:
+	ASSERT_NOT_REACHED;
+	return CAIRO_STATUS_SUCCESS;
+    }
+}
+
+static cairo_bool_t
+_can_paint_pattern (const cairo_pattern_t *pattern)
+{
+    double min_alpha;
+
+    switch (pattern->type) {
+    case CAIRO_PATTERN_TYPE_SOLID:
+	return FALSE;
+
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	return (pattern->extend == CAIRO_EXTEND_NONE ||
+		pattern->extend == CAIRO_EXTEND_PAD);
+
+    case CAIRO_PATTERN_TYPE_LINEAR:
+    case CAIRO_PATTERN_TYPE_RADIAL:
+	_cairo_pattern_alpha_range (pattern, &min_alpha, NULL);
+	return CAIRO_ALPHA_IS_OPAQUE (min_alpha);
+
+    case CAIRO_PATTERN_TYPE_MESH:
+	return FALSE;
+
+    default:
+	ASSERT_NOT_REACHED;
+	return FALSE;
+    }
+}
+
+static cairo_status_t
 _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
 				    cairo_operator_t     op)
 {
@@ -6041,15 +6216,12 @@ _cairo_pdf_surface_paint (void			*abstract_surface,
     if (unlikely (status))
 	goto cleanup;
 
-    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
-	(source->extend == CAIRO_EXTEND_NONE ||
-	 source->extend == CAIRO_EXTEND_PAD))
-    {
+    if (_can_paint_pattern (source)) {
 	_cairo_output_stream_printf (surface->output, "q\n");
-	status = _cairo_pdf_surface_paint_surface_pattern (surface,
-							   (cairo_surface_pattern_t *) source,
-							   &extents.bounded,
-							   FALSE);
+	status = _cairo_pdf_surface_paint_pattern (surface,
+						   source,
+						   &extents.bounded,
+						   FALSE);
 	if (unlikely (status))
 	    goto cleanup;
 
@@ -6458,10 +6630,7 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
     if (unlikely (status))
 	goto cleanup;
 
-    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
-	(source->extend == CAIRO_EXTEND_NONE ||
-	 source->extend == CAIRO_EXTEND_PAD))
-    {
+    if (_can_paint_pattern (source)) {
 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 	if (unlikely (status))
 	    goto cleanup;
@@ -6473,10 +6642,10 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 	if (unlikely (status))
 	    goto cleanup;
 
-	status = _cairo_pdf_surface_paint_surface_pattern (surface,
-							   (cairo_surface_pattern_t *) source,
-							   &extents.bounded,
-							   FALSE);
+	status = _cairo_pdf_surface_paint_pattern (surface,
+						   source,
+						   &extents.bounded,
+						   FALSE);
 	if (unlikely (status))
 	    goto cleanup;
 
commit dee48f0dcadf96e88872894a1cef280905cd255f
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:46:35 2011 +1030

    ps: allow embedding of cmyk jpeg images

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index def9e62..f206adc 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2511,6 +2511,8 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
     const unsigned char *mime_data;
     unsigned long mime_data_length;
     cairo_image_info_t info;
+    const char *colorspace;
+    const char *decode;
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
 				 &mime_data, &mime_data_length);
@@ -2523,8 +2525,22 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
     if (unlikely (status))
 	return status;
 
-    if (info.num_components != 1 && info.num_components != 3)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    switch (info.num_components) {
+	case 1:
+	    colorspace = "/DeviceGray";
+	    decode = "0 1";
+	    break;
+	case 3:
+	    colorspace = "/DeviceRGB";
+	    decode =  "0 1 0 1 0 1";
+	    break;
+	case 4:
+	    colorspace = "/DeviceCMYK";
+	    decode =  "0 1 0 1 0 1 0 1";
+	    break;
+	default:
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     if (surface->use_string_datasource) {
 	/* Emit the image data as a base85-encoded string which will
@@ -2547,18 +2563,18 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
     }
 
     _cairo_output_stream_printf (surface->stream,
-				 "/%s setcolorspace\n"
+				 "%s setcolorspace\n"
 				 "8 dict dup begin\n"
 				 "  /ImageType 1 def\n"
 				 "  /Width %d def\n"
 				 "  /Height %d def\n"
 				 "  /BitsPerComponent %d def\n"
 				 "  /Decode [ %s ] def\n",
-				 info.num_components == 1 ? "DeviceGray" : "DeviceRGB",
+				 colorspace,
 				 info.width,
 				 info.height,
 				 info.bits_per_component,
-                                 info.num_components == 1 ? "0 1" : "0 1 0 1 0 1");
+                                 decode);
 
     if (surface->use_string_datasource) {
 	_cairo_output_stream_printf (surface->stream,
commit 74c0a06105e3d08b057a770e0545849836f6babb
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:46:21 2011 +1030

    pdf: allow embedding of cmyk jpeg images

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 5a54530..f61638c 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2330,6 +2330,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
     const unsigned char *mime_data;
     unsigned long mime_data_length;
     cairo_image_info_t info;
+    const char *colorspace;
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
 				 &mime_data, &mime_data_length);
@@ -2342,8 +2343,19 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
     if (unlikely (status))
 	return status;
 
-    if (info.num_components != 1 && info.num_components != 3)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    switch (info.num_components) {
+	case 1:
+	    colorspace = "/DeviceGray";
+	    break;
+	case 3:
+	    colorspace = "/DeviceRGB";
+	    break;
+	case 4:
+	    colorspace = "/DeviceCMYK";
+	    break;
+	default:
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     status = _cairo_pdf_surface_open_stream (surface,
 					     &res,
@@ -2357,7 +2369,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
 					     "   /Filter /DCTDecode\n",
 					     info.width,
 					     info.height,
-					     info.num_components == 1 ? "/DeviceGray" : "/DeviceRGB",
+					     colorspace,
 					     info.bits_per_component);
     if (unlikely (status))
 	return status;
commit 25e35b46bfd2a71a8cf0484e51351961ad1c82a3
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:45:31 2011 +1030

    ps: avoid padding images if the padding is not required to fill the extents

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 95b3d12..def9e62 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2820,6 +2820,7 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t      *surface,
     cairo_surface_t	   *pad_image;
     int x = 0;
     int y = 0;
+    int w, h;
 
     surface->acquired_image = NULL;
     surface->image = NULL;
@@ -2866,32 +2867,42 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t      *surface,
 	    _cairo_box_from_rectangle (&box, 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_pixman_format (NULL,
-								surface->acquired_image->pixman_format,
-								rect.width, rect.height,
-								0);
-	    if (pad_image->status) {
-		status = pad_image->status;
-		goto BAIL;
-	    }
 
-	    _cairo_pattern_init_for_surface (&pad_pattern, &surface->acquired_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)) {
-		if (pad_image != &surface->acquired_image->base)
-		    cairo_surface_destroy (pad_image);
+	    /* Check if image needs padding to fill extents. */
+	    w = surface->acquired_image->width;
+	    h = surface->acquired_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_pixman_format (NULL,
+								    surface->acquired_image->pixman_format,
+								    rect.width, rect.height,
+								    0);
+		if (pad_image->status) {
+		    status = pad_image->status;
+		    goto BAIL;
+		}
 
-		goto BAIL;
+		_cairo_pattern_init_for_surface (&pad_pattern, &surface->acquired_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)) {
+		    if (pad_image != &surface->acquired_image->base)
+			cairo_surface_destroy (pad_image);
+
+		    goto BAIL;
+		}
 	    }
 	}
 
commit c7ce1b68d5370f6e804a6edbf5be4bca3a5b7c57
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:45:14 2011 +1030

    pdf: don't use patterns with padded images
    
    and avoid padding if the padding is not required to fill the extents.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index f45846c..5a54530 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1875,6 +1875,93 @@ _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,
+						    FALSE,
+						    surface_res,
+						    &w,
+						    &h,
+						    &extents2);
+    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.
  *
@@ -2318,100 +2405,6 @@ BAIL:
 }
 
 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_int_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_paint (pad_image,
-				       CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
-				       NULL);
-        _cairo_pattern_fini (&pad_pattern.base);
-        if (unlikely (status))
-            goto BAIL;
-    }
-
-    switch (pdf_pattern->pattern->filter) {
-    default:
-    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, FALSE);
-    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_pdf_source_surface_t *pdf_source)
 {
@@ -2590,13 +2583,14 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
     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);
 	pattern_extents.x = 0;
 	pattern_extents.y = 0;
 	pattern_extents.width = pattern_width;
@@ -3653,25 +3647,41 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
 }
 
 static cairo_status_t
-_cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t     *surface,
-					  cairo_surface_pattern_t *source,
-					  cairo_bool_t             stencil_mask)
+_cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t          *surface,
+					  cairo_surface_pattern_t      *source,
+					  const cairo_rectangle_int_t  *extents,
+					  cairo_bool_t                  stencil_mask)
 {
     cairo_pdf_resource_t surface_res;
     int width, height;
     cairo_matrix_t cairo_p2d, pdf_p2d;
     cairo_status_t status;
     int alpha;
-    cairo_rectangle_int_t extents;
+    cairo_rectangle_int_t extents2;
+    int origin_x = 0;
+    int origin_y = 0;
 
-    status = _cairo_pdf_surface_add_source_surface (surface,
-						    source->surface,
-						    source->base.filter,
-						    stencil_mask,
-						    &surface_res,
-						    &width,
-						    &height,
-						    &extents);
+    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,
+							stencil_mask,
+							&surface_res,
+							&width,
+							&height,
+							&extents2);
+    }
     if (unlikely (status))
 	return status;
 
@@ -3682,6 +3692,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t     *surface,
 
     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)
@@ -5943,6 +5954,7 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t   *surface,
     _cairo_output_stream_printf (surface->output, "q\n");
     status = _cairo_pdf_surface_paint_surface_pattern (surface,
 						       (cairo_surface_pattern_t *) surface_pattern,
+						       NULL,
 						       TRUE);
     if (unlikely (status))
 	return status;
@@ -6018,11 +6030,13 @@ _cairo_pdf_surface_paint (void			*abstract_surface,
 	goto cleanup;
 
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
-	source->extend == CAIRO_EXTEND_NONE)
+	(source->extend == CAIRO_EXTEND_NONE ||
+	 source->extend == CAIRO_EXTEND_PAD))
     {
 	_cairo_output_stream_printf (surface->output, "q\n");
 	status = _cairo_pdf_surface_paint_surface_pattern (surface,
 							   (cairo_surface_pattern_t *) source,
+							   &extents.bounded,
 							   FALSE);
 	if (unlikely (status))
 	    goto cleanup;
@@ -6433,7 +6447,8 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 	goto cleanup;
 
     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))
@@ -6448,6 +6463,7 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 
 	status = _cairo_pdf_surface_paint_surface_pattern (surface,
 							   (cairo_surface_pattern_t *) source,
+							   &extents.bounded,
 							   FALSE);
 	if (unlikely (status))
 	    goto cleanup;
commit 346b8fe3984acd2127285f4a57516a3deda5df25
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:44:50 2011 +1030

    type1-subset: remove unused variables

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index efe3028..e12d1c2 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1094,7 +1094,7 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
     const char *p, *subrs, *charstrings, *array_start, *array_end, *dict_start, *dict_end;
     const char *closefile_token;
     char buffer[32], *subr_count_end, *glyph_count_end;
-    int num_charstrings, length;
+    int length;
     const cairo_scaled_font_backend_t *backend;
     unsigned int i;
 
@@ -1160,7 +1160,7 @@ skip_subrs:
 
     /* Scan past /CharStrings and the integer following it. */
     p = charstrings + strlen ("/CharStrings");
-    num_charstrings = strtol (p, &glyph_count_end, 10);
+    strtol (p, &glyph_count_end, 10);
     if (p == glyph_count_end)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -1513,7 +1513,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
                           cairo_bool_t                   hex_encode)
 {
     cairo_type1_font_subset_t font;
-    cairo_status_t status, status_ignored;
+    cairo_status_t status;
     unsigned long length;
     unsigned int i;
     char buf[30];
@@ -1579,7 +1579,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
  fail2:
     free (type1_subset->base_font);
  fail1:
-    status_ignored = _cairo_type1_font_subset_fini (&font);
+    _cairo_type1_font_subset_fini (&font);
 
     return status;
 }
commit ed7157d705ba9bfe3cc95f1e7b0ea11a91df7fa3
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Dec 6 20:44:22 2011 +1030

    truetype-subset: remove unused variable

diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 1afdf3a..18ee685 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1250,7 +1250,6 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
     uint16_t *end_code;
     uint16_t *delta;
     uint16_t *range_offset;
-    uint16_t *glyph_array;
     uint16_t  c;
 
     backend = scaled_font->backend;
@@ -1290,7 +1289,6 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
     start_code = &(end_code[num_segments + 1]);
     delta = &(start_code[num_segments]);
     range_offset = &(delta[num_segments]);
-    glyph_array = &(range_offset[num_segments]);
 
     /* search for glyph in segments with rangeOffset=0 */
     for (i = 0; i < num_segments; i++) {


More information about the cairo-commit mailing list