]> Dogcows Code - chaz/openbox/blob - src/Font.cc
was ending up using the wrong cache items. now i find and release it every time a...
[chaz/openbox] / src / Font.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Font.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
23
24 #ifdef HAVE_CONFIG_H
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 extern "C" {
29 #ifdef HAVE_STDLIB_H
30 # include <stdlib.h>
31 #endif // HAVE_STDLIB_H
32 }
33
34 #include <iostream>
35 #include <algorithm>
36
37 using std::string;
38 using std::cerr;
39 using std::endl;
40
41 #include "i18n.hh"
42 #include "Font.hh"
43 #include "Util.hh"
44 #include "GCCache.hh"
45 #include "Color.hh"
46
47 //bool BFont::_antialias = False;
48 string BFont::_fallback_font = "fixed";
49
50
51 BFont::BFont(Display *d, BScreen *screen, const string &family, int size,
52 bool bold, bool italic) : _display(d),
53 _screen(screen),
54 _name(family),
55 _simplename(False),
56 _size(size * 10),
57 _bold(bold),
58 _italic(italic),
59 #ifdef XFT
60 _xftfont(0),
61 #endif // XFT
62 _font(0),
63 _fontset(0),
64 _fontset_extents(0) {
65 _valid = init();
66 }
67
68
69 BFont::BFont(Display *d, BScreen *screen, const string &xlfd) :
70 _display(d),
71 _screen(screen),
72 #ifdef XFT
73 _xftfont(0),
74 #endif // XFT
75 _font(0),
76 _fontset(0),
77 _fontset_extents(0) {
78 string int_xlfd;
79 if (xlfd.empty())
80 int_xlfd = _fallback_font;
81 else
82 int_xlfd = xlfd;
83
84 _valid = init(xlfd);
85 }
86
87
88 bool BFont::init(const string &xlfd) {
89 // try load the specified font
90 if (xlfd.empty() || parseFontString(xlfd))
91 if (createFont())
92 return True;
93
94 if (xlfd != _fallback_font) {
95 // try the fallback
96 cerr << "BFont::BFont(): couldn't load font '" << _name << "'" << endl <<
97 "Falling back to default '" << _fallback_font << "'" << endl;
98 if (parseFontString(_fallback_font))
99 if (createFont())
100 return True;
101 }
102
103 cerr << "BFont::BFont(): couldn't load font '" << _name << "'" << endl <<
104 "Giving up!" << endl;
105
106 return False;
107 }
108
109
110 bool BFont::createFont(void) {
111 std::string fullname;
112
113 #ifdef XFT
114 fullname = buildXlfdName(False);
115 _xftfont = XftFontOpenXlfd(_display, _screen->getScreenNumber(),
116 fullname.c_str());
117 if (_xftfont)
118 return True;
119
120 cerr << "BFont::BFont(): couldn't load font '" << _name << "'" << endl <<
121 "as an Xft font, trying as a standard X font." << endl;
122 #endif
123
124 if (i18n.multibyte()) {
125 char **missing, *def = "-";
126 int nmissing;
127
128 fullname = buildXlfdName(True);
129 _fontset = XCreateFontSet(_display, fullname.c_str(), &missing, &nmissing,
130 &def);
131 if (nmissing) XFreeStringList(missing);
132 if (_fontset)
133 _fontset_extents = XExtentsOfFontSet(_fontset);
134 else
135 return False;
136
137 assert(_fontset_extents);
138 }
139
140 fullname = buildXlfdName(False);
141 cerr << "loading font '" << fullname.c_str() << "'\n";
142 _font = XLoadQueryFont(_display, fullname.c_str());
143 if (! _font)
144 return False;
145 return True;
146 }
147
148
149 BFont::~BFont() {
150 #ifdef XFT
151 if (_xftfont)
152 XftFontClose(_display, _xftfont);
153 #endif // XFT
154
155 if (i18n.multibyte() && _fontset)
156 XFreeFontSet(_display, _fontset);
157 if (_font)
158 XFreeFont(_display, _font);
159 }
160
161
162 /*
163 * Takes _name, _size, _bold, _italic, etc and builds them into a full XLFD.
164 */
165 string BFont::buildXlfdName(bool mb) const {
166 string weight = _bold ? "bold" : "medium";
167 string slant = _italic ? "i" : "r";
168 string sizestr= _size ? itostring(_size) : "*";
169
170 if (mb)
171 return _name + ',' +
172 "-*-*-" + weight + "-" + slant + "-*-*-" + sizestr +
173 "-*-*-*-*-*-*-*" + ',' +
174 "-*-*-*-*-*-*-" + sizestr + "-*-*-*-*-*-*-*" + ',' +
175 "*";
176 else if (_simplename)
177 return _name;
178 else
179 return "-*-" + _name + "-" + weight + "-" + slant + "-*-*-*-" +
180 sizestr + "-*-*-*-*-*-*";
181 }
182
183
184 /*
185 * Takes a full X font name and parses it out so we know if we're bold, our
186 * size, etc.
187 */
188 bool BFont::parseFontString(const string &xlfd) {
189 if (xlfd.empty() || xlfd[0] != '-') {
190 _name = xlfd;
191 _simplename = True;
192 _bold = False;
193 _italic = False;
194 _size = 0;
195 } else {
196 _simplename = False;
197 string weight,
198 slant,
199 sizestr;
200 int i = 0;
201
202 string::const_iterator it = xlfd.begin(), end = xlfd.end();
203 while(1) {
204 string::const_iterator tmp = it; // current string.begin()
205 it = std::find(tmp, end, '-'); // look for comma between tmp and end
206 if (i == 2) _name = string(tmp, it); // s[tmp:it]
207 if (i == 3) weight = string(tmp, it);
208 if (i == 4) slant = string(tmp, it);
209 if (i == 8) sizestr = string(tmp, it);
210 if (it == end || i >= 8)
211 break;
212 ++it;
213 ++i;
214 }
215 if (i < 3) // no name even! can't parse that
216 return False;
217 _bold = weight == "bold" || weight == "demibold";
218 _italic = slant == "i" || slant == "o";
219 if (atoi(sizestr.c_str()))
220 _size = atoi(sizestr.c_str());
221 }
222
223 // min/max size restrictions for sanity, but 0 is the font's "default size"
224 if (_size && _size < 30)
225 _size = 30;
226 else if (_size > 970)
227 _size = 970;
228
229 return True;
230 }
231
232
233 void BFont::drawString(Drawable d, int x, int y, const BColor &color,
234 const string &string) const {
235 assert(_valid);
236
237 #ifdef XFT
238 if (_xftfont) {
239 XftDraw *draw = XftDrawCreate(_display, d, _screen->getVisual(),
240 _screen->getColormap());
241 assert(draw);
242
243 XftColor c;
244 c.color.red = color.red() | color.red() << 8;
245 c.color.green = color.green() | color.green() << 8;
246 c.color.blue = color.blue() | color.blue() << 8;
247 c.color.alpha = 0xff | 0xff << 8; // no transparency in BColor yet
248 c.pixel = color.pixel();
249
250 XftDrawStringUtf8(draw, &c, _xftfont, x, _xftfont->ascent + y,
251 (XftChar8 *) string.c_str(), string.size());
252
253 XftDrawDestroy(draw);
254 return;
255 }
256 #endif // XFT
257
258 BGCCache *_cache = color.display()->gcCache();
259 BGCCacheItem *_item = _cache->find(color, _font, GXcopy, ClipByChildren);
260
261 assert(_cache);
262 assert(_item);
263
264 if (i18n.multibyte())
265 XmbDrawString(_display, d, _fontset, _item->gc(),
266 x, y - _fontset_extents->max_ink_extent.y,
267 string.c_str(), string.size());
268 else
269 XDrawString(_display, d, _item->gc(),
270 x, _font->ascent + y,
271 string.c_str(), string.size());
272
273 _cache->release(_item);
274 }
275
276
277 unsigned int BFont::measureString(const string &string) const {
278 assert(_valid);
279
280 #ifdef XFT
281 if (_xftfont) {
282 XGlyphInfo info;
283 XftTextExtentsUtf8(_display, _xftfont, (XftChar8 *) string.c_str(),
284 string.size(), &info);
285 return info.xOff;
286 }
287 #endif // XFT
288
289 if (i18n.multibyte()) {
290 XRectangle ink, logical;
291 XmbTextExtents(_fontset, string.c_str(), string.size(), &ink, &logical);
292 return logical.width;
293 } else {
294 return XTextWidth(_font, string.c_str(), string.size());
295 }
296 }
297
298
299 unsigned int BFont::height(void) const {
300 assert(_valid);
301
302 #ifdef XFT
303 if (_xftfont)
304 return _xftfont->height;
305 #endif // XFT
306
307 if (i18n.multibyte())
308 return _fontset_extents->max_ink_extent.height;
309 else
310 return _font->ascent + _font->descent;
311 }
312
313
314 unsigned int BFont::maxCharWidth(void) const {
315 assert(_valid);
316
317 #ifdef XFT
318 if (_xftfont)
319 return _xftfont->max_advance_width;
320 #endif // XFT
321
322 if (i18n.multibyte())
323 return _fontset_extents->max_logical_extent.width;
324 else
325 return _font->max_bounds.rbearing - _font->min_bounds.lbearing;
326 }
This page took 0.047972 seconds and 5 git commands to generate.