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)
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:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
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.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
31 #endif // HAVE_STDLIB_H
46 string BFont::_fallback_font = "fixed";
49 BFont::BFont(Display *d, BScreen *screen, const string &family, int size,
50 bool bold, bool italic, bool shadow, unsigned char offset,
51 unsigned char tint, bool antialias) :
59 _antialias(antialias),
69 _xftfont = XftFontOpen(_display, _screen->getScreenNumber(),
70 XFT_FAMILY, XftTypeString, _family.c_str(),
71 XFT_SIZE, XftTypeInteger, _size,
72 XFT_WEIGHT, XftTypeInteger, (_bold ?
75 XFT_SLANT, XftTypeInteger, (_italic ?
78 XFT_ANTIALIAS, XftTypeBool, _antialias,
83 _font = XLoadQueryFont(_display, buildXlfd().c_str());
92 BFont::BFont(Display *d, BScreen *screen, const string &xlfd) :
102 _fontset_extents(0) {
105 int_xlfd = _fallback_font;
109 if ((_valid = createXFont(int_xlfd)))
112 if (int_xlfd != _fallback_font) {
114 cerr << "BFont::BFont(): couldn't load font '" << _family << "'" << endl <<
115 "Falling back to default '" << _fallback_font << "'" << endl;
117 if ((_valid = createXFont(_fallback_font)))
121 cerr << "BFont::BFont(): couldn't load font '" << _family << "'" << endl <<
122 "Giving up!" << endl;
127 bool BFont::createXFont(const std::string &xlfd) {
129 Even though this is only used for font sets (multibyte), it is still parsed
130 out so that the bold/italic/etc information is still available from the
131 class when using non-multibyte.
133 This is where _simplename, _bold, _italic, and _size are initialized, since
134 they are not initialized in the constructor. This needs to occur before
135 calling any Xlfd-building functions.
137 if (! parseXlfd(xlfd))
140 if (i18n.multibyte()) {
141 char **missing, *def = "-";
144 _fontset = XCreateFontSet(_display, buildMultibyteXlfd().c_str(),
145 &missing, &nmissing, &def);
146 if (nmissing) XFreeStringList(missing);
148 _fontset_extents = XExtentsOfFontSet(_fontset);
152 assert(_fontset_extents);
155 _font = XLoadQueryFont(_display, xlfd.c_str());
162 BFont::~BFont(void) {
165 XftFontClose(_display, _xftfont);
168 if (i18n.multibyte() && _fontset)
169 XFreeFontSet(_display, _fontset);
171 XFreeFont(_display, _font);
176 * Takes _family, _size, _bold, _italic, etc and builds them into a full XLFD.
178 string BFont::buildXlfd(void) const {
182 string weight = _bold ? "bold" : "medium";
183 string slant = _italic ? "i" : "r";
184 string sizestr= _size ? itostring(_size * 10) : "*";
186 return "-*-" + _family + "-" + weight + "-" + slant + "-*-*-*-" + sizestr +
192 * Takes _family, _size, _bold, _italic, etc and builds them into a full XLFD.
194 string BFont::buildMultibyteXlfd(void) const {
195 string weight = _bold ? "bold" : "medium";
196 string slant = _italic ? "i" : "r";
197 string sizestr= _size ? itostring(_size) : "*";
200 + "-*-*-" + weight + "-" + slant + "-*-*-*-" + sizestr +
202 + "-*-*-*-*-*-*-*-" + sizestr + "-*-*-*-*-*-*" + ',' +
208 * Takes a full X font name and parses it out so we know if we're bold, our
211 bool BFont::parseXlfd(const string &xlfd) {
212 if (xlfd.empty() || xlfd[0] != '-') {
225 string::const_iterator it = xlfd.begin(), end = xlfd.end();
227 string::const_iterator tmp = it; // current string.begin()
228 it = std::find(tmp, end, '-'); // look for comma between tmp and end
229 if (i == 2) _family = string(tmp, it); // s[tmp:it]
230 if (i == 3) weight = string(tmp, it);
231 if (i == 4) slant = string(tmp, it);
232 if (i == 7 && string(tmp, it) != "*") sizestr = string(tmp, it);
233 if (sizestr.empty() &&
234 i == 8 && string(tmp, it) != "*") sizestr = string(tmp, it);
235 if (it == end || i >= 8)
240 if (i < 3) // no name even! can't parse that
242 _bold = weight == "bold" || weight == "demibold";
243 _italic = slant == "i" || slant == "o";
244 _size = atoi(sizestr.c_str()) / 10;
247 // min/max size restrictions for sanity, but 0 is the font's "default size"
248 if (_size && _size < 3)
257 void BFont::drawString(Drawable d, int x, int y, const BColor &color,
258 const string &string) const {
263 XftDraw *draw = XftDrawCreate(_display, d, _screen->getVisual(),
264 _screen->getColormap());
272 c.color.alpha = _tint | _tint << 8; // transparent shadow
273 c.pixel = BlackPixel(_display, _screen->getScreenNumber());
280 draw, &c, _xftfont, x + _offset,
281 _xftfont->ascent + y + _offset, (XftChar8 *) string.c_str(),
286 c.color.red = color.red() | color.red() << 8;
287 c.color.green = color.green() | color.green() << 8;
288 c.color.blue = color.blue() | color.blue() << 8;
289 c.pixel = color.pixel();
290 c.color.alpha = 0xff | 0xff << 8; // no transparency in BColor yet
297 draw, &c, _xftfont, x, _xftfont->ascent + y,
298 (XftChar8 *) string.c_str(), string.size());
300 XftDrawDestroy(draw);
305 BPen pen(color, _font);
307 if (i18n.multibyte())
308 XmbDrawString(_display, d, _fontset, pen.gc(),
309 x, y - _fontset_extents->max_ink_extent.y,
310 string.c_str(), string.size());
312 XDrawString(_display, d, pen.gc(),
313 x, _font->ascent + y,
314 string.c_str(), string.size());
318 unsigned int BFont::measureString(const string &string) const {
330 _display, _xftfont, (XftChar8 *) string.c_str(),
331 string.size(), &info);
333 return info.xOff + (_shadow ? _offset : 0);
337 if (i18n.multibyte()) {
338 XRectangle ink, logical;
339 XmbTextExtents(_fontset, string.c_str(), string.size(), &ink, &logical);
340 return logical.width;
342 return XTextWidth(_font, string.c_str(), string.size());
347 unsigned int BFont::height(void) const {
352 return _xftfont->height + (_shadow ? _offset : 0);
355 if (i18n.multibyte())
356 return _fontset_extents->max_ink_extent.height;
358 return _font->ascent + _font->descent;
362 unsigned int BFont::maxCharWidth(void) const {
367 return _xftfont->max_advance_width;
370 if (i18n.multibyte())
371 return _fontset_extents->max_logical_extent.width;
373 return _font->max_bounds.rbearing - _font->min_bounds.lbearing;