[cairo-commit] 8 commits - src/cairo-clip-boxes.c src/cairo-clip.c src/cairo-clip-private.h src/cairo-composite-rectangles.c src/cairo-freed-pool-private.h src/cairo.h src/cairo-recording-surface.c src/cairo-scaled-font.c src/cairo-surface-wrapper.c src/cairo-surface-wrapper-private.h test/Makefile.refs test/Makefile.sources test/paint-with-alpha.c test/paint-with-alpha-clip-mask.ref.png test/record.c test/record-fill-alpha.ref.png test/record-paint-alpha-clip-mask.ref.png test/record-paint-alpha-clip.ref.png test/record-paint-alpha.ref.png test/record-paint-alpha-solid-clip.ref.png test/record-paint.ref.png test/record-select-font-face.ref.png test/record-self-intersecting.ref.png test/record-text-transform.ref.png util/cairo-script util/cairo-trace

Chris Wilson ickle at kemper.freedesktop.org
Sun Jul 24 03:51:59 PDT 2011


 src/cairo-clip-boxes.c                     |   61 ++-
 src/cairo-clip-private.h                   |    2 
 src/cairo-clip.c                           |   33 +
 src/cairo-composite-rectangles.c           |   11 
 src/cairo-freed-pool-private.h             |    2 
 src/cairo-recording-surface.c              |   78 ++--
 src/cairo-scaled-font.c                    |   72 +++-
 src/cairo-surface-wrapper-private.h        |    6 
 src/cairo-surface-wrapper.c                |    4 
 src/cairo.h                                |    8 
 test/Makefile.refs                         |   10 
 test/Makefile.sources                      |    1 
 test/paint-with-alpha-clip-mask.ref.png    |binary
 test/paint-with-alpha.c                    |   34 ++
 test/record-fill-alpha.ref.png             |binary
 test/record-paint-alpha-clip-mask.ref.png  |binary
 test/record-paint-alpha-clip.ref.png       |binary
 test/record-paint-alpha-solid-clip.ref.png |binary
 test/record-paint-alpha.ref.png            |binary
 test/record-paint.ref.png                  |binary
 test/record-select-font-face.ref.png       |binary
 test/record-self-intersecting.ref.png      |binary
 test/record-text-transform.ref.png         |binary
 test/record.c                              |  485 +++++++++++++++++++++++++++++
 util/cairo-script/cairo-script-operators.c |   64 +++
 util/cairo-trace/trace.c                   |   11 
 26 files changed, 778 insertions(+), 104 deletions(-)

New commits:
commit 4d5c95f6296b606c7fba31a75211129119ad9e2c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jul 24 10:41:10 2011 +0100

    test: Exercise replaying basic painting paths
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/Makefile.refs b/test/Makefile.refs
index 0618e90..f0e131d 100644
--- a/test/Makefile.refs
+++ b/test/Makefile.refs
@@ -866,6 +866,7 @@ REFERENCE_IMAGES = \
 	paint-source-alpha.image16.ref.png \
 	paint-source-alpha.ref.png \
 	paint-source-alpha.svg.ref.png \
+	paint-with-alpha-clip-mask.ref.png \
 	paint-with-alpha-clip.ref.png \
 	paint-with-alpha-clip.xlib.ref.png \
 	paint-with-alpha-solid-clip.ref.png \
@@ -993,6 +994,15 @@ REFERENCE_IMAGES = \
 	random-intersections-nonzero.quartz.ref.png \
 	random-intersections-nonzero.ref.png \
 	random-intersections-nonzero.xlib.ref.png \
+	record-fill-alpha.ref.png \
+	record-paint-alpha-clip-mask.ref.png \
+	record-paint-alpha-clip.ref.png \
+	record-paint-alpha-solid-clip.ref.png \
+	record-paint-alpha.ref.png \
+	record-paint.ref.png \
+	record-select-font-face.ref.png \
+	record-self-intersecting.ref.png \
+	record-text-transform.ref.png \
 	recording-surface-over.gl.argb32.ref.png \
 	recording-surface-over.image16.ref.png \
 	recording-surface-over.pdf.argb32.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index e9c69ae..0e6173b 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -219,6 +219,7 @@ test_sources = \
 	random-intersections-nonzero.c			\
 	random-intersections-curves-eo.c		\
 	random-intersections-curves-nz.c		\
+	record.c					\
 	recording-surface-pattern.c			\
 	rectangle-rounding-error.c			\
 	rectilinear-fill.c				\
