summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-12-30 12:26:06 -0500
committerMatthias Clasen <mclasen@redhat.com>2022-01-28 09:03:03 -0500
commit41d718553a1358661e58ca7915b59f958e780600 (patch)
treee34ff101c64fc93aa789e0e2f573fcdc7c10a867
parent0c5b714c17ef5efa6d8e19592cb30f0b9a608402 (diff)
downloadpango-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.c90
-rw-r--r--pango/pango-font-private.h14
-rw-r--r--pango/pango-font.c0
-rw-r--r--pango/pango-font.h8
-rw-r--r--pango/pangofc-font.c19
-rw-r--r--pango/pangofc-fontmap.c53
-rw-r--r--pango/pangofc-private.h3
-rw-r--r--tests/test-font.c37
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 ();
}