1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "gretl.h"
21 #include "fontfilter.h"
22
23 #define FONT_DEBUG 0
24
25 static GtkWidget *font_test_widget;
26 static PangoContext *font_test_context;
27 static PangoLanguage *font_test_lang;
28
gretl_font_filter_init(void)29 int gretl_font_filter_init (void)
30 {
31 font_test_widget = gtk_label_new(NULL);
32 font_test_context = gtk_widget_get_pango_context(font_test_widget);
33
34 if (font_test_context == NULL) {
35 gtk_widget_destroy(font_test_widget);
36 font_test_widget = NULL;
37 return 1;
38 }
39
40 font_test_lang = pango_language_from_string("eng");
41 if (font_test_lang == NULL) {
42 gretl_font_filter_cleanup();
43 return 1;
44 }
45
46 return 0;
47 }
48
gretl_font_filter_cleanup(void)49 void gretl_font_filter_cleanup (void)
50 {
51 if (font_test_context != NULL) {
52 g_object_unref(G_OBJECT(font_test_context));
53 font_test_context = NULL;
54 }
55 if (font_test_widget != NULL) {
56 gtk_widget_destroy(font_test_widget);
57 font_test_widget = NULL;
58 }
59 }
60
61 enum {
62 HACK_LATIN_FONT = 1 << 0,
63 HACK_MONO_FONT = 1 << 1,
64 HACK_WEIRD_FONT = 1 << 2
65 };
66
67 /* We test a font for "latin text" compatibility, via the heuristic
68 of seeing if it contains the letters 'i' and 'W' in English. Given the
69 latin text characteristic, we then see if the font is monospaced
70 using pango_font_family_is_monospace().
71 */
72
get_font_characteristics(PangoFontFamily * family,PangoFontDescription * desc)73 static int get_font_characteristics (PangoFontFamily *family,
74 PangoFontDescription *desc)
75 {
76 PangoFont *font;
77 int ret = 0;
78
79 font = pango_context_load_font(font_test_context, desc);
80
81 if (font != NULL) {
82 PangoCoverage *coverage;
83
84 coverage = pango_font_get_coverage(font, font_test_lang);
85 if (coverage != NULL) {
86 if (pango_coverage_get(coverage, 'i') == PANGO_COVERAGE_EXACT &&
87 pango_coverage_get(coverage, 'W') == PANGO_COVERAGE_EXACT) {
88 ret = HACK_LATIN_FONT;
89 if (pango_font_family_is_monospace(family)) {
90 ret |= HACK_MONO_FONT;
91 }
92 }
93 pango_coverage_unref(coverage);
94 }
95 g_object_unref(font);
96 }
97
98 #if FONT_DEBUG
99 fprintf(stderr, " latin %s, monospaced %s\n",
100 (ret & HACK_LATIN_FONT)? "yes" : "no",
101 (ret & HACK_MONO_FONT)? "yes" : "no");
102 #endif
103
104 return ret;
105 }
106
font_progress_bar(int i,int nf)107 static void font_progress_bar (int i, int nf)
108 {
109 static int (*show_progress) (double, double, int) = NULL;
110 static int show = 1;
111
112 if (show && show_progress == NULL) {
113 show_progress = gui_get_plugin_function("show_progress");
114 if (show_progress == NULL) {
115 show = 0;
116 } else {
117 (*show_progress)(0, nf, SP_FONT_INIT);
118 }
119 }
120
121 if (show) {
122 if (i == nf - 1) {
123 (*show_progress)(0, nf, SP_FINISH);
124 show = 0;
125 } else if (i > 0) {
126 (*show_progress)(1, nf, SP_NONE);
127 }
128 }
129 }
130
131 #define weird_font(s) (strstr(s, "arioso") || \
132 strstr(s, "dings") || \
133 strstr(s, "ancery"))
134
135 /* If we're on the first run, check the font's characteristics and
136 cache the info. Otherwise just read off the information we cached
137 previously. In either case, return non-zero iff the font validates
138 in respect of the criterion in @filter.
139 */
140
validate_font_family(PangoFontFamily * family,const gchar * famname,gint i,gint nf,gint filter,gint * err)141 int validate_font_family (PangoFontFamily *family,
142 const gchar *famname,
143 gint i, gint nf,
144 gint filter, gint *err)
145 {
146 static char *fcache;
147 static int build_cache;
148 int ret;
149
150 if (i >= nf) {
151 fprintf(stderr, "validate_font_family: got excess font!\n");
152 return 0;
153 }
154
155 if (fcache == NULL) {
156 fcache = calloc(nf, 1);
157 if (fcache == NULL) {
158 *err = 1;
159 return 0;
160 }
161 build_cache = 1;
162 gretl_font_filter_init();
163 }
164
165 if (build_cache) {
166 #if FONT_DEBUG
167 fprintf(stderr, "Checking font family %d, '%s'\n", i, famname);
168 #endif
169 font_progress_bar(i, nf);
170 if (weird_font(famname)) {
171 fcache[i] = HACK_WEIRD_FONT;
172 } else {
173 gchar *fontname = g_strdup_printf("%s 10", famname);
174 PangoFontDescription *desc =
175 pango_font_description_from_string(fontname);
176
177 if (desc != NULL) {
178 fcache[i] = get_font_characteristics(family, desc);
179 pango_font_description_free(desc);
180 }
181 g_free(fontname);
182 }
183 }
184
185 if (build_cache && i == nf - 1) {
186 gretl_font_filter_cleanup();
187 build_cache = 0;
188 }
189
190 if (filter == FONT_FILTER_LATIN) {
191 ret = fcache[i] & HACK_LATIN_FONT;
192 } else if (filter == FONT_FILTER_LATIN_MONO) {
193 ret = fcache[i] & HACK_MONO_FONT;
194 } else {
195 ret = !(fcache[i] & HACK_WEIRD_FONT);
196 }
197
198 return ret;
199 }
200
validate_single_font(const PangoFontFamily * family,gint filter)201 int validate_single_font (const PangoFontFamily *family,
202 gint filter)
203 {
204 const gchar *famname =
205 pango_font_family_get_name((PangoFontFamily *) family);
206 int ret, fc = 0;
207
208 #if FONT_DEBUG
209 fprintf(stderr, "Checking font '%s'\n", famname);
210 #endif
211
212 if (weird_font(famname)) {
213 fc = HACK_WEIRD_FONT;
214 } else {
215 gchar *font = g_strdup_printf("%s 10", famname);
216 PangoFontDescription *desc = pango_font_description_from_string(font);
217
218 if (desc != NULL) {
219 fc = get_font_characteristics((PangoFontFamily *) family, desc);
220 pango_font_description_free(desc);
221 }
222 g_free(font);
223 }
224
225
226 if (filter == FONT_FILTER_LATIN) {
227 ret = fc & HACK_LATIN_FONT;
228 } else if (filter == FONT_FILTER_LATIN_MONO) {
229 ret = fc & HACK_MONO_FONT;
230 } else {
231 ret = !(fc & HACK_WEIRD_FONT);
232 }
233
234 return ret;
235 }
236