diff --git a/test/paint-with-alpha-clip-mask.ref.png b/test/paint-with-alpha-clip-mask.ref.png
new file mode 100644
index 0000000..3ea5e57
Binary files /dev/null and b/test/paint-with-alpha-clip-mask.ref.png differ
diff --git a/test/paint-with-alpha.c b/test/paint-with-alpha.c
index e827bb9..8daa935 100644
--- a/test/paint-with-alpha.c
+++ b/test/paint-with-alpha.c
@@ -94,6 +94,34 @@ draw_clip (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
+static cairo_test_status_t
+draw_clip_mask (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_image_surface_create_for_data ((unsigned char *) data,
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
+
+    cairo_test_paint_checkered (cr);
+
+    cairo_move_to (cr, 16, 5);
+    cairo_line_to (cr, 5, 16);
+    cairo_line_to (cr, 16, 27);
+    cairo_line_to (cr, 27, 16);
+    cairo_clip (cr);
+
+    cairo_scale (cr, 4, 4);
+
+    cairo_set_source_surface (cr, surface, 2 , 2);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+    cairo_paint_with_alpha (cr, 0.5);
+
+    cairo_surface_finish (surface); /* data will go out of scope */
+    cairo_surface_destroy (surface);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
 CAIRO_TEST (paint_with_alpha,
 	    "Simple test of cairo_paint_with_alpha",
 	    "paint, alpha", /* keywords */
@@ -112,3 +140,9 @@ CAIRO_TEST (paint_with_alpha_clip,
 	    NULL, /* requirements */
 	    32, 32,
 	    NULL, draw_clip)
+CAIRO_TEST (paint_with_alpha_clip_mask,
+	    "Simple test of cairo_paint_with_alpha+unaligned clip",
+	    "paint, alpha, clip", /* keywords */
+	    NULL, /* requirements */
+	    32, 32,
+	    NULL, draw_clip_mask)
diff --git a/test/record-fill-alpha.ref.png b/test/record-fill-alpha.ref.png
new file mode 100644
index 0000000..b50a456
Binary files /dev/null and b/test/record-fill-alpha.ref.png differ
diff --git a/test/record-paint-alpha-clip-mask.ref.png b/test/record-paint-alpha-clip-mask.ref.png
new file mode 100644
index 0000000..3ea5e57
Binary files /dev/null and b/test/record-paint-alpha-clip-mask.ref.png differ
diff --git a/test/record-paint-alpha-clip.ref.png b/test/record-paint-alpha-clip.ref.png
new file mode 100644
index 0000000..c8c0bde
Binary files /dev/null and b/test/record-paint-alpha-clip.ref.png differ
diff --git a/test/record-paint-alpha-solid-clip.ref.png b/test/record-paint-alpha-solid-clip.ref.png
new file mode 100644
index 0000000..59d226d
Binary files /dev/null and b/test/record-paint-alpha-solid-clip.ref.png differ
diff --git a/test/record-paint-alpha.ref.png b/test/record-paint-alpha.ref.png
new file mode 100644
index 0000000..ab7ce3e
Binary files /dev/null and b/test/record-paint-alpha.ref.png differ
diff --git a/test/record-paint.ref.png b/test/record-paint.ref.png
new file mode 100644
index 0000000..fff03b3
Binary files /dev/null and b/test/record-paint.ref.png differ
diff --git a/test/record-select-font-face.ref.png b/test/record-select-font-face.ref.png
new file mode 100644
index 0000000..b3d2322
Binary files /dev/null and b/test/record-select-font-face.ref.png differ
diff --git a/test/record-self-intersecting.ref.png b/test/record-self-intersecting.ref.png
new file mode 100644
index 0000000..d554d83
Binary files /dev/null and b/test/record-self-intersecting.ref.png differ
diff --git a/test/record-text-transform.ref.png b/test/record-text-transform.ref.png
new file mode 100644
index 0000000..6f36b9d
Binary files /dev/null and b/test/record-text-transform.ref.png differ
diff --git a/test/record.c b/test/record.c
new file mode 100644
index 0000000..2f30653
--- /dev/null
+++ b/test/record.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ *	Carl D. Worth <cworth at cworth.org>
+ *	Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#define TEXT_SIZE 12
+#define SIZE 60 /* needs to be big to check large area effects (dithering) */
+#define PAD 2
+
+#define TT_SIZE 100
+#define TT_PAD 5
+#define TT_FONT_SIZE 32.0
+
+static uint32_t data[16] = {
+    0xffffffff, 0xffffffff,		0xffff0000, 0xffff0000,
+    0xffffffff, 0xffffffff,		0xffff0000, 0xffff0000,
+
+    0xff00ff00, 0xff00ff00,		0xff0000ff, 0xff0000ff,
+    0xff00ff00, 0xff00ff00,		0xff0000ff, 0xff0000ff
+};
+
+static const char *png_filename = "romedalen.png";
+
+static cairo_t *
+paint (cairo_t *cr)
+{
+    cairo_set_source_rgb (cr, 0, 0, 1);
+    cairo_paint (cr);
+
+    cairo_translate (cr, 2, 2);
+    cairo_scale (cr, 0.5, 0.5);
+
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_paint (cr);
+
+    return cr;
+}
+
+static cairo_t *
+paint_alpha (cairo_t *cr)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_image_surface_create_for_data ((unsigned char *) data,
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
+
+    cairo_test_paint_checkered (cr);
+
+    cairo_scale (cr, 4, 4);
+
+    cairo_set_source_surface (cr, surface, 2 , 2);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+    cairo_paint_with_alpha (cr, 0.5);
+
+    cairo_surface_finish (surface); /* data will go out of scope */
+    cairo_surface_destroy (surface);
+
+    return cr;
+}
+
+static cairo_t *
+paint_alpha_solid_clip (cairo_t *cr)
+{
+    cairo_test_paint_checkered (cr);
+
+    cairo_rectangle (cr, 2.5, 2.5, 27, 27);
+    cairo_clip (cr);
+
+    cairo_set_source_rgb (cr, 1., 0.,0.);
+    cairo_paint_with_alpha (cr, 0.5);
+
+    return cr;
+}
+
+static cairo_t *
+paint_alpha_clip (cairo_t *cr)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_image_surface_create_for_data ((unsigned char *) data,
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
+
+    cairo_test_paint_checkered (cr);
+
+    cairo_rectangle (cr, 10.5, 10.5, 11, 11);
+    cairo_clip (cr);
+
+    cairo_scale (cr, 4, 4);
+
+    cairo_set_source_surface (cr, surface, 2 , 2);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+    cairo_paint_with_alpha (cr, 0.5);
+
+    cairo_surface_finish (surface); /* data will go out of scope */
+    cairo_surface_destroy (surface);
+
+    return cr;
+}
+
+static cairo_t *
+paint_alpha_clip_mask (cairo_t *cr)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_image_surface_create_for_data ((unsigned char *) data,
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
+
+    cairo_test_paint_checkered (cr);
+
+    cairo_move_to (cr, 16, 5);
+    cairo_line_to (cr, 5, 16);
+    cairo_line_to (cr, 16, 27);
+    cairo_line_to (cr, 27, 16);
+    cairo_clip (cr);
+
+    cairo_scale (cr, 4, 4);
+
+    cairo_set_source_surface (cr, surface, 2 , 2);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+    cairo_paint_with_alpha (cr, 0.5);
+
+    cairo_surface_finish (surface); /* data will go out of scope */
+    cairo_surface_destroy (surface);
+
+    return cr;
+}
+
+static cairo_t *
+select_font_face (cairo_t *cr)
+{
+    /* We draw in the default black, so paint white first. */
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+    cairo_paint (cr);
+
+    cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+
+    cairo_set_font_size (cr, TEXT_SIZE);
+    cairo_move_to (cr, 0, TEXT_SIZE);
+
+    cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Serif",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_show_text (cr, "i-am-serif");
+
+    cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_show_text (cr, " i-am-sans");
+
+    cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans Mono",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_show_text (cr, " i-am-mono");
+
+    return cr;
+}
+
+static cairo_t *
+fill_alpha (cairo_t *cr)
+{
+    const double alpha = 1./3;
+    int n;
+
+    /* flatten to white */
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+
+    /* square */
+    cairo_rectangle (cr, PAD, PAD, SIZE, SIZE);
+    cairo_set_source_rgba (cr, 1, 0, 0, alpha);
+    cairo_fill (cr);
+
+    /* circle */
+    cairo_translate (cr, SIZE + 2 * PAD, 0);
+    cairo_arc (cr, PAD + SIZE / 2., PAD + SIZE / 2., SIZE / 2., 0, 2 * M_PI);
+    cairo_set_source_rgba (cr, 0, 1, 0, alpha);
+    cairo_fill (cr);
+
+    /* triangle */
+    cairo_translate (cr, 0, SIZE + 2 * PAD);
+    cairo_move_to (cr, PAD + SIZE / 2, PAD);
+    cairo_line_to (cr, PAD + SIZE, PAD + SIZE);
+    cairo_line_to (cr, PAD, PAD + SIZE);
+    cairo_set_source_rgba (cr, 0, 0, 1, alpha);
+    cairo_fill (cr);
+
+    /* star */
+    cairo_translate (cr, -(SIZE + 2 * PAD) + SIZE/2., SIZE/2.);
+    for (n = 0; n < 5; n++) {
+	cairo_line_to (cr,
+		       SIZE/2 * cos (2*n * 2*M_PI / 10),
+		       SIZE/2 * sin (2*n * 2*M_PI / 10));
+
+	cairo_line_to (cr,
+		       SIZE/4 * cos ((2*n+1)*2*M_PI / 10),
+		       SIZE/4 * sin ((2*n+1)*2*M_PI / 10));
+    }
+    cairo_set_source_rgba (cr, 0, 0, 0, alpha);
+    cairo_fill (cr);
+
+    return cr;
+}
+
+static cairo_t *
+self_intersecting (cairo_t *cr)
+{
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+
+    cairo_translate (cr, 1.0, 1.0);
+
+    cairo_set_source_rgb (cr, 1, 0, 0); /* red */
+
+    /* First draw the desired shape with a fill */
+    cairo_rectangle (cr, 0.5, 0.5,  4.0, 4.0);
+    cairo_rectangle (cr, 3.5, 3.5,  4.0, 4.0);
+    cairo_rectangle (cr, 3.5, 1.5, -2.0, 2.0);
+    cairo_rectangle (cr, 6.5, 4.5, -2.0, 2.0);
+
+    cairo_fill (cr);
+
+    /* Then try the same thing with a stroke */
+    cairo_translate (cr, 0, 10);
+    cairo_move_to (cr, 1.0, 1.0);
+    cairo_rel_line_to (cr,  3.0,  0.0);
+    cairo_rel_line_to (cr,  0.0,  6.0);
+    cairo_rel_line_to (cr,  3.0,  0.0);
+    cairo_rel_line_to (cr,  0.0, -3.0);
+    cairo_rel_line_to (cr, -6.0,  0.0);
+    cairo_close_path (cr);
+
+    cairo_set_line_width (cr, 1.0);
+    cairo_stroke (cr);
+
+    return cr;
+}
+
+static void
+draw_text_transform (cairo_t *cr)
+{
+    cairo_matrix_t tm;
+
+    /* skew */
+    cairo_matrix_init (&tm, 1, 0,
+                       -0.25, 1,
+                       0, 0);
+    cairo_matrix_scale (&tm, TT_FONT_SIZE, TT_FONT_SIZE);
+    cairo_set_font_matrix (cr, &tm);
+
+    cairo_new_path (cr);
+    cairo_move_to (cr, 50, TT_SIZE-TT_PAD);
+    cairo_show_text (cr, "A");
+
+    /* rotate and scale */
+    cairo_matrix_init_rotate (&tm, M_PI / 2);
+    cairo_matrix_scale (&tm, TT_FONT_SIZE, TT_FONT_SIZE * 2.0);
+    cairo_set_font_matrix (cr, &tm);
+
+    cairo_new_path (cr);
+    cairo_move_to (cr, TT_PAD, TT_PAD + 25);
+    cairo_show_text (cr, "A");
+
+    cairo_matrix_init_rotate (&tm, M_PI / 2);
+    cairo_matrix_scale (&tm, TT_FONT_SIZE * 2.0, TT_FONT_SIZE);
+    cairo_set_font_matrix (cr, &tm);
+
+    cairo_new_path (cr);
+    cairo_move_to (cr, TT_PAD, TT_PAD + 50);
+    cairo_show_text (cr, "A");
+}
+
+static cairo_t *
+text_transform (cairo_t *cr)
+{
+    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
+    cairo_pattern_t *pattern;
+
+    cairo_set_source_rgb (cr, 1., 1., 1.);
+    cairo_paint (cr);
+
+    cairo_set_source_rgb (cr, 0., 0., 0.);
+
+    cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+
+    draw_text_transform (cr);
+
+    cairo_translate (cr, SIZE, SIZE);
+    cairo_rotate (cr, M_PI);
+
+    pattern = cairo_test_create_pattern_from_png (ctx, png_filename);
+    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+    cairo_set_source (cr, pattern);
+    cairo_pattern_destroy (pattern);
+
+    draw_text_transform (cr);
+
+    return cr;
+}
+
+/* And here begins the recording and replaying... */
+
+static cairo_t *
+record_create (cairo_t *target)
+{
+    cairo_surface_t *surface;
+    cairo_t *cr;
+
+    surface = cairo_recording_surface_create (cairo_surface_get_content (cairo_get_target (target)), NULL);
+    cr = cairo_create (surface);
+    cairo_surface_destroy (surface);
+
+    return cr;
+}
+
+static cairo_surface_t *
+record_get (cairo_t *target)
+{
+    cairo_surface_t *surface;
+
+    surface = cairo_surface_reference (cairo_get_target (target));
+    cairo_destroy (target);
+
+    return surface;
+}
+
+static cairo_test_status_t
+record_replay (cairo_t *cr, cairo_t *(*func)(cairo_t *), int width, int height)
+{
+    cairo_surface_t *surface;
+    int x, y;
+
+    surface = record_get (func (record_create (cr)));
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_surface (cr, surface, 0, 0);
+    cairo_surface_destroy (surface);
+    cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
+
+    for (y = 0; y < height; y += 2) {
+	for (x = 0; x < width; x += 2) {
+	    cairo_rectangle (cr, x, y, 2, 2);
+	    cairo_clip (cr);
+	    cairo_paint (cr);
+	    cairo_reset_clip (cr);
+	}
+    }
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+record_paint (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, paint, width, height);
+}
+
+static cairo_test_status_t
+record_paint_alpha (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, paint_alpha, width, height);
+}
+
+static cairo_test_status_t
+record_paint_alpha_solid_clip (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, paint_alpha_solid_clip, width, height);
+}
+
+static cairo_test_status_t
+record_paint_alpha_clip (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, paint_alpha_clip, width, height);
+}
+
+static cairo_test_status_t
+record_paint_alpha_clip_mask (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, paint_alpha_clip_mask, width, height);
+}
+
+static cairo_test_status_t
+record_fill_alpha (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, fill_alpha, width, height);
+}
+
+static cairo_test_status_t
+record_self_intersecting (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, self_intersecting, width, height);
+}
+
+static cairo_test_status_t
+record_select_font_face (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, select_font_face, width, height);
+}
+
+static cairo_test_status_t
+record_text_transform (cairo_t *cr, int width, int height)
+{
+    return record_replay (cr, text_transform, width, height);
+}
+
+CAIRO_TEST (record_paint,
+	    "Test replayed calls to cairo_paint",
+	    "paint,record", /* keywords */
+	    NULL, /* requirements */
+	    8, 8,
+	    NULL, record_paint)
+CAIRO_TEST (record_paint_alpha,
+	    "Simple test of cairo_paint_with_alpha",
+	    "record, paint, alpha", /* keywords */
+	    NULL, /* requirements */
+	    32, 32,
+	    NULL, record_paint_alpha)
+CAIRO_TEST (record_paint_alpha_solid_clip,
+	    "Simple test of cairo_paint_with_alpha+unaligned clip",
+	    "record, paint, alpha, clip", /* keywords */
+	    NULL, /* requirements */
+	    32, 32,
+	    NULL, record_paint_alpha_solid_clip)
+CAIRO_TEST (record_paint_alpha_clip,
+	    "Simple test of cairo_paint_with_alpha+unaligned clip",
+	    "record, paint, alpha, clip", /* keywords */
+	    NULL, /* requirements */
+	    32, 32,
+	    NULL, record_paint_alpha_clip)
+CAIRO_TEST (record_paint_alpha_clip_mask,
+	    "Simple test of cairo_paint_with_alpha+triangular clip",
+	    "record, paint, alpha, clip", /* keywords */
+	    NULL, /* requirements */
+	    32, 32,
+	    NULL, record_paint_alpha_clip_mask)
+CAIRO_TEST (record_fill_alpha,
+	    "Tests using set_rgba();fill()",
+	    "record,fill, alpha", /* keywords */
+	    NULL, /* requirements */
+	    2*SIZE + 4*PAD, 2*SIZE + 4*PAD,
+	    NULL, record_fill_alpha)
+CAIRO_TEST (record_select_font_face,
+	    "Tests using cairo_select_font_face to draw text in different faces",
+	    "record, font", /* keywords */
+	    NULL, /* requirements */
+	    192, TEXT_SIZE + 4,
+	    NULL, record_select_font_face)
+CAIRO_TEST (record_self_intersecting,
+	    "Test strokes of self-intersecting paths",
+	    "record, stroke, trap", /* keywords */
+	    NULL, /* requirements */
+	    10, 20,
+	    NULL, record_self_intersecting)
+CAIRO_TEST (record_text_transform,
+	    "Test various applications of the font matrix",
+	    "record, text, transform", /* keywords */
+	    NULL, /* requirements */
+	    TT_SIZE, TT_SIZE,
+	    NULL, record_text_transform)
commit 2b19dd3fbd9ea8d44c9cccbb9ae28b81992b4483
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jul 24 10:09:43 2011 +0100

    recording: Only look for a fill-stroke operation if the target supports one
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 96c71fd..1460aff 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -907,45 +907,46 @@ _cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
 	    break;
 
 	case CAIRO_COMMAND_FILL:
