]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/xfont_metrics.C
Introduce LFUN_PRINT.
[lyx.git] / src / frontends / xforms / xfont_metrics.C
1 /**
2  * \file xfont_metrics.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 "xfont_metrics.h"
15 #include "font_metrics.h"
16 #include "xfont_loader.h"
17
18 #include "encoding.h"
19 #include "language.h"
20 #include "lyxrc.h"
21
22 #include "frontends/lyx_gui.h"
23
24 #include "support/lstrings.h"
25
26 #include <boost/scoped_array.hpp>
27
28 using lyx::support::uppercase;
29
30 using std::string;
31
32
33 namespace {
34
35 inline
36 XFontStruct * getXFontstruct(LyXFont const & f)
37 {
38         return fontloader.load
39                 (f.family(), f.series(),
40                 f.realShape(), f.size());
41 }
42
43
44 inline
45 XID getFontID(LyXFont const & f)
46 {
47         return getXFontstruct(f)->fid;
48 }
49
50 } // namespace anon
51
52
53 namespace font_metrics {
54
55 int maxAscent(LyXFont const & f)
56 {
57         return getXFontstruct(f)->ascent;
58 }
59
60
61 int maxDescent(LyXFont const & f)
62 {
63         return getXFontstruct(f)->descent;
64 }
65
66
67 int ascent(char c, LyXFont const & f)
68 {
69         XFontStruct * finfo = getXFontstruct(f);
70         unsigned int uc = static_cast<unsigned char>(c);
71         if (finfo->per_char
72             && uc >= finfo->min_char_or_byte2
73             && uc <= finfo->max_char_or_byte2+256*finfo->max_byte1)
74                 return finfo->per_char[uc - finfo->min_char_or_byte2].ascent;
75         else
76                 return finfo->ascent;
77 }
78
79
80 int descent(char c, LyXFont const & f)
81 {
82         XFontStruct * finfo = getXFontstruct(f);
83         unsigned int uc = static_cast<unsigned char>(c);
84         if (finfo->per_char
85             && uc >= finfo->min_char_or_byte2
86             && uc <= finfo->max_char_or_byte2+256*finfo->max_byte1)
87                 return finfo->per_char[uc - finfo->min_char_or_byte2].descent;
88         else
89                 return finfo->descent;
90 }
91
92
93 int lbearing(char c, LyXFont const & f)
94 {
95         XFontStruct * finfo = getXFontstruct(f);
96         unsigned int uc = static_cast<unsigned char>(c);
97         if (finfo->per_char
98             && uc >= finfo->min_char_or_byte2
99             && uc <= finfo->max_char_or_byte2+256*finfo->max_byte1)
100                 return finfo->per_char[uc - finfo->min_char_or_byte2].lbearing;
101         else
102                 return 0;
103 }
104
105
106 int rbearing(char c, LyXFont const & f)
107 {
108         XFontStruct * finfo = getXFontstruct(f);
109         unsigned int uc = static_cast<unsigned char>(c);
110         if (finfo->per_char
111             && uc >= finfo->min_char_or_byte2
112             && uc <= finfo->max_char_or_byte2+256*finfo->max_byte1)
113                 return finfo->per_char[uc - finfo->min_char_or_byte2].rbearing;
114         else
115                 return width(c, f);
116 }
117
118
119 int width(char const * s, size_t n, LyXFont const & f)
120 {
121         if (!lyx_gui::use_gui)
122                 return n;
123
124         if (lyxrc.font_norm_type == LyXRC::ISO_10646_1) {
125                 boost::scoped_array<XChar2b> xs(new XChar2b[n]);
126                 Encoding const * encoding = f.language()->encoding();
127                 LyXFont font(f);
128                 if (f.isSymbolFont()) {
129 #ifdef USE_UNICODE_FOR_SYMBOLS
130                         font.setFamily(LyXFont::ROMAN_FAMILY);
131                         font.setShape(LyXFont::UP_SHAPE);
132 #endif
133                         encoding = encodings.symbol_encoding();
134                 }
135                 for (size_t i = 0; i < n; ++i) {
136                         Uchar c = encoding->ucs(s[i]);
137                         xs[i].byte1 = c >> 8;
138                         xs[i].byte2 = c & 0xff;
139                 }
140                 int result = xfont_metrics::width(xs.get(), n, font);
141                 return result;
142         }
143
144         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
145                 return ::XTextWidth(getXFontstruct(f), s, n);
146         } else {
147                 // emulate smallcaps since X doesn't support this
148                 int result = 0;
149                 LyXFont smallfont(f);
150                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
151                 for (size_t i = 0; i < n; ++i) {
152                         char const c = uppercase(s[i]);
153                         if (c != s[i]) {
154                                 result += ::XTextWidth(getXFontstruct(smallfont), &c, 1);
155                         } else {
156                                 result += ::XTextWidth(getXFontstruct(f), &c, 1);
157                         }
158                 }
159                 return result;
160         }
161 }
162
163
164 int signedWidth(string const & s, LyXFont const & f)
165 {
166         if (s.empty())
167                 return 0;
168         if (s[0] == '-')
169                 return -width(s.substr(1, s.length() - 1), f);
170         else
171                 return width(s, f);
172 }
173
174
175 void rectText(string const & str, LyXFont const & font,
176         int & width,
177         int & ascent,
178         int & descent)
179 {
180         static int const d = 2;
181         width = font_metrics::width(str, font) + d * 2 + 2;
182         ascent = font_metrics::maxAscent(font) + d;
183         descent = font_metrics::maxDescent(font) + d;
184 }
185
186
187
188 void buttonText(string const & str, LyXFont const & font,
189         int & width,
190         int & ascent,
191         int & descent)
192 {
193         static int const d = 3;
194
195         width = font_metrics::width(str, font) + d * 2 + 2;
196         ascent = font_metrics::maxAscent(font) + d;
197         descent = font_metrics::maxDescent(font) + d;
198 }
199
200 } // namespace font_metrics
201
202 namespace xfont_metrics {
203
204 int width(XChar2b const * s, int n, LyXFont const & f)
205 {
206         if (!lyx_gui::use_gui)
207                 return n;
208
209         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
210                 return ::XTextWidth16(getXFontstruct(f), s, n);
211         } else {
212                 // emulate smallcaps since X doesn't support this
213                 int result = 0;
214                 static XChar2b c;
215                 LyXFont smallfont(f);
216                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
217                 for (int i = 0; i < n; ++i) {
218                         if (s[i].byte1)
219                                 c = s[i];
220                         else {
221                                 c.byte1 = s[i].byte1;
222                                 c.byte2 = uppercase(s[i].byte2);
223                         }
224                         if (c.byte2 != s[i].byte2) {
225                                 result += ::XTextWidth16(getXFontstruct(smallfont), &c, 1);
226                         } else {
227                                 result += ::XTextWidth16(getXFontstruct(f), &s[i], 1);
228                 }
229                 }
230                 return result;
231         }
232 }
233
234
235 int XTextWidth(LyXFont const & f, char const * str, int count)
236 {
237         return ::XTextWidth(getXFontstruct(f), str, count);
238 }
239
240
241 int XTextWidth16(LyXFont const & f, XChar2b const * str, int count)
242 {
243         return ::XTextWidth16(getXFontstruct(f), str, count);
244 }
245
246
247 /// hmm, not a metric !
248 void XSetFont(Display * display, GC gc, LyXFont const & f)
249 {
250         ::XSetFont(display, gc, getFontID(f));
251 }
252
253 } // namespace xfont_metrics