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; }
cairo_int_status_t _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset) { const cairo_scaled_font_backend_t *backend; unsigned int i; cairo_status_t status; cairo_hash_table_t *names; cairo_string_entry_t key, *entry; char buf[30]; if (subset->to_unicode == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_truetype_create_glyph_to_unicode_map (subset); if (status) { if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; backend = subset->scaled_font->backend; if (backend->map_glyphs_to_unicode == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; status = backend->map_glyphs_to_unicode (subset->scaled_font, subset); if (status) return status; } names = _cairo_hash_table_create (_cairo_string_equal); if (names == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *)); if (subset->glyph_names == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_HASH; } subset->glyph_names[0] = strdup (".notdef"); if (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 (status) goto CLEANUP_HASH; status = _cairo_hash_table_insert (names, &entry->base); if (status) { free (entry); goto CLEANUP_HASH; } for (i = 1; i < subset->num_glyphs; i++) { if (subset->to_unicode[i] <= 0xffff) { snprintf (buf, sizeof(buf), "uni%04X", (unsigned int)(subset->to_unicode[i])); _cairo_string_init_key (&key, buf); if (_cairo_hash_table_lookup (names, &key.base, (cairo_hash_entry_t **) &entry)) { snprintf (buf, sizeof(buf), "g%d", i); } } else { snprintf (buf, sizeof(buf), "g%d", i); } subset->glyph_names[i] = strdup (buf); if (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 (status) goto CLEANUP_HASH; status = _cairo_hash_table_insert (names, &entry->base); if (status) { free (entry); goto CLEANUP_HASH; } } CLEANUP_HASH: while (1) { entry = _cairo_hash_table_random_entry (names, NULL); if (entry == NULL) break; _cairo_hash_table_remove (names, (cairo_hash_entry_t *) entry); free (entry); } _cairo_hash_table_destroy (names); if (status == CAIRO_STATUS_SUCCESS) return CAIRO_STATUS_SUCCESS; if (subset->glyph_names != NULL) { for (i = 0; i < subset->num_glyphs; i++) { if (subset->glyph_names[i] != NULL) free (subset->glyph_names[i]); } free (subset->glyph_names); subset->glyph_names = NULL; } return status; }