[pango/simple-fontmap: 18/37] Add some useful face api




commit 82c4435f2da58f4f4da72de8ad7eab6f5db5f6a5
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Dec 30 12:26:06 2021 -0500

    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.

 pango/fonts.c              | 90 ++++++++++++++++++++++++++++++++++++++--------
 pango/pango-font-private.h | 14 +++++++-
 pango/pango-font.c         |  0
 pango/pango-font.h         |  8 +++++
 pango/pangofc-font.c       | 19 ----------
 pango/pangofc-fontmap.c    | 53 ++++++++++++++++++++++++---
 pango/pangofc-private.h    |  3 --
 tests/test-font.c          | 37 +++++++++++++++++++
 8 files changed, 181 insertions(+), 43 deletions(-)
---
diff --git a/pango/fonts.c b/pango/fonts.c
index 915f5b4a..2f4a0014 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
@@ -2774,6 +2784,56 @@ pango_font_face_is_variable (PangoFontFace *face)
   return PANGO_FONT_FACE_GET_CLASS (face)->is_variable (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`
@@ -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
diff --git a/pango/pango-font.h b/pango/pango-font.h
index 0a997f08..38cd7582 100644
--- a/pango/pango-font.h
+++ b/pango/pango-font.h
@@ -537,6 +537,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 5b0c4999..0b0ea41d 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 ();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]