summaryrefslogtreecommitdiff
path: root/pango/pangofc-fontmap.cI
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2003-08-03 02:35:20 +0000
committerOwen Taylor <otaylor@src.gnome.org>2003-08-03 02:35:20 +0000
commit94f39b93e929db7881070f4b5e1f5dc3c106e3fb (patch)
tree1fa92651d4e9d2c7c41d413468f37bdb8095cd52 /pango/pangofc-fontmap.cI
parente2ea77ce2f99c122a0087c28fcd9316be4d6e205 (diff)
downloadpango-94f39b93e929db7881070f4b5e1f5dc3c106e3fb.tar.gz
Make pangoxft depend on pangoft2.
Sat Aug 2 14:33:28 2003 Owen Taylor <otaylor@redhat.com> * pango/Makefile.am (libpangoxft_1_0_la_LIBADD): Make pangoxft depend on pangoft2. * pango/pangofc-fontmap.[ch]: Make pangofc-fontmap.cI into a real base class. * pango/pangofc-font.[ch]: Move some of the pangoxft/ pangoft2 implementation here. * pango/pangoft2.c pango/pangoft2-fontmap.c pango/pangoft2-private.h pango/pangoxft-font.c pango/pangoxft2-fontmap.c pango/pangoxft-private.h: Adapt to the new scheme * modules/*/Makefile.am Modules/*/*/*-fc.c: Don't build separate FT2 and Xft shapers, just build one Fc shaper. * docs/pango-sections.txt docs/pango-docs.sgml docs/tmpl/pangofc-font{,map}.sgml: Basic docs for the new stuff. * configure.in: Up pango_module_version to 1.4.0.
Diffstat (limited to 'pango/pangofc-fontmap.cI')
-rw-r--r--pango/pangofc-fontmap.cI1138
1 files changed, 0 insertions, 1138 deletions
diff --git a/pango/pangofc-fontmap.cI b/pango/pangofc-fontmap.cI
deleted file mode 100644
index 28d5fa20..00000000
--- a/pango/pangofc-fontmap.cI
+++ /dev/null
@@ -1,1138 +0,0 @@
-/* Pango
- * pangofc-fontmap.cI: Common font handling between Xft and FT2
- *
- * Copyright (C) 2000,2001,2002 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.
- */
-
-/*
- * This file is included by both pangoxft-fontmap.c and pangoft2-fontmap.c
- * after making appropriate #defines for public symbols.
- */
-
-/* Size of fontset cache */
-#define FONTSET_CACHE_SIZE 16
-
-typedef struct _PangoFcCoverageKey PangoFcCoverageKey;
-typedef struct _PangoFcFace PangoFcFace;
-typedef struct _PangoFcPatternSet PangoFcPatternSet;
-
-#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 _PangoFcCoverageKey
-{
- char *filename;
- int id; /* needed to handle TTC files with multiple faces */
-};
-
-struct _PangoFcFace
-{
- PangoFontFace parent_instance;
-
- PangoFcFamily *family;
- char *style;
-};
-
-struct _PangoFcFamily
-{
- PangoFontFamily parent_instance;
-
- PangoFcFontMap *fontmap;
- char *family_name;
-
- PangoFcFace **faces;
- int n_faces; /* -1 == uninitialized */
-};
-
-struct _PangoFcPatternSet
-{
- int n_patterns;
- FcPattern **patterns;
- PangoFontset *fontset;
- GList *cache_link;
-};
-
-GType pango_fc_font_map_get_type (void);
-static GType pango_fc_family_get_type (void);
-static GType pango_fc_face_get_type (void);
-
-static void pango_fc_font_map_init (PangoFcFontMap *fontmap);
-static void pango_fc_font_map_class_init (PangoFontMapClass *class);
-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_pattern_set_free (PangoFcPatternSet *patterns);
-
-static void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap);
-static void pango_fc_default_substitute (PangoFcFontMap *fontmap,
- FcPattern *pattern);
-static void pango_fc_do_finalize (PangoFcFontMap *fontmap);
-
-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 PangoFontClass *parent_class; /* Parent class structure for PangoFcFontMap */
-
-GType
-pango_fc_font_map_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontMapClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_fc_font_map_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFcFontMap),
- 0, /* n_preallocs */
- (GInstanceInitFunc) pango_fc_font_map_init,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
- PANGO_FC_NAME "FontMap",
- &object_info, 0);
- }
-
- return object_type;
-}
-
-static void
-pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
-{
- fcfontmap->n_families = -1;
-
- fcfontmap->fonts = g_hash_table_new ((GHashFunc)g_direct_hash, NULL);
- fcfontmap->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);
- fcfontmap->fontset_cache = g_queue_new ();
-}
-static void
-pango_fc_font_map_class_init (PangoFontMapClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- parent_class = g_type_class_peek_parent (class);
-
- object_class->finalize = pango_fc_font_map_finalize;
- class->load_font = pango_fc_font_map_load_font;
- class->load_fontset = pango_fc_font_map_load_fontset;
- class->list_families = pango_fc_font_map_list_families;
-}
-
-static GSList *fontmaps = NULL;
-
-static guint
-pango_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 gboolean
-pango_fc_pattern_equal (FcPattern *pattern1,
- FcPattern *pattern2)
-{
- if (pattern1 == pattern2)
- return TRUE;
- else
- return FcPatternEqual (pattern1, pattern2);
-}
-
-static guint
-pango_fc_coverage_key_hash (PangoFcCoverageKey *key)
-{
- return g_str_hash (key->filename) ^ key->id;
-}
-
-static gboolean
-pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
- PangoFcCoverageKey *key2)
-{
- return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0;
-}
-
-typedef struct _FontsetHashListNode FontsetHashListNode;
-
-struct _FontsetHashListNode {
- GHashTable *fontset_hash;
- PangoLanguage *language;
-};
-
-/* Get the description => fontset map for a particular
- * language tag.
- */
-static GHashTable *
-pango_fc_get_fontset_hash (PangoFcFontMap *fcfontmap,
- PangoLanguage *language)
-{
- /* We treat NULL as a distinct language tag, but
- * we should actually determine the real language
- * tag it corresponds to to avoid duplicate entries
- * in the list.
- */
- GList *tmp_list = fcfontmap->fontset_hash_list;
- while (tmp_list)
- {
- FontsetHashListNode *node = tmp_list->data;
- if (node->language == language)
- {
- if (tmp_list != fcfontmap->fontset_hash_list)
- {
- /* Put the found node at the beginning
- */
- fcfontmap->fontset_hash_list = g_list_remove_link (fcfontmap->fontset_hash_list, tmp_list);
- fcfontmap->fontset_hash_list->prev = tmp_list;
- tmp_list->next = fcfontmap->fontset_hash_list;
- fcfontmap->fontset_hash_list = tmp_list;
- }
-
- return node->fontset_hash;
- }
-
- tmp_list = tmp_list->next;
- }
-
- {
- FontsetHashListNode *node = g_new (FontsetHashListNode, 1);
- fcfontmap->fontset_hash_list = g_list_prepend (fcfontmap->fontset_hash_list, node);
-
- node->fontset_hash =
- g_hash_table_new_full ((GHashFunc)pango_font_description_hash,
- (GEqualFunc)pango_font_description_equal,
- (GDestroyNotify)pango_font_description_free,
- (GDestroyNotify)pango_fc_pattern_set_free);
- node->language = language;
-
- return node->fontset_hash;
- }
-}
-
-static void
-pango_fc_clear_pattern_hashes (PangoFcFontMap *fcfontmap)
-{
- GList *tmp_list;
-
- tmp_list = fcfontmap->fontset_hash_list;
- while (tmp_list)
- {
- FontsetHashListNode *node = tmp_list->data;
-
- g_hash_table_destroy (node->fontset_hash);
- g_free (node);
-
- tmp_list = tmp_list->next;
- }
-
- g_list_free (fcfontmap->fontset_hash_list);
- fcfontmap->fontset_hash_list = NULL;
-}
-
-static void
-pango_fc_font_map_finalize (GObject *object)
-{
- PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (object);
-
- fontmaps = g_slist_remove (fontmaps, object);
-
- if (fcfontmap->substitute_destroy)
- fcfontmap->substitute_destroy (fcfontmap->substitute_data);
-
- pango_fc_font_map_cache_clear (fcfontmap);
- g_queue_free (fcfontmap->fontset_cache);
- g_hash_table_destroy (fcfontmap->coverage_hash);
-
- if (fcfontmap->fonts)
- g_hash_table_destroy (fcfontmap->fonts);
-
- if (fcfontmap->pattern_hash)
- g_hash_table_destroy (fcfontmap->pattern_hash);
-
- pango_fc_do_finalize (fcfontmap);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-
-/* Add a mapping from xfont->font_pattern to xfont */
-void
-_pango_fc_font_map_add (PangoFontMap *fontmap,
- PangoFcFont *xfont)
-{
- PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
-
- g_hash_table_insert (fcfontmap->fonts,
- xfont->font_pattern,
- xfont);
-}
-
-/* Remove mapping from xfont->font_pattern to xfont */
-void
-_pango_fc_font_map_remove (PangoFontMap *fontmap,
- PangoFcFont *xfont)
-{
- PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
-
- g_hash_table_remove (fcfontmap->fonts,
- xfont->font_pattern);
-}
-
-static PangoFcFamily *
-create_family (PangoFcFontMap *fcfontmap,
- const char *family_name)
-{
- PangoFcFamily *family = g_object_new (PANGO_FC_TYPE_FAMILY, NULL);
- family->fontmap = fcfontmap;
- family->family_name = g_strdup (family_name);
-
- return family;
-}
-
-static gboolean
-is_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 void
-pango_fc_font_map_list_families (PangoFontMap *fontmap,
- PangoFontFamily ***families,
- int *n_families)
-{
- PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
- FcFontSet *fontset;
- int i;
- int count;
-
- if (fcfontmap->closed)
- {
- if (families)
- *families = NULL;
- if (n_families)
- n_families = 0;
-
- return;
- }
-
- if (fcfontmap->n_families < 0)
- {
- FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL);
- FcPattern *pat = FcPatternCreate ();
-
- fontset = FcFontList (NULL, pat, os);
-
- FcPatternDestroy (pat);
- FcObjectSetDestroy (os);
-
- fcfontmap->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */
-
- count = 0;
- for (i = 0; i < fontset->nfont; i++)
- {
- char *s;
- FcResult res;
-
- res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &s);
- g_assert (res == FcResultMatch);
-
- if (!is_alias_family (s))
- fcfontmap->families[count++] = create_family (fcfontmap, s);
- }
-
- FcFontSetDestroy (fontset);
-
- fcfontmap->families[count++] = create_family (fcfontmap, "Sans");
- fcfontmap->families[count++] = create_family (fcfontmap, "Serif");
- fcfontmap->families[count++] = create_family (fcfontmap, "Monospace");
-
- fcfontmap->n_families = count;
- }
-
- if (n_families)
- *n_families = fcfontmap->n_families;
-
- if (families)
- *families = g_memdup (fcfontmap->families, fcfontmap->n_families * sizeof (PangoFontFamily *));
-}
-
-static int
-pango_fc_convert_weight (PangoWeight pango_weight)
-{
- int weight;
-
- if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
- weight = FC_WEIGHT_LIGHT;
- else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2)
- weight = FC_WEIGHT_MEDIUM;
- else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2)
- weight = FC_WEIGHT_DEMIBOLD;
- else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
- weight = FC_WEIGHT_BOLD;
- else
- weight = FC_WEIGHT_BLACK;
-
- return weight;
-}
-
-static int
-pango_fc_convert_slant (PangoStyle pango_style)
-{
- int slant;
-
- if (pango_style == PANGO_STYLE_ITALIC)
- slant = FC_SLANT_ITALIC;
- else if (pango_style == PANGO_STYLE_OBLIQUE)
- slant = FC_SLANT_OBLIQUE;
- else
- slant = FC_SLANT_ROMAN;
-
- return slant;
-}
-
-
-static FcPattern *
-pango_fc_make_pattern (const PangoFontDescription *description)
-{
- FcPattern *pattern;
- PangoStyle pango_style;
- int slant;
- int weight;
- char **families;
- int i;
-
- pango_style = pango_font_description_get_style (description);
-
- slant = pango_fc_convert_slant (pango_style);
- weight = pango_fc_convert_weight (pango_font_description_get_weight (description));
-
- pattern = FcPatternBuild (0,
- FC_WEIGHT, FcTypeInteger, weight,
- FC_SLANT, FcTypeInteger, slant,
- FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
- 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);
-
- return pattern;
-}
-
-static PangoFont *
-pango_fc_font_map_new_font (PangoFontMap *fontmap,
- FcPattern *match)
-{
- PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
- PangoFcFont *font;
-
- /* Returning NULL here actually violates a contract
- * that loading load_font() will never return NULL.
- * We probably should actually create a dummy
- * font that doesn't draw anything and has empty
- * metrics.
- */
- if (fcfontmap->closed)
- return NULL;
-
- /* Look up cache */
- font = g_hash_table_lookup (fcfontmap->fonts, match);
-
- if (font)
- return g_object_ref (font);
-
- FcPatternReference (match);
- return (PangoFont *)_pango_fc_font_new (fontmap, match);
-}
-
-static FcPattern *
-uniquify_pattern (PangoFcFontMap *fcfontmap,
- FcPattern *pattern)
-{
- FcPattern *old_pattern;
-
- if (!fcfontmap->pattern_hash)
- fcfontmap->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 (fcfontmap->pattern_hash, pattern);
- if (old_pattern)
- {
- FcPatternDestroy (pattern);
- FcPatternReference (old_pattern);
- return old_pattern;
- }
- else
- {
- FcPatternReference (pattern);
- g_hash_table_insert (fcfontmap->pattern_hash, pattern, pattern);
- return pattern;
- }
-}
-
-static PangoFcPatternSet *
-pango_fc_font_map_get_patterns (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language)
-{
- PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
- FcPattern *pattern, *font_pattern;
- FcResult res;
- int f;
- PangoFcPatternSet *patterns;
- FcFontSet *font_patterns;
- GHashTable *fontset_hash;
-
- if (!language && context)
- language = pango_context_get_language (context);
-
- fontset_hash = pango_fc_get_fontset_hash (fcfontmap, language);
- patterns = g_hash_table_lookup (fontset_hash, desc);
-
- if (patterns == NULL)
- {
- pattern = pango_fc_make_pattern (desc);
- if (language)
- FcPatternAddString (pattern, FC_LANG, (FcChar8 *) pango_language_to_string (language));
-
- pango_fc_default_substitute (fcfontmap, pattern);
-
- font_patterns = FcFontSort (NULL, pattern, FcTrue, 0, &res);
-
- if (!font_patterns)
- {
- g_printerr ("No fonts found; this probably means that the fontconfig\n"
- "library is not correctly configured. You may need to\n"
- "edit the fonts.conf configuration file. More information\n"
- "about fontconfig can be found in the fontconfig(3) manual\n"
- "page and on http://fontconfig.org\n");
-
- /* There is no point in proceeding; we'll just get a segfault later
- * on, and a bunch more possibly confusing error messages in between.
- */
-
- /* return NULL; */
- exit (1);
- }
-
- patterns = g_new (PangoFcPatternSet, 1);
- patterns->patterns = g_new (FcPattern *, font_patterns->nfont);
- patterns->n_patterns = 0;
- patterns->fontset = NULL;
- patterns->cache_link = NULL;
-
- for (f = 0; f < font_patterns->nfont; f++)
- {
- font_pattern = FcFontRenderPrepare (NULL, pattern,
- font_patterns->fonts[f]);
-#ifdef FC_PATTERN
- /* The FC_PATTERN element, which points back to our the original patterm
- * defeats our hash tables.
- */
- FcPatternDel (font_pattern, FC_PATTERN);
-#endif /* FC_PATTERN */
-
- if (font_pattern)
- patterns->patterns[patterns->n_patterns++] = uniquify_pattern (fcfontmap, font_pattern);
- }
-
- FcPatternDestroy (pattern);
-
- FcFontSetSortDestroy (font_patterns);
-
- g_hash_table_insert (fontset_hash,
- pango_font_description_copy (desc),
- patterns);
- }
-
- return patterns;
-}
-
-static PangoFont *
-pango_fc_font_map_load_font (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *description)
-{
- PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, description, NULL);
- if (!patterns)
- return NULL;
-
- if (patterns->n_patterns > 0)
- return pango_fc_font_map_new_font (fontmap, patterns->patterns[0]);
-
- return NULL;
-}
-
-static void
-pango_fc_pattern_set_free (PangoFcPatternSet *patterns)
-{
- int i;
-
- if (patterns->fontset)
- g_object_remove_weak_pointer (G_OBJECT (patterns->fontset),
- (gpointer *)&patterns->fontset);
-
- for (i = 0; i < patterns->n_patterns; i++)
- FcPatternDestroy (patterns->patterns[i]);
-
- g_free (patterns->patterns);
- g_free (patterns);
-}
-
-static void
-pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap,
- PangoFcPatternSet *patterns)
-{
- GQueue *cache = fcfontmap->fontset_cache;
-
- if (patterns->cache_link)
- {
- /* Already in cache, move to head
- */
- if (patterns->cache_link == cache->tail)
- cache->tail = patterns->cache_link->prev;
-
- cache->head = g_list_remove_link (cache->head, patterns->cache_link);
- cache->length--;
- }
- else
- {
- /* Add to cache initially
- */
- if (cache->length == FONTSET_CACHE_SIZE)
- {
- PangoFcPatternSet *tmp_patterns = g_queue_pop_tail (cache);
- tmp_patterns->cache_link = NULL;
- g_object_unref (tmp_patterns->fontset);
- }
-
- g_object_ref (patterns->fontset);
- patterns->cache_link = g_list_prepend (NULL, patterns);
- }
-
- g_queue_push_head_link (cache, patterns->cache_link);
-}
-
-static PangoFontset *
-pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language)
-{
- int i;
- PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language);
- PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
- if (!patterns)
- return NULL;
-
- if (!patterns->fontset)
- {
- PangoFontsetSimple *simple;
- simple = pango_fontset_simple_new (language);
-
- for (i = 0; i < patterns->n_patterns; i++)
- {
- PangoFont *font = pango_fc_font_map_new_font (fontmap, patterns->patterns[i]);
- if (font)
- pango_fontset_simple_append (simple, font);
- }
-
- patterns->fontset = PANGO_FONTSET (simple);
- g_object_add_weak_pointer (G_OBJECT (patterns->fontset),
- (gpointer *)&patterns->fontset);
- }
- else
- g_object_ref (patterns->fontset);
-
- if (!patterns->cache_link ||
- patterns->cache_link != fcfontmap->fontset_cache->head)
- pango_fc_font_map_cache_fontset (fcfontmap, patterns);
-
- return patterns->fontset;
-}
-
-static void
-uncache_patterns (PangoFcPatternSet *patterns)
-{
- g_object_unref (patterns->fontset);
-}
-
-static void
-pango_fc_font_map_clear_fontset_cache (PangoFcFontMap *fcfontmap)
-{
- GQueue *cache = fcfontmap->fontset_cache;
-
- g_list_foreach (cache->head, (GFunc)uncache_patterns, NULL);
- g_list_free (cache->head);
- cache->head = NULL;
- cache->tail = NULL;
- cache->length = 0;
-}
-
-static void
-pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap)
-{
- /* Clear the fontset cache first, since any entries
- * in the fontset_cache must also be in the pattern cache.
- */
- pango_fc_font_map_clear_fontset_cache (fcfontmap);
- pango_fc_clear_pattern_hashes (fcfontmap);
-}
-
-static void
-pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap,
- PangoFcCoverageKey *key,
- PangoCoverage *coverage)
-{
- PangoFcCoverageKey *key_dup;
-
- key_dup = g_malloc (sizeof (PangoFcCoverageKey) + strlen (key->filename) + 1);
- key_dup->id = key->id;
- key_dup->filename = (char *) (key_dup + 1);
- strcpy (key_dup->filename, key->filename);
-
- g_hash_table_insert (fcfontmap->coverage_hash,
- key_dup, pango_coverage_ref (coverage));
-}
-
-PangoCoverage *
-_pango_fc_font_map_get_coverage (PangoFontMap *fontmap,
- FcPattern *pattern)
-{
- PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
- PangoFcCoverageKey key;
- PangoCoverage *coverage;
- FcChar32 map[FC_CHARSET_MAP_SIZE];
- FcChar32 ucs4, pos;
- FcCharSet *charset;
- int i;
-
- /*
- * Assume that coverage information is identified by
- * a filename/index pair; there shouldn't be any reason
- * this isn't true, but it's not specified anywhere
- */
- if (FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &key.filename) != FcResultMatch)
- return NULL;
-
- if (FcPatternGetInteger (pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
- return NULL;
-
- coverage = g_hash_table_lookup (fcfontmap->coverage_hash, &key);
- if (coverage)
- return pango_coverage_ref (coverage);
-
- /*
- * Pull the coverage out of the pattern, this
- * doesn't require loading the font
- */
- if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
- return NULL;
-
- /*
- * Convert an Fc CharSet into a pango coverage structure. Sure
- * would be nice to just use the Fc structure in place...
- */
- coverage = pango_coverage_new ();
- for (ucs4 = FcCharSetFirstPage (charset, map, &pos);
- ucs4 != FC_CHARSET_DONE;
- ucs4 = FcCharSetNextPage (charset, map, &pos))
- {
- for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
- {
- FcChar32 bits = map[i];
- FcChar32 base = ucs4 + i * 32;
- int b = 0;
- bits = map[i];
- while (bits)
- {
- if (bits & 1)
- pango_coverage_set (coverage, base + b, PANGO_COVERAGE_EXACT);
-
- bits >>= 1;
- b++;
- }
- }
- }
-
- /* Awful hack so Hangul Tone marks get rendered with the same
- * font and in the same run as other Hangul characters. If a font
- * covers the first composed Hangul glyph, then it is declared to cover
- * the Hangul tone marks. This hack probably needs to be formalized
- * by choosing fonts for scripts rather than individual code points.
- */
- if (pango_coverage_get (coverage, 0xac00) == PANGO_COVERAGE_EXACT)
- {
- pango_coverage_set (coverage, 0x302e, PANGO_COVERAGE_EXACT);
- pango_coverage_set (coverage, 0x302f, PANGO_COVERAGE_EXACT);
- }
-
- pango_fc_font_map_set_coverage (fcfontmap, &key, coverage);
-
- return coverage;
-}
-
-/*
- * PangoFcFace
- */
-
-PangoFontDescription *
-_pango_fc_font_desc_from_pattern (FcPattern *pattern, gboolean include_size)
-{
- PangoFontDescription *desc;
- PangoStyle style;
- PangoWeight weight;
- double size;
-
- char *s;
- int i;
-
- desc = pango_font_description_new ();
-
- g_assert (FcPatternGetString (pattern, FC_FAMILY, 0, (FcChar8 **) &s) == FcResultMatch);
-
- pango_font_description_set_family (desc, s);
-
- if (FcPatternGetInteger (pattern, FC_SLANT, 0, &i) == FcResultMatch)
- {
- if (i == FC_SLANT_ROMAN)
- style = PANGO_STYLE_NORMAL;
- else if (i == FC_SLANT_OBLIQUE)
- style = PANGO_STYLE_OBLIQUE;
- else
- style = PANGO_STYLE_ITALIC;
- }
- else
- style = PANGO_STYLE_NORMAL;
-
- pango_font_description_set_style (desc, style);
-
- if (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &i) == FcResultMatch)
- {
- if (i < FC_WEIGHT_LIGHT)
- weight = PANGO_WEIGHT_ULTRALIGHT;
- else if (i < (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
- weight = PANGO_WEIGHT_LIGHT;
- else if (i < (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
- weight = PANGO_WEIGHT_NORMAL;
- else if (i < (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
- weight = 600;
- else if (i < (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
- weight = PANGO_WEIGHT_BOLD;
- else
- weight = PANGO_WEIGHT_ULTRABOLD;
- }
- else
- weight = PANGO_WEIGHT_NORMAL;
-
- if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
- pango_font_description_set_size (desc, size * PANGO_SCALE);
-
- pango_font_description_set_weight (desc, weight);
-
- pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
- pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
-
- return desc;
-}
-
-static PangoFontDescription *
-make_alias_description (PangoFcFamily *fcfamily,
- gboolean bold,
- gboolean italic)
-{
- PangoFontDescription *desc = pango_font_description_new ();
-
- pango_font_description_set_family (desc, fcfamily->family_name);
- pango_font_description_set_style (desc, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
- pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
- pango_font_description_set_weight (desc, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
- pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
-
- return desc;
-}
-
-static PangoFontDescription *
-pango_fc_face_describe (PangoFontFace *face)
-{
- PangoFcFace *fcface = PANGO_FC_FACE (face);
- PangoFcFamily *fcfamily = fcface->family;
- PangoFontDescription *desc = NULL;
- FcResult res;
- FcPattern *match_pattern;
- FcPattern *result_pattern;
-
- if (is_alias_family (fcfamily->family_name))
- {
- if (strcmp (fcface->style, "Regular") == 0)
- return make_alias_description (fcfamily, FALSE, FALSE);
- else if (strcmp (fcface->style, "Bold") == 0)
- return make_alias_description (fcfamily, TRUE, FALSE);
- else if (strcmp (fcface->style, "Italic") == 0)
- return make_alias_description (fcfamily, FALSE, TRUE);
- else /* Bold Italic */
- return make_alias_description (fcfamily, TRUE, TRUE);
- }
-
- match_pattern = FcPatternBuild (NULL,
- FC_FAMILY, FcTypeString, fcfamily->family_name,
- FC_STYLE, FcTypeString, fcface->style,
- NULL);
-
- g_assert (match_pattern);
-
- result_pattern = FcFontMatch (NULL, match_pattern, &res);
- if (result_pattern)
- {
- desc = _pango_fc_font_desc_from_pattern (result_pattern, FALSE);
- FcPatternDestroy (result_pattern);
- }
-
- FcPatternDestroy (match_pattern);
-
- return desc;
-}
-
-static const char *
-pango_fc_face_get_face_name (PangoFontFace *face)
-{
- PangoFcFace *fcface = PANGO_FC_FACE (face);
-
- return fcface->style;
-}
-
-static void
-pango_fc_face_class_init (PangoFontFaceClass *class)
-{
- class->describe = pango_fc_face_describe;
- class->get_face_name = pango_fc_face_get_face_name;
-}
-
-static GType
-pango_fc_face_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontFaceClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_fc_face_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFcFace),
- 0, /* n_preallocs */
- (GInstanceInitFunc) NULL,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
- PANGO_FC_NAME "Face",
- &object_info, 0);
- }
-
- return object_type;
-}
-
-/*
- * PangoFcFamily
- */
-static PangoFcFace *
-create_face (PangoFcFamily *fcfamily,
- const char *style)
-{
- PangoFcFace *face = g_object_new (PANGO_FC_TYPE_FACE, NULL);
- face->style = g_strdup (style);
- face->family = fcfamily;
-
- return face;
-}
-
-static void
-pango_fc_family_list_faces (PangoFontFamily *family,
- PangoFontFace ***faces,
- int *n_faces)
-{
- PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
- PangoFcFontMap *fcfontmap = fcfamily->fontmap;
-
- if (fcfamily->n_faces < 0)
- {
- FcFontSet *fontset;
- int i;
-
- if (is_alias_family (fcfamily->family_name) || fcfontmap->closed)
- {
- fcfamily->n_faces = 4;
- fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
-
- i = 0;
- fcfamily->faces[i++] = create_face (fcfamily, "Regular");
- fcfamily->faces[i++] = create_face (fcfamily, "Bold");
- fcfamily->faces[i++] = create_face (fcfamily, "Italic");
- fcfamily->faces[i++] = create_face (fcfamily, "Bold Italic");
- }
- else
- {
- FcObjectSet *os = FcObjectSetBuild (FC_STYLE, NULL);
- FcPattern *pat = FcPatternBuild (NULL,
- FC_FAMILY, FcTypeString, fcfamily->family_name,
- NULL);
-
- fontset = FcFontList (NULL, pat, os);
-
- FcPatternDestroy (pat);
- FcObjectSetDestroy (os);
-
- fcfamily->n_faces = fontset->nfont;
- fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
-
- for (i = 0; i < fontset->nfont; i++)
- {
- FcChar8 *s;
- FcResult res;
-
- res = FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, &s);
- if (res != FcResultMatch)
- s = "Regular";
-
- fcfamily->faces[i] = create_face (fcfamily, s);
- }
-
- FcFontSetDestroy (fontset);
- }
- }
-
- if (n_faces)
- *n_faces = fcfamily->n_faces;
-
- if (faces)
- *faces = g_memdup (fcfamily->faces, fcfamily->n_faces * sizeof (PangoFontFace *));
-}
-
-static const char *
-pango_fc_family_get_name (PangoFontFamily *family)
-{
- PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
-
- return fcfamily->family_name;
-}
-
-static void
-pango_fc_family_class_init (PangoFontFamilyClass *class)
-{
- class->list_faces = pango_fc_family_list_faces;
- class->get_name = pango_fc_family_get_name;
-}
-
-static void
-pango_fc_family_init (PangoFcFamily *fcfamily)
-{
- fcfamily->n_faces = -1;
-}
-
-static GType
-pango_fc_family_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontFamilyClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_fc_family_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFcFamily),
- 0, /* n_preallocs */
- (GInstanceInitFunc) pango_fc_family_init,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
- PANGO_FC_NAME "Family",
- &object_info, 0);
- }
-
- return object_type;
-}