static cairo_scaled_font_subsets_t * _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type) { cairo_scaled_font_subsets_t *subsets; subsets = malloc (sizeof (cairo_scaled_font_subsets_t)); if (subsets == NULL) return NULL; subsets->type = type; subsets->max_glyphs_per_unscaled_subset_used = 0; subsets->max_glyphs_per_scaled_subset_used = 0; subsets->num_sub_fonts = 0; subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); if (! subsets->unscaled_sub_fonts) { free (subsets); return NULL; } subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); if (! subsets->scaled_sub_fonts) { _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); free (subsets); return NULL; } return subsets; }
static cairo_scaled_font_subsets_t * _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type) { cairo_scaled_font_subsets_t *subsets; subsets = malloc (sizeof (cairo_scaled_font_subsets_t)); if (unlikely (subsets == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; } subsets->type = type; subsets->max_glyphs_per_unscaled_subset_used = 0; subsets->max_glyphs_per_scaled_subset_used = 0; subsets->num_sub_fonts = 0; subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); if (! subsets->unscaled_sub_fonts) { free (subsets); return NULL; } subsets->unscaled_sub_fonts_list = NULL; subsets->unscaled_sub_fonts_list_end = NULL; subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); if (! subsets->scaled_sub_fonts) { _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); free (subsets); return NULL; } subsets->scaled_sub_fonts_list = NULL; subsets->scaled_sub_fonts_list_end = NULL; return subsets; }
static cairo_scaled_font_map_t * _cairo_scaled_font_map_lock (void) { CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); if (cairo_scaled_font_map == NULL) { cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t)); if (cairo_scaled_font_map == NULL) goto CLEANUP_MUTEX_LOCK; cairo_scaled_font_map->hash_table = _cairo_hash_table_create (_cairo_scaled_font_keys_equal); if (cairo_scaled_font_map->hash_table == NULL) goto CLEANUP_SCALED_FONT_MAP; cairo_scaled_font_map->num_holdovers = 0; } return cairo_scaled_font_map; CLEANUP_SCALED_FONT_MAP: free (cairo_scaled_font_map); CLEANUP_MUTEX_LOCK: CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); return NULL; }
static cairo_status_t _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, cairo_scaled_font_t *scaled_font, unsigned int font_id, int max_glyphs_per_subset, cairo_bool_t is_scaled, cairo_bool_t is_composite, cairo_sub_font_t **sub_font_out) { cairo_sub_font_t *sub_font; int i; sub_font = _cairo_malloc (sizeof (cairo_sub_font_t)); if (unlikely (sub_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); sub_font->is_scaled = is_scaled; sub_font->is_composite = is_composite; sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face); sub_font->reserve_notdef = !sub_font->is_user; _cairo_sub_font_init_key (sub_font, scaled_font); sub_font->parent = parent; sub_font->scaled_font = scaled_font; sub_font->font_id = font_id; sub_font->use_latin_subset = parent->use_latin_subset; /* latin subsets of Type 3 and CID CFF fonts are not supported */ if (sub_font->is_user || sub_font->is_scaled || _cairo_cff_scaled_font_is_cid_cff (scaled_font) ) { sub_font->use_latin_subset = FALSE; } if (sub_font->use_latin_subset) sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */ else sub_font->current_subset = 0; sub_font->num_glyphs_in_current_subset = 0; sub_font->num_glyphs_in_latin_subset = 0; sub_font->max_glyphs_per_subset = max_glyphs_per_subset; for (i = 0; i < 256; i++) sub_font->latin_char_map[i] = FALSE; sub_font->sub_font_glyphs = _cairo_hash_table_create (NULL); if (unlikely (sub_font->sub_font_glyphs == NULL)) { free (sub_font); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } sub_font->next = NULL; *sub_font_out = sub_font; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, cairo_scaled_font_t *scaled_font, unsigned int font_id, int max_glyphs_per_subset, cairo_bool_t is_scaled, cairo_bool_t is_composite, cairo_sub_font_t **sub_font_out) { cairo_sub_font_t *sub_font; cairo_status_t status; cairo_scaled_font_subsets_glyph_t subset_glyph; sub_font = malloc (sizeof (cairo_sub_font_t)); if (unlikely (sub_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); sub_font->is_scaled = is_scaled; sub_font->is_composite = is_composite; sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face); _cairo_sub_font_init_key (sub_font, scaled_font); sub_font->parent = parent; sub_font->scaled_font = scaled_font; sub_font->font_id = font_id; sub_font->current_subset = 0; sub_font->num_glyphs_in_current_subset = 0; sub_font->max_glyphs_per_subset = max_glyphs_per_subset; sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal); if (unlikely (sub_font->sub_font_glyphs == NULL)) { free (sub_font); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } sub_font->next = NULL; /* Reserve first glyph in subset for the .notdef glyph except for * Type 3 fonts */ if (! is_scaled) { status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph); if (unlikely (status)) { _cairo_hash_table_destroy (sub_font->sub_font_glyphs); free (sub_font); return status; } } *sub_font_out = sub_font; return CAIRO_STATUS_SUCCESS; }
static cairo_hash_table_t * _cairo_toy_font_face_hash_table_lock (void) { CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); if (cairo_toy_font_face_hash_table == NULL) { cairo_toy_font_face_hash_table = _cairo_hash_table_create (_cairo_toy_font_face_keys_equal); if (cairo_toy_font_face_hash_table == NULL) { CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); return NULL; } } return cairo_toy_font_face_hash_table; }
static cairo_status_t _cairo_cache_init (cairo_cache_t *cache, cairo_cache_keys_equal_func_t keys_equal, cairo_destroy_func_t entry_destroy, unsigned long max_size) { cache->hash_table = _cairo_hash_table_create (keys_equal); if (unlikely (cache->hash_table == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); cache->entry_destroy = entry_destroy; cache->max_size = max_size; cache->size = 0; cache->freeze_count = 0; return CAIRO_STATUS_SUCCESS; }
static cairo_sub_font_t * _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, cairo_scaled_font_t *scaled_font, unsigned int font_id, int max_glyphs_per_subset, cairo_bool_t is_scaled, cairo_bool_t is_composite) { cairo_sub_font_t *sub_font; sub_font = malloc (sizeof (cairo_sub_font_t)); if (sub_font == NULL) return NULL; sub_font->is_scaled = is_scaled; sub_font->is_composite = is_composite; _cairo_sub_font_init_key (sub_font, scaled_font); sub_font->parent = parent; sub_font->scaled_font = scaled_font; sub_font->font_id = font_id; sub_font->current_subset = 0; sub_font->num_glyphs_in_current_subset = 0; sub_font->max_glyphs_per_subset = max_glyphs_per_subset; sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal); if (! sub_font->sub_font_glyphs) { free (sub_font); return NULL; } if (parent->type != CAIRO_SUBSETS_SCALED) { /* Reserve first glyph in subset for the .notdef glyph */ sub_font->num_glyphs_in_current_subset++; } return sub_font; }
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; }
static void parse_options (cairo_perf_t *perf, int argc, char *argv[]) { int c; const char *iters; char *end; int verbose = 0; int use_surface_cache = 0; if ((iters = getenv ("CAIRO_PERF_ITERATIONS")) && *iters) perf->iterations = strtol (iters, NULL, 0); else perf->iterations = CAIRO_PERF_ITERATIONS_DEFAULT; perf->exact_iterations = 0; perf->raw = FALSE; perf->list_only = FALSE; perf->names = NULL; perf->num_names = 0; perf->summary = stdout; perf->summary_continuous = FALSE; perf->exclude_names = NULL; perf->num_exclude_names = 0; while (1) { c = _cairo_getopt (argc, argv, "i:x:lrvc"); if (c == -1) break; switch (c) { case 'i': perf->exact_iterations = TRUE; perf->iterations = strtoul (optarg, &end, 10); if (*end != '\0') { fprintf (stderr, "Invalid argument for -i (not an integer): %s\n", optarg); exit (1); } break; case 'l': perf->list_only = TRUE; break; case 'r': perf->raw = TRUE; perf->summary = NULL; break; case 'v': verbose = 1; break; case 'c': use_surface_cache = 1; break; case 'x': if (! read_excludes (perf, optarg)) { fprintf (stderr, "Invalid argument for -x (not readable file): %s\n", optarg); exit (1); } break; default: fprintf (stderr, "Internal error: unhandled option: %c\n", c); /* fall-through */ case '?': usage (argv[0]); exit (1); } } if (verbose && perf->summary == NULL) perf->summary = stderr; #if HAVE_UNISTD_H if (perf->summary && isatty (fileno (perf->summary))) perf->summary_continuous = TRUE; #endif if (optind < argc) { perf->names = &argv[optind]; perf->num_names = argc - optind; } if (use_surface_cache) surface_cache = _cairo_hash_table_create (scache_equal); }
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; }