[cairo-commit] 8 commits - perf/box-outline.c perf/cairo-perf.c perf/cairo-perf.h perf/composite-checker.c perf/dragon.c perf/fill.c perf/intersections.c perf/long-dashed-lines.c perf/long-lines.c perf/mosaic.c perf/paint.c perf/paint-with-alpha.c perf/pattern_create_radial.c perf/pythagoras-tree.c perf/rectangles.c perf/rounded-rectangles.c perf/spiral.c perf/stroke.c perf/subimage_copy.c perf/tessellate.c perf/text.c perf/twin.c perf/unaligned-clip.c perf/world-map.c perf/zrusin.c src/cairo-array.c src/cairo.c src/cairoint.h src/cairo-misc.c src/cairo-path.c src/cairo-pattern.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-surface-private.h test/fallback-resolution.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Feb 13 05:35:24 PST 2009


 perf/box-outline.c           |    3 +
 perf/cairo-perf.c            |   34 +++++++++++--------
 perf/cairo-perf.h            |    4 ++
 perf/composite-checker.c     |    3 +
 perf/dragon.c                |    3 +
 perf/fill.c                  |    3 +
 perf/intersections.c         |    3 +
 perf/long-dashed-lines.c     |    3 +
 perf/long-lines.c            |    3 +
 perf/mosaic.c                |    3 +
 perf/paint-with-alpha.c      |    3 +
 perf/paint.c                 |    3 +
 perf/pattern_create_radial.c |    3 +
 perf/pythagoras-tree.c       |    3 +
 perf/rectangles.c            |    3 +
 perf/rounded-rectangles.c    |    3 +
 perf/spiral.c                |    3 +
 perf/stroke.c                |    3 +
 perf/subimage_copy.c         |    3 +
 perf/tessellate.c            |    3 +
 perf/text.c                  |   10 +++--
 perf/twin.c                  |    3 +
 perf/unaligned-clip.c        |    3 +
 perf/world-map.c             |    3 +
 perf/zrusin.c                |    3 +
 src/cairo-array.c            |   36 ++++++++++++++++++++
 src/cairo-misc.c             |    9 -----
 src/cairo-path.c             |   76 ++++++++++++++++++++++++++++++++-----------
 src/cairo-pattern.c          |   32 +++++++++---------
 src/cairo-surface-fallback.c |   28 +--------------
 src/cairo-surface-private.h  |    1 
 src/cairo-surface.c          |   72 +++++++++++++++++++++++++++-------------
 src/cairo.c                  |   14 ++++---
 src/cairoint.h               |   27 +++++++++++++--
 test/fallback-resolution.c   |    2 +
 35 files changed, 291 insertions(+), 120 deletions(-)

New commits:
commit 655f6987334b991763a5ab7746dbfd73c6b05f3e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 6 20:11:17 2009 +0000

    [perf] Split can_run? into a separate precondition.
    
    Allow tests to skip unnecessary setup when pruning the list of perf cases.

diff --git a/perf/box-outline.c b/perf/box-outline.c
index 74dd19a..2d826e6 100644
--- a/perf/box-outline.c
+++ b/perf/box-outline.c
@@ -88,6 +88,9 @@ box_outline_fill (cairo_t *cr, int width, int height)
 void
 box_outline (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "box-outline"))
+	return;
+
     cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke);
     cairo_perf_run (perf, "box-outline-fill", box_outline_fill);
 }
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index ad7da0a..efe6e8d 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -141,6 +141,22 @@ cairo_perf_has_similar (cairo_perf_t *perf)
     return TRUE;
 }
 
