Beispiel #1
0
cairo_status_t
_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
				   double		x,
				   double		y,
				   const char          *utf8, 
				   cairo_glyph_t      **glyphs, 
				   int 		       *num_glyphs)
{
    size_t i;
    uint32_t *ucs4 = NULL;
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
    cairo_scaled_glyph_t *scaled_glyph;

    if (scaled_font->backend->text_to_glyphs) {
	status = scaled_font->backend->text_to_glyphs (scaled_font,
						       x, y, utf8,
						       glyphs, num_glyphs);

        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
            return status;
    }

    status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs);
    if (status)
	return status;

    *glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t)));

    if (*glyphs == NULL) {
	status = CAIRO_STATUS_NO_MEMORY;
	goto FAIL;
    }

    for (i = 0; i < *num_glyphs; i++) {            
        (*glyphs)[i].index = (*scaled_font->backend->
			      ucs4_to_index) (scaled_font, ucs4[i]);
	(*glyphs)[i].x = x;
	(*glyphs)[i].y = y;
	
	status = _cairo_scaled_glyph_lookup (scaled_font,
					     (*glyphs)[i].index,
					     CAIRO_SCALED_GLYPH_INFO_METRICS,
					     &scaled_glyph);
	if (status) {
	    free (*glyphs);
	    *glyphs = NULL;
	    goto FAIL;
	}
					     
        x += scaled_glyph->metrics.x_advance;
        y += scaled_glyph->metrics.y_advance;
    }

 FAIL:
    free (ucs4);
    
    return status;
}
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;
}
Beispiel #3
0
/**
 * cairo_toy_font_face_create:
 * @family: a font family name, encoded in UTF-8
 * @slant: the slant for the font
 * @weight: the weight for the font
 *
 * Creates a font face from a triplet of family, slant, and weight.
 * These font faces are used in implementation of the the #cairo_t "toy"
 * font API.
 *
 * If @family is the zero-length string "", the platform-specific default
 * family is assumed.  The default family then can be queried using
 * cairo_toy_font_face_get_family().
 *
 * The cairo_select_font_face() function uses this to create font faces.
 * See that function for limitations of toy font faces.
 *
 * Return value: a newly created #cairo_font_face_t. Free with
 *  cairo_font_face_destroy() when you are done using it.
 *
 * Since: 1.8
 **/
cairo_font_face_t *
cairo_toy_font_face_create (const char          *family,
			    cairo_font_slant_t   slant,
			    cairo_font_weight_t  weight)
{
    cairo_status_t status;
    cairo_toy_font_face_t key, *font_face;
    cairo_hash_table_t *hash_table;

    if (family == NULL)
	return (cairo_font_face_t*) &_cairo_font_face_null_pointer;

    /* Make sure we've got valid UTF-8 for the family */
    status = _cairo_utf8_to_ucs4 (family, -1, NULL, NULL);
    if (status == CAIRO_STATUS_INVALID_STRING)
	return (cairo_font_face_t*) &_cairo_font_face_invalid_string;
    else if (status)
	return (cairo_font_face_t*) &_cairo_font_face_nil;

    switch (slant) {
	case CAIRO_FONT_SLANT_NORMAL:
	case CAIRO_FONT_SLANT_ITALIC:
	case CAIRO_FONT_SLANT_OBLIQUE:
	    break;
	default:
	    return (cairo_font_face_t*) &_cairo_font_face_invalid_slant;
    }

    switch (weight) {
	case CAIRO_FONT_WEIGHT_NORMAL:
	case CAIRO_FONT_WEIGHT_BOLD:
	    break;
	default:
	    return (cairo_font_face_t*) &_cairo_font_face_invalid_weight;
    }

    if (*family == '\0')
	family = CAIRO_FONT_FAMILY_DEFAULT;

    hash_table = _cairo_toy_font_face_hash_table_lock ();
    if (hash_table == NULL)
	goto UNWIND;

    _cairo_toy_font_face_init_key (&key, family, slant, weight);

    /* Return existing font_face if it exists in the hash table. */
    if (_cairo_hash_table_lookup (hash_table,
				  &key.base.hash_entry,
				  (cairo_hash_entry_t **) &font_face))
    {
	if (! font_face->base.status)  {
	    /* We increment the reference count here manually to avoid
	       double-locking. */
	    _cairo_reference_count_inc (&font_face->base.ref_count);
	    _cairo_toy_font_face_hash_table_unlock ();
	    return &font_face->base;
	}

	/* remove the bad font from the hash table */
	_cairo_hash_table_remove (hash_table, &key.base.hash_entry);
	font_face->base.hash_entry.hash = 0;
    }

    /* Otherwise create it and insert into hash table. */
    //+EAWebKitChange
    //11/10/2011
    font_face = cairo_malloc (sizeof (cairo_toy_font_face_t));
    //-EAWebKitChange
    if (font_face == NULL) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto UNWIND_HASH_TABLE_LOCK;
    }

    status = _cairo_toy_font_face_init (font_face, family, slant, weight);
    if (status)
	goto UNWIND_FONT_FACE_MALLOC;

    status = _cairo_hash_table_insert (hash_table, &font_face->base.hash_entry);
    if (status)
	goto UNWIND_FONT_FACE_INIT;

    _cairo_toy_font_face_hash_table_unlock ();

    return &font_face->base;

 UNWIND_FONT_FACE_INIT:
    _cairo_toy_font_face_fini (font_face);
 UNWIND_FONT_FACE_MALLOC:
    //+EAWebKitChange
    //11/10/2011
    cairo_free (font_face);
    //-EAWebKitChange
 UNWIND_HASH_TABLE_LOCK:
    _cairo_toy_font_face_hash_table_unlock ();
 UNWIND:
    return (cairo_font_face_t*) &_cairo_font_face_nil;
}
Beispiel #4
0
/**
 * cairo_toy_font_face_create:
 * @family: a font family name, encoded in UTF-8
 * @slant: the slant for the font
 * @weight: the weight for the font
 *
 * Creates a font face from a triplet of family, slant, and weight.
 * These font faces are used in implementation of the the #cairo_t "toy"
 * font API.
 *
 * If @family is the zero-length string "", the platform-specific default
 * family is assumed.  The default family then can be queried using
 * cairo_toy_font_face_get_family().
 *
 * The cairo_select_font_face() function uses this to create font faces.
 * See that function for limitations and other details of toy font faces.
 *
 * Return value: a newly created #cairo_font_face_t. Free with
 *  cairo_font_face_destroy() when you are done using it.
 *
 * Since: 1.8
 **/
