diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-06-14 21:17:57 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-06-22 13:57:26 -0400 |
commit | 031c610eb1ef240cc7a165416a02b48cff1070d7 (patch) | |
tree | ec9baf59e3eba5de0359048d088b4df83e5bafc0 | |
parent | aee6b79e1ecb061616fed1dfe539d802a2b681f6 (diff) | |
download | pango-031c610eb1ef240cc7a165416a02b48cff1070d7.tar.gz |
tests: Unify font loading code
We want full control over what gets
loaded here, so avoid using fontconfig.
-rw-r--r-- | tests/test-break.c | 39 | ||||
-rw-r--r-- | tests/test-common.c | 280 | ||||
-rw-r--r-- | tests/test-common.h | 2 | ||||
-rw-r--r-- | 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); |