summaryrefslogtreecommitdiff
path: root/src/cairo-cff-subset.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2007-10-04 17:12:26 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2007-10-04 17:18:25 +0100
commit37fd0d8967df21695d6536af1d7aedbeef2d2449 (patch)
treef056c2c4ca531bb28abccd69e329de6780f89d9e /src/cairo-cff-subset.c
parentadd0959328117e2023db0ba2432ed29ecb93275e (diff)
[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.
Diffstat (limited to 'src/cairo-cff-subset.c')
-rw-r--r--src/cairo-cff-subset.c291
1 files changed, 209 insertions, 82 deletions
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 7bc7cb9c..d1826dfd 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -385,6 +385,7 @@ cff_index_append_copy (cairo_array_t *index,
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 *index,
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, const void *key_b)
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_cff_font_t *font,
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_cff_font_t *font,
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_cff_font_t *font, unsigned char *ptr)
}
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_cff_font_t *font, unsigned char *ptr)
}
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_font_t *font)
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_t *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_cff_font_t *font)
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_cff_font_t *font,
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 (cairo_cff_font_t *font)
{
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 (cairo_cff_font_t *font)
* 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_font_t *font)
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_font_t *font)
{
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_font_t *font)
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_cff_font_t *font,
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_and_local_sub (cairo_cff_font_t *font)
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_font_subset_t *scaled_font_subset,
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_font_subset_t *scaled_font_subset,
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_font_subset_t *scaled_font_subset,
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_font_subset_t *scaled_font_subset,
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_t *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_t *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_scaled_font_subset_t *scaled_font_subset
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_scaled_font_subset_t *scaled_font_subset
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_scaled_font_subset_t *scaled_font_subset
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_cff_font_t *font,
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_subset_t *cff_subset,
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_subset_t *cff_subset,
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);