cairo_font_face_t *
cairo_toy_font_face_create (const char          *family,
			    cairo_font_slant_t   slant,
			    cairo_font_weight_t  weight)
{
    cairo_status_t status;
    cairo_toy_font_face_t key, *font_face;
    cairo_hash_table_t *hash_table;

    if (family == NULL)
	return (cairo_font_face_t*) &_cairo_font_face_null_pointer;

    /* Make sure we've got valid UTF-8 for the family */
    status = _cairo_utf8_to_ucs4 (family, -1, NULL, NULL);
    if (unlikely (status)) {
	if (status == CAIRO_STATUS_INVALID_STRING)
	    return (cairo_font_face_t*) &_cairo_font_face_invalid_string;

	return (cairo_font_face_t*) &_cairo_font_face_nil;
    }

    switch (slant) {
	case CAIRO_FONT_SLANT_NORMAL:
	case CAIRO_FONT_SLANT_ITALIC:
	case CAIRO_FONT_SLANT_OBLIQUE:
	    break;
	default:
	    return (cairo_font_face_t*) &_cairo_font_face_invalid_slant;
    }

    switch (weight) {
	case CAIRO_FONT_WEIGHT_NORMAL:
	case CAIRO_FONT_WEIGHT_BOLD:
	    break;
	default:
	    return (cairo_font_face_t*) &_cairo_font_face_invalid_weight;
    }

    if (*family == '\0')
	family = CAIRO_FONT_FAMILY_DEFAULT;

    hash_table = _cairo_toy_font_face_hash_table_lock ();
    if (unlikely (hash_table == NULL))
	goto UNWIND;

    _cairo_toy_font_face_init_key (&key, family, slant, weight);

    /* Return existing font_face if it exists in the hash table. */
    font_face = _cairo_hash_table_lookup (hash_table,
					  &key.base.hash_entry);
    if (font_face != NULL) {
	if (font_face->base.status == CAIRO_STATUS_SUCCESS) {
	    cairo_font_face_reference (&font_face->base);
	    _cairo_toy_font_face_hash_table_unlock ();
	    return &font_face->base;
	}

	/* remove the bad font from the hash table */
	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
    }

    /* Otherwise create it and insert into hash table. */
    font_face = _cairo_malloc (sizeof (cairo_toy_font_face_t));
    if (unlikely (font_face == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto UNWIND_HASH_TABLE_LOCK;
    }

    status = _cairo_toy_font_face_init (font_face, family, slant, weight);
    if (unlikely (status))
	goto UNWIND_FONT_FACE_MALLOC;

    assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
    status = _cairo_hash_table_insert (hash_table, &font_face->base.hash_entry);
    if (unlikely (status))
	goto UNWIND_FONT_FACE_INIT;

    _cairo_toy_font_face_hash_table_unlock ();

    return &font_face->base;

 UNWIND_FONT_FACE_INIT:
    _cairo_toy_font_face_fini (font_face);
 UNWIND_FONT_FACE_MALLOC:
    free (font_face);
 UNWIND_HASH_TABLE_LOCK:
    _cairo_toy_font_face_hash_table_unlock ();
 UNWIND:
    return (cairo_font_face_t*) &_cairo_font_face_nil;
}