summaryrefslogtreecommitdiff
path: root/tests/test-common.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-06-14 21:17:57 -0400
committerMatthias Clasen <mclasen@redhat.com>2022-06-22 13:57:26 -0400
commit031c610eb1ef240cc7a165416a02b48cff1070d7 (patch)
treeec9baf59e3eba5de0359048d088b4df83e5bafc0 /tests/test-common.c
parentaee6b79e1ecb061616fed1dfe539d802a2b681f6 (diff)
downloadpango-031c610eb1ef240cc7a165416a02b48cff1070d7.tar.gz
tests: Unify font loading code
We want full control over what gets loaded here, so avoid using fontconfig.
Diffstat (limited to 'tests/test-common.c')
-rw-r--r--tests/test-common.c280
1 files changed, 280 insertions, 0 deletions
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);
+ }
+}
+