📄 pangofc-fontmap.c
字号:
/* Pango * pangofc-fontmap.c: Base fontmap type for fontconfig-based backends * * Copyright (C) 2000-2003 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* Size of fontset cache */#define FONTSET_CACHE_SIZE 64#include <config.h>#include <math.h>#include "pango-context.h"#include "pangofc-fontmap.h"#include "pangofc-private.h"#include "pango-impl-utils.h"#include "modules.h"#include "pango-enum-types.h"typedef struct _PangoFcCoverageKey PangoFcCoverageKey;typedef struct _PangoFcFace PangoFcFace;typedef struct _PangoFcFamily PangoFcFamily;typedef struct _PangoFcPatternSet PangoFcPatternSet;typedef struct _PangoFcFindFuncInfo PangoFcFindFuncInfo;typedef struct _FontsetHashKey FontsetHashKey;typedef struct _FontHashKey FontHashKey;#define PANGO_FC_TYPE_FAMILY (pango_fc_family_get_type ())#define PANGO_FC_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FAMILY, PangoFcFamily))#define PANGO_FC_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FAMILY))#define PANGO_FC_TYPE_FACE (pango_fc_face_get_type ())#define PANGO_FC_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FACE, PangoFcFace))#define PANGO_FC_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FACE))struct _PangoFcFontMapPrivate{ GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoFcPatternSet */ /* pattern_hash is used to make sure we only store one copy of * each identical pattern. (Speeds up lookup). */ GHashTable *pattern_hash; GHashTable *coverage_hash; /* Maps font file name/id -> PangoCoverage */ GHashTable *font_hash; /* Maps FcPattern -> PangoFcFont */ GQueue *fontset_cache; /* Recently used fontsets */ /* List of all families availible */ PangoFcFamily **families; int n_families; /* -1 == uninitialized */ double dpi; /* Decoders */ GSList *findfuncs; guint closed : 1;};struct _PangoFcCoverageKey{ char *filename; int id; /* needed to handle TTC files with multiple faces */};struct _PangoFcFace{ PangoFontFace parent_instance; PangoFcFamily *family; char *style; guint fake : 1;};struct _PangoFcFamily{ PangoFontFamily parent_instance; PangoFcFontMap *fontmap; char *family_name; PangoFcFace **faces; int n_faces; /* -1 == uninitialized */ int spacing; /* FC_SPACING */};struct _PangoFcPatternSet{ int n_patterns; FcPattern **patterns; PangoFontset *fontset; GList *cache_link; FontsetHashKey *key;};struct _PangoFcFindFuncInfo{ PangoFcDecoderFindFunc findfunc; gpointer user_data; GDestroyNotify dnotify; gpointer ddata;};static GType pango_fc_family_get_type (void);static GType pango_fc_face_get_type (void);static void pango_fc_font_map_finalize (GObject *object);static PangoFont * pango_fc_font_map_load_font (PangoFontMap *fontmap, PangoContext *context, const PangoFontDescription *description);static PangoFontset *pango_fc_font_map_load_fontset (PangoFontMap *fontmap, PangoContext *context, const PangoFontDescription *desc, PangoLanguage *language);static void pango_fc_font_map_list_families (PangoFontMap *fontmap, PangoFontFamily ***families, int *n_families);static void pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap, PangoFcPatternSet *patterns);static void pango_fc_pattern_set_free (PangoFcPatternSet *patterns);static guint pango_fc_pattern_hash (FcPattern *pattern);static gboolean pango_fc_pattern_equal (FcPattern *pattern1, FcPattern *pattern2);static guint pango_fc_coverage_key_hash (PangoFcCoverageKey *key);static gboolean pango_fc_coverage_key_equal (PangoFcCoverageKey *key1, PangoFcCoverageKey *key2);static guint font_hash_key_hash (const FontHashKey *key);static gboolean font_hash_key_equal (const FontHashKey *key_a, const FontHashKey *key_b);static void font_hash_key_free (FontHashKey *key);static guint fontset_hash_key_hash (const FontsetHashKey *key);static gboolean fontset_hash_key_equal (const FontsetHashKey *key_a, const FontsetHashKey *key_b);static void fontset_hash_key_free (FontsetHashKey *key);G_DEFINE_TYPE (PangoFcFontMap, pango_fc_font_map, PANGO_TYPE_FONT_MAP)static voidpango_fc_font_map_init (PangoFcFontMap *fcfontmap){ static gboolean registered_modules = FALSE; PangoFcFontMapPrivate *priv; priv = fcfontmap->priv = G_TYPE_INSTANCE_GET_PRIVATE (fcfontmap, PANGO_TYPE_FC_FONT_MAP, PangoFcFontMapPrivate); if (!registered_modules) { int i; registered_modules = TRUE; for (i = 0; _pango_included_fc_modules[i].list; i++) pango_module_register (&_pango_included_fc_modules[i]); } priv->n_families = -1; priv->font_hash = g_hash_table_new_full ((GHashFunc)font_hash_key_hash, (GEqualFunc)font_hash_key_equal, (GDestroyNotify)font_hash_key_free, NULL); priv->fontset_hash = g_hash_table_new_full ((GHashFunc)fontset_hash_key_hash, (GEqualFunc)fontset_hash_key_equal, (GDestroyNotify)fontset_hash_key_free, (GDestroyNotify)pango_fc_pattern_set_free); priv->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash, (GEqualFunc)pango_fc_coverage_key_equal, (GDestroyNotify)g_free, (GDestroyNotify)pango_coverage_unref); priv->fontset_cache = g_queue_new (); priv->dpi = -1;}static voidpango_fc_font_map_class_init (PangoFcFontMapClass *class){ GObjectClass *object_class = G_OBJECT_CLASS (class); PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class); object_class->finalize = pango_fc_font_map_finalize; fontmap_class->load_font = pango_fc_font_map_load_font; fontmap_class->load_fontset = pango_fc_font_map_load_fontset; fontmap_class->list_families = pango_fc_font_map_list_families; fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_FC; g_type_class_add_private (object_class, sizeof (PangoFcFontMapPrivate));}static gpointerget_gravity_class (void){ static GEnumClass *class = NULL; if (G_UNLIKELY (!class)) class = g_type_class_ref (PANGO_TYPE_GRAVITY); return class;}static guintpango_fc_pattern_hash (FcPattern *pattern){#if 1 return FcPatternHash (pattern);#else /* Hashing only part of the pattern can improve speed a bit. */ char *str; int i; double d; guint hash = 0; FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &str); if (str) hash = g_str_hash (str); if (FcPatternGetInteger (pattern, FC_INDEX, 0, &i) == FcResultMatch) hash ^= i; if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch) hash ^= (guint) (d*1000.0); return hash;#endif}static gbooleanpango_fc_pattern_equal (FcPattern *pattern1, FcPattern *pattern2){ if (pattern1 == pattern2) return TRUE; else return FcPatternEqual (pattern1, pattern2);}static guintpango_fc_coverage_key_hash (PangoFcCoverageKey *key){ return g_str_hash (key->filename) ^ key->id;}static gbooleanpango_fc_coverage_key_equal (PangoFcCoverageKey *key1, PangoFcCoverageKey *key2){ return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0;}struct _FontsetHashKey { PangoFcFontMap *fontmap; PangoMatrix matrix; PangoLanguage *language; PangoFontDescription *desc; int size; /* scaled via the current DPI */ gpointer context_key;};struct _FontHashKey { PangoFcFontMap *fontmap; PangoMatrix matrix; FcPattern *pattern; gpointer context_key;};/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) * * Not necessarily better than a lot of other hashes, but should be OK, and * well tested with binary data. */#define FNV_32_PRIME ((guint32)0x01000193)#define FNV1_32_INIT ((guint32)0x811c9dc5)static guint32hash_bytes_fnv (unsigned char *buffer, int len, guint32 hval){ while (len--) { hval *= FNV_32_PRIME; hval ^= *buffer++; } return hval;}static gbooleanfontset_hash_key_equal (const FontsetHashKey *key_a, const FontsetHashKey *key_b){ if (key_a->size == key_b->size && pango_font_description_equal (key_a->desc, key_b->desc) && key_a->language == key_b->language && key_a->matrix.xx == key_b->matrix.xx && key_a->matrix.xy == key_b->matrix.xy && key_a->matrix.yx == key_b->matrix.yx && key_a->matrix.yy == key_b->matrix.yy) { if (key_a->context_key) return PANGO_FC_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap, key_a->context_key, key_b->context_key); else return TRUE; } else return FALSE;}static guintfontset_hash_key_hash (const FontsetHashKey *key){ guint32 hash = FNV1_32_INIT; /* We do a bytewise hash on the context matrix */ hash = hash_bytes_fnv ((unsigned char *)(&key->matrix), sizeof(double) * 4, hash); if (key->context_key) hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap, key->context_key); /* 1237 is just an abitrary prime */ return (hash ^ GPOINTER_TO_UINT (key->language) ^ (key->size * 1237) ^ pango_font_description_hash (key->desc));}static voidfontset_hash_key_free (FontsetHashKey *key){ pango_font_description_free (key->desc); if (key->context_key) PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap, key->context_key); g_slice_free (FontsetHashKey, key);}static FontsetHashKey *fontset_hash_key_copy (FontsetHashKey *old){ FontsetHashKey *key = g_slice_new (FontsetHashKey); key->fontmap = old->fontmap; key->matrix = old->matrix; key->language = old->language; key->desc = pango_font_description_copy (old->desc); key->size = old->size; if (old->context_key) key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap, old->context_key); else key->context_key = NULL; return key;}static gbooleanfont_hash_key_equal (const FontHashKey *key_a, const FontHashKey *key_b){ if (key_a->matrix.xx == key_b->matrix.xx && key_a->matrix.xy == key_b->matrix.xy && key_a->matrix.yx == key_b->matrix.yx && key_a->matrix.yy == key_b->matrix.yy && key_a->pattern == key_b->pattern) { if (key_a->context_key) return PANGO_FC_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap, key_a->context_key, key_b->context_key); else return TRUE; } else return FALSE;}static guintfont_hash_key_hash (const FontHashKey *key){ guint32 hash = FNV1_32_INIT; /* We do a bytewise hash on the context matrix */ hash = hash_bytes_fnv ((unsigned char *)(&key->matrix), sizeof(double) * 4, hash); if (key->context_key) hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap, key->context_key); return (hash ^ GPOINTER_TO_UINT (key->pattern));}static voidfont_hash_key_free (FontHashKey *key){ if (key->context_key) PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap, key->context_key); g_slice_free (FontHashKey, key);}static FontHashKey *font_hash_key_copy (FontHashKey *old){ FontHashKey *key = g_slice_new (FontHashKey); key->fontmap = old->fontmap; key->matrix = old->matrix; key->pattern = old->pattern; if (old->context_key) key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap, old->context_key); else key->context_key = NULL; return key;}/** * pango_fc_font_map_add_decoder_find_func: * @fcfontmap: The #PangoFcFontMap to add this method to. * @findfunc: The #PangoFcDecoderFindFunc callback function * @user_data: User data. * @dnotify: A #GDestroyNotify callback that will be called when the * fontmap is finalized and the decoder is released. * * This function saves a callback method in the #PangoFcFontMap that * will be called whenever new fonts are created. If the * function returns a #PangoFcDecoder, that decoder will be used to * determine both coverage via a #FcCharSet and a one-to-one mapping of * characters to glyphs. This will allow applications to have * application-specific encodings for various fonts. * * Since: 1.6. **/voidpango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, PangoFcDecoderFindFunc findfunc, gpointer user_data, GDestroyNotify dnotify){ PangoFcFontMapPrivate *priv = fcfontmap->priv; PangoFcFindFuncInfo *info; info = g_slice_new (PangoFcFindFuncInfo); info->findfunc = findfunc; info->user_data = user_data; info->dnotify = dnotify; priv->findfuncs = g_slist_append (priv->findfuncs, info);}static voidpango_fc_font_map_finalize (GObject *object){ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (object); PangoFcFontMapPrivate *priv = fcfontmap->priv; pango_fc_font_map_cache_clear (fcfontmap); g_queue_free (priv->fontset_cache); g_hash_table_destroy (priv->coverage_hash); if (priv->fontset_hash) g_hash_table_destroy (priv->fontset_hash); if (priv->font_hash) g_hash_table_destroy (priv->font_hash); if (priv->pattern_hash) g_hash_table_destroy (priv->pattern_hash); while (priv->findfuncs) { PangoFcFindFuncInfo *info;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -