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