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

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Mar 21 09:34:41 PDT 2007


 src/cairo-gstate.c  |   57 ++++++++++++++++++++++++++++++++++++++++++++++++----
 src/cairo-pattern.c |   19 +++++++++++++----
 src/cairo.c         |   32 +++++++++--------------------
 src/cairoint.h      |    8 +++----
 4 files changed, 82 insertions(+), 34 deletions(-)

New commits:
diff-tree bd275c19782700f2cfc6905f348e4d4b3f15d311 (from e76d3cfa4f06ba813528a018fa77ba4d210a44e3)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Mar 21 12:34:37 2007 -0400

    [cairo-pattern] Make sure cached solid patterns are not put in error status

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index beb95e8..920542c 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -270,6 +270,19 @@ static struct {
     int size;
 } solid_pattern_cache;
 
+static cairo_pattern_t *
+_cairo_pattern_create_solid_not_cached (const cairo_color_t *color)
+{
+    void *pattern;
+
+    /* Not cached, need to create a new pattern. */
+    pattern = malloc (sizeof (cairo_solid_pattern_t));
+    if (pattern != NULL)
+	_cairo_pattern_init_solid (pattern, color);
+
+    return pattern;
+}
+
 cairo_pattern_t *
 _cairo_pattern_create_solid (const cairo_color_t *color)
 {
@@ -290,12 +303,10 @@ _cairo_pattern_create_solid (const cairo
 	    goto DONE;
 
     /* Not cached, need to create a new pattern. */
-    pattern = malloc (sizeof (cairo_solid_pattern_t));
+    pattern = _cairo_pattern_create_solid_not_cached (color);
     if (pattern == NULL)
 	return (cairo_pattern_t *) &cairo_pattern_nil.base;
 
-    _cairo_pattern_init_solid (pattern, color);
-
     /* And insert it into the cache. */
     if (solid_pattern_cache.size < MAX_PATTERN_CACHE_SIZE) {
 	solid_pattern_cache.size ++;
@@ -337,7 +348,7 @@ _cairo_pattern_create_in_error (cairo_st
 {
     cairo_pattern_t *pattern;
 
-    pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK));
+    pattern = _cairo_pattern_create_solid_not_cached (_cairo_stock_color (CAIRO_STOCK_BLACK));
     if (cairo_pattern_status (pattern))
 	return pattern;
 
diff-tree e76d3cfa4f06ba813528a018fa77ba4d210a44e3 (from 1469ea22ba659ba7afa6892e9b6b2a3f26d0dddb)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Mar 21 12:33:31 2007 -0400

    [cairo-gstate] Make sure gstate->next is initialized

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index cc4f893..d639cfd 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -64,6 +64,8 @@ cairo_status_t
 _cairo_gstate_init (cairo_gstate_t  *gstate,
 		    cairo_surface_t *target)
 {
+    gstate->next = NULL;
+
     gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
 
     gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
@@ -95,8 +97,6 @@ _cairo_gstate_init (cairo_gstate_t  *gst
     if (gstate->source->status)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    gstate->next = NULL;
-
     return CAIRO_STATUS_SUCCESS;
 }
 
diff-tree 1469ea22ba659ba7afa6892e9b6b2a3f26d0dddb (from 5f83a1b542a1932a59299a45f36dff22268dca14)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Mar 21 11:22:33 2007 -0400

    [cairo-gstate] Move save/restore logic into gstate instead of cairo_t
    by adding _cairo_gstate_save/restore().  This is in preparation for
    adding copy-on-write behavior to gstate.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index b75a90b..cc4f893 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -175,7 +175,7 @@ _cairo_gstate_fini (cairo_gstate_t *gsta
     gstate->source = NULL;
 }
 
-void
+static void
 _cairo_gstate_destroy (cairo_gstate_t *gstate)
 {
     if (gstate == NULL)
@@ -197,7 +197,7 @@ _cairo_gstate_destroy (cairo_gstate_t *g
  * Return value: a new cairo_gstate_t or NULL if there is insufficient
  * memory.
  **/
-cairo_gstate_t*
+static cairo_gstate_t*
 _cairo_gstate_clone (cairo_gstate_t *other)
 {
     cairo_status_t status;
@@ -218,6 +218,55 @@ _cairo_gstate_clone (cairo_gstate_t *oth
     return gstate;
 }
 
+/**
+ * _cairo_gstate_save:
+ * @gstate: input/output gstate pointer
+ *
+ * Makes a copy of the current state of @gstate and saves it
+ * to @gstate->next, then put the address of the newly allcated
+ * copy into @gstate.  _cairo_gstate_restore() reverses this.
+ **/
+cairo_status_t
+_cairo_gstate_save (cairo_gstate_t **gstate)
+{
+    cairo_gstate_t *top;
+
+    top = _cairo_gstate_clone (*gstate);
+
+    if (top == NULL) {
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    top->next = *gstate;
+    *gstate = top;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * _cairo_gstate_restore:
+ * @gstate: input/output gstate pointer
+ *
+ * Reverses the effects of one _cairo_gstate_save() call.
+ **/
+cairo_status_t
+_cairo_gstate_restore (cairo_gstate_t **gstate)
+{
+    cairo_gstate_t *top;
+
+    top = *gstate;
+
+    if (top->next == NULL) {
+	return CAIRO_STATUS_INVALID_RESTORE;
+    }
+
+    *gstate = top->next;
+
+    _cairo_gstate_destroy (top);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_status_t
 _cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
 					 cairo_clip_path_t *cpath)
diff --git a/src/cairo.c b/src/cairo.c
index 21303de..2165045 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -260,10 +260,8 @@ cairo_destroy (cairo_t *cr)
 	return;
 
     while (cr->gstate != cr->gstate_tail) {
-	cairo_gstate_t *tmp = cr->gstate;
-	cr->gstate = tmp->next;
-
-	_cairo_gstate_destroy (tmp);
+	if (_cairo_gstate_restore (&cr->gstate))
+	    break;
     }
 
     _cairo_gstate_fini (cr->gstate);
@@ -368,20 +366,15 @@ cairo_get_reference_count (cairo_t *cr)
 void
 cairo_save (cairo_t *cr)
 {
-    cairo_gstate_t *top;
+    cairo_status_t status;
 
     if (cr->status)
 	return;
 
-    top = _cairo_gstate_clone (cr->gstate);
-
-    if (top == NULL) {
-	_cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);
-	return;
+    status = _cairo_gstate_save (&cr->gstate);
+    if (status) {
+	_cairo_set_error (cr, status);
     }
-
-    top->next = cr->gstate;
-    cr->gstate = top;
 }
 slim_hidden_def(cairo_save);
 
@@ -396,20 +389,15 @@ slim_hidden_def(cairo_save);
 void
 cairo_restore (cairo_t *cr)
 {
-    cairo_gstate_t *top;
+    cairo_status_t status;
 
     if (cr->status)
 	return;
 
-    if (cr->gstate == cr->gstate_tail) {
-	_cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);
-	return;
+    status = _cairo_gstate_restore (&cr->gstate);
+    if (status) {
+	_cairo_set_error (cr, status);
     }
-
-    top = cr->gstate;
-    cr->gstate = top->next;
-
-    _cairo_gstate_destroy (top);
 }
 slim_hidden_def(cairo_restore);
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 6e171e5..d54292e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1244,11 +1244,11 @@ _cairo_gstate_init (cairo_gstate_t  *gst
 cairo_private void
 _cairo_gstate_fini (cairo_gstate_t *gstate);
 
-cairo_private cairo_gstate_t *
-_cairo_gstate_clone (cairo_gstate_t *gstate);
+cairo_private cairo_status_t
+_cairo_gstate_save (cairo_gstate_t **gstate);
 
-cairo_private void
-_cairo_gstate_destroy (cairo_gstate_t *gstate);
+cairo_private cairo_status_t
+_cairo_gstate_restore (cairo_gstate_t **gstate);
 
 cairo_private cairo_bool_t
 _cairo_gstate_is_redirected (cairo_gstate_t *gstate);


More information about the cairo-commit mailing list