[cairo-commit] 2 commits - src/cairo-meta-surface.c

Carl Worth cworth at kemper.freedesktop.org
Thu Aug 3 19:26:55 PDT 2006


 src/cairo-meta-surface.c |  114 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 83 insertions(+), 31 deletions(-)

New commits:
diff-tree 1feb4291cf7813494355459bb547eec604c54ffb (from 8c953167ba045ffdfc25ac4f19faff83720f2473)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Aug 3 19:25:53 2006 -0700

    Apply device_transform during meta-surface replay to fix bug 7533

diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 5aeaf79..d6beaf0 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -615,6 +615,26 @@ static const cairo_surface_backend_t cai
     _cairo_meta_surface_snapshot
 };
 
+static cairo_path_fixed_t *
+_cairo_command_get_path (cairo_command_t *command)
+{
+    switch (command->type) {
+    case CAIRO_COMMAND_PAINT:
+    case CAIRO_COMMAND_MASK:
+    case CAIRO_COMMAND_SHOW_GLYPHS:
+	return NULL;
+    case CAIRO_COMMAND_STROKE:
+	return &command->stroke.path;
+    case CAIRO_COMMAND_FILL:
+	return &command->fill.path;
+    case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
+	return command->intersect_clip_path.path_pointer;
+    }
+
+    ASSERT_NOT_REACHED;
+    return NULL;
+}
+
 cairo_status_t
 _cairo_meta_surface_replay (cairo_surface_t *surface,
 			    cairo_surface_t *target)
@@ -624,6 +644,9 @@ _cairo_meta_surface_replay (cairo_surfac
     int i, num_elements;
     cairo_int_status_t status;
     cairo_clip_t clip;
+    cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target);
+    cairo_matrix_t *device_transform = &target->device_transform;
+    cairo_path_fixed_t path_copy, *dev_path;
 
     meta = (cairo_meta_surface_t *) surface;
     status = CAIRO_STATUS_SUCCESS;
@@ -643,6 +666,12 @@ _cairo_meta_surface_replay (cairo_surfac
 		break;
 	}
 
