static void _cairo_sub_font_glyph_pluck (void *entry, void *closure) { cairo_sub_font_glyph_t *sub_font_glyph = entry; cairo_hash_table_t *sub_font_glyphs = closure; _cairo_hash_table_remove (sub_font_glyphs, &sub_font_glyph->base); _cairo_sub_font_glyph_destroy (sub_font_glyph); }
static cairo_status_t _cairo_sub_font_add_glyph (cairo_sub_font_t *sub_font, unsigned long scaled_font_glyph_index, cairo_bool_t is_latin, int latin_character, uint32_t unicode, char *utf8, int utf8_len, cairo_sub_font_glyph_t **sub_font_glyph_out) { cairo_scaled_glyph_t *scaled_glyph; cairo_sub_font_glyph_t *sub_font_glyph; int *num_glyphs_in_subset_ptr; double x_advance; double y_advance; cairo_int_status_t status; _cairo_scaled_font_freeze_cache (sub_font->scaled_font); status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, scaled_font_glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (unlikely (status)) { _cairo_scaled_font_thaw_cache (sub_font->scaled_font); return status; } x_advance = scaled_glyph->metrics.x_advance; y_advance = scaled_glyph->metrics.y_advance; _cairo_scaled_font_thaw_cache (sub_font->scaled_font); if (!is_latin && sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) { sub_font->current_subset++; sub_font->num_glyphs_in_current_subset = 0; } if (is_latin) num_glyphs_in_subset_ptr = &sub_font->num_glyphs_in_latin_subset; else num_glyphs_in_subset_ptr = &sub_font->num_glyphs_in_current_subset; /* Reserve first glyph in subset for the .notdef glyph except for * Type 3 fonts */ if (*num_glyphs_in_subset_ptr == 0 && scaled_font_glyph_index != 0 && ! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) { status = _cairo_sub_font_add_glyph (sub_font, 0, is_latin, 0, 0, NULL, -1, &sub_font_glyph); if (unlikely (status)) return status; } sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, is_latin ? 0 : sub_font->current_subset, *num_glyphs_in_subset_ptr, x_advance, y_advance, is_latin ? latin_character : -1, unicode, utf8, utf8_len); if (unlikely (sub_font_glyph == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base); if (unlikely (status)) { _cairo_sub_font_glyph_destroy (sub_font_glyph); return status; } (*num_glyphs_in_subset_ptr)++; if (sub_font->is_scaled) { if (*num_glyphs_in_subset_ptr > sub_font->parent->max_glyphs_per_scaled_subset_used) sub_font->parent->max_glyphs_per_scaled_subset_used = *num_glyphs_in_subset_ptr; } else { if (*num_glyphs_in_subset_ptr > sub_font->parent->max_glyphs_per_unscaled_subset_used) sub_font->parent->max_glyphs_per_unscaled_subset_used = *num_glyphs_in_subset_ptr; } *sub_font_glyph_out = sub_font_glyph; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, unsigned long scaled_font_glyph_index, cairo_scaled_font_subsets_glyph_t *subset_glyph) { cairo_sub_font_glyph_t key, *sub_font_glyph; cairo_status_t status; cairo_scaled_glyph_t *scaled_glyph; _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, (cairo_hash_entry_t **) &sub_font_glyph)) { if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) { sub_font->current_subset++; sub_font->num_glyphs_in_current_subset = 0; if (sub_font->parent->type != CAIRO_SUBSETS_SCALED) { /* Reserve first glyph in subset for the .notdef glyph */ sub_font->num_glyphs_in_current_subset++; } } status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, scaled_font_glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (status) return status; sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, sub_font->current_subset, sub_font->num_glyphs_in_current_subset++, scaled_glyph->metrics.x_advance); if (sub_font_glyph == NULL) return CAIRO_STATUS_NO_MEMORY; if (sub_font->is_scaled) { if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used) sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset; } else { if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used) sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset; } status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base); if (status) { _cairo_sub_font_glyph_destroy (sub_font_glyph); return status; } } subset_glyph->font_id = sub_font->font_id; subset_glyph->subset_id = sub_font_glyph->subset_id; subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; subset_glyph->is_scaled = sub_font->is_scaled; subset_glyph->is_composite = sub_font->is_composite; subset_glyph->x_advance = sub_font_glyph->x_advance; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, unsigned long scaled_font_glyph_index, const char *utf8, int utf8_len, cairo_scaled_font_subsets_glyph_t *subset_glyph) { cairo_sub_font_glyph_t key, *sub_font_glyph; cairo_status_t status; _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base); if (sub_font_glyph == NULL) { cairo_scaled_glyph_t *scaled_glyph; if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) { cairo_scaled_font_subsets_glyph_t tmp_subset_glyph; sub_font->current_subset++; sub_font->num_glyphs_in_current_subset = 0; /* Reserve first glyph in subset for the .notdef glyph * except for Type 3 fonts */ if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) { status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph); if (unlikely (status)) return status; } } _cairo_scaled_font_freeze_cache (sub_font->scaled_font); status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, scaled_font_glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (unlikely (status)) { _cairo_scaled_font_thaw_cache (sub_font->scaled_font); return status; } sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, sub_font->current_subset, sub_font->num_glyphs_in_current_subset, scaled_glyph->metrics.x_advance, scaled_glyph->metrics.y_advance); _cairo_scaled_font_thaw_cache (sub_font->scaled_font); if (unlikely (sub_font_glyph == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph, sub_font->scaled_font, scaled_font_glyph_index); if (unlikely (status)) { _cairo_sub_font_glyph_destroy (sub_font_glyph); return status; } status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base); if (unlikely (status)) { _cairo_sub_font_glyph_destroy (sub_font_glyph); return status; } sub_font->num_glyphs_in_current_subset++; if (sub_font->is_scaled) { if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used) sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset; } else { if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used) sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset; } } subset_glyph->font_id = sub_font->font_id; subset_glyph->subset_id = sub_font_glyph->subset_id; subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; subset_glyph->is_scaled = sub_font->is_scaled; subset_glyph->is_composite = sub_font->is_composite; subset_glyph->x_advance = sub_font_glyph->x_advance; subset_glyph->y_advance = sub_font_glyph->y_advance; status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len, &subset_glyph->utf8_is_mapped); subset_glyph->unicode = sub_font_glyph->unicode; return status; }