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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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);
}
Пример #11
0
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;
}