1 | #include <string.h> |
2 | #include <locale.h> |
3 | |
4 | #include <pango/pango.h> |
5 | #include <pango/pangocairo-fc.h> |
6 | #include <pango/pangofc-fontmap.h> |
7 | #include "test-common.h" |
8 | |
9 | static void |
10 | install_fonts (const char *dir) |
11 | { |
12 | FcConfig *config; |
13 | PangoFontMap *map; |
14 | char *path; |
15 | gsize len; |
16 | char *conf; |
17 | |
18 | map = g_object_new (PANGO_TYPE_CAIRO_FC_FONT_MAP, NULL); |
19 | |
20 | config = FcConfigCreate (); |
21 | |
22 | path = g_build_filename (first_element: dir, "fonts.conf" , NULL); |
23 | g_file_get_contents (filename: path, contents: &conf, length: &len, NULL); |
24 | |
25 | if (!FcConfigParseAndLoadFromMemory (config, buffer: (const FcChar8 *) conf, TRUE)) |
26 | g_error ("Failed to parse fontconfig configuration" ); |
27 | |
28 | g_free (mem: conf); |
29 | g_free (mem: path); |
30 | |
31 | FcConfigAppFontAddDir (config, dir: (const FcChar8 *) dir); |
32 | pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (map), fcconfig: config); |
33 | FcConfigDestroy (config); |
34 | |
35 | pango_cairo_font_map_set_default (PANGO_CAIRO_FONT_MAP (map)); |
36 | |
37 | g_object_unref (object: map); |
38 | } |
39 | |
40 | static gboolean |
41 | append_one (PangoFontset *fonts, |
42 | PangoFont *font, |
43 | gpointer data) |
44 | { |
45 | PangoFontDescription *desc; |
46 | GString *str = data; |
47 | char *s; |
48 | |
49 | desc = pango_font_describe (font); |
50 | s = pango_font_description_to_string (desc); |
51 | |
52 | g_string_append_printf (string: str, format: "%s\n" , s); |
53 | |
54 | g_free (mem: s); |
55 | pango_font_description_free (desc); |
56 | |
57 | return FALSE; |
58 | } |
59 | |
60 | static char * |
61 | list_fonts (const char *contents) |
62 | { |
63 | char *p, *s; |
64 | PangoFontDescription *desc; |
65 | PangoContext *context; |
66 | PangoFontset *fonts; |
67 | GString *str; |
68 | |
69 | p = strchr (s: contents, c: '\n'); |
70 | if (p) |
71 | s = g_strndup (str: contents, n: p - contents); |
72 | else |
73 | s = g_strdup (str: contents); |
74 | |
75 | desc = pango_font_description_from_string (str: s); |
76 | |
77 | context = pango_font_map_create_context (fontmap: pango_cairo_font_map_get_default ()); |
78 | fonts = pango_context_load_fontset (context, desc, language: pango_language_get_default ()); |
79 | |
80 | str = g_string_new (init: s); |
81 | g_string_append (string: str, val: "\n\n" ); |
82 | |
83 | pango_fontset_foreach (fontset: fonts, func: append_one, data: str); |
84 | |
85 | g_object_unref (object: fonts); |
86 | g_object_unref (object: context); |
87 | pango_font_description_free (desc); |
88 | |
89 | g_free (mem: s); |
90 | |
91 | return g_string_free (string: str, FALSE); |
92 | } |
93 | |
94 | static void |
95 | test_fontset (gconstpointer d) |
96 | { |
97 | const char *filename = d; |
98 | GError *error = NULL; |
99 | char *diff; |
100 | GBytes *bytes; |
101 | char *contents; |
102 | gsize length; |
103 | char *s; |
104 | GBytes *orig; |
105 | |
106 | if (!PANGO_IS_FC_FONT_MAP (pango_cairo_font_map_get_default ())) |
107 | { |
108 | g_test_skip (msg: "Not an fc fontmap. Skipping..." ); |
109 | return; |
110 | } |
111 | |
112 | char *old_locale = g_strdup (str: setlocale (LC_ALL, NULL)); |
113 | setlocale (LC_ALL, locale: "en_US.UTF-8" ); |
114 | if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "en_US" ) == NULL) |
115 | { |
116 | char *msg = g_strdup_printf (format: "Locale en_US.UTF-8 not available, skipping layout %s" , filename); |
117 | g_test_skip (msg); |
118 | g_free (mem: msg); |
119 | g_free (mem: old_locale); |
120 | return; |
121 | } |
122 | |
123 | g_file_get_contents (filename, contents: &contents, length: &length, error: &error); |
124 | g_assert_no_error (error); |
125 | |
126 | s = list_fonts (contents); |
127 | |
128 | orig = g_bytes_new_take (data: contents, size: length); |
129 | bytes = g_bytes_new_take (data: s, size: strlen (s: s)); |
130 | |
131 | diff = diff_bytes (b1: orig, b2: bytes, error: &error); |
132 | g_assert_no_error (error); |
133 | |
134 | g_bytes_unref (bytes); |
135 | g_bytes_unref (bytes: orig); |
136 | |
137 | setlocale (LC_ALL, locale: old_locale); |
138 | g_free (mem: old_locale); |
139 | |
140 | if (diff && diff[0]) |
141 | { |
142 | char **lines = g_strsplit (string: diff, delimiter: "\n" , max_tokens: -1); |
143 | const char *line; |
144 | int i = 0; |
145 | |
146 | g_test_message (format: "Contents don't match expected contents" ); |
147 | |
148 | for (line = lines[0]; line != NULL; line = lines[++i]) |
149 | g_test_message (format: "%s" , line); |
150 | |
151 | g_test_fail (); |
152 | g_strfreev (str_array: lines); |
153 | } |
154 | |
155 | g_free (mem: diff); |
156 | } |
157 | |
158 | int |
159 | main (int argc, char *argv[]) |
160 | { |
161 | GDir *dir; |
162 | GError *error = NULL; |
163 | char *opt_fonts = NULL; |
164 | const gchar *name; |
165 | char *path; |
166 | GOptionContext *option_context; |
167 | GOptionEntry entries[] = { |
168 | { "fonts" , 0, 0, G_OPTION_ARG_FILENAME, &opt_fonts, "Fonts to use" , "DIR" }, |
169 | { NULL, 0 }, |
170 | }; |
171 | |
172 | setlocale (LC_ALL, locale: "" ); |
173 | option_context = g_option_context_new (parameter_string: "" ); |
174 | g_option_context_add_main_entries (context: option_context, entries, NULL); |
175 | g_option_context_set_ignore_unknown_options (context: option_context, TRUE); |
176 | if (!g_option_context_parse (context: option_context, argc: &argc, argv: &argv, error: &error)) |
177 | { |
178 | g_error ("failed to parse options: %s" , error->message); |
179 | return 1; |
180 | } |
181 | g_option_context_free (context: option_context); |
182 | |
183 | if (opt_fonts) |
184 | { |
185 | install_fonts (dir: opt_fonts); |
186 | g_free (mem: opt_fonts); |
187 | } |
188 | |
189 | /* allow to easily generate expected output for new test cases */ |
190 | if (argc > 1 && argv[1][0] != '-') |
191 | { |
192 | char *contents; |
193 | gsize length; |
194 | GError *error = NULL; |
195 | char *s; |
196 | |
197 | g_file_get_contents (filename: argv[1], contents: &contents, length: &length, error: &error); |
198 | g_assert_no_error (error); |
199 | |
200 | s = list_fonts (contents); |
201 | |
202 | g_print (format: "%s" , s); |
203 | |
204 | g_free (mem: s); |
205 | g_free (mem: contents); |
206 | |
207 | return 0; |
208 | } |
209 | |
210 | g_test_init (argc: &argc, argv: &argv, NULL); |
211 | |
212 | if (!opt_fonts) |
213 | { |
214 | path = g_test_build_filename (file_type: G_TEST_DIST, first_path: "fonts" , NULL); |
215 | install_fonts (dir: path); |
216 | g_free (mem: path); |
217 | } |
218 | |
219 | path = g_test_build_filename (file_type: G_TEST_DIST, first_path: "fontsets" , NULL); |
220 | dir = g_dir_open (path, flags: 0, error: &error); |
221 | g_free (mem: path); |
222 | g_assert_no_error (error); |
223 | while ((name = g_dir_read_name (dir)) != NULL) |
224 | { |
225 | path = g_strdup_printf (format: "/fontsets/%s" , name); |
226 | g_test_add_data_func_full (testpath: path, test_data: g_test_build_filename (file_type: G_TEST_DIST, first_path: "fontsets" , name, NULL), |
227 | test_func: test_fontset, data_free_func: g_free); |
228 | g_free (mem: path); |
229 | } |
230 | g_dir_close (dir); |
231 | |
232 | return g_test_run (); |
233 | } |
234 | |