summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2007-04-20 22:30:55 +0930
committerAdrian Johnson <ajohnson@redneon.com>2007-04-20 22:30:55 +0930
commit0c2a653033e0b631a1cb6591263cbd6125ccc00c (patch)
tree0568fe5c4f1f53468a91698dcc299041eea436a3
parentc68a2389f51880b0fa9df6750abdd840258666fc (diff)
Add CFF CID Fallback
Switching to CID font embedding requires a fallback font for the case where CFF CID or TrueType CID subsetting fails. The new function _cairo_type2_charstrings_init() added to cairo-type1-fallback.c creates Type2 charstrings from glyph paths. _cairo_cff_fallback_init() in cairo-cff-subset.c wraps these charstrings in a CFF CID font.
-rw-r--r--src/cairo-cff-subset.c212
-rw-r--r--src/cairo-scaled-font-subsets-private.h68
-rw-r--r--src/cairo-type1-fallback.c211
3 files changed, 432 insertions, 59 deletions
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index e4c8cfce..a448e372 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -1915,3 +1915,215 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
free (subset->widths);
free (subset->data);
}
+
+static cairo_int_status_t
+_cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset,
+ cairo_cff_font_t **font_return,
+ const char *subset_name)
+{
+ cairo_status_t status;
+ cairo_cff_font_t *font;
+
+ font = malloc (sizeof (cairo_cff_font_t));
+ if (font == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ font->backend = NULL;
+ font->scaled_font_subset = scaled_font_subset;
+
+ _cairo_array_init (&font->output, sizeof (char));
+ status = _cairo_array_grow_by (&font->output, 4096);
+ if (status)
+ goto fail1;
+
+ font->subset_font_name = strdup (subset_name);
+ if (font->subset_font_name == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail2;
+ }
+
+ font->font_name = strdup (subset_name);
+ if (font->subset_font_name == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail3;
+ }
+
+ font->x_min = 0;
+ font->y_min = 0;
+ font->x_max = 0;
+ font->y_max = 0;
+ font->ascent = 0;
+ font->descent = 0;
+
+ font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
+ if (font->widths == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail4;
+ }
+
+ font->data_length = 0;
+ font->data = NULL;
+ font->data_end = 0;
+
+ 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);
+ cff_index_init (&font->local_sub_index);
+ cff_index_init (&font->charstrings_subset_index);
+ cff_index_init (&font->strings_subset_index);
+ font->fdselect = NULL;
+ font->fd_dict = NULL;
+ font->fd_private_dict = NULL;
+ font->fd_local_sub_index = NULL;
+ font->fdselect_subset = NULL;
+ font->fd_subset_map = NULL;
+ font->private_dict_offset = NULL;
+
+ *font_return = font;
+
+ return CAIRO_STATUS_SUCCESS;
+
+fail4:
+ free (font->font_name);
+fail3:
+ free (font->subset_font_name);
+fail2:
+ _cairo_array_fini (&font->output);
+fail1:
+ free (font);
+ return status;
+}
+
+static cairo_int_status_t
+cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
+ cairo_type2_charstrings_t *type2_subset,
+ const char **data,
+ unsigned long *length)
+{
+ cairo_int_status_t status;
+ cff_header_t header;
+ cairo_array_t *charstring;
+ unsigned char buf[40];
+ unsigned char *end_buf;
+ unsigned int i;
+
+ /* Create header */
+ header.major = 1;
+ header.minor = 0;
+ header.header_size = 4;
+ header.offset_size = 4;
+ font->header = &header;
+
+ /* Create Top Dict */
+ font->is_cid = FALSE;
+ end_buf = encode_integer (buf, type2_subset->x_min);
+ 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);
+ 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);
+
+ /* Create CID FD dictionary */
+ cairo_cff_font_create_cid_fontdict (font);
+
+ /* Create charstrings */
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ charstring = _cairo_array_index(&type2_subset->charstrings, i);
+
+ status = cff_index_append (&font->charstrings_subset_index,
+ _cairo_array_index (charstring, 0),
+ _cairo_array_num_elements (charstring));
+
+ if (status)
+ return status;
+ }
+
+ status = cairo_cff_font_write_subset (font);
+ if (status)
+ return status;
+
+ *data = _cairo_array_index (&font->output, 0);
+ *length = _cairo_array_num_elements (&font->output);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
+ const char *subset_name,
+ cairo_scaled_font_subset_t *font_subset)
+{
+ cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
+ cairo_status_t status;
+ const char *data = NULL; /* squelch bogus compiler warning */
+ unsigned long length = 0; /* squelch bogus compiler warning */
+ unsigned int i;
+ cairo_type2_charstrings_t type2_subset;
+
+ status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
+ if (status)
+ return status;
+
+ status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
+ if (status)
+ goto fail1;
+
+ status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
+ if (status)
+ goto fail1;
+
+ cff_subset->base_font = strdup (font->font_name);
+ if (cff_subset->base_font == NULL)
+ goto fail1;
+
+ cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
+ if (cff_subset->widths == NULL)
+ goto fail2;
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
+ cff_subset->widths[i] = type2_subset.widths[i];
+
+ cff_subset->x_min = type2_subset.x_min;
+ cff_subset->y_min = type2_subset.y_min;
+ cff_subset->x_max = type2_subset.x_max;
+ cff_subset->y_max = type2_subset.y_max;
+ 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;
+
+ memcpy (cff_subset->data, data, length);
+ cff_subset->data_length = length;
+ cff_subset->data_length = length;
+
+ cairo_cff_font_destroy (font);
+
+ return CAIRO_STATUS_SUCCESS;
+
+ fail3:
+ free (cff_subset->widths);
+ fail2:
+ free (cff_subset->base_font);
+ fail1:
+ cairo_cff_font_destroy (font);
+
+ return status;
+}
+
+void
+_cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
+{
+ free (subset->base_font);
+ free (subset->widths);
+ free (subset->data);
+}
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 4c8221e1..03076c86 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -305,6 +305,37 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
cairo_private void
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
+/**
+ * _cairo_cff_fallback_init:
+ * @cff_subset: a #cairo_cff_subset_t to initialize
+ * @font_subset: the #cairo_scaled_font_subset_t to initialize from
+ *
+ * If possible (depending on the format of the underlying
+ * cairo_scaled_font_t and the font backend in use) generate a cff
+ * file corresponding to @font_subset and initialize @cff_subset
+ * with information about the subset and the cff data.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful,
+ * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
+ * cff file, or an non-zero value indicating an error. Possible
+ * errors include CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
+ const char *name,
+ cairo_scaled_font_subset_t *font_subset);
+
+/**
+ * _cairo_cff_fallback_fini:
+ * @cff_subset: a #cairo_cff_subset_t
+ *
+ * Free all resources associated with @cff_subset. After this
+ * call, @cff_subset should not be used again without a
+ * subsequent call to _cairo_cff_subset_init() again first.
+ **/
+cairo_private void
+_cairo_cff_fallback_fini (cairo_cff_subset_t *cff_subset);
+
typedef struct _cairo_truetype_subset {
char *base_font;
double *widths;
@@ -446,6 +477,43 @@ _cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset,
cairo_private void
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset);
+typedef struct _cairo_type2_charstrings {
+ int *widths;
+ long x_min, y_min, x_max, y_max;
+ long ascent, descent;
+ cairo_array_t charstrings;
+} cairo_type2_charstrings_t;
+
+/**
+ * _cairo_type2_charstrings_init:
+ * @type2_subset: a #cairo_type2_subset_t to initialize
+ * @font_subset: the #cairo_scaled_font_subset_t to initialize from
+ *
+ * If possible (depending on the format of the underlying
+ * cairo_scaled_font_t and the font backend in use) generate type2
+ * charstrings to @font_subset and initialize @type2_subset
+ * with information about the subset.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful,
+ * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type2
+ * charstrings, or an non-zero value indicating an error. Possible errors
+ * include CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_type2_charstrings_init (cairo_type2_charstrings_t *charstrings,
+ cairo_scaled_font_subset_t *font_subset);
+
+/**
+ * _cairo_type2_charstrings_fini:
+ * @subset: a #cairo_type2_charstrings_t
+ *
+ * Free all resources associated with @type2_charstring. After this call,
+ * @type2_charstring should not be used again without a subsequent call to
+ * _cairo_type2_charstring_init() again first.
+ **/
+cairo_private void
+_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
+
/**
* _cairo_truetype_create_glyph_to_unicode_map:
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index dcf55f44..3a0bd124 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -39,6 +39,11 @@
#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
+typedef enum {
+ CAIRO_CHARSTRING_TYPE1,
+ CAIRO_CHARSTRING_TYPE2,
+} cairo_charstring_type_t;
+
typedef struct _cairo_type1_font {
int *widths;
@@ -90,7 +95,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
- cairo_matrix_init_scale (&font_matrix, 1000, 1000);
+ cairo_matrix_init_scale (&font_matrix, 1000, -1000);
cairo_matrix_init_identity (&ctm);
_cairo_font_options_init_default (&font_options);
@@ -156,7 +161,9 @@ charstring_encode_command (cairo_array_t *data, int command)
* bytes that will be used is 5.
*/
static void
-charstring_encode_integer (cairo_array_t *data, int i)
+charstring_encode_integer (cairo_array_t *data,
+ int i,
+ cairo_charstring_type_t type)
{
cairo_status_t status;
int orig_size;
@@ -174,11 +181,19 @@ charstring_encode_integer (cairo_array_t *data, int i)
*p++ = (i >> 8)+ 251;
*p++ = i & 0xff;
} else {
- *p++ = 0xff;
- *p++ = i >> 24;
- *p++ = (i >> 16) & 0xff;
- *p++ = (i >> 8) & 0xff;
- *p++ = i & 0xff;
+ if (type == CAIRO_CHARSTRING_TYPE1) {
+ *p++ = 0xff;
+ *p++ = i >> 24;
+ *p++ = (i >> 16) & 0xff;
+ *p++ = (i >> 8) & 0xff;
+ *p++ = i & 0xff;
+ } else {
+ *p++ = 0xff;
+ *p++ = (i >> 8) & 0xff;
+ *p++ = i & 0xff;
+ *p++ = 0;
+ *p++ = 0;
+ }
}
/* Ensure the array doesn't grow, which allows this function to
@@ -193,6 +208,7 @@ charstring_encode_integer (cairo_array_t *data, int i)
typedef struct _ps_path_info {
cairo_array_t *data;
int current_x, current_y;
+ cairo_charstring_type_t type;
} t1_path_info_t;
static cairo_status_t
@@ -209,8 +225,8 @@ _charstring_move_to (void *closure,
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
- charstring_encode_integer (path_info->data, dx);
- charstring_encode_integer (path_info->data, dy);
+ charstring_encode_integer (path_info->data, dx, path_info->type);
+ charstring_encode_integer (path_info->data, dy, path_info->type);
path_info->current_x += dx;
path_info->current_y += dy;
@@ -233,8 +249,8 @@ _charstring_line_to (void *closure,
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
- charstring_encode_integer (path_info->data, dx);
- charstring_encode_integer (path_info->data, dy);
+ charstring_encode_integer (path_info->data, dx, path_info->type);
+ charstring_encode_integer (path_info->data, dy, path_info->type);
path_info->current_x += dx;
path_info->current_y += dy;
@@ -263,12 +279,12 @@ _charstring_curve_to (void *closure,
dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
- charstring_encode_integer (path_info->data, dx1);
- charstring_encode_integer (path_info->data, dy1);
- charstring_encode_integer (path_info->data, dx2);
- charstring_encode_integer (path_info->data, dy2);
- charstring_encode_integer (path_info->data, dx3);
- charstring_encode_integer (path_info->data, dy3);
+ charstring_encode_integer (path_info->data, dx1, path_info->type);
+ charstring_encode_integer (path_info->data, dy1, path_info->type);
+ charstring_encode_integer (path_info->data, dx2, path_info->type);
+ charstring_encode_integer (path_info->data, dy2, path_info->type);
+ charstring_encode_integer (path_info->data, dx3, path_info->type);
+ charstring_encode_integer (path_info->data, dy3, path_info->type);
path_info->current_x += dx1 + dx2 + dx3;
path_info->current_y += dy1 + dy2 + dy3;
charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
@@ -282,6 +298,9 @@ _charstring_close_path (void *closure)
cairo_status_t status;
t1_path_info_t *path_info = (t1_path_info_t *) closure;
+ if (path_info->type == CAIRO_CHARSTRING_TYPE2)
+ return CAIRO_STATUS_SUCCESS;
+
status = _cairo_array_grow_by (path_info->data, 2);
if (status)
return status;
@@ -309,7 +328,7 @@ charstring_encrypt (cairo_array_t *data)
}
static cairo_int_status_t
-create_notdef_charstring (cairo_array_t *data)
+create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
{
cairo_status_t status;
@@ -320,13 +339,15 @@ create_notdef_charstring (cairo_array_t *data)
if (status)
return status;
- charstring_encode_integer (data, 0);
- charstring_encode_integer (data, 0);
+ if (type == CAIRO_CHARSTRING_TYPE1) {
+ charstring_encode_integer (data, 0, type);
+ charstring_encode_integer (data, 0, type);
- /* The width and height is arbitrary. */
- charstring_encode_integer (data, 500);
- charstring_encode_integer (data, 500);
- charstring_encode_command (data, CHARSTRING_sbw);
+ /* The width and height is arbitrary. */
+ charstring_encode_integer (data, 500, type);
+ charstring_encode_integer (data, 500, type);
+ charstring_encode_command (data, CHARSTRING_sbw);
+ }
charstring_encode_command (data, CHARSTRING_endchar);
@@ -334,10 +355,11 @@ create_notdef_charstring (cairo_array_t *data)
}
static cairo_int_status_t
-cairo_type1_font_create_charstring (cairo_type1_font_t *font,
- int subset_index,
- int glyph_index,
- cairo_array_t *data)
+cairo_type1_font_create_charstring (cairo_type1_font_t *font,
+ int subset_index,
+ int glyph_index,
+ cairo_charstring_type_t type,
+ cairo_array_t *data)
{
cairo_int_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
@@ -369,21 +391,29 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
if (metrics->y_bearing + metrics->height > font->y_max)
font->y_max = metrics->y_bearing + metrics->height;
}
- font->widths[subset_index] = metrics->width;
+ font->widths[subset_index] = metrics->x_advance;
status = _cairo_array_grow_by (data, 30);
if (status)
return status;
- charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing);
- charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing);
- charstring_encode_integer (data, (int) scaled_glyph->metrics.width);
- charstring_encode_integer (data, (int) scaled_glyph->metrics.height);
- charstring_encode_command (data, CHARSTRING_sbw);
+ if (type == CAIRO_CHARSTRING_TYPE1) {
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type);
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.height, type);
+ charstring_encode_command (data, CHARSTRING_sbw);
+ path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
+ path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
+ } else {
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
+
+ path_info.current_x = 0;
+ path_info.current_y = 0;
+ }
path_info.data = data;
- path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
- path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
+ path_info.type = type;
status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_charstring_move_to,
@@ -429,6 +459,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
goto fail;
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
+ CAIRO_CHARSTRING_TYPE1,
&data);
if (status)
goto fail;
@@ -448,7 +479,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
- status = create_notdef_charstring (&data);
+ status = create_notdef_charstring (&data, CAIRO_CHARSTRING_TYPE1);
if (status)
goto fail;
charstring_encrypt (&data);
@@ -464,35 +495,22 @@ fail:
return status;
}
-static cairo_status_t
+static void
cairo_type1_font_write_header (cairo_type1_font_t *font,
const char *name)
{
- cairo_matrix_t matrix;
- cairo_status_t status;
unsigned int i;
const char spaces[50] = " ";
- matrix = font->type1_scaled_font->scale;
- matrix.xy = -matrix.xy;
- matrix.yy = -matrix.yy;
- status = cairo_matrix_invert (&matrix);
- if (status)
- return status;
-
_cairo_output_stream_printf (font->output,
"%%!FontType1-1.1 %s 1.0\n"
"11 dict begin\n"
"/FontName /%s def\n"
"/PaintType 0 def\n"
"/FontType 1 def\n"
- "/FontMatrix [%f %f %f %f 0 0] readonly def\n",
- name,
+ "/FontMatrix [0.001 0 0 0.001 0 0] readonly def\n",
name,
- matrix.xx,
- matrix.yx,
- matrix.xy,
- matrix.yy);
+ name);
/* We don't know the bbox values until after the charstrings have
* been generated. Reserve some space and fill in the bbox
@@ -515,8 +533,6 @@ cairo_type1_font_write_header (cairo_type1_font_t *font,
"readonly def\n"
"currentdict end\n"
"currentfile eexec\n");
-
- return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@@ -640,10 +656,7 @@ cairo_type1_font_write (cairo_type1_font_t *font,
{
cairo_int_status_t status;
- status = cairo_type1_font_write_header (font, name);
- if (status)
- return status;
-
+ cairo_type1_font_write_header (font, name);
font->header_size = _cairo_output_stream_get_position (font->output);
status = cairo_type1_font_write_private_dict (font, name);
@@ -798,3 +811,83 @@ _cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
free (subset->widths);
free (subset->data);
}
+
+cairo_status_t
+_cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
+ cairo_scaled_font_subset_t *scaled_font_subset)
+{
+ cairo_type1_font_t *font;
+ cairo_status_t status;
+ unsigned int i;
+ cairo_array_t charstring;
+
+ status = cairo_type1_font_create (scaled_font_subset, &font, FALSE);
+ if (status)
+ return status;
+
+ _cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t));
+
+ type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
+ if (type2_subset->widths == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail1;
+ }
+
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ _cairo_array_init (&charstring, sizeof (unsigned char));
+ status = _cairo_array_grow_by (&charstring, 32);
+ if (status)
+ goto fail2;
+
+ if (i == 0) {
+ status = create_notdef_charstring (&charstring, CAIRO_CHARSTRING_TYPE2);
+ } else {
+ status = cairo_type1_font_create_charstring (font, i,
+ font->scaled_font_subset->glyphs[i],
+ CAIRO_CHARSTRING_TYPE2,
+ &charstring);
+ }
+ if (status)
+ goto fail2;
+
+ status = _cairo_array_append (&type2_subset->charstrings, &charstring);
+ if (status)
+ goto fail2;
+ }
+
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
+ type2_subset->widths[i] = font->widths[i];
+
+ type2_subset->x_min = (int) font->x_min;
+ type2_subset->y_min = (int) font->y_min;
+ type2_subset->x_max = (int) font->x_max;
+ type2_subset->y_max = (int) font->y_max;
+ type2_subset->ascent = (int) font->y_max;
+ type2_subset->descent = (int) font->y_min;
+
+ cairo_type1_font_destroy (font);
+ return CAIRO_STATUS_SUCCESS;
+
+fail2:
+ _cairo_array_fini (&charstring);
+ _cairo_type2_charstrings_fini (type2_subset);
+fail1:
+ cairo_type1_font_destroy (font);
+ return status;
+}
+
+void
+_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset)
+{
+ unsigned int i, num_charstrings;
+ cairo_array_t *charstring;
+
+ num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings);
+ for (i = 0; i < num_charstrings; i++) {
+ charstring = _cairo_array_index (&type2_subset->charstrings, i);
+ _cairo_array_fini (charstring);
+ }
+ _cairo_array_fini (&type2_subset->charstrings);
+
+ free (type2_subset->widths);
+}