コード例 #1
0
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
			   unsigned long	 scaled_font_glyph_index,
			   const char		*text_utf8,
			   int			 text_utf8_len,
                           cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
    cairo_sub_font_glyph_t key, *sub_font_glyph;
    cairo_status_t status;

    _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
    sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs,
					       &key.base);
    if (sub_font_glyph == NULL) {
	uint32_t font_unicode;
	char *font_utf8;
	int font_utf8_len;
	cairo_bool_t is_latin;
	int latin_character;

	status = _cairo_sub_font_glyph_lookup_unicode (sub_font->scaled_font,
							   scaled_font_glyph_index,
							   &font_unicode,
							   &font_utf8,
							   &font_utf8_len);
	if (unlikely(status))
	    return status;

	/* If the supplied utf8 is a valid single character, use it
	 * instead of the font lookup */
	if (text_utf8 != NULL && text_utf8_len > 0) {
	    uint32_t  *ucs4;
	    int	ucs4_len;

	    status = _cairo_utf8_to_ucs4 (text_utf8, text_utf8_len,
					  &ucs4, &ucs4_len);
	    if (status == CAIRO_STATUS_SUCCESS) {
		if (ucs4_len == 1) {
		    font_unicode = ucs4[0];
		    free (font_utf8);
		    font_utf8 = malloc (text_utf8_len + 1);
		    if (font_utf8 == NULL) {
			free (ucs4);
			return _cairo_error (CAIRO_STATUS_NO_MEMORY);
		    }
		    memcpy (font_utf8, text_utf8, text_utf8_len);
		    font_utf8[text_utf8_len] = 0;
		    font_utf8_len = text_utf8_len;
		}
		free (ucs4);
	    }
	}

	/* If glyph is in the winansi encoding and font is not a user
	 * font, put glyph in the latin subset. If glyph is .notdef
	 * the latin subset is preferred but only if the latin subset
	 * already contains at least one glyph. We don't want to
	 * create a separate subset just for the .notdef glyph.
	 */
	is_latin = FALSE;
	latin_character = -1;
	if (sub_font->use_latin_subset &&
	    (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)))
	{
	    latin_character = _cairo_unicode_to_winansi (font_unicode);
	    if (latin_character > 0 ||
		(latin_character == 0 && sub_font->num_glyphs_in_latin_subset > 0))
	    {
		if (!sub_font->latin_char_map[latin_character]) {
		    sub_font->latin_char_map[latin_character] = TRUE;
		    is_latin = TRUE;
		}
	    }
	}

	status = _cairo_sub_font_add_glyph (sub_font,
					    scaled_font_glyph_index,
					    is_latin,
					    latin_character,
					    font_unicode,
					    font_utf8,
					    font_utf8_len,
					    &sub_font_glyph);
	if (unlikely(status))
	    return status;
    }

    subset_glyph->font_id = sub_font->font_id;
    subset_glyph->subset_id = sub_font_glyph->subset_id;
    if (sub_font_glyph->is_latin)
	subset_glyph->subset_glyph_index = sub_font_glyph->latin_character;
    else
	subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;

    subset_glyph->is_scaled = sub_font->is_scaled;
    subset_glyph->is_composite = sub_font->is_composite;
    subset_glyph->is_latin = sub_font_glyph->is_latin;
    subset_glyph->x_advance = sub_font_glyph->x_advance;
    subset_glyph->y_advance = sub_font_glyph->y_advance;
    status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
						   text_utf8, text_utf8_len,
						   &subset_glyph->utf8_is_mapped);
    subset_glyph->unicode = sub_font_glyph->unicode;

    return status;
}
コード例 #2
0
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
			   unsigned long	 scaled_font_glyph_index,
			   const char		*utf8,
			   int			 utf8_len,
                           cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
    cairo_sub_font_glyph_t key, *sub_font_glyph;
    cairo_status_t status;

    _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
    sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs,
					       &key.base);
    if (sub_font_glyph == NULL) {
	cairo_scaled_glyph_t *scaled_glyph;

	if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
	{
	    cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;

	    sub_font->current_subset++;
	    sub_font->num_glyphs_in_current_subset = 0;

	    /* Reserve first glyph in subset for the .notdef glyph
	     * except for Type 3 fonts */
	    if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) {
		status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph);
		if (unlikely (status))
		    return status;
	    }
	}

	_cairo_scaled_font_freeze_cache (sub_font->scaled_font);
        status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
                                             scaled_font_glyph_index,
                                             CAIRO_SCALED_GLYPH_INFO_METRICS,
                                             &scaled_glyph);
	assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
	if (unlikely (status)) {
	    _cairo_scaled_font_thaw_cache (sub_font->scaled_font);
	    return status;
	}

        sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
						       sub_font->current_subset,
						       sub_font->num_glyphs_in_current_subset,
                                                       scaled_glyph->metrics.x_advance,
                                                       scaled_glyph->metrics.y_advance);
	_cairo_scaled_font_thaw_cache (sub_font->scaled_font);

	if (unlikely (sub_font_glyph == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);

	status = _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
						       sub_font->scaled_font,
						       scaled_font_glyph_index);
	if (unlikely (status)) {
	    _cairo_sub_font_glyph_destroy (sub_font_glyph);
	    return status;
	}

	status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
	if (unlikely (status)) {
	    _cairo_sub_font_glyph_destroy (sub_font_glyph);
	    return status;
	}

	sub_font->num_glyphs_in_current_subset++;

        if (sub_font->is_scaled) {
            if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used)
                sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset;
        } else {
            if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used)
                sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset;
        }
    }

    subset_glyph->font_id = sub_font->font_id;
    subset_glyph->subset_id = sub_font_glyph->subset_id;
    subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
    subset_glyph->is_scaled = sub_font->is_scaled;
    subset_glyph->is_composite = sub_font->is_composite;
    subset_glyph->x_advance = sub_font_glyph->x_advance;
    subset_glyph->y_advance = sub_font_glyph->y_advance;
    status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
						   utf8, utf8_len,
						   &subset_glyph->utf8_is_mapped);
    subset_glyph->unicode = sub_font_glyph->unicode;

    return status;
}