]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiFontMetrics.C
* qt_helpers.h:
[lyx.git] / src / frontends / qt4 / GuiFontMetrics.C
1 /**
2  * \file GuiFontMetrics.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author unknown
7  * \author John Levon
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiFontMetrics.h"
15
16 #include "qt_helpers.h"
17
18 #include "language.h"
19
20 #include "support/unicode.h"
21
22 using std::string;
23
24 namespace lyx {
25 namespace frontend {
26
27 GuiFontMetrics::GuiFontMetrics(QFont const & font)
28 : metrics_(font), smallcaps_metrics_(font), smallcaps_shape_(false)
29 {
30 }
31
32
33 GuiFontMetrics::GuiFontMetrics(QFont const & font, QFont const & smallcaps_font)
34 : metrics_(font), smallcaps_metrics_(smallcaps_font), smallcaps_shape_(true)
35 {
36 }
37
38
39 int GuiFontMetrics::maxAscent() const
40 {
41         return metrics_.ascent();
42 }
43
44
45 int GuiFontMetrics::maxDescent() const
46 {
47         // We add 1 as the value returned by QT is different than X
48         // See http://doc.trolltech.com/2.3/qfontmetrics.html#200b74
49         return metrics_.descent() + 1;
50 }
51
52
53 int GuiFontMetrics::lbearing(char_type c) const
54 {
55         return metrics_.leftBearing(ucs4_to_qchar(c));
56 }
57
58
59 int GuiFontMetrics::rbearing(char_type c) const
60 {
61         // Qt rbearing is from the right edge of the char's width().
62         QChar sc = ucs4_to_qchar(c);
63         return metrics_.width(sc) - metrics_.rightBearing(sc);
64 }
65
66
67 int GuiFontMetrics::smallcapsWidth(QString const & s) const
68 {
69         int w = 0;
70         int const ls = s.size();
71
72         for (int i = 0; i < ls; ++i) {
73                 QChar const & c = s[i];
74                 QChar const uc = c.toUpper();
75                 if (c != uc)
76                         w += smallcaps_metrics_.width(uc);
77                 else
78                         w += metrics_.width(c);
79         }
80         return w;
81 }
82
83
84 int GuiFontMetrics::width(char_type const * s, size_t ls) const
85 {
86         // Caution: The following ucs4_to_something conversions work for
87         // symbol fonts only because they are no real conversions but simple
88         // casts in reality.
89
90         if (ls == 1 && !smallcaps_shape_) {
91                 return width(s[0]);
92         }
93
94         if (smallcaps_shape_) {
95                 QString ucs2;
96                 ucs4_to_qstring(s, ls, ucs2);
97                 return smallcapsWidth(ucs2);
98         }
99
100         int w = 0;
101         for (unsigned int i = 0; i < ls; ++i)
102                 w += width(s[i]);
103
104         return w;
105 }
106
107
108 int GuiFontMetrics::width(QString const & ucs2) const
109 {
110         int const ls = ucs2.size();
111         if (ls == 1 && !smallcaps_shape_) {
112                 return width(ucs2[0].unicode());
113         }
114
115         if (smallcaps_shape_)
116                 return smallcapsWidth(ucs2);
117
118         int w = 0;
119         for (int i = 0; i < ls; ++i)
120                 w += width(ucs2[i].unicode());
121
122         return w;
123 }
124
125
126 int GuiFontMetrics::signedWidth(docstring const & s) const
127 {
128         if (s.empty())
129                 return 0;
130
131         if (s[0] == '-')
132                 return -width(&(s[1]), s.length() - 1);
133         else
134                 return FontMetrics::width(s);
135 }
136
137
138 void GuiFontMetrics::rectText(docstring const & str,
139         int & w, int & ascent, int & descent) const
140 {
141         static int const d = 2;
142         w = FontMetrics::width(str) + d * 2 + 2;
143         ascent = metrics_.ascent() + d;
144         descent = metrics_.descent() + d;
145 }
146
147
148
149 void GuiFontMetrics::buttonText(docstring const & str,
150         int & w, int & ascent, int & descent) const
151 {
152         static int const d = 3;
153         w = FontMetrics::width(str) + d * 2 + 2;
154         ascent = metrics_.ascent() + d;
155         descent = metrics_.descent() + d;
156 }
157
158 #ifndef USE_LYX_FONTCACHE
159
160 int GuiFontMetrics::ascent(char_type c) const
161 {
162         QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
163         return -r.top();
164 }
165
166
167 int GuiFontMetrics::descent(char_type c) const
168 {
169         QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
170         return r.bottom() + 1;
171 }
172
173 #else
174
175 void GuiFontMetrics::fillMetricsCache(char_type c) const
176 {
177         QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
178         AscendDescend ad = { -r.top(), r.bottom() + 1};
179         // We could as well compute the width but this is not really
180         // needed for now as it is done directly in width() below.
181         metrics_cache_.insert(c, ad);
182 }
183
184
185 int GuiFontMetrics::width(char_type c) const
186 {
187         if (!width_cache_.contains(c)) {
188                 width_cache_.insert(c, metrics_.width(ucs4_to_qchar(c)));
189         }
190
191         return width_cache_.value(c);
192 }
193
194
195 int GuiFontMetrics::ascent(char_type c) const
196 {
197         if (!metrics_cache_.contains(c))
198                 fillMetricsCache(c);
199
200         return metrics_cache_.value(c).ascent;
201 }
202
203
204 int GuiFontMetrics::descent(char_type c) const
205 {
206         if (!metrics_cache_.contains(c))
207                 fillMetricsCache(c);
208
209         return metrics_cache_.value(c).descent;
210 }
211
212 #endif
213
214 } // frontend
215 } // lyx