]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/xfont_loader.C
Strip out another 180 #includes.
[lyx.git] / src / frontends / xforms / xfont_loader.C
1 /**
2  * \file xfont_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  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "xfont_loader.h"
14 #include "FontInfo.h"
15
16 #include "debug.h"
17 #include "lyxrc.h"      // lyxrc.font_*
18
19 #include "frontends/lyx_gui.h"
20
21 #include "support/filetools.h"
22 #include "support/systemcall.h"
23
24 #include "lyx_forms.h"
25
26 using namespace lyx::support;
27
28 using std::endl;
29
30
31 // The global fontloader
32 xfont_loader fontloader;
33
34
35 // Initialize font loader
36 xfont_loader::xfont_loader()
37 {
38         reset();
39 }
40
41
42 // Destroy font loader
43 xfont_loader::~xfont_loader()
44 {
45         unload();
46 }
47
48
49 // Update fonts after zoom, dpi, font names, or norm change
50 // For now, we just ditch all fonts we have. Later, we should
51 // reuse the ones that are already loaded.
52 void xfont_loader::update()
53 {
54         unload();
55 }
56
57
58 // Reset font loader
59 void xfont_loader::reset()
60 {
61         // Clear font infos, font structs and font metrics
62         for (int i1 = 0; i1 < LyXFont::NUM_FAMILIES; ++i1)
63                 for (int i2 = 0; i2 < 2; ++i2)
64                         for (int i3 = 0; i3 < 4; ++i3) {
65                                 fontinfo[i1][i2][i3] = 0;
66                                 for (int i4 = 0; i4<10; ++i4) {
67                                         fontstruct[i1][i2][i3][i4] = 0;
68                                 }
69                         }
70 }
71
72
73 // Unload all fonts
74 void xfont_loader::unload()
75 {
76         // Unload all fonts
77         for (int i1 = 0; i1 < LyXFont::NUM_FAMILIES; ++i1)
78                 for (int i2 = 0; i2 < 2; ++i2)
79                         for (int i3 = 0; i3 < 4; ++i3) {
80                                 if (fontinfo[i1][i2][i3]) {
81                                         delete fontinfo[i1][i2][i3];
82                                         fontinfo[i1][i2][i3] = 0;
83                                 }
84                                 for (int i4 = 0; i4 < 10; ++i4) {
85                                         if (fontstruct[i1][i2][i3][i4]) {
86                                                 XFreeFont(fl_get_display(), fontstruct[i1][i2][i3][i4]);
87                                                 fontstruct[i1][i2][i3][i4] = 0;
88                                         }
89                                 }
90                         }
91 }
92
93 namespace {
94
95 string const symbolPattern(LyXFont::FONT_FAMILY family)
96 {
97         switch (family) {
98         case LyXFont::SYMBOL_FAMILY:
99                 return "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific";
100
101         case LyXFont::CMR_FAMILY:
102                 return "-*-cmr10-medium-*-*-*-*-*-*-*-*-*-*-*";
103
104         case LyXFont::CMSY_FAMILY:
105                 return "-*-cmsy10-*-*-*-*-*-*-*-*-*-*-*-*";
106
107         case LyXFont::CMM_FAMILY:
108                 return "-*-cmmi10-medium-*-*-*-*-*-*-*-*-*-*-*";
109
110         case LyXFont::CMEX_FAMILY:
111                 return "-*-cmex10-*-*-*-*-*-*-*-*-*-*-*-*";
112
113         case LyXFont::MSA_FAMILY:
114                 return "-*-msam10-*-*-*-*-*-*-*-*-*-*-*-*";
115
116         case LyXFont::MSB_FAMILY:
117                 return "-*-msbm10-*-*-*-*-*-*-*-*-*-*-*-*";
118
119         case LyXFont::EUFRAK_FAMILY:
120                 return "-*-eufm10-medium-*-*-*-*-*-*-*-*-*-*-*";
121
122         case LyXFont::WASY_FAMILY:
123                 return "-*-wasy10-medium-*-*-*-*-*-*-*-*-*-*-*";
124
125         default:
126                 return string();
127         }
128 }
129
130 string const fontName(string const & family, string const & foundry)
131 {
132         if (foundry.empty() || foundry == "Xft")
133                 return "-*-"+family;
134         else
135                 return "-"+foundry+"-"+family;
136 }
137
138
139 bool addFontPath()
140 {
141         string const dir =  OnlyPath(LibFileSearch("xfonts", "fonts.dir"));
142         if (!dir.empty()) {
143                 int n;
144                 char ** p = XGetFontPath(fl_get_display(), &n);
145                 if (std::find(p, p + n, dir) != p + n)
146                         return false;
147                 lyxerr[Debug::FONT] << "Adding " << dir
148                                     << " to the font path." << endl;
149                 string const command = "xset fp+ " + dir;
150                 Systemcall s;
151                 if (!s.startscript(Systemcall::Wait, command))
152                         return true;
153                 lyxerr << "Unable to add " << dir << "to the font path."
154                        << endl;
155         }
156         return false;
157 }
158
159 } // namespace anon
160
161 // Get font info
162 /* Takes care of finding which font that can match the given request. Tries
163 different alternatives. */
164 void xfont_loader::getFontinfo(LyXFont::FONT_FAMILY family,
165                              LyXFont::FONT_SERIES series,
166                              LyXFont::FONT_SHAPE shape)
167 {
168         // Do we have the font info already?
169         if (fontinfo[family][series][shape] != 0)
170                 return;
171
172         // Special fonts
173         string pat = symbolPattern(family);
174         if (!pat.empty()) {
175                 static bool first_time = true;
176                 fontinfo[family][series][shape] = new FontInfo(pat);
177                 if (family != LyXFont::SYMBOL_FAMILY &&
178                     !fontinfo[family][series][shape]->exist() &&
179                     first_time) {
180                         first_time = false;
181                         if (addFontPath()) {
182                                 delete fontinfo[family][series][shape];
183                                 fontinfo[family][series][shape] = new FontInfo(pat);
184                         }
185                 }
186                 return;
187         }
188
189
190         // Normal font. Let's search for an existing name that matches.
191         string ffamily;
192         string fseries;
193         string fshape;
194         string norm = lyxrc.font_norm;
195         string fontname;
196
197         FontInfo * fi = new FontInfo;
198         fontinfo[family][series][shape] = fi;
199
200         for (int cfam = 0; cfam < 2; ++cfam) {
201                 // Determine family name
202                 switch (family) {
203                 case LyXFont::ROMAN_FAMILY:
204                         switch (cfam) {
205                         case 0: ffamily = fontName(lyxrc.roman_font_name,
206                                                    lyxrc.roman_font_foundry);
207                                 break;
208                         case 1: ffamily = "-*-times";
209                         default: cfam = 100;
210                         }
211                         break;
212                 case LyXFont::SANS_FAMILY:
213                         switch (cfam) {
214                         case 0: ffamily = fontName(lyxrc.sans_font_name,
215                                                    lyxrc.sans_font_foundry);
216                                 break;
217                         case 1: ffamily = "-*-helvetica";
218                         default: cfam = 100;
219                         }
220                         break;
221                 case LyXFont::TYPEWRITER_FAMILY:
222                         switch (cfam) {
223                         case 0: ffamily = fontName(lyxrc.typewriter_font_name,
224                                                    lyxrc.typewriter_font_foundry);
225                                 break;
226                         case 1: ffamily = "-*-courier";
227                         default: cfam = 100;
228                         }
229                         break;
230                 default: ;
231                 }
232
233                 for (int cser = 0; cser < 4; ++cser) {
234                         // Determine series name
235                         switch (series) {
236                         case LyXFont::MEDIUM_SERIES:
237                                 switch (cser) {
238                                 case 0: fseries = "-medium"; break;
239                                 case 1: fseries = "-book"; break;
240                                 case 2: fseries = "-light";
241                                 default: cser = 100;
242                                 }
243                                 break;
244                         case LyXFont::BOLD_SERIES:
245                                 switch (cser) {
246                                 case 0: fseries = "-bold"; break;
247                                 case 1: fseries = "-black"; break;
248                                 case 2: fseries = "-demi"; break;
249                                 case 3: fseries = "-demibold";
250                                 default: cser = 100;
251                                 }
252                                 break;
253                         default: ;
254                         }
255
256                         for (int csha = 0; csha < 2; ++csha) {
257                                 // Determine shape name
258                                 switch (shape) {
259                                 case LyXFont::UP_SHAPE:
260                                 case LyXFont::SMALLCAPS_SHAPE:
261                                         switch (csha) {
262                                         case 0: fshape = "-r";
263                                         default: csha = 100;
264                                         }
265                                         break;
266                                 case LyXFont::ITALIC_SHAPE:
267                                         switch (csha) {
268                                         case 0: fshape = "-i"; break;
269                                         case 1: fshape = "-o";
270                                         default: csha = 100;
271                                         }
272                                         break;
273                                 case LyXFont::SLANTED_SHAPE:
274                                         switch (csha) {
275                                         case 0: fshape = "-o"; break;
276                                         case 1: fshape = "-i";
277                                         default: csha = 100;
278                                         }
279                                         break;
280                                 default: ;
281                                 }
282                                 //
283                                 fontname = ffamily + fseries + fshape +
284                                            "-normal-*-*-*-*-*-*-*-" + norm;
285                                 fi->setPattern(fontname);
286                                 if (fi->exist()) {
287                                         return;
288                                 }
289                         }
290                 }
291         }
292 }
293
294
295 // A dummy fontstruct used when there is no gui.
296 namespace {
297
298 XFontStruct dummyXFontStruct;
299 bool dummyXFontStructisGood = false;
300
301 } // namespace anon
302
303 /// Do load font
304 XFontStruct * xfont_loader::doLoad(LyXFont::FONT_FAMILY family,
305                                 LyXFont::FONT_SERIES series,
306                                 LyXFont::FONT_SHAPE shape,
307                                 LyXFont::FONT_SIZE size)
308 {
309         if (!lyx_gui::use_gui) {
310                 if (!dummyXFontStructisGood) {
311                         // no character specific info
312                         dummyXFontStruct.per_char = 0;
313                         // unit ascent on character displays
314                         dummyXFontStruct.ascent = 1;
315                         // no descent on character displays
316                         dummyXFontStruct.descent = 0;
317                         dummyXFontStructisGood = true;
318                 }
319
320                 return &dummyXFontStruct;
321         }
322
323         getFontinfo(family, series, shape);
324         // FIXME! CHECK! Should we use 72.0 or 72.27? (Lgb)
325         int fsize = int((lyxrc.font_sizes[size] * lyxrc.dpi *
326                           (lyxrc.zoom/100.0)) / 72.27 + 0.5);
327
328         string font = fontinfo[family][series][shape]->getFontname(fsize);
329
330         if (font.empty()) {
331                 lyxerr << "No font matches request. Using 'fixed'." << endl;
332                 lyxerr << "Start LyX as 'lyx -dbg 515' to get more information." << endl;
333                 font = "fixed";
334         }
335
336         XFontStruct * fs = 0;
337
338         fs = XLoadQueryFont(fl_get_display(), font.c_str());
339
340         if (fs == 0) {
341                 if (font == "fixed") {
342                         lyxerr << "We're doomed. Can't get 'fixed' font." << endl;
343                 } else {
344                         lyxerr << "Could not get font '" << font
345                                 << "'. Using 'fixed'." << endl;
346                         fs = XLoadQueryFont(fl_get_display(), "fixed");
347                 }
348         } else if (lyxerr.debugging(Debug::FONT)) {
349                 // Tell user the font matching
350                 LyXFont f;
351                 f.setFamily(family);
352                 f.setSeries(series);
353                 f.setShape(shape);
354                 f.setSize(size);
355                 // The rest of the attributes are not interesting
356                 f.setEmph(LyXFont::INHERIT);
357                 f.setUnderbar(LyXFont::INHERIT);
358                 f.setNoun(LyXFont::INHERIT);
359                 f.setColor(LColor::inherit);
360                 lyxerr << "Font '" << f.stateText(0)
361                        << "' matched by\n" << font << endl;
362         }
363
364         fontstruct[family][series][shape][size] = fs;
365         return fs;
366 }
367
368
369 bool xfont_loader::available(LyXFont const & f)
370 {
371         if (!lyx_gui::use_gui)
372                 return false;
373
374         if (!fontinfo[f.family()][f.series()][f.realShape()])
375                 getFontinfo(f.family(), f.series(), f.realShape());
376         return fontinfo[f.family()][f.series()][f.realShape()]->exist();
377 }