[cairo-commit] src/cairo-ps-surface.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Wed Feb 1 04:02:48 PST 2012


 src/cairo-ps-surface.c |  220 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 144 insertions(+), 76 deletions(-)

New commits:
commit d95172858bbf12ff4596493c49c4eefe562cd81c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Feb 1 21:38:07 2012 +1030

    ps: avoid using ps patterns to paint/fill 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-ps-surface.c b/src/cairo-ps-surface.c
index fe7e960..59dcdb9 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3216,55 +3216,6 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t     *surface,
 }
 
 static cairo_status_t
-_cairo_ps_surface_paint_pattern (cairo_ps_surface_t           *surface,
-				 const cairo_pattern_t        *source,
-				 cairo_rectangle_int_t        *extents,
-				 cairo_operator_t              op,
-				 cairo_bool_t                  stencil_mask)
-{
-    switch (source->type) {
-    case CAIRO_PATTERN_TYPE_SURFACE:
-    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
-       return _cairo_ps_surface_paint_surface (surface,
-                                               (cairo_pattern_t *)source,
-                                               extents,
-                                               op,
-					       stencil_mask);
-
-    case CAIRO_PATTERN_TYPE_LINEAR:
-    case CAIRO_PATTERN_TYPE_RADIAL:
-    case CAIRO_PATTERN_TYPE_MESH:
-    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)
-{
-    switch (pattern->type) {
-    case CAIRO_PATTERN_TYPE_SOLID:
-	return FALSE;
-
-    case CAIRO_PATTERN_TYPE_SURFACE:
-    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
-	return (pattern->extend == CAIRO_EXTEND_NONE ||
-		pattern->extend == CAIRO_EXTEND_PAD);
-
-    case CAIRO_PATTERN_TYPE_LINEAR:
-    case CAIRO_PATTERN_TYPE_RADIAL:
-    case CAIRO_PATTERN_TYPE_MESH:
-	return FALSE;
-
-    default:
-	ASSERT_NOT_REACHED;
-	return FALSE;
-    }
-}
-
-static cairo_status_t
 _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
 					cairo_pattern_t         *pattern,
 					cairo_rectangle_int_t   *extents,
@@ -3663,7 +3614,8 @@ _cairo_ps_surface_emit_repeating_function (cairo_ps_surface_t       *surface,
 
 static cairo_status_t
 _cairo_ps_surface_emit_gradient (cairo_ps_surface_t       *surface,
-				 cairo_gradient_pattern_t *pattern)
+				 cairo_gradient_pattern_t *pattern,
+				 cairo_bool_t              is_ps_pattern)
 {
     cairo_matrix_t pat_to_ps;
     cairo_circle_double_t start, end;
@@ -3759,10 +3711,14 @@ _cairo_ps_surface_emit_gradient (cairo_ps_surface_t       *surface,
 	domain[1] = 1.0;
     }
 
-    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
+    if (is_ps_pattern) {
 	_cairo_output_stream_printf (surface->stream,
 				     "<< /PatternType 2\n"
-				     "   /Shading\n"
+				     "   /Shading\n");
+    }
+
+    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
+	_cairo_output_stream_printf (surface->stream,
 				     "   << /ShadingType 2\n"
 				     "      /ColorSpace /DeviceRGB\n"
 				     "      /Coords [ %f %f %f %f ]\n",
@@ -3770,8 +3726,6 @@ _cairo_ps_surface_emit_gradient (cairo_ps_surface_t       *surface,
 				     end.center.x, end.center.y);
     } else {
 	_cairo_output_stream_printf (surface->stream,
-				     "<< /PatternType 2\n"
-				     "   /Shading\n"
 				     "   << /ShadingType 3\n"
 				     "      /ColorSpace /DeviceRGB\n"
 				     "      /Coords [ %f %f %f %f %f %f ]\n",
@@ -3795,20 +3749,28 @@ _cairo_ps_surface_emit_gradient (cairo_ps_surface_t       *surface,
 
     _cairo_output_stream_printf (surface->stream,
 				 "      /Function CairoFunction\n"
-				 "   >>\n"
-				 ">>\n"
-				 "[ %f %f %f %f %f %f ]\n"
-				 "makepattern setpattern\n",
-                                 pat_to_ps.xx, pat_to_ps.yx,
-                                 pat_to_ps.xy, pat_to_ps.yy,
-                                 pat_to_ps.x0, pat_to_ps.y0);
+				 "   >>\n");
+
+    if (is_ps_pattern) {
+	_cairo_output_stream_printf (surface->stream,
+				     ">>\n"
+				     "[ %f %f %f %f %f %f ]\n"
+				     "makepattern setpattern\n",
+				     pat_to_ps.xx, pat_to_ps.yx,
+				     pat_to_ps.xy, pat_to_ps.yy,
+				     pat_to_ps.x0, pat_to_ps.y0);
+    } else {
+	_cairo_output_stream_printf (surface->stream,
+				     "shfill\n");
+    }
 
     return status;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t     *surface,
-				     cairo_mesh_pattern_t   *pattern)
+				     cairo_mesh_pattern_t   *pattern,
+				     cairo_bool_t            is_ps_pattern)
 {
     cairo_matrix_t pat_to_ps;
     cairo_status_t status;
@@ -3843,9 +3805,15 @@ _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t     *surface,
 
     _cairo_output_stream_printf (surface->stream,
 				 "\n"
-				 "/CairoData exch def\n"
-				 "<< /PatternType 2\n"
-				 "   /Shading\n"
+				 "/CairoData exch def\n");
+
+    if (is_ps_pattern) {
+	_cairo_output_stream_printf (surface->stream,
+				     "<< /PatternType 2\n"
+				     "   /Shading\n");
+    }
+
+    _cairo_output_stream_printf (surface->stream,
 				 "   << /ShadingType %d\n"
 				 "      /ColorSpace /DeviceRGB\n"
 				 "      /DataSource CairoData\n"
@@ -3863,17 +3831,23 @@ _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t     *surface,
 
     _cairo_output_stream_printf (surface->stream,
 				 "]\n"
-				 "   >>\n"
-				 ">>\n");
+				 "   >>\n");
+
+    if (is_ps_pattern) {
+	_cairo_output_stream_printf (surface->stream,
+				     ">>\n"
+				     "[ %f %f %f %f %f %f ]\n",
+				     pat_to_ps.xx, pat_to_ps.yx,
+				     pat_to_ps.xy, pat_to_ps.yy,
+				     pat_to_ps.x0, pat_to_ps.y0);
+	_cairo_output_stream_printf (surface->stream,
+				     "makepattern\n"
+				     "setpattern\n");
+    } else {
+	_cairo_output_stream_printf (surface->stream, "shfill\n");
+    }
 
     _cairo_output_stream_printf (surface->stream,
-				 "[ %f %f %f %f %f %f ]\n",
-				 pat_to_ps.xx, pat_to_ps.yx,
-                                 pat_to_ps.xy, pat_to_ps.yy,
-                                 pat_to_ps.x0, pat_to_ps.y0);
-    _cairo_output_stream_printf (surface->stream,
-				 "makepattern\n"
-				 "setpattern\n"
 				 "currentdict /CairoData undef\n");
 
     _cairo_pdf_shading_fini (&shading);
@@ -3932,14 +3906,16 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
 	status = _cairo_ps_surface_emit_gradient (surface,
-					  (cairo_gradient_pattern_t *) pattern);
+						  (cairo_gradient_pattern_t *) pattern,
+						  TRUE);
 	if (unlikely (status))
 	    return status;
 	break;
 
     case CAIRO_PATTERN_TYPE_MESH:
 	status = _cairo_ps_surface_emit_mesh_pattern (surface,
-					  (cairo_mesh_pattern_t *) pattern);
+						      (cairo_mesh_pattern_t *) pattern,
+						      TRUE);
 	if (unlikely (status))
 	    return status;
 	break;
@@ -3948,6 +3924,98 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_cairo_ps_surface_paint_gradient (cairo_ps_surface_t          *surface,
+				  const cairo_pattern_t       *source,
+				  const cairo_rectangle_int_t *extents)
+{
+    cairo_matrix_t pat_to_ps;
+    cairo_status_t status;
+
+    pat_to_ps = source->matrix;
+    status = cairo_matrix_invert (&pat_to_ps);
+    /* cairo_pattern_set_matrix ensures the matrix is invertible */
+    assert (status == CAIRO_STATUS_SUCCESS);
+    cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
+
+    if (! _cairo_matrix_is_identity (&pat_to_ps)) {
+	_cairo_output_stream_printf (surface->stream,
+				     "[%f %f %f %f %f %f] concat\n",
+				     pat_to_ps.xx, pat_to_ps.yx,
+				     pat_to_ps.xy, pat_to_ps.yy,
+				     pat_to_ps.x0, pat_to_ps.y0);
+    }
+
+    if (source->type == CAIRO_PATTERN_TYPE_MESH) {
+	status = _cairo_ps_surface_emit_mesh_pattern (surface,
+						      (cairo_mesh_pattern_t *)source,
+						      FALSE);
+	if (unlikely (status))
+	    return status;
+    } else {
+	status = _cairo_ps_surface_emit_gradient (surface,
+						  (cairo_gradient_pattern_t *)source,
+						  FALSE);
+	if (unlikely (status))
+	    return status;
+    }
+
+    return status;
+}
+
+static cairo_status_t
+_cairo_ps_surface_paint_pattern (cairo_ps_surface_t           *surface,
+				 const cairo_pattern_t        *source,
+				 cairo_rectangle_int_t        *extents,
+				 cairo_operator_t              op,
+				 cairo_bool_t                  stencil_mask)
+{
+    switch (source->type) {
+    case CAIRO_PATTERN_TYPE_SURFACE:
+    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+       return _cairo_ps_surface_paint_surface (surface,
+                                               (cairo_pattern_t *)source,
+                                               extents,
+                                               op,
+					       stencil_mask);
+
+    case CAIRO_PATTERN_TYPE_LINEAR:
+    case CAIRO_PATTERN_TYPE_RADIAL:
+    case CAIRO_PATTERN_TYPE_MESH:
+	return _cairo_ps_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)
+{
+    switch (pattern->type) {
+    case CAIRO_PATTERN_TYPE_SOLID:
+	return FALSE;
+
+    case CAIRO_PATTERN_TYPE_SURFACE:
+    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+	return (pattern->extend == CAIRO_EXTEND_NONE ||
+		pattern->extend == CAIRO_EXTEND_PAD);
+
+    case CAIRO_PATTERN_TYPE_LINEAR:
+    case CAIRO_PATTERN_TYPE_RADIAL:
+    case CAIRO_PATTERN_TYPE_MESH:
+	return TRUE;
+
+    default:
+	ASSERT_NOT_REACHED;
+	return FALSE;
+    }
+}
+
 static cairo_bool_t
 _cairo_ps_surface_get_extents (void		       *abstract_surface,
 			       cairo_rectangle_int_t   *rectangle)


More information about the cairo-commit mailing list