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;
    }
}
示例#4
0
/**
 * _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);
}
示例#5
0
/**
 * _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;
    }
}
示例#10
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;
}