diff options
author | Matthias Clasen <mclasen@redhat.com> | 2021-12-30 12:26:06 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-01-28 09:03:03 -0500 |
commit | 41d718553a1358661e58ca7915b59f958e780600 (patch) | |
tree | e34ff101c64fc93aa789e0e2f573fcdc7c10a867 | |
parent | 0c5b714c17ef5efa6d8e19592cb30f0b9a608402 (diff) | |
download | pango-41d718553a1358661e58ca7915b59f958e780600.tar.gz |
Add some useful face api
Add pango_font_face_supports_language and pango_font_face_get_languages.
There is no particular reason to tie language information to fonts
instead of faces. This will be useful for the font chooser.
Update the fontconfig implementation for these changes.
-rw-r--r-- | pango/fonts.c | 90 | ||||
-rw-r--r-- | pango/pango-font-private.h | 14 | ||||
-rw-r--r-- | pango/pango-font.c | 0 | ||||
-rw-r--r-- | pango/pango-font.h | 8 | ||||
-rw-r--r-- | pango/pangofc-font.c | 19 | ||||
-rw-r--r-- | pango/pangofc-fontmap.c | 53 | ||||
-rw-r--r-- | pango/pangofc-private.h | 3 | ||||
-rw-r--r-- | tests/test-font.c | 37 |
8 files changed, 181 insertions, 43 deletions
diff --git a/pango/fonts.c b/pango/fonts.c index 3afc8f27..0f566a79 100644 --- a/pango/fonts.c +++ b/pango/fonts.c @@ -1704,10 +1704,6 @@ typedef struct { hb_font_t *hb_font; } PangoFontPrivate; -#define PANGO_FONT_GET_CLASS_PRIVATE(font) ((PangoFontClassPrivate *) \ - g_type_class_get_private ((GTypeClass *) PANGO_FONT_GET_CLASS (font), \ - PANGO_TYPE_FONT)) - G_DEFINE_ABSTRACT_TYPE_WITH_CODE (PangoFont, pango_font, G_TYPE_OBJECT, G_ADD_PRIVATE (PangoFont) g_type_add_class_private (g_define_type_id, sizeof (PangoFontClassPrivate))) @@ -1723,12 +1719,6 @@ pango_font_finalize (GObject *object) G_OBJECT_CLASS (pango_font_parent_class)->finalize (object); } -static PangoLanguage ** -pango_font_default_get_languages (PangoFont *font) -{ - return NULL; -} - static gboolean pango_font_default_is_hinted (PangoFont *font) { @@ -1791,7 +1781,6 @@ pango_font_class_init (PangoFontClass *class G_GNUC_UNUSED) pclass = g_type_class_get_private ((GTypeClass *) class, PANGO_TYPE_FONT); - pclass->get_languages = pango_font_default_get_languages; pclass->is_hinted = pango_font_default_is_hinted; pclass->get_scale_factors = pango_font_default_get_scale_factors; pclass->has_char = pango_font_default_has_char; @@ -2582,7 +2571,8 @@ pango_font_family_is_variable (PangoFontFamily *family) * PangoFontFace */ -G_DEFINE_ABSTRACT_TYPE (PangoFontFace, pango_font_face, G_TYPE_OBJECT) +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (PangoFontFace, pango_font_face, G_TYPE_OBJECT, + g_type_add_class_private (g_define_type_id, sizeof (PangoFontFaceClassPrivate))) static gboolean pango_font_face_default_is_monospace (PangoFontFace *face) @@ -2596,11 +2586,31 @@ pango_font_face_default_is_variable (PangoFontFace *face) return pango_font_family_is_variable (pango_font_face_get_family (face)); } +static gboolean +pango_font_face_default_supports_language (PangoFontFace *face, + PangoLanguage *language) +{ + return TRUE; +} + +static PangoLanguage ** +pango_font_face_default_get_languages (PangoFontFace *face) +{ + return NULL; +} + static void pango_font_face_class_init (PangoFontFaceClass *class G_GNUC_UNUSED) { + PangoFontFaceClassPrivate *pclass; + class->is_monospace = pango_font_face_default_is_monospace; class->is_variable = pango_font_face_default_is_variable; + + pclass = g_type_class_get_private ((GTypeClass *) class, PANGO_TYPE_FONT_FACE); + + pclass->get_languages = pango_font_face_default_get_languages; + pclass->supports_language = pango_font_face_default_supports_language; } static void @@ -2775,6 +2785,56 @@ pango_font_face_is_variable (PangoFontFace *face) } /** + * pango_font_face_supports_language: + * @face: a `PangoFontFace` + * @language: a `PangoLanguage` + * + * Returns whether @face has all the glyphs necessary to write @language. + * + * Returns: `TRUE` if @face supports @language + * + * Since: 1.52 + */ +gboolean +pango_font_face_supports_language (PangoFontFace *face, + PangoLanguage *language) +{ + PangoFontFaceClassPrivate *pclass = PANGO_FONT_FACE_GET_CLASS_PRIVATE (face); + + g_return_val_if_fail (PANGO_IS_FONT_FACE (face), FALSE); + + return pclass->supports_language (face, language); +} + +/** + * pango_font_face_get_languages: + * @face: a `PangoFontFace` + * + * Returns the languages that are supported by @face. + * + * If the font backend does not provide this information, + * %NULL is returned. For the fontconfig backend, this + * corresponds to the FC_LANG member of the FcPattern. + * + * The returned array is only valid as long as the face + * and its fontmap are valid. + * + * Returns: (transfer none) (nullable) (array zero-terminated=1) (element-type PangoLanguage): + * an array of `PangoLanguage` + * + * Since: 1.52 + */ +PangoLanguage ** +pango_font_face_get_languages (PangoFontFace *face) +{ + PangoFontFaceClassPrivate *pclass = PANGO_FONT_FACE_GET_CLASS_PRIVATE (face); + + g_return_val_if_fail (PANGO_IS_FONT_FACE (face), FALSE); + + return pclass->get_languages (face); +} + +/** * pango_font_has_char: * @font: a `PangoFont` * @wc: a Unicode character @@ -2791,6 +2851,8 @@ pango_font_has_char (PangoFont *font, { PangoFontClassPrivate *pclass = PANGO_FONT_GET_CLASS_PRIVATE (font); + g_return_val_if_fail (PANGO_IS_FONT (font), FALSE); + return pclass->has_char (font, wc); } @@ -2841,9 +2903,7 @@ pango_font_get_features (PangoFont *font, PangoLanguage ** pango_font_get_languages (PangoFont *font) { - PangoFontClassPrivate *pclass = PANGO_FONT_GET_CLASS_PRIVATE (font); - - return pclass->get_languages (font); + return pango_font_face_get_languages (pango_font_get_face (font)); } /*< private > diff --git a/pango/pango-font-private.h b/pango/pango-font-private.h index f378ccdc..92647e86 100644 --- a/pango/pango-font-private.h +++ b/pango/pango-font-private.h @@ -34,8 +34,16 @@ PANGO_AVAILABLE_IN_ALL PangoFontMetrics *pango_font_metrics_new (void); typedef struct { - PangoLanguage ** (* get_languages) (PangoFont *font); + gboolean (* supports_language) (PangoFontFace *face, + PangoLanguage *language); + PangoLanguage ** (* get_languages) (PangoFontFace *face); +} PangoFontFaceClassPrivate; +#define PANGO_FONT_FACE_GET_CLASS_PRIVATE(font) ((PangoFontFaceClassPrivate *) \ + g_type_class_get_private ((GTypeClass *) PANGO_FONT_FACE_GET_CLASS (font), PANGO_TYPE_FONT_FACE)) + + +typedef struct { gboolean (* is_hinted) (PangoFont *font); void (* get_scale_factors) (PangoFont *font, @@ -50,6 +58,10 @@ typedef struct { int (* get_absolute_size) (PangoFont *font); } PangoFontClassPrivate; +#define PANGO_FONT_GET_CLASS_PRIVATE(font) ((PangoFontClassPrivate *) \ + g_type_class_get_private ((GTypeClass *) PANGO_FONT_GET_CLASS (font), PANGO_TYPE_FONT)) + + gboolean pango_font_is_hinted (PangoFont *font); void pango_font_get_scale_factors (PangoFont *font, double *x_scale, diff --git a/pango/pango-font.c b/pango/pango-font.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/pango/pango-font.c diff --git a/pango/pango-font.h b/pango/pango-font.h index d54dd820..1ba02b06 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -534,6 +534,14 @@ gboolean pango_font_face_is_monospace (PangoFontFace *face); PANGO_AVAILABLE_IN_1_52 gboolean pango_font_face_is_variable (PangoFontFace *face); +PANGO_AVAILABLE_IN_1_52 +gboolean pango_font_face_supports_language (PangoFontFace *face, + PangoLanguage *language); + +PANGO_AVAILABLE_IN_1_52 +PangoLanguage ** pango_font_face_get_languages (PangoFontFace *face); + + /* * PangoFont diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c index 9d555a37..40a6b68e 100644 --- a/pango/pangofc-font.c +++ b/pango/pangofc-font.c @@ -70,7 +70,6 @@ static void pango_fc_font_get_features (PangoFont *font, guint len, guint *num_features); static hb_font_t * pango_fc_font_create_hb_font (PangoFont *font); -static PangoLanguage ** _pango_fc_font_get_languages (PangoFont *font); static gboolean _pango_fc_font_is_hinted (PangoFont *font); static void _pango_fc_font_get_scale_factors (PangoFont *font, double *x_scale, @@ -109,7 +108,6 @@ pango_fc_font_class_init (PangoFcFontClass *class) pclass = g_type_class_get_private ((GTypeClass *) class, PANGO_TYPE_FONT); - pclass->get_languages = _pango_fc_font_get_languages; pclass->is_hinted = _pango_fc_font_is_hinted; pclass->get_scale_factors = _pango_fc_font_get_scale_factors; pclass->get_matrix = pango_fc_font_get_matrix; @@ -1093,23 +1091,6 @@ pango_fc_font_get_languages (PangoFcFont *font) return pango_font_get_languages (PANGO_FONT (font)); } -static PangoLanguage ** -_pango_fc_font_get_languages (PangoFont *font) -{ - PangoFcFont * fcfont = PANGO_FC_FONT (font); - PangoFcFontMap *fontmap; - PangoLanguage **languages; - - fontmap = g_weak_ref_get ((GWeakRef *) &fcfont->fontmap); - if (!fontmap) - return NULL; - - languages = _pango_fc_font_map_get_languages (fontmap, fcfont); - g_object_unref (fontmap); - - return languages; -} - /** * pango_fc_font_get_pattern: (skip) * @font: a `PangoFcFont` diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 4c39ea1f..3ed1b4d2 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -248,6 +248,10 @@ static PangoFontFace *pango_fc_font_map_get_face (PangoFontMap *fontmap, static void pango_fc_font_map_changed (PangoFontMap *fontmap); + +PangoLanguage **_pango_fc_font_map_get_languages (PangoFcFontMap *fcfontmap, + PangoFcFace *fcface); + static guint pango_fc_font_face_data_hash (PangoFcFontFaceData *key); static gboolean pango_fc_font_face_data_equal (PangoFcFontFaceData *key1, PangoFcFontFaceData *key2); @@ -1683,6 +1687,7 @@ ensure_families (PangoFcFontMap *fcfontmap) FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SPACING, FC_STYLE, FC_WEIGHT, FC_WIDTH, FC_SLANT, FC_VARIABLE, FC_FONTFORMAT, + FC_FILE, FC_INDEX, FC_LANG, NULL); FcPattern *pat = FcPatternCreate (); GHashTable *temp_family_hash; @@ -2052,9 +2057,10 @@ pango_fc_font_map_get_face (PangoFontMap *fontmap, family = pango_font_map_get_family (fontmap, s); res = FcPatternGetString (fcfont->font_pattern, FC_STYLE, 0, (FcChar8 **)(void*)&s); - g_assert (res == FcResultMatch); + if (res == FcResultMatch) + return pango_font_family_get_face (family, s); - return pango_font_family_get_face (family, s); + return PANGO_FONT_FACE (PANGO_FC_FAMILY (family)->faces[0]); } static void @@ -2593,14 +2599,18 @@ _pango_fc_font_map_fc_to_languages (FcLangSet *langset) return (PangoLanguage **) g_ptr_array_free (langs, FALSE); } + PangoLanguage ** _pango_fc_font_map_get_languages (PangoFcFontMap *fcfontmap, - PangoFcFont *fcfont) + PangoFcFace *fcface) { PangoFcFontFaceData *data; FcLangSet *langset; - data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); + if (!fcface->pattern) + return NULL; + + data = pango_fc_font_map_get_font_face_data (fcfontmap, fcface->pattern); if (G_UNLIKELY (!data)) return NULL; @@ -2610,7 +2620,7 @@ _pango_fc_font_map_get_languages (PangoFcFontMap *fcfontmap, * Pull the languages out of the pattern, this * doesn't require loading the font */ - if (FcPatternGetLangSet (fcfont->font_pattern, FC_LANG, 0, &langset) != FcResultMatch) + if (FcPatternGetLangSet (fcface->pattern, FC_LANG, 0, &langset) != FcResultMatch) return NULL; data->languages = _pango_fc_font_map_fc_to_languages (langset); @@ -3099,10 +3109,38 @@ pango_fc_face_init (PangoFcFace *self) { } +static gboolean +pango_fc_face_supports_language (PangoFontFace *face, + PangoLanguage *language) +{ + PangoFcFace *fcface = PANGO_FC_FACE (face); + FcLangSet *langs; + + if (!fcface->pattern) + return TRUE; + + if (FcPatternGetLangSet (fcface->pattern, FC_LANG, 0, &langs) != FcResultMatch) + return TRUE; + + return FcLangSetHasLang (langs, (FcChar8 *) pango_language_to_string (language)) != FcLangDifferentLang; +} + +static PangoLanguage ** +pango_fc_face_get_languages (PangoFontFace *face) +{ + PangoFcFace *fcface = PANGO_FC_FACE (face); + + if (!fcface->family->fontmap) + return NULL; + + return _pango_fc_font_map_get_languages (fcface->family->fontmap, fcface); +} + static void pango_fc_face_class_init (PangoFcFaceClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); + PangoFontFaceClassPrivate *pclass; object_class->finalize = pango_fc_face_finalize; @@ -3111,6 +3149,11 @@ pango_fc_face_class_init (PangoFcFaceClass *class) class->list_sizes = pango_fc_face_list_sizes; class->is_synthesized = pango_fc_face_is_synthesized; class->get_family = pango_fc_face_get_family; + + pclass = g_type_class_get_private ((GTypeClass *) class, PANGO_TYPE_FONT_FACE); + + pclass->supports_language = pango_fc_face_supports_language; + pclass->get_languages = pango_fc_face_get_languages; } diff --git a/pango/pangofc-private.h b/pango/pangofc-private.h index 7e216ed9..27b96df4 100644 --- a/pango/pangofc-private.h +++ b/pango/pangofc-private.h @@ -78,9 +78,6 @@ _PANGO_EXTERN PangoFontMetrics *pango_fc_font_create_base_metrics_for_context (PangoFcFont *font, PangoContext *context); -PangoLanguage **_pango_fc_font_map_get_languages (PangoFcFontMap *fcfontmap, - PangoFcFont *fcfont); - G_END_DECLS #endif /* __PANGOFC_PRIVATE_H__ */ diff --git a/tests/test-font.c b/tests/test-font.c index 2fa54cdf..8dd540f4 100644 --- a/tests/test-font.c +++ b/tests/test-font.c @@ -564,6 +564,42 @@ test_match (void) pango_font_description_free (desc2); } +static void +test_font_languages (void) +{ + PangoFontMap *fontmap; + PangoContext *context; + PangoFontDescription *desc; + PangoFont *font; + PangoFontFace *face; + PangoLanguage **languages; + +#ifdef HAVE_CARBON + desc = pango_font_description_from_string ("Helvetica 11"); +#else + desc = pango_font_description_from_string ("Cantarell 11"); +#endif + + fontmap = pango_cairo_font_map_get_default (); + context = pango_font_map_create_context (fontmap); + + font = pango_context_load_font (context, desc); + + languages = pango_font_get_languages (font); + g_assert_nonnull (languages); + g_assert_nonnull (languages[0]); + + face = pango_font_get_face (font); + languages = pango_font_face_get_languages (face); + g_assert_nonnull (languages); + g_assert_nonnull (languages[0]); + g_assert_true (pango_font_face_supports_language (face, languages[0])); + + g_object_unref (font); + pango_font_description_free (desc); + g_object_unref (context); +} + int main (int argc, char *argv[]) { @@ -589,6 +625,7 @@ main (int argc, char *argv[]) g_test_add_func ("/pango/font/models", test_font_models); g_test_add_func ("/pango/font/glyph-extents", test_glyph_extents); g_test_add_func ("/pango/font/font-metrics", test_font_metrics); + g_test_add_func ("/pango/font/languages", test_font_languages); return g_test_run (); } |