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