⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-ft-font.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (unscaled == NULL)	return;    if (unscaled->from_face) {	/* See comments in _ft_font_face_destroy about the "zombie" state	 * for a _ft_font_face.	 */	if (unscaled->faces && !unscaled->faces->unscaled)	    cairo_font_face_destroy (&unscaled->faces->base);    } else {	cairo_ft_unscaled_font_map_t *font_map;	font_map = _cairo_ft_unscaled_font_map_lock ();	/* All created objects must have been mapped in the font map. */	assert (font_map != NULL);	_cairo_hash_table_remove (font_map->hash_table,				  &unscaled->base.hash_entry);	_font_map_release_face_lock_held (font_map, unscaled);	_cairo_ft_unscaled_font_fini (unscaled);	_cairo_ft_unscaled_font_map_unlock ();    }}static cairo_bool_t_has_unlocked_face (void *entry){    cairo_ft_unscaled_font_t *unscaled = entry;    return (unscaled->lock == 0 && unscaled->face);}/* Ensures that an unscaled font has a face object. If we exceed * MAX_OPEN_FACES, try to close some. * * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't * set the scale on the face, but just returns it at the last scale. */FT_Face_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled){    cairo_ft_unscaled_font_map_t *font_map;    FT_Face face = NULL;    if (unscaled->face) {	unscaled->lock++;	return unscaled->face;    }    /* If this unscaled font was created from an FT_Face then we just     * returned it above. */    assert (!unscaled->from_face);    font_map = _cairo_ft_unscaled_font_map_lock ();    assert (font_map != NULL);    while (font_map->num_open_faces >= MAX_OPEN_FACES)    {	cairo_ft_unscaled_font_t *entry;	entry = _cairo_hash_table_random_entry (font_map->hash_table,						_has_unlocked_face);	if (entry == NULL)	    break;	_font_map_release_face_lock_held (font_map, entry);    }    if (FT_New_Face (font_map->ft_library,		     unscaled->filename,		     unscaled->id,		     &face) != FT_Err_Ok)	goto FAIL;    unscaled->face = face;    unscaled->lock++;    font_map->num_open_faces++; FAIL:    _cairo_ft_unscaled_font_map_unlock ();    return face;}/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face */void_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled){    assert (unscaled->lock > 0);    unscaled->lock--;}static void_compute_transform (cairo_ft_font_transform_t *sf,		    cairo_matrix_t      *scale){    cairo_matrix_t normalized = *scale;    double tx, ty;    /* The font matrix has x and y "scale" components which we extract and     * use as character scale values. These influence the way freetype     * chooses hints, as well as selecting different bitmaps in     * hand-rendered fonts. We also copy the normalized matrix to     * freetype's transformation.     */    _cairo_matrix_compute_scale_factors (&normalized,					 &sf->x_scale, &sf->y_scale,					 /* XXX */ 1);    if (sf->x_scale != 0 && sf->y_scale != 0) {	cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale);	_cairo_matrix_get_affine (&normalized,				  &sf->shape[0][0], &sf->shape[0][1],				  &sf->shape[1][0], &sf->shape[1][1],				  &tx, &ty);    } else {	sf->shape[0][0] = sf->shape[1][1] = 1.0;	sf->shape[0][1] = sf->shape[1][0] = 0.0;    }}/* Temporarily scales an unscaled font to the give scale. We catch * scaling to the same size, since changing a FT_Face is expensive. */static void_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,				   cairo_matrix_t	      *scale){    cairo_ft_font_transform_t sf;    FT_Matrix mat;    FT_UInt pixel_width, pixel_height;    FT_Error error;    assert (unscaled->face != NULL);    if (unscaled->have_scale &&	scale->xx == unscaled->current_scale.xx &&	scale->yx == unscaled->current_scale.yx &&	scale->xy == unscaled->current_scale.xy &&	scale->yy == unscaled->current_scale.yy)	return;    unscaled->have_scale = TRUE;    unscaled->current_scale = *scale;    _compute_transform (&sf, scale);    unscaled->x_scale = sf.x_scale;    unscaled->y_scale = sf.y_scale;    mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]);    mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]);    mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);    mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);    unscaled->have_shape = (mat.xx != 0x10000 ||			    mat.yx != 0x00000 ||			    mat.xy != 0x00000 ||			    mat.yy != 0x10000);    cairo_matrix_init (&unscaled->current_shape,		       sf.shape[0][0], sf.shape[0][1],		       sf.shape[1][0], sf.shape[1][1],		       0.0, 0.0);    FT_Set_Transform(unscaled->face, &mat, NULL);    if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {	pixel_width = sf.x_scale;	pixel_height = sf.y_scale;	error = FT_Set_Char_Size (unscaled->face,				  sf.x_scale * 64.0,				  sf.y_scale * 64.0,				  0, 0);    } else {	double min_distance = DBL_MAX;	int i;	int best_i = 0;	pixel_width = pixel_height = 0;	for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {#if HAVE_FT_BITMAP_SIZE_Y_PPEM	    double size = unscaled->face->available_sizes[i].y_ppem / 64.;#else	    double size = unscaled->face->available_sizes[i].height;#endif	    double distance = fabs (size - sf.y_scale);	    if (distance <= min_distance) {		min_distance = distance;		best_i = i;	    }	}#if HAVE_FT_BITMAP_SIZE_Y_PPEM	error = FT_Set_Char_Size (unscaled->face,				  unscaled->face->available_sizes[best_i].x_ppem,				  unscaled->face->available_sizes[best_i].y_ppem,				  0, 0);	if (error)#endif	    error = FT_Set_Pixel_Sizes (unscaled->face,					unscaled->face->available_sizes[best_i].width,					unscaled->face->available_sizes[best_i].height);    }    assert (error == 0);}/* Empirically-derived subpixel filtering values thanks to Keith * Packard and libXft. */static const int    filters[3][3] = {    /* red */#if 0    {    65538*4/7,65538*2/7,65538*1/7 },    /* green */    {    65536*1/4, 65536*2/4, 65537*1/4 },    /* blue */    {    65538*1/7,65538*2/7,65538*4/7 },#endif    {    65538*9/13,65538*3/13,65538*1/13 },    /* green */    {    65538*1/6, 65538*4/6, 65538*1/6 },    /* blue */    {    65538*1/13,65538*3/13,65538*9/13 },};/* Fills in val->image with an image surface created from @bitmap */static cairo_status_t_get_bitmap_surface (FT_Bitmap		     *bitmap,		     cairo_bool_t	      own_buffer,		     cairo_font_options_t    *font_options,		     cairo_image_surface_t  **surface){    int width, height, stride;    unsigned char *data;    int format = CAIRO_FORMAT_A8;    cairo_bool_t subpixel = FALSE;    width = bitmap->width;    height = bitmap->rows;    switch (bitmap->pixel_mode) {    case FT_PIXEL_MODE_MONO:	stride = (((width + 31) & ~31) >> 3);	if (own_buffer) {	    data = bitmap->buffer;	    assert (stride == bitmap->pitch);	} else {	    data = malloc (stride * height);	    if (!data)		return CAIRO_STATUS_NO_MEMORY;	    if (stride == bitmap->pitch) {		memcpy (data, bitmap->buffer, stride * height);	    } else {		int i;		unsigned char *source, *dest;		source = bitmap->buffer;		dest = data;		for (i = height; i; i--) {		    memcpy (dest, source, bitmap->pitch);		    memset (dest + bitmap->pitch, '\0', stride - bitmap->pitch);		    source += bitmap->pitch;		    dest += stride;		}	    }	}#ifndef WORDS_BIGENDIAN	{	    unsigned char   *d = data;	    int		count = stride * height;	    while (count--) {		*d = CAIRO_BITSWAP8 (*d);		d++;	    }	}#endif	format = CAIRO_FORMAT_A1;	break;    case FT_PIXEL_MODE_LCD:    case FT_PIXEL_MODE_LCD_V:    case FT_PIXEL_MODE_GRAY:	switch (font_options->antialias) {	case CAIRO_ANTIALIAS_DEFAULT:	case CAIRO_ANTIALIAS_GRAY:	case CAIRO_ANTIALIAS_NONE:	default:	    stride = bitmap->pitch;	    if (own_buffer) {		data = bitmap->buffer;	    } else {		data = malloc (stride * height);		if (!data)		    return CAIRO_STATUS_NO_MEMORY;		memcpy (data, bitmap->buffer, stride * height);	    }	    format = CAIRO_FORMAT_A8;	    break;	case CAIRO_ANTIALIAS_SUBPIXEL: {	    int		    x, y;	    unsigned char   *in_line, *out_line, *in;	    unsigned int    *out;	    unsigned int    red, green, blue;	    int		    rf, gf, bf;	    int		    s;	    int		    o, os;	    unsigned char   *data_rgba;	    unsigned int    width_rgba, stride_rgba;	    int		    vmul = 1;	    int		    hmul = 1;	    switch (font_options->subpixel_order) {	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:	    case CAIRO_SUBPIXEL_ORDER_RGB:	    case CAIRO_SUBPIXEL_ORDER_BGR:	    default:		width /= 3;		hmul = 3;		break;	    case CAIRO_SUBPIXEL_ORDER_VRGB:	    case CAIRO_SUBPIXEL_ORDER_VBGR:		vmul = 3;		height /= 3;		break;	    }	    /*	     * Filter the glyph to soften the color fringes	     */	    width_rgba = width;	    stride = bitmap->pitch;	    stride_rgba = (width_rgba * 4 + 3) & ~3;	    data_rgba = calloc (1, stride_rgba * height);	    os = 1;	    switch (font_options->subpixel_order) {	    case CAIRO_SUBPIXEL_ORDER_VRGB:		os = stride;	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:	    case CAIRO_SUBPIXEL_ORDER_RGB:	    default:		rf = 0;		gf = 1;		bf = 2;		break;	    case CAIRO_SUBPIXEL_ORDER_VBGR:		os = stride;	    case CAIRO_SUBPIXEL_ORDER_BGR:		bf = 0;		gf = 1;		rf = 2;		break;	    }	    in_line = bitmap->buffer;	    out_line = data_rgba;	    for (y = 0; y < height; y++)	    {		in = in_line;		out = (unsigned int *) out_line;		in_line += stride * vmul;		out_line += stride_rgba;		for (x = 0; x < width * hmul; x += hmul)		{		    red = green = blue = 0;		    o = 0;		    for (s = 0; s < 3; s++)		    {			red += filters[rf][s]*in[x+o];			green += filters[gf][s]*in[x+o];			blue += filters[bf][s]*in[x+o];			o += os;		    }		    red = red / 65536;		    green = green / 65536;		    blue = blue / 65536;		    *out++ = (green << 24) | (red << 16) | (green << 8) | blue;		}	    }	    /* Images here are stored in native format. The	     * backend must convert to its own format as needed	     */	    if (own_buffer)		free (bitmap->buffer);	    data = data_rgba;	    stride = stride_rgba;	    format = CAIRO_FORMAT_ARGB32;	    subpixel = TRUE;	    break;	}	}	break;    case FT_PIXEL_MODE_GRAY2:    case FT_PIXEL_MODE_GRAY4:	/* These could be triggered by very rare types of TrueType fonts */    default:	return CAIRO_STATUS_NO_MEMORY;    }    *surface = (cairo_image_surface_t *)	cairo_image_surface_create_for_data (data,					     format,					     width, height, stride);    if ((*surface)->base.status) {	free (data);	return CAIRO_STATUS_NO_MEMORY;    }    if (subpixel)	pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);    _cairo_image_surface_assume_ownership_of_data ((*surface));    return CAIRO_STATUS_SUCCESS;}/* Converts an outline FT_GlyphSlot into an image * * This could go through _render_glyph_bitmap as well, letting * FreeType convert the outline to a bitmap, but doing it ourselves * has two minor advantages: first, we save a copy of the bitmap * buffer: we can directly use the buffer that FreeType renders * into. * * Second, it may help when we add support for subpixel * rendering: the Xft code does it this way. (Keith thinks that * it may also be possible to get the subpixel rendering with * FT_Render_Glyph: something worth looking into in more detail * when we add subpixel support. If so, we may want to eliminate * this version of the code path entirely. */static cairo_status_t_render_glyph_outline (FT_Face                    face,		       cairo_font_options_t	 *font_options,		       cairo_image_surface_t	**surface){    FT_GlyphSlot glyphslot = face->glyph;    FT_Outline *outline = &glyphslot->outline;    FT_Bitmap bitmap;    FT_BBox cbox;    FT_Matrix matrix;    int hmul = 1;    int vmul = 1;    unsigned int width, height, stride;    cairo_bool_t subpixel = FALSE;    cairo_status_t status;    FT_Outline_Get_CBox (outline, &cbox);    cbox.xMin &= -64;    cbox.yMin &= -64;    cbox.xMax = (cbox.xMax + 63) & -64;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -