📄 pangofc-fontmap.c
字号:
info = priv->findfuncs->data; if (info->dnotify) info->dnotify (info->user_data); g_slice_free (PangoFcFindFuncInfo, info); priv->findfuncs = g_slist_delete_link (priv->findfuncs, priv->findfuncs); } G_OBJECT_CLASS (pango_fc_font_map_parent_class)->finalize (object);}static voidget_context_matrix (PangoContext *context, PangoMatrix *matrix){ const PangoMatrix *set_matrix; static const PangoMatrix identity = PANGO_MATRIX_INIT; if (context) set_matrix = pango_context_get_matrix (context); else set_matrix = NULL; if (set_matrix) *matrix = *set_matrix; else *matrix = identity;}static voidfont_hash_key_for_context (PangoFcFontMap *fcfontmap, PangoContext *context, FontHashKey *key){ key->fontmap = fcfontmap; get_context_matrix (context, &key->matrix); if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get) key->context_key = (gpointer)PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context); else key->context_key = NULL;}/* Add a mapping from xfont->font_pattern to xfont */static voidpango_fc_font_map_add (PangoFcFontMap *fcfontmap, PangoContext *context, PangoFcFont *fcfont){ PangoFcFontMapPrivate *priv = fcfontmap->priv; FontHashKey key; FontHashKey *key_copy; g_assert (fcfont->fontmap == NULL); fcfont->fontmap = g_object_ref (fcfontmap); font_hash_key_for_context (fcfontmap, context, &key); key.pattern = fcfont->font_pattern; key_copy = font_hash_key_copy (&key); _pango_fc_font_set_context_key (fcfont, key_copy->context_key); fcfont->matrix = key.matrix; g_hash_table_insert (priv->font_hash, key_copy, fcfont);}static PangoFcFont *pango_fc_font_map_lookup (PangoFcFontMap *fcfontmap, PangoContext *context, FcPattern *pattern){ PangoFcFontMapPrivate *priv = fcfontmap->priv; FontHashKey key; font_hash_key_for_context (fcfontmap, context, &key); key.pattern = pattern; return g_hash_table_lookup (priv->font_hash, &key);}/* Remove mapping from xfont->font_pattern to xfont */void_pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, PangoFcFont *fcfont){ PangoFcFontMapPrivate *priv = fcfontmap->priv; FontHashKey key; key.fontmap = fcfontmap; key.matrix = fcfont->matrix; key.pattern = fcfont->font_pattern; key.context_key = _pango_fc_font_get_context_key (fcfont); g_hash_table_remove (priv->font_hash, &key); fcfont->fontmap = NULL; _pango_fc_font_set_context_key (fcfont, NULL); g_object_unref (fcfontmap);}static PangoFcFamily *create_family (PangoFcFontMap *fcfontmap, const char *family_name, int spacing){ PangoFcFamily *family = g_object_new (PANGO_FC_TYPE_FAMILY, NULL); family->fontmap = fcfontmap; family->family_name = g_strdup (family_name); family->spacing = spacing; return family;}static gbooleanis_alias_family (const char *family_name){ switch (family_name[0]) { case 'm': case 'M': return (g_ascii_strcasecmp (family_name, "monospace") == 0); case 's': case 'S': return (g_ascii_strcasecmp (family_name, "sans") == 0 || g_ascii_strcasecmp (family_name, "serif") == 0); } return FALSE;}static voidpango_fc_font_map_list_families (PangoFontMap *fontmap, PangoFontFamily ***families, int *n_families){ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); PangoFcFontMapPrivate *priv = fcfontmap->priv; FcFontSet *fontset; int i; int count; if (priv->closed) { if (families) *families = NULL; if (n_families) *n_families = 0; return; } if (priv->n_families < 0) { FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SPACING, NULL); FcPattern *pat = FcPatternCreate (); /* use hash table to avoid duplicate listings if different faces in * the same family have different spacing values */ GHashTable *temp_family_hash; fontset = FcFontList (NULL, pat, os); FcPatternDestroy (pat); FcObjectSetDestroy (os); priv->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */ temp_family_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); count = 0; for (i = 0; i < fontset->nfont; i++) { FcChar8 *s; FcResult res; int spacing; res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &s); g_assert (res == FcResultMatch); res = FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &spacing); g_assert (res == FcResultMatch || res == FcResultNoMatch); if (res == FcResultNoMatch) spacing = FC_PROPORTIONAL; if (!is_alias_family (s) && !g_hash_table_lookup (temp_family_hash, s)) { PangoFcFamily *temp_family = create_family (fcfontmap, (gchar *)s, spacing); g_hash_table_insert (temp_family_hash, g_strdup (s), s); priv->families[count++] = temp_family; } } FcFontSetDestroy (fontset); g_hash_table_destroy (temp_family_hash); priv->families[count++] = create_family (fcfontmap, "Sans", FC_PROPORTIONAL); priv->families[count++] = create_family (fcfontmap, "Serif", FC_PROPORTIONAL); priv->families[count++] = create_family (fcfontmap, "Monospace", FC_MONO); priv->n_families = count; } if (n_families) *n_families = priv->n_families; if (families) *families = g_memdup (priv->families, priv->n_families * sizeof (PangoFontFamily *));}static intpango_fc_convert_weight_to_fc (PangoWeight pango_weight){#ifdef FC_WEIGHT_ULTRABOLD /* fontconfig 2.1 only had light/medium/demibold/bold/black */ if (pango_weight < (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2) return FC_WEIGHT_ULTRALIGHT; else if (pango_weight < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2) return FC_WEIGHT_LIGHT; else if (pango_weight < (PANGO_WEIGHT_NORMAL + 500 /* PANGO_WEIGHT_MEDIUM */) / 2) return FC_WEIGHT_NORMAL; else if (pango_weight < (500 /* PANGO_WEIGHT_MEDIUM */ + PANGO_WEIGHT_SEMIBOLD) / 2) return FC_WEIGHT_MEDIUM; else if (pango_weight < (PANGO_WEIGHT_SEMIBOLD + PANGO_WEIGHT_BOLD) / 2) return FC_WEIGHT_DEMIBOLD; else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2) return FC_WEIGHT_BOLD; else if (pango_weight < (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY) / 2) return FC_WEIGHT_ULTRABOLD; else return FC_WEIGHT_BLACK;#else /* fontconfig < 2.2 */ if (pango_weight < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2) return FC_WEIGHT_LIGHT; else if (pango_weight < (500 /* PANGO_WEIGHT_MEDIUM */ + PANGO_WEIGHT_SEMIBOLD) / 2) return FC_WEIGHT_MEDIUM; else if (pango_weight < (PANGO_WEIGHT_SEMIBOLD + PANGO_WEIGHT_BOLD) / 2) return FC_WEIGHT_DEMIBOLD; else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2) return FC_WEIGHT_BOLD; else return FC_WEIGHT_BLACK;#endif}static intpango_fc_convert_slant_to_fc (PangoStyle pango_style){ switch (pango_style) { case PANGO_STYLE_NORMAL: return FC_SLANT_ROMAN; case PANGO_STYLE_ITALIC: return FC_SLANT_ITALIC; case PANGO_STYLE_OBLIQUE: return FC_SLANT_OBLIQUE; default: return FC_SLANT_ROMAN; }}#ifdef FC_WIDTHstatic intpango_fc_convert_width_to_fc (PangoStretch pango_stretch){ switch (pango_stretch) { case PANGO_STRETCH_NORMAL: return FC_WIDTH_NORMAL; case PANGO_STRETCH_ULTRA_CONDENSED: return FC_WIDTH_ULTRACONDENSED; case PANGO_STRETCH_EXTRA_CONDENSED: return FC_WIDTH_EXTRACONDENSED; case PANGO_STRETCH_CONDENSED: return FC_WIDTH_CONDENSED; case PANGO_STRETCH_SEMI_CONDENSED: return FC_WIDTH_SEMICONDENSED; case PANGO_STRETCH_SEMI_EXPANDED: return FC_WIDTH_SEMIEXPANDED; case PANGO_STRETCH_EXPANDED: return FC_WIDTH_EXPANDED; case PANGO_STRETCH_EXTRA_EXPANDED: return FC_WIDTH_EXTRAEXPANDED; case PANGO_STRETCH_ULTRA_EXPANDED: return FC_WIDTH_ULTRAEXPANDED; default: return FC_WIDTH_NORMAL; }}#endifstatic FcPattern *pango_fc_make_pattern (const PangoFontDescription *description, PangoLanguage *language, double pixel_size, double dpi){ FcPattern *pattern; int slant; int weight; PangoGravity gravity; FcBool vertical; char **families; int i;#ifdef FC_WIDTH int width;#endif slant = pango_fc_convert_slant_to_fc (pango_font_description_get_style (description)); weight = pango_fc_convert_weight_to_fc (pango_font_description_get_weight (description));#ifdef FC_WIDTH width = pango_fc_convert_width_to_fc (pango_font_description_get_stretch (description));#endif gravity = pango_font_description_get_gravity (description); vertical = PANGO_GRAVITY_IS_VERTICAL (gravity) ? FcTrue : FcFalse; /* The reason for passing in FC_SIZE as well as FC_PIXEL_SIZE is * to work around a bug in libgnomeprint where it doesn't look * for FC_PIXEL_SIZE. See http://bugzilla.gnome.org/show_bug.cgi?id=169020 * * Putting FC_SIZE in here slightly reduces the efficiency * of caching of patterns and fonts when working with multiple different * dpi values. */ pattern = FcPatternBuild (NULL, FC_WEIGHT, FcTypeInteger, weight, FC_SLANT, FcTypeInteger, slant,#ifdef FC_WIDTH FC_WIDTH, FcTypeInteger, width,#endif#ifdef FC_VERTICAL_LAYOUT FC_VERTICAL_LAYOUT, FcTypeBool, vertical,#endif FC_SIZE, FcTypeDouble, pixel_size * (72. / dpi), FC_PIXEL_SIZE, FcTypeDouble, pixel_size, NULL); families = g_strsplit (pango_font_description_get_family (description), ",", -1); for (i = 0; families[i]; i++) FcPatternAddString (pattern, FC_FAMILY, families[i]); g_strfreev (families); if (language) FcPatternAddString (pattern, FC_LANG, (FcChar8 *) pango_language_to_string (language)); if (gravity != PANGO_GRAVITY_SOUTH) { GEnumValue *value = g_enum_get_value (get_gravity_class (), gravity); FcPatternAddString (pattern, PANGO_FC_GRAVITY, value->value_nick); } return pattern;}static PangoFont *pango_fc_font_map_new_font (PangoFontMap *fontmap, PangoContext *context, const PangoFontDescription *description, FcPattern *match){ PangoFcFontMapClass *class; PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap; PangoFcFontMapPrivate *priv = fcfontmap->priv; FcPattern *pattern; PangoFcFont *fcfont; GSList *l; if (priv->closed) return NULL; fcfont = pango_fc_font_map_lookup (fcfontmap, context, match); if (fcfont) return g_object_ref (fcfont); class = PANGO_FC_FONT_MAP_GET_CLASS (fontmap); if (class->create_font) { fcfont = PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->create_font (fcfontmap, context, description, match); } else { const PangoMatrix *pango_matrix; if (context) pango_matrix = pango_context_get_matrix (context); else pango_matrix = NULL; if (pango_matrix) { FcMatrix fc_matrix; /* Fontconfig has the Y axis pointing up, Pango, down. */ fc_matrix.xx = pango_matrix->xx; fc_matrix.xy = - pango_matrix->xy; fc_matrix.yx = - pango_matrix->yx; fc_matrix.yy = pango_matrix->yy; pattern = FcPatternDuplicate (match); FcPatternAddMatrix (pattern, FC_MATRIX, &fc_matrix); } else pattern = match; fcfont = PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->new_font (fcfontmap, pattern); if (pango_matrix) FcPatternDestroy (pattern); } if (!fcfont) return NULL; pango_fc_font_map_add (fcfontmap, context, fcfont); /* * Give any custom decoders a crack at this font now that it's been * created. */ for (l = priv->findfuncs; l && l->data; l = l->next) { PangoFcFindFuncInfo *info = l->data; PangoFcDecoder *decoder; decoder = info->findfunc (match, info->user_data); if (decoder) { _pango_fc_font_set_decoder (fcfont, decoder); break; } } return (PangoFont *)fcfont;}static FcPattern *uniquify_pattern (PangoFcFontMap *fcfontmap, FcPattern *pattern){ PangoFcFontMapPrivate *priv = fcfontmap->priv; FcPattern *old_pattern; if (!priv->pattern_hash) priv->pattern_hash = g_hash_table_new_full ((GHashFunc)pango_fc_pattern_hash, (GEqualFunc)pango_fc_pattern_equal, (GDestroyNotify)FcPatternDestroy, NULL); old_pattern = g_hash_table_lookup (priv->pattern_hash, pattern); if (old_pattern) { FcPatternDestroy (pattern); FcPatternReference (old_pattern); return old_pattern; } else { FcPatternReference (pattern); g_hash_table_insert (priv->pattern_hash, pattern, pattern); return pattern; }}static voidpango_fc_default_substitute (PangoFcFontMap *fontmap, PangoContext *context, FcPattern *pattern){ if (PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->context_substitute) PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->context_substitute (fontmap, context, pattern); else if (PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute) PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute (fontmap, pattern);}static gdoublepango_fc_font_map_get_resolution (PangoFcFontMap *fcfontmap, PangoContext *context){ if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution) return PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution (fcfontmap, context); if (fcfontmap->priv->dpi < 0) { FcResult result = FcResultNoMatch; FcPattern *tmp = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "Sans", FC_SIZE, FcTypeDouble, 10., NULL); if (tmp) { pango_fc_default_substitute (fcfontmap, NULL, tmp); result = FcPatternGetDouble (tmp, FC_DPI, 0, &fcfontmap->priv->dpi); FcPatternDestroy (tmp); } if (result != FcResultMatch) { g_warning ("Error getting DPI from fontconfig, using 72.0"); fcfontmap->priv->dpi = 72.0; } } return fcfontmap->priv->dpi;}static intget_unscaled_size (PangoFcFontMap *fcfontmap, PangoContext *context,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -