2 * pangofc-fontmap.c: Base fontmap type for fontconfig-based backends
4 * Copyright (C) 2000-2003 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #define FONTSET_CACHE_SIZE 256
27 #include "pango-context.h"
28 #include "pangofc-fontmap.h"
29 #include "pangofc-private.h"
30 #include "pango-impl-utils.h"
32 #include "pango-enum-types.h"
37 * All programming is a practice in caching data. PangoFcFontMap is the
38 * major caching container of a Pango system on a Linux desktop. Here is
39 * a short overview of how it all works.
41 * In short, Fontconfig search patterns are constructed and a fontset loaded
42 * using them. Here is how we achieve that:
44 * - All FcPattern's referenced by any object in the fontmap are uniquified
45 * and cached in the fontmap. This both speeds lookups based on patterns
46 * faster, and saves memory. This is handled by fontmap->priv->pattern_hash.
47 * The patterns are cached indefinitely.
49 * - The results of a FcFontSort() are used to populate fontsets. However,
50 * FcFontSort() relies on the search pattern only, which includes the font
51 * size but not the full font matrix. The fontset however depends on the
52 * matrix. As a result, multiple fontsets may need results of the
53 * FcFontSort() on the same input pattern (think rotating text). As such,
54 * we cache FcFontSort() results in fontmap->priv->patterns_hash which
55 * is a refcounted structure. This level of abstraction also allows for
56 * optimizations like calling FcFontMatch() instead of FcFontSort(), and
57 * only calling FcFontSort() if any patterns other than the first match
58 * are needed. Another possible optimization would be to call FcFontSort()
59 * without trimming, and do the trimming lazily as we go. Only pattern sets
60 * already referenced by a fontset are cached.
62 * - A number of most-recently-used fontsets are cached and reused when
63 * needed. This is achieved using fontmap->priv->fontset_hash and
64 * fontmap->priv->fontset_cache.
66 * - All fonts created by any of our fontsets are also cached and reused.
67 * This is what fontmap->priv->font_hash does.
69 * - Data that only depends on the font file and face index is cached and
70 * reused by multiple fonts. This includes coverage and cmap cache info.
71 * This is done using fontmap->priv->font_face_data_hash.
73 * Upon a cache_clear() request, all caches are emptied. All objects (fonts,
74 * fontsets, faces, families) having a reference from outside will still live
75 * and may reference the fontmap still, but will not be reused by the fontmap.
80 * - Make PangoCoverage a GObject and subclass it as PangoFcCoverage which
81 * will directly use FcCharset. (#569622)
83 * - Lazy trimming of FcFontSort() results. Requires fontconfig with
88 typedef struct _PangoFcFontFaceData PangoFcFontFaceData;
89 typedef struct _PangoFcFace PangoFcFace;
90 typedef struct _PangoFcFamily PangoFcFamily;
91 typedef struct _PangoFcFindFuncInfo PangoFcFindFuncInfo;
92 typedef struct _PangoFcPatterns PangoFcPatterns;
93 typedef struct _PangoFcFontset PangoFcFontset;
95 #define PANGO_FC_TYPE_FAMILY (pango_fc_family_get_type ())
96 #define PANGO_FC_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FAMILY, PangoFcFamily))
97 #define PANGO_FC_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FAMILY))
99 #define PANGO_FC_TYPE_FACE (pango_fc_face_get_type ())
100 #define PANGO_FC_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FACE, PangoFcFace))
101 #define PANGO_FC_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FACE))
103 #define PANGO_FC_TYPE_FONTSET (pango_fc_fontset_get_type ())
104 #define PANGO_FC_FONTSET(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FONTSET, PangoFcFontset))
105 #define PANGO_FC_IS_FONTSET(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FONTSET))
107 struct _PangoFcFontMapPrivate
109 GHashTable *fontset_hash; /* Maps PangoFcFontsetKey -> PangoFcFontset */
110 GQueue *fontset_cache; /* Recently used fontsets */
112 GHashTable *font_hash; /* Maps PangoFcFontKey -> PangoFcFont */
114 GHashTable *patterns_hash; /* Maps FcPattern -> PangoFcPatterns */
116 /* pattern_hash is used to make sure we only store one copy of
117 * each identical pattern. (Speeds up lookup).
119 GHashTable *pattern_hash;
121 GHashTable *font_face_data_hash; /* Maps font file name/id -> data */
123 /* List of all families availible */
124 PangoFcFamily **families;
125 int n_families; /* -1 == uninitialized */
135 struct _PangoFcFontFaceData
139 int id; /* needed to handle TTC files with multiple faces */
142 FcPattern *pattern; /* Referenced pattern that owns filename */
143 PangoCoverage *coverage;
144 PangoFcCmapCache *cmap_cache;
149 PangoFontFace parent_instance;
151 PangoFcFamily *family;
157 struct _PangoFcFamily
159 PangoFontFamily parent_instance;
161 PangoFcFontMap *fontmap;
165 int n_faces; /* -1 == uninitialized */
167 int spacing; /* FC_SPACING */
170 struct _PangoFcFindFuncInfo
172 PangoFcDecoderFindFunc findfunc;
174 GDestroyNotify dnotify;
178 static GType pango_fc_family_get_type (void);
179 static GType pango_fc_face_get_type (void);
180 static GType pango_fc_fontset_get_type (void);
182 static void pango_fc_font_map_finalize (GObject *object);
183 static PangoFont * pango_fc_font_map_load_font (PangoFontMap *fontmap,
184 PangoContext *context,
185 const PangoFontDescription *description);
186 static PangoFontset *pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
187 PangoContext *context,
188 const PangoFontDescription *desc,
189 PangoLanguage *language);
190 static void pango_fc_font_map_list_families (PangoFontMap *fontmap,
191 PangoFontFamily ***families,
194 static double pango_fc_font_map_get_resolution (PangoFcFontMap *fcfontmap,
195 PangoContext *context);
196 static PangoFont *pango_fc_font_map_new_font (PangoFcFontMap *fontmap,
197 PangoFcFontsetKey *fontset_key,
200 static guint pango_fc_font_face_data_hash (PangoFcFontFaceData *key);
201 static gboolean pango_fc_font_face_data_equal (PangoFcFontFaceData *key1,
202 PangoFcFontFaceData *key2);
204 static void pango_fc_fontset_key_init (PangoFcFontsetKey *key,
205 PangoFcFontMap *fcfontmap,
206 PangoContext *context,
207 const PangoFontDescription *desc,
208 PangoLanguage *language);
209 static PangoFcFontsetKey *pango_fc_fontset_key_copy (const PangoFcFontsetKey *key);
210 static void pango_fc_fontset_key_free (PangoFcFontsetKey *key);
211 static guint pango_fc_fontset_key_hash (const PangoFcFontsetKey *key);
212 static gboolean pango_fc_fontset_key_equal (const PangoFcFontsetKey *key_a,
213 const PangoFcFontsetKey *key_b);
215 static void pango_fc_font_key_init (PangoFcFontKey *key,
216 PangoFcFontMap *fcfontmap,
217 PangoFcFontsetKey *fontset_key,
219 static PangoFcFontKey *pango_fc_font_key_copy (const PangoFcFontKey *key);
220 static void pango_fc_font_key_free (PangoFcFontKey *key);
221 static guint pango_fc_font_key_hash (const PangoFcFontKey *key);
222 static gboolean pango_fc_font_key_equal (const PangoFcFontKey *key_a,
223 const PangoFcFontKey *key_b);
225 static PangoFcPatterns *pango_fc_patterns_new (FcPattern *pat,
226 PangoFcFontMap *fontmap);
227 static PangoFcPatterns *pango_fc_patterns_ref (PangoFcPatterns *pats);
228 static void pango_fc_patterns_unref (PangoFcPatterns *pats);
229 static FcPattern *pango_fc_patterns_get_pattern (PangoFcPatterns *pats);
230 static FcPattern *pango_fc_patterns_get_font_pattern (PangoFcPatterns *pats, int i);
232 static FcPattern *uniquify_pattern (PangoFcFontMap *fcfontmap,
236 get_gravity_class (void)
238 static GEnumClass *class = NULL;
240 if (G_UNLIKELY (!class))
241 class = g_type_class_ref (PANGO_TYPE_GRAVITY);
247 pango_fc_font_face_data_hash (PangoFcFontFaceData *key)
249 return g_str_hash (key->filename) ^ key->id;
253 pango_fc_font_face_data_equal (PangoFcFontFaceData *key1,
254 PangoFcFontFaceData *key2)
256 return key1->id == key2->id &&
257 (key1 == key2 || 0 == strcmp (key1->filename, key2->filename));
261 pango_fc_font_face_data_free (PangoFcFontFaceData *data)
263 FcPatternDestroy (data->pattern);
266 pango_coverage_unref (data->coverage);
268 if (data->cmap_cache)
269 _pango_fc_cmap_cache_unref (data->cmap_cache);
271 g_slice_free (PangoFcFontFaceData, data);
274 /* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
276 * Not necessarily better than a lot of other hashes, but should be OK, and
277 * well tested with binary data.
280 #define FNV_32_PRIME ((guint32)0x01000193)
281 #define FNV1_32_INIT ((guint32)0x811c9dc5)
284 hash_bytes_fnv (unsigned char *buffer,
290 hval *= FNV_32_PRIME;
298 get_context_matrix (PangoContext *context,
301 const PangoMatrix *set_matrix;
302 static const PangoMatrix identity = PANGO_MATRIX_INIT;
304 set_matrix = context ? pango_context_get_matrix (context) : NULL;
305 *matrix = set_matrix ? *set_matrix : identity;
306 matrix->x0 = matrix->y0 = 0.;
310 get_scaled_size (PangoFcFontMap *fcfontmap,
311 PangoContext *context,
312 const PangoFontDescription *desc)
314 double size = pango_font_description_get_size (desc);
316 if (!pango_font_description_get_size_is_absolute (desc))
318 double dpi = pango_fc_font_map_get_resolution (fcfontmap, context);
320 size = size * dpi / 72.;
323 return .5 + pango_matrix_get_font_scale_factor (pango_context_get_matrix (context)) * size;
328 struct _PangoFcFontsetKey {
329 PangoFcFontMap *fontmap;
330 PangoLanguage *language;
331 PangoFontDescription *desc;
335 gpointer context_key;
338 struct _PangoFcFontKey {
339 PangoFcFontMap *fontmap;
342 gpointer context_key;
346 pango_fc_fontset_key_init (PangoFcFontsetKey *key,
347 PangoFcFontMap *fcfontmap,
348 PangoContext *context,
349 const PangoFontDescription *desc,
350 PangoLanguage *language)
352 if (!language && context)
353 language = pango_context_get_language (context);
355 key->fontmap = fcfontmap;
356 get_context_matrix (context, &key->matrix);
357 key->pixelsize = get_scaled_size (fcfontmap, context, desc);
358 key->resolution = pango_fc_font_map_get_resolution (fcfontmap, context);
359 key->language = language;
360 key->desc = pango_font_description_copy_static (desc);
361 pango_font_description_unset_fields (key->desc, PANGO_FONT_MASK_SIZE);
363 if (context && PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get)
364 key->context_key = (gpointer)PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context);
366 key->context_key = NULL;
370 pango_fc_fontset_key_equal (const PangoFcFontsetKey *key_a,
371 const PangoFcFontsetKey *key_b)
373 if (key_a->language == key_b->language &&
374 key_a->pixelsize == key_b->pixelsize &&
375 key_a->resolution == key_b->resolution &&
376 pango_font_description_equal (key_a->desc, key_b->desc) &&
377 0 == memcmp (&key_a->matrix, &key_b->matrix, 4 * sizeof (double)))
379 if (key_a->context_key)
380 return PANGO_FC_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap,
384 return key_a->context_key == key_b->context_key;
391 pango_fc_fontset_key_hash (const PangoFcFontsetKey *key)
393 guint32 hash = FNV1_32_INIT;
395 /* We do a bytewise hash on the doubles */
396 hash = hash_bytes_fnv ((unsigned char *)(&key->matrix), sizeof (double) * 4, hash);
397 hash = hash_bytes_fnv ((unsigned char *)(&key->resolution), sizeof (double), hash);
399 hash ^= key->pixelsize;
401 if (key->context_key)
402 hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap,
406 GPOINTER_TO_UINT (key->language) ^
407 pango_font_description_hash (key->desc));
411 pango_fc_fontset_key_free (PangoFcFontsetKey *key)
413 pango_font_description_free (key->desc);
415 if (key->context_key)
416 PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap,
419 g_slice_free (PangoFcFontsetKey, key);
422 static PangoFcFontsetKey *
423 pango_fc_fontset_key_copy (const PangoFcFontsetKey *old)
425 PangoFcFontsetKey *key = g_slice_new (PangoFcFontsetKey);
427 key->fontmap = old->fontmap;
428 key->language = old->language;
429 key->desc = pango_font_description_copy (old->desc);
430 key->matrix = old->matrix;
431 key->pixelsize = old->pixelsize;
432 key->resolution = old->resolution;
433 if (old->context_key)
434 key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap,
437 key->context_key = NULL;
443 * pango_fc_fontset_key_get_language:
444 * @key: the fontset key
446 * Gets the language member of @key.
448 * Returns: the language
453 pango_fc_fontset_key_get_language (const PangoFcFontsetKey *key)
455 return key->language;
459 * pango_fc_fontset_key_get_description:
460 * @key: the fontset key
462 * Gets the font description of @key.
464 * Returns: the font description, which is owned by @key and should not be modified.
468 const PangoFontDescription *
469 pango_fc_fontset_key_get_description (const PangoFcFontsetKey *key)
475 * pango_fc_fontset_key_get_matrix:
476 * @key: the fontset key
478 * Gets the matrix member of @key.
480 * Returns: the matrix, which is owned by @key and should not be modified.
485 pango_fc_fontset_key_get_matrix (const PangoFcFontsetKey *key)
491 * pango_fc_fontset_key_get_absolute_size:
492 * @key: the fontset key
494 * Gets the absolute font size of @key in Pango units. This is adjusted
495 * for both resolution and transformation matrix.
497 * Returns: the pixel size of @key.
502 pango_fc_fontset_key_get_absolute_size (const PangoFcFontsetKey *key)
504 return key->pixelsize;
508 * pango_fc_fontset_key_get_resolution:
509 * @key: the fontset key
511 * Gets the resolution of @key
513 * Returns: the resolution of @key
518 pango_fc_fontset_key_get_resolution (const PangoFcFontsetKey *key)
520 return key->resolution;
524 * pango_fc_fontset_key_get_context_key:
527 * Gets the context key member of @key.
529 * Returns: the context key, which is owned by @key and should not be modified.
534 pango_fc_fontset_key_get_context_key (const PangoFcFontsetKey *key)
536 return key->context_key;
544 pango_fc_font_key_equal (const PangoFcFontKey *key_a,
545 const PangoFcFontKey *key_b)
547 if (key_a->pattern == key_b->pattern &&
548 0 == memcmp (&key_a->matrix, &key_b->matrix, 4 * sizeof (double)))
550 if (key_a->context_key && key_b->context_key)
551 return PANGO_FC_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap,
555 return key_a->context_key == key_b->context_key;
562 pango_fc_font_key_hash (const PangoFcFontKey *key)
564 guint32 hash = FNV1_32_INIT;
566 /* We do a bytewise hash on the doubles */
567 hash = hash_bytes_fnv ((unsigned char *)(&key->matrix), sizeof (double) * 4, hash);
569 if (key->context_key)
570 hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap,
573 return (hash ^ GPOINTER_TO_UINT (key->pattern));
577 pango_fc_font_key_free (PangoFcFontKey *key)
580 FcPatternDestroy (key->pattern);
582 if (key->context_key)
583 PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap,
586 g_slice_free (PangoFcFontKey, key);
589 static PangoFcFontKey *
590 pango_fc_font_key_copy (const PangoFcFontKey *old)
592 PangoFcFontKey *key = g_slice_new (PangoFcFontKey);
594 key->fontmap = old->fontmap;
595 FcPatternReference (old->pattern);
596 key->pattern = old->pattern;
597 key->matrix = old->matrix;
598 if (old->context_key)
599 key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap,
602 key->context_key = NULL;
608 pango_fc_font_key_init (PangoFcFontKey *key,
609 PangoFcFontMap *fcfontmap,
610 PangoFcFontsetKey *fontset_key,
613 key->fontmap = fcfontmap;
614 key->pattern = pattern;
615 key->matrix = *pango_fc_fontset_key_get_matrix (fontset_key);
616 key->context_key = pango_fc_fontset_key_get_context_key (fontset_key);
622 * pango_fc_font_key_get_pattern:
625 * Gets the fontconfig pattern member of @key.
627 * Returns: the pattern, which is owned by @key and should not be modified.
632 pango_fc_font_key_get_pattern (const PangoFcFontKey *key)
638 * pango_fc_font_key_get_matrix:
641 * Gets the matrix member of @key.
643 * Returns: the matrix, which is owned by @key and should not be modified.
648 pango_fc_font_key_get_matrix (const PangoFcFontKey *key)
654 * pango_fc_font_key_get_context_key:
657 * Gets the context key member of @key.
659 * Returns: the context key, which is owned by @key and should not be modified.
664 pango_fc_font_key_get_context_key (const PangoFcFontKey *key)
666 return key->context_key;
674 struct _PangoFcPatterns {
677 PangoFcFontMap *fontmap;
684 static PangoFcPatterns *
685 pango_fc_patterns_new (FcPattern *pat, PangoFcFontMap *fontmap)
687 PangoFcPatterns *pats;
689 pat = uniquify_pattern (fontmap, pat);
690 pats = g_hash_table_lookup (fontmap->priv->patterns_hash, pat);
692 return pango_fc_patterns_ref (pats);
694 pats = g_slice_new0 (PangoFcPatterns);
696 pats->fontmap = fontmap;
699 FcPatternReference (pat);
702 g_hash_table_insert (fontmap->priv->patterns_hash,
703 pats->pattern, pats);
708 static PangoFcPatterns *
709 pango_fc_patterns_ref (PangoFcPatterns *pats)
711 g_return_val_if_fail (pats->ref_count > 0, NULL);
719 pango_fc_patterns_unref (PangoFcPatterns *pats)
721 g_return_if_fail (pats->ref_count > 0);
728 /* Only remove from fontmap hash if we are in it. This is not necessarily
729 * the case after a cache_clear() call. */
730 if (pats->fontmap->priv->patterns_hash &&
731 pats == g_hash_table_lookup (pats->fontmap->priv->patterns_hash, pats->pattern))
732 g_hash_table_remove (pats->fontmap->priv->patterns_hash,
736 FcPatternDestroy (pats->pattern);
739 FcPatternDestroy (pats->match);
742 FcFontSetDestroy (pats->fontset);
744 g_slice_free (PangoFcPatterns, pats);
748 pango_fc_patterns_get_pattern (PangoFcPatterns *pats)
750 return pats->pattern;
754 pango_fc_patterns_get_font_pattern (PangoFcPatterns *pats, int i)
759 if (!pats->match && !pats->fontset)
761 pats->match = FcFontMatch (NULL, pats->pattern, &result);
772 pats->fontset = FcFontSort (NULL, pats->pattern, FcTrue, NULL, &result);
775 FcPatternDestroy (pats->match);
781 if (pats->fontset && i < pats->fontset->nfont)
782 return pats->fontset->fonts[i];
792 static void pango_fc_fontset_finalize (GObject *object);
793 static void pango_fc_fontset_init (PangoFcFontset *fontset);
794 static PangoLanguage * pango_fc_fontset_get_language (PangoFontset *fontset);
795 static PangoFont * pango_fc_fontset_get_font (PangoFontset *fontset,
797 static void pango_fc_fontset_foreach (PangoFontset *fontset,
798 PangoFontsetForeachFunc func,
801 struct _PangoFcFontset
803 PangoFontset parent_instance;
805 PangoFcFontsetKey *key;
807 PangoFcPatterns *patterns;
811 GPtrArray *coverages;
816 typedef PangoFontsetClass PangoFcFontsetClass;
818 static PangoFontsetClass *fc_fontset_parent_class; /* Parent class structure for PangoFcFontset */
820 static PangoFcFontset *
821 pango_fc_fontset_new (PangoFcFontsetKey *key,
822 PangoFcPatterns *patterns)
824 PangoFcFontset *fontset;
826 fontset = g_object_new (PANGO_FC_TYPE_FONTSET, NULL);
828 fontset->key = pango_fc_fontset_key_copy (key);
829 fontset->patterns = pango_fc_patterns_ref (patterns);
834 static PangoFcFontsetKey *
835 pango_fc_fontset_get_key (PangoFcFontset *fontset)
841 pango_fc_fontset_load_next_font (PangoFcFontset *fontset)
843 FcPattern *pattern, *font_pattern;
846 pattern = pango_fc_patterns_get_pattern (fontset->patterns),
847 font_pattern = pango_fc_patterns_get_font_pattern (fontset->patterns,
848 fontset->patterns_i++);
849 if (G_UNLIKELY (!font_pattern))
852 font_pattern = FcFontRenderPrepare (NULL, pattern, font_pattern);
854 if (G_UNLIKELY (!font_pattern))
858 /* The FC_PATTERN element, which points back to our the original
859 * pattern defeats our hash tables.
861 FcPatternDel (font_pattern, FC_PATTERN);
862 #endif /* FC_PATTERN */
864 font = pango_fc_font_map_new_font (fontset->key->fontmap,
868 FcPatternDestroy (font_pattern);
874 pango_fc_fontset_get_font_at (PangoFcFontset *fontset,
877 while (i >= fontset->fonts->len)
879 PangoFont *font = pango_fc_fontset_load_next_font (fontset);
880 g_ptr_array_add (fontset->fonts, font);
881 g_ptr_array_add (fontset->coverages, NULL);
886 return g_ptr_array_index (fontset->fonts, i);
890 pango_fc_fontset_class_init (PangoFcFontsetClass *class)
892 GObjectClass *object_class = G_OBJECT_CLASS (class);
893 PangoFontsetClass *fontset_class = PANGO_FONTSET_CLASS (class);
895 fc_fontset_parent_class = g_type_class_peek_parent (class);
897 object_class->finalize = pango_fc_fontset_finalize;
898 fontset_class->get_font = pango_fc_fontset_get_font;
899 fontset_class->get_language = pango_fc_fontset_get_language;
900 fontset_class->foreach = pango_fc_fontset_foreach;
904 pango_fc_fontset_init (PangoFcFontset *fontset)
906 fontset->fonts = g_ptr_array_new ();
907 fontset->coverages = g_ptr_array_new ();
911 pango_fc_fontset_finalize (GObject *object)
913 PangoFcFontset *fontset = PANGO_FC_FONTSET (object);
916 for (i = 0; i < fontset->fonts->len; i++)
918 PangoFont *font = g_ptr_array_index(fontset->fonts, i);
920 g_object_unref (font);
922 g_ptr_array_free (fontset->fonts, TRUE);
924 for (i = 0; i < fontset->coverages->len; i++)
926 PangoCoverage *coverage = g_ptr_array_index (fontset->coverages, i);
928 pango_coverage_unref (coverage);
930 g_ptr_array_free (fontset->coverages, TRUE);
933 pango_fc_fontset_key_free (fontset->key);
935 if (fontset->patterns)
936 pango_fc_patterns_unref (fontset->patterns);
938 G_OBJECT_CLASS (fc_fontset_parent_class)->finalize (object);
941 static PangoLanguage *
942 pango_fc_fontset_get_language (PangoFontset *fontset)
944 PangoFcFontset *fcfontset = PANGO_FC_FONTSET (fontset);
946 return pango_fc_fontset_key_get_language (pango_fc_fontset_get_key (fcfontset));
950 pango_fc_fontset_get_font (PangoFontset *fontset,
953 PangoFcFontset *fcfontset = PANGO_FC_FONTSET (fontset);
954 PangoCoverageLevel best_level = PANGO_COVERAGE_NONE;
955 PangoCoverageLevel level;
957 PangoCoverage *coverage;
962 (font = pango_fc_fontset_get_font_at (fcfontset, i));
965 coverage = g_ptr_array_index (fcfontset->coverages, i);
967 if (coverage == NULL)
969 font = g_ptr_array_index (fcfontset->fonts, i);
971 coverage = pango_font_get_coverage (font, fcfontset->key->language);
972 g_ptr_array_index (fcfontset->coverages, i) = coverage;
975 level = pango_coverage_get (coverage, wc);
977 if (result == -1 || level > best_level)
981 if (level == PANGO_COVERAGE_EXACT)
986 if (G_UNLIKELY (result == -1))
989 font = g_ptr_array_index(fcfontset->fonts, result);
990 return g_object_ref (font);
994 pango_fc_fontset_foreach (PangoFontset *fontset,
995 PangoFontsetForeachFunc func,
998 PangoFcFontset *fcfontset = PANGO_FC_FONTSET (fontset);
1003 (font = pango_fc_fontset_get_font_at (fcfontset, i));
1006 if ((*func) (fontset, font, data))
1011 static PANGO_DEFINE_TYPE (PangoFcFontset, pango_fc_fontset,
1012 pango_fc_fontset_class_init, pango_fc_fontset_init,
1019 G_DEFINE_ABSTRACT_TYPE (PangoFcFontMap, pango_fc_font_map, PANGO_TYPE_FONT_MAP)
1022 pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
1024 static gboolean registered_modules = FALSE;
1025 PangoFcFontMapPrivate *priv;
1027 priv = fcfontmap->priv = G_TYPE_INSTANCE_GET_PRIVATE (fcfontmap,
1028 PANGO_TYPE_FC_FONT_MAP,
1029 PangoFcFontMapPrivate);
1031 if (!registered_modules)
1035 registered_modules = TRUE;
1037 for (i = 0; _pango_included_fc_modules[i].list; i++)
1038 pango_module_register (&_pango_included_fc_modules[i]);
1041 priv->n_families = -1;
1043 priv->font_hash = g_hash_table_new ((GHashFunc)pango_fc_font_key_hash,
1044 (GEqualFunc)pango_fc_font_key_equal);
1046 priv->fontset_hash = g_hash_table_new_full ((GHashFunc)pango_fc_fontset_key_hash,
1047 (GEqualFunc)pango_fc_fontset_key_equal,
1049 (GDestroyNotify)g_object_unref);
1050 priv->fontset_cache = g_queue_new ();
1052 priv->patterns_hash = g_hash_table_new (NULL, NULL);
1054 priv->pattern_hash = g_hash_table_new_full ((GHashFunc) FcPatternHash,
1055 (GEqualFunc) FcPatternEqual,
1056 (GDestroyNotify) FcPatternDestroy,
1059 priv->font_face_data_hash = g_hash_table_new_full ((GHashFunc)pango_fc_font_face_data_hash,
1060 (GEqualFunc)pango_fc_font_face_data_equal,
1061 (GDestroyNotify)pango_fc_font_face_data_free,
1067 pango_fc_font_map_fini (PangoFcFontMap *fcfontmap)
1069 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1072 g_queue_free (priv->fontset_cache);
1073 priv->fontset_cache = NULL;
1075 g_hash_table_destroy (priv->fontset_hash);
1076 priv->fontset_hash = NULL;
1078 g_hash_table_destroy (priv->patterns_hash);
1079 priv->patterns_hash = NULL;
1081 g_hash_table_destroy (priv->font_hash);
1082 priv->font_hash = NULL;
1084 g_hash_table_destroy (priv->font_face_data_hash);
1085 priv->font_face_data_hash = NULL;
1087 g_hash_table_destroy (priv->pattern_hash);
1088 priv->pattern_hash = NULL;
1090 for (i = 0; i < priv->n_families; i++)
1091 g_object_unref (priv->families[i]);
1092 g_free (priv->families);
1093 priv->n_families = -1;
1094 priv->families = NULL;
1098 pango_fc_font_map_class_init (PangoFcFontMapClass *class)
1100 GObjectClass *object_class = G_OBJECT_CLASS (class);
1101 PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class);
1103 object_class->finalize = pango_fc_font_map_finalize;
1104 fontmap_class->load_font = pango_fc_font_map_load_font;
1105 fontmap_class->load_fontset = pango_fc_font_map_load_fontset;
1106 fontmap_class->list_families = pango_fc_font_map_list_families;
1107 fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_FC;
1109 g_type_class_add_private (object_class, sizeof (PangoFcFontMapPrivate));
1114 * pango_fc_font_map_add_decoder_find_func:
1115 * @fcfontmap: The #PangoFcFontMap to add this method to.
1116 * @findfunc: The #PangoFcDecoderFindFunc callback function
1117 * @user_data: User data.
1118 * @dnotify: A #GDestroyNotify callback that will be called when the
1119 * fontmap is finalized and the decoder is released.
1121 * This function saves a callback method in the #PangoFcFontMap that
1122 * will be called whenever new fonts are created. If the
1123 * function returns a #PangoFcDecoder, that decoder will be used to
1124 * determine both coverage via a #FcCharSet and a one-to-one mapping of
1125 * characters to glyphs. This will allow applications to have
1126 * application-specific encodings for various fonts.
1131 pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap,
1132 PangoFcDecoderFindFunc findfunc,
1134 GDestroyNotify dnotify)
1136 PangoFcFontMapPrivate *priv;
1137 PangoFcFindFuncInfo *info;
1139 g_return_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap));
1141 priv = fcfontmap->priv;
1143 info = g_slice_new (PangoFcFindFuncInfo);
1145 info->findfunc = findfunc;
1146 info->user_data = user_data;
1147 info->dnotify = dnotify;
1149 priv->findfuncs = g_slist_append (priv->findfuncs, info);
1153 * pango_fc_font_map_find_decoder:
1154 * @fcfontmap: The #PangoFcFontMap to use.
1155 * @pattern: The #FcPattern to find the decoder for.
1157 * Finds the decoder to use for @pattern. Decoders can be added to
1158 * a font map using pango_fc_font_map_add_decoder_find_func().
1160 * Returns: a newly created #PangoFcDecoder object or %NULL if
1161 * no decoder is set for @pattern.
1166 pango_fc_font_map_find_decoder (PangoFcFontMap *fcfontmap,
1171 g_return_val_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap), NULL);
1172 g_return_val_if_fail (pattern != NULL, NULL);
1174 for (l = fcfontmap->priv->findfuncs; l && l->data; l = l->next)
1176 PangoFcFindFuncInfo *info = l->data;
1177 PangoFcDecoder *decoder;
1179 decoder = info->findfunc (pattern, info->user_data);
1188 pango_fc_font_map_finalize (GObject *object)
1190 PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (object);
1192 pango_fc_font_map_shutdown (fcfontmap);
1194 G_OBJECT_CLASS (pango_fc_font_map_parent_class)->finalize (object);
1197 /* Add a mapping from key to fcfont */
1199 pango_fc_font_map_add (PangoFcFontMap *fcfontmap,
1200 PangoFcFontKey *key,
1201 PangoFcFont *fcfont)
1203 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1204 PangoFcFontKey *key_copy;
1206 key_copy = pango_fc_font_key_copy (key);
1207 _pango_fc_font_set_font_key (fcfont, key_copy);
1208 g_hash_table_insert (priv->font_hash, key_copy, fcfont);
1211 /* Remove mapping from fcfont->key to fcfont */
1212 /* Closely related to shutdown_font() */
1214 _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap,
1215 PangoFcFont *fcfont)
1217 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1218 PangoFcFontKey *key;
1220 key = _pango_fc_font_get_font_key (fcfont);
1223 /* Only remove from fontmap hash if we are in it. This is not necessarily
1224 * the case after a cache_clear() call. */
1225 if (priv->font_hash &&
1226 fcfont == g_hash_table_lookup (priv->font_hash, key))
1228 g_hash_table_remove (priv->font_hash, key);
1230 _pango_fc_font_set_font_key (fcfont, NULL);
1231 pango_fc_font_key_free (key);
1235 static PangoFcFamily *
1236 create_family (PangoFcFontMap *fcfontmap,
1237 const char *family_name,
1240 PangoFcFamily *family = g_object_new (PANGO_FC_TYPE_FAMILY, NULL);
1241 family->fontmap = fcfontmap;
1242 family->family_name = g_strdup (family_name);
1243 family->spacing = spacing;
1249 is_alias_family (const char *family_name)
1251 switch (family_name[0])
1255 return (g_ascii_strcasecmp (family_name, "monospace") == 0);
1258 return (g_ascii_strcasecmp (family_name, "sans") == 0 ||
1259 g_ascii_strcasecmp (family_name, "serif") == 0);
1266 pango_fc_font_map_list_families (PangoFontMap *fontmap,
1267 PangoFontFamily ***families,
1270 PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
1271 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1286 if (priv->n_families < 0)
1288 FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SPACING, NULL);
1289 FcPattern *pat = FcPatternCreate ();
1290 /* use hash table to avoid duplicate listings if different faces in
1291 * the same family have different spacing values */
1292 GHashTable *temp_family_hash;
1294 fontset = FcFontList (NULL, pat, os);
1296 FcPatternDestroy (pat);
1297 FcObjectSetDestroy (os);
1299 priv->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */
1300 temp_family_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1303 for (i = 0; i < fontset->nfont; i++)
1309 res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **)(void*)&s);
1310 g_assert (res == FcResultMatch);
1312 res = FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &spacing);
1313 g_assert (res == FcResultMatch || res == FcResultNoMatch);
1314 if (res == FcResultNoMatch)
1315 spacing = FC_PROPORTIONAL;
1317 if (!is_alias_family (s) && !g_hash_table_lookup (temp_family_hash, s))
1319 PangoFcFamily *temp_family = create_family (fcfontmap, s, spacing);
1320 g_hash_table_insert (temp_family_hash, g_strdup (s), s);
1321 priv->families[count++] = temp_family;
1325 FcFontSetDestroy (fontset);
1326 g_hash_table_destroy (temp_family_hash);
1328 priv->families[count++] = create_family (fcfontmap, "Sans", FC_PROPORTIONAL);
1329 priv->families[count++] = create_family (fcfontmap, "Serif", FC_PROPORTIONAL);
1330 priv->families[count++] = create_family (fcfontmap, "Monospace", FC_MONO);
1332 priv->n_families = count;
1336 *n_families = priv->n_families;
1339 *families = g_memdup (priv->families, priv->n_families * sizeof (PangoFontFamily *));
1343 pango_fc_convert_weight_to_fc (PangoWeight pango_weight)
1345 if (pango_weight <= (PANGO_WEIGHT_THIN + PANGO_WEIGHT_ULTRALIGHT) / 2)
1346 return FC_WEIGHT_THIN;
1347 else if (pango_weight <= (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2)
1348 return FC_WEIGHT_ULTRALIGHT;
1349 else if (pango_weight <= (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_BOOK) / 2)
1350 return FC_WEIGHT_LIGHT;
1351 else if (pango_weight <= (PANGO_WEIGHT_BOOK + PANGO_WEIGHT_NORMAL) / 2)
1352 return FC_WEIGHT_BOOK;
1353 else if (pango_weight <= (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_MEDIUM) / 2)
1354 return FC_WEIGHT_NORMAL;
1355 else if (pango_weight <= (PANGO_WEIGHT_MEDIUM + PANGO_WEIGHT_SEMIBOLD) / 2)
1356 return FC_WEIGHT_MEDIUM;
1357 else if (pango_weight <= (PANGO_WEIGHT_SEMIBOLD + PANGO_WEIGHT_BOLD) / 2)
1358 return FC_WEIGHT_DEMIBOLD;
1359 else if (pango_weight <= (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
1360 return FC_WEIGHT_BOLD;
1361 else if (pango_weight <= (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY) / 2)
1362 return FC_WEIGHT_ULTRABOLD;
1363 else if (pango_weight <= (PANGO_WEIGHT_HEAVY + PANGO_WEIGHT_ULTRAHEAVY) / 2)
1364 return FC_WEIGHT_BLACK;
1366 return FC_WEIGHT_EXTRABLACK;
1370 pango_fc_convert_slant_to_fc (PangoStyle pango_style)
1372 switch (pango_style)
1374 case PANGO_STYLE_NORMAL:
1375 return FC_SLANT_ROMAN;
1376 case PANGO_STYLE_ITALIC:
1377 return FC_SLANT_ITALIC;
1378 case PANGO_STYLE_OBLIQUE:
1379 return FC_SLANT_OBLIQUE;
1381 return FC_SLANT_ROMAN;
1387 pango_fc_convert_width_to_fc (PangoStretch pango_stretch)
1389 switch (pango_stretch)
1391 case PANGO_STRETCH_NORMAL:
1392 return FC_WIDTH_NORMAL;
1393 case PANGO_STRETCH_ULTRA_CONDENSED:
1394 return FC_WIDTH_ULTRACONDENSED;
1395 case PANGO_STRETCH_EXTRA_CONDENSED:
1396 return FC_WIDTH_EXTRACONDENSED;
1397 case PANGO_STRETCH_CONDENSED:
1398 return FC_WIDTH_CONDENSED;
1399 case PANGO_STRETCH_SEMI_CONDENSED:
1400 return FC_WIDTH_SEMICONDENSED;
1401 case PANGO_STRETCH_SEMI_EXPANDED:
1402 return FC_WIDTH_SEMIEXPANDED;
1403 case PANGO_STRETCH_EXPANDED:
1404 return FC_WIDTH_EXPANDED;
1405 case PANGO_STRETCH_EXTRA_EXPANDED:
1406 return FC_WIDTH_EXTRAEXPANDED;
1407 case PANGO_STRETCH_ULTRA_EXPANDED:
1408 return FC_WIDTH_ULTRAEXPANDED;
1410 return FC_WIDTH_NORMAL;
1416 pango_fc_make_pattern (const PangoFontDescription *description,
1417 PangoLanguage *language,
1422 const char *prgname;
1425 PangoGravity gravity;
1433 prgname = g_get_prgname ();
1434 slant = pango_fc_convert_slant_to_fc (pango_font_description_get_style (description));
1435 weight = pango_fc_convert_weight_to_fc (pango_font_description_get_weight (description));
1437 width = pango_fc_convert_width_to_fc (pango_font_description_get_stretch (description));
1440 gravity = pango_font_description_get_gravity (description);
1441 vertical = PANGO_GRAVITY_IS_VERTICAL (gravity) ? FcTrue : FcFalse;
1443 /* The reason for passing in FC_SIZE as well as FC_PIXEL_SIZE is
1444 * to work around a bug in libgnomeprint where it doesn't look
1445 * for FC_PIXEL_SIZE. See http://bugzilla.gnome.org/show_bug.cgi?id=169020
1447 * Putting FC_SIZE in here slightly reduces the efficiency
1448 * of caching of patterns and fonts when working with multiple different
1451 pattern = FcPatternBuild (NULL,
1452 PANGO_FC_VERSION, FcTypeInteger, pango_version(),
1453 FC_WEIGHT, FcTypeInteger, weight,
1454 FC_SLANT, FcTypeInteger, slant,
1456 FC_WIDTH, FcTypeInteger, width,
1458 #ifdef FC_VERTICAL_LAYOUT
1459 FC_VERTICAL_LAYOUT, FcTypeBool, vertical,
1461 FC_DPI, FcTypeDouble, dpi,
1462 FC_SIZE, FcTypeDouble, pixel_size * (72. / 1024. / dpi),
1463 FC_PIXEL_SIZE, FcTypeDouble, pixel_size / 1024.,
1466 if (pango_font_description_get_family (description))
1468 families = g_strsplit (pango_font_description_get_family (description), ",", -1);
1470 for (i = 0; families[i]; i++)
1471 FcPatternAddString (pattern, FC_FAMILY, (FcChar8*) families[i]);
1473 g_strfreev (families);
1477 FcPatternAddString (pattern, FC_LANG, (FcChar8 *) pango_language_to_string (language));
1479 if (gravity != PANGO_GRAVITY_SOUTH)
1481 GEnumValue *value = g_enum_get_value (get_gravity_class (), gravity);
1482 FcPatternAddString (pattern, PANGO_FC_GRAVITY, (FcChar8*) value->value_nick);
1486 FcPatternAddString (pattern, PANGO_FC_PRGNAME, (FcChar8*) prgname);
1492 uniquify_pattern (PangoFcFontMap *fcfontmap,
1495 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1496 FcPattern *old_pattern;
1498 old_pattern = g_hash_table_lookup (priv->pattern_hash, pattern);
1505 FcPatternReference (pattern);
1506 g_hash_table_insert (priv->pattern_hash, pattern, pattern);
1512 pango_fc_font_map_new_font (PangoFcFontMap *fcfontmap,
1513 PangoFcFontsetKey *fontset_key,
1516 PangoFcFontMapClass *class;
1517 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1519 PangoFcFont *fcfont;
1525 match = uniquify_pattern (fcfontmap, match);
1527 pango_fc_font_key_init (&key, fcfontmap, fontset_key, match);
1529 fcfont = g_hash_table_lookup (priv->font_hash, &key);
1531 return g_object_ref (fcfont);
1533 class = PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap);
1535 if (class->create_font)
1537 fcfont = class->create_font (fcfontmap, &key);
1541 const PangoMatrix *pango_matrix = pango_fc_fontset_key_get_matrix (fontset_key);
1542 FcMatrix fc_matrix, *fc_matrix_val;
1545 /* Fontconfig has the Y axis pointing up, Pango, down.
1547 fc_matrix.xx = pango_matrix->xx;
1548 fc_matrix.xy = - pango_matrix->xy;
1549 fc_matrix.yx = - pango_matrix->yx;
1550 fc_matrix.yy = pango_matrix->yy;
1552 pattern = FcPatternDuplicate (match);
1554 for (i = 0; FcPatternGetMatrix (pattern, FC_MATRIX, i, &fc_matrix_val) == FcResultMatch; i++)
1555 FcMatrixMultiply (&fc_matrix, &fc_matrix, fc_matrix_val);
1557 FcPatternDel (pattern, FC_MATRIX);
1558 FcPatternAddMatrix (pattern, FC_MATRIX, &fc_matrix);
1560 fcfont = class->new_font (fcfontmap, uniquify_pattern (fcfontmap, pattern));
1562 FcPatternDestroy (pattern);
1568 fcfont->matrix = key.matrix;
1569 /* In case the backend didn't set the fontmap */
1570 if (!fcfont->fontmap)
1571 g_object_set (fcfont,
1572 "fontmap", fcfontmap,
1575 /* cache it on fontmap */
1576 pango_fc_font_map_add (fcfontmap, &key, fcfont);
1578 return (PangoFont *)fcfont;
1582 pango_fc_default_substitute (PangoFcFontMap *fontmap,
1583 PangoFcFontsetKey *fontsetkey,
1586 if (PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->fontset_key_substitute)
1587 PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->fontset_key_substitute (fontmap, fontsetkey, pattern);
1588 else if (PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute)
1589 PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute (fontmap, pattern);
1593 pango_fc_font_map_get_resolution (PangoFcFontMap *fcfontmap,
1594 PangoContext *context)
1596 if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution)
1597 return PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution (fcfontmap, context);
1599 if (fcfontmap->priv->dpi < 0)
1601 FcResult result = FcResultNoMatch;
1602 FcPattern *tmp = FcPatternBuild (NULL,
1603 FC_FAMILY, FcTypeString, "Sans",
1604 FC_SIZE, FcTypeDouble, 10.,
1608 pango_fc_default_substitute (fcfontmap, NULL, tmp);
1609 result = FcPatternGetDouble (tmp, FC_DPI, 0, &fcfontmap->priv->dpi);
1610 FcPatternDestroy (tmp);
1613 if (result != FcResultMatch)
1615 g_warning ("Error getting DPI from fontconfig, using 72.0");
1616 fcfontmap->priv->dpi = 72.0;
1620 return fcfontmap->priv->dpi;
1624 pango_fc_fontset_key_make_pattern (PangoFcFontsetKey *key)
1626 return pango_fc_make_pattern (key->desc,
1632 static PangoFcPatterns *
1633 pango_fc_font_map_get_patterns (PangoFontMap *fontmap,
1634 PangoFcFontsetKey *key)
1636 PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
1637 PangoFcPatterns *patterns;
1640 pattern = pango_fc_fontset_key_make_pattern (key);
1641 pango_fc_default_substitute (fcfontmap, key, pattern);
1643 patterns = pango_fc_patterns_new (pattern, fcfontmap);
1645 FcPatternDestroy (pattern);
1651 get_first_font (PangoFontset *fontset G_GNUC_UNUSED,
1655 *(PangoFont **)data = font;
1661 pango_fc_font_map_load_font (PangoFontMap *fontmap,
1662 PangoContext *context,
1663 const PangoFontDescription *description)
1665 PangoLanguage *language;
1666 PangoFontset *fontset;
1667 PangoFont *font = NULL;
1670 language = pango_context_get_language (context);
1674 fontset = pango_font_map_load_fontset (fontmap, context, description, language);
1678 pango_fontset_foreach (fontset, get_first_font, &font);
1681 g_object_ref (font);
1683 g_object_unref (fontset);
1690 pango_fc_fontset_cache (PangoFcFontset *fontset,
1691 PangoFcFontMap *fcfontmap)
1693 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1694 GQueue *cache = priv->fontset_cache;
1696 if (fontset->cache_link)
1698 if (fontset->cache_link == cache->head)
1701 /* Already in cache, move to head
1703 if (fontset->cache_link == cache->tail)
1704 cache->tail = fontset->cache_link->prev;
1706 cache->head = g_list_remove_link (cache->head, fontset->cache_link);
1711 /* Add to cache initially
1713 if (cache->length == FONTSET_CACHE_SIZE)
1715 PangoFcFontset *tmp_fontset = g_queue_pop_tail (cache);
1716 tmp_fontset->cache_link = NULL;
1717 g_hash_table_remove (priv->fontset_hash, tmp_fontset->key);
1720 fontset->cache_link = g_list_prepend (NULL, fontset);
1723 g_queue_push_head_link (cache, fontset->cache_link);
1726 static PangoFontset *
1727 pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
1728 PangoContext *context,
1729 const PangoFontDescription *desc,
1730 PangoLanguage *language)
1732 PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
1733 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1734 PangoFcFontset *fontset;
1735 PangoFcFontsetKey key;
1737 pango_fc_fontset_key_init (&key, fcfontmap, context, desc, language);
1739 fontset = g_hash_table_lookup (priv->fontset_hash, &key);
1741 if (G_UNLIKELY (!fontset))
1743 PangoFcPatterns *patterns = pango_fc_font_map_get_patterns (fontmap, &key);
1748 fontset = pango_fc_fontset_new (&key, patterns);
1749 g_hash_table_insert (priv->fontset_hash, pango_fc_fontset_get_key (fontset), fontset);
1751 pango_fc_patterns_unref (patterns);
1754 pango_fc_fontset_cache (fontset, fcfontmap);
1756 pango_font_description_free (key.desc);
1758 return g_object_ref (fontset);
1762 * pango_fc_font_map_cache_clear:
1763 * @fcfontmap: a #PangoFcFontmap
1765 * Clear all cached information and fontsets for this font map;
1766 * this should be called whenever there is a change in the
1767 * output of the default_substitute() virtual function of the
1768 * font map, or if fontconfig has been reinitialized to new
1774 pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap)
1776 if (G_UNLIKELY (fcfontmap->priv->closed))
1779 pango_fc_font_map_fini (fcfontmap);
1780 pango_fc_font_map_init (fcfontmap);
1783 static PangoFcFontFaceData *
1784 pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap,
1785 FcPattern *font_pattern)
1787 PangoFcFontMapPrivate *priv = fcfontmap->priv;
1788 PangoFcFontFaceData key;
1789 PangoFcFontFaceData *data;
1791 if (FcPatternGetString (font_pattern, FC_FILE, 0, (FcChar8 **)(void*)&key.filename) != FcResultMatch)
1794 if (FcPatternGetInteger (font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
1797 data = g_hash_table_lookup (priv->font_face_data_hash, &key);
1798 if (G_LIKELY (data))
1801 data = g_slice_new0 (PangoFcFontFaceData);
1802 data->filename = key.filename;
1805 data->pattern = font_pattern;
1806 FcPatternReference (data->pattern);
1808 g_hash_table_insert (priv->font_face_data_hash, data, data);
1813 static PangoFcCmapCache *
1814 _pango_fc_cmap_cache_ref (PangoFcCmapCache *cmap_cache)
1816 g_atomic_int_inc ((int *) &cmap_cache->ref_count);
1822 _pango_fc_cmap_cache_unref (PangoFcCmapCache *cmap_cache)
1824 g_return_if_fail (cmap_cache->ref_count > 0);
1826 if (g_atomic_int_dec_and_test ((int *) &cmap_cache->ref_count))
1828 g_free (cmap_cache);
1833 _pango_fc_font_map_get_cmap_cache (PangoFcFontMap *fcfontmap,
1834 PangoFcFont *fcfont)
1836 PangoFcFontMapPrivate *priv;
1837 PangoFcFontFaceData *data;
1839 if (G_UNLIKELY (fcfontmap == NULL))
1842 if (G_UNLIKELY (!fcfont->font_pattern))
1845 priv = fcfontmap->priv;
1847 data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern);
1848 if (G_UNLIKELY (!data))
1851 if (G_UNLIKELY (data->cmap_cache == NULL))
1853 data->cmap_cache = g_new0 (PangoFcCmapCache, 1);
1854 data->cmap_cache->ref_count = 1;
1856 /* Make sure all cache entries are invalid initially */
1857 data->cmap_cache->entries[0].ch = 1; /* char 1 cannot happen in bucket 0 */
1860 return _pango_fc_cmap_cache_ref (data->cmap_cache);
1864 _pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap,
1865 PangoFcFont *fcfont)
1867 PangoFcFontFaceData *data;
1870 if (G_UNLIKELY (!fcfont->font_pattern))
1873 data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern);
1874 if (G_UNLIKELY (!data))
1877 if (G_UNLIKELY (data->coverage == NULL))
1880 * Pull the coverage out of the pattern, this
1881 * doesn't require loading the font
1883 if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
1886 data->coverage = _pango_fc_font_map_fc_to_coverage (charset);
1889 return pango_coverage_ref (data->coverage);
1893 * _pango_fc_font_map_fc_to_coverage:
1894 * @charset: #FcCharSet to convert to a #PangoCoverage object.
1896 * Convert the given #FcCharSet into a new #PangoCoverage object. The
1897 * caller is responsible for freeing the newly created object.
1902 _pango_fc_font_map_fc_to_coverage (FcCharSet *charset)
1904 PangoCoverage *coverage;
1906 FcChar32 map[FC_CHARSET_MAP_SIZE];
1910 * Convert an Fc CharSet into a pango coverage structure. Sure
1911 * would be nice to just use the Fc structure in place...
1913 coverage = pango_coverage_new ();
1914 for (ucs4 = FcCharSetFirstPage (charset, map, &pos);
1915 ucs4 != FC_CHARSET_DONE;
1916 ucs4 = FcCharSetNextPage (charset, map, &pos))
1918 for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
1920 FcChar32 bits = map[i];
1921 FcChar32 base = ucs4 + i * 32;
1927 pango_coverage_set (coverage, base + b, PANGO_COVERAGE_EXACT);
1935 /* Awful hack so Hangul Tone marks get rendered with the same
1936 * font and in the same run as other Hangul characters. If a font
1937 * covers the first composed Hangul glyph, then it is declared to cover
1938 * the Hangul tone marks. This hack probably needs to be formalized
1939 * by choosing fonts for scripts rather than individual code points.
1941 if (pango_coverage_get (coverage, 0xac00) == PANGO_COVERAGE_EXACT)
1943 pango_coverage_set (coverage, 0x302e, PANGO_COVERAGE_EXACT);
1944 pango_coverage_set (coverage, 0x302f, PANGO_COVERAGE_EXACT);
1951 * pango_fc_font_map_create_context:
1952 * @fcfontmap: a #PangoFcFontMap
1954 * Creates a new context for this fontmap. This function is intended
1955 * only for backend implementations deriving from #PangoFcFontmap;
1956 * it is possible that a backend will store additional information
1957 * needed for correct operation on the #PangoContext after calling
1960 * Return value: a new #PangoContext
1964 * Deprecated: 1.22: Use pango_font_map_create_context() instead.
1967 pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap)
1969 g_return_val_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap), NULL);
1971 return pango_font_map_create_context (PANGO_FONT_MAP (fcfontmap));
1975 shutdown_font (gpointer key,
1976 PangoFcFont *fcfont,
1977 PangoFcFontMap *fcfontmap)
1979 _pango_fc_font_shutdown (fcfont);
1981 _pango_fc_font_set_font_key (fcfont, NULL);
1982 pango_fc_font_key_free (key);
1986 * pango_fc_font_map_shutdown:
1987 * @fcfontmap: a #PangoFcFontmap
1989 * Clears all cached information for the fontmap and marks
1990 * all fonts open for the fontmap as dead. (See the shutdown()
1991 * virtual function of #PangoFcFont.) This function might be used
1992 * by a backend when the underlying windowing system for the font
1993 * map exits. This function is only intended to be called
1994 * only for backend implementations deriving from #PangoFcFontmap.
1999 pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap)
2001 PangoFcFontMapPrivate *priv = fcfontmap->priv;
2007 g_hash_table_foreach (priv->font_hash, (GHFunc) shutdown_font, fcfontmap);
2008 for (i = 0; i < priv->n_families; i++)
2009 priv->families[i]->fontmap = NULL;
2011 pango_fc_font_map_fini (fcfontmap);
2013 while (priv->findfuncs)
2015 PangoFcFindFuncInfo *info;
2016 info = priv->findfuncs->data;
2018 info->dnotify (info->user_data);
2020 g_slice_free (PangoFcFindFuncInfo, info);
2021 priv->findfuncs = g_slist_delete_link (priv->findfuncs, priv->findfuncs);
2024 priv->closed = TRUE;
2028 pango_fc_convert_weight_to_pango (int fc_weight)
2030 if (fc_weight <= (FC_WEIGHT_THIN + FC_WEIGHT_EXTRALIGHT) / 2)
2031 return PANGO_WEIGHT_THIN;
2032 else if (fc_weight <= (FC_WEIGHT_EXTRALIGHT + FC_WEIGHT_LIGHT) / 2)
2033 return PANGO_WEIGHT_ULTRALIGHT;
2034 else if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_BOOK) / 2)
2035 return PANGO_WEIGHT_LIGHT;
2036 else if (fc_weight <= (FC_WEIGHT_BOOK + FC_WEIGHT_REGULAR) / 2)
2037 return PANGO_WEIGHT_BOOK;
2038 else if (fc_weight <= (FC_WEIGHT_REGULAR + FC_WEIGHT_MEDIUM) / 2)
2039 return PANGO_WEIGHT_NORMAL;
2040 else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
2041 return PANGO_WEIGHT_MEDIUM;
2042 else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
2043 return PANGO_WEIGHT_SEMIBOLD;
2044 else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_EXTRABOLD) / 2)
2045 return PANGO_WEIGHT_BOLD;
2046 else if (fc_weight <= (FC_WEIGHT_EXTRABOLD + FC_WEIGHT_BLACK) / 2)
2047 return PANGO_WEIGHT_ULTRABOLD;
2048 else if (fc_weight <= (FC_WEIGHT_BLACK + FC_WEIGHT_EXTRABLACK) / 2)
2049 return PANGO_WEIGHT_HEAVY;
2051 return PANGO_WEIGHT_ULTRAHEAVY;
2055 pango_fc_convert_slant_to_pango (int fc_style)
2059 case FC_SLANT_ROMAN:
2060 return PANGO_STYLE_NORMAL;
2061 case FC_SLANT_ITALIC:
2062 return PANGO_STYLE_ITALIC;
2063 case FC_SLANT_OBLIQUE:
2064 return PANGO_STYLE_OBLIQUE;
2066 return PANGO_STYLE_NORMAL;
2072 pango_fc_convert_width_to_pango (int fc_stretch)
2076 case FC_WIDTH_NORMAL:
2077 return PANGO_STRETCH_NORMAL;
2078 case FC_WIDTH_ULTRACONDENSED:
2079 return PANGO_STRETCH_ULTRA_CONDENSED;
2080 case FC_WIDTH_EXTRACONDENSED:
2081 return PANGO_STRETCH_EXTRA_CONDENSED;
2082 case FC_WIDTH_CONDENSED:
2083 return PANGO_STRETCH_CONDENSED;
2084 case FC_WIDTH_SEMICONDENSED:
2085 return PANGO_STRETCH_SEMI_CONDENSED;
2086 case FC_WIDTH_SEMIEXPANDED:
2087 return PANGO_STRETCH_SEMI_EXPANDED;
2088 case FC_WIDTH_EXPANDED:
2089 return PANGO_STRETCH_EXPANDED;
2090 case FC_WIDTH_EXTRAEXPANDED:
2091 return PANGO_STRETCH_EXTRA_EXPANDED;
2092 case FC_WIDTH_ULTRAEXPANDED:
2093 return PANGO_STRETCH_ULTRA_EXPANDED;
2095 return PANGO_STRETCH_NORMAL;
2101 * pango_fc_font_description_from_pattern:
2102 * @pattern: a #FcPattern
2103 * @include_size: if %TRUE, the pattern will include the size from
2104 * the @pattern; otherwise the resulting pattern will be unsized.
2105 * (only %FC_SIZE is examined, not %FC_PIXEL_SIZE)
2107 * Creates a #PangoFontDescription that matches the specified
2108 * Fontconfig pattern as closely as possible. Many possible Fontconfig
2109 * pattern values, such as %FC_RASTERIZER or %FC_DPI, don't make sense in
2110 * the context of #PangoFontDescription, so will be ignored.
2112 * Return value: a new #PangoFontDescription. Free with
2113 * pango_font_description_free().
2117 PangoFontDescription *
2118 pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_size)
2120 PangoFontDescription *desc;
2123 PangoStretch stretch;
2125 PangoGravity gravity;
2131 desc = pango_font_description_new ();
2133 res = FcPatternGetString (pattern, FC_FAMILY, 0, (FcChar8 **) &s);
2134 g_assert (res == FcResultMatch);
2136 pango_font_description_set_family (desc, (gchar *)s);
2138 if (FcPatternGetInteger (pattern, FC_SLANT, 0, &i) == FcResultMatch)
2139 style = pango_fc_convert_slant_to_pango (i);
2141 style = PANGO_STYLE_NORMAL;
2143 pango_font_description_set_style (desc, style);
2145 if (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &i) == FcResultMatch)
2146 weight = pango_fc_convert_weight_to_pango (i);
2148 weight = PANGO_WEIGHT_NORMAL;
2150 pango_font_description_set_weight (desc, weight);
2153 if (FcPatternGetInteger (pattern, FC_WIDTH, 0, &i) == FcResultMatch)
2154 stretch = pango_fc_convert_width_to_pango (i);
2157 stretch = PANGO_STRETCH_NORMAL;
2159 pango_font_description_set_stretch (desc, stretch);
2161 pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
2163 if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
2164 pango_font_description_set_size (desc, size * PANGO_SCALE);
2166 /* gravity is a bit different. we don't want to set it if it was not set on
2168 if (FcPatternGetString (pattern, PANGO_FC_GRAVITY, 0, (FcChar8 **)&s) == FcResultMatch)
2170 GEnumValue *value = g_enum_get_value_by_nick (get_gravity_class (), (char *)s);
2171 gravity = value->value;
2173 pango_font_description_set_gravity (desc, gravity);
2183 static GObjectClass *pango_fc_face_parent_class = NULL;
2185 static PangoFontDescription *
2186 make_alias_description (PangoFcFamily *fcfamily,
2190 PangoFontDescription *desc = pango_font_description_new ();
2192 pango_font_description_set_family (desc, fcfamily->family_name);
2193 pango_font_description_set_style (desc, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
2194 pango_font_description_set_weight (desc, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
2199 static PangoFontDescription *
2200 pango_fc_face_describe (PangoFontFace *face)
2202 PangoFcFace *fcface = PANGO_FC_FACE (face);
2203 PangoFcFamily *fcfamily = fcface->family;
2204 PangoFontDescription *desc = NULL;
2206 FcPattern *match_pattern;
2207 FcPattern *result_pattern;
2209 if (G_UNLIKELY (!fcfamily))
2210 return pango_font_description_new ();
2214 if (strcmp (fcface->style, "Regular") == 0)
2215 return make_alias_description (fcfamily, FALSE, FALSE);
2216 else if (strcmp (fcface->style, "Bold") == 0)
2217 return make_alias_description (fcfamily, TRUE, FALSE);
2218 else if (strcmp (fcface->style, "Italic") == 0)
2219 return make_alias_description (fcfamily, FALSE, TRUE);
2220 else /* Bold Italic */
2221 return make_alias_description (fcfamily, TRUE, TRUE);
2224 match_pattern = FcPatternBuild (NULL,
2225 FC_FAMILY, FcTypeString, fcfamily->family_name,
2226 FC_STYLE, FcTypeString, fcface->style,
2229 g_assert (match_pattern);
2231 FcConfigSubstitute (NULL, match_pattern, FcMatchPattern);
2232 FcDefaultSubstitute (match_pattern);
2234 result_pattern = FcFontMatch (NULL, match_pattern, &res);
2237 desc = pango_fc_font_description_from_pattern (result_pattern, FALSE);
2238 FcPatternDestroy (result_pattern);
2241 FcPatternDestroy (match_pattern);
2247 pango_fc_face_get_face_name (PangoFontFace *face)
2249 PangoFcFace *fcface = PANGO_FC_FACE (face);
2251 return fcface->style;
2255 compare_ints (gconstpointer ap,
2270 pango_fc_face_list_sizes (PangoFontFace *face,
2274 PangoFcFace *fcface = PANGO_FC_FACE (face);
2277 FcObjectSet *objectset;
2281 if (G_UNLIKELY (!fcface->family || !fcface->family->fontmap))
2284 pattern = FcPatternCreate ();
2285 FcPatternAddString (pattern, FC_FAMILY, (FcChar8*)(void*)fcface->family->family_name);
2286 FcPatternAddString (pattern, FC_STYLE, (FcChar8*)(void*)fcface->style);
2288 objectset = FcObjectSetCreate ();
2289 FcObjectSetAdd (objectset, FC_PIXEL_SIZE);
2291 fontset = FcFontList (NULL, pattern, objectset);
2296 double size, dpi = -1.0;
2299 size_array = g_array_new (FALSE, FALSE, sizeof (int));
2301 for (i = 0; i < fontset->nfont; i++)
2303 if (FcPatternGetDouble (fontset->fonts[i], FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
2306 dpi = pango_fc_font_map_get_resolution (fcface->family->fontmap, NULL);
2308 size_i = (int) (PANGO_SCALE * size * 72.0 / dpi);
2309 g_array_append_val (size_array, size_i);
2313 g_array_sort (size_array, compare_ints);
2315 if (size_array->len == 0)
2320 g_array_free (size_array, TRUE);
2324 *n_sizes = size_array->len;
2327 *sizes = (int *) size_array->data;
2328 g_array_free (size_array, FALSE);
2331 g_array_free (size_array, TRUE);
2334 FcFontSetDestroy (fontset);
2343 FcPatternDestroy (pattern);
2344 FcObjectSetDestroy (objectset);
2348 pango_fc_face_is_synthesized (PangoFontFace *face)
2350 PangoFcFace *fcface = PANGO_FC_FACE (face);
2352 return fcface->fake;
2356 pango_fc_face_finalize (GObject *object)
2358 PangoFcFace *fcface = PANGO_FC_FACE (object);
2360 g_free (fcface->style);
2362 pango_fc_face_parent_class->finalize (object);
2365 typedef PangoFontFaceClass PangoFcFaceClass;
2368 pango_fc_face_class_init (PangoFcFaceClass *class)
2370 GObjectClass *object_class = G_OBJECT_CLASS (class);
2372 pango_fc_face_parent_class = g_type_class_peek_parent (class);
2373 object_class->finalize = pango_fc_face_finalize;
2375 class->describe = pango_fc_face_describe;
2376 class->get_face_name = pango_fc_face_get_face_name;
2377 class->list_sizes = pango_fc_face_list_sizes;
2378 class->is_synthesized = pango_fc_face_is_synthesized;
2381 static PANGO_DEFINE_TYPE (PangoFcFace, pango_fc_face,
2382 pango_fc_face_class_init, NULL,
2383 PANGO_TYPE_FONT_FACE)
2389 static GObjectClass *pango_fc_family_parent_class = NULL;
2391 static PangoFcFace *
2392 create_face (PangoFcFamily *fcfamily,
2396 PangoFcFace *face = g_object_new (PANGO_FC_TYPE_FACE, NULL);
2397 face->style = g_strdup (style);
2398 face->family = fcfamily;
2405 pango_fc_family_list_faces (PangoFontFamily *family,
2406 PangoFontFace ***faces,
2409 PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
2410 PangoFcFontMap *fcfontmap = fcfamily->fontmap;
2411 PangoFcFontMapPrivate *priv;
2415 if (G_UNLIKELY (!fcfontmap))
2418 priv = fcfontmap->priv;
2420 if (fcfamily->n_faces < 0)
2425 if (is_alias_family (fcfamily->family_name) || priv->closed)
2427 fcfamily->n_faces = 4;
2428 fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
2431 fcfamily->faces[i++] = create_face (fcfamily, "Regular", TRUE);
2432 fcfamily->faces[i++] = create_face (fcfamily, "Bold", TRUE);
2433 fcfamily->faces[i++] = create_face (fcfamily, "Italic", TRUE);
2434 fcfamily->faces[i++] = create_face (fcfamily, "Bold Italic", TRUE);
2438 FcObjectSet *os = FcObjectSetBuild (FC_STYLE, FC_WEIGHT, FC_SLANT, NULL);
2439 FcPattern *pat = FcPatternBuild (NULL,
2440 FC_FAMILY, FcTypeString, fcfamily->family_name,
2449 /* Regular, Italic, Bold, Bold Italic */
2450 gboolean has_face [4] = { FALSE, FALSE, FALSE, FALSE };
2451 PangoFcFace **faces;
2454 fontset = FcFontList (NULL, pat, os);
2456 FcPatternDestroy (pat);
2457 FcObjectSetDestroy (os);
2459 /* at most we have 3 additional artifical faces */
2460 faces = g_new (PangoFcFace *, fontset->nfont + 3);
2462 for (i = 0; i < fontset->nfont; i++)
2464 const char *style, *font_style = NULL;
2467 if (FcPatternGetInteger(fontset->fonts[i], FC_WEIGHT, 0, &weight) != FcResultMatch)
2468 weight = FC_WEIGHT_MEDIUM;
2470 if (FcPatternGetInteger(fontset->fonts[i], FC_SLANT, 0, &slant) != FcResultMatch)
2471 slant = FC_SLANT_ROMAN;
2473 if (FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, (FcChar8 **)(void*)&font_style) != FcResultMatch)
2476 if (weight <= FC_WEIGHT_MEDIUM)
2478 if (slant == FC_SLANT_ROMAN)
2480 has_face[REGULAR] = TRUE;
2485 has_face[ITALIC] = TRUE;
2491 if (slant == FC_SLANT_ROMAN)
2493 has_face[BOLD] = TRUE;
2498 has_face[BOLD_ITALIC] = TRUE;
2499 style = "Bold Italic";
2505 faces[num++] = create_face (fcfamily, font_style, FALSE);
2508 if (has_face[REGULAR])
2510 if (!has_face[ITALIC])
2511 faces[num++] = create_face (fcfamily, "Italic", TRUE);
2512 if (!has_face[BOLD])
2513 faces[num++] = create_face (fcfamily, "Bold", TRUE);
2516 if ((has_face[REGULAR] || has_face[ITALIC] || has_face[BOLD]) && !has_face[BOLD_ITALIC])
2517 faces[num++] = create_face (fcfamily, "Bold Italic", TRUE);
2519 faces = g_renew (PangoFcFace *, faces, num);
2521 fcfamily->n_faces = num;
2522 fcfamily->faces = faces;
2524 FcFontSetDestroy (fontset);
2529 *n_faces = fcfamily->n_faces;
2532 *faces = g_memdup (fcfamily->faces, fcfamily->n_faces * sizeof (PangoFontFace *));
2536 pango_fc_family_get_name (PangoFontFamily *family)
2538 PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
2540 return fcfamily->family_name;
2544 pango_fc_family_is_monospace (PangoFontFamily *family)
2546 PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
2548 return fcfamily->spacing == FC_MONO ||
2550 fcfamily->spacing == FC_DUAL ||
2552 fcfamily->spacing == FC_CHARCELL;
2556 pango_fc_family_finalize (GObject *object)
2559 PangoFcFamily *fcfamily = PANGO_FC_FAMILY (object);
2561 g_free (fcfamily->family_name);
2563 for (i = 0; i < fcfamily->n_faces; i++)
2565 fcfamily->faces[i]->family = NULL;
2566 g_object_unref (fcfamily->faces[i]);
2568 g_free (fcfamily->faces);
2570 pango_fc_family_parent_class->finalize (object);
2573 typedef PangoFontFamilyClass PangoFcFamilyClass;
2576 pango_fc_family_class_init (PangoFcFamilyClass *class)
2578 GObjectClass *object_class = G_OBJECT_CLASS (class);
2580 pango_fc_family_parent_class = g_type_class_peek_parent (class);
2581 object_class->finalize = pango_fc_family_finalize;
2583 class->list_faces = pango_fc_family_list_faces;
2584 class->get_name = pango_fc_family_get_name;
2585 class->is_monospace = pango_fc_family_is_monospace;
2589 pango_fc_family_init (PangoFcFamily *fcfamily)
2591 fcfamily->n_faces = -1;
2594 static PANGO_DEFINE_TYPE (PangoFcFamily, pango_fc_family,
2595 pango_fc_family_class_init, pango_fc_family_init,
2596 PANGO_TYPE_FONT_FAMILY)