static cairo_status_t _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets, cairo_scaled_font_subset_callback_func_t font_subset_callback, void *closure, cairo_bool_t is_scaled) { cairo_sub_font_collection_t collection; if (is_scaled) collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used; else collection.glyphs_size = font_subsets->max_glyphs_per_unscaled_subset_used; if (! collection.glyphs_size) return CAIRO_STATUS_SUCCESS; collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long)); if (collection.glyphs == NULL) return CAIRO_STATUS_NO_MEMORY; collection.font_subset_callback = font_subset_callback; collection.font_subset_callback_closure = closure; if (is_scaled) _cairo_hash_table_foreach (font_subsets->scaled_sub_fonts, _cairo_sub_font_collect, &collection); else _cairo_hash_table_foreach (font_subsets->unscaled_sub_fonts, _cairo_sub_font_collect, &collection); free (collection.glyphs); return CAIRO_STATUS_SUCCESS; }
void _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets) { _cairo_hash_table_foreach (subsets->scaled_sub_fonts, _cairo_sub_font_pluck, subsets->scaled_sub_fonts); _cairo_hash_table_destroy (subsets->scaled_sub_fonts); _cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts); _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); free (subsets); }
static void _cairo_sub_font_collect (void *entry, void *closure) { cairo_sub_font_t *sub_font = entry; cairo_sub_font_collection_t *collection = closure; cairo_scaled_font_subset_t subset; int i; unsigned int j; if (collection->status) return; for (i = 0; i <= sub_font->current_subset; i++) { collection->subset_id = i; collection->num_glyphs = 0; collection->max_glyph = 0; _cairo_hash_table_foreach (sub_font->sub_font_glyphs, _cairo_sub_font_glyph_collect, collection); if (collection->status) break; if (collection->num_glyphs == 0) continue; /* Ensure the resulting array has no uninitialized holes */ assert (collection->num_glyphs == collection->max_glyph + 1); subset.scaled_font = sub_font->scaled_font; subset.is_composite = sub_font->is_composite; subset.font_id = sub_font->font_id; subset.subset_id = i; subset.glyphs = collection->glyphs; subset.num_glyphs = collection->num_glyphs; subset.glyph_names = NULL; /* No need to check for out of memory here. If to_unicode is NULL, the PDF * surface does not emit an ToUnicode stream */ subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long)); if (subset.to_unicode) { for (j = 0; j < collection->num_glyphs; j++) { /* default unicode character required when mapping fails */ subset.to_unicode[j] = 0xfffd; } } collection->status = (collection->font_subset_callback) (&subset, collection->font_subset_callback_closure); if (subset.to_unicode != NULL) free (subset.to_unicode); if (subset.glyph_names != NULL) { for (j = 0; j < collection->num_glyphs; j++) free (subset.glyph_names[j]); free (subset.glyph_names); } if (collection->status) break; } }
/** * _cairo_cache_foreach: * @cache: a cache * @cache_callback: function to be called for each entry * @closure: additional argument to be passed to @cache_callback * * Call @cache_callback for each entry in the cache, in a * non-specified order. **/ void _cairo_cache_foreach (cairo_cache_t *cache, cairo_cache_callback_func_t cache_callback, void *closure) { _cairo_hash_table_foreach (cache->hash_table, cache_callback, closure); }
/** * _cairo_cache_fini: * @cache: a cache to destroy * * Immediately destroys the given cache, freeing all resources * associated with it. As part of this process, the entry_destroy() * function, (as passed to _cairo_cache_init()), will be called for * each entry in the cache. **/ void _cairo_cache_fini (cairo_cache_t *cache) { _cairo_hash_table_foreach (cache->hash_table, _cairo_cache_pluck, cache); assert (cache->size == 0); _cairo_hash_table_destroy (cache->hash_table); }
static void _cairo_sub_font_destroy (cairo_sub_font_t *sub_font) { _cairo_hash_table_foreach (sub_font->sub_font_glyphs, _cairo_sub_font_glyph_pluck, sub_font->sub_font_glyphs); _cairo_hash_table_destroy (sub_font->sub_font_glyphs); cairo_scaled_font_destroy (sub_font->scaled_font); free (sub_font); }
static void _cairo_sub_font_collect (void *entry, void *closure) { cairo_sub_font_t *sub_font = entry; cairo_sub_font_collection_t *collection = closure; cairo_scaled_font_subset_t subset; int i; unsigned int j; for (i = 0; i <= sub_font->current_subset; i++) { collection->subset_id = i; if (sub_font->parent->type == CAIRO_SUBSETS_SCALED) { collection->num_glyphs = 0; collection->max_glyph = 0; } else { /* Assign .notdef glyph to the first glyph in the subset */ collection->glyphs[0] = 0; collection->num_glyphs = 1; collection->max_glyph = 0; } _cairo_hash_table_foreach (sub_font->sub_font_glyphs, _cairo_sub_font_glyph_collect, collection); /* Ensure the resulting array has no uninitialized holes */ assert (collection->num_glyphs == collection->max_glyph + 1); subset.scaled_font = sub_font->scaled_font; subset.is_composite = sub_font->is_composite; subset.font_id = sub_font->font_id; subset.subset_id = i; subset.glyphs = collection->glyphs; subset.num_glyphs = collection->num_glyphs; /* No need to check for out of memory here. If to_unicode is NULL, the PDF * surface does not emit an ToUnicode stream */ subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long)); if (subset.to_unicode) { for (j = 0; j < collection->num_glyphs; j++) { /* default unicode character required when mapping fails */ subset.to_unicode[j] = 0xfffd; } } (collection->font_subset_callback) (&subset, collection->font_subset_callback_closure); if (subset.to_unicode != NULL) free (subset.to_unicode); } }
static void dump_subfont (cairo_sub_font_t *sub_font) { while (sub_font) { printf(" font_id: %d\n", sub_font->font_id); printf(" current_subset: %d\n", sub_font->current_subset); printf(" is_scaled: %d\n", sub_font->is_scaled); printf(" is_composite: %d\n", sub_font->is_composite); printf(" is_user: %d\n", sub_font->is_user); printf(" use_latin_subset: %d\n", sub_font->use_latin_subset); printf(" reserve_notdef: %d\n", sub_font->reserve_notdef); printf(" num_glyphs_in_current_subset: %d\n", sub_font->num_glyphs_in_current_subset); printf(" num_glyphs_in_latin_subset: %d\n", sub_font->num_glyphs_in_latin_subset); printf(" max_glyphs_per_subset: %d\n\n", sub_font->max_glyphs_per_subset); _cairo_hash_table_foreach (sub_font->sub_font_glyphs, dump_glyph, NULL); printf("\n"); sub_font = sub_font->next; } }
static void _cairo_sub_font_collect (void *entry, void *closure) { cairo_sub_font_t *sub_font = entry; cairo_sub_font_collection_t *collection = closure; cairo_scaled_font_subset_t subset; int i; unsigned int j; if (collection->status) return; collection->status = sub_font->scaled_font->status; if (collection->status) return; for (i = 0; i <= sub_font->current_subset; i++) { collection->subset_id = i; collection->num_glyphs = 0; collection->max_glyph = 0; memset (collection->latin_to_subset_glyph_index, 0, 256*sizeof(unsigned long)); _cairo_hash_table_foreach (sub_font->sub_font_glyphs, _cairo_sub_font_glyph_collect, collection); if (collection->status) break; if (collection->num_glyphs == 0) continue; /* Ensure the resulting array has no uninitialized holes */ assert (collection->num_glyphs == collection->max_glyph + 1); subset.scaled_font = sub_font->scaled_font; subset.is_composite = sub_font->is_composite; subset.is_scaled = sub_font->is_scaled; subset.font_id = sub_font->font_id; subset.subset_id = i; subset.glyphs = collection->glyphs; subset.utf8 = collection->utf8; subset.num_glyphs = collection->num_glyphs; subset.glyph_names = NULL; subset.is_latin = FALSE; if (sub_font->use_latin_subset && i == 0) { subset.is_latin = TRUE; subset.to_latin_char = collection->to_latin_char; subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index; } else { subset.to_latin_char = NULL; subset.latin_to_subset_glyph_index = NULL; } collection->status = (collection->font_subset_callback) (&subset, collection->font_subset_callback_closure); if (subset.glyph_names != NULL) { for (j = 0; j < collection->num_glyphs; j++) free (subset.glyph_names[j]); free (subset.glyph_names); } if (collection->status) break; } }
cairo_int_status_t _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset) { unsigned int i; cairo_hash_table_t *names; cairo_string_entry_t key, *entry; char buf[30]; char *utf8; uint16_t *utf16; int utf16_len; cairo_status_t status = CAIRO_STATUS_SUCCESS; names = _cairo_hash_table_create (_cairo_string_equal); if (unlikely (names == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *)); if (unlikely (subset->glyph_names == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_HASH; } i = 0; if (! subset->is_scaled) { subset->glyph_names[0] = strdup (".notdef"); if (unlikely (subset->glyph_names[0] == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_HASH; } status = create_string_entry (subset->glyph_names[0], &entry); if (unlikely (status)) goto CLEANUP_HASH; status = _cairo_hash_table_insert (names, &entry->base); if (unlikely (status)) { free (entry); goto CLEANUP_HASH; } i++; } for (; i < subset->num_glyphs; i++) { utf8 = subset->utf8[i]; utf16 = NULL; utf16_len = 0; if (utf8 && *utf8) { status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len); if (unlikely (status)) goto CLEANUP_HASH; } if (utf16_len == 1) { int ch = _cairo_unicode_to_winansi (utf16[0]); if (ch > 0 && _cairo_winansi_to_glyphname (ch)) strncpy (buf, _cairo_winansi_to_glyphname (ch), sizeof (buf)); else snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]); _cairo_string_init_key (&key, buf); entry = _cairo_hash_table_lookup (names, &key.base); if (entry != NULL) snprintf (buf, sizeof (buf), "g%d", i); } else { snprintf (buf, sizeof (buf), "g%d", i); } free (utf16); subset->glyph_names[i] = strdup (buf); if (unlikely (subset->glyph_names[i] == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_HASH; } status = create_string_entry (subset->glyph_names[i], &entry); if (unlikely (status)) goto CLEANUP_HASH; status = _cairo_hash_table_insert (names, &entry->base); if (unlikely (status)) { free (entry); goto CLEANUP_HASH; } } CLEANUP_HASH: _cairo_hash_table_foreach (names, _pluck_entry, names); _cairo_hash_table_destroy (names); if (likely (status == CAIRO_STATUS_SUCCESS)) return CAIRO_STATUS_SUCCESS; if (subset->glyph_names != NULL) { for (i = 0; i < subset->num_glyphs; i++) { free (subset->glyph_names[i]); } free (subset->glyph_names); subset->glyph_names = NULL; } return status; }