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