]> git.lyx.org Git - lyx.git/blob - src/frontends/qt2/qfont_loader.C
remove preamble dialog from the qt frontend
[lyx.git] / src / frontends / qt2 / qfont_loader.C
1 /**
2  * \file qfont_loader.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author John Levon
8  *
9  * Full author contact details are available in file CREDITS
10  */
11
12 #include <config.h>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include "qfont_loader.h"
19 #include "qt_helpers.h"
20 #include "debug.h"
21 #include "lyxrc.h"
22 #include "BufferView.h"
23 #include "qt_helpers.h"
24
25 #include <qglobal.h>
26 #include <qfontmetrics.h>
27 #include <qfontdatabase.h>
28 #include <qstringlist.h>
29 #include "support/lstrings.h"
30
31 #ifdef Q_WS_X11
32 #include <qwidget.h>
33 #include <X11/Xlib.h>
34 #include "support/systemcall.h"
35 #include "support/filetools.h"
36 #endif
37
38 using std::endl;
39
40
41 namespace {
42
43 void addFontPath()
44 {
45 #ifdef Q_WS_X11
46         string const dir =  OnlyPath(LibFileSearch("xfonts", "fonts.dir"));
47         if (!dir.empty()) {
48                 QWidget w;
49                 int n;
50                 char ** p = XGetFontPath(w.x11Display(), &n);
51                 if (std::find(p, p + n, dir) != p + n)
52                         return;
53                 lyxerr << "Adding " << dir << " to the font path.\n";
54                 string const command = "xset fp+ " + dir;
55                 Systemcall s;
56                 if (!s.startscript(Systemcall::Wait, command))
57                         return;
58                 lyxerr << "Unable to add font path.\n";
59         }
60 #endif
61 }
62
63
64 struct symbol_font {
65         LyXFont::FONT_FAMILY lyx_family;
66         string family;
67         string xlfd;
68 };
69
70 symbol_font symbol_fonts[] = {
71         { LyXFont::SYMBOL_FAMILY,
72                 "symbol",
73                 "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific" },
74
75         { LyXFont::CMR_FAMILY,
76                 "cmr10",
77                 "-*-cmr10-medium-*-*-*-*-*-*-*-*-*-*-*" },
78
79         { LyXFont::CMSY_FAMILY,
80                 "cmsy10",
81                 "-*-cmsy10-*-*-*-*-*-*-*-*-*-*-*-*" },
82
83         { LyXFont::CMM_FAMILY,
84                 "cmmi10",
85                 "-*-cmmi10-medium-*-*-*-*-*-*-*-*-*-*-*" },
86
87         { LyXFont::CMEX_FAMILY,
88                 "cmex10",
89                 "-*-cmex10-*-*-*-*-*-*-*-*-*-*-*-*" },
90
91         { LyXFont::MSA_FAMILY,
92                 "msam10",
93                 "-*-msam10-*-*-*-*-*-*-*-*-*-*-*-*" },
94
95         { LyXFont::MSB_FAMILY,
96                 "msbm10",
97                 "-*-msbm10-*-*-*-*-*-*-*-*-*-*-*-*" },
98
99         { LyXFont::EUFRAK_FAMILY,
100                 "eufm10",
101                 "-*-eufm10-medium-*-*-*-*-*-*-*-*-*-*-*" },
102
103         { LyXFont::WASY_FAMILY,
104                 "wasy10",
105                 "-*-wasy10-medium-*-*-*-*-*-*-*-*-*-*-*" }
106 };
107
108 size_t const nr_symbol_fonts = sizeof(symbol_fonts) / sizeof(symbol_font);
109
110
111 string getRawName(string const & family)
112 {
113         for (size_t i = 0; i < nr_symbol_fonts; ++i) {
114                 if (family == symbol_fonts[i].family)
115                         return symbol_fonts[i].xlfd;
116         }
117         lyxerr[Debug::FONT] << "BUG: family not found !" << endl;
118         return string();
119 }
120
121
122 string const symbolFamily(LyXFont::FONT_FAMILY family)
123 {
124         for (size_t i = 0; i < nr_symbol_fonts; ++i) {
125                 if (family == symbol_fonts[i].lyx_family)
126                         return symbol_fonts[i].family;
127         }
128         return string();
129 }
130
131
132 bool isSymbolFamily(LyXFont::FONT_FAMILY family)
133 {
134         return family >= LyXFont::SYMBOL_FAMILY &&
135                 family <= LyXFont::WASY_FAMILY;
136 }
137
138
139 QFont const getSymbolFont(string const & family)
140 {
141         lyxerr[Debug::FONT] << "Looking for font family "
142                 << family << " ... ";
143         string upper = family;
144         upper[0] = toupper(family[0]);
145
146         QFont font;
147         font.setFamily(toqstr(family));
148
149         // Note Qt lies about family, so we use rawName.
150         if (contains(fromqstr(font.rawName()), family)) {
151                 lyxerr[Debug::FONT] << " got it !" << endl;
152                 return font;
153         }
154
155         font.setFamily(toqstr(upper));
156
157         if (contains(fromqstr(font.rawName()), upper)) {
158                 lyxerr[Debug::FONT] << " got it (uppercase version) !" << endl;
159                 return font;
160         }
161
162         // A simple setFamily() fails on Qt 2
163
164         font.setRawName(toqstr(getRawName(family)));
165
166         if (contains(fromqstr(font.rawName()), family)) {
167                 lyxerr[Debug::FONT] << " got it (raw version) !" << endl;
168                 return font;
169         }
170
171         lyxerr[Debug::FONT] << " FAILED :-(" << endl;
172         return font;
173 }
174
175
176 bool isAvailable(LyXFont const & f)
177 {
178         static std::vector<bool> cache(LyXFont::NUM_FAMILIES, false);
179         static std::vector<bool> cache_initialized(LyXFont::NUM_FAMILIES, false);
180         static bool first_call = true;
181
182         LyXFont::FONT_FAMILY lyxfamily = f.family();
183         if (cache_initialized[lyxfamily])
184                 return cache[lyxfamily];
185         cache_initialized[lyxfamily] = true;
186
187         if (first_call && isSymbolFamily(lyxfamily)) {
188                 first_call = false;
189                 addFontPath();
190         }
191
192         string const tmp = symbolFamily(lyxfamily);
193
194         if (tmp.empty())
195                 return false;
196
197         QString const family(toqstr(tmp));
198
199         lyxerr[Debug::FONT] << "Family " << tmp
200                << " isAvailable ?";
201
202         QFontDatabase db;
203         // pass false for match-locale: LaTeX fonts
204         // do not have non-matching locale according
205         // to Qt 2
206         QStringList sl(db.families(false));
207
208         for (QStringList::Iterator it = sl.begin(); it != sl.end(); ++it) {
209                 // Case-insensitive for Cmmi10 vs. cmmi10
210                 if ((*it).lower().startsWith(family.lower())) {
211                         lyxerr[Debug::FONT]
212                                 << "found family "
213                                 << fromqstr(*it) << endl;
214                         cache[lyxfamily] = true;
215                         return true;
216                 }
217         }
218         lyxerr[Debug::FONT] << " no." << endl;
219         return false;
220 }
221
222
223 } // namespace anon
224
225
226 qfont_loader::qfont_loader()
227 {
228         for (int i1 = 0; i1 < LyXFont::NUM_FAMILIES; ++i1) {
229                 for (int i2 = 0; i2 < 2; ++i2) {
230                         for (int i3 = 0; i3 < 4; ++i3) {
231                                 for (int i4 = 0; i4 < 10; ++i4) {
232                                         fontinfo_[i1][i2][i3][i4] = 0;
233                                 }
234                         }
235                 }
236         }
237 }
238
239
240 qfont_loader::~qfont_loader()
241 {
242 }
243
244
245 void qfont_loader::update()
246 {
247         for (int i1 = 0; i1 < LyXFont::NUM_FAMILIES; ++i1) {
248                 for (int i2 = 0; i2 < 2; ++i2) {
249                         for (int i3 = 0; i3 < 4; ++i3) {
250                                 for (int i4 = 0; i4 < 10; ++i4) {
251                                         delete fontinfo_[i1][i2][i3][i4];
252                                         fontinfo_[i1][i2][i3][i4] = 0;
253                                 }
254                         }
255                 }
256         }
257 }
258
259
260 QFont const & qfont_loader::get(LyXFont const & f)
261 {
262         static bool first_call = true;
263
264         if (first_call && isSymbolFamily(f.family())) {
265                 first_call = false;
266                 addFontPath();
267         }
268
269         QFont const & ret(getfontinfo(f)->font);
270
271         return ret;
272 }
273
274
275 qfont_loader::font_info::font_info(LyXFont const & f)
276         : metrics(font)
277 {
278
279         string const pat = symbolFamily(f.family());
280         if (!pat.empty()) {
281                 font = getSymbolFont(pat);
282         } else {
283                 switch (f.family()) {
284                 case LyXFont::ROMAN_FAMILY:
285                         font.setFamily(toqstr(makeFontName(lyxrc.roman_font_name,
286                                                     lyxrc.roman_font_foundry)));
287                         break;
288                 case LyXFont::SANS_FAMILY:
289                         font.setFamily(toqstr(makeFontName(lyxrc.sans_font_name,
290                                                     lyxrc.sans_font_foundry)));
291                         break;
292                 case LyXFont::TYPEWRITER_FAMILY:
293                         font.setFamily(toqstr(makeFontName(lyxrc.typewriter_font_name,
294                                                     lyxrc.typewriter_font_foundry)));
295                         break;
296                 default:
297                         break;
298                 }
299         }
300
301         font.setPointSizeFloat(lyxrc.font_sizes[f.size()]
302                                * lyxrc.zoom / 100.0);
303
304         switch (f.series()) {
305                 case LyXFont::MEDIUM_SERIES:
306                         font.setWeight(QFont::Normal);
307                         break;
308                 case LyXFont::BOLD_SERIES:
309                         font.setWeight(QFont::Bold);
310                         break;
311                 default:
312                         break;
313         }
314
315         switch (f.realShape()) {
316                 case LyXFont::ITALIC_SHAPE:
317                 case LyXFont::SLANTED_SHAPE:
318                         font.setItalic(true);
319                         break;
320                 default:
321                         break;
322         }
323
324         if (lyxerr.debugging(Debug::FONT)) {
325                 lyxerr[Debug::FONT] << "Font '" << f.stateText(0)
326                         << "' matched by\n" << font.rawName() << endl;
327         }
328
329         lyxerr[Debug::FONT] << "The font has size: "
330                             << font.pointSizeFloat() << endl;
331
332         // Is this an exact match?
333         if (font.exactMatch()) {
334                 lyxerr[Debug::FONT] << "This font is an exact match" << endl;
335         } else {
336                 lyxerr[Debug::FONT] << "This font is NOT an exact match"
337                                     << endl;
338         }
339
340         lyxerr[Debug::FONT] << "XFLD: " << font.rawName() << endl;
341
342         metrics = QFontMetrics(font);
343 }
344
345
346 qfont_loader::font_info * qfont_loader::getfontinfo(LyXFont const & f)
347 {
348         if (!lyxrc.use_gui) {
349                 // FIXME
350         }
351
352         font_info * fi = fontinfo_[f.family()][f.series()][f.realShape()][f.size()];
353         if (fi)
354                 return fi;
355  
356         font_info * fi2 = new font_info(f);
357         fontinfo_[f.family()][f.series()][f.realShape()][f.size()] = fi2;
358         return fi2;
359 }
360
361
362 int qfont_loader::charwidth(LyXFont const & f, Uchar val)
363 {
364         font_info * fi = getfontinfo(f);
365
366         font_info::WidthCache::const_iterator cit = fi->widthcache.find(val);
367         if (cit != fi->widthcache.end())
368                 return cit->second;
369
370         int const w = fi->metrics.width(QChar(val));
371         fi->widthcache[val] = w;
372         return w;
373 }
374
375  
376 bool qfont_loader::available(LyXFont const & f)
377 {
378         if (!lyxrc.use_gui)
379                 return false;
380
381         return isAvailable(f);
382 }