]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/xftFontLoader.C
098d3a2e34df6d7b3a2cd1694ff40e8144321945
[lyx.git] / src / frontends / gtk / xftFontLoader.C
1 /**
2  * \file xftFontLoader.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Huang Ying
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 // Too hard to make concept checks work with this file
14 #ifdef _GLIBCPP_CONCEPT_CHECKS
15 #undef _GLIBCPP_CONCEPT_CHECKS
16 #endif
17
18 #include "xftFontLoader.h"
19 #include "FontInfo.h"
20 #include "gettext.h"
21 #include "debug.h"
22 #include "lyxrc.h"      // lyxrc.font_*
23 #include "BufferView.h"
24 #include "GtkmmX.h"
25
26 #include "frontends/LyXView.h"
27 #include "frontends/lyx_gui.h"
28
29 #include "support/lstrings.h"
30 #include "support/systemcall.h"
31 #include "support/filetools.h"
32
33 #include <cmath>        // fabs()
34 #include <vector>
35
36 using lyx::support::strToDbl;
37
38 using std::endl;
39 using std::string;
40
41 // The global fontLoader
42 xftFontLoader fontLoader;
43
44
45 // Initialize font loader
46 xftFontLoader::xftFontLoader()
47 {
48 }
49
50
51 // Destroy font loader
52 xftFontLoader::~xftFontLoader()
53 {
54         unload();
55 }
56
57
58 // Update fonts after zoom, dpi, font names, or norm change
59 // For now, we just ditch all fonts we have. Later, we should
60 // reuse the ones that are already loaded.
61 void xftFontLoader::update()
62 {
63         unload();
64 }
65
66
67 // Unload all fonts
68 void xftFontLoader::unload()
69 {
70         // Unload all fonts
71         for (int i1 = 0; i1 < LyXFont::NUM_FAMILIES; ++i1)
72                 for (int i2 = 0; i2 < 2; ++i2)
73                         for (int i3 = 0; i3 < 4; ++i3)
74                                 for (int i4 = 0; i4 < 10; ++i4) {
75                                         if (fonts_[i1][i2][i3][i4]){
76                                                 XftFontClose(getDisplay(), fonts_[i1][i2][i3][i4]);
77                                                 fonts_[i1][i2][i3][i4] = 0;
78                                         }
79                                 }
80 }
81
82
83 string xftFontLoader::familyString(LyXFont::FONT_FAMILY family)
84 {
85         string ffamily;
86         switch (family) {
87         case LyXFont::ROMAN_FAMILY:
88                 ffamily = lyxrc.roman_font_name;
89                 break;
90         case LyXFont::SANS_FAMILY:
91                 ffamily = lyxrc.sans_font_name;
92                 break;
93         case LyXFont::TYPEWRITER_FAMILY:
94                 ffamily = lyxrc.typewriter_font_name;
95                 break;
96         case LyXFont::CMR_FAMILY:
97                 ffamily = "cmr10";
98                 break;
99         case LyXFont::CMSY_FAMILY:
100                 ffamily = "cmsy10";
101                 break;
102         case LyXFont::CMM_FAMILY:
103                 ffamily = "cmmi10";
104                 break;
105         case LyXFont::CMEX_FAMILY:
106                 ffamily = "cmex10";
107                 break;
108         case LyXFont::MSA_FAMILY:
109                 ffamily = "msam10";
110                 break;
111         case LyXFont::MSB_FAMILY:
112                 ffamily = "msbm10";
113                 break;
114         default:
115                 ffamily = "Sans";
116                 break;
117         }
118         return ffamily;
119 }
120
121
122 // Get font pattern
123 /* Takes care of finding which font that can match the given request. Tries
124 different alternatives. */
125 XftPattern * xftFontLoader::getFontPattern(LyXFont::FONT_FAMILY family,
126                                           LyXFont::FONT_SERIES series,
127                                           LyXFont::FONT_SHAPE shape,
128                                           LyXFont::FONT_SIZE size)
129 {
130         // Normal font. Let's search for an existing name that matches.
131         string ffamily;
132         int fweight;
133         int fslant;
134         double fsize = strToDbl(lyxrc.font_sizes[size]) * lyxrc.zoom / 100.0;
135         XftPattern *fpat = XftPatternCreate();
136
137         ffamily = familyString(family);
138         switch (series) {
139         case LyXFont::MEDIUM_SERIES:
140                 fweight = XFT_WEIGHT_MEDIUM;
141                 break;
142         case LyXFont::BOLD_SERIES:
143                 fweight = XFT_WEIGHT_BOLD;
144                 break;
145         default:
146                 fweight = XFT_WEIGHT_MEDIUM;
147                 break;
148         }
149
150         switch (shape) {
151         case LyXFont::UP_SHAPE:
152         case LyXFont::SMALLCAPS_SHAPE:
153                 fslant = XFT_SLANT_ROMAN;
154                 break;
155         case LyXFont::ITALIC_SHAPE:
156                 fslant = XFT_SLANT_ITALIC;
157                 break;
158         case LyXFont::SLANTED_SHAPE:
159                 fslant = XFT_SLANT_OBLIQUE;
160                 break;
161         default:
162                 fslant = XFT_SLANT_ROMAN;
163                 break;
164         }
165         XftPatternAddString(fpat, XFT_FAMILY, ffamily.c_str());
166         XftPatternAddInteger(fpat, XFT_WEIGHT, fweight);
167         XftPatternAddInteger(fpat, XFT_SLANT, fslant);
168         XftPatternAddDouble(fpat, XFT_SIZE, fsize);
169         return fpat;
170 }
171
172
173 /// Do load font
174 XftFont * xftFontLoader::doLoad(LyXFont::FONT_FAMILY family,
175                                LyXFont::FONT_SERIES series,
176                                LyXFont::FONT_SHAPE shape,
177                                LyXFont::FONT_SIZE size)
178 {
179         XftPattern * fpat = getFontPattern(family, series, shape, size);
180         XftResult result;
181         XftPattern * fpat2 = XftFontMatch(getDisplay(), getScreen(),
182                                           fpat, &result);
183         XftFont * font = XftFontOpenPattern(getDisplay(), fpat2);
184         fonts_[family][series][shape][size] = font;
185         return font;
186 }
187
188
189 bool xftFontLoader::available(LyXFont const & f)
190 {
191         if (!lyx_gui::use_gui)
192                 return false;
193
194         static std::vector<bool> cache_set(LyXFont::NUM_FAMILIES, false);
195         static std::vector<bool> cache(LyXFont::NUM_FAMILIES, false);
196
197         LyXFont::FONT_FAMILY family = f.family();
198         if (cache_set[family])
199                 return cache[family];
200         cache_set[family] = true;
201
202         string const ffamily = familyString(family);
203         if (isSpecial(f)) {
204                 cache_set[family] = true;
205                 XftPattern * fpat = XftPatternCreate();
206                 XftPatternAddString(fpat, XFT_FAMILY, ffamily.c_str());
207                 XftResult result;
208                 XftPattern * fpat2 = XftFontMatch(getDisplay(), getScreen(),
209                                                   fpat, &result);
210                 XftPatternDestroy(fpat);
211                 char * familyM;
212                 XftPatternGetString(fpat2, XFT_FAMILY, 0, &familyM);
213                 if (ffamily == familyM) {
214                         cache[family] = true;
215                         return true;
216                 }
217                 // We don't need to set cache[family] to false, as it
218                 // is initialized to false;
219                 return false;
220         }
221         // We don't care about non-symbol fonts
222         return false;
223 }