[pango/pango2: 113/168] tests: Unify font loading code




commit 8d4be1ac9307999a92ee0d9ab71e16fcbf339bbb
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Jun 14 21:17:57 2022 -0400

    tests: Unify font loading code
    
    We want full control over what gets
    loaded here, so avoid using fontconfig.

 tests/test-break.c  |  39 +-------
 tests/test-common.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-common.h |   2 +
 tests/test-layout.c |  42 +-------
 4 files changed, 290 insertions(+), 73 deletions(-)
---
diff --git a/tests/test-break.c b/tests/test-break.c
index f815fae2..42cd5346 100644
--- a/tests/test-break.c
+++ b/tests/test-break.c
@@ -29,12 +29,10 @@
 
 #include "config.h"
 #include <pango/pangocairo.h>
-#include <pango/pangofc-fontmap.h>
 #include "test-common.h"
 #include "validate-log-attrs.h"
 
 
-static PangoFontMap *map = NULL;
 static PangoContext *context;
 
 static gboolean opt_hex_chars;
@@ -360,31 +358,6 @@ test_break (gconstpointer d)
   g_free (expected_file);
 }
 
-static void
-install_fonts (const char *dir)
-{
-  FcConfig *config;
-  char *path;
-  gsize len;
-  char *conf;
-
-  config = FcConfigCreate ();
-
-  path = g_build_filename (dir, "fonts.conf", NULL);
-  g_file_get_contents (path, &conf, &len, NULL);
-
-  if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, TRUE))
-    g_error ("Failed to parse fontconfig configuration");
-
-  g_free (conf);
-  g_free (path);
-
-  FcConfigAppFontAddDir (config, (const FcChar8 *) dir);
-  map = PANGO_FONT_MAP (pango_fc_font_map_new ());
-  pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (map), config);
-  FcConfigDestroy (config);
-}
-
 int
 main (int argc, char *argv[])
 {
@@ -417,12 +390,10 @@ main (int argc, char *argv[])
   if (opt_fonts)
     {
       install_fonts (opt_fonts);
+      context = pango_font_map_create_context (pango_font_map_get_default ());
       g_free (opt_fonts);
     }
 
-  if (map)
-    context = pango_font_map_create_context (map);
-
   if (opt_legend)
     {
       g_print ("test-break uses the following symbols for log attrs\n\n");
@@ -455,14 +426,10 @@ main (int argc, char *argv[])
 
   if (!opt_fonts)
     {
-      path = g_test_build_filename (G_TEST_DIST, "fonts", NULL);
-      install_fonts (path);
-      g_free (path);
+      install_fonts (NULL);
+      context = pango_font_map_create_context (pango_font_map_get_default ());
     }
 
-  if (map)
-    context = pango_font_map_create_context (map);
-
   path = g_test_build_filename (G_TEST_DIST, "breaks", NULL);
   dir = g_dir_open (path, 0, &error);
   g_free (path);
diff --git a/tests/test-common.c b/tests/test-common.c
index 99733d3b..861a06d6 100644
--- a/tests/test-common.c
+++ b/tests/test-common.c
@@ -34,6 +34,8 @@
 #include <pango/pangocairo.h>
 #include "test-common.h"
 
+#include <hb-ot.h>
+
 char *
 diff_with_file (const char  *file,
                 char        *text,
@@ -234,3 +236,281 @@ get_script_name (GUnicodeScript s)
   return nick;
 }
 
+static void
+add_file (PangoFontMap *map,
+          const char   *path,
+          const char   *name)
+{
+  char *fullname;
+  hb_blob_t *blob;
+  hb_face_t *hbface;
+  PangoHbFace *face;
+
+  fullname = g_build_filename (path, name, NULL);
+
+  blob = hb_blob_create_from_file_or_fail (fullname);
+  if (!blob)
+    g_error ("No font data in %s", fullname);
+
+  g_free (fullname);
+
+  hbface = hb_face_create (blob, 0);
+  hb_face_make_immutable (hbface);
+
+  if (hb_ot_var_get_axis_count (hbface) == 0)
+    {
+      /* Add the default instance */
+      face = pango_hb_face_new_from_hb_face (hbface, -1, NULL, NULL);
+      pango_font_map_add_face (map, PANGO_FONT_FACE (face));
+      return;
+    }
+
+  /* Add the variable face */
+  face = pango_hb_face_new_from_hb_face (hbface, -2, "Variable", NULL);
+  pango_font_map_add_face (map, PANGO_FONT_FACE (face));
+
+  if (hb_ot_var_get_named_instance_count (hbface) > 0)
+    {
+      /* Add named instances */
+      for (int i = 0; i < hb_ot_var_get_named_instance_count (hbface); i++)
+        {
+          face = pango_hb_face_new_from_hb_face (hbface, i, NULL, NULL);
+          pango_font_map_add_face (map, PANGO_FONT_FACE (face));
+        }
+    }
+
+  hb_face_destroy (hbface);
+}
+
+static void
+add_generic_family (PangoFontMap *map,
+                    const char   *path,
+                    const char   *name)
+{
+  char *fullname;
+  char *contents;
+  gsize length;
+  char *basename;
+  char **families;
+  GError *error = NULL;
+  PangoGenericFamily *generic;
+
+  g_assert (g_str_has_suffix (name, ".generic"));
+
+  fullname = g_build_filename (path, name, NULL);
+
+  if (!g_file_get_contents (fullname, &contents, &length, &error))
+    g_error ("Failed to load %s: %s", fullname, error->message);
+
+  g_free (fullname);
+
+  basename = g_strdup (name);
+  basename[strlen (name) - strlen (".generic")] = '\0';
+
+  generic = pango_generic_family_new (basename);
+
+  families = g_strsplit (contents, "\n", -1);
+  for (int i = 0; families[i]; i++)
+    {
+      const char *name = families[i];
+      PangoFontFamily *family;
+
+      if (name[0] == '\0')
+        continue;
+
+      family = pango_font_map_get_family (map, name);
+      if (!family)
+        {
+          g_warning ("no such family: %s", name);
+          continue;
+        }
+
+      pango_generic_family_add_family (generic, family);
+    }
+
+  pango_font_map_add_family (map, PANGO_FONT_FAMILY (generic));
+
+  g_strfreev (families);
+  g_free (basename);
+  g_free (contents);
+}
+
+static void
+add_synthetic_faces (PangoFontMap *map,
+                     const char   *path,
+                     const char   *name)
+{
+  char *fullname;
+  char *contents;
+  GError *error = NULL;
+  gsize length;
+  char *basename;
+  PangoFontFamily *family;
+  gboolean make_italic;
+  PangoMatrix italic_matrix = { 1, 0.2, 0, 1, 0, 0 };
+  PangoHbFace *newface;
+  GSList *newfaces, *l;
+
+  g_assert (g_str_has_suffix (name, ".synthetic"));
+
+  fullname = g_build_filename (path, name, NULL);
+
+  if (!g_file_get_contents (fullname, &contents, &length, &error))
+    g_error ("Failed to load %s: %s", fullname, error->message);
+
+  g_free (fullname);
+
+  basename = g_strdup (name);
+  basename[strlen (name) - strlen (".synthetic")] = '\0';
+
+  family = pango_font_map_get_family (map, basename);
+  if (!family)
+    g_error ("Family %s not found", basename);
+
+  make_italic = strstr (contents, "Italic") != NULL;
+
+  newfaces = NULL;
+
+
+  for (int i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (family)); i++)
+    {
+      PangoHbFace *face = g_list_model_get_item (G_LIST_MODEL (family), i);
+
+      if (make_italic)
+        {
+          char *name;
+          PangoFontDescription *desc;
+
+          name = g_strconcat (pango_font_face_get_name (PANGO_FONT_FACE (face)),
+                              " Italic",
+                              NULL);
+          desc = pango_font_face_describe (PANGO_FONT_FACE (face));
+          pango_font_description_set_style (desc, PANGO_STYLE_ITALIC);
+          pango_font_description_unset_fields (desc, ~(PANGO_FONT_MASK_FAMILY|
+                                                       PANGO_FONT_MASK_STYLE|
+                                                       PANGO_FONT_MASK_STRETCH|
+                                                       PANGO_FONT_MASK_WEIGHT));
+          newface = pango_hb_face_new_synthetic (face, &italic_matrix, FALSE, name, desc);
+          newfaces = g_slist_prepend (newfaces, newface);
+
+          g_free (name);
+          pango_font_description_free (desc);
+        }
+
+      g_object_unref (face);
+    }
+
+
+  for (l = newfaces; l; l = l->next)
+    {
+      newface = l->data;
+      pango_font_map_add_face (map, PANGO_FONT_FACE (newface));
+    }
+
+  g_slist_free (newfaces);
+
+  g_free (basename);
+  g_free (contents);
+}
+
+void
+install_fonts (const char *path)
+{
+  PangoFontMap *map;
+  GDir *dir;
+  GError *error = NULL;
+  const char *name;
+  GPtrArray *generic;
+  GPtrArray *synthetic;
+  char *testpath = NULL;
+
+  map = pango_font_map_new ();
+
+  if (!path)
+    path = testpath = g_test_build_filename (G_TEST_DIST, "fonts", NULL);
+
+  dir = g_dir_open (path, 0, &error);
+
+  if (!dir)
+    g_error ("Failed to install fonts: %s", error->message);
+
+  generic = g_ptr_array_new ();
+  synthetic = g_ptr_array_new ();
+
+  while (TRUE)
+    {
+      name = g_dir_read_name (dir);
+      if (name == NULL)
+        break;
+
+      if (g_str_has_suffix (name, ".ttf") ||
+          g_str_has_suffix (name, ".otf"))
+        add_file (map, path, name);
+      else if (g_str_has_suffix (name, ".generic"))
+        g_ptr_array_add (generic, (gpointer) name);
+      else if (g_str_has_suffix (name, ".synthetic"))
+        g_ptr_array_add (synthetic, (gpointer) name);
+    }
+
+  /* Add generics and synthetics in a second path,
+   * so all families are already added.
+   */
+  for (int i = 0; i < generic->len; i++)
+    {
+      name = g_ptr_array_index (generic, i);
+      add_generic_family (map, path, name);
+    }
+  g_ptr_array_free (generic, TRUE);
+
+  for (int i = 0; i < synthetic->len; i++)
+    {
+      name = g_ptr_array_index (synthetic, i);
+      add_synthetic_faces (map, path, name);
+    }
+  g_ptr_array_free (synthetic, TRUE);
+
+
+  pango_font_map_set_default (map);
+
+  g_object_unref (map);
+  g_dir_close (dir);
+
+  g_free (testpath);
+}
+
+void
+dump_fonts (void)
+{
+  PangoFontMap *map;
+
+  map = pango_font_map_get_default ();
+
+  for (int i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (map)); i++)
+    {
+      PangoFontFamily *family = g_list_model_get_item (G_LIST_MODEL (map), i);
+
+      if (PANGO_IS_GENERIC_FAMILY (family))
+        {
+          g_print ("%s (generic)\n", pango_font_family_get_name (family));
+        }
+      else
+        {
+          g_print ("%s\n", pango_font_family_get_name (family));
+
+          for (int j = 0; j < g_list_model_get_n_items (G_LIST_MODEL (family)); j++)
+            {
+              PangoFontFace *face = g_list_model_get_item (G_LIST_MODEL (family), j);
+
+              g_print ("\t%s %s%s\n",
+                       pango_font_family_get_name (family),
+                       pango_font_face_get_name (face),
+                       pango_font_face_is_variable (face) ? " (variable)" : "");
+
+              g_object_unref (face);
+            }
+        }
+
+      g_object_unref (family);
+    }
+}
+
diff --git a/tests/test-common.h b/tests/test-common.h
index 6fe96133..d29db299 100644
--- a/tests/test-common.h
+++ b/tests/test-common.h
@@ -25,5 +25,7 @@ void print_attr_list (PangoAttrList  *attrs,
 
 const char *get_script_name (GUnicodeScript s);
 
+void install_fonts (const char *path);
+void dump_fonts (void);
 
 #endif
diff --git a/tests/test-layout.c b/tests/test-layout.c
index 8b7fe37f..f83fbc36 100644
--- a/tests/test-layout.c
+++ b/tests/test-layout.c
@@ -27,12 +27,10 @@
 #include <unistd.h>
 #endif
 
-#include "config.h"
 #include <pango/pangocairo.h>
-#include <pango/pangofc-fontmap.h>
 #include "test-common.h"
 
-static PangoFontMap *map = NULL;
+#include <hb-ot.h>
 
 static void
 test_layout (gconstpointer d)
@@ -62,7 +60,7 @@ test_layout (gconstpointer d)
   g_assert_no_error (error);
   orig = g_bytes_new_take (contents, length);
 
-  context = pango_font_map_create_context (map);
+  context = pango_font_map_create_context (pango_font_map_get_default ());
   layout = pango_layout_deserialize (context, orig, PANGO_LAYOUT_DESERIALIZE_CONTEXT, &error);
   g_assert_no_error (error);
 
@@ -99,33 +97,6 @@ test_layout (gconstpointer d)
   g_free (diff);
 }
 
