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