]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FontInfo.C
fix crash with "save as"
[lyx.git] / src / frontends / xforms / FontInfo.C
1 /**
2  * \file FontInfo.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  * \author John Levon 
8  *
9  * Full author contact details are available in file CREDITS
10  */
11
12 #include <config.h>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include "FontInfo.h"
19 #include "debug.h"
20 #include "lyxrc.h"      // lyxrc.use_scalable_fonts
21
22 #include "support/lstrings.h"
23 #include "support/lyxlib.h"
24
25 #include <cmath>        // abs()
26
27 using std::endl;
28 using std::abs;
29
30 #include FORMS_H_LOCATION
31
32 /// Load font close to this size
33 string const FontInfo::getFontname(int size)
34 {
35         if (!exist())
36                 return string();
37
38         int closestind = -1;
39         double error = 100000.0;
40
41         for (int i = 0; i < matches; ++i) {
42                 if (sizes[i] == 0) {
43                         // Scalable font should not be considered close
44                 } else if (sizes[i] == size) {
45                         lyxerr[Debug::FONT] << "Exact font match with\n"
46                                             << strings[i] << endl;
47                         return strings[i];
48                 } else if (abs(sizes[i] - size - 0.1) < error) {
49                         error = abs(sizes[i] - size - 0.1);
50                         closestind = i;
51                 }
52         }
53
54         if (scalable && (lyxrc.use_scalable_fonts || closestind == -1)) {
55                 // We can use scalable
56                 string const font = resize(strings[scaleindex], size);
57                 lyxerr[Debug::FONT] << "Using scalable font to get\n"
58                                     << font << endl;
59                 return font;
60         }
61
62         // Did any fonts get close?
63         if (closestind == -1) {
64                 // No, so...
65                 return string();
66         }
67
68         // We use the closest match
69         lyxerr[Debug::FONT] << "Using closest font match to get size "
70                             << size
71                             << " with\n" << strings[closestind] << endl;
72         return strings[closestind];
73 }
74
75
76 /// Build newly sized font string
77 string const FontInfo::resize(string const & font, int size) const
78 {
79         string ret(font);
80         // Find the position of the size spec
81         int cut = 0;
82         string::iterator before = string::iterator(0);
83         string::iterator after = string::iterator(0);
84         for (string::iterator sit = ret.begin();
85              sit != ret.end(); ++sit)
86                 if ((*sit) == '-') {
87                         ++cut;
88                         if (cut == 7) before = sit + 1;
89                         else if (cut == 8) {
90                                 after = sit;
91                                 break;
92                         }
93                 }
94         ret.replace(before, after, tostr(size));
95         return ret;
96 }
97
98
99 /// Set new pattern
100 void FontInfo::setPattern(string const & pat)
101 {
102         init();
103         pattern = pat;
104 }
105
106
107 /// Query font in X11
108 void FontInfo::query()
109 {
110         if (queried)
111                 return;
112
113         if (pattern.empty()) {
114                 lyxerr << "Cannot use empty font name for font query."
115                        << endl;
116                 queried = true;
117                 return;
118         }
119
120         char ** list = 0;
121         if (lyxrc.use_gui)
122                 list = XListFonts(fl_get_display(), pattern.c_str(),
123                                   100, &matches);
124
125         if (list == 0) {
126                 // No fonts matched
127                 scalable = false;
128                 sizes.reset();
129         } else {
130                 sizes.reset(new int[matches]);
131                 strings.reset(new string[matches]);
132
133                 // We have matches. Run them through
134                 for (int i = 0; i < matches; ++i) {
135                         string name(list[i]);
136                         lyxerr[Debug::FONT] << "match #" << i << " "
137                                             << name << endl;
138                         sizes[i] = lyx::atoi(token(name, '-', 7));
139                         strings[i] = name;
140                         if (sizes[i] == 0) {
141                                 if (scaleindex == -1) {
142                                         scaleindex = i;
143                                 }
144                                 scalable = true;
145                         } else if (lyx::atoi(token(name, '-', 12)) == 0)
146                                 // Ignore bogus matches of scalable fonts.
147                                 sizes[i] = 0;
148                 };
149                 XFreeFontNames(list);
150         }
151         queried = true;
152 }
153
154
155 void FontInfo::init()
156 {
157         sizes.reset();
158         strings.reset();
159         matches = 0;
160         queried = false;
161         scalable = false;
162         scaleindex = -1;
163 }