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

📄 cairo-ft-font.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2000 Keith Packard * Copyright © 2005 Red Hat, Inc * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is Red Hat, Inc. * * Contributor(s): *      Graydon Hoare <graydon@redhat.com> *	Owen Taylor <otaylor@redhat.com> *      Keith Packard <keithp@keithp.com> *      Carl Worth <cworth@cworth.org> */#include <float.h>#include "cairo-ft-private.h"#include <fontconfig/fontconfig.h>#include <fontconfig/fcfreetype.h>#include <ft2build.h>#include FT_FREETYPE_H#include FT_OUTLINE_H#include FT_IMAGE_H#if HAVE_FT_GLYPHSLOT_EMBOLDEN#include FT_SYNTHESIS_H#endif#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)/* This is the max number of FT_face objects we keep open at once */#define MAX_OPEN_FACES 10/* * The simple 2x2 matrix is converted into separate scale and shape * factors so that hinting works right */typedef struct _cairo_ft_font_transform {    double  x_scale, y_scale;    double  shape[2][2];} cairo_ft_font_transform_t;/* * We create an object that corresponds to a single font on the disk; * (identified by a filename/id pair) these are shared between all * fonts using that file.  For cairo_ft_font_face_create_for_ft_face(), we * just create a one-off version with a permanent face value. */typedef struct _cairo_ft_font_face cairo_ft_font_face_t;struct _cairo_ft_unscaled_font {    cairo_unscaled_font_t base;    cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */    FT_Face face;	    /* provided or cached face */    /* only set if from_face is false */    char *filename;    int id;    /* We temporarily scale the unscaled font as needed */    cairo_bool_t have_scale;    cairo_matrix_t current_scale;    double x_scale;		/* Extracted X scale factor */    double y_scale;             /* Extracted Y scale factor */    cairo_bool_t have_shape;	/* true if the current scale has a non-scale component*/    cairo_matrix_t current_shape;    int lock;		/* count of how many times this font has been locked */    cairo_ft_font_face_t *faces;	/* Linked list of faces for this font */};static int_cairo_ft_unscaled_font_keys_equal (const void *key_a,				    const void *key_b);static void_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);typedef enum _cairo_ft_extra_flags {    CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0),    CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1)} cairo_ft_extra_flags_t;typedef struct _cairo_ft_options {    cairo_font_options_t    base;    int			    load_flags;	 /* flags for FT_Load_Glyph */    cairo_ft_extra_flags_t  extra_flags; /* other flags that affect results */} cairo_ft_options_t;struct _cairo_ft_font_face {    cairo_font_face_t base;    cairo_ft_unscaled_font_t *unscaled;    cairo_ft_options_t ft_options;    cairo_ft_font_face_t *next;};static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;/* * We maintain a hash table to map file/id => cairo_ft_unscaled_font_t. * The hash table itself isn't limited in size. However, we limit the * number of FT_Face objects we keep around; when we've exceeeded that * limit and need to create a new FT_Face, we dump the FT_Face from a * random cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if * there are any). */typedef struct _cairo_ft_unscaled_font_map {    cairo_hash_table_t *hash_table;    FT_Library ft_library;    int num_open_faces;} cairo_ft_unscaled_font_map_t;static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;CAIRO_MUTEX_DECLARE(cairo_ft_unscaled_font_map_mutex);static void_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,				  cairo_ft_unscaled_font_t *unscaled){    if (unscaled->face) {	FT_Done_Face (unscaled->face);	unscaled->face = NULL;	unscaled->have_scale = FALSE;	font_map->num_open_faces--;    }}static void_cairo_ft_unscaled_font_map_create (void){    cairo_ft_unscaled_font_map_t *font_map;    /* This function is only intended to be called from     * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can     * detect some other call path. */    assert (cairo_ft_unscaled_font_map == NULL);    font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t));    if (font_map == NULL)	goto FAIL;    font_map->hash_table =	_cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);    if (font_map->hash_table == NULL)	goto FAIL;    if (FT_Init_FreeType (&font_map->ft_library))	goto FAIL;    font_map->num_open_faces = 0;    cairo_ft_unscaled_font_map = font_map;    return;FAIL:    if (font_map) {	if (font_map->hash_table)	    _cairo_hash_table_destroy (font_map->hash_table);	free (font_map);    }    cairo_ft_unscaled_font_map = NULL;}static void_cairo_ft_unscaled_font_map_destroy (void){    cairo_ft_unscaled_font_t *unscaled;    cairo_ft_unscaled_font_map_t *font_map;    CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex);    if (cairo_ft_unscaled_font_map) {	font_map = cairo_ft_unscaled_font_map;	/* This is rather inefficient, but destroying the hash table	 * is something we only do during debugging, (during	 * cairo_debug_reset_static_data), when efficiency is not	 * relevant. */        while (1) {	    unscaled = _cairo_hash_table_random_entry (font_map->hash_table,						       NULL);	    if (unscaled == NULL)		break;	    _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);	    free (unscaled);	}	assert (font_map->num_open_faces == 0);	FT_Done_FreeType (font_map->ft_library);	_cairo_hash_table_destroy (font_map->hash_table);	free (font_map);	cairo_ft_unscaled_font_map = NULL;    }    CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);}static cairo_ft_unscaled_font_map_t *_cairo_ft_unscaled_font_map_lock (void){    CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex);    if (cairo_ft_unscaled_font_map == NULL)    {	_cairo_ft_unscaled_font_map_create ();	if (cairo_ft_unscaled_font_map == NULL) {	    CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);	    return NULL;	}    }    return cairo_ft_unscaled_font_map;}static void_cairo_ft_unscaled_font_map_unlock (void){    CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);}static void_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,				  char			   *filename,				  int			    id){    unsigned long hash;    key->filename = filename;    key->id = id;    /* 1607 is just an arbitrary prime. */    hash = _cairo_hash_string (filename);    hash += ((unsigned long) id) * 1607;    key->base.hash_entry.hash = hash;}/** * _cairo_ft_unscaled_font_init: * * Initialize a cairo_ft_unscaled_font_t. * * There are two basic flavors of cairo_ft_unscaled_font_t, one * created from an FT_Face and the other created from a filename/id * pair. These two flavors are identified as from_face and !from_face. * * To initialize a from_face font, pass filename==NULL, id=0 and the * desired face. * * To initialize a !from_face font, pass the filename/id as desired * and face==NULL. * * Note that the code handles these two flavors in very distinct * ways. For example there is a hash_table mapping * filename/id->cairo_unscaled_font_t in the !from_face case, but no * parallel in the from_face case, (where the calling code would have * to do its own mapping to ensure similar sharing). **/static cairo_status_t_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,			      const char	       *filename,			      int			id,			      FT_Face			face){    _cairo_unscaled_font_init (&unscaled->base,			       &cairo_ft_unscaled_font_backend);    if (face) {	unscaled->from_face = TRUE;	unscaled->face = face;	unscaled->filename = NULL;	unscaled->id = 0;    } else {	char *filename_copy;	unscaled->from_face = FALSE;	unscaled->face = NULL;	filename_copy = strdup (filename);	if (filename_copy == NULL)	    return CAIRO_STATUS_NO_MEMORY;	_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);    }    unscaled->have_scale = FALSE;    unscaled->lock = 0;    unscaled->faces = NULL;    return CAIRO_STATUS_SUCCESS;}cairo_bool_t_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font){    return unscaled_font->backend == &cairo_ft_unscaled_font_backend;}/** * _cairo_ft_unscaled_font_fini: * * Free all data associated with a cairo_ft_unscaled_font_t. * * CAUTION: The unscaled->face field must be NULL before calling this * function. This is because the cairo_ft_unscaled_font_map keeps a * count of these faces (font_map->num_open_faces) so it maintains the * unscaled->face field while it has its lock held. See * _font_map_release_face_lock_held(). **/static void_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled){    assert (unscaled->face == NULL);    if (unscaled->filename) {	free (unscaled->filename);	unscaled->filename = NULL;    }}static int_cairo_ft_unscaled_font_keys_equal (const void *key_a,				    const void *key_b){    const cairo_ft_unscaled_font_t *unscaled_a = key_a;    const cairo_ft_unscaled_font_t *unscaled_b = key_b;    return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&	    unscaled_a->id == unscaled_b->id);}/* Finds or creates a cairo_ft_unscaled_font for the filename/id from * pattern.  Returns a new reference to the unscaled font. */static cairo_ft_unscaled_font_t *_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern){    cairo_ft_unscaled_font_t key, *unscaled;    cairo_ft_unscaled_font_map_t *font_map;    cairo_status_t status;    FcChar8 *fc_filename;    char *filename;    int id;    if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)	goto UNWIND;    filename = (char *) fc_filename;    if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)	goto UNWIND;    font_map = _cairo_ft_unscaled_font_map_lock ();    if (font_map == NULL)	goto UNWIND;    _cairo_ft_unscaled_font_init_key (&key, filename, id);    /* Return existing unscaled font if it exists in the hash table. */    if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,				  (cairo_hash_entry_t **) &unscaled))    {	_cairo_ft_unscaled_font_map_unlock ();	_cairo_unscaled_font_reference (&unscaled->base);	return unscaled;    }    /* Otherwise create it and insert into hash table. */    unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));    if (unscaled == NULL)	goto UNWIND_FONT_MAP_LOCK;    status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);    if (status)	goto UNWIND_UNSCALED_MALLOC;    status = _cairo_hash_table_insert (font_map->hash_table,				       &unscaled->base.hash_entry);    if (status)	goto UNWIND_UNSCALED_FONT_INIT;    _cairo_ft_unscaled_font_map_unlock ();    return unscaled;UNWIND_UNSCALED_FONT_INIT:    _cairo_ft_unscaled_font_fini (unscaled);UNWIND_UNSCALED_MALLOC:    free (unscaled);UNWIND_FONT_MAP_LOCK:    _cairo_ft_unscaled_font_map_unlock ();UNWIND:    return NULL;}static cairo_ft_unscaled_font_t *_cairo_ft_unscaled_font_create_from_face (FT_Face face){    cairo_status_t status;    cairo_ft_unscaled_font_t *unscaled;    unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));    if (unscaled == NULL)	return NULL;    status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);    if (status) {	free (unscaled);	return NULL;    }    return unscaled;}static void_cairo_ft_unscaled_font_destroy (void *abstract_font){    cairo_ft_unscaled_font_t *unscaled  = abstract_font;

⌨️ 快捷键说明

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