-	{
-	    cairo_command_t *stroke_command;
-
-	    stroke_command = NULL;
-	    if (type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1)
-		stroke_command = elements[i + 1];
-
-	    if (stroke_command != NULL &&
-		type == CAIRO_RECORDING_REPLAY &&
-		region != CAIRO_RECORDING_REGION_ALL)
-	    {
-		if (stroke_command->header.region != region)
-		    stroke_command = NULL;
-	    }
-
-	    if (stroke_command != NULL &&
-		stroke_command->header.type == CAIRO_COMMAND_STROKE &&
-		_cairo_path_fixed_equal (&command->fill.path,
-					 &stroke_command->stroke.path))
-	    {
-		status = _cairo_surface_wrapper_fill_stroke (&wrapper,
-							     command->header.op,
-							     &command->fill.source.base,
-							     command->fill.fill_rule,
-							     command->fill.tolerance,
-							     command->fill.antialias,
-							     &command->fill.path,
-							     stroke_command->header.op,
-							     &stroke_command->stroke.source.base,
-							     &stroke_command->stroke.style,
-							     &stroke_command->stroke.ctm,
-							     &stroke_command->stroke.ctm_inverse,
-							     stroke_command->stroke.tolerance,
-							     stroke_command->stroke.antialias,
-							     clip);
-		i++;
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
+	    if (_cairo_surface_wrapper_has_fill_stroke (&wrapper)) {
+		cairo_command_t *stroke_command;
+
+		stroke_command = NULL;
+		if (type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1)
+		    stroke_command = elements[i + 1];
+
+		if (stroke_command != NULL &&
+		    type == CAIRO_RECORDING_REPLAY &&
+		    region != CAIRO_RECORDING_REGION_ALL)
+		{
+		    if (stroke_command->header.region != region)
+			stroke_command = NULL;
+		}
+
+		if (stroke_command != NULL &&
+		    stroke_command->header.type == CAIRO_COMMAND_STROKE &&
+		    _cairo_path_fixed_equal (&command->fill.path,
+					     &stroke_command->stroke.path))
+		{
+		    status = _cairo_surface_wrapper_fill_stroke (&wrapper,
+								 command->header.op,
+								 &command->fill.source.base,
+								 command->fill.fill_rule,
+								 command->fill.tolerance,
+								 command->fill.antialias,
+								 &command->fill.path,
+								 stroke_command->header.op,
+								 &stroke_command->stroke.source.base,
+								 &stroke_command->stroke.style,
+								 &stroke_command->stroke.ctm,
+								 &stroke_command->stroke.ctm_inverse,
+								 stroke_command->stroke.tolerance,
+								 stroke_command->stroke.antialias,
+								 clip);
+		    i++;
+		}
 	    }
-	    else
-	    {
+	    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 		status = _cairo_surface_wrapper_fill (&wrapper,
 						      command->header.op,
 						      &command->fill.source.base,
@@ -956,7 +957,6 @@ _cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
 						      clip);
 	    }
 	    break;
-	}
 
 	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
 	{
diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h
index 97ac809..b810730 100644
--- a/src/cairo-surface-wrapper-private.h
+++ b/src/cairo-surface-wrapper-private.h
@@ -74,6 +74,12 @@ _cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper,
 cairo_private void
 _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper);
 
+static inline cairo_bool_t
+_cairo_surface_wrapper_has_fill_stroke (cairo_surface_wrapper_t *wrapper)
+{
+    return wrapper->target->backend->fill_stroke != NULL;
+}
+
 cairo_private cairo_status_t
 _cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper,
 					     cairo_image_surface_t  **image_out,
commit dc67d8e7f907062c7d0f02b57498c7503cb72f69
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jul 24 10:03:48 2011 +0100

    composite: Perform a quick is-clipped for glyphs
    
    Computing the exact bbox of the glyphs and whether they are overlapped
    is expensive. However, we can often check whether they are visible just
    by looking at the maximal extents of the fonts along with the bbox of
    the positions; much cheaper.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c
index 7f288cb..881d264 100644
--- a/src/cairo-composite-rectangles.c
+++ b/src/cairo-composite-rectangles.c
@@ -234,6 +234,17 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
     }
 
+    /* Computing the exact bbox and the overlap is expensive.
+     * First perform a cheap test to see if the glyphs are all clipped out.
+     */
+    if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) {
+	_cairo_scaled_font_glyph_approximate_extents (scaled_font,
+						      glyphs, num_glyphs,
+						      &extents->mask);
+	if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask))
+	    return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
+
     status = _cairo_scaled_font_glyph_device_extents (scaled_font,
 						      glyphs, num_glyphs,
 						      &extents->mask,
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index ee79e2a..efab44f 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2193,11 +2193,14 @@ _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t	 *scaled_font,
 					      int                      num_glyphs,
 					      cairo_rectangle_int_t   *extents)
 {
-    double x0 = HUGE_VAL, x1 = -HUGE_VAL;
-    double y0 = HUGE_VAL, y1 = -HUGE_VAL;
+    double x0, x1, y0, y1, pad;
     int i;
 
-    for (i = 0; i < num_glyphs; i++) {
+    assert (num_glyphs);
+
+    x0 = x1 = glyphs[0].x;
+    y0 = y1 = glyphs[0].y;
+    for (i = 1; i < num_glyphs; i++) {
 	double g;
 
 	g = glyphs[i].x;
@@ -2209,18 +2212,14 @@ _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t	 *scaled_font,
 	if (g > y1) y1 = g;
     }
 
-    if (x0 <= x1 && y0 <= y1) {
-	extents->x = floor (x0 - scaled_font->extents.max_x_advance);
-	extents->width = ceil (x1 + scaled_font->extents.max_x_advance);
-	extents->width -= extents->x;
+    pad = MAX(scaled_font->fs_extents.max_x_advance,
+	      scaled_font->fs_extents.height);
+    pad *= scaled_font->max_scale;
 
-	extents->y = floor (y0 - scaled_font->extents.ascent);
-	extents->height = ceil (y1 + scaled_font->extents.descent);
-	extents->height -= extents->y;
-    } else {
-	extents->x = extents->y = 0;
-	extents->width = extents->height = 0;
-    }
+    extents->x = floor (x0 - pad);
+    extents->width = ceil (x1 + pad) - extents->x;
+    extents->y = floor (y0 - pad);
+    extents->height = ceil (y1 + pad) - extents->y;
 }
 
 cairo_status_t
diff --git a/src/cairo.h b/src/cairo.h
index 3cab6bc..ba35de4 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1060,7 +1060,7 @@ typedef struct {
  *           portions below the baseline. Note that this is not always
  *           exactly equal to the maximum of the extents of all the
  *           glyphs in the font, but rather is picked to express the
- *           font designer's intent as to how the the font should
+ *           font designer's intent as to how the font should
  *           align with elements below it.
  * @height: the recommended vertical distance between baselines when
  *          setting consecutive lines of text with the font. This
@@ -1070,10 +1070,10 @@ typedef struct {
  *          is at a premium, most fonts can be set with only
  *          a distance of @ascent+ at descent between lines.
  * @max_x_advance: the maximum distance in the X direction that
- *         the the origin is advanced for any glyph in the font.
+ *         the origin is advanced for any glyph in the font.
  * @max_y_advance: the maximum distance in the Y direction that
- *         the the origin is advanced for any glyph in the font.
- *         this will be zero for normal fonts used for horizontal
+ *         the origin is advanced for any glyph in the font.
+ *         This will be zero for normal fonts used for horizontal
  *         writing. (The scripts of East Asia are sometimes written
  *         vertically.)
  *
commit 05bed4c574a9e6577bca93bfce837804c3dc6d19
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jul 24 01:05:40 2011 +0100

    scaled-font: Single glyph extent computations are worryingly frequent
    
    But easy to optimise.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 6cca4ac..ee79e2a 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2059,6 +2059,43 @@ _range_contains_glyph (const cairo_box_t *extents,
 	   top < extents->p2.y;
 }
 
+static cairo_status_t
+_cairo_scaled_font_single_glyph_device_extents (cairo_scaled_font_t	 *scaled_font,
+						const cairo_glyph_t	 *glyph,
+						cairo_rectangle_int_t   *extents)
+{
+    cairo_round_glyph_positions_t round_xy;
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_status_t status;
+    cairo_box_t box;
+    cairo_fixed_t v;
+
+    status = _cairo_scaled_glyph_lookup (scaled_font,
+					 glyph->index,
+					 CAIRO_SCALED_GLYPH_INFO_METRICS,
+					 &scaled_glyph);
+    if (unlikely (status))
+	return status;
+
+    round_xy = _cairo_font_options_get_round_glyph_positions (&scaled_font->options);
+    if (round_xy == CAIRO_ROUND_GLYPH_POS_ON)
+	v = _cairo_fixed_from_int (_cairo_lround (glyph->x));
+    else
+	v = _cairo_fixed_from_double (glyph->x);
+    box.p1.x = v + scaled_glyph->bbox.p1.x;
+    box.p2.x = v + scaled_glyph->bbox.p2.x;
+
+    if (round_xy == CAIRO_ROUND_GLYPH_POS_ON)
+	v = _cairo_fixed_from_int (_cairo_lround (glyph->y));
+    else
+	v = _cairo_fixed_from_double (glyph->y);
+    box.p1.y = v + scaled_glyph->bbox.p1.y;
+    box.p2.y = v + scaled_glyph->bbox.p2.y;
+
+    _cairo_box_round_to_rectangle (&box, extents);
+    return CAIRO_STATUS_SUCCESS;
+}
+
 /*
  * Compute a device-space bounding box for the glyphs.
  */
@@ -2079,6 +2116,14 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t	 *scaled_font,
     if (unlikely (scaled_font->status))
 	return scaled_font->status;
 
+    if (num_glyphs == 1) {
+	if (overlap_out)
+	    *overlap_out = FALSE;
+	return _cairo_scaled_font_single_glyph_device_extents (scaled_font,
+							       glyphs,
+							       extents);
+    }
+
     _cairo_scaled_font_freeze_cache (scaled_font);
 
     memset (glyph_cache, 0, sizeof (glyph_cache));
commit 5ac9e3e2812a240e9e1b19ccf2199784d5739ced
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jul 24 10:05:43 2011 +0100

    freed-pool: Enlarge the freed cache
    
    Clips end up recursing more than 4 levels and so we need a larger stash
    to avoid mallocs.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-freed-pool-private.h b/src/cairo-freed-pool-private.h
index f0549e6..c3267ef 100644
--- a/src/cairo-freed-pool-private.h
+++ b/src/cairo-freed-pool-private.h
@@ -44,7 +44,7 @@
 /* Keep a stash of recently freed clip_paths, since we need to
  * reallocate them frequently.
  */
-#define MAX_FREED_POOL_SIZE 4
+#define MAX_FREED_POOL_SIZE 16
 typedef struct {
     void *pool[MAX_FREED_POOL_SIZE];
     int top;
commit 04ef07ee3bdeab9b2b3d74547214c6735ebb27b3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jul 24 00:58:06 2011 +0100

    clip: Embed a single box to avoid a common allocation
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-clip-boxes.c b/src/cairo-clip-boxes.c
index 98d1a18..663e92b 100644
--- a/src/cairo-clip-boxes.c
+++ b/src/cairo-clip-boxes.c
@@ -163,26 +163,22 @@ _cairo_clip_intersect_rectangle_box (cairo_clip_t *clip,
 	clip = _cairo_clip_create ();
 	if (clip == NULL)
 	    return _cairo_clip_set_all_clipped (clip);
+    }
 
-	clip->boxes = _cairo_malloc (sizeof (cairo_box_t));
-	if (clip->boxes == NULL)
-	    return _cairo_clip_set_all_clipped (clip);
-
-	clip->extents = *r;
-	clip->num_boxes = 1;
+    if (clip->num_boxes == 0) {
+	clip->boxes = &clip->embedded_box;
 	clip->boxes[0] = *box;
-
+	clip->num_boxes = 1;
+	if (clip->path == NULL) {
+	    clip->extents = *r;
+	} else {
+	    if (! _cairo_rectangle_intersect (&clip->extents, r))
+		clip = _cairo_clip_set_all_clipped (clip);
+	}
 	return clip;
     }
 
-    if (clip->num_boxes == 0) {
-	clip->boxes = _cairo_malloc (sizeof (cairo_box_t));
-	if (clip->boxes == NULL)
-	    return _cairo_clip_set_all_clipped (clip);
-
-	j = 1;
-	clip->boxes[0] = *box;
-    } else for (i = j = 0; i < clip->num_boxes; i++) {
+    for (i = j = 0; i < clip->num_boxes; i++) {
 	cairo_box_t *b = &clip->boxes[j];
 
 	if (j != i)
@@ -268,18 +264,27 @@ _cairo_clip_intersect_boxes (cairo_clip_t *clip,
     if (clip == NULL)
 	clip = _cairo_clip_create ();
 
-    if (clip->num_boxes == 0) {
-	clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE);
-	_cairo_boxes_extents (boxes, &extents);
-    } else {
+    if (clip->num_boxes) {
 	_cairo_boxes_init_for_array (&clip_boxes, clip->boxes, clip->num_boxes);
 	if (unlikely (_cairo_boxes_intersect (&clip_boxes, boxes, &clip_boxes)))
 	    return _cairo_clip_set_all_clipped (clip);
 
-	free (clip->boxes);
-	clip->boxes = _cairo_boxes_to_array (&clip_boxes, &clip->num_boxes, TRUE);
-	_cairo_boxes_extents (&clip_boxes, &extents);
+	if (clip->boxes != &clip->embedded_box)
+	    free (clip->boxes);
+
+	boxes = &clip_boxes;
+    }
+
+    if(boxes->num_boxes == 1) {
+	clip->boxes = &clip->embedded_box;
+	clip->boxes[0] = boxes->chunks.base[0];
+	clip->num_boxes = 1;
+    } else {
+	clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE);
     }
+    _cairo_boxes_extents (boxes, &extents);
+    if (boxes == &clip_boxes)
+	_cairo_boxes_fini (&clip_boxes);
 
     if (clip->path == NULL)
 	clip->extents = extents;
@@ -569,9 +574,15 @@ _cairo_clip_from_boxes (const cairo_boxes_t *boxes)
 	return _cairo_clip_set_all_clipped (clip);
 
     /* XXX cow-boxes? */
-    clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE);
-    if (clip->boxes == NULL)
-	return _cairo_clip_set_all_clipped (clip);
+    if(boxes->num_boxes == 1) {
+	clip->boxes = &clip->embedded_box;
+	clip->boxes[0] = boxes->chunks.base[0];
+	clip->num_boxes = 1;
+    } else {
+	clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE);
+	if (clip->boxes == NULL)
+	    return _cairo_clip_set_all_clipped (clip);
+    }
 
     _cairo_boxes_extents (boxes, &clip->extents);
 
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index 7f44bdf..1fad89c 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -66,6 +66,8 @@ struct _cairo_clip {
 
     cairo_region_t *region;
     cairo_bool_t is_region;
+
+    cairo_box_t embedded_box;
 };
 
 cairo_private cairo_clip_t *
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 99336bd..fcd1acb 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -139,7 +139,8 @@ _cairo_clip_destroy (cairo_clip_t *clip)
     if (clip->path != NULL)
 	_cairo_clip_path_destroy (clip->path);
 
-    free (clip->boxes);
+    if (clip->boxes != &clip->embedded_box)
+	free (clip->boxes);
     cairo_region_destroy (clip->region);
 
     _freed_pool_put (&clip_pool, clip);
@@ -159,9 +160,13 @@ _cairo_clip_copy (const cairo_clip_t *clip)
 	copy->path = _cairo_clip_path_reference (clip->path);
 
     if (clip->num_boxes) {
-	copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
-	if (unlikely (copy->boxes == NULL))
-	    return _cairo_clip_set_all_clipped (copy);
+	if (clip->num_boxes == 1) {
+	    copy->boxes = &copy->embedded_box;
+	} else {
+	    copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+	    if (unlikely (copy->boxes == NULL))
+		return _cairo_clip_set_all_clipped (copy);
+	}
 
 	memcpy (copy->boxes, clip->boxes,
 		clip->num_boxes * sizeof (cairo_box_t));
@@ -189,9 +194,13 @@ _cairo_clip_copy_region (const cairo_clip_t *clip)
     copy = _cairo_clip_create ();
     copy->extents = clip->extents;
 
-    copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
-    if (unlikely (copy->boxes == NULL))
-	return _cairo_clip_set_all_clipped (copy);
+    if (clip->num_boxes == 1) {
+	copy->boxes = &copy->embedded_box;
+    } else {
+	copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+	if (unlikely (copy->boxes == NULL))
+	    return _cairo_clip_set_all_clipped (copy);
+    }
 
     for (i = 0; i < clip->num_boxes; i++) {
 	copy->boxes[i].p1.x = _cairo_fixed_floor (clip->boxes[i].p1.x);
@@ -397,9 +406,13 @@ _cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty)
     fy = _cairo_fixed_from_int (ty);
 
     if (clip->num_boxes) {
-	copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
-	if (unlikely (copy->boxes == NULL))
-	    return _cairo_clip_set_all_clipped (copy);
+	if (clip->num_boxes == 1) {
+	    copy->boxes = &copy->embedded_box;
+	} else {
+	    copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+	    if (unlikely (copy->boxes == NULL))
+		return _cairo_clip_set_all_clipped (copy);
+	}
 
 	for (i = 0; i < clip->num_boxes; i++) {
 	    copy->boxes[i].p1.x = clip->boxes[i].p1.x + fx;
commit 926287aeeae8e96d96cdc18c829eef6430c270db
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jul 23 22:57:48 2011 +0100

    surface-wrapper: Fix use of uninitialised variable
    
    Introduced recently in a30a7402f73485dabdb6a016178247f9844017a1,
    
    ==32234== Conditional jump or move depends on uninitialised value(s)
    ==32234==    at 0x6BCA326: _cairo_surface_wrapper_needs_device_transform (cairo-surface-wrapper.c:549)
    ==32234==    by 0x6BCB47D: _cairo_surface_wrapper_set_inverse_transform (cairo-surface-wrapper.c:579)
    ==32234==    by 0x6BCB55A: _cairo_surface_wrapper_init (cairo-surface-wrapper.c:621)
    ==32234==    by 0x6BB87A6: _cairo_recording_surface_replay_internal (cairo-recording-surface.c:854)
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index 8dc40f8..5684a14 100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -618,10 +618,10 @@ void
 _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
 			     cairo_surface_t *target)
 {
-    _cairo_surface_wrapper_set_inverse_transform (wrapper, NULL);
-
     wrapper->target = cairo_surface_reference (target);
+    cairo_matrix_init_identity (&wrapper->transform);
     wrapper->has_extents = FALSE;
+
     wrapper->needs_transform =
 	! _cairo_matrix_is_identity (&wrapper->target->device_transform);
 }
commit 7f77e2f36a0803e3ec08bc70f4923bb2d043658e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jul 23 22:48:15 2011 +0100

    trace: Create a new opcode for recording surface
    
    During replay we want to handle recording surfaces specially, and not
    redirect the creation of those to the target surface. This is similar to
    the need to keep image surfaces as images during replay.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index f5a9bf1..ef96e44 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -278,6 +278,24 @@ _csi_ostack_get_number (csi_t *ctx, unsigned int i, double *out)
     return CSI_STATUS_SUCCESS;
 }
 
+static double
+_csi_object_as_real (csi_object_t *obj)
+{
+    int type;
+
+    type = csi_object_get_type (obj);
+    switch (type) {
+    case CSI_OBJECT_TYPE_BOOLEAN:
+	return obj->datum.boolean;
+    case CSI_OBJECT_TYPE_INTEGER:
+	return obj->datum.integer;
+    case CSI_OBJECT_TYPE_REAL:
+	return obj->datum.real;
+    default:
+	return 0;
+    }
+}
+
 static csi_status_t
 _csi_ostack_get_name (csi_t *ctx, unsigned int i, csi_name_t *out)
 {
@@ -5947,6 +5965,51 @@ _surface (csi_t *ctx)
 }
 
 static csi_status_t
+_record (csi_t *ctx)
+{
+    csi_object_t obj;
+    long content;
+    csi_array_t *array;
+    csi_status_t status;
+    cairo_rectangle_t extents;
+    cairo_rectangle_t *r;
+
+    check (2);
+
+    status = _csi_ostack_get_array (ctx, 0, &array);
+    if (_csi_unlikely (status))
+	return status;
+
+    status = _csi_ostack_get_integer (ctx, 1, &content);
+    if (_csi_unlikely (status))
+	return status;
+
+    switch (array->stack.len) {
+    case 0:
+	r = NULL;
+    case 2:
+	extents.x = extents.y = 0;
+	extents.width = _csi_object_as_real (&array->stack.objects[0]);
+	extents.height = _csi_object_as_real (&array->stack.objects[1]);
+	break;
+    case 4:
+	extents.x = _csi_object_as_real (&array->stack.objects[0]);
+	extents.y = _csi_object_as_real (&array->stack.objects[1]);
+	extents.width = _csi_object_as_real (&array->stack.objects[2]);
+	extents.height = _csi_object_as_real (&array->stack.objects[3]);
+	r = &extents;
+	break;
+    default:
+	return _csi_error (CSI_STATUS_INVALID_SCRIPT);
+    }
+
+    obj.type = CSI_OBJECT_TYPE_SURFACE;
+    obj.datum.surface = cairo_recording_surface_create (content, r);
+    pop (2);
+    return push (&obj);
+}
+
+static csi_status_t
 _text_path (csi_t *ctx)
 {
     csi_status_t status;
@@ -6270,6 +6333,7 @@ _defs[] = {
     { "push-group", _push_group },
     { "radial", _radial },
     { "rand", NULL },
+    { "record", _record },
     { "rectangle", _rectangle },
     { "repeat", _repeat },
     { "restore", _restore },
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 3470c88..9c59b1d 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -4836,11 +4836,7 @@ cairo_recording_surface_create (cairo_content_t content,
 	Object *obj = _create_surface (ret);
 
 	if (extents) {
-	    _trace_printf ("dict\n"
-			   "  /type /recording set\n"
-			   "  /content //%s set\n"
-			   "  /extents [%f %f %f %f] set\n"
-			   "  surface dup /s%ld exch def\n",
+	    _trace_printf ("//%s [ %f %f %f %f ] record dup /s%ld exch def\n",
 			   _content_to_string (content),
 			   extents->x, extents->y,
 			   extents->width, extents->height,
@@ -4848,10 +4844,7 @@ cairo_recording_surface_create (cairo_content_t content,
 	    obj->width = extents->width;
 	    obj->height = extents->height;
 	} else {
-	    _trace_printf ("dict\n"
-			   "  /type /recording set\n"
-			   "  /content //%s set\n"
-			   "  surface dup /s%ld exch def\n",
+	    _trace_printf ("//%s [ ] record dup /s%ld exch def\n",
 			   _content_to_string (content),
 			   obj->token);
 	}


More information about the cairo-commit mailing list