/** * _cairo_array_allocate: * @array: a #cairo_array_t * * Allocate space at the end of the array for @num_elements additional * elements, providing the address of the new memory chunk in * @elements. This memory will be unitialized, but will be accounted * for in the return value of _cairo_array_num_elements(). * * Return value: %CAIRO_STATUS_SUCCESS if successful or * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the * operation. **/ cairo_status_t _cairo_array_allocate (cairo_array_t *array, unsigned int num_elements, void **elements) { cairo_status_t status; status = _cairo_array_grow_by (array, num_elements); if (unlikely (status)) return status; assert (array->num_elements + num_elements <= array->size); *elements = array->elements + array->num_elements * array->element_size; array->num_elements += num_elements; return CAIRO_STATUS_SUCCESS; }
/** * _cairo_array_allocate: * * Allocate space at the end of the array for @num_elements additional * elements, providing the address of the new memory chunk in * @elements. This memory will be unitialized, but will be accounted * for in the return value of _cairo_array_num_elements(). * * Return value: %CAIRO_STATUS_SUCCESS if successful or * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the * operation. **/ cairo_status_t _cairo_array_allocate (cairo_array_t *array, unsigned int num_elements, void **elements) { cairo_status_t status; assert (! array->is_snapshot); status = _cairo_array_grow_by (array, num_elements); if (status) return status; assert (array->num_elements + num_elements <= array->size); *elements = &(*array->elements)[array->num_elements * array->element_size]; array->num_elements += num_elements; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, cairo_truetype_font_t **font_return) { cairo_status_t status; cairo_truetype_font_t *font; const cairo_scaled_font_backend_t *backend; tt_head_t head; tt_hhea_t hhea; tt_maxp_t maxp; unsigned long size; backend = scaled_font_subset->scaled_font->backend; if (!backend->load_truetype_table) return CAIRO_INT_STATUS_UNSUPPORTED; /* FIXME: We should either support subsetting vertical fonts, or fail on * vertical. Currently font_options_t doesn't have vertical flag, but * it should be added in the future. For now, the freetype backend * returns UNSUPPORTED in load_truetype_table if the font is vertical. * * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font)) * return CAIRO_INT_STATUS_UNSUPPORTED; */ size = sizeof (tt_head_t); status = backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_head, 0, (unsigned char *) &head, &size); if (unlikely (status)) return status; size = sizeof (tt_maxp_t); status = backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_maxp, 0, (unsigned char *) &maxp, &size); if (unlikely (status)) return status; size = sizeof (tt_hhea_t); status = backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_hhea, 0, (unsigned char *) &hhea, &size); if (unlikely (status)) return status; font = malloc (sizeof (cairo_truetype_font_t)); if (unlikely (font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); font->backend = backend; font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs); font->scaled_font_subset = scaled_font_subset; font->last_offset = 0; font->last_boundary = 0; _cairo_array_init (&font->output, sizeof (char)); status = _cairo_array_grow_by (&font->output, 4096); if (unlikely (status)) goto fail1; font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t)); if (unlikely (font->glyphs == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; } font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int)); if (unlikely (font->parent_to_subset == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail2; } font->base.num_glyphs = 0; font->base.x_min = (int16_t) be16_to_cpu (head.x_min); font->base.y_min = (int16_t) be16_to_cpu (head.y_min); font->base.x_max = (int16_t) be16_to_cpu (head.x_max); font->base.y_max = (int16_t) be16_to_cpu (head.y_max); font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender); font->base.descent = (int16_t) be16_to_cpu (hhea.descender); font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em); if (font->base.units_per_em == 0) font->base.units_per_em = 2048; font->base.font_name = NULL; status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font, &font->base.ps_name, &font->base.font_name); if (_cairo_status_is_error (status)) goto fail3; /* If the PS name is not found, create a CairoFont-x-y name. */ if (font->base.ps_name == NULL) { font->base.ps_name = malloc (30); if (unlikely (font->base.ps_name == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail3; } snprintf(font->base.ps_name, 30, "CairoFont-%u-%u", scaled_font_subset->font_id, scaled_font_subset->subset_id); } font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int)); if (unlikely (font->base.widths == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail4; } _cairo_array_init (&font->string_offsets, sizeof (unsigned long)); status = _cairo_array_grow_by (&font->string_offsets, 10); if (unlikely (status)) goto fail5; font->status = CAIRO_STATUS_SUCCESS; *font_return = font; return CAIRO_STATUS_SUCCESS; fail5: _cairo_array_fini (&font->string_offsets); free (font->base.widths); fail4: free (font->base.ps_name); fail3: free (font->parent_to_subset); if (font->base.font_name) free (font->base.font_name); fail2: free (font->glyphs); fail1: _cairo_array_fini (&font->output); free (font); return status; }
static cairo_status_t _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, cairo_truetype_font_t **font_return) { cairo_status_t status; cairo_truetype_font_t *font; const cairo_scaled_font_backend_t *backend; tt_head_t head; tt_hhea_t hhea; tt_maxp_t maxp; tt_name_t *name; tt_name_record_t *record; unsigned long size; int i, j; backend = scaled_font_subset->scaled_font->backend; if (!backend->load_truetype_table) return CAIRO_INT_STATUS_UNSUPPORTED; /* FIXME: We should either support subsetting vertical fonts, or fail on * vertical. Currently font_options_t doesn't have vertical flag, but * it should be added in the future. For now, the freetype backend * returns UNSUPPORTED in load_truetype_table if the font is vertical. * * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font)) * return CAIRO_INT_STATUS_UNSUPPORTED; */ size = sizeof (tt_head_t); if (backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_head, 0, (unsigned char *) &head, &size) != CAIRO_STATUS_SUCCESS) return CAIRO_INT_STATUS_UNSUPPORTED; size = sizeof (tt_maxp_t); if (backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_maxp, 0, (unsigned char *) &maxp, &size) != CAIRO_STATUS_SUCCESS) return CAIRO_INT_STATUS_UNSUPPORTED; size = sizeof (tt_hhea_t); if (backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_hhea, 0, (unsigned char *) &hhea, &size) != CAIRO_STATUS_SUCCESS) return CAIRO_INT_STATUS_UNSUPPORTED; size = 0; if (backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_name, 0, NULL, &size) != CAIRO_STATUS_SUCCESS) return CAIRO_INT_STATUS_UNSUPPORTED; name = malloc(size); if (name == NULL) return CAIRO_STATUS_NO_MEMORY; status = backend->load_truetype_table (scaled_font_subset->scaled_font, TT_TAG_name, 0, (unsigned char *) name, &size); if (status) goto fail0; font = malloc (sizeof (cairo_truetype_font_t)); if (font == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto fail0; } font->backend = backend; font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs); font->scaled_font_subset = scaled_font_subset; font->last_offset = 0; font->last_boundary = 0; _cairo_array_init (&font->output, sizeof (char)); status = _cairo_array_grow_by (&font->output, 4096); if (status) goto fail1; font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t)); if (font->glyphs == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto fail1; } font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int)); if (font->parent_to_subset == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto fail2; } font->base.num_glyphs = 0; font->base.x_min = (int16_t) be16_to_cpu (head.x_min); font->base.y_min = (int16_t) be16_to_cpu (head.y_min); font->base.x_max = (int16_t) be16_to_cpu (head.x_max); font->base.y_max = (int16_t) be16_to_cpu (head.y_max); font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender); font->base.descent = (int16_t) be16_to_cpu (hhea.descender); font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em); if (font->base.units_per_em == 0) font->base.units_per_em = 2048; /* Extract the font name from the name table. At present this * just looks for the Mac platform/Roman encoded font name. It * should be extended to use any suitable font name in the * name table. If the mac/roman font name is not found a * CairoFont-x-y name is created. */ font->base.base_font = NULL; for (i = 0; i < be16_to_cpu(name->num_records); i++) { record = &(name->records[i]); if ((be16_to_cpu (record->platform) == 1) && (be16_to_cpu (record->encoding) == 0) && (be16_to_cpu (record->name) == 4)) { font->base.base_font = malloc (be16_to_cpu(record->length) + 1); if (font->base.base_font) { strncpy(font->base.base_font, ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), be16_to_cpu (record->length)); font->base.base_font[be16_to_cpu (record->length)] = 0; } break; } } free (name); name = NULL; if (font->base.base_font == NULL) { font->base.base_font = malloc (30); if (font->base.base_font == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto fail3; } snprintf(font->base.base_font, 30, "CairoFont-%u-%u", scaled_font_subset->font_id, scaled_font_subset->subset_id); } for (i = 0, j = 0; font->base.base_font[j]; j++) { if (font->base.base_font[j] == ' ') continue; font->base.base_font[i++] = font->base.base_font[j]; } font->base.base_font[i] = '\0'; font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int)); if (font->base.widths == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto fail4; } _cairo_array_init (&font->string_offsets, sizeof (unsigned long)); status = _cairo_array_grow_by (&font->string_offsets, 10); if (status) goto fail5; font->status = CAIRO_STATUS_SUCCESS; *font_return = font; return CAIRO_STATUS_SUCCESS; fail5: _cairo_array_fini (&font->string_offsets); free (font->base.widths); fail4: free (font->base.base_font); fail3: free (font->parent_to_subset); fail2: free (font->glyphs); fail1: _cairo_array_fini (&font->output); free (font); fail0: if (name) free (name); return status; }