-static void
-install_fonts (const char *dir)
-{
-  FcConfig *config;
-  char *path;
-  gsize len;
-  char *conf;
-
-  config = FcConfigCreate ();
-
-  path = g_build_filename (dir, "fonts.conf", NULL);
-  g_file_get_contents (path, &conf, &len, NULL);
-
-  if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, TRUE))
-    g_error ("Failed to parse fontconfig configuration");
-
-  g_free (conf);
-  g_free (path);
-
-  FcConfigAppFontAddDir (config, (const FcChar8 *) dir);
-
-  map = PANGO_FONT_MAP (pango_fc_font_map_new ());
-  pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (map), config);
-
-  FcConfigDestroy (config);
-}
-
 int
 main (int argc, char *argv[])
 {
@@ -144,6 +115,7 @@ main (int argc, char *argv[])
   option_context = g_option_context_new ("");
   g_option_context_add_main_entries (option_context, entries, NULL);
   g_option_context_set_ignore_unknown_options (option_context, TRUE);
+
   if (!g_option_context_parse (option_context, &argc, &argv, &error))
     {
       g_error ("failed to parse options: %s", error->message);
@@ -171,7 +143,7 @@ main (int argc, char *argv[])
       g_file_get_contents (argv[1], &contents, &length, &error);
       g_assert_no_error (error);
       orig = g_bytes_new_take (contents, length);
-      context = pango_font_map_create_context (map);
+      context = pango_font_map_create_context (pango_font_map_get_default ());
       layout = pango_layout_deserialize (context, orig, PANGO_LAYOUT_DESERIALIZE_CONTEXT, &error);
       g_assert_no_error (error);
 
@@ -192,11 +164,7 @@ main (int argc, char *argv[])
   g_test_init (&argc, &argv, NULL);
 
   if (!opt_fonts)
-    {
-      path = g_test_build_filename (G_TEST_DIST, "fonts", NULL);
-      install_fonts (path);
-      g_free (path);
-    }
+    install_fonts (NULL);
 
   path = g_test_build_filename (G_TEST_DIST, "layouts", NULL);
   dir = g_dir_open (path, 0, &error);


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