[cairo-commit] 2 commits - src/cairoint.h src/cairo-pattern.c

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Mar 14 14:25:50 PDT 2007


 src/cairo-pattern.c |   82 +++++++++++++++++++++++++++++++++++++++-------------
 src/cairoint.h      |    4 +-
 2 files changed, 65 insertions(+), 21 deletions(-)

New commits:
diff-tree e803e2e69ba02a1db316c97eb9a8d386709380e2 (from 4514fdca1ba0f3922c2797744f4b0d42d37f8b42)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Mar 14 17:23:57 2007 -0400

    [cairo-pattern] Add a cache of two color stops to cairo_gradient_pattern_t
    
    Most of gradients have only two color stops.  This avoids
    calling malloc() for those cases.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 7aef3c7..f076259 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -117,7 +117,9 @@ _cairo_gradient_pattern_init_copy (cairo
 	*dst = *src;
     }
 
-    if (other->n_stops)
+    if (other->stops == other->stops_embedded)
+	pattern->stops = pattern->stops_embedded;
+    else if (other->stops)
     {
 	pattern->stops = malloc (other->stops_size *
 				 sizeof (pixman_gradient_stop_t));
@@ -187,7 +189,7 @@ _cairo_pattern_fini (cairo_pattern_t *pa
 	cairo_gradient_pattern_t *gradient =
 	    (cairo_gradient_pattern_t *) pattern;
 
-	if (gradient->stops)
+	if (gradient->stops && gradient->stops != gradient->stops_embedded)
 	    free (gradient->stops);
     } break;
     }
@@ -657,11 +659,26 @@ _cairo_pattern_gradient_grow (cairo_grad
 {
     pixman_gradient_stop_t *new_stops;
     int old_size = pattern->stops_size;
-    int new_size = old_size ? 2 * old_size : 8;
+    int embedded_size = sizeof (pattern->stops_embedded) / sizeof (pattern->stops_embedded[0]);
+    int new_size = 2 * MAX (old_size, 4);
+
+    /* we have a local buffer at pattern->stops_embedded.  try to fulfill the request
+     * from there. */
+    if (old_size < embedded_size) {
+	pattern->stops = pattern->stops_embedded;
+	pattern->stops_size = embedded_size;
+	return CAIRO_STATUS_SUCCESS;
+    }
 
     assert (pattern->n_stops <= pattern->stops_size);
 
-    new_stops = realloc (pattern->stops, new_size *  sizeof (pixman_gradient_stop_t));
+    if (pattern->stops == pattern->stops_embedded) {
+	new_stops = malloc (new_size * sizeof (pixman_gradient_stop_t));
+	if (new_stops)
+	    memcpy (new_stops, pattern->stops, old_size * sizeof (pixman_gradient_stop_t));
+    } else {
+	new_stops = realloc (pattern->stops, new_size * sizeof (pixman_gradient_stop_t));
+    }
 
     if (new_stops == NULL) {
 	return CAIRO_STATUS_NO_MEMORY;
diff --git a/src/cairoint.h b/src/cairoint.h
index ea690f2..17f8187 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1181,6 +1181,7 @@ typedef struct _cairo_gradient_pattern {
     unsigned int	    n_stops;
     unsigned int	    stops_size;
     pixman_gradient_stop_t *stops;
+    pixman_gradient_stop_t  stops_embedded[2];
 } cairo_gradient_pattern_t;
 
 typedef struct _cairo_linear_pattern {
diff-tree 4514fdca1ba0f3922c2797744f4b0d42d37f8b42 (from e878f2259b2512f0411d698bf078fe91b7373246)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Mar 13 20:49:52 2007 -0400

    [cairo-pattern] Grow color-stops array exponentially

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 7cd033c..7aef3c7 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -119,9 +119,11 @@ _cairo_gradient_pattern_init_copy (cairo
 
     if (other->n_stops)
     {
-	pattern->stops = malloc (other->n_stops *
+	pattern->stops = malloc (other->stops_size *
 				 sizeof (pixman_gradient_stop_t));
 	if (pattern->stops == NULL) {
+	    pattern->stops_size = 0;
+	    pattern->n_stops = 0;
 	    _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
 	    return;
 	}
@@ -221,8 +223,9 @@ _cairo_pattern_init_gradient (cairo_grad
 {
     _cairo_pattern_init (&pattern->base, type);
 
-    pattern->stops   = NULL;
-    pattern->n_stops = 0;
+    pattern->n_stops    = 0;
+    pattern->stops_size = 0;
+    pattern->stops      = NULL;
 }
 
 void
@@ -648,6 +651,28 @@ cairo_pattern_set_user_data (cairo_patte
 					    key, user_data, destroy);
 }
 
+/* make room for at least one more color stop */
+static cairo_status_t
+_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
+{
+    pixman_gradient_stop_t *new_stops;
+    int old_size = pattern->stops_size;
+    int new_size = old_size ? 2 * old_size : 8;
+
+    assert (pattern->n_stops <= pattern->stops_size);
+
+    new_stops = realloc (pattern->stops, new_size *  sizeof (pixman_gradient_stop_t));
+
+    if (new_stops == NULL) {
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    pattern->stops = new_stops;
+    pattern->stops_size = new_size;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static void
 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
 			       double			 offset,
@@ -656,38 +681,38 @@ _cairo_pattern_add_color_stop (cairo_gra
 			       double			 blue,
 			       double			 alpha)
 {
-    pixman_gradient_stop_t *new_stops;
+    pixman_gradient_stop_t *stops;
     cairo_fixed_t	   x;
     unsigned int	   i;
 
-    new_stops = realloc (pattern->stops, (pattern->n_stops + 1) *
-			 sizeof (pixman_gradient_stop_t));
-    if (new_stops == NULL)
-    {
-	_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
-	return;
+    if (pattern->n_stops >= pattern->stops_size) {
+        cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
+	if (status) {
+	    _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
+	    return;
+	}
     }
 
-    pattern->stops = new_stops;
+    stops = pattern->stops;
 
     x = _cairo_fixed_from_double (offset);
     for (i = 0; i < pattern->n_stops; i++)
     {
-	if (x < new_stops[i].x)
+	if (x < stops[i].x)
 	{
-	    memmove (&new_stops[i + 1], &new_stops[i],
+	    memmove (&stops[i + 1], &stops[i],
 		     sizeof (pixman_gradient_stop_t) * (pattern->n_stops - i));
 
 	    break;
 	}
     }
 
-    new_stops[i].x = x;
+    stops[i].x = x;
 
-    new_stops[i].color.red   = _cairo_color_double_to_short (red);
-    new_stops[i].color.green = _cairo_color_double_to_short (green);
-    new_stops[i].color.blue  = _cairo_color_double_to_short (blue);
-    new_stops[i].color.alpha = _cairo_color_double_to_short (alpha);
+    stops[i].color.red   = _cairo_color_double_to_short (red);
+    stops[i].color.green = _cairo_color_double_to_short (green);
+    stops[i].color.blue  = _cairo_color_double_to_short (blue);
+    stops[i].color.alpha = _cairo_color_double_to_short (alpha);
 
     pattern->n_stops++;
 }
diff --git a/src/cairoint.h b/src/cairoint.h
index c31f1dc..ea690f2 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1178,8 +1178,9 @@ typedef struct _cairo_surface_pattern {
 typedef struct _cairo_gradient_pattern {
     cairo_pattern_t base;
 
+    unsigned int	    n_stops;
+    unsigned int	    stops_size;
     pixman_gradient_stop_t *stops;
-    unsigned int	   n_stops;
 } cairo_gradient_pattern_t;
 
 typedef struct _cairo_linear_pattern {


More information about the cairo-commit mailing list