[cairo-commit] 14 commits - src/cairo.c src/cairo-cff-subset.c src/cairo-debug.c src/cairo-font-face.c src/cairo-ft-font.c src/cairo-gstate.c src/cairoint.h src/cairo-matrix.c src/cairo-output-stream.c src/cairo-scaled-font.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Oct 4 09:36:55 PDT 2007


 src/cairo-cff-subset.c    |  291 +++++++++++++++++++++++++++++++++-------------
 src/cairo-debug.c         |    4 
 src/cairo-font-face.c     |   46 +++++--
 src/cairo-ft-font.c       |    8 -
 src/cairo-gstate.c        |   27 +++-
 src/cairo-matrix.c        |   10 +
 src/cairo-output-stream.c |   12 +
 src/cairo-scaled-font.c   |   88 +++++++++----
 src/cairo.c               |   51 +++++++-
 src/cairoint.h            |    9 +
 10 files changed, 409 insertions(+), 137 deletions(-)

New commits:
diff-tree 37fd0d8967df21695d6536af1d7aedbeef2d2449 (from add0959328117e2023db0ba2432ed29ecb93275e)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 17:12:26 2007 +0100

    [cairo-cff-subset] Propagate errors and review error paths.
    
    Ensure that errors get duly propagated back to the caller and all
    locally allocated resources are freed along error paths.

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 7bc7cb9..d1826df 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -385,6 +385,7 @@ cff_index_append_copy (cairo_array_t *in
                        unsigned int length)
 {
     cff_index_element_t element;
+    cairo_status_t status;
 
     element.length = length;
     element.is_copy = TRUE;
@@ -394,7 +395,13 @@ cff_index_append_copy (cairo_array_t *in
 
     memcpy (element.data, object, element.length);
 
-    return _cairo_array_append (index, &element);
+    status = _cairo_array_append (index, &element);
+    if (status) {
+	free (element.data);
+	return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -420,10 +427,14 @@ _cairo_cff_dict_equal (const void *key_a
     return op_a->operator == op_b->operator;
 }
 
-static void
+static cairo_status_t
 cff_dict_init (cairo_hash_table_t **dict)
 {
     *dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
+    if (*dict == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -697,6 +708,7 @@ cairo_cff_font_read_private_dict (cairo_
                                   unsigned char      *ptr,
                                   int                 size)
 {
+    cairo_int_status_t status;
     unsigned char buf[10];
     unsigned char *end_buf;
     int offset;
@@ -704,16 +716,23 @@ cairo_cff_font_read_private_dict (cairo_
     unsigned char *operand;
     unsigned char *p;
 
-    cff_dict_read (private_dict, ptr, size);
+    status = cff_dict_read (private_dict, ptr, size);
+    if (status)
+	return status;
+
     operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
     if (operand) {
         decode_integer (operand, &offset);
         p = ptr + offset;
-        cff_index_read (local_sub_index, &p, font->data_end);
+        status = cff_index_read (local_sub_index, &p, font->data_end);
+	if (status)
+	    return status;
 
         /* Use maximum sized encoding to reserve space for later modification. */
         end_buf = encode_integer_max (buf, 0);
-        cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
+        status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
+	if (status)
+	    return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -791,11 +810,10 @@ cairo_cff_font_read_cid_fontdict (cairo_
     }
 
     for (i = 0; i < font->num_fontdicts; i++) {
-        cff_dict_init (&font->fd_dict[i]);
-        if (font->fd_dict[i] == NULL) {
-            status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+        status = cff_dict_init (&font->fd_dict[i]);
+        if (status)
             goto fail;
-        }
+
         element = _cairo_array_index (&index, i);
         status = cff_dict_read (font->fd_dict[i], element->data, element->length);
         if (status)
@@ -808,11 +826,10 @@ cairo_cff_font_read_cid_fontdict (cairo_
         }
         operand = decode_integer (operand, &size);
         decode_integer (operand, &offset);
-        cff_dict_init (&font->fd_private_dict[i]);
-        if (font->fd_private_dict[i] == NULL) {
-            status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+        status = cff_dict_init (&font->fd_private_dict[i]);
+	if (status)
             goto fail;
-        }
+
         cff_index_init (&font->fd_local_sub_index[i]);
         status = cairo_cff_font_read_private_dict (font,
                                                    font->fd_private_dict[i],
@@ -877,28 +894,49 @@ cairo_cff_font_read_top_dict (cairo_cff_
     if (font->is_cid) {
         operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
         decode_integer (operand, &offset);
-        cairo_cff_font_read_fdselect (font, font->data + offset);
+        status = cairo_cff_font_read_fdselect (font, font->data + offset);
+	if (status)
+	    goto fail;
 
         operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
         decode_integer (operand, &offset);
-        cairo_cff_font_read_cid_fontdict (font, font->data + offset);
+        status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
+	if (status)
+	    goto fail;
     } else {
         operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
         operand = decode_integer (operand, &size);
         decode_integer (operand, &offset);
-        cairo_cff_font_read_private_dict (font,
-                                          font->private_dict,
-                                          &font->local_sub_index,
-                                          font->data + offset,
-                                          size);
+        status = cairo_cff_font_read_private_dict (font,
+                                                   font->private_dict,
+						   &font->local_sub_index,
+						   font->data + offset,
+						   size);
+	if (status)
+	    goto fail;
     }
 
     /* Use maximum sized encoding to reserve space for later modification. */
     end_buf = encode_integer_max (buf, 0);
-    cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
-    cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
-    cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
-    cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
+    status = cff_dict_set_operands (font->top_dict,
+	                            CHARSTRINGS_OP, buf, end_buf - buf);
+    if (status)
+	goto fail;
+
+    status = cff_dict_set_operands (font->top_dict,
+	                            FDSELECT_OP, buf, end_buf - buf);
+    if (status)
+	goto fail;
+
+    status = cff_dict_set_operands (font->top_dict,
+	                            FDARRAY_OP, buf, end_buf - buf);
+    if (status)
+	goto fail;
+
+    status = cff_dict_set_operands (font->top_dict,
+	                            CHARSET_OP, buf, end_buf - buf);
+    if (status)
+	goto fail;
 
     cff_dict_remove (font->top_dict, ENCODING_OP);
     cff_dict_remove (font->top_dict, PRIVATE_OP);
@@ -952,9 +990,10 @@ cairo_cff_font_read_font (cairo_cff_font
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
 {
+    cairo_status_t status;
     unsigned char buf[30];
     unsigned char *p;
     int sid1, sid2;
@@ -974,10 +1013,16 @@ cairo_cff_font_set_ros_strings (cairo_cf
     p = encode_integer (buf, sid1);
     p = encode_integer (p, sid2);
     p = encode_integer (p, 0);
-    cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
+    status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
+    if (status)
+	return status;
 
     p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
-    cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
+    status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
+    if (status)
+	return status;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
@@ -1007,7 +1052,9 @@ cairo_cff_font_subset_dict_string(cairo_
         return status;
 
     p = encode_integer (buf, sid);
-    cff_dict_set_operands (dict, operator, buf, p - buf);
+    status = cff_dict_set_operands (dict, operator, buf, p - buf);
+    if (status)
+	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1107,13 +1154,19 @@ cairo_cff_font_create_cid_fontdict (cair
 {
     unsigned char buf[100];
     unsigned char *end_buf;
+    cairo_status_t status;
 
     font->num_fontdicts = 1;
     font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
     if (font->fd_dict == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    cff_dict_init (&font->fd_dict[0]);
+    if (cff_dict_init (&font->fd_dict[0])) {
+	free (font->fd_dict);
+	font->fd_dict = NULL;
+	font->num_fontdicts = 0;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     font->fd_subset_map = malloc (sizeof (int));
     if (font->fd_subset_map == NULL)
@@ -1130,7 +1183,9 @@ cairo_cff_font_create_cid_fontdict (cair
      * space for any value later */
     end_buf = encode_integer_max (buf, 0);
     end_buf = encode_integer_max (end_buf, 0);
-    cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
+    status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
+    if (status)
+	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1144,6 +1199,7 @@ cairo_cff_font_subset_strings (cairo_cff
     status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
     if (status)
         return status;
+
     if (font->is_cid) {
         for (i = 0; i < font->num_subset_fontdicts; i++) {
             status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
@@ -1166,16 +1222,20 @@ cairo_cff_font_subset_font (cairo_cff_fo
 {
     cairo_status_t status;
 
-    cairo_cff_font_set_ros_strings (font);
+    status = cairo_cff_font_set_ros_strings (font);
+    if (status)
+	return status;
 
     status = cairo_cff_font_subset_charstrings (font);
     if (status)
         return status;
 
     if (font->is_cid)
-        cairo_cff_font_subset_fontdict (font);
+        status = cairo_cff_font_subset_fontdict (font);
     else
-        cairo_cff_font_create_cid_fontdict (font);
+        status = cairo_cff_font_create_cid_fontdict (font);
+    if (status)
+	return status;
 
     status = cairo_cff_font_subset_strings (font);
     if (status)
@@ -1218,21 +1278,25 @@ cairo_cff_font_write_header (cairo_cff_f
 static cairo_status_t
 cairo_cff_font_write_name (cairo_cff_font_t *font)
 {
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_array_t index;
-    cairo_status_t status;
 
     cff_index_init (&index);
+
     status = cff_index_append_copy (&index,
                                     (unsigned char *) font->subset_font_name,
                                     strlen(font->subset_font_name));
     if (status)
-        return status;
+	goto FAIL;
+
     status = cff_index_write (&index, &font->output);
     if (status)
-        return status;
+        goto FAIL;
+
+FAIL:
     cff_index_fini (&index);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 static cairo_status_t
@@ -1435,6 +1499,7 @@ cairo_cff_font_write_private_dict (cairo
     status = cff_dict_write (private_dict, &font->output);
     if (status)
         return status;
+
     size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
     /* private entry has two operands - size and offset */
     buf_end = encode_integer_max (buf, size);
@@ -1483,7 +1548,7 @@ static cairo_status_t
 cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t  *font)
 {
     unsigned int i;
-    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_int_status_t status;
 
     if (font->is_cid) {
         for (i = 0; i < font->num_subset_fontdicts; i++) {
@@ -1510,13 +1575,18 @@ cairo_cff_font_write_cid_private_dict_an
                                                     0,
                                                     font->fd_dict[0],
                                                     font->private_dict);
+	if (status)
+	    return status;
+
         status = cairo_cff_font_write_local_sub (font,
                                                  0,
                                                  font->private_dict,
                                                  &font->local_sub_index);
+	if (status)
+	    return status;
     }
 
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 typedef cairo_status_t
@@ -1701,7 +1771,7 @@ _cairo_cff_font_create (cairo_scaled_fon
     font->subset_font_name = strdup (subset_name);
     if (font->subset_font_name == NULL) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail3;
+	goto fail2;
     }
     font->x_min = (int16_t) be16_to_cpu (head.x_min);
     font->y_min = (int16_t) be16_to_cpu (head.y_min);
@@ -1737,7 +1807,7 @@ _cairo_cff_font_create (cairo_scaled_fon
         font->font_name = malloc (30);
         if (font->font_name == NULL) {
             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-            goto fail4;
+            goto fail3;
         }
         snprintf(font->font_name, 30, "CairoFont-%u-%u",
                  scaled_font_subset->font_id,
@@ -1754,25 +1824,35 @@ _cairo_cff_font_create (cairo_scaled_fon
     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
     if (font->widths == NULL) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        goto fail5;
+        goto fail4;
     }
-    cairo_cff_font_create_set_widths (font);
+
+    status = cairo_cff_font_create_set_widths (font);
+    if (status)
+	goto fail5;
 
     font->data_length = data_length;
     font->data = malloc (data_length);
     if (font->data == NULL) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        goto fail6;
+        goto fail5;
     }
     status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
                                                   TT_TAG_CFF, 0, font->data,
                                                   &font->data_length);
     if (status)
-        goto fail7;
+        goto fail6;
+
     font->data_end = font->data + font->data_length;
 
-    cff_dict_init (&font->top_dict);
-    cff_dict_init (&font->private_dict);
+    status = cff_dict_init (&font->top_dict);
+    if (status)
+	goto fail6;
+
+    status = cff_dict_init (&font->private_dict);
+    if (status)
+	goto fail7;
+
     cff_index_init (&font->strings_index);
     cff_index_init (&font->charstrings_index);
     cff_index_init (&font->global_sub_index);
@@ -1793,16 +1873,17 @@ _cairo_cff_font_create (cairo_scaled_fon
     return CAIRO_STATUS_SUCCESS;
 
 fail7:
-    free (font->data);
+    _cairo_hash_table_destroy (font->top_dict);
 fail6:
-    free (font->widths);
+    free (font->data);
 fail5:
-    free (font->font_name);
+    free (font->widths);
 fail4:
-    free (font->subset_font_name);
+    free (font->font_name);
 fail3:
-    _cairo_array_fini (&font->output);
+    free (font->subset_font_name);
 fail2:
+    _cairo_array_fini (&font->output);
     free (font);
 fail1:
     free (name);
@@ -1886,12 +1967,16 @@ _cairo_cff_subset_init (cairo_cff_subset
 	goto fail1;
 
     cff_subset->base_font = strdup (font->font_name);
-    if (cff_subset->base_font == NULL)
+    if (cff_subset->base_font == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail1;
+    }
 
     cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
-    if (cff_subset->widths == NULL)
+    if (cff_subset->widths == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail2;
+    }
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
         cff_subset->widths[i] = font->widths[i];
 
@@ -1903,8 +1988,10 @@ _cairo_cff_subset_init (cairo_cff_subset
     cff_subset->descent = font->descent;
 
     cff_subset->data = malloc (length);
-    if (cff_subset->data == NULL)
+    if (cff_subset->data == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail3;
+    }
 
     memcpy (cff_subset->data, data, length);
     cff_subset->data_length = length;
@@ -1954,13 +2041,13 @@ _cairo_cff_font_fallback_create (cairo_s
     font->subset_font_name = strdup (subset_name);
     if (font->subset_font_name == NULL) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail2;
+	goto fail1;
     }
 
     font->font_name = strdup (subset_name);
     if (font->subset_font_name == NULL) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail3;
+	goto fail2;
     }
 
     font->x_min = 0;
@@ -1973,15 +2060,21 @@ _cairo_cff_font_fallback_create (cairo_s
     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
     if (font->widths == NULL) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        goto fail4;
+        goto fail3;
     }
 
     font->data_length = 0;
     font->data = NULL;
-    font->data_end = 0;
+    font->data_end = NULL;
+
+    status = cff_dict_init (&font->top_dict);
+    if (status)
+	goto fail4;
+
+    status = cff_dict_init (&font->private_dict);
+    if (status)
+	goto fail5;
 
-    cff_dict_init (&font->top_dict);
-    cff_dict_init (&font->private_dict);
     cff_index_init (&font->strings_index);
     cff_index_init (&font->charstrings_index);
     cff_index_init (&font->global_sub_index);
@@ -2000,13 +2093,16 @@ _cairo_cff_font_fallback_create (cairo_s
 
     return CAIRO_STATUS_SUCCESS;
 
+fail5:
+    _cairo_hash_table_destroy (font->top_dict);
 fail4:
-    free (font->font_name);
+    free (font->widths);
 fail3:
-    free (font->subset_font_name);
+    free (font->font_name);
 fail2:
-    _cairo_array_fini (&font->output);
+    free (font->subset_font_name);
 fail1:
+    _cairo_array_fini (&font->output);
     free (font);
     return _cairo_error (status);
 }
@@ -2037,16 +2133,40 @@ cairo_cff_font_fallback_generate (cairo_
     end_buf = encode_integer (end_buf, type2_subset->y_min);
     end_buf = encode_integer (end_buf, type2_subset->x_max);
     end_buf = encode_integer (end_buf, type2_subset->y_max);
-    cff_dict_set_operands (font->top_dict, FONTBBOX_OP, buf, end_buf - buf);
+    status = cff_dict_set_operands (font->top_dict,
+	                            FONTBBOX_OP, buf, end_buf - buf);
+    if (status)
+	return status;
+
     end_buf = encode_integer_max (buf, 0);
-    cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
-    cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
-    cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
-    cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
-    cairo_cff_font_set_ros_strings (font);
+    status = cff_dict_set_operands (font->top_dict,
+	                            CHARSTRINGS_OP, buf, end_buf - buf);
+    if (status)
+	return status;
+
+    status = cff_dict_set_operands (font->top_dict,
+	                            FDSELECT_OP, buf, end_buf - buf);
+    if (status)
+	return status;
+
+    status = cff_dict_set_operands (font->top_dict,
+	                            FDARRAY_OP, buf, end_buf - buf);
+    if (status)
+	return status;
+
+    status = cff_dict_set_operands (font->top_dict,
+	                            CHARSET_OP, buf, end_buf - buf);
+    if (status)
+	return status;
+
+    status = cairo_cff_font_set_ros_strings (font);
+    if (status)
+	return status;
 
     /* Create CID FD dictionary */
-    cairo_cff_font_create_cid_fontdict (font);
+    status = cairo_cff_font_create_cid_fontdict (font);
+    if (status)
+	return status;
 
     /* Create charstrings */
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
@@ -2092,15 +2212,19 @@ _cairo_cff_fallback_init (cairo_cff_subs
 
     status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
     if (status)
-	goto fail1;
+	goto fail2;
 
     cff_subset->base_font = strdup (font->font_name);
-    if (cff_subset->base_font == NULL)
-	goto fail1;
+    if (cff_subset->base_font == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto fail2;
+    }
 
     cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
-    if (cff_subset->widths == NULL)
-	goto fail2;
+    if (cff_subset->widths == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto fail3;
+    }
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
         cff_subset->widths[i] = type2_subset.widths[i];
 
@@ -2111,24 +2235,27 @@ _cairo_cff_fallback_init (cairo_cff_subs
     cff_subset->ascent = type2_subset.y_max;
     cff_subset->descent = type2_subset.y_min;
 
-    _cairo_type2_charstrings_fini (&type2_subset);
-
     cff_subset->data = malloc (length);
-    if (cff_subset->data == NULL)
-	goto fail3;
+    if (cff_subset->data == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto fail4;
+    }
 
     memcpy (cff_subset->data, data, length);
     cff_subset->data_length = length;
     cff_subset->data_length = length;
 
+    _cairo_type2_charstrings_fini (&type2_subset);
     cairo_cff_font_destroy (font);
 
     return CAIRO_STATUS_SUCCESS;
 
- fail3:
+ fail4:
     free (cff_subset->widths);
- fail2:
+ fail3:
     free (cff_subset->base_font);
+ fail2:
+    _cairo_type2_charstrings_fini (&type2_subset);
  fail1:
     cairo_cff_font_destroy (font);
 
diff-tree add0959328117e2023db0ba2432ed29ecb93275e (from a4f20610afd18d58a964dbe84cc90c5723b2996d)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 17:00:26 2007 +0100

    [cairo-debug] Finalize mutexes along with other static data.
    
    Initialize (so repeated calls of cairo_debug_reset_static_data() is
    safe) and finalize the mutexes with the reset of the static data.

diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 6a50353..cdd3ce9 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -59,6 +59,8 @@
 void
 cairo_debug_reset_static_data (void)
 {
+    CAIRO_MUTEX_INITIALIZE ();
+
     _cairo_font_reset_static_data ();
 
 #if CAIRO_HAS_FT_FONT
@@ -66,4 +68,6 @@ cairo_debug_reset_static_data (void)
 #endif
 
     _cairo_pattern_reset_static_data ();
+
+    CAIRO_MUTEX_FINALIZE ();
 }
diff-tree a4f20610afd18d58a964dbe84cc90c5723b2996d (from 80c06f4539962231df771b38e64834a238f410dd)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 16:37:44 2007 +0100

    [cairo] Protect the getters when operating on the nil object.
    
    Put a guard that checks the context's status at the start of each
    getter that prevents the function from trying to dereference NULL state.
    Use the status, as opposed to the invalid reference count, for
    consistency with the existing guards on some of the getters.

diff --git a/src/cairo.c b/src/cairo.c
index ef628e7..73c2dc4 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1073,6 +1073,9 @@ cairo_get_dash_count (cairo_t *cr)
 {
     int num_dashes;
 
+    if (cr->status)
+	return 0;
+
     _cairo_gstate_get_dash (cr->gstate, NULL, &num_dashes, NULL);
 
     return num_dashes;
@@ -1095,6 +1098,9 @@ cairo_get_dash (cairo_t *cr,
 		double  *dashes,
 		double  *offset)
 {
+    if (cr->status)
+	return;
+
     _cairo_gstate_get_dash (cr->gstate, dashes, NULL, offset);
 }
 
@@ -2631,6 +2637,11 @@ cairo_set_font_matrix (cairo_t		    *cr,
 void
 cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix)
 {
+    if (cr->status) {
+	cairo_matrix_init_identity (matrix);
+	return;
+    }
+
     _cairo_gstate_get_font_matrix (cr->gstate, matrix);
 }
 
@@ -2682,6 +2693,11 @@ cairo_get_font_options (cairo_t         
     if (cairo_font_options_status (options))
 	return;
 
+    if (cr->status) {
+	_cairo_font_options_init_default (options);
+	return;
+    }
+
     _cairo_gstate_get_font_options (cr->gstate, options);
 }
 
@@ -3077,6 +3093,9 @@ cairo_glyph_path (cairo_t *cr, const cai
 cairo_operator_t
 cairo_get_operator (cairo_t *cr)
 {
+    if (cr->status)
+	return (cairo_operator_t) 0;
+
     return _cairo_gstate_get_operator (cr->gstate);
 }
 
@@ -3091,6 +3110,9 @@ cairo_get_operator (cairo_t *cr)
 double
 cairo_get_tolerance (cairo_t *cr)
 {
+    if (cr->status)
+	return 0.;
+
     return _cairo_gstate_get_tolerance (cr->gstate);
 }
 slim_hidden_def (cairo_get_tolerance);
@@ -3106,6 +3128,9 @@ slim_hidden_def (cairo_get_tolerance);
 cairo_antialias_t
 cairo_get_antialias (cairo_t *cr)
 {
+    if (cr->status)
+	return (cairo_antialias_t) 0;
+
     return _cairo_gstate_get_antialias (cr->gstate);
 }
 
@@ -3141,11 +3166,13 @@ cairo_get_antialias (cairo_t *cr)
 void
 cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
 {
-    cairo_status_t status;
+    cairo_status_t status = CAIRO_STATUS_NO_CURRENT_POINT;
     cairo_fixed_t x_fixed, y_fixed;
     double x, y;
 
-    status = _cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed);
+    if (cr->status == CAIRO_STATUS_SUCCESS)
+	status = _cairo_path_fixed_get_current_point (cr->path,
+	                                              &x_fixed, &y_fixed);
     if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
 	x = 0.0;
 	y = 0.0;
@@ -3173,6 +3200,9 @@ slim_hidden_def(cairo_get_current_point)
 cairo_fill_rule_t
 cairo_get_fill_rule (cairo_t *cr)
 {
+    if (cr->status)
+	return (cairo_fill_rule_t) 0;
+
     return _cairo_gstate_get_fill_rule (cr->gstate);
 }
 
@@ -3190,6 +3220,9 @@ cairo_get_fill_rule (cairo_t *cr)
 double
 cairo_get_line_width (cairo_t *cr)
 {
+    if (cr->status)
+	return 0.;
+
     return _cairo_gstate_get_line_width (cr->gstate);
 }
 
@@ -3204,6 +3237,9 @@ cairo_get_line_width (cairo_t *cr)
 cairo_line_cap_t
 cairo_get_line_cap (cairo_t *cr)
 {
+    if (cr->status)
+	return (cairo_line_cap_t) 0;
+
     return _cairo_gstate_get_line_cap (cr->gstate);
 }
 
@@ -3218,6 +3254,9 @@ cairo_get_line_cap (cairo_t *cr)
 cairo_line_join_t
 cairo_get_line_join (cairo_t *cr)
 {
+    if (cr->status)
+	return (cairo_line_join_t) 0;
+
     return _cairo_gstate_get_line_join (cr->gstate);
 }
 
@@ -3232,6 +3271,9 @@ cairo_get_line_join (cairo_t *cr)
 double
 cairo_get_miter_limit (cairo_t *cr)
 {
+    if (cr->status)
+	return 0.;
+
     return _cairo_gstate_get_miter_limit (cr->gstate);
 }
 
@@ -3245,6 +3287,11 @@ cairo_get_miter_limit (cairo_t *cr)
 void
 cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
 {
+    if (cr->status) {
+	cairo_matrix_init_identity (matrix);
+	return;
+    }
+
     _cairo_gstate_get_matrix (cr->gstate, matrix);
 }
 slim_hidden_def (cairo_get_matrix);
diff-tree 80c06f4539962231df771b38e64834a238f410dd (from 6e93941a7605a3958269de195dc16f255dda7bfd)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 16:16:41 2007 +0100

    [cairo-scaled-font] Don't hold onto to a dropped font.
    
    Mark fonts that have been removed from the cache due to an error on a
    shared object and do not put them into the holdovers array.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index e905917..9cbe7bb 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -177,8 +177,9 @@ _cairo_scaled_glyph_destroy (void *abstr
     free (scaled_glyph);
 }
 
+#define ZOMBIE 0
 const cairo_scaled_font_t _cairo_scaled_font_nil = {
-    { 0 },			/* hash_entry */
+    { ZOMBIE },			/* hash_entry */
     CAIRO_STATUS_NO_MEMORY,	/* status */
     CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
     { 0, 0, 0, NULL },		/* user_data */
@@ -423,6 +424,7 @@ _cairo_scaled_font_init_key (cairo_scale
 
     hash ^= cairo_font_options_hash (&scaled_font->options);
 
+    assert (hash != ZOMBIE);
     scaled_font->hash_entry.hash = hash;
 }
 
@@ -650,6 +652,7 @@ cairo_scaled_font_create (cairo_font_fac
 
 	/* the font has been put into an error status - abandon the cache */
 	_cairo_hash_table_remove (font_map->hash_table, &key.hash_entry);
+	scaled_font->hash_entry.hash = ZOMBIE;
     }
 
     /* Otherwise create it and insert it into the hash table. */
@@ -730,7 +733,8 @@ cairo_scaled_font_destroy (cairo_scaled_
 
     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
 
-    if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)) {
+    if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)
+	    && scaled_font->hash_entry.hash != ZOMBIE) {
 	/* Rather than immediately destroying this object, we put it into
 	 * the font_map->holdovers array in case it will get used again
 	 * soon (and is why we must hold the lock over the atomic op on
diff-tree 6e93941a7605a3958269de195dc16f255dda7bfd (from 261971a3fb9c10c267cced53a440161f1acb4b5d)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 16:04:49 2007 +0100

    [cairo-scaled-font] Acquire mutex around _cairo_scaled_font_glyph_path().
    
    All calls that manipulate the scaled_font->cache must hold its mutex.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index e2c7d13..3e92c54 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1631,9 +1631,11 @@ _cairo_gstate_glyph_path (cairo_gstate_t
     _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
                                                transformed_glyphs);
 
+    CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
     status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
 					    transformed_glyphs, num_glyphs,
 					    path);
+    CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
 
     if (transformed_glyphs != stack_transformed_glyphs)
       free (transformed_glyphs);
diff-tree 261971a3fb9c10c267cced53a440161f1acb4b5d (from 4e44d54f3e99b65f5e80485b22d31890ea3d6561)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 16:03:12 2007 +0100

    [cairo-gstate] Fix resource leaks on error paths.
    
    Ensure that all locally allocated (or referenced) resources are freed
    if we later encounter an error.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 2867243..e2c7d13 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -93,8 +93,13 @@ _cairo_gstate_init (cairo_gstate_t  *gst
 
     gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
 						  CAIRO_CONTENT_COLOR);
-    if (gstate->source->status)
+    if (gstate->source->status) {
+	cairo_surface_destroy (gstate->target);
+	gstate->target = NULL;
+	cairo_surface_destroy (gstate->original_target);
+	gstate->original_target = NULL;
 	return gstate->source->status;
+    }
 
     return target ? target->status : CAIRO_STATUS_NULL_POINTER;
 }
@@ -131,8 +136,12 @@ _cairo_gstate_init_copy (cairo_gstate_t 
     _cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
 
     status = _cairo_clip_init_copy (&gstate->clip, &other->clip);
-    if (status)
+    if (status) {
+	_cairo_stroke_style_fini (&gstate->stroke_style);
+	cairo_font_face_destroy (gstate->font_face);
+	cairo_scaled_font_destroy (gstate->scaled_font);
 	return status;
+    }
 
     gstate->target = cairo_surface_reference (other->target);
     /* parent_target is always set to NULL; it's only ever set by redirect_target */
@@ -994,7 +1003,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t	
 			 double		     y,
 			 cairo_bool_t	    *inside_ret)
 {
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     cairo_traps_t traps;
 
     if (gstate->stroke_style.line_width <= 0.0) {
@@ -1060,7 +1069,7 @@ _cairo_gstate_in_fill (cairo_gstate_t	  
 		       double		   y,
 		       cairo_bool_t	  *inside_ret)
 {
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     cairo_traps_t traps;
 
     _cairo_gstate_user_to_backend (gstate, &x, &y);
@@ -1267,11 +1276,9 @@ _cairo_gstate_select_font_face (cairo_gs
 	return font_face->status;
 
     status = _cairo_gstate_set_font_face (gstate, font_face);
-    if (status)
-	return status;
     cairo_font_face_destroy (font_face);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 cairo_status_t
@@ -1558,7 +1565,6 @@ _cairo_gstate_show_glyphs (cairo_gstate_
     cairo_glyph_t *transformed_glyphs;
     cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
 
-
     if (gstate->source->status)
 	return gstate->source->status;
 
diff-tree 4e44d54f3e99b65f5e80485b22d31890ea3d6561 (from 528da4e5e131fe385a60431eb6656a542b27c70f)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 15:58:21 2007 +0100

    [cairo-matrix] Check whether a matrix is invertible before use.
    
    Provide an early check as to whether the font matrix is invertible.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index b1fc6b3..2867243 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1289,6 +1289,9 @@ cairo_status_t
 _cairo_gstate_set_font_matrix (cairo_gstate_t	    *gstate,
 			       const cairo_matrix_t *matrix)
 {
+    if (! _cairo_matrix_is_invertible (matrix))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
     _cairo_gstate_unset_scaled_font (gstate);
 
     gstate->font_matrix = *matrix;
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index cf31c5d..00c2d48 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -486,6 +486,16 @@ cairo_matrix_invert (cairo_matrix_t *mat
 }
 slim_hidden_def(cairo_matrix_invert);
 
+cairo_bool_t
+_cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
+{
+    double det;
+
+    _cairo_matrix_compute_determinant (matrix, &det);
+
+    return det != 0. && det * det > 0.;
+}
+
 void
 _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
 				   double		*det)
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 2da9912..e905917 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -603,6 +603,9 @@ cairo_scaled_font_create (cairo_font_fac
     if (cairo_font_options_status ((cairo_font_options_t *) options))
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
 
+    if (! _cairo_matrix_is_invertible (font_matrix))
+	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
+
     font_map = _cairo_scaled_font_map_lock ();
     if (font_map == NULL)
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
diff --git a/src/cairoint.h b/src/cairoint.h
index 80915d7..c5cdf1a 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2104,6 +2104,9 @@ _cairo_matrix_transform_bounding_box (co
 				      double *x2, double *y2,
 				      cairo_bool_t *is_tight);
 
+cairo_private cairo_bool_t
+_cairo_matrix_is_invertible (const cairo_matrix_t *matrix);
+
 cairo_private void
 _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det);
 
diff-tree 528da4e5e131fe385a60431eb6656a542b27c70f (from 4b81eeb20ebe070692ef8099c00de3829da8bf69)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 15:50:40 2007 +0100

    [cairo-scaled-font] Freeze the font cache whilst iterating over glyphs.
    
    Prevent glyph cache removal whilst iterating over a glyph string.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index aec958a..2da9912 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -934,6 +934,7 @@ cairo_scaled_font_glyph_extents (cairo_s
 	return;
 
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
+    _cairo_scaled_font_freeze_cache (scaled_font);
 
     for (i = 0; i < num_glyphs; i++) {
 	double			left, top, right, bottom;
@@ -1000,6 +1001,7 @@ cairo_scaled_font_glyph_extents (cairo_s
     }
 
  UNLOCK:
+    _cairo_scaled_font_thaw_cache (scaled_font);
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 }
 slim_hidden_def (cairo_scaled_font_glyph_extents);
@@ -1028,6 +1030,7 @@ _cairo_scaled_font_text_to_glyphs (cairo
     }
 
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
+    _cairo_scaled_font_freeze_cache (scaled_font);
 
     if (scaled_font->backend->text_to_glyphs) {
 	status = scaled_font->backend->text_to_glyphs (scaled_font,
@@ -1070,6 +1073,7 @@ _cairo_scaled_font_text_to_glyphs (cairo
     }
 
  DONE:
+    _cairo_scaled_font_thaw_cache (scaled_font);
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 
     if (ucs4)
@@ -1430,6 +1434,7 @@ _cairo_scaled_font_glyph_path (cairo_sca
 	return status;
 
     closure.path = path;
+    _cairo_scaled_font_freeze_cache (scaled_font);
     for (i = 0; i < num_glyphs; i++) {
 	cairo_scaled_glyph_t *scaled_glyph;
 
@@ -1482,6 +1487,7 @@ _cairo_scaled_font_glyph_path (cairo_sca
 	    goto BAIL;
     }
   BAIL:
+    _cairo_scaled_font_thaw_cache (scaled_font);
 
     return _cairo_scaled_font_set_error (scaled_font, status);
 }
diff-tree 4b81eeb20ebe070692ef8099c00de3829da8bf69 (from d0b1308cd73a6b3602e5414abf03a3bdf8d2d001)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 15:46:13 2007 +0100

    [cairo-scaled-font] Destroy the mask on the error path.
    
    Do not leak the mask if we encounter an error whilst tracing.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index d506e93..aec958a 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1381,12 +1381,15 @@ _trace_mask_to_path (cairo_image_surface
     double xoff, yoff;
 
     if (mask->format == CAIRO_FORMAT_A1)
-	a1_mask = mask;
+	a1_mask = (cairo_image_surface_t *) cairo_surface_reference (&mask->base);
     else
 	a1_mask = _cairo_image_surface_clone (mask, CAIRO_FORMAT_A1);
 
-    if (cairo_surface_status (&a1_mask->base))
-	return cairo_surface_status (&a1_mask->base);
+    status = cairo_surface_status (&a1_mask->base);
+    if (status) {
+	cairo_surface_destroy (&a1_mask->base);
+	return status;
+    }
 
     cairo_surface_get_device_offset (&mask->base, &xoff, &yoff);
 
@@ -1399,16 +1402,16 @@ _trace_mask_to_path (cairo_image_surface
 		    status = _add_unit_rectangle_to_path (path,
 							  x - xoff, y - yoff);
 		    if (status)
-			return status;
+			goto BAIL;
 		}
 	    }
 	}
     }
 
-    if (a1_mask != mask)
-	cairo_surface_destroy (&a1_mask->base);
+BAIL:
+    cairo_surface_destroy (&a1_mask->base);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 cairo_status_t
diff-tree d0b1308cd73a6b3602e5414abf03a3bdf8d2d001 (from 4c32e6bfde5d613e0eeef407b9b50c557b1878e3)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 15:43:09 2007 +0100

    [cairo-scaled-font] Store fatal errors on the cairo_scaled_font_t.
    
    Ensure that all fatal errors raised whilst using the font are stored on
    the font.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 434e09c..d506e93 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -221,6 +221,9 @@ cairo_status_t
 _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
 			      cairo_status_t status)
 {
+    if (status == CAIRO_STATUS_SUCCESS)
+	return status;
+
     /* Don't overwrite an existing error. This preserves the first
      * error, which is the most significant. */
     _cairo_status_set_error (&scaled_font->status, status);
@@ -1011,9 +1014,13 @@ _cairo_scaled_font_text_to_glyphs (cairo
 {
     int i;
     uint32_t *ucs4 = NULL;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     cairo_scaled_glyph_t *scaled_glyph;
 
+    status = scaled_font->status;
+    if (status)
+	return status;
+
     if (utf8[0] == '\0') {
 	*num_glyphs = 0;
 	*glyphs = NULL;
@@ -1165,7 +1172,7 @@ _cairo_scaled_font_show_glyphs (cairo_sc
 						    width, height,
 						    glyphs, num_glyphs);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return status;
+	    return _cairo_scaled_font_set_error (scaled_font, status);
     }
 
     /* Font display routine either does not exist or failed. */
@@ -1255,7 +1262,7 @@ CLEANUP_MASK:
 
     if (mask != NULL)
 	cairo_surface_destroy (mask);
-    return status;
+    return _cairo_scaled_font_set_error (scaled_font, status);
 }
 
 typedef struct _cairo_scaled_glyph_path_closure {
@@ -1415,8 +1422,9 @@ _cairo_scaled_font_glyph_path (cairo_sca
     cairo_scaled_glyph_path_closure_t closure;
     cairo_path_fixed_t *glyph_path;
 
-    if (scaled_font->status)
-	return scaled_font->status;
+    status = scaled_font->status;
+    if (status)
+	return status;
 
     closure.path = path;
     for (i = 0; i < num_glyphs; i++) {
@@ -1429,7 +1437,7 @@ _cairo_scaled_font_glyph_path (cairo_sca
 	if (status == CAIRO_STATUS_SUCCESS)
 	    glyph_path = scaled_glyph->path;
 	else if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return status;
+	    goto BAIL;
 
 	/* If the font is incapable of providing a path, then we'll
 	 * have to trace our own from a surface. */
@@ -1439,16 +1447,18 @@ _cairo_scaled_font_glyph_path (cairo_sca
 						 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 						 &scaled_glyph);
 	    if (status)
-		return status;
+		goto BAIL;
 
 	    glyph_path = _cairo_path_fixed_create ();
-	    if (glyph_path == NULL)
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    if (glyph_path == NULL) {
+		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		goto BAIL;
+	    }
 
 	    status = _trace_mask_to_path (scaled_glyph->surface, glyph_path);
 	    if (status) {
 		_cairo_path_fixed_destroy (glyph_path);
-		return status;
+		goto BAIL;
 	    }
 	}
 
@@ -1466,10 +1476,11 @@ _cairo_scaled_font_glyph_path (cairo_sca
 	    _cairo_path_fixed_destroy (glyph_path);
 
 	if (status)
-	    return status;
+	    goto BAIL;
     }
+  BAIL:
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_scaled_font_set_error (scaled_font, status);
 }
 
 /**
diff-tree 4c32e6bfde5d613e0eeef407b9b50c557b1878e3 (from 06ae5f1ba3bb679c145d2f7e9ed8c244abf7ff17)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 15:31:25 2007 +0100

    [cairo-scaled-font] Return the error status from _cairo_scaled_font_set_error()
    
    Similar to the other _cairo_*_set_error() return the error status.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index d6a6771..e141ba7 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2539,7 +2539,7 @@ cairo_ft_scaled_font_lock_face (cairo_sc
 
     face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
     if (face == NULL) {
-	_cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
+	status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
 	return NULL;
     }
 
@@ -2547,7 +2547,7 @@ cairo_ft_scaled_font_lock_face (cairo_sc
 				                &scaled_font->base.scale);
     if (status) {
 	_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
-	_cairo_scaled_font_set_error (&scaled_font->base, status);
+	status = _cairo_scaled_font_set_error (&scaled_font->base, status);
 	return NULL;
     }
 
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index ff844a5..434e09c 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -214,8 +214,10 @@ const cairo_scaled_font_t _cairo_scaled_
  * The purpose of this function is to allow the user to set a
  * breakpoint in _cairo_error() to generate a stack trace for when the
  * user causes cairo to detect an error.
+ *
+ * Return value: the error status.
  **/
-void
+cairo_status_t
 _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
 			      cairo_status_t status)
 {
@@ -223,7 +225,7 @@ _cairo_scaled_font_set_error (cairo_scal
      * error, which is the most significant. */
     _cairo_status_set_error (&scaled_font->status, status);
 
-    _cairo_error_throw (status);
+    return _cairo_error (status);
 }
 
 /**
@@ -888,7 +890,7 @@ cairo_scaled_font_text_extents (cairo_sc
 
     status = _cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., utf8, &glyphs, &num_glyphs);
     if (status) {
-        _cairo_scaled_font_set_error (scaled_font, status);
+        status = _cairo_scaled_font_set_error (scaled_font, status);
         return;
     }
     cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents);
@@ -938,7 +940,7 @@ cairo_scaled_font_glyph_extents (cairo_s
 					     CAIRO_SCALED_GLYPH_INFO_METRICS,
 					     &scaled_glyph);
 	if (status) {
-	    _cairo_scaled_font_set_error (scaled_font, status);
+	    status = _cairo_scaled_font_set_error (scaled_font, status);
 	    goto UNLOCK;
 	}
 
@@ -1096,10 +1098,8 @@ _cairo_scaled_font_glyph_device_extents 
 					     glyphs[i].index,
 					     CAIRO_SCALED_GLYPH_INFO_METRICS,
 					     &scaled_glyph);
-	if (status) {
-	    _cairo_scaled_font_set_error (scaled_font, status);
-	    return status;
-	}
+	if (status)
+	    return _cairo_scaled_font_set_error (scaled_font, status);
 
 	/* glyph images are snapped to pixel locations */
 	x = _cairo_lround (glyphs[i].x);
@@ -1677,7 +1677,7 @@ _cairo_scaled_glyph_lookup (cairo_scaled
     if (status) {
 	/* It's not an error for the backend to not support the info we want. */
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    _cairo_scaled_font_set_error (scaled_font, status);
+	    status = _cairo_scaled_font_set_error (scaled_font, status);
 	*scaled_glyph_ret = NULL;
     } else {
 	*scaled_glyph_ret = scaled_glyph;
diff --git a/src/cairoint.h b/src/cairoint.h
index 9cd42f2..80915d7 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1360,7 +1360,7 @@ _cairo_scaled_font_thaw_cache (cairo_sca
 cairo_private void
 _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font);
 
-cairo_private void
+cairo_private cairo_status_t
 _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
 			      cairo_status_t status);
 
diff-tree 06ae5f1ba3bb679c145d2f7e9ed8c244abf7ff17 (from 4cffdf2681ba254587bd774ea49718e71535b067)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 15:26:09 2007 +0100

    [cairo-font-face] Set the error on the font.
    
    Similar to the other shared objects, store fatal errors on the shared
    font_face. And do not return a cached reference to an object in an
    error state.

diff --git a/src/cairo-font-face.c b/src/cairo-font-face.c
index 0285b52..f729476 100644
--- a/src/cairo-font-face.c
+++ b/src/cairo-font-face.c
@@ -55,6 +55,18 @@ const cairo_font_face_t _cairo_font_face
     &_cairo_toy_font_face_backend
 };
 
+cairo_status_t
+_cairo_font_face_set_error (cairo_font_face_t *font_face,
+	                    cairo_status_t     status)
+{
+    if (status == CAIRO_STATUS_SUCCESS)
+	return status;
+
+    _cairo_status_set_error (&font_face->status, status);
+
+    return _cairo_error (status);
+}
+
 void
 _cairo_font_face_init (cairo_font_face_t               *font_face,
 		       const cairo_font_face_backend_t *backend)
@@ -308,6 +320,7 @@ _cairo_toy_font_face_init_key (cairo_toy
     hash += ((unsigned long) slant) * 1607;
     hash += ((unsigned long) weight) * 1451;
 
+    assert (hash != 0);
     key->base.hash_entry.hash = hash;
 }
 
@@ -386,11 +399,17 @@ _cairo_toy_font_face_create (const char 
 				  &key.base.hash_entry,
 				  (cairo_hash_entry_t **) &font_face))
     {
-	/* We increment the reference count here manually to avoid
-	   double-locking. */
-	_cairo_reference_count_inc (&font_face->base.ref_count);
-	_cairo_toy_font_face_hash_table_unlock ();
-	return &font_face->base;
+	if (! font_face->base.status)  {
+	    /* We increment the reference count here manually to avoid
+	       double-locking. */
+	    _cairo_reference_count_inc (&font_face->base.ref_count);
+	    _cairo_toy_font_face_hash_table_unlock ();
+	    return &font_face->base;
+	}
+
+	/* remove the bad font from the hash table */
+	_cairo_hash_table_remove (hash_table, &key.base.hash_entry);
+	font_face->base.hash_entry.hash = 0;
     }
 
     /* Otherwise create it and insert into hash table. */
@@ -427,14 +446,16 @@ _cairo_toy_font_face_destroy (void *abst
     cairo_toy_font_face_t *font_face = abstract_face;
     cairo_hash_table_t *hash_table;
 
-    if (font_face == NULL)
+    if (font_face == NULL ||
+	    CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->base.ref_count))
 	return;
 
     hash_table = _cairo_toy_font_face_hash_table_lock ();
     /* All created objects must have been mapped in the hash table. */
     assert (hash_table != NULL);
 
-    _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
+    if (font_face->base.hash_entry.hash != 0)
+	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
 
     _cairo_toy_font_face_hash_table_unlock ();
 
@@ -452,12 +473,19 @@ _cairo_toy_font_face_scaled_font_create 
     const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
     cairo_status_t status;
 
+    if (font_face->base.status)
+	return font_face->base.status;
+
     status = cairo_font_options_status ((cairo_font_options_t *) options);
     if (status)
 	return status;
 
-    return backend->create_toy (font_face,
-				font_matrix, ctm, options, scaled_font);
+    return _cairo_font_face_set_error (&font_face->base,
+	                               backend->create_toy (font_face,
+				                            font_matrix,
+							    ctm,
+							    options,
+							    scaled_font));
 }
 
 static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 47f06e7..ff844a5 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -649,6 +649,7 @@ cairo_scaled_font_create (cairo_font_fac
 						     ctm, options, &scaled_font);
     if (status) {
 	_cairo_scaled_font_map_unlock ();
+	status = _cairo_font_face_set_error (font_face, status);
 	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
     }
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 7382292..9cd42f2 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1371,6 +1371,10 @@ cairo_private void
 _cairo_font_face_init (cairo_font_face_t               *font_face,
 		       const cairo_font_face_backend_t *backend);
 
+cairo_private cairo_status_t
+_cairo_font_face_set_error (cairo_font_face_t *font_face,
+	                    cairo_status_t     status);
+
 cairo_private cairo_font_face_t *
 _cairo_toy_font_face_create (const char           *family,
 			     cairo_font_slant_t    slant,
diff-tree 4cffdf2681ba254587bd774ea49718e71535b067 (from de1f92ae14bfc4d74d8df88ae81d7b90dd6739f0)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 14:59:55 2007 +0100

    [cairo-ft-font] Always call _cairo_ft_unscaled_font_fini ().
    
    The _cairo_ft_unscaled_font_fini() was skipped during the destroy for
    fonts generated by cairo_ft_font_face_create_for_ft_face(). However
    this causes a mutex to be 'leaked' for each font.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 7768a77..d6a6771 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -486,6 +486,8 @@ _cairo_ft_unscaled_font_destroy (void *a
 	 */
 	if (unscaled->faces && !unscaled->faces->unscaled)
 	    cairo_font_face_destroy (&unscaled->faces->base);
+
+	unscaled->face = NULL;
     } else {
 	cairo_ft_unscaled_font_map_t *font_map;
 
@@ -497,10 +499,10 @@ _cairo_ft_unscaled_font_destroy (void *a
 				  &unscaled->base.hash_entry);
 
 	_font_map_release_face_lock_held (font_map, unscaled);
-	_cairo_ft_unscaled_font_fini (unscaled);
 
 	_cairo_ft_unscaled_font_map_unlock ();
     }
+    _cairo_ft_unscaled_font_fini (unscaled);
 }
 
 static cairo_bool_t
diff-tree de1f92ae14bfc4d74d8df88ae81d7b90dd6739f0 (from 2c256f292fc4a9fd8414e29c4df32d347e360900)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 14:51:16 2007 +0100

    [cairo-output-stream] Propagate error status when copying streams.
    
    During _cairo_memory_stream_copy(), if set, copy the incoming error over
    to the destination stream and return early.

diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 791c0f2..323bd06 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -46,7 +46,7 @@
 #endif /* _MSC_VER */
 
 
-cairo_private void
+void
 _cairo_output_stream_init (cairo_output_stream_t            *stream,
 			   cairo_output_stream_write_func_t  write_func,
 			   cairo_output_stream_close_func_t  close_func)
@@ -58,7 +58,7 @@ _cairo_output_stream_init (cairo_output_
     stream->closed = FALSE;
 }
 
-cairo_private cairo_status_t
+cairo_status_t
 _cairo_output_stream_fini (cairo_output_stream_t *stream)
 {
     return _cairo_output_stream_close (stream);
@@ -560,6 +560,14 @@ _cairo_memory_stream_copy (cairo_output_
 {
     memory_stream_t *stream = (memory_stream_t *) base;
 
+    if (dest->status)
+	return;
+
+    if (base->status) {
+	dest->status = base->status;
+	return;
+    }
+
     _cairo_output_stream_write (dest, 
 				_cairo_array_index (&stream->array, 0),
 				_cairo_array_num_elements (&stream->array));


More information about the cairo-commit mailing list