+	dev_path = _cairo_command_get_path (command);
+	if (dev_path && has_device_transform) {
+	    _cairo_path_fixed_init_copy (&path_copy, dev_path);
+	    _cairo_path_fixed_device_transform (&path_copy, device_transform);
+	    dev_path = &path_copy;
+	}
 
 	switch (command->type) {
 	case CAIRO_COMMAND_PAINT:
@@ -657,41 +686,77 @@ _cairo_meta_surface_replay (cairo_surfac
 					  &command->mask.mask.base);
 	    break;
 	case CAIRO_COMMAND_STROKE:
+	{
+	    cairo_matrix_t dev_ctm = command->stroke.ctm;
+	    cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse;
+	    cairo_matrix_t tmp;
+
+	    if (has_device_transform) {
+		cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
+		tmp = surface->device_transform;
+		status = cairo_matrix_invert (&tmp);
+		assert (status == CAIRO_STATUS_SUCCESS);
+		cairo_matrix_multiply (&dev_ctm_inverse, &tmp, &dev_ctm_inverse);
+	    }
+
 	    status = _cairo_surface_stroke (target,
 					    command->stroke.op,
 					    &command->stroke.source.base,
-					    &command->stroke.path,
+					    dev_path,
 					    &command->stroke.style,
-					    &command->stroke.ctm,
-					    &command->stroke.ctm_inverse,
+					    &dev_ctm,
+					    &dev_ctm_inverse,
 					    command->stroke.tolerance,
 					    command->stroke.antialias);
 	    break;
+	}
 	case CAIRO_COMMAND_FILL:
 	    status = _cairo_surface_fill (target,
 					  command->fill.op,
 					  &command->fill.source.base,
-					  &command->fill.path,
+					  dev_path,
 					  command->fill.fill_rule,
 					  command->fill.tolerance,
 					  command->fill.antialias);
 	    break;
 	case CAIRO_COMMAND_SHOW_GLYPHS:
+	{
+	    cairo_glyph_t *glyphs = command->show_glyphs.glyphs;
+	    cairo_glyph_t *dev_glyphs = glyphs;
+	    int i, num_glyphs = command->show_glyphs.num_glyphs;
+
+	    if (has_device_transform) {
+		dev_glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
+		if (dev_glyphs == NULL) {
+		    status = CAIRO_STATUS_NO_MEMORY;
+		    break;
+		}
+		for (i = 0; i < num_glyphs; i++) {
+		    dev_glyphs[i] = glyphs[i];
+		    cairo_matrix_transform_point (device_transform,
+						  &dev_glyphs[i].x,
+						  &dev_glyphs[i].y);
+		}
+	    }
+
 	    status = _cairo_surface_show_glyphs	(target,
 						 command->show_glyphs.op,
 						 &command->show_glyphs.source.base,
-						 command->show_glyphs.glyphs,
-						 command->show_glyphs.num_glyphs,
+						 dev_glyphs, num_glyphs,
 						 command->show_glyphs.scaled_font);
+
+	    if (dev_glyphs != glyphs)
+		free (dev_glyphs);
+
 	    break;
+	}
 	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
 	    /* XXX Meta surface clipping is broken and requires some
 	     * cairo-gstate.c rewriting.  Work around it for now. */
-	    if (command->intersect_clip_path.path_pointer == NULL)
+	    if (dev_path == NULL)
 		status = _cairo_clip_reset (&clip);
 	    else
-		status = _cairo_clip_clip (&clip,
-					   command->intersect_clip_path.path_pointer,
+		status = _cairo_clip_clip (&clip, dev_path,
 					   command->intersect_clip_path.fill_rule,
 					   command->intersect_clip_path.tolerance,
 					   command->intersect_clip_path.antialias,
@@ -701,6 +766,9 @@ _cairo_meta_surface_replay (cairo_surfac
 	    ASSERT_NOT_REACHED;
 	}
 
+	if (dev_path == &path_copy)
+	    _cairo_path_fixed_fini (&path_copy);
+
 	if (status)
 	    break;
     }
diff-tree 8c953167ba045ffdfc25ac4f19faff83720f2473 (from 34a0b728fb0e19a4d03152318a002362791c30d1)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Aug 3 17:48:25 2006 -0700

    Simplify common set_clip operation in meta-surface replay.

diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 3fe6bc2..5aeaf79 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -634,33 +634,29 @@ _cairo_meta_surface_replay (cairo_surfac
     elements = _cairo_array_index (&meta->commands, 0);
     for (i = meta->replay_start_idx; i < num_elements; i++) {
 	command = elements[i];
-	switch (command->type) {
-	case CAIRO_COMMAND_PAINT:
+
+	/* For all commands except intersect_clip_path, we have to
+	 * ensure the current clip gets set on the surface. */
+	if (command->type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) {
 	    status = _cairo_surface_set_clip (target, &clip);
 	    if (status)
 		break;
+	}
 
+
+	switch (command->type) {
+	case CAIRO_COMMAND_PAINT:
 	    status = _cairo_surface_paint (target,
 					   command->paint.op,
 					   &command->paint.source.base);
 	    break;
-
 	case CAIRO_COMMAND_MASK:
-	    status = _cairo_surface_set_clip (target, &clip);
-	    if (status)
-		break;
-
 	    status = _cairo_surface_mask (target,
 					  command->mask.op,
 					  &command->mask.source.base,
 					  &command->mask.mask.base);
 	    break;
-
 	case CAIRO_COMMAND_STROKE:
-	    status = _cairo_surface_set_clip (target, &clip);
-	    if (status)
-		break;
-
 	    status = _cairo_surface_stroke (target,
 					    command->stroke.op,
 					    &command->stroke.source.base,
@@ -671,12 +667,7 @@ _cairo_meta_surface_replay (cairo_surfac
 					    command->stroke.tolerance,
 					    command->stroke.antialias);
 	    break;
-
 	case CAIRO_COMMAND_FILL:
-	    status = _cairo_surface_set_clip (target, &clip);
-	    if (status)
-		break;
-
 	    status = _cairo_surface_fill (target,
 					  command->fill.op,
 					  &command->fill.source.base,
@@ -685,12 +676,7 @@ _cairo_meta_surface_replay (cairo_surfac
 					  command->fill.tolerance,
 					  command->fill.antialias);
 	    break;
-
 	case CAIRO_COMMAND_SHOW_GLYPHS:
-	    status = _cairo_surface_set_clip (target, &clip);
-	    if (status)
-		break;
-
 	    status = _cairo_surface_show_glyphs	(target,
 						 command->show_glyphs.op,
 						 &command->show_glyphs.source.base,
@@ -698,7 +684,6 @@ _cairo_meta_surface_replay (cairo_surfac
 						 command->show_glyphs.num_glyphs,
 						 command->show_glyphs.scaled_font);
 	    break;
-
 	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
 	    /* XXX Meta surface clipping is broken and requires some
 	     * cairo-gstate.c rewriting.  Work around it for now. */
@@ -712,7 +697,6 @@ _cairo_meta_surface_replay (cairo_surfac
 					   command->intersect_clip_path.antialias,
 					   target);
 	    break;
-
 	default:
 	    ASSERT_NOT_REACHED;
 	}


More information about the cairo-commit mailing list