+cairo_bool_t
+cairo_perf_can_run (cairo_perf_t	*perf,
+		    const char		*name)
+{
+    unsigned int i;
+
+    if (perf->num_names == 0)
+	return TRUE;
+
+    for (i = 0; i < perf->num_names; i++)
+	if (strstr (name, perf->names[i]))
+	    return TRUE;
+
+    return FALSE;
+}
+
 void
 cairo_perf_run (cairo_perf_t		*perf,
 		const char		*name,
@@ -152,14 +168,6 @@ cairo_perf_run (cairo_perf_t		*perf,
     cairo_stats_t stats = {0.0, 0.0};
     int low_std_dev_count;
 
-    if (perf->num_names) {
-	for (i = 0; i < perf->num_names; i++)
-	    if (strstr (name, perf->names[i]))
-		goto NAME_FOUND;
-	return;
-    }
-  NAME_FOUND:
-
     if (perf->list_only) {
 	printf ("%s\n", name);
 	return;
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 8c44c9a..7e792ad 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -89,6 +89,10 @@ typedef struct _cairo_perf {
 typedef cairo_perf_ticks_t
 (*cairo_perf_func_t) (cairo_t *cr, int width, int height);
 
+cairo_bool_t
+cairo_perf_can_run (cairo_perf_t	*perf,
+		    const char		*name);
+
 void
 cairo_perf_run (cairo_perf_t		*perf,
 		const char		*name,
diff --git a/perf/composite-checker.c b/perf/composite-checker.c
index 69f48a0..e978990 100644
--- a/perf/composite-checker.c
+++ b/perf/composite-checker.c
@@ -81,6 +81,9 @@ composite_checker (cairo_perf_t *perf,
 {
     cairo_surface_t *image;
 
+    if (! cairo_perf_can_run (perf, "composite-checker"))
+	return;
+
     /* Create the checker pattern. We don't actually need to draw
      * anything on it since that wouldn't affect performance.
      */
diff --git a/perf/dragon.c b/perf/dragon.c
index a6167cb..1866c9a 100644
--- a/perf/dragon.c
+++ b/perf/dragon.c
@@ -201,6 +201,9 @@ do_dragon_solid (cairo_t *cr, int width, int height)
 void
 dragon (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "dragon"))
+	return;
+
     cairo_perf_run (perf, "dragon-solid", do_dragon_solid);
     cairo_perf_run (perf, "dragon", do_dragon);
 }
diff --git a/perf/fill.c b/perf/fill.c
index 2a41355..6ebe70e 100644
--- a/perf/fill.c
+++ b/perf/fill.c
@@ -45,5 +45,8 @@ do_fill (cairo_t *cr, int width, int height)
 void
 fill (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "fill"))
+	return;
+
     cairo_perf_cover_sources_and_operators (perf, "fill", do_fill);
 }
diff --git a/perf/intersections.c b/perf/intersections.c
index 5e41036..347c4a5 100644
--- a/perf/intersections.c
+++ b/perf/intersections.c
@@ -92,6 +92,9 @@ random_nz (cairo_t *cr, int width, int height)
 void
 intersections (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "intersections"))
+	return;
+
     cairo_perf_run (perf, "intersections-nz-fill", random_nz);
     cairo_perf_run (perf, "intersections-eo-fill", random_eo);
 }
diff --git a/perf/long-dashed-lines.c b/perf/long-dashed-lines.c
index 31ddfe6..3520a19 100644
--- a/perf/long-dashed-lines.c
+++ b/perf/long-dashed-lines.c
@@ -63,5 +63,8 @@ do_long_dashed_lines (cairo_t *cr, int width, int height)
 void
 long_dashed_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "long-dashed-lines"))
+	return;
+
     cairo_perf_run (perf, "long-dashed-lines", do_long_dashed_lines);
 }
diff --git a/perf/long-lines.c b/perf/long-lines.c
index 62e8e16..0359201 100644
--- a/perf/long-lines.c
+++ b/perf/long-lines.c
@@ -112,6 +112,9 @@ long_lines_cropped (cairo_t *cr, int width, int height)
 void
 long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "long-lines"))
+	return;
+
     cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
     cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
 }
diff --git a/perf/mosaic.c b/perf/mosaic.c
index 7172a9d..257a362 100644
--- a/perf/mosaic.c
+++ b/perf/mosaic.c
@@ -161,6 +161,9 @@ mosaic_tessellate_curves (cairo_t *cr, int width, int height)
 void
 mosaic (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "mosaic"))
+	return;
+
     cairo_perf_run (perf, "mosaic_fill_curves", mosaic_fill_curves);
     cairo_perf_run (perf, "mosaic_fill_lines", mosaic_fill_lines);
     cairo_perf_run (perf, "mosaic_tessellate_curves", mosaic_tessellate_curves);
diff --git a/perf/paint-with-alpha.c b/perf/paint-with-alpha.c
index d4d860e..6ffe8bb 100644
--- a/perf/paint-with-alpha.c
+++ b/perf/paint-with-alpha.c
@@ -40,6 +40,9 @@ do_paint_with_alpha (cairo_t *cr, int width, int height)
 void
 paint_with_alpha (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "paint-with-alpha"))
+	return;
+
     cairo_perf_cover_sources_and_operators (perf, "paint-with-alpha",
 					    do_paint_with_alpha);
 }
diff --git a/perf/paint.c b/perf/paint.c
index 6f75016..a60d132 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -40,5 +40,8 @@ do_paint (cairo_t *cr, int width, int height)
 void
 paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "paint"))
+	return;
+
     cairo_perf_cover_sources_and_operators (perf, "paint", do_paint);
 }
diff --git a/perf/pattern_create_radial.c b/perf/pattern_create_radial.c
index 09f15a8..8fa683b 100644
--- a/perf/pattern_create_radial.c
+++ b/perf/pattern_create_radial.c
@@ -82,6 +82,9 @@ pattern_create_radial (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
     int i;
 
+    if (! cairo_perf_can_run (perf, "pattern_create_radial"))
+	return;
+
     srand (time (0));
     for (i = 0; i < RADIALS_COUNT; i++)
     {
diff --git a/perf/pythagoras-tree.c b/perf/pythagoras-tree.c
index 5a78d8a..750e83b 100644
--- a/perf/pythagoras-tree.c
+++ b/perf/pythagoras-tree.c
@@ -82,5 +82,8 @@ do_pythagoras_tree (cairo_t *cr, int width, int height)
 void
 pythagoras_tree (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "pythagoras_tree"))
+	return;
+
     cairo_perf_run (perf, "pythagoras_tree", do_pythagoras_tree);
 }
diff --git a/perf/rectangles.c b/perf/rectangles.c
index 374e364..c224968 100644
--- a/perf/rectangles.c
+++ b/perf/rectangles.c
@@ -96,6 +96,9 @@ rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
     int i;
 
+    if (! cairo_perf_can_run (perf, "rectangles"))
+	return;
+
     srand (8478232);
     for (i = 0; i < RECTANGLE_COUNT; i++)
     {
diff --git a/perf/rounded-rectangles.c b/perf/rounded-rectangles.c
index 7d20825..25133f3 100644
--- a/perf/rounded-rectangles.c
+++ b/perf/rounded-rectangles.c
@@ -98,6 +98,9 @@ rounded_rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
     int i;
 
+    if (! cairo_perf_can_run (perf, "rounded-rectangles"))
+	return;
+
     srand (8478232);
     for (i = 0; i < RECTANGLE_COUNT; i++) {
         rects[i].x = rand () % width;
diff --git a/perf/spiral.c b/perf/spiral.c
index f26d0a2..fb2af61 100644
--- a/perf/spiral.c
+++ b/perf/spiral.c
@@ -189,6 +189,9 @@ draw_spiral_nz_na_di (cairo_t *cr, int width, int height)
 void
 spiral (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "spiral"))
+	return;
+
     cairo_perf_run (perf, "spiral-diag-nonalign-evenodd-fill", draw_spiral_eo_na_di);
     cairo_perf_run (perf, "spiral-diag-nonalign-nonzero-fill", draw_spiral_nz_na_di);
     cairo_perf_run (perf, "spiral-diag-pixalign-evenodd-fill", draw_spiral_eo_pa_di);
diff --git a/perf/stroke.c b/perf/stroke.c
index 0b4ea8e..7b3990d 100644
--- a/perf/stroke.c
+++ b/perf/stroke.c
@@ -47,5 +47,8 @@ do_stroke (cairo_t *cr, int width, int height)
 void
 stroke (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "stroke"))
+	return;
+
     cairo_perf_cover_sources_and_operators (perf, "stroke", do_stroke);
 }
diff --git a/perf/subimage_copy.c b/perf/subimage_copy.c
index 54f596f..722705b 100644
--- a/perf/subimage_copy.c
+++ b/perf/subimage_copy.c
@@ -55,6 +55,9 @@ subimage_copy (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     cairo_surface_t *image;
     cairo_t *cr2;
 
+    if (! cairo_perf_can_run (perf, "subimage_copy"))
+	return;
+
     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
     cairo_paint (cr);
 
diff --git a/perf/tessellate.c b/perf/tessellate.c
index fc97db7..4af3841 100644
--- a/perf/tessellate.c
+++ b/perf/tessellate.c
@@ -143,6 +143,9 @@ tessellate_256 (cairo_t *cr, int width, int height)
 void
 tessellate (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "tessellate"))
+	return;
+
     cairo_perf_run (perf, "tessellate-16", tessellate_16);
     cairo_perf_run (perf, "tessellate-64", tessellate_64);
     cairo_perf_run (perf, "tessellate-256", tessellate_256);
diff --git a/perf/text.c b/perf/text.c
index 7aba1f9..4448802 100644
--- a/perf/text.c
+++ b/perf/text.c
@@ -56,5 +56,8 @@ do_text (cairo_t *cr, int width, int height)
 void
 text (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "text"))
+	return;
+
     cairo_perf_cover_sources_and_operators (perf, "text", do_text);
 }
diff --git a/perf/twin.c b/perf/twin.c
index 84ac759..f65cccf 100644
--- a/perf/twin.c
+++ b/perf/twin.c
@@ -46,5 +46,8 @@ twin (cairo_perf_t *perf,
       int           width,
       int           height)
 {
+    if (! cairo_perf_can_run (perf, "twin"))
+	return;
+
     cairo_perf_run (perf, "twin", do_twin);
 }
diff --git a/perf/unaligned-clip.c b/perf/unaligned-clip.c
index 6d2b179..a757fa6 100644
--- a/perf/unaligned-clip.c
+++ b/perf/unaligned-clip.c
@@ -59,5 +59,8 @@ do_unaligned_clip (cairo_t *cr, int width, int height)
 void
 unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "unaligned-clip"))
+	return;
+
     cairo_perf_run (perf, "unaligned_clip", do_unaligned_clip);
 }
diff --git a/perf/world-map.c b/perf/world-map.c
index fe6d42d..5b8be45 100644
--- a/perf/world-map.c
+++ b/perf/world-map.c
@@ -105,5 +105,8 @@ do_world_map (cairo_t *cr, int width, int height)
 void
 world_map (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "world_map"))
+	return;
+
     cairo_perf_run (perf, "world_map", do_world_map);
 }
diff --git a/perf/zrusin.c b/perf/zrusin.c
index 6840775..2195615 100644
--- a/perf/zrusin.c
+++ b/perf/zrusin.c
@@ -85,6 +85,9 @@ zrusin_another_fill (cairo_t *cr, int width, int height)
 void
 zrusin (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
+    if (! cairo_perf_can_run (perf, "zrusin"))
+	return;
+
     cairo_perf_run (perf, "zrusin_another_tessellate", zrusin_another_tessellate);
     cairo_perf_run (perf, "zrusin_another_fill", zrusin_another_fill);
 }
commit 798581a1b5a8a56ce9d16c5b21eab82851061732
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 30 22:12:49 2009 +0000

    [perf] Extend range of testing.
    
    Primarily to test longer glyph runs, but also test large upper bounds for
    strokes and fills.

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 6bb48f1..ad7da0a 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -444,11 +444,11 @@ main (int argc, char *argv[])
 }
 
 const cairo_perf_case_t perf_cases[] = {
-    { paint,  256, 512},
-    { paint_with_alpha,  256, 512},
-    { fill,   64, 256},
-    { stroke, 64, 256},
-    { text,   64, 256},
+    { paint,  64, 512},
+    { paint_with_alpha,  64, 512},
+    { fill,   64, 512},
+    { stroke, 64, 512},
+    { text,   64, 512},
     { tessellate, 100, 100},
     { subimage_copy, 16, 512},
     { pattern_create_radial, 16, 16},
commit 1522fac5c71708fc9e98e03da9f51926c1e3769c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Feb 3 17:18:53 2009 +0000

    [perf] Fix infinite loop in text
    
    The row would wrap-around with the character index, causing an infinite
    loop when trying to fill a window of size 512x512 and above.

diff --git a/perf/text.c b/perf/text.c
index efe7d91..7aba1f9 100644
--- a/perf/text.c
+++ b/perf/text.c
@@ -31,21 +31,20 @@ do_text (cairo_t *cr, int width, int height)
     const char text[] = "the jay, pig, fox, zebra and my wolves quack";
     int len = strlen (text);
     double x, y;
-    int i = 0;
+    int i = 0, j = 0;
 
     cairo_perf_timer_start ();
 
     cairo_set_font_size (cr, 9);
     do {
-	cairo_move_to (cr, 0, i * 10);
+	cairo_move_to (cr, 0, j++ * 10);
 	cairo_show_text (cr, text + i);
 	cairo_get_current_point (cr, &x, &y);
 	while (x < width && cairo_status (cr) == CAIRO_STATUS_SUCCESS) {
 	    cairo_show_text (cr, text);
 	    cairo_get_current_point (cr, &x, &y);
 	}
-	i++;
-	if (i >= len)
+	if (++i >= len)
 	    i = 0;
     } while (y < height && cairo_status (cr) == CAIRO_STATUS_SUCCESS);
 
commit 187e3473512e40fa1d046783e797ec3a198b09b2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 13 13:09:32 2009 +0000

    [test] Free ref_name in fallback-resolution.
    
    Trivial leak of a few thousand bytes.

diff --git a/test/fallback-resolution.c b/test/fallback-resolution.c
index 7b1d313..eab7995 100644
--- a/test/fallback-resolution.c
+++ b/test/fallback-resolution.c
@@ -216,6 +216,7 @@ check_result (cairo_test_context_t *ctx,
 	cairo_surface_destroy (test_image);
 	free (png_name);
 	free (diff_name);
+	free (ref_name);
 	return FALSE;
     }
 
@@ -247,6 +248,7 @@ check_result (cairo_test_context_t *ctx,
     cairo_surface_destroy (diff_image);
     free (png_name);
     free (diff_name);
+    free (ref_name);
 
     return ret;
 }
commit 005436758c5679f76cc462841678fb93d6c7e0ac
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Feb 3 10:20:26 2009 +0000

    [path] Inline path ops during append_to_context()
    
    By inlining the operations, and most significantly, precomputing the
    combined user-to-backend matrix, we can achieve a speed up of over 50%,
    which is a noticeable performance boost in swfdec - where append-to-path
    accounts for over 35% [inclusive] of the time for a h/w accelerated
    backend.

diff --git a/src/cairo-path.c b/src/cairo-path.c
index 6572da9..d62843e 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -36,6 +36,7 @@
 
 #include "cairoint.h"
 
+#include "cairo-private.h"
 #include "cairo-path-private.h"
 #include "cairo-path-fixed-private.h"
 
@@ -441,43 +442,82 @@ cairo_status_t
 _cairo_path_append_to_context (const cairo_path_t	*path,
 			       cairo_t			*cr)
 {
-    int i;
-    cairo_path_data_t *p;
+    const cairo_path_data_t *p, *end;
+    cairo_fixed_t x1_fixed, y1_fixed;
+    cairo_fixed_t x2_fixed, y2_fixed;
+    cairo_fixed_t x3_fixed, y3_fixed;
+    cairo_matrix_t user_to_backend;
     cairo_status_t status;
+    double x, y;
+
+    user_to_backend = cr->gstate->ctm;
+    cairo_matrix_multiply (&user_to_backend,
+	                   &cr->gstate->target->device_transform,
+			   &user_to_backend);
 
-    for (i=0; i < path->num_data; i += path->data[i].header.length) {
-	p = &path->data[i];
+    end = &path->data[path->num_data];
+    for (p = &path->data[0]; p < end; p += p->header.length) {
 	switch (p->header.type) {
 	case CAIRO_PATH_MOVE_TO:
-	    if (p->header.length < 2)
+	    if (unlikely (p->header.length < 2))
 		return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
-	    cairo_move_to (cr,
-			   p[1].point.x, p[1].point.y);
+
+	    x = p[1].point.x, y = p[1].point.y;
+	    cairo_matrix_transform_point (&user_to_backend, &x, &y);
+	    x1_fixed = _cairo_fixed_from_double (x);
+	    y1_fixed = _cairo_fixed_from_double (y);
+
+	    status = _cairo_path_fixed_move_to (cr->path, x1_fixed, y1_fixed);
 	    break;
+
 	case CAIRO_PATH_LINE_TO:
-	    if (p->header.length < 2)
+	    if (unlikely (p->header.length < 2))
 		return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
-	    cairo_line_to (cr,
-			   p[1].point.x, p[1].point.y);
+
+	    x = p[1].point.x, y = p[1].point.y;
+	    cairo_matrix_transform_point (&user_to_backend, &x, &y);
+	    x1_fixed = _cairo_fixed_from_double (x);
+	    y1_fixed = _cairo_fixed_from_double (y);
+
+	    status = _cairo_path_fixed_line_to (cr->path, x1_fixed, y1_fixed);
 	    break;
+
 	case CAIRO_PATH_CURVE_TO:
-	    if (p->header.length < 4)
+	    if (unlikely (p->header.length < 4))
 		return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
-	    cairo_curve_to (cr,
-			    p[1].point.x, p[1].point.y,
-			    p[2].point.x, p[2].point.y,
-			    p[3].point.x, p[3].point.y);
+
+	    x = p[1].point.x, y = p[1].point.y;
+	    cairo_matrix_transform_point (&user_to_backend, &x, &y);
+	    x1_fixed = _cairo_fixed_from_double (x);
+	    y1_fixed = _cairo_fixed_from_double (y);
+
+	    x = p[2].point.x, y = p[2].point.y;
+	    cairo_matrix_transform_point (&user_to_backend, &x, &y);
+	    x2_fixed = _cairo_fixed_from_double (x);
+	    y2_fixed = _cairo_fixed_from_double (y);
+
+	    x = p[3].point.x, y = p[3].point.y;
+	    cairo_matrix_transform_point (&user_to_backend, &x, &y);
+	    x3_fixed = _cairo_fixed_from_double (x);
+	    y3_fixed = _cairo_fixed_from_double (y);
+
+	    status = _cairo_path_fixed_curve_to (cr->path,
+		                                 x1_fixed, y1_fixed,
+						 x2_fixed, y2_fixed,
+						 x3_fixed, y3_fixed);
 	    break;
+
 	case CAIRO_PATH_CLOSE_PATH:
-	    if (p->header.length < 1)
+	    if (unlikely (p->header.length < 1))
 		return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
-	    cairo_close_path (cr);
+
+	    status = _cairo_path_fixed_close_path (cr->path);
 	    break;
+
 	default:
 	    return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
 	}
 
-	status = cairo_status (cr);
 	if (unlikely (status))
 	    return status;
     }
commit d295942b9d4da3be3318cd5fe2d3b0b1fe005d11
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jan 31 00:56:45 2009 +0000

    Inline _cairo_restrict_value()
    
    This is one instance where the function call overhead dominated the
    function call in both time and size.

diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index 2ed1413..0c9db90 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -384,15 +384,6 @@ _cairo_operator_bounded_by_source (cairo_operator_t op)
 }
 
 
-void
-_cairo_restrict_value (double *value, double min, double max)
-{
-    if (*value < min)
-	*value = min;
-    else if (*value > max)
-	*value = max;
-}
-
 /* This function is identical to the C99 function lround(), except that it
  * performs arithmetic rounding (floor(d + .5) instead of away-from-zero rounding) and
  * has a valid input range of (INT_MIN, INT_MAX] instead of
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 9f367b5..e8b1b23 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -453,9 +453,9 @@ cairo_pattern_create_rgb (double red, double green, double blue)
 {
     cairo_color_t color;
 
-    _cairo_restrict_value (&red,   0.0, 1.0);
-    _cairo_restrict_value (&green, 0.0, 1.0);
-    _cairo_restrict_value (&blue,  0.0, 1.0);
+    red   = _cairo_restrict_value (red,   0.0, 1.0);
+    green = _cairo_restrict_value (green, 0.0, 1.0);
+    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
 
     _cairo_color_init_rgb (&color, red, green, blue);
 
@@ -492,10 +492,10 @@ cairo_pattern_create_rgba (double red, double green, double blue,
 {
     cairo_color_t color;
 
-    _cairo_restrict_value (&red,   0.0, 1.0);
-    _cairo_restrict_value (&green, 0.0, 1.0);
-    _cairo_restrict_value (&blue,  0.0, 1.0);
-    _cairo_restrict_value (&alpha, 0.0, 1.0);
+    red   = _cairo_restrict_value (red,   0.0, 1.0);
+    green = _cairo_restrict_value (green, 0.0, 1.0);
+    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
+    alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
 
     _cairo_color_init_rgba (&color, red, green, blue, alpha);
 
@@ -949,10 +949,10 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
 	return;
     }
 
-    _cairo_restrict_value (&offset, 0.0, 1.0);
-    _cairo_restrict_value (&red,    0.0, 1.0);
-    _cairo_restrict_value (&green,  0.0, 1.0);
-    _cairo_restrict_value (&blue,   0.0, 1.0);
+    offset = _cairo_restrict_value (offset, 0.0, 1.0);
+    red    = _cairo_restrict_value (red,    0.0, 1.0);
+    green  = _cairo_restrict_value (green,  0.0, 1.0);
+    blue   = _cairo_restrict_value (blue,   0.0, 1.0);
 
     _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
 				   offset, red, green, blue, 1.0);
@@ -1003,11 +1003,11 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
 	return;
     }
 
-    _cairo_restrict_value (&offset, 0.0, 1.0);
-    _cairo_restrict_value (&red,    0.0, 1.0);
-    _cairo_restrict_value (&green,  0.0, 1.0);
-    _cairo_restrict_value (&blue,   0.0, 1.0);
-    _cairo_restrict_value (&alpha,  0.0, 1.0);
+    offset = _cairo_restrict_value (offset, 0.0, 1.0);
+    red    = _cairo_restrict_value (red,    0.0, 1.0);
+    green  = _cairo_restrict_value (green,  0.0, 1.0);
+    blue   = _cairo_restrict_value (blue,   0.0, 1.0);
+    alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
 
     _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
 				   offset, red, green, blue, alpha);
diff --git a/src/cairo.c b/src/cairo.c
index 632fac5..4aa52f6 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -648,10 +648,10 @@ _current_source_matches_solid (cairo_t *cr,
     if (current->type != CAIRO_PATTERN_TYPE_SOLID)
 	return FALSE;
 
-    _cairo_restrict_value (&red,   0.0, 1.0);
-    _cairo_restrict_value (&green, 0.0, 1.0);
-    _cairo_restrict_value (&blue,  0.0, 1.0);
-    _cairo_restrict_value (&alpha, 0.0, 1.0);
+    red   = _cairo_restrict_value (red,   0.0, 1.0);
+    green = _cairo_restrict_value (green, 0.0, 1.0);
+    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
+    alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
 
     _cairo_color_init_rgba (&color, red, green, blue, alpha);
     return _cairo_color_equal (&color,
@@ -868,7 +868,8 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
     if (cr->status)
 	return;
 
-    _cairo_restrict_value (&tolerance, CAIRO_TOLERANCE_MINIMUM, tolerance);
+    if (tolerance < CAIRO_TOLERANCE_MINIMUM)
+	tolerance = CAIRO_TOLERANCE_MINIMUM;
 
     status = _cairo_gstate_set_tolerance (cr->gstate, tolerance);
     if (unlikely (status))
@@ -962,7 +963,8 @@ cairo_set_line_width (cairo_t *cr, double width)
     if (cr->status)
 	return;
 
-    _cairo_restrict_value (&width, 0.0, width);
+    if (width < 0.)
+	width = 0.;
 
     status = _cairo_gstate_set_line_width (cr->gstate, width);
     if (unlikely (status))
diff --git a/src/cairoint.h b/src/cairoint.h
index 21f0e49..1d6939f 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1032,8 +1032,17 @@ typedef struct _cairo_stroke_face {
 } cairo_stroke_face_t;
 
 /* cairo.c */
-cairo_private void
-_cairo_restrict_value (double *value, double min, double max);
+
+static inline double
+_cairo_restrict_value (double value, double min, double max)
+{
+    if (value < min)
+	return min;
+    else if (value > max)
+	return max;
+    else
+	return value;
+}
 
 /* C99 round() rounds to the nearest integral value with halfway cases rounded
  * away from 0. _cairo_round rounds halfway cases toward negative infinity.
commit cc8a09567ca034e7d95e2ef8a3ec833b12c9f87a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 13 13:23:50 2009 +0000

    [surface] Move the meta-data copy-on-snapshot to the generic layer.
    
    As pointed out by Paolo Bonzini, copying the meta data for a snapshot is
    common for all backends and so should be handled by the generic layer.

diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 9b33d11..7c38cbd 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1152,17 +1152,6 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
 	return _cairo_surface_create_in_error (status);
     }
 
-    status = _cairo_surface_copy_mime_data (snapshot, surface);
-    if (unlikely (status)) {
-	cairo_surface_destroy (snapshot);
-	return _cairo_surface_create_in_error (status);
-    }
-
-    snapshot->device_transform = surface->device_transform;
-    snapshot->device_transform_inverse = surface->device_transform_inverse;
-
-    snapshot->is_snapshot = TRUE;
-
     return snapshot;
 }
 
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 2afc6f6..7bb502b 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1399,16 +1399,40 @@ _cairo_surface_clone_similar (cairo_surface_t  *surface,
 cairo_surface_t *
 _cairo_surface_snapshot (cairo_surface_t *surface)
 {
+    cairo_surface_t *snapshot;
+    cairo_status_t status;
+
     if (surface->status)
 	return _cairo_surface_create_in_error (surface->status);
 
     if (surface->finished)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 
-    if (surface->backend->snapshot)
-	return surface->backend->snapshot (surface);
+    if (surface->is_snapshot)
+	return cairo_surface_reference (surface);
+
+    snapshot = NULL;
+    if (surface->backend->snapshot != NULL)
+	snapshot = surface->backend->snapshot (surface);
+
+    if (snapshot == NULL)
+	snapshot = _cairo_surface_fallback_snapshot (surface);
+
+    if (unlikely (snapshot->status))
+	return snapshot;
+
+    status = _cairo_surface_copy_mime_data (snapshot, surface);
+    if (unlikely (status)) {
+	cairo_surface_destroy (snapshot);
+	return _cairo_surface_create_in_error (status);
+    }
+
+    snapshot->device_transform = surface->device_transform;
+    snapshot->device_transform_inverse = surface->device_transform_inverse;
+
+    snapshot->is_snapshot = TRUE;
 
-    return _cairo_surface_fallback_snapshot (surface);
+    return snapshot;
 }
 
 /**
commit adaf70a93f4449e85997bcde531b76c9044758ea
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 13 12:56:46 2009 +0000

    [surface] Separate the mime-data from the user-data.
    
    Move the mime-data into its own array so that it cannot be confused with
    user-data and we do not need to hard-code the copy list during
    snapshotting. The copy-on-snapshotting code becomes far simpler and will
    accommodate all future mime-types.
    
    Keeping mime-data separate from user-data is important due to the
    principle of least surprise - the API is different and so it would be
    surprising if you queried for user-data and were returned an opaque
    mime-data pointer, and vice versa. (Note this should have been prevented
    by using interned strings, but conceptually it is cleaner to make the
    separation.) Also it aides in trimming the user data arrays which are
    linearly searched.
    
    Based on the original patch by Adrian Johnson:
    http://cgit.freedesktop.org/~ajohnson/cairo/commit/?h=metadata&id=37e607cc777523ad12a2d214708d79ecbca5b380

diff --git a/src/cairo-array.c b/src/cairo-array.c
index 9c084b9..70c1646 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -494,3 +494,39 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t     *array,
 
     return CAIRO_STATUS_SUCCESS;
 }
+
+cairo_status_t
+_cairo_user_data_array_copy (cairo_user_data_array_t	*dst,
+			     cairo_user_data_array_t	*src)
+{
+    /* discard any existing user-data */
+    if (dst->num_elements != 0) {
+	_cairo_user_data_array_fini (dst);
+	_cairo_user_data_array_init (dst);
+    }
+
+    if (src->num_elements == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    return _cairo_array_append_multiple (dst,
+					 _cairo_array_index (src, 0),
+					 src->num_elements);
+}
+
+void
+_cairo_user_data_array_foreach (cairo_user_data_array_t     *array,
+				void (*func) (void *key,
+					      void *elt,
+					      void *closure),
+				void *closure)
+{
+    cairo_user_data_slot_t *slots;
+    int i, num_slots;
+
+    num_slots = array->num_elements;
+    slots = _cairo_array_index (array, 0);
+    for (i = 0; i < num_slots; i++) {
+	if (slots[i].user_data != NULL)
+	    func (slots[i].key, slots[i].user_data, closure);
+    }
+}
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index bcbc984..9b33d11 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1121,12 +1121,6 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
     cairo_surface_pattern_t pattern;
     cairo_image_surface_t *image;
     void *image_extra;
-    const char *mime_types[] = {
-	CAIRO_MIME_TYPE_JPEG,
-	CAIRO_MIME_TYPE_PNG,
-	CAIRO_MIME_TYPE_JP2,
-	NULL
-    }, **mime_type;
 
     status = _cairo_surface_acquire_source_image (surface,
 						  &image, &image_extra);
@@ -1137,13 +1131,11 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
 					   image->width,
 					   image->height);
     if (cairo_surface_status (snapshot)) {
-	_cairo_surface_release_source_image (surface,
-					     image, image_extra);
+	_cairo_surface_release_source_image (surface, image, image_extra);
 	return snapshot;
     }
 
     _cairo_pattern_init_for_surface (&pattern, &image->base);
-
     status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
 			               &pattern.base,
 				       NULL,
@@ -1153,11 +1145,14 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
 				       0, 0,
 				       image->width,
 				       image->height);
-
     _cairo_pattern_fini (&pattern.base);
-    _cairo_surface_release_source_image (surface,
-					 image, image_extra);
+    _cairo_surface_release_source_image (surface, image, image_extra);
+    if (unlikely (status)) {
+	cairo_surface_destroy (snapshot);
+	return _cairo_surface_create_in_error (status);
+    }
 
+    status = _cairo_surface_copy_mime_data (snapshot, surface);
     if (unlikely (status)) {
 	cairo_surface_destroy (snapshot);
 	return _cairo_surface_create_in_error (status);
@@ -1166,14 +1161,6 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
     snapshot->device_transform = surface->device_transform;
     snapshot->device_transform_inverse = surface->device_transform_inverse;
 
-    for (mime_type = mime_types; *mime_type; mime_type++) {
-	status = _cairo_surface_copy_mime_data (snapshot, surface, *mime_type);
-	if (unlikely (status)) {
-	    cairo_surface_destroy (snapshot);
-	    return _cairo_surface_create_in_error (status);
-	}
-    }
-
     snapshot->is_snapshot = TRUE;
 
     return snapshot;
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index efd4365..12b38f0 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -57,6 +57,7 @@ struct _cairo_surface {
     cairo_status_t status;
     cairo_bool_t finished;
     cairo_user_data_array_t user_data;
+    cairo_user_data_array_t mime_data;
 
     cairo_matrix_t device_transform;
     cairo_matrix_t device_transform_inverse;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 3b1dfe2..2afc6f6 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -51,6 +51,7 @@ const cairo_surface_t name = {					\
     status,				/* status */		\
     FALSE,				/* finished */		\
     { 0, 0, 0, NULL, },			/* user_data */		\
+    { 0, 0, 0, NULL, },			/* mime_data */         \
     { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },   /* device_transform */	\
     { 1.0, 0.0,	0.0, 1.0, 0.0, 0.0 },	/* device_transform_inverse */	\
     0.0,				/* x_resolution */	\
@@ -194,6 +195,7 @@ _cairo_surface_init (cairo_surface_t			*surface,
     surface->finished = FALSE;
 
     _cairo_user_data_array_init (&surface->user_data);
+    _cairo_user_data_array_init (&surface->mime_data);
 
     cairo_matrix_init_identity (&surface->device_transform);
     cairo_matrix_init_identity (&surface->device_transform_inverse);
@@ -437,6 +439,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
 	cairo_surface_finish (surface);
 
     _cairo_user_data_array_fini (&surface->user_data);
+    _cairo_user_data_array_fini (&surface->mime_data);
 
     free (surface);
 }
@@ -459,6 +462,7 @@ _cairo_surface_reset (cairo_surface_t *surface)
     assert (CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count) == 1);
 
     _cairo_user_data_array_fini (&surface->user_data);
+    _cairo_user_data_array_fini (&surface->mime_data);
 
     if (surface->backend->reset != NULL) {
 	cairo_status_t status = surface->backend->reset (surface);
@@ -620,7 +624,7 @@ cairo_surface_get_mime_data (cairo_surface_t		*surface,
 	return;
     }
 
-    mime_data = _cairo_user_data_array_get_data (&surface->user_data,
+    mime_data = _cairo_user_data_array_get_data (&surface->mime_data,
 						 (cairo_user_data_key_t *) mime_type);
     if (mime_data == NULL)
 	return;
@@ -696,7 +700,7 @@ cairo_surface_set_mime_data (cairo_surface_t		*surface,
     } else
 	mime_data = NULL;
 
-    status = _cairo_user_data_array_set_data (&surface->user_data,
+    status = _cairo_user_data_array_set_data (&surface->mime_data,
 					      (cairo_user_data_key_t *) mime_type,
 					      mime_data,
 					      _cairo_mime_data_destroy);
@@ -711,13 +715,19 @@ cairo_surface_set_mime_data (cairo_surface_t		*surface,
 }
 slim_hidden_def (cairo_surface_set_mime_data);
 
+static void
+_cairo_mime_data_reference (void *key, void *elt, void *closure)
+{
+    cairo_mime_data_t *mime_data = elt;
+
+    _cairo_reference_count_inc (&mime_data->ref_count);
+}
+
 cairo_status_t
 _cairo_surface_copy_mime_data (cairo_surface_t *dst,
-			       cairo_surface_t *src,
-			       const char *mime_type)
+			       cairo_surface_t *src)
 {
     cairo_status_t status;
-    cairo_mime_data_t *mime_data;
 
     if (dst->status)
 	return dst->status;
@@ -725,25 +735,15 @@ _cairo_surface_copy_mime_data (cairo_surface_t *dst,
     if (src->status)
 	return _cairo_surface_set_error (dst, src->status);
 
-    status = _cairo_intern_string (&mime_type, -1);
+    /* first copy the mime-data, discarding any already set on dst */
+    status = _cairo_user_data_array_copy (&dst->mime_data, &src->mime_data);
     if (unlikely (status))
 	return _cairo_surface_set_error (dst, status);
 
-    mime_data = _cairo_user_data_array_get_data (&src->user_data,
-						 (cairo_user_data_key_t *) mime_type);
-    if (mime_data == NULL)
-	return CAIRO_STATUS_SUCCESS;
-
-    _cairo_reference_count_inc (&mime_data->ref_count);
-
-    status = _cairo_user_data_array_set_data (&dst->user_data,
-					      (cairo_user_data_key_t *) mime_type,
-					      mime_data,
-					      _cairo_mime_data_destroy);
-    if (unlikely (status)) {
-	_cairo_mime_data_destroy (mime_data);
-	return _cairo_surface_set_error (dst, status);
-    }
+    /* now increment the reference counters for the copies */
+    _cairo_user_data_array_foreach (&dst->mime_data,
+				    _cairo_mime_data_reference,
+				    NULL);
 
     return CAIRO_STATUS_SUCCESS;
 }
diff --git a/src/cairoint.h b/src/cairoint.h
index 99185b6..21f0e49 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -330,6 +330,17 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t     *array,
 				 void			     *user_data,
 				 cairo_destroy_func_t	      destroy);
 
+cairo_private cairo_status_t
+_cairo_user_data_array_copy (cairo_user_data_array_t	*dst,
+			     cairo_user_data_array_t	*src);
+
+cairo_private void
+_cairo_user_data_array_foreach (cairo_user_data_array_t     *array,
+				void (*func) (void *key,
+					      void *elt,
+					      void *closure),
+				void *closure);
+
 #define _CAIRO_HASH_INIT_VALUE 5381
 
 cairo_private unsigned long
@@ -1742,8 +1753,7 @@ _cairo_surface_create_in_error (cairo_status_t status);
 
 cairo_private cairo_status_t
 _cairo_surface_copy_mime_data (cairo_surface_t *dst,
-			       cairo_surface_t *src,
-			       const char *mime_type);
+			       cairo_surface_t *src);
 
 cairo_private cairo_status_t
 _cairo_surface_set_error (cairo_surface_t	*surface,


More information about the cairo-commit mailing list