static void cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font, unsigned char *buffer) { tt_glyph_data_t *glyph_data; tt_composite_glyph_t *composite_glyph; int num_args; int has_more_components; unsigned short flags; unsigned short index; glyph_data = (tt_glyph_data_t *) buffer; if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0) return; composite_glyph = &glyph_data->glyph; do { flags = be16_to_cpu (composite_glyph->flags); has_more_components = flags & TT_MORE_COMPONENTS; index = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index)); composite_glyph->index = cpu_to_be16 (index); num_args = 1; if (flags & TT_ARG_1_AND_2_ARE_WORDS) num_args += 1; if (flags & TT_WE_HAVE_A_SCALE) num_args += 1; else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE) num_args += 2; else if (flags & TT_WE_HAVE_A_TWO_BY_TWO) num_args += 3; composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]); } while (has_more_components); }
static cairo_status_t cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font, unsigned char *buffer, unsigned long size) { tt_glyph_data_t *glyph_data; tt_composite_glyph_t *composite_glyph; int num_args; int has_more_components; unsigned short flags; unsigned short index; cairo_status_t status; unsigned char *end = buffer + size; if (font->status) return font->status; glyph_data = (tt_glyph_data_t *) buffer; if ((unsigned char *)(&glyph_data->data) >= end) return CAIRO_INT_STATUS_UNSUPPORTED; if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0) return CAIRO_STATUS_SUCCESS; composite_glyph = &glyph_data->glyph; do { if ((unsigned char *)(&composite_glyph->args[1]) > end) return CAIRO_INT_STATUS_UNSUPPORTED; flags = be16_to_cpu (composite_glyph->flags); has_more_components = flags & TT_MORE_COMPONENTS; status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index); if (unlikely (status)) return status; composite_glyph->index = cpu_to_be16 (index); num_args = 1; if (flags & TT_ARG_1_AND_2_ARE_WORDS) num_args += 1; if (flags & TT_WE_HAVE_A_SCALE) num_args += 1; else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE) num_args += 2; else if (flags & TT_WE_HAVE_A_TWO_BY_TWO) num_args += 4; composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]); } while (has_more_components); return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, cairo_scaled_font_subset_t *font_subset) { cairo_truetype_font_t *font = NULL; cairo_status_t status; const char *data = NULL; /* squelch bogus compiler warning */ unsigned long length = 0; /* squelch bogus compiler warning */ unsigned long offsets_length; unsigned int i; const unsigned long *string_offsets = NULL; unsigned long num_strings = 0; status = _cairo_truetype_font_create (font_subset, &font); if (unlikely (status)) return status; for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { unsigned short parent_glyph = font->scaled_font_subset->glyphs[i]; status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph); if (unlikely (status)) goto fail1; } cairo_truetype_font_create_truetype_table_list (font); status = cairo_truetype_font_generate (font, &data, &length, &string_offsets, &num_strings); if (unlikely (status)) goto fail1; truetype_subset->ps_name = strdup (font->base.ps_name); if (unlikely (truetype_subset->ps_name == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; } if (font->base.font_name != NULL) { truetype_subset->font_name = strdup (font->base.font_name); if (unlikely (truetype_subset->font_name == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail2; } } else { truetype_subset->font_name = NULL; } /* The widths array returned must contain only widths for the * glyphs in font_subset. Any subglyphs appended after * font_subset->num_glyphs are omitted. */ truetype_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs); if (unlikely (truetype_subset->widths == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail3; } for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em; truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em; truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em; truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em; truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em; truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em; truetype_subset->descent = (double)font->base.descent/font->base.units_per_em; if (length) { truetype_subset->data = malloc (length); if (unlikely (truetype_subset->data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail4; } memcpy (truetype_subset->data, data, length); } else truetype_subset->data = NULL; truetype_subset->data_length = length; if (num_strings) { offsets_length = num_strings * sizeof (unsigned long); truetype_subset->string_offsets = malloc (offsets_length); if (unlikely (truetype_subset->string_offsets == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail5; } memcpy (truetype_subset->string_offsets, string_offsets, offsets_length); truetype_subset->num_string_offsets = num_strings; } else { truetype_subset->string_offsets = NULL; truetype_subset->num_string_offsets = 0; } cairo_truetype_font_destroy (font); return CAIRO_STATUS_SUCCESS; fail5: free (truetype_subset->data); fail4: free (truetype_subset->widths); fail3: if (truetype_subset->font_name) free (truetype_subset->font_name); fail2: free (truetype_subset->ps_name); fail1: cairo_truetype_font_destroy (font); return status; }