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
47 //bool BFont::_antialias = False;
48 string BFont::_fallback_font = "fixed";
51 BFont::BFont(Display *d, BScreen *screen, const string &family, int size,
52 bool bold, bool italic) : _display(d),
71 BFont::BFont(Display *d, BScreen *screen, const string &xlfd) :
84 int_xlfd = _fallback_font;
92 bool BFont::init(const string &xlfd) {
93 // try load the specified font
94 if (xlfd.empty() || parseFontString(xlfd))
98 if (xlfd != _fallback_font) {
100 cerr << "BFont::BFont(): couldn't load font '" << _name << "'" << endl <<
101 "Falling back to default '" << _fallback_font << "'" << endl;
102 if (parseFontString(_fallback_font))
107 cerr << "BFont::BFont(): couldn't load font '" << _name << "'" << endl <<
108 "Giving up!" << endl;
114 bool BFont::createFont(void) {
115 std::string fullname;
118 fullname = buildXlfdName(False);
119 _xftfont = XftFontOpenXlfd(_display, _screen->getScreenNumber(),
124 cerr << "BFont::BFont(): couldn't load font '" << _name << "'" << endl <<
125 "as an Xft font, trying as a standard X font." << endl;
128 if (i18n.multibyte()) {
129 char **missing, *def = "-";
132 fullname = buildXlfdName(True);
133 _fontset = XCreateFontSet(_display, fullname.c_str(), &missing, &nmissing,
135 if (nmissing) XFreeStringList(missing);
137 _fontset_extents = XExtentsOfFontSet(_fontset);
141 assert(_fontset_extents);
144 fullname = buildXlfdName(False);
145 cerr << "loading font '" << fullname.c_str() << "'\n";
146 _font = XLoadQueryFont(_display, fullname.c_str());
156 XftFontClose(_display, _xftfont);
159 if (i18n.multibyte() && _fontset)
160 XFreeFontSet(_display, _fontset);
162 XFreeFont(_display, _font);
165 _cache->release(_item);
170 * Takes _name, _size, _bold, _italic, etc and builds them into a full XLFD.
172 string BFont::buildXlfdName(bool mb) const {
173 string weight = _bold ? "bold" : "medium";
174 string slant = _italic ? "i" : "r";
175 string sizestr= _size ? itostring(_size) : "*";
179 "-*-*-" + weight + "-" + slant + "-*-*-" + sizestr +
180 "-*-*-*-*-*-*-*" + ',' +
181 "-*-*-*-*-*-*-" + sizestr + "-*-*-*-*-*-*-*" + ',' +
183 else if (_simplename)
186 return "-*-" + _name + "-" + weight + "-" + slant + "-*-*-*-" +
187 sizestr + "-*-*-*-*-*-*";
192 * Takes a full X font name and parses it out so we know if we're bold, our
195 bool BFont::parseFontString(const string &xlfd) {
196 if (xlfd.empty() || xlfd[0] != '-') {
209 string::const_iterator it = xlfd.begin(), end = xlfd.end();
211 string::const_iterator tmp = it; // current string.begin()
212 it = std::find(tmp, end, '-'); // look for comma between tmp and end
213 if (i == 2) _name = string(tmp, it); // s[tmp:it]
214 if (i == 3) weight = string(tmp, it);
215 if (i == 4) slant = string(tmp, it);
216 if (i == 8) sizestr = string(tmp, it);
217 if (it == end || i >= 8)
222 if (i < 3) // no name even! can't parse that
224 _bold = weight == "bold" || weight == "demibold";
225 _italic = slant == "i" || slant == "o";
226 if (atoi(sizestr.c_str()))
227 _size = atoi(sizestr.c_str());
230 // min/max size restrictions for sanity, but 0 is the font's "default size"
231 if (_size && _size < 30)
233 else if (_size > 970)
240 void BFont::drawString(Drawable d, int x, int y, const BColor &color,
241 const string &string) const {
246 XftDraw *draw = XftDrawCreate(_display, d, _screen->getVisual(),
247 _screen->getColormap());
251 c.color.red = color.red() | color.red() << 8;
252 c.color.green = color.green() | color.green() << 8;
253 c.color.blue = color.blue() | color.blue() << 8;
254 c.color.alpha = 0xff | 0xff << 8; // no transparency in BColor yet
255 c.pixel = color.pixel();
257 XftDrawStringUtf8(draw, &c, _xftfont, x, _xftfont->ascent + y,
258 (XftChar8 *) string.c_str(), string.size());
260 XftDrawDestroy(draw);
266 _cache = color.display()->gcCache();
268 _item = _cache->find(color, _font, GXcopy, ClipByChildren);
273 if (i18n.multibyte())
274 XmbDrawString(_display, d, _fontset, _item->gc(),
275 x, y - _fontset_extents->max_ink_extent.y,
276 string.c_str(), string.size());
278 XDrawString(_display, d, _item->gc(),
279 x, _font->ascent + y,
280 string.c_str(), string.size());
284 unsigned int BFont::measureString(const string &string) const {
290 XftTextExtentsUtf8(_display, _xftfont, (XftChar8 *) string.c_str(),
291 string.size(), &info);
296 if (i18n.multibyte()) {
297 XRectangle ink, logical;
298 XmbTextExtents(_fontset, string.c_str(), string.size(), &ink, &logical);
299 return logical.width;
301 return XTextWidth(_font, string.c_str(), string.size());
306 unsigned int BFont::height(void) const {
311 return _xftfont->height;
314 if (i18n.multibyte())
315 return _fontset_extents->max_ink_extent.height;
317 return _font->ascent + _font->descent;
321 unsigned int BFont::maxCharWidth(void) const {
326 return _xftfont->max_advance_width;
329 if (i18n.multibyte())
330 return _fontset_extents->max_logical_extent.width;
332 return _font->max_bounds.rbearing - _font->min_bounds.lbearing;