]> git.lyx.org Git - lyx.git/blob - src/FontLoader.C
Fix crash when running lyx -dbg insets -e ...
[lyx.git] / src / FontLoader.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1997 Asger Alstrup
7  *           and the LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12 #include <cmath>        // fabs()
13
14 #ifdef __GNUG__
15 #pragma implementation "FontLoader.h"
16 #endif
17
18 #include FORMS_H_LOCATION
19 #include "FontLoader.h"
20 #include "FontInfo.h"
21 #include "gettext.h"
22 #include "debug.h"
23 #include "lyxrc.h"      // lyxrc.font_*
24 #include "BufferView.h"
25 #include "LyXView.h"
26 #include "frontends/GUIRunTime.h"
27
28 using std::endl;
29
30 extern BufferView * current_view;
31
32
33 // The global fontloader
34 FontLoader fontloader;
35
36
37 // Initialize font loader
38 FontLoader::FontLoader()
39 {
40         reset();
41 }
42
43
44 // Destroy font loader
45 FontLoader::~FontLoader()
46 {
47         unload();
48 }
49
50
51 // Update fonts after zoom, dpi, font names, or norm change
52 // For now, we just ditch all fonts we have. Later, we should
53 // reuse the ones that are already loaded.
54 void FontLoader::update()
55 {
56         unload();
57 }
58
59
60 // Reset font loader
61 void FontLoader::reset()
62 {
63         // Clear font infos, font structs and font metrics
64         for (int i1 = 0; i1 < 4; ++i1)
65                 for (int i2 = 0; i2 < 2; ++i2)
66                         for (int i3 = 0; i3 < 4; ++i3) {
67                                 fontinfo[i1][i2][i3] = 0;
68                                 for (int i4 = 0; i4<10; ++i4) {
69                                         fontstruct[i1][i2][i3][i4] = 0;
70                                 }
71                         }
72 }
73
74
75 // Unload all fonts
76 void FontLoader::unload() 
77 {
78         // Unload all fonts
79         for (int i1 = 0; i1 < 4; ++i1)
80                 for (int i2 = 0; i2 < 2; ++i2)
81                         for (int i3 = 0; i3 < 4; ++i3) {
82                                 if (fontinfo[i1][i2][i3]) {
83                                         delete fontinfo[i1][i2][i3];
84                                         fontinfo[i1][i2][i3] = 0;
85                                 }
86                                 for (int i4 = 0; i4 < 10; ++i4) {
87                                         if (fontstruct[i1][i2][i3][i4]) {
88                                                 XFreeFont(GUIRunTime::x11Display(), fontstruct[i1][i2][i3][i4]);
89                                                 fontstruct[i1][i2][i3][i4] = 0;
90                                         }
91                                 }
92                         }
93 }
94
95
96 // Get font info
97 /* Takes care of finding which font that can match the given request. Tries
98 different alternatives. */
99 void FontLoader::getFontinfo(LyXFont::FONT_FAMILY family, 
100                              LyXFont::FONT_SERIES series, 
101                              LyXFont::FONT_SHAPE shape)
102 {
103         // Do we have the font info already?
104         if (fontinfo[family][series][shape] != 0)
105                 return;
106
107         // Special code for the symbol family
108         if (family == LyXFont::SYMBOL_FAMILY){
109                 fontinfo[family][series][shape] = new FontInfo("-*-symbol-*");
110                 return;
111         }
112
113         // Normal font. Let's search for an existing name that matches.
114         string ffamily;
115         string fseries;
116         string fshape;
117         string norm = lyxrc.font_norm;
118         string fontname;
119
120         FontInfo * fi = new FontInfo();
121         fontinfo[family][series][shape] = fi;
122
123         for (int cfam = 0; cfam < 2; ++cfam) {
124                 // Determine family name
125                 switch (family) {
126                 case LyXFont::ROMAN_FAMILY:
127                         switch (cfam) {
128                         case 0: ffamily = lyxrc.roman_font_name; break;
129                         case 1: ffamily = "-*-times";
130                         default: cfam = 100;
131                         }
132                         break;
133                 case LyXFont::SANS_FAMILY:
134                         switch (cfam) {
135                         case 0: ffamily = lyxrc.sans_font_name; break;
136                         case 1: ffamily = "-*-helvetica";
137                         default: cfam = 100;
138                         }
139                         break;
140                 case LyXFont::TYPEWRITER_FAMILY:
141                         switch (cfam) {
142                         case 0: ffamily = lyxrc.typewriter_font_name; break;
143                         case 1: ffamily = "-*-courier";
144                         default: cfam = 100;
145                         }
146                         break;
147                 default: ;
148                 }
149
150                 for (int cser = 0; cser < 4; ++cser) {
151                         // Determine series name
152                         switch (series) {
153                         case LyXFont::MEDIUM_SERIES:
154                                 switch (cser) {
155                                 case 0: fseries = "-medium"; break;
156                                 case 1: fseries = "-book"; break;
157                                 case 2: fseries = "-light";
158                                 default: cser = 100;
159                                 }
160                                 break;
161                         case LyXFont::BOLD_SERIES:
162                                 switch (cser) {
163                                 case 0: fseries = "-bold"; break;
164                                 case 1: fseries = "-black"; break;
165                                 case 2: fseries = "-demi"; break;
166                                 case 3: fseries = "-demibold";
167                                 default: cser = 100;
168                                 }
169                                 break;
170                         default: ;
171                         }
172
173                         for (int csha = 0; csha < 2; ++csha) {
174                                 // Determine shape name
175                                 switch (shape) {
176                                 case LyXFont::UP_SHAPE:
177                                 case LyXFont::SMALLCAPS_SHAPE:
178                                         switch (csha) {
179                                         case 0: fshape = "-r";
180                                         default: csha = 100;
181                                         }
182                                         break;
183                                 case LyXFont::ITALIC_SHAPE:
184                                         switch (csha) {
185                                         case 0: fshape = "-i"; break;
186                                         case 1: fshape = "-o";
187                                         default: csha = 100;
188                                         }
189                                         break;
190                                 case LyXFont::SLANTED_SHAPE:
191                                         switch (csha) {
192                                         case 0: fshape = "-o"; break;
193                                         case 1: fshape = "-i";
194                                         default: csha = 100;
195                                         }
196                                         break;
197                                 default: ;
198                                 }
199                                 //
200                                 fontname = ffamily + fseries + fshape +
201                                            "-normal-*-*-*-*-*-*-*-" + norm;
202                                 fi->setPattern(fontname);
203                                 if (fi->exist()) {
204                                         return;
205                                 }
206                         }
207                 }
208         }
209 }
210
211
212 // A dummy fontstruct used when there is no gui.
213 namespace {
214
215 XFontStruct dummyXFontStruct;
216 bool dummyXFontStructisGood = false;
217
218 } // namespace anon
219
220 /// Do load font
221 XFontStruct * FontLoader::doLoad(LyXFont::FONT_FAMILY family, 
222                                 LyXFont::FONT_SERIES series, 
223                                 LyXFont::FONT_SHAPE shape, 
224                                 LyXFont::FONT_SIZE size)
225 {
226         if (!lyxrc.use_gui) {
227                 if (!dummyXFontStructisGood) {
228                         // no character specific info
229                         dummyXFontStruct.per_char = 0; 
230                         // unit ascent on character displays
231                         dummyXFontStruct.ascent = 1; 
232                         // no descent on character displays
233                         dummyXFontStruct.descent = 0; 
234                         dummyXFontStructisGood = true;
235                 }
236
237                 return &dummyXFontStruct;
238         }
239
240         getFontinfo(family, series, shape);
241         int fsize = int( (lyxrc.font_sizes[size] * lyxrc.dpi * 
242                           (lyxrc.zoom/100.0) ) / 72.27 + 0.5 );
243
244         string font = fontinfo[family][series][shape]->getFontname(fsize);
245
246         if (font.empty()) {
247                 lyxerr << "No font matches request. Using 'fixed'." << endl;
248                 lyxerr << "Start LyX as 'lyx -dbg 515' to get more information." << endl;
249                 font = "fixed";
250         }
251
252         XFontStruct * fs = 0;
253
254         current_view->owner()->messagePush(_("Loading font into X-Server..."));
255
256         fs = XLoadQueryFont(GUIRunTime::x11Display(), font.c_str());
257         
258         if (fs == 0) {
259                 if (font == "fixed") {
260                         lyxerr << "We're doomed. Can't get 'fixed' font." << endl;
261                 } else {
262                         lyxerr << "Could not get font. Using 'fixed'." << endl;
263                         fs = XLoadQueryFont(GUIRunTime::x11Display(), "fixed");
264                 }
265         } else if (lyxerr.debugging(Debug::FONT)) {
266                 // Tell user the font matching
267                 LyXFont f;
268                 f.setFamily(family);
269                 f.setSeries(series);
270                 f.setShape(shape);
271                 f.setSize(size);
272                 // The rest of the attributes are not interesting
273                 f.setEmph(LyXFont::INHERIT);
274                 f.setUnderbar(LyXFont::INHERIT);
275                 f.setNoun(LyXFont::INHERIT);
276 #ifndef NO_LATEX
277                 f.setLatex(LyXFont::INHERIT);
278 #endif
279                 f.setColor(LColor::inherit);
280                 lyxerr << "Font '" << f.stateText(0) 
281                        << "' matched by\n" << font << endl;
282         }
283
284         current_view->owner()->messagePop();
285
286         fontstruct[family][series][shape][size] = fs;
287         return fs;
288 }