[cairo-commit] 7 commits - boilerplate/cairo-boilerplate.c perf/cairo-perf-trace.c src/cairo.c src/cairo-ft-font.c src/cairo-gstate.c src/cairoint.h src/cairo-pattern.c util/cairo-script

Chris Wilson ickle at kemper.freedesktop.org
Sat Jun 27 17:01:47 PDT 2009


 boilerplate/cairo-boilerplate.c              |    4 
 perf/cairo-perf-trace.c                      |    2 
 src/cairo-ft-font.c                          |   39 ++
 src/cairo-gstate.c                           |  184 +++---------
 src/cairo-pattern.c                          |   35 ++
 src/cairo.c                                  |  215 +++++++-------
 src/cairoint.h                               |    8 
 util/cairo-script/cairo-script-interpreter.c |   14 
 util/cairo-script/cairo-script-objects.c     |   46 ---
 util/cairo-script/cairo-script-private.h     |   51 ++-
 util/cairo-script/cairo-script-scanner.c     |  390 ++++++++++++---------------
 11 files changed, 462 insertions(+), 526 deletions(-)

New commits:
commit 2bbb69420289aa372512602db312611369e70f54
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jun 28 00:57:10 2009 +0100

    [test] Disable fallback16 testing
    
    Only use the RGB16_565 surface as a source during testing. We presume that
    pixman is itself rigorously tested and the output is equivalent to the
    image surface. Enabling this test surface would require too large of a
    burden to maintain the reference images for the 16-bit backend.

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index 0ab45ee..1b0fa29 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -319,7 +319,7 @@ static const cairo_boilerplate_target_t targets[] =
 	CAIRO_CONTENT_COLOR_ALPHA, 0,
 	_cairo_boilerplate_test_fallback16_create_surface,
 	NULL, NULL,
-	_cairo_boilerplate_get_image_surface,
+	NULL, /* _cairo_boilerplate_get_image_surface, */
 	cairo_surface_write_to_png
     },
     {
@@ -328,7 +328,7 @@ static const cairo_boilerplate_target_t targets[] =
 	CAIRO_CONTENT_COLOR, 0,
 	_cairo_boilerplate_test_fallback16_create_surface,
 	NULL, NULL,
-	_cairo_boilerplate_get_image_surface,
+	NULL, /* _cairo_boilerplate_get_image_surface, */
 	cairo_surface_write_to_png
     },
     {
commit 34ac8673b2d51edeb0b29a4949d7d16c3d07a790
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jun 28 00:48:05 2009 +0100

    [script] Use setjmp exception handling during scanning
    
    Save ~5% of overhead by using longjmp on error to terminate scanning
    instead of propagating the error, incurring lots of redundant error
    checks.

diff --git a/util/cairo-script/cairo-script-interpreter.c b/util/cairo-script/cairo-script-interpreter.c
index db26b00..16283e2 100644
--- a/util/cairo-script/cairo-script-interpreter.c
+++ b/util/cairo-script/cairo-script-interpreter.c
@@ -214,9 +214,7 @@ _add_operator (csi_t *ctx,
     if (status)
 	return status;
 
-    status = csi_operator_new (ctx, &operator, def->op);
-    if (status)
-	return status;
+    csi_operator_new (&operator, def->op);
 
     return csi_dictionary_put (ctx, dict, name.datum.name, &operator);
 }
@@ -234,9 +232,7 @@ _add_integer_constant (csi_t *ctx,
     if (status)
 	return status;
 
-    status = csi_integer_new (ctx, &constant, def->value);
-    if (status)
-	return status;
+    csi_integer_new (&constant, def->value);
 
     return csi_dictionary_put (ctx, dict, name.datum.name, &constant);
 }
@@ -254,9 +250,7 @@ _add_real_constant (csi_t *ctx,
     if (status)
 	return status;
 
-    status = csi_real_new (ctx, &constant, def->value);
-    if (status)
-	return status;
+    csi_real_new (&constant, def->value);
 
     return csi_dictionary_put (ctx, dict, name.datum.name, &constant);
 }
@@ -462,8 +456,6 @@ _csi_intern_string (csi_t *ctx, const char **str_inout, int len)
     csi_intern_string_t tmpl, *istring;
     csi_status_t status = CSI_STATUS_SUCCESS;
 
-    if (len < 0)
-	len = strlen (str);
     tmpl.hash_entry.hash = _intern_string_hash (str, len);
     tmpl.len = len;
     tmpl.string = (char *) str;
diff --git a/util/cairo-script/cairo-script-objects.c b/util/cairo-script/cairo-script-objects.c
index 4ff39ec..c48f720 100644
--- a/util/cairo-script/cairo-script-objects.c
+++ b/util/cairo-script/cairo-script-objects.c
@@ -181,17 +181,6 @@ csi_array_free (csi_t *ctx, csi_array_t *array)
 #endif
 }
 
-csi_status_t
-csi_boolean_new (csi_t *ctx,
-		 csi_object_t *obj,
-		 csi_boolean_t v)
-{
-    obj->type = CSI_OBJECT_TYPE_BOOLEAN;
-    obj->datum.boolean = v;
-
-    return CSI_STATUS_SUCCESS;
-}
-
 static cairo_bool_t
 _dictionary_name_equal (const void *_a, const void *_b)
 {
@@ -351,17 +340,6 @@ csi_dictionary_remove (csi_t *ctx,
 }
 
 csi_status_t
-csi_integer_new (csi_t *ctx,
-		 csi_object_t *obj,
-		 csi_integer_t v)
-{
-    obj->type = CSI_OBJECT_TYPE_INTEGER;
-    obj->datum.integer = v;
-
-    return CSI_STATUS_SUCCESS;
-}
-
-csi_status_t
 csi_matrix_new (csi_t *ctx,
 		csi_object_t *obj)
 {
@@ -486,7 +464,7 @@ csi_name_new_static (csi_t *ctx,
 {
     csi_status_t status;
 
-    status = _csi_intern_string (ctx, &str, -1);
+    status = _csi_intern_string (ctx, &str, strlen (str));
     if (_csi_unlikely (status))
 	return status;
 
@@ -497,28 +475,6 @@ csi_name_new_static (csi_t *ctx,
 }
 
 csi_status_t
-csi_operator_new (csi_t *ctx,
-		  csi_object_t *obj,
-		  csi_operator_t op)
-{
-    obj->type = CSI_OBJECT_TYPE_OPERATOR | CSI_OBJECT_ATTR_EXECUTABLE;
-    obj->datum.op = op;
-
-    return CSI_STATUS_SUCCESS;
-}
-
-csi_status_t
-csi_real_new (csi_t *ctx,
-	      csi_object_t *obj,
-	      csi_real_t v)
-{
-    obj->type = CSI_OBJECT_TYPE_REAL;
-    obj->datum.real = v;
-
-    return CSI_STATUS_SUCCESS;
-}
-
-csi_status_t
 csi_string_new (csi_t *ctx,
 		csi_object_t *obj,
 		const char *str,
diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h
index 96c2044..f09c69b 100644
--- a/util/cairo-script/cairo-script-private.h
+++ b/util/cairo-script/cairo-script-private.h
@@ -41,6 +41,8 @@
 
 #include "cairo-script-interpreter.h"
 
+#include <setjmp.h>
+
 #ifndef FALSE
 #define FALSE 0
 #endif
@@ -351,8 +353,6 @@ struct _csi_list {
 };
 
 struct _csi_buffer {
-    csi_status_t status;
-
     char *base, *ptr, *end;
     unsigned int size;
 };
@@ -423,7 +423,7 @@ union _csi_union_object {
 };
 
 struct _csi_scanner {
-    csi_status_t status;
+    jmp_buf jmpbuf;
 
     enum {
 	NONE,
@@ -650,10 +650,13 @@ csi_array_append (csi_t *ctx,
 csi_private void
 csi_array_free (csi_t *ctx, csi_array_t *array);
 
-csi_private csi_status_t
-csi_boolean_new (csi_t *ctx,
-		 csi_object_t *obj,
-		 csi_boolean_t v);
+static inline void
+csi_boolean_new (csi_object_t *obj,
+		 csi_boolean_t v)
+{
+    obj->type = CSI_OBJECT_TYPE_BOOLEAN;
+    obj->datum.boolean = v;
+}
 
 csi_private csi_status_t
 csi_dictionary_new (csi_t *ctx,
@@ -684,10 +687,14 @@ csi_private void
 csi_dictionary_free (csi_t *ctx,
 		     csi_dictionary_t *dict);
 
-csi_private csi_status_t
-csi_integer_new (csi_t *ctx,
-		 csi_object_t *obj,
-		 csi_integer_t v);
+static inline void
+csi_integer_new (csi_object_t *obj,
+		 csi_integer_t v)
+{
+    obj->type = CSI_OBJECT_TYPE_INTEGER;
+    obj->datum.integer = v;
+}
+
 
 csi_private csi_status_t
 csi_matrix_new (csi_t *ctx,
@@ -723,15 +730,21 @@ csi_name_new_static (csi_t *ctx,
 		     csi_object_t *obj,
 		     const char *str);
 
-csi_private csi_status_t
-csi_operator_new (csi_t *ctx,
-		  csi_object_t *obj,
-		  csi_operator_t op);
+static inline void
+csi_operator_new (csi_object_t *obj,
+		  csi_operator_t op)
+{
+    obj->type = CSI_OBJECT_TYPE_OPERATOR | CSI_OBJECT_ATTR_EXECUTABLE;
+    obj->datum.op = op;
+}
 
-csi_private csi_status_t
-csi_real_new (csi_t *ctx,
-	      csi_object_t *obj,
-	      csi_real_t v);
+static inline void
+csi_real_new (csi_object_t *obj,
+	      csi_real_t v)
+{
+    obj->type = CSI_OBJECT_TYPE_REAL;
+    obj->datum.real = v;
+}
 
 csi_private csi_status_t
 csi_string_new (csi_t *ctx,
diff --git a/util/cairo-script/cairo-script-scanner.c b/util/cairo-script/cairo-script-scanner.c
index 6ade97f..0c6a64d 100644
--- a/util/cairo-script/cairo-script-scanner.c
+++ b/util/cairo-script/cairo-script-scanner.c
@@ -57,99 +57,70 @@
  */
 
 static cairo_status_t
-_csi_buffer_init (csi_t *ctx, csi_buffer_t *buffer)
+buffer_init (csi_t *ctx, csi_buffer_t *buffer)
 {
-    buffer->status = CSI_STATUS_SUCCESS;
+    cairo_status_t status = CSI_STATUS_SUCCESS;
+
     buffer->size = 16384;
     buffer->base = _csi_alloc (ctx, buffer->size);
     if (_csi_unlikely (buffer->base == NULL)) {
-	buffer->status = _csi_error (CSI_STATUS_NO_MEMORY);
+	status = _csi_error (CSI_STATUS_NO_MEMORY);
 	buffer->size = 0;
     }
 
     buffer->ptr = buffer->base;
     buffer->end = buffer->base + buffer->size;
 
-    return buffer->status;
+    return status;
 }
 
 static void
-_csi_buffer_fini (csi_t *ctx, csi_buffer_t *buffer)
+buffer_fini (csi_t *ctx, csi_buffer_t *buffer)
 {
     _csi_free (ctx, buffer->base);
 }
 
-static cairo_status_t
-_csi_buffer_grow (csi_t *ctx, csi_buffer_t *buffer)
+static inline void
+_buffer_grow (csi_t *ctx, csi_scanner_t *scan)
 {
     int newsize;
     int offset;
     char *base;
 
-    if (_csi_unlikely (buffer->status))
-	return buffer->status;
-
-    if (_csi_unlikely (buffer->size > INT_MAX / 2))
-	return buffer->status = _csi_error (CSI_STATUS_NO_MEMORY);
+    if (_csi_unlikely (scan->buffer.size > INT_MAX / 2))
+	longjmp (scan->jmpbuf,  _csi_error (CSI_STATUS_NO_MEMORY));
 
-    offset = buffer->ptr - buffer->base;
-    newsize = buffer->size * 2;
-    base = _csi_realloc (ctx, buffer->base, newsize);
+    offset = scan->buffer.ptr - scan->buffer.base;
+    newsize = scan->buffer.size * 2;
+    base = _csi_realloc (ctx, scan->buffer.base, newsize);
     if (_csi_unlikely (base == NULL))
-	return buffer->status = _csi_error (CSI_STATUS_NO_MEMORY);
+	longjmp (scan->jmpbuf,  _csi_error (CSI_STATUS_NO_MEMORY));
 
-    buffer->base = base;
-    buffer->ptr  = base + offset;
-    buffer->end  = base + newsize;
-    buffer->size = newsize;
-
-    return CSI_STATUS_SUCCESS;
+    scan->buffer.base = base;
+    scan->buffer.ptr  = base + offset;
+    scan->buffer.end  = base + newsize;
+    scan->buffer.size = newsize;
 }
 
-static inline csi_boolean_t
-_csi_buffer_check (csi_t *ctx, csi_buffer_t *buffer, int count)
+static inline void
+buffer_check (csi_t *ctx, csi_scanner_t *scan, int count)
 {
-    if (_csi_unlikely (buffer->ptr + count > buffer->end)) {
-	if (_csi_buffer_grow (ctx, buffer))
-	    return FALSE;
-    }
-
-    return TRUE;
+    if (_csi_unlikely (scan->buffer.ptr + count > scan->buffer.end))
+	_buffer_grow (ctx, scan);
 }
 
 static inline void
-_csi_buffer_add (csi_buffer_t *buffer, int c)
+buffer_add (csi_buffer_t *buffer, int c)
 {
     *buffer->ptr++ = c;
 }
 
 static inline void
-_csi_buffer_reset (csi_buffer_t *buffer)
+buffer_reset (csi_buffer_t *buffer)
 {
     buffer->ptr = buffer->base;
 }
 
-static inline int
-scan_getc (csi_scanner_t *scan, csi_file_t *src)
-{
-    if (_csi_unlikely (scan->status))
-	return EOF;
-
-    return csi_file_getc (src);
-}
-
-static inline int
-scan_read (csi_scanner_t *scan, csi_file_t *src, void *buf, int len)
-{
-    return csi_file_read (src, buf, len);
-}
-
-static inline void
-scan_putc (csi_scanner_t *scan, csi_file_t *src, int c)
-{
-    csi_file_putc (src, c);
-}
-
 static inline void
 reset (csi_scanner_t *scan)
 {
@@ -160,20 +131,20 @@ static void
 token_start (csi_scanner_t *scan)
 {
     scan->state = TOKEN;
-    _csi_buffer_reset (&scan->buffer);
+    buffer_reset (&scan->buffer);
 }
 
 static void
 token_add (csi_t *ctx, csi_scanner_t *scan, int c)
 {
-    if (_csi_likely (_csi_buffer_check (ctx, &scan->buffer, 1)))
-	_csi_buffer_add (&scan->buffer, c);
+    buffer_check (ctx, scan, 1);
+    buffer_add (&scan->buffer, c);
 }
 
 static void
 token_add_unchecked (csi_scanner_t *scan, int c)
 {
-    _csi_buffer_add (&scan->buffer, c);
+    buffer_add (&scan->buffer, c);
 }
 
 static csi_boolean_t
@@ -340,6 +311,7 @@ parse_number (csi_object_t *obj, const char *s, int len)
 static void
 token_end (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 {
+    cairo_status_t status;
     char *s;
     csi_object_t obj;
     int len;
@@ -355,43 +327,46 @@ token_end (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
     if (_csi_unlikely (scan->buffer.ptr == scan->buffer.base))
 	return;
 
-    scan->status = scan->buffer.status;
-    if (_csi_unlikely (scan->status))
-	return;
-
     s = scan->buffer.base;
     len = scan->buffer.ptr - scan->buffer.base;
 
     if (s[0] == '{') { /* special case procedures */
-	if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
-	    scan->status = _csi_stack_push (ctx,
-					    &scan->procedure_stack,
-					    &scan->build_procedure);
+	if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
+	    status = _csi_stack_push (ctx,
+				      &scan->procedure_stack,
+				      &scan->build_procedure);
+	    if (_csi_unlikely (status))
+		longjmp (scan->jmpbuf, status);
+	}
+
+	status = csi_array_new (ctx, 0, &scan->build_procedure);
+	if (_csi_unlikely (status))
+	    longjmp (scan->jmpbuf, status);
 
-	scan->status = csi_array_new (ctx, 0, &scan->build_procedure);
 	scan->build_procedure.type |= CSI_OBJECT_ATTR_EXECUTABLE;
 	reset (scan);
 	return;
     } else if (s[0] == '}') {
-	csi_object_t *next;
-
 	if (_csi_unlikely
 	    (scan->build_procedure.type == CSI_OBJECT_TYPE_NULL))
 	{
-	    scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
-	    return;
+	    longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
 	}
 
 	if (scan->procedure_stack.len) {
+	    csi_object_t *next;
+
 	    next = _csi_stack_peek (&scan->procedure_stack, 0);
-	    scan->status = csi_array_append (ctx, next->datum.array,
-					     &scan->build_procedure);
+	    status = csi_array_append (ctx, next->datum.array,
+				       &scan->build_procedure);
 	    scan->build_procedure = *next;
 	    scan->procedure_stack.len--;
 	} else {
-	    scan->status = _csi_push_ostack (ctx, &scan->build_procedure);
+	    status = _csi_push_ostack (ctx, &scan->build_procedure);
 	    scan->build_procedure.type = CSI_OBJECT_TYPE_NULL;
 	}
+	if (_csi_unlikely (status))
+	    longjmp (scan->jmpbuf, status);
 
 	reset (scan);
 	return;
@@ -399,35 +374,40 @@ token_end (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 
     if (s[0] == '/') {
 	if (len >= 2 && s[1] == '/') { /* substituted name */
-	    scan->status = csi_name_new (ctx, &obj, s + 2, len - 2);
-	    if (_csi_unlikely (scan->status))
-		return;
+	    status = csi_name_new (ctx, &obj, s + 2, len - 2);
+	    if (_csi_unlikely (status))
+		longjmp (scan->jmpbuf, status);
 
-	    scan->status = _csi_name_lookup (ctx, obj.datum.name, &obj);
+	    status = _csi_name_lookup (ctx, obj.datum.name, &obj);
 	} else { /* literal name */
-	    scan->status = csi_name_new (ctx, &obj, s + 1, len - 1);
+	    status = csi_name_new (ctx, &obj, s + 1, len - 1);
 	}
+	if (_csi_unlikely (status))
+	    longjmp (scan->jmpbuf, status);
     } else {
 	if (! parse_number (&obj, s, len)) {
-	    scan->status = csi_name_new (ctx, &obj, s, len);
+	    status = csi_name_new (ctx, &obj, s, len);
+	    if (_csi_unlikely (status))
+		longjmp (scan->jmpbuf, status);
+
 	    obj.type |= CSI_OBJECT_ATTR_EXECUTABLE;
 	}
     }
-    if (_csi_unlikely (scan->status))
-	return;
 
     /* consume whitespace after token, before calling the interpreter */
     reset (scan);
 
     if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
-	scan->status = csi_array_append (ctx,
-					 scan->build_procedure.datum.array,
-					 &obj);
+	status = csi_array_append (ctx,
+				   scan->build_procedure.datum.array,
+				   &obj);
     } else if (obj.type & CSI_OBJECT_ATTR_EXECUTABLE) {
-	scan->status = csi_object_execute (ctx, csi_object_reference (&obj));
-	csi_object_free (ctx, &obj);
-    } else
-	scan->status = _csi_push_ostack (ctx, &obj);
+	status = csi_object_execute (ctx, &obj);
+    } else {
+	status = _csi_push_ostack (ctx, &obj);
+    }
+    if (_csi_unlikely (status))
+	longjmp (scan->jmpbuf, status);
 }
 
 static void
@@ -448,7 +428,7 @@ string_start (csi_scanner_t *scan)
 {
     scan->state = STRING;
     scan->string_p = 1;
-    _csi_buffer_reset (&scan->buffer);
+    buffer_reset (&scan->buffer);
 }
 
 static void
@@ -466,32 +446,31 @@ string_dec_p (csi_scanner_t *scan)
 static void
 string_add (csi_t *ctx, csi_scanner_t *scan, int c)
 {
-    if (_csi_likely (_csi_buffer_check (ctx, &scan->buffer, 1)))
-	_csi_buffer_add (&scan->buffer, c);
+    buffer_check (ctx, scan, 1);
+    buffer_add (&scan->buffer, c);
 }
 
 static void
 string_end (csi_t *ctx, csi_scanner_t *scan)
 {
     csi_object_t obj;
+    cairo_status_t status;
 
-    scan->status = scan->buffer.status;
-    if (_csi_unlikely (scan->status))
-	return;
-
-    scan->status = csi_string_new (ctx,
-				   &obj,
-				   scan->buffer.base,
-				   scan->buffer.ptr - scan->buffer.base);
-    if (_csi_unlikely (scan->status))
-	return;
+    status = csi_string_new (ctx,
+			     &obj,
+			     scan->buffer.base,
+			     scan->buffer.ptr - scan->buffer.base);
+    if (_csi_unlikely (status))
+	longjmp (scan->jmpbuf, status);
 
     if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
-	scan->status = csi_array_append (ctx,
-					 scan->build_procedure.datum.array,
-					 &obj);
+	status = csi_array_append (ctx,
+				   scan->build_procedure.datum.array,
+				   &obj);
     else
-	scan->status = _csi_push_ostack (ctx, &obj);
+	status = _csi_push_ostack (ctx, &obj);
+    if (_csi_unlikely (status))
+	longjmp (scan->jmpbuf, status);
 
     reset (scan);
 }
@@ -503,7 +482,7 @@ hex_start (csi_scanner_t *scan)
     scan->accumulator_count = 0;
     scan->accumulator = 0;
 
-    _csi_buffer_reset (&scan->buffer);
+    buffer_reset (&scan->buffer);
 }
 
 static int
@@ -529,8 +508,9 @@ hex_add (csi_t *ctx, csi_scanner_t *scan, int c)
 	scan->accumulator_count = 1;
     } else {
 	scan->accumulator |= hex_value (c) << 0;
-	if (_csi_likely (_csi_buffer_check (ctx, &scan->buffer, 1)))
-	    _csi_buffer_add (&scan->buffer, scan->accumulator);
+	buffer_check (ctx, scan, 1);
+	buffer_add (&scan->buffer, scan->accumulator);
+
 	scan->accumulator = 0;
 	scan->accumulator_count = 0;
     }
@@ -540,27 +520,26 @@ static void
 hex_end (csi_t *ctx, csi_scanner_t *scan)
 {
     csi_object_t obj;
+    cairo_status_t status;
 
     if (scan->accumulator_count)
 	hex_add (ctx, scan, '0');
 
-    scan->status = scan->buffer.status;
-    if (_csi_unlikely (scan->status))
-	return;
-
-    scan->status = csi_string_new (ctx,
-				   &obj,
-				   scan->buffer.base,
-				   scan->buffer.ptr - scan->buffer.base);
-    if (_csi_unlikely (scan->status))
-	return;
+    status = csi_string_new (ctx,
+			     &obj,
+			     scan->buffer.base,
+			     scan->buffer.ptr - scan->buffer.base);
+    if (_csi_unlikely (status))
+	longjmp (scan->jmpbuf, status);
 
     if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
-	scan->status = csi_array_append (ctx,
-					 scan->build_procedure.datum.array,
-					 &obj);
+	status = csi_array_append (ctx,
+				   scan->build_procedure.datum.array,
+				   &obj);
     else
-	scan->status = _csi_push_ostack (ctx, &obj);
+	status = _csi_push_ostack (ctx, &obj);
+    if (_csi_unlikely (status))
+	longjmp (scan->jmpbuf, status);
 
     reset (scan);
 }
@@ -572,39 +551,31 @@ base85_start (csi_scanner_t *scan)
     scan->accumulator = 0;
     scan->accumulator_count = 0;
 
-    _csi_buffer_reset (&scan->buffer);
+    buffer_reset (&scan->buffer);
 }
 
 static void
 base85_add (csi_t *ctx, csi_scanner_t *scan, int c)
 {
     if (c == 'z') {
-	if (_csi_unlikely (scan->accumulator_count != 0)) {
-	    scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
-	    return;
-	}
-	if (_csi_likely (_csi_buffer_check (ctx, &scan->buffer, 4))) {
-	    _csi_buffer_add (&scan->buffer, 0);
-	    _csi_buffer_add (&scan->buffer, 0);
-	    _csi_buffer_add (&scan->buffer, 0);
-	    _csi_buffer_add (&scan->buffer, 0);
-	}
+	if (_csi_unlikely (scan->accumulator_count != 0))
+	    longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
+
+	buffer_check (ctx, scan, 4);
+	buffer_add (&scan->buffer, 0);
+	buffer_add (&scan->buffer, 0);
+	buffer_add (&scan->buffer, 0);
+	buffer_add (&scan->buffer, 0);
     } else if (_csi_unlikely (c < '!' || c > 'u')) {
-	scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
-	return;
+	longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
     } else {
 	scan->accumulator = scan->accumulator*85 + c - '!';
 	if (++scan->accumulator_count == 5) {
-	    if (_csi_likely (_csi_buffer_check (ctx, &scan->buffer, 4))) {
-		_csi_buffer_add (&scan->buffer,
-				 (scan->accumulator >> 24) & 0xff);
-		_csi_buffer_add (&scan->buffer,
-				 (scan->accumulator >> 16) & 0xff);
-		_csi_buffer_add (&scan->buffer,
-				 (scan->accumulator >>  8) & 0xff);
-		_csi_buffer_add (&scan->buffer,
-				 (scan->accumulator >>  0) & 0xff);
-	    }
+	    buffer_check (ctx, scan, 4);
+	    buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
+	    buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
+	    buffer_add (&scan->buffer, (scan->accumulator >>  8) & 0xff);
+	    buffer_add (&scan->buffer, (scan->accumulator >>  0) & 0xff);
 
 	    scan->accumulator = 0;
 	    scan->accumulator_count = 0;
@@ -616,49 +587,49 @@ static void
 base85_end (csi_t *ctx, csi_scanner_t *scan)
 {
     csi_object_t obj;
+    cairo_status_t status;
 
-    if (_csi_unlikely (! _csi_buffer_check (ctx, &scan->buffer, 4))) {
-	scan->status = scan->buffer.status;
-	return;
-    }
+    buffer_check (ctx, scan, 4);
 
     switch (scan->accumulator_count) {
     case 0:
 	break;
     case 1:
-	scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
+	longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
 	break;
 
     case 2:
 	scan->accumulator = scan->accumulator * (85*85*85) + 85*85*85 -1;
-	_csi_buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
+	buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
 	break;
     case 3:
 	scan->accumulator = scan->accumulator * (85*85) + 85*85 -1;
-	_csi_buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
-	_csi_buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
+	buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
+	buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
 	break;
     case 4:
 	scan->accumulator = scan->accumulator * 85 + 84;
-	_csi_buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
-	_csi_buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
-	_csi_buffer_add (&scan->buffer, (scan->accumulator >>  8) & 0xff);
+	buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
+	buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
+	buffer_add (&scan->buffer, (scan->accumulator >>  8) & 0xff);
 	break;
     }
 
-    scan->status = csi_string_new (ctx,
-				   &obj,
-				   scan->buffer.base,
-				   scan->buffer.ptr - scan->buffer.base);
-    if (_csi_unlikely (scan->status))
-	return;
+    status = csi_string_new (ctx,
+			     &obj,
+			     scan->buffer.base,
+			     scan->buffer.ptr - scan->buffer.base);
+    if (_csi_unlikely (status))
+	longjmp (scan->jmpbuf, status);
 
     if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
-	scan->status = csi_array_append (ctx,
-					 scan->build_procedure.datum.array,
-					 &obj);
+	status = csi_array_append (ctx,
+				   scan->build_procedure.datum.array,
+				   &obj);
     else
-	scan->status = _csi_push_ostack (ctx, &obj);
+	status = _csi_push_ostack (ctx, &obj);
+    if (_csi_unlikely (status))
+	longjmp (scan->jmpbuf, status);
 
     reset (scan);
 }
@@ -674,7 +645,7 @@ scan_none (csi_t *ctx,
 	float f;
     } u;
 
-    while ((c = scan_getc (scan, src)) != EOF) {
+    while ((c = csi_file_getc (src)) != EOF) {
 	csi_object_t obj = { CSI_OBJECT_TYPE_NULL };
 
 	switch (c) {
@@ -705,10 +676,10 @@ scan_none (csi_t *ctx,
 	    return 1;
 
 	case '<':
-	    next = scan_getc (scan, src);
+	    next = csi_file_getc (src);
 	    switch (next) {
 	    case EOF:
-		scan_putc (scan, src, '<');
+		csi_file_putc (src, '<');
 		return 0;
 	    case '<':
 		/* dictionary name */
@@ -721,7 +692,7 @@ scan_none (csi_t *ctx,
 		base85_start (scan);
 		return 1;
 	    default:
-		scan_putc (scan, src, next);
+		csi_file_putc (src, next);
 		hex_start (scan);
 		return 1;
 	    }
@@ -747,22 +718,22 @@ scan_none (csi_t *ctx,
 	case 137: /* 16/32-bit fixed point */
 	    break;
 	case 138: /* 32-bit real, MSB */
-	    scan_read (scan, src, &u.i, 4);
+	    csi_file_read (src, &u.i, 4);
 #if ! WORDS_BIGENDIAN
 	    u.i = bswap_32 (u.i);
 #endif
-	    scan->status = csi_real_new (ctx, &obj, u.f);
+	    csi_real_new (&obj, u.f);
 	    break;
 	case 139: /* 32-bit real, LSB */
-	    scan_read (scan, src, &u.f, 4);
+	    csi_file_read (src, &u.f, 4);
 #if WORDS_BIGENDIAN
 	    u.i = bswap_32 (u.i);
 #endif
-	    scan->status = csi_real_new (ctx, &obj, u.f);
+	    csi_real_new (&obj, u.f);
 	    break;
 	case 140: /* 32-bit real, native */
-	    scan_read (scan, src, &u.f, 4);
-	    scan->status = csi_real_new (ctx, &obj, u.f);
+	    csi_file_read (src, &u.f, 4);
+	    csi_real_new (&obj, u.f);
 	    break;
 	case 141: /* boolean */
 	    break;
@@ -794,13 +765,13 @@ scan_none (csi_t *ctx,
 	case 157:
 	case 158:
 	case 159:
-	    scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
+	    longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
 	    return 0;
 
 	case '#': /* PDF 1.2 escape code */
 	    {
-		int c_hi = scan_getc (scan, src);
-		int c_lo = scan_getc (scan, src);
+		int c_hi = csi_file_getc (src);
+		int c_lo = csi_file_getc (src);
 		c = (hex_value (c_hi) << 4) | hex_value (c_lo);
 	    }
 	    /* fall-through */
@@ -811,12 +782,16 @@ scan_none (csi_t *ctx,
 	}
 
 	if (obj.type != CSI_OBJECT_TYPE_NULL) {
+	    cairo_status_t status;
+
 	    if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
-		scan->status = csi_array_append (ctx,
-						 scan->build_procedure.datum.array,
-						 &obj);
+		status = csi_array_append (ctx,
+					   scan->build_procedure.datum.array,
+					   &obj);
 	    else
-		scan->status = csi_object_execute (ctx, &obj);
+		status = csi_object_execute (ctx, &obj);
+	    if (_csi_unlikely (status))
+		longjmp (scan->jmpbuf, status);
 	}
     }
 
@@ -828,7 +803,7 @@ scan_token (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 {
     int c;
 
-    while ((c = scan_getc (scan, src)) != EOF) {
+    while ((c = csi_file_getc (src)) != EOF) {
 	switch (c) {
 	case 0xa:
 	    scan->line_number++;
@@ -875,14 +850,14 @@ scan_token (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 	    return 1;
 
 	case '<':
-	    scan_putc (scan, src, '<');
+	    csi_file_putc (src, '<');
 	    token_end (ctx, scan, src);
 	    return 1;
 
 	case '#': /* PDF 1.2 escape code */
 	    {
-		int c_hi = scan_getc (scan, src);
-		int c_lo = scan_getc (scan, src);
+		int c_hi = csi_file_getc (src);
+		int c_lo = csi_file_getc (src);
 		c = (hex_value (c_hi) << 4) | hex_value (c_lo);
 	    }
 	    /* fall-through */
@@ -901,7 +876,7 @@ scan_hex (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 {
     int c;
 
-    while ((c = scan_getc (scan, src)) != EOF) {
+    while ((c = csi_file_getc (src)) != EOF) {
 	switch (c) {
 	case 0xa:
 	    scan->line_number++;
@@ -942,12 +917,12 @@ scan_hex (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 	    break;
 
 	default:
-	    scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
+	    longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
 	    return 0;
 	}
     }
 
-    scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
+    longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
     return 0;
 }
 
@@ -956,10 +931,10 @@ scan_base85 (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 {
     int c, next;
 
-    while ((c = scan_getc (scan, src)) != EOF) {
+    while ((c = csi_file_getc (src)) != EOF) {
 	switch (c) {
 	case '~':
-	    next = scan_getc (scan, src);
+	    next = csi_file_getc (src);
 	    switch (next) {
 	    case EOF:
 		return 0;
@@ -968,7 +943,7 @@ scan_base85 (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 		base85_end (ctx, scan);
 		return 1;
 	    }
-	    scan_putc (scan, src, next);
+	    csi_file_putc (src, next);
 
 	    /* fall-through */
 	default:
@@ -977,7 +952,7 @@ scan_base85 (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 	}
     }
 
-    scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
+    longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
     return 0;
 }
 
@@ -986,12 +961,13 @@ scan_string (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 {
     int c, next;
 
-    while ((c = scan_getc (scan, src)) != EOF) {
+    while ((c = csi_file_getc (src)) != EOF) {
 	switch (c) {
 	case '\\': /* escape */
-	    next = scan_getc (scan, src);
+	    next = csi_file_getc (src);
 	    switch (next) {
 	    case EOF:
+		longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
 		return 0;
 
 	    case 'n':
@@ -1027,7 +1003,7 @@ scan_string (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 		    c = next - '0';
 
 		    for (i = 0; i < 2; i++) {
-			next = scan_getc (scan, src);
+			next = csi_file_getc (src);
 			switch (next) {
 			case EOF:
 			    return 0;
@@ -1038,7 +1014,7 @@ scan_string (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 			    break;
 
 			default:
-			    scan_putc (scan, src, next);
+			    csi_file_putc (src, next);
 			    goto octal_code_done;
 			}
 		    }
@@ -1049,14 +1025,14 @@ scan_string (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 
 	    case 0xa:
 		/* skip the newline */
-		next = scan_getc (scan, src); /* might be compound LFCR */
+		next = csi_file_getc (src); /* might be compound LFCR */
 		switch (next) {
 		case EOF:
 		    return 0;
 		case 0xc:
 		    break;
 		default:
-		    scan_putc (scan, src, next);
+		    csi_file_putc (src, next);
 		    break;
 		}
 		scan->line_number++;
@@ -1089,7 +1065,7 @@ scan_string (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 	}
     }
 
-    scan->status = _csi_error (CSI_STATUS_INVALID_SCRIPT);
+    longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
     return 0;
 }
 
@@ -1099,7 +1075,7 @@ scan_comment (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
     int c;
 
     /* discard until newline */
-    while ((c = scan_getc (scan, src)) != EOF) {
+    while ((c = csi_file_getc (src)) != EOF) {
 	switch (c) {
 	case 0xa:
 	    scan->line_number++;
@@ -1123,12 +1099,16 @@ _csi_scan_file (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
 	scan_hex,
 	scan_base85,
     };
+    csi_status_t status;
+
+    if ((status = setjmp (scan->jmpbuf)))
+	return status;
 
     scan->line_number = 0;
     while (func[scan->state] (ctx, scan, src))
 	;
 
-    return scan->status;
+    return CSI_STATUS_SUCCESS;
 }
 
 #if 0
@@ -1180,7 +1160,7 @@ _csi_scanner_init (csi_t *ctx, csi_scanner_t *scanner)
 
     memset (scanner, 0, sizeof (csi_scanner_t));
 
-    status = _csi_buffer_init (ctx, &scanner->buffer);
+    status = buffer_init (ctx, &scanner->buffer);
     if (status)
 	return status;
 
@@ -1196,7 +1176,7 @@ _csi_scanner_init (csi_t *ctx, csi_scanner_t *scanner)
 void
 _csi_scanner_fini (csi_t *ctx, csi_scanner_t *scanner)
 {
-    _csi_buffer_fini (ctx, &scanner->buffer);
+    buffer_fini (ctx, &scanner->buffer);
     _csi_stack_fini (ctx, &scanner->procedure_stack);
     if (scanner->build_procedure.type != CSI_OBJECT_TYPE_NULL)
 	csi_object_free (ctx, &scanner->build_procedure);
commit 2b1ec7a4d87399824dacb9803627c9322b12d894
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 27 22:48:19 2009 +0100

    [cairo] Report true error via pattern from cairo_pop_group()
    
    Report the correct error via the returned pattern->status rather than
    simply returning the NO_MEMORY nil object.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index c97ebe6..3e82650 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -566,7 +566,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color,
     return &pattern->base;
 }
 
-static const cairo_pattern_t *
+cairo_pattern_t *
 _cairo_pattern_create_in_error (cairo_status_t status)
 {
     cairo_pattern_t *pattern;
@@ -686,7 +686,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
     }
 
     if (surface->status)
-	return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
+	return _cairo_pattern_create_in_error (surface->status);
 
     pattern =
 	_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
diff --git a/src/cairo.c b/src/cairo.c
index 9b8f432..4324af7 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -569,11 +569,12 @@ cairo_pattern_t *
 cairo_pop_group (cairo_t *cr)
 {
     cairo_surface_t *group_surface, *parent_target;
-    cairo_pattern_t *group_pattern = (cairo_pattern_t*) &_cairo_pattern_nil.base;
+    cairo_pattern_t *group_pattern;
     cairo_matrix_t group_matrix;
+    cairo_status_t status;
 
     if (unlikely (cr->status))
-	return group_pattern;
+	return _cairo_pattern_create_in_error (cr->status);
 
     /* Grab the active surfaces */
     group_surface = _cairo_gstate_get_target (cr->gstate);
@@ -582,7 +583,7 @@ cairo_pop_group (cairo_t *cr)
     /* Verify that we are at the right nesting level */
     if (parent_target == NULL) {
 	_cairo_set_error (cr, CAIRO_STATUS_INVALID_POP_GROUP);
-	return group_pattern;
+	return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_POP_GROUP);
     }
 
     /* We need to save group_surface before we restore; we don't need
@@ -592,12 +593,15 @@ cairo_pop_group (cairo_t *cr)
 
     cairo_restore (cr);
 
-    if (unlikely (cr->status))
+    if (unlikely (cr->status)) {
+	group_pattern = _cairo_pattern_create_in_error (cr->status);
 	goto done;
+    }
 
     group_pattern = cairo_pattern_create_for_surface (group_surface);
-    if (cairo_pattern_status (group_pattern)) {
-	_cairo_set_error (cr, cairo_pattern_status (group_pattern));
+    status = group_pattern->status;
+    if (unlikely (status)) {
+	_cairo_set_error (cr, status);
         goto done;
     }
 
@@ -894,7 +898,7 @@ cairo_pattern_t *
 cairo_get_source (cairo_t *cr)
 {
     if (unlikely (cr->status))
-	return (cairo_pattern_t*) &_cairo_pattern_nil.base;
+	return _cairo_pattern_create_in_error (cr->status);
 
     return _cairo_gstate_get_source (cr->gstate);
 }
diff --git a/src/cairoint.h b/src/cairoint.h
index 98bef24..52f813f 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -916,7 +916,6 @@ struct _cairo_solid_pattern {
     cairo_content_t content;
 };
 
-extern const cairo_private cairo_solid_pattern_t _cairo_pattern_nil;
 extern const cairo_private cairo_solid_pattern_t _cairo_pattern_black;
 
 typedef struct _cairo_surface_pattern {
@@ -2468,6 +2467,9 @@ _cairo_slope_compare (const cairo_slope_t *a,
 
 /* cairo-pattern.c */
 
+cairo_private cairo_pattern_t *
+_cairo_pattern_create_in_error (cairo_status_t status);
+
 cairo_private cairo_status_t
 _cairo_pattern_create_copy (cairo_pattern_t	  **pattern,
 			    const cairo_pattern_t  *other);
commit 5c3be3ece27b7cf6e4b1262ea18ac51b45c62389
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 27 22:40:15 2009 +0100

    [cairo] Mark cr->status guard as unlikely
    
    For correct operation, the context should never be in error, so mark the
    error context as being unlikely to optimize the common path.

diff --git a/src/cairo.c b/src/cairo.c
index 0913036..9b8f432 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -107,14 +107,9 @@ _cairo_error (cairo_status_t status)
 static void
 _cairo_set_error (cairo_t *cr, cairo_status_t status)
 {
-    if (status == CAIRO_STATUS_SUCCESS)
-	return;
-
     /* Don't overwrite an existing error. This preserves the first
      * error, which is the most significant. */
-    _cairo_status_set_error (&cr->status, status);
-
-    status = _cairo_error (status);
+    _cairo_status_set_error (&cr->status, _cairo_error (status));
 }
 
 #if HAS_ATOMIC_OPS
@@ -394,7 +389,7 @@ cairo_save (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
@@ -416,7 +411,7 @@ cairo_restore (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
@@ -501,7 +496,7 @@ cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
     cairo_rectangle_int_t extents;
     cairo_surface_t *parent_surface, *group_surface = NULL;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     parent_surface = _cairo_gstate_get_target (cr->gstate);
@@ -537,7 +532,7 @@ cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
 
     /* create a new gstate for the redirect */
     cairo_save (cr);
-    if (cr->status)
+    if (unlikely (cr->status))
 	goto bail;
 
     status = _cairo_gstate_redirect_target (cr->gstate, group_surface);
@@ -577,7 +572,7 @@ cairo_pop_group (cairo_t *cr)
     cairo_pattern_t *group_pattern = (cairo_pattern_t*) &_cairo_pattern_nil.base;
     cairo_matrix_t group_matrix;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return group_pattern;
 
     /* Grab the active surfaces */
@@ -597,7 +592,7 @@ cairo_pop_group (cairo_t *cr)
 
     cairo_restore (cr);
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	goto done;
 
     group_pattern = cairo_pattern_create_for_surface (group_surface);
@@ -683,7 +678,7 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_operator (cr->gstate, op);
@@ -739,7 +734,7 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
 {
     cairo_pattern_t *pattern;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (_current_source_matches_solid (cr, red, green, blue, 1.))
@@ -780,7 +775,7 @@ cairo_set_source_rgba (cairo_t *cr,
 {
     cairo_pattern_t *pattern;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (_current_source_matches_solid (cr, red, green, blue, alpha))
@@ -826,7 +821,7 @@ cairo_set_source_surface (cairo_t	  *cr,
     cairo_pattern_t *pattern;
     cairo_matrix_t matrix;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     /* push the current pattern to the freed lists */
@@ -866,7 +861,7 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (source == NULL) {
@@ -898,7 +893,7 @@ slim_hidden_def (cairo_set_source);
 cairo_pattern_t *
 cairo_get_source (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return (cairo_pattern_t*) &_cairo_pattern_nil.base;
 
     return _cairo_gstate_get_source (cr->gstate);
@@ -925,7 +920,7 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (tolerance < CAIRO_TOLERANCE_MINIMUM)
@@ -955,7 +950,7 @@ cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_antialias (cr->gstate, antialias);
@@ -981,7 +976,7 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
@@ -1020,7 +1015,7 @@ cairo_set_line_width (cairo_t *cr, double width)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (width < 0.)
@@ -1053,7 +1048,7 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_line_cap (cr->gstate, line_cap);
@@ -1083,7 +1078,7 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_line_join (cr->gstate, line_join);
@@ -1132,7 +1127,7 @@ cairo_set_dash (cairo_t	     *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_dash (cr->gstate,
@@ -1159,7 +1154,7 @@ cairo_get_dash_count (cairo_t *cr)
 {
     int num_dashes;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return 0;
 
     _cairo_gstate_get_dash (cr->gstate, NULL, &num_dashes, NULL);
@@ -1184,7 +1179,7 @@ cairo_get_dash (cairo_t *cr,
 		double  *dashes,
 		double  *offset)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_get_dash (cr->gstate, dashes, NULL, offset);
@@ -1223,7 +1218,7 @@ cairo_set_miter_limit (cairo_t *cr, double limit)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_miter_limit (cr->gstate, limit);
@@ -1248,7 +1243,7 @@ cairo_translate (cairo_t *cr, double tx, double ty)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_translate (cr->gstate, tx, ty);
@@ -1273,7 +1268,7 @@ cairo_scale (cairo_t *cr, double sx, double sy)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_scale (cr->gstate, sx, sy);
@@ -1299,7 +1294,7 @@ cairo_rotate (cairo_t *cr, double angle)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_rotate (cr->gstate, angle);
@@ -1322,7 +1317,7 @@ cairo_transform (cairo_t	      *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_transform (cr->gstate, matrix);
@@ -1345,7 +1340,7 @@ cairo_set_matrix (cairo_t	       *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_matrix (cr->gstate, matrix);
@@ -1366,7 +1361,7 @@ slim_hidden_def (cairo_set_matrix);
 void
 cairo_identity_matrix (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_identity_matrix (cr->gstate);
@@ -1385,7 +1380,7 @@ cairo_identity_matrix (cairo_t *cr)
 void
 cairo_user_to_device (cairo_t *cr, double *x, double *y)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_device (cr->gstate, x, y);
@@ -1406,7 +1401,7 @@ slim_hidden_def (cairo_user_to_device);
 void
 cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
@@ -1426,7 +1421,7 @@ slim_hidden_def (cairo_user_to_device_distance);
 void
 cairo_device_to_user (cairo_t *cr, double *x, double *y)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_device_to_user (cr->gstate, x, y);
@@ -1446,7 +1441,7 @@ cairo_device_to_user (cairo_t *cr, double *x, double *y)
 void
 cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
@@ -1462,7 +1457,7 @@ cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
 void
 cairo_new_path (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_path_fixed_fini (cr->path);
@@ -1485,7 +1480,7 @@ cairo_move_to (cairo_t *cr, double x, double y)
     cairo_status_t status;
     cairo_fixed_t x_fixed, y_fixed;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
@@ -1519,7 +1514,7 @@ slim_hidden_def(cairo_move_to);
 void
 cairo_new_sub_path (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_path_fixed_new_sub_path (cr->path);
@@ -1544,7 +1539,7 @@ cairo_line_to (cairo_t *cr, double x, double y)
     cairo_status_t status;
     cairo_fixed_t x_fixed, y_fixed;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
@@ -1587,7 +1582,7 @@ cairo_curve_to (cairo_t *cr,
     cairo_fixed_t x2_fixed, y2_fixed;
     cairo_fixed_t x3_fixed, y3_fixed;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
@@ -1665,7 +1660,7 @@ cairo_arc (cairo_t *cr,
 	   double radius,
 	   double angle1, double angle2)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     /* Do nothing, successfully, if radius is <= 0 */
@@ -1707,7 +1702,7 @@ cairo_arc_negative (cairo_t *cr,
 		    double radius,
 		    double angle1, double angle2)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     /* Do nothing, successfully, if radius is <= 0 */
@@ -1734,7 +1729,7 @@ cairo_arc_to (cairo_t *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_arc_to (cr->gstate,
@@ -1768,7 +1763,7 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
     cairo_fixed_t dx_fixed, dy_fixed;
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
@@ -1805,7 +1800,7 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy)
     cairo_fixed_t dx_fixed, dy_fixed;
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
@@ -1855,7 +1850,7 @@ cairo_rel_curve_to (cairo_t *cr,
     cairo_fixed_t dx3_fixed, dy3_fixed;
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1);
@@ -1904,7 +1899,7 @@ cairo_rectangle (cairo_t *cr,
 		 double x, double y,
 		 double width, double height)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     cairo_move_to (cr, x, y);
@@ -1921,7 +1916,7 @@ cairo_stroke_to_path (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     /* The code in _cairo_meta_surface_get_path has a poorman's stroke_to_path */
@@ -1963,7 +1958,7 @@ cairo_close_path (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_path_fixed_close_path (cr->path);
@@ -2007,7 +2002,7 @@ void
 cairo_path_extents (cairo_t *cr,
 		    double *x1, double *y1, double *x2, double *y2)
 {
-    if (cr->status) {
+    if (unlikely (cr->status)) {
 	if (x1)
 	    *x1 = 0.0;
 	if (y1)
@@ -2037,7 +2032,7 @@ cairo_paint (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_paint (cr->gstate);
@@ -2064,7 +2059,7 @@ cairo_paint_with_alpha (cairo_t *cr,
     cairo_color_t color;
     cairo_solid_pattern_t pattern;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (CAIRO_ALPHA_IS_OPAQUE (alpha)) {
@@ -2102,7 +2097,7 @@ cairo_mask (cairo_t         *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (pattern == NULL) {
@@ -2142,7 +2137,7 @@ cairo_mask_surface (cairo_t         *cr,
     cairo_pattern_t *pattern;
     cairo_matrix_t matrix;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     pattern = cairo_pattern_create_for_surface (surface);
@@ -2214,7 +2209,7 @@ cairo_stroke_preserve (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_stroke (cr->gstate, cr->path);
@@ -2257,7 +2252,7 @@ cairo_fill_preserve (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_fill (cr->gstate, cr->path);
@@ -2283,7 +2278,7 @@ cairo_copy_page (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_copy_page (cr->gstate);
@@ -2306,7 +2301,7 @@ cairo_show_page (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_show_page (cr->gstate);
@@ -2338,7 +2333,7 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
     cairo_status_t status;
     cairo_bool_t inside = FALSE;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return 0;
 
     status = _cairo_gstate_in_stroke (cr->gstate,
@@ -2371,7 +2366,7 @@ cairo_in_fill (cairo_t *cr, double x, double y)
 {
     cairo_bool_t inside;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return 0;
 
     _cairo_gstate_in_fill (cr->gstate,
@@ -2415,7 +2410,7 @@ cairo_stroke_extents (cairo_t *cr,
 {
     cairo_status_t status;
 
-    if (cr->status) {
+    if (unlikely (cr->status)) {
 	if (x1)
 	    *x1 = 0.0;
 	if (y1)
@@ -2466,7 +2461,7 @@ cairo_fill_extents (cairo_t *cr,
 {
     cairo_status_t status;
 
-    if (cr->status) {
+    if (unlikely (cr->status)) {
 	if (x1)
 	    *x1 = 0.0;
 	if (y1)
@@ -2543,7 +2538,7 @@ cairo_clip_preserve (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_clip (cr->gstate, cr->path);
@@ -2573,7 +2568,7 @@ cairo_reset_clip (cairo_t *cr)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_reset_clip (cr->gstate);
@@ -2601,7 +2596,7 @@ cairo_clip_extents (cairo_t *cr,
 {
     cairo_status_t status;
 
-    if (cr->status) {
+    if (unlikely (cr->status)) {
 	if (x1)
 	    *x1 = 0.0;
 	if (y1)
@@ -2659,7 +2654,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
 cairo_rectangle_list_t *
 cairo_copy_clip_rectangle_list (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return _cairo_rectangle_list_create_in_error (cr->status);
 
     return _cairo_gstate_copy_clip_rectangle_list (cr->gstate);
@@ -2724,7 +2719,7 @@ cairo_select_font_face (cairo_t              *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight);
@@ -2752,7 +2747,7 @@ cairo_font_extents (cairo_t              *cr,
     extents->max_x_advance = 0.0;
     extents->max_y_advance = 0.0;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_get_font_extents (cr->gstate, extents);
@@ -2775,7 +2770,7 @@ cairo_set_font_face (cairo_t           *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_font_face (cr->gstate, font_face);
@@ -2807,7 +2802,7 @@ cairo_get_font_face (cairo_t *cr)
     cairo_status_t status;
     cairo_font_face_t *font_face;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return (cairo_font_face_t*) &_cairo_font_face_nil;
 
     status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
@@ -2839,7 +2834,7 @@ cairo_set_font_size (cairo_t *cr, double size)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_font_size (cr->gstate, size);
@@ -2867,7 +2862,7 @@ cairo_set_font_matrix (cairo_t		    *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = _cairo_gstate_set_font_matrix (cr->gstate, matrix);
@@ -2886,7 +2881,7 @@ cairo_set_font_matrix (cairo_t		    *cr,
 void
 cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix)
 {
-    if (cr->status) {
+    if (unlikely (cr->status)) {
 	cairo_matrix_init_identity (matrix);
 	return;
     }
@@ -2911,7 +2906,7 @@ cairo_set_font_options (cairo_t                    *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     status = cairo_font_options_status ((cairo_font_options_t *) options);
@@ -2943,7 +2938,7 @@ cairo_get_font_options (cairo_t              *cr,
     if (cairo_font_options_status (options))
 	return;
 
-    if (cr->status) {
+    if (unlikely (cr->status)) {
 	_cairo_font_options_init_default (options);
 	return;
     }
@@ -2971,7 +2966,7 @@ cairo_set_scaled_font (cairo_t                   *cr,
     cairo_status_t status;
     cairo_bool_t was_previous;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (scaled_font == NULL) {
@@ -3033,7 +3028,7 @@ cairo_get_scaled_font (cairo_t *cr)
     cairo_status_t status;
     cairo_scaled_font_t *scaled_font;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return _cairo_scaled_font_create_in_error (cr->status);
 
     status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
@@ -3082,7 +3077,7 @@ cairo_text_extents (cairo_t              *cr,
     extents->x_advance = 0.0;
     extents->y_advance = 0.0;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (utf8 == NULL)
@@ -3140,7 +3135,7 @@ cairo_glyph_extents (cairo_t                *cr,
     extents->x_advance = 0.0;
     extents->y_advance = 0.0;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (num_glyphs == 0)
@@ -3203,7 +3198,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
     cairo_glyph_t stack_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
     cairo_text_cluster_t stack_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (utf8 == NULL)
@@ -3283,7 +3278,7 @@ cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (num_glyphs == 0)
@@ -3354,7 +3349,7 @@ cairo_show_text_glyphs (cairo_t			   *cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     /* A slew of sanity checks */
@@ -3445,7 +3440,7 @@ cairo_text_path  (cairo_t *cr, const char *utf8)
     int num_glyphs;
     double x, y;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (utf8 == NULL)
@@ -3511,7 +3506,7 @@ cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (num_glyphs == 0)
@@ -3545,7 +3540,7 @@ cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
 cairo_operator_t
 cairo_get_operator (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_GSTATE_OPERATOR_DEFAULT;
 
     return _cairo_gstate_get_operator (cr->gstate);
@@ -3562,7 +3557,7 @@ cairo_get_operator (cairo_t *cr)
 double
 cairo_get_tolerance (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_GSTATE_TOLERANCE_DEFAULT;
 
     return _cairo_gstate_get_tolerance (cr->gstate);
@@ -3580,7 +3575,7 @@ slim_hidden_def (cairo_get_tolerance);
 cairo_antialias_t
 cairo_get_antialias (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_ANTIALIAS_DEFAULT;
 
     return _cairo_gstate_get_antialias (cr->gstate);
@@ -3600,7 +3595,7 @@ cairo_get_antialias (cairo_t *cr)
 cairo_bool_t
 cairo_has_current_point (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
     return FALSE;
 
     return cr->path->has_current_point;
@@ -3673,7 +3668,7 @@ slim_hidden_def(cairo_get_current_point);
 cairo_fill_rule_t
 cairo_get_fill_rule (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_GSTATE_FILL_RULE_DEFAULT;
 
     return _cairo_gstate_get_fill_rule (cr->gstate);
@@ -3693,7 +3688,7 @@ cairo_get_fill_rule (cairo_t *cr)
 double
 cairo_get_line_width (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
 
     return _cairo_gstate_get_line_width (cr->gstate);
@@ -3711,7 +3706,7 @@ slim_hidden_def (cairo_get_line_width);
 cairo_line_cap_t
 cairo_get_line_cap (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_GSTATE_LINE_CAP_DEFAULT;
 
     return _cairo_gstate_get_line_cap (cr->gstate);
@@ -3728,7 +3723,7 @@ cairo_get_line_cap (cairo_t *cr)
 cairo_line_join_t
 cairo_get_line_join (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_GSTATE_LINE_JOIN_DEFAULT;
 
     return _cairo_gstate_get_line_join (cr->gstate);
@@ -3745,7 +3740,7 @@ cairo_get_line_join (cairo_t *cr)
 double
 cairo_get_miter_limit (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
         return CAIRO_GSTATE_MITER_LIMIT_DEFAULT;
 
     return _cairo_gstate_get_miter_limit (cr->gstate);
@@ -3761,7 +3756,7 @@ cairo_get_miter_limit (cairo_t *cr)
 void
 cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
 {
-    if (cr->status) {
+    if (unlikely (cr->status)) {
 	cairo_matrix_init_identity (matrix);
 	return;
     }
@@ -3789,7 +3784,7 @@ slim_hidden_def (cairo_get_matrix);
 cairo_surface_t *
 cairo_get_target (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return _cairo_surface_create_in_error (cr->status);
 
     return _cairo_gstate_get_original_target (cr->gstate);
@@ -3819,7 +3814,7 @@ slim_hidden_def (cairo_get_target);
 cairo_surface_t *
 cairo_get_group_target (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return _cairo_surface_create_in_error (cr->status);
 
     return _cairo_gstate_get_target (cr->gstate);
@@ -3854,7 +3849,7 @@ cairo_get_group_target (cairo_t *cr)
 cairo_path_t *
 cairo_copy_path (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return _cairo_path_create_in_error (cr->status);
 
     return _cairo_path_create (cr->path, cr->gstate);
@@ -3896,7 +3891,7 @@ cairo_copy_path (cairo_t *cr)
 cairo_path_t *
 cairo_copy_path_flat (cairo_t *cr)
 {
-    if (cr->status)
+    if (unlikely (cr->status))
 	return _cairo_path_create_in_error (cr->status);
 
     return _cairo_path_create_flat (cr->path, cr->gstate);
@@ -3920,7 +3915,7 @@ cairo_append_path (cairo_t		*cr,
 {
     cairo_status_t status;
 
-    if (cr->status)
+    if (unlikely (cr->status))
 	return;
 
     if (path == NULL) {
commit f3880283331f3bda374e24fd0e1de677d8d368a9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 27 20:18:18 2009 +0100

    [gstate] Avoid temporary allocation for transformed patterns
    
    Observe that patterns are not altered during an operation and so we are
    safe to use the data from the original pattern without copying. (This is
    enforced through the declaration that the backends operate on constant
    patterns which are not allowed to be referenced or destroyed.)

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 8f6f01b..8f206ad 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -827,14 +827,13 @@ _cairo_gstate_path_extents (cairo_gstate_t     *gstate,
 	*y2 = py2;
 }
 
-static cairo_status_t
+static void
 _cairo_gstate_copy_transformed_pattern (cairo_gstate_t  *gstate,
-					cairo_pattern_t **pattern,
+					cairo_pattern_t *pattern,
 					cairo_pattern_t *original,
 					cairo_matrix_t  *ctm_inverse)
 {
-    cairo_status_t status;
-    cairo_bool_t have_copy = FALSE;
+    _cairo_pattern_init_static_copy (pattern, original);
 
     /* apply device_transform first so that it is transformed by ctm_inverse */
     if (original->type == CAIRO_PATTERN_TYPE_SURFACE) {
@@ -844,60 +843,38 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t  *gstate,
         surface_pattern = (cairo_surface_pattern_t *) original;
         surface = surface_pattern->surface;
 
-	if (_cairo_surface_has_device_transform (surface)) {
-	    status = _cairo_pattern_init_copy (*pattern, original);
-	    if (unlikely (status))
-		return status;
-
-	    have_copy = TRUE;
-
-	    _cairo_pattern_transform (*pattern, &surface->device_transform);
-	}
-    }
-
-    if (! _cairo_matrix_is_identity (ctm_inverse)) {
-	if (! have_copy) {
-	    status = _cairo_pattern_init_copy (*pattern, original);
-	    if (unlikely (status))
-		return status;
-
-	    have_copy = TRUE;
-	}
-
-	_cairo_pattern_transform (*pattern, ctm_inverse);
+	if (_cairo_surface_has_device_transform (surface))
+	    _cairo_pattern_transform (pattern, &surface->device_transform);
     }
 
-    if (! have_copy)
-	*pattern = original;
-
-    return CAIRO_STATUS_SUCCESS;
+    if (! _cairo_matrix_is_identity (ctm_inverse))
+	_cairo_pattern_transform (pattern, ctm_inverse);
 }
 
-static cairo_status_t
+static void
 _cairo_gstate_copy_transformed_source (cairo_gstate_t   *gstate,
-				       cairo_pattern_t **pattern)
+				       cairo_pattern_t  *pattern)
 {
-    return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
-					           gstate->source,
-					           &gstate->source_ctm_inverse);
+    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+					    gstate->source,
+					    &gstate->source_ctm_inverse);
 }
 
-static cairo_status_t
+static void
 _cairo_gstate_copy_transformed_mask (cairo_gstate_t   *gstate,
-				     cairo_pattern_t **pattern,
+				     cairo_pattern_t  *pattern,
 				     cairo_pattern_t  *mask)
 {
-    return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
-					           mask,
-					           &gstate->ctm_inverse);
+    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+					    mask,
+					    &gstate->ctm_inverse);
 }
 
 cairo_status_t
 _cairo_gstate_paint (cairo_gstate_t *gstate)
 {
     cairo_status_t status;
-    cairo_pattern_t *pattern;
-    cairo_pattern_union_t pattern_stack;
+    cairo_pattern_union_t pattern;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -906,19 +883,12 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
     if (unlikely (status))
 	return status;
 
-    pattern = &pattern_stack.base;
-    status = _cairo_gstate_copy_transformed_source (gstate, &pattern);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_surface_paint (gstate->target,
-				   gstate->op,
-				   pattern, NULL);
-
-    if (pattern == &pattern_stack.base)
-	_cairo_pattern_fini (pattern);
+    _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
 
-    return status;
+    return _cairo_surface_paint (gstate->target,
+				 gstate->op,
+				 &pattern.base,
+				 NULL);
 }
 
 cairo_status_t
@@ -926,8 +896,7 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
 		    cairo_pattern_t *mask)
 {
     cairo_status_t status;
-    cairo_pattern_union_t source_pattern_stack, mask_pattern_stack;
-    cairo_pattern_t *source_pattern, *mask_pattern;
+    cairo_pattern_union_t source_pattern, mask_pattern;
 
     if (mask->status)
 	return mask->status;
@@ -939,36 +908,21 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
     if (unlikely (status))
 	return status;
 
-    source_pattern = &source_pattern_stack.base;
-    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern);
-    if (unlikely (status))
-	return status;
-
-    mask_pattern = &mask_pattern_stack.base;
-    status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern, mask);
-    if (unlikely (status))
-	goto CLEANUP_SOURCE;
+    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
 
-    status = _cairo_surface_mask (gstate->target,
-				  gstate->op,
-				  source_pattern,
-				  mask_pattern, NULL);
-
-    if (mask_pattern == &mask_pattern_stack.base)
-	_cairo_pattern_fini (&mask_pattern_stack.base);
-CLEANUP_SOURCE:
-    if (source_pattern == &source_pattern_stack.base)
-	_cairo_pattern_fini (&source_pattern_stack.base);
-
-    return status;
+    return _cairo_surface_mask (gstate->target,
+				gstate->op,
+				&source_pattern.base,
+				&mask_pattern.base,
+				NULL);
 }
 
 cairo_status_t
 _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
-    cairo_pattern_union_t source_pattern_stack;
-    cairo_pattern_t *source_pattern;
+    cairo_pattern_union_t source_pattern;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -980,26 +934,18 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
     if (unlikely (status))
 	return status;
 
-    source_pattern = &source_pattern_stack.base;
-    status = _cairo_gstate_copy_transformed_source (gstate,
-	                                            &source_pattern);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_surface_stroke (gstate->target,
-				    gstate->op,
-				    source_pattern,
-				    path,
-				    &gstate->stroke_style,
-				    &gstate->ctm,
-				    &gstate->ctm_inverse,
-				    gstate->tolerance,
-				    gstate->antialias, NULL);
-
-    if (source_pattern == &source_pattern_stack.base)
-	_cairo_pattern_fini (&source_pattern_stack.base);
+    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
 
-    return status;
+    return _cairo_surface_stroke (gstate->target,
+				  gstate->op,
+				  &source_pattern.base,
+				  path,
+				  &gstate->stroke_style,
+				  &gstate->ctm,
+				  &gstate->ctm_inverse,
+				  gstate->tolerance,
+				  gstate->antialias,
+				  NULL);
 }
 
 cairo_status_t
@@ -1064,8 +1010,7 @@ cairo_status_t
 _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
-    cairo_pattern_union_t pattern_stack;
-    cairo_pattern_t *pattern;
+    cairo_pattern_union_t pattern;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1074,24 +1019,16 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
     if (unlikely (status))
 	return status;
 
-    pattern = &pattern_stack.base;
-    status = _cairo_gstate_copy_transformed_source (gstate, &pattern);
-    if (unlikely (status))
-	return status;
+    _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
 
-    status = _cairo_surface_fill (gstate->target,
-				  gstate->op,
-				  pattern,
-				  path,
-				  gstate->fill_rule,
-				  gstate->tolerance,
-				  gstate->antialias,
-				  NULL);
-
-    if (pattern == &pattern_stack.base)
-	_cairo_pattern_fini (&pattern_stack.base);
-
-    return status;
+    return _cairo_surface_fill (gstate->target,
+				gstate->op,
+				&pattern.base,
+				path,
+				gstate->fill_rule,
+				gstate->tolerance,
+				gstate->antialias,
+				NULL);
 }
 
 void
@@ -1632,8 +1569,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 				int			    num_clusters,
 				cairo_text_cluster_flags_t  cluster_flags)
 {
-    cairo_pattern_union_t source_pattern_stack;
-    cairo_pattern_t *source_pattern;
+    cairo_pattern_union_t source_pattern;
     cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
     cairo_glyph_t *transformed_glyphs;
     cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
@@ -1686,10 +1622,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (status || num_glyphs == 0)
 	goto CLEANUP_GLYPHS;
 
-    source_pattern = &source_pattern_stack.base;
-    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern);
-    if (unlikely (status))
-	goto CLEANUP_GLYPHS;
+    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
 
     /* For really huge font sizes, we can just do path;fill instead of
      * show_glyphs, as show_glyphs would put excess pressure on the cache,
@@ -1705,7 +1638,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
 	status = _cairo_surface_show_text_glyphs (gstate->target,
 						  gstate->op,
-						  source_pattern,
+						  &source_pattern.base,
 						  utf8, utf8_len,
 						  transformed_glyphs, num_glyphs,
 						  transformed_clusters, num_clusters,
@@ -1723,7 +1656,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 	if (status == CAIRO_STATUS_SUCCESS)
 	  status = _cairo_surface_fill (gstate->target,
 					gstate->op,
-					source_pattern,
+					&source_pattern.base,
 					&path,
 					CAIRO_FILL_RULE_WINDING,
 					gstate->tolerance,
@@ -1732,9 +1665,6 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 	_cairo_path_fixed_fini (&path);
     }
 
-    if (source_pattern == &source_pattern_stack.base)
-	_cairo_pattern_fini (&source_pattern_stack.base);
-
 CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
       cairo_glyph_free (transformed_glyphs);
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 38db980..c97ebe6 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -224,6 +224,37 @@ _cairo_pattern_init_copy (cairo_pattern_t	*pattern,
     return CAIRO_STATUS_SUCCESS;
 }
 
+void
+_cairo_pattern_init_static_copy (cairo_pattern_t	*pattern,
+				 const cairo_pattern_t *other)
+{
+    int size;
+
+    assert (other->status == CAIRO_STATUS_SUCCESS);
+
+    switch (other->type) {
+    default:
+	ASSERT_NOT_REACHED;
+    case CAIRO_PATTERN_TYPE_SOLID:
+	size = sizeof (cairo_solid_pattern_t);
+	break;
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	size = sizeof (cairo_surface_pattern_t);
+	break;
+    case CAIRO_PATTERN_TYPE_LINEAR:
+	size = sizeof (cairo_linear_pattern_t);
+	break;
+    case CAIRO_PATTERN_TYPE_RADIAL:
+	size = sizeof (cairo_radial_pattern_t);
+	break;
+    }
+
+    memcpy (pattern, other, size);
+
+    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
+    _cairo_user_data_array_init (&pattern->user_data);
+}
+
 cairo_status_t
 _cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
 			      const cairo_pattern_t *other)
diff --git a/src/cairoint.h b/src/cairoint.h
index 3d6acc1..98bef24 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2476,6 +2476,10 @@ cairo_private cairo_status_t
 _cairo_pattern_init_copy (cairo_pattern_t	*pattern,
 			  const cairo_pattern_t *other);
 
+cairo_private void
+_cairo_pattern_init_static_copy (cairo_pattern_t	*pattern,
+				 const cairo_pattern_t *other);
+
 cairo_private cairo_status_t
 _cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
 			      const cairo_pattern_t *other);
commit 3759c7b34b662ccdc0486c68798aca0a6438ab7e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 27 19:38:30 2009 +0100

    [perf] Enable the null-backend for trace replays.

diff --git a/perf/cairo-perf-trace.c b/perf/cairo-perf-trace.c
index 512bfa2..340601b 100644
--- a/perf/cairo-perf-trace.c
+++ b/perf/cairo-perf-trace.c
@@ -106,7 +106,7 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
 #if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1,9,3)
     case CAIRO_SURFACE_TYPE_QT:
 #endif
-#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1,9,3)
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,9,3)
     case CAIRO_INTERNAL_SURFACE_TYPE_NULL:
 #endif
 	return TRUE;
commit 8d4c704129132effa10fb9242239952c2f4b7721
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 27 19:34:20 2009 +0100

    [ft] Cache the resolved font face
    
    Keep the resolved font face alive whilst the default FcConfig remains
    identical i.e. resolve the pattern again if the system configuration
    changes (e.g. a new font is added or the rules are updated). This should
    retain the benefits of lazily resolving font patterns whilst improving
    performance by reducing the number of calls to FcFontMatch().

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index b62a923..d66732f 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -139,6 +139,8 @@ struct _cairo_ft_font_face {
 
 #if CAIRO_HAS_FC_FONT
     FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
+    cairo_font_face_t *resolved_font_face;
+    FcConfig *resolved_config;
 #endif
 };
 
@@ -2289,8 +2291,10 @@ _cairo_ft_font_face_destroy (void *abstract_face)
     }
 
 #if CAIRO_HAS_FC_FONT
-    if (font_face->pattern)
+    if (font_face->pattern) {
 	FcPatternDestroy (font_face->pattern);
+	cairo_font_face_destroy (font_face->resolved_font_face);
+    }
 #endif
 }
 
@@ -2317,10 +2321,32 @@ _cairo_ft_font_face_get_implementation (void                     *abstract_face,
      * unscaled font.  Otherwise, use the ones stored in font_face.
      */
     if (font_face->pattern) {
-	return _cairo_ft_resolve_pattern (font_face->pattern,
-					  font_matrix,
-					  ctm,
-					  options);
+	cairo_font_face_t *resolved;
+
+	/* Cache the resolved font whilst the FcConfig remains consistent. */
+	resolved = font_face->resolved_font_face;
+	if (resolved != NULL) {
+	    if (! FcInitBringUptoDate ()) {
+		_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+		return (cairo_font_face_t *) &_cairo_font_face_nil;
+	    }
+
+	    if (font_face->resolved_config == FcConfigGetCurrent ())
+		return resolved;
+
+	    cairo_font_face_destroy (resolved);
+	    font_face->resolved_font_face = NULL;
+	}
+
+	resolved = _cairo_ft_resolve_pattern (font_face->pattern,
+					      font_matrix,
+					      ctm,
+					      options);
+
+	font_face->resolved_font_face = cairo_font_face_reference (resolved);
+	font_face->resolved_config = FcConfigGetCurrent ();
+
+	return resolved;
     }
 #endif
 
@@ -2359,6 +2385,9 @@ _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
+    font_face->resolved_font_face = NULL;
+    font_face->resolved_config = NULL;
+
     _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
 
     *out = &font_face->base;


More information about the cairo-